• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • fonts
kfontchooser.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@kde.org>
3 Copyright (c) 1999 Preston Brown <pbrown@kde.org>
4 Copyright (c) 1999 Mario Weilguni <mweilguni@kde.org>
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10 
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15 
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21 
22 #include "kfontchooser.h"
23 #include "fonthelpers_p.h"
24 #include "sampleedit_p.h"
25 
26 #include <QtGui/QCheckBox>
27 #include <QtGui/QLabel>
28 #include <QtGui/QLayout>
29 #include <QtGui/QSplitter>
30 #include <QtGui/QScrollBar>
31 #include <QtGui/QFontDatabase>
32 #include <QtGui/QGroupBox>
33 #include <kcharsets.h>
34 #include <kconfig.h>
35 #include <kdialog.h>
36 #include <kglobal.h>
37 #include <kglobalsettings.h>
38 #include <klineedit.h>
39 #include <klistwidget.h>
40 #include <klocale.h>
41 #include <kstandarddirs.h>
42 #include <kdebug.h>
43 #include <knuminput.h>
44 #include <kconfiggroup.h>
45 
46 #include <cmath>
47 
48 // When message extraction needs to be avoided.
49 #define I18NC_NOX i18nc
50 
51 static int minimumListWidth( const QListWidget *list )
52 {
53  int w=0;
54  for( int i=0; i<list->count(); i++ )
55  {
56  int itemWidth = list->visualItemRect(list->item(i)).width();
57  // ...and add a space on both sides for not too tight look.
58  itemWidth += list->fontMetrics().width(' ') * 2;
59  w = qMax(w,itemWidth);
60  }
61  if( w == 0 ) { w = 40; }
62  w += list->frameWidth() * 2;
63  w += list->verticalScrollBar()->sizeHint().width();
64  return w;
65 }
66 
67 static int minimumListHeight( const QListWidget *list, int numVisibleEntry )
68 {
69  int w = list->count() > 0 ? list->visualItemRect(list->item(0)).height() :
70  list->fontMetrics().lineSpacing();
71 
72  if( w < 0 ) { w = 10; }
73  if( numVisibleEntry <= 0 ) { numVisibleEntry = 4; }
74  return ( w * numVisibleEntry + 2 * list->frameWidth() );
75 }
76 
77 static QString formatFontSize(qreal size)
78 {
79  return KGlobal::locale()->formatNumber(size, (size == floor(size)) ? 0 : 1);
80 }
81 
82 class KFontChooser::Private
83 {
84 public:
85  Private( KFontChooser* qq )
86  : q( qq )
87  {
88  m_palette.setColor(QPalette::Active, QPalette::Text, Qt::black);
89  m_palette.setColor(QPalette::Active, QPalette::Base, Qt::white);
90  signalsAllowed = true;
91  selectedSize = -1;
92  customSizeRow = -1;
93  }
94 
95  // pointer to an optinally supplied list of fonts to
96  // inserted into the fontdialog font-family combo-box
97 // QStringList fontList;
98 
99  void setFamilyBoxItems(const QStringList &fonts);
100  void fillFamilyListBox(bool onlyFixedFonts = false);
101  int nearestSizeRow(qreal val, bool customize);
102  qreal fillSizeList(const QList<qreal> &sizes = QList<qreal>());
103  qreal setupSizeListBox(const QString& family, const QString& style);
104 
105  void setupDisplay();
106 
107  void _k_toggled_checkbox();
108  void _k_family_chosen_slot(const QString&);
109  void _k_size_chosen_slot(const QString&);
110  void _k_style_chosen_slot(const QString&);
111  void _k_displaySample(const QFont &font);
112  void _k_showXLFDArea(bool);
113  void _k_size_value_slot(double);
114 
115  KFontChooser *q;
116 
117  QPalette m_palette;
118  bool signalsAllowed:1;
119 
120  bool usingFixed:1;
121 
122  KDoubleNumInput *sizeOfFont;
123 
124  SampleEdit *sampleEdit;
125  KLineEdit *xlfdEdit;
126 
127  QLabel *familyLabel;
128  QLabel *styleLabel;
129  QCheckBox *familyCheckbox;
130  QCheckBox *styleCheckbox;
131  QCheckBox *sizeCheckbox;
132  QLabel *sizeLabel;
133  KListWidget *familyListBox;
134  KListWidget *styleListBox;
135  KListWidget *sizeListBox;
136  QCheckBox *sizeIsRelativeCheckBox;
137 
138  QFont selFont;
139 
140  QString selectedStyle;
141  qreal selectedSize;
142 
143  int customSizeRow;
144  QString standardSizeAtCustom;
145 
146  // Mappings of translated to Qt originated family and style strings.
147  QHash<QString, QString> qtFamilies;
148  QHash<QString, QString> qtStyles;
149 
150 };
151 
152 
153 KFontChooser::KFontChooser( QWidget *parent,
154  const DisplayFlags& flags,
155  const QStringList &fontList,
156  int visibleListSize,
157  Qt::CheckState *sizeIsRelativeState )
158  : QWidget(parent),
159  d( new KFontChooser::Private( this ) )
160 {
161  d->usingFixed = flags & FixedFontsOnly;
162  setWhatsThis(i18nc("@info:whatsthis", "Here you can choose the font to be used." ));
163 
164  // The top layout is divided vertically into a splitter with font
165  // attribute widgets and preview on the top, and XLFD data at the bottom.
166  QVBoxLayout *topLayout = new QVBoxLayout( this );
167  topLayout->setMargin( 0 );
168  int checkBoxGap = KDialog::spacingHint() / 2;
169 
170  // The splitter contains font attribute widgets in the top part,
171  // and the font preview in the bottom part.
172  // The splitter is there to allow the user to resize the font preview.
173  QSplitter *splitter = new QSplitter(Qt::Vertical, this);
174  splitter->setChildrenCollapsible(false);
175  topLayout->addWidget(splitter);
176 
177  // Build the grid of font attribute widgets for the upper splitter part.
178  //
179  QWidget *page;
180  QGridLayout *gridLayout;
181  int row = 0;
182  if( flags & DisplayFrame )
183  {
184  page = new QGroupBox( i18n("Requested Font"), this );
185  splitter->addWidget(page);
186  gridLayout = new QGridLayout( page );
187  row = 1;
188  }
189  else
190  {
191  page = new QWidget( this );
192  splitter->addWidget(page);
193  gridLayout = new QGridLayout( page );
194  gridLayout->setMargin( 0 );
195  }
196 
197  //
198  // first, create the labels across the top
199  //
200  QHBoxLayout *familyLayout = new QHBoxLayout();
201  familyLayout->addSpacing( checkBoxGap );
202  if ( flags & ShowDifferences ) {
203  d->familyCheckbox = new QCheckBox(i18nc("@option:check","Font"), page);
204  connect(d->familyCheckbox, SIGNAL(toggled(bool)),
205  this, SLOT(_k_toggled_checkbox()));
206  familyLayout->addWidget(d->familyCheckbox, 0, Qt::AlignLeft);
207  d->familyCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font family settings."));
208  d->familyCheckbox->setToolTip(i18nc("@info:tooltip","Change font family?") );
209  d->familyLabel = 0;
210  } else {
211  d->familyCheckbox = 0;
212  d->familyLabel = new QLabel( i18nc("@label","Font:"), page );
213  familyLayout->addWidget(d->familyLabel, 1, Qt::AlignLeft);
214  }
215  gridLayout->addLayout(familyLayout, row, 0 );
216 
217  QHBoxLayout *styleLayout = new QHBoxLayout();
218  if ( flags & ShowDifferences ) {
219  d->styleCheckbox = new QCheckBox(i18nc("@option:check","Font style"), page);
220  connect(d->styleCheckbox, SIGNAL(toggled(bool)),
221  this, SLOT(_k_toggled_checkbox()));
222  styleLayout->addWidget(d->styleCheckbox, 0, Qt::AlignLeft);
223  d->styleCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font style settings."));
224  d->styleCheckbox->setToolTip(i18nc("@info:tooltip","Change font style?"));
225  d->styleLabel = 0;
226  } else {
227  d->styleCheckbox = 0;
228  d->styleLabel = new QLabel(i18n("Font style:"), page );
229  styleLayout->addWidget(d->styleLabel, 1, Qt::AlignLeft);
230  }
231  styleLayout->addSpacing( checkBoxGap );
232  gridLayout->addLayout(styleLayout, row, 1 );
233 
234  QHBoxLayout *sizeLayout = new QHBoxLayout();
235  if ( flags & ShowDifferences ) {
236  d->sizeCheckbox = new QCheckBox(i18nc("@option:check","Size"),page);
237  connect(d->sizeCheckbox, SIGNAL(toggled(bool)),
238  this, SLOT(_k_toggled_checkbox()));
239  sizeLayout->addWidget(d->sizeCheckbox, 0, Qt::AlignLeft);
240  d->sizeCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font size settings."));
241  d->sizeCheckbox->setToolTip(i18nc("@info:tooltip","Change font size?"));
242  d->sizeLabel = 0;
243  } else {
244  d->sizeCheckbox = 0;
245  d->sizeLabel = new QLabel(i18nc("@label:listbox Font size", "Size:"), page );
246  sizeLayout->addWidget(d->sizeLabel, 1, Qt::AlignLeft);
247  }
248  sizeLayout->addSpacing( checkBoxGap );
249  sizeLayout->addSpacing( checkBoxGap ); // prevent label from eating border
250  gridLayout->addLayout(sizeLayout, row, 2 );
251 
252  row ++;
253 
254  //
255  // now create the actual boxes that hold the info
256  //
257  d->familyListBox = new KListWidget( page );
258  d->familyListBox->setEnabled( flags ^ ShowDifferences );
259  gridLayout->addWidget( d->familyListBox, row, 0 );
260  QString fontFamilyWhatsThisText (
261  i18nc("@info:whatsthis","Here you can choose the font family to be used." ));
262  d->familyListBox->setWhatsThis(fontFamilyWhatsThisText );
263 
264  if ( flags & ShowDifferences ) {
265  d->familyCheckbox->setWhatsThis(fontFamilyWhatsThisText );
266  } else {
267  d->familyLabel->setWhatsThis(fontFamilyWhatsThisText );
268  }
269 
270  connect(d->familyListBox, SIGNAL(currentTextChanged(QString)),
271  this, SLOT(_k_family_chosen_slot(QString)));
272  if ( !fontList.isEmpty() ) {
273  d->setFamilyBoxItems(fontList);
274  }
275  else
276  {
277  d->fillFamilyListBox( flags & FixedFontsOnly );
278  }
279 
280  d->familyListBox->setMinimumWidth( minimumListWidth( d->familyListBox ) );
281  d->familyListBox->setMinimumHeight(
282  minimumListHeight( d->familyListBox, visibleListSize ) );
283 
284  d->styleListBox = new KListWidget( page );
285  d->styleListBox->setEnabled( flags ^ ShowDifferences );
286  gridLayout->addWidget(d->styleListBox, row, 1);
287  d->styleListBox->setWhatsThis(i18nc("@info:whatsthis","Here you can choose the font style to be used." ));
288  if ( flags & ShowDifferences ) {
289  ((QWidget *)d->styleCheckbox)->setWhatsThis(fontFamilyWhatsThisText );
290  } else {
291  ((QWidget *)d->styleLabel)->setWhatsThis( fontFamilyWhatsThisText );
292  }
293  // Populate usual styles, to determine minimum list width;
294  // will be replaced later with correct styles.
295  d->styleListBox->addItem(i18nc("@item font","Regular"));
296  d->styleListBox->addItem(i18nc("@item font","Italic"));
297  d->styleListBox->addItem(i18nc("@item font","Oblique"));
298  d->styleListBox->addItem(i18nc("@item font","Bold"));
299  d->styleListBox->addItem(i18nc("@item font","Bold Italic"));
300  d->styleListBox->setMinimumWidth( minimumListWidth( d->styleListBox ) );
301  d->styleListBox->setMinimumHeight(
302  minimumListHeight( d->styleListBox, visibleListSize ) );
303 
304  connect(d->styleListBox, SIGNAL(currentTextChanged(QString)),
305  this, SLOT(_k_style_chosen_slot(QString)));
306 
307 
308  d->sizeListBox = new KListWidget( page );
309  d->sizeOfFont = new KDoubleNumInput(page);
310  d->sizeOfFont->setMinimum(4);
311  d->sizeOfFont->setMaximum(999);
312  d->sizeOfFont->setDecimals(1);
313  d->sizeOfFont->setSingleStep(1);
314  d->sizeOfFont->setSliderEnabled(false);
315 
316  d->sizeListBox->setEnabled( flags ^ ShowDifferences );
317  d->sizeOfFont->setEnabled( flags ^ ShowDifferences );
318  if( sizeIsRelativeState ) {
319  QString sizeIsRelativeCBText =
320  i18nc("@item font size","Relative");
321  QString sizeIsRelativeCBToolTipText =
322  i18n("Font size<br /><i>fixed</i> or <i>relative</i><br />to environment");
323  QString sizeIsRelativeCBWhatsThisText =
324  i18n("Here you can switch between fixed font size and font size "
325  "to be calculated dynamically and adjusted to changing "
326  "environment (e.g. widget dimensions, paper size)." );
327  d->sizeIsRelativeCheckBox = new QCheckBox( sizeIsRelativeCBText,
328  page );
329  d->sizeIsRelativeCheckBox->setTristate( flags & ShowDifferences );
330  QGridLayout *sizeLayout2 = new QGridLayout();
331  sizeLayout2->setSpacing( KDialog::spacingHint()/2 );
332  gridLayout->addLayout(sizeLayout2, row, 2);
333  sizeLayout2->setColumnStretch( 1, 1 ); // to prevent text from eating the right border
334  sizeLayout2->addWidget( d->sizeOfFont, 0, 0, 1, 2);
335  sizeLayout2->addWidget(d->sizeListBox, 1,0, 1,2);
336  sizeLayout2->addWidget(d->sizeIsRelativeCheckBox, 2, 0, Qt::AlignLeft);
337  d->sizeIsRelativeCheckBox->setWhatsThis(sizeIsRelativeCBWhatsThisText );
338  d->sizeIsRelativeCheckBox->setToolTip( sizeIsRelativeCBToolTipText );
339  }
340  else {
341  d->sizeIsRelativeCheckBox = 0L;
342  QGridLayout *sizeLayout2 = new QGridLayout();
343  sizeLayout2->setSpacing( KDialog::spacingHint()/2 );
344  gridLayout->addLayout(sizeLayout2, row, 2);
345  sizeLayout2->addWidget( d->sizeOfFont, 0, 0);
346  sizeLayout2->addWidget(d->sizeListBox, 1,0);
347  }
348  QString fontSizeWhatsThisText =
349  i18n("Here you can choose the font size to be used." );
350  d->sizeListBox->setWhatsThis(fontSizeWhatsThisText );
351 
352  if ( flags & ShowDifferences ) {
353  ((QWidget *)d->sizeCheckbox)->setWhatsThis(fontSizeWhatsThisText );
354  } else {
355  ((QWidget *)d->sizeLabel)->setWhatsThis( fontSizeWhatsThisText );
356  }
357 
358  // Populate with usual sizes, to determine minimum list width;
359  // will be replaced later with correct sizes.
360  d->fillSizeList();
361  d->sizeListBox->setMinimumWidth( minimumListWidth(d->sizeListBox) +
362  d->sizeListBox->fontMetrics().maxWidth() );
363  d->sizeListBox->setMinimumHeight(
364  minimumListHeight( d->sizeListBox, visibleListSize ) );
365 
366  connect( d->sizeOfFont, SIGNAL(valueChanged(double)),
367  this, SLOT(_k_size_value_slot(double)));
368 
369  connect( d->sizeListBox, SIGNAL(currentTextChanged(QString)),
370  this, SLOT(_k_size_chosen_slot(QString)) );
371 
372  row ++;
373  //
374  // Completed the font attribute grid.
375 
376  // Add the font preview into the lower part of the splitter.
377  //
378  d->sampleEdit = new SampleEdit(page);
379  d->sampleEdit->setAcceptRichText(false);
380  QFont tmpFont( KGlobalSettings::generalFont().family(), 64, QFont::Black );
381  d->sampleEdit->setFont(tmpFont);
382  d->sampleEdit->setMinimumHeight( d->sampleEdit->fontMetrics().lineSpacing() );
383  // i18n: A classical test phrase, with all letters of the English alphabet.
384  // Replace it with a sample text in your language, such that it is
385  // representative of language's writing system.
386  // If you wish, you can input several lines of text separated by \n.
387  setSampleText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog"));
388  d->sampleEdit->setTextCursor(QTextCursor(d->sampleEdit->document()));
389  QString sampleEditWhatsThisText =
390  i18n("This sample text illustrates the current settings. "
391  "You may edit it to test special characters." );
392  d->sampleEdit->setWhatsThis(sampleEditWhatsThisText );
393 
394  connect(this, SIGNAL(fontSelected(QFont)),
395  this, SLOT(_k_displaySample(QFont)));
396 
397  splitter->addWidget(d->sampleEdit);
398  //
399  // Finished setting up the splitter.
400 
401  // Add XLFD data below the font attributes/preview splitter.
402  //
403  QVBoxLayout *vbox;
404  if( flags & DisplayFrame )
405  {
406  page = new QGroupBox( i18n("Actual Font"), this );
407  topLayout->addWidget(page);
408  vbox = new QVBoxLayout( page );
409  vbox->addSpacing( fontMetrics().lineSpacing() );
410  }
411  else
412  {
413  page = new QWidget( this );
414  topLayout->addWidget(page);
415  vbox = new QVBoxLayout( page );
416  vbox->setMargin( 0 );
417  QLabel *label = new QLabel( i18n("Actual Font"), page );
418  vbox->addWidget( label );
419  }
420 
421  d->xlfdEdit = new KLineEdit( page );
422  vbox->addWidget( d->xlfdEdit );
423  //
424  // Finished setting up the chooser layout.
425 
426  // lets initialize the display if possible
427  setFont( d->usingFixed ? KGlobalSettings::fixedFont() : KGlobalSettings::generalFont(), d->usingFixed );
428 
429  // check or uncheck or gray out the "relative" checkbox
430  if( sizeIsRelativeState && d->sizeIsRelativeCheckBox )
431  setSizeIsRelative( *sizeIsRelativeState );
432 
433  KConfigGroup cg(KGlobal::config(), QLatin1String("General"));
434  d->_k_showXLFDArea(cg.readEntry(QLatin1String("fontSelectorShowXLFD"), false));
435 
436  // Set focus to the size list as this is the most commonly changed property
437  d->sizeListBox->setFocus();
438 }
439 
440 KFontChooser::~KFontChooser()
441 {
442  delete d;
443 }
444 
445 void KFontChooser::setColor( const QColor & col )
446 {
447  d->m_palette.setColor( QPalette::Active, QPalette::Text, col );
448  QPalette pal = d->sampleEdit->palette();
449  pal.setColor( QPalette::Active, QPalette::Text, col );
450  d->sampleEdit->setPalette( pal );
451  QTextCursor cursor = d->sampleEdit->textCursor();
452  d->sampleEdit->selectAll();
453  d->sampleEdit->setTextColor( col );
454  d->sampleEdit->setTextCursor( cursor );
455 }
456 
457 QColor KFontChooser::color() const
458 {
459  return d->m_palette.color( QPalette::Active, QPalette::Text );
460 }
461 
462 void KFontChooser::setBackgroundColor( const QColor & col )
463 {
464  d->m_palette.setColor( QPalette::Active, QPalette::Base, col );
465  QPalette pal = d->sampleEdit->palette();
466  pal.setColor( QPalette::Active, QPalette::Base, col );
467  d->sampleEdit->setPalette( pal );
468 }
469 
470 QColor KFontChooser::backgroundColor() const
471 {
472  return d->m_palette.color( QPalette::Active, QPalette::Base );
473 }
474 
475 void KFontChooser::setSizeIsRelative( Qt::CheckState relative )
476 {
477  // check or uncheck or gray out the "relative" checkbox
478  if( d->sizeIsRelativeCheckBox ) {
479  if( Qt::PartiallyChecked == relative )
480  d->sizeIsRelativeCheckBox->setCheckState(Qt::PartiallyChecked);
481  else
482  d->sizeIsRelativeCheckBox->setCheckState( (Qt::Checked == relative ) ? Qt::Checked : Qt::Unchecked);
483  }
484 }
485 
486 Qt::CheckState KFontChooser::sizeIsRelative() const
487 {
488  return d->sizeIsRelativeCheckBox
489  ? d->sizeIsRelativeCheckBox->checkState()
490  : Qt::PartiallyChecked;
491 }
492 
493 QString KFontChooser::sampleText() const
494 {
495  return d->sampleEdit->toPlainText();
496 }
497 
498 void KFontChooser::setSampleText( const QString &text )
499 {
500  d->sampleEdit->setPlainText(text);
501 }
502 
503 void KFontChooser::setSampleBoxVisible( bool visible )
504 {
505  d->sampleEdit->setVisible( visible );
506 }
507 
508 QSize KFontChooser::sizeHint( void ) const
509 {
510  return minimumSizeHint();
511 }
512 
513 
514 void KFontChooser::enableColumn( int column, bool state )
515 {
516  if( column & FamilyList )
517  {
518  d->familyListBox->setEnabled(state);
519  }
520  if( column & StyleList )
521  {
522  d->styleListBox->setEnabled(state);
523  }
524  if( column & SizeList )
525  {
526  d->sizeListBox->setEnabled(state);
527  d->sizeOfFont->setEnabled(state);
528  }
529 }
530 
531 
532 void KFontChooser::setFont( const QFont& aFont, bool onlyFixed )
533 {
534  d->selFont = aFont;
535  d->selectedSize=aFont.pointSizeF();
536  if (d->selectedSize == -1)
537  d->selectedSize = QFontInfo(aFont).pointSizeF();
538 
539  if( onlyFixed != d->usingFixed)
540  {
541  d->usingFixed = onlyFixed;
542  d->fillFamilyListBox(d->usingFixed);
543  }
544  d->setupDisplay();
545 }
546 
547 
548 KFontChooser::FontDiffFlags KFontChooser::fontDiffFlags() const
549 {
550  FontDiffFlags diffFlags = NoFontDiffFlags;
551 
552  if ( d->familyCheckbox && d->familyCheckbox->isChecked() ) {
553  diffFlags |= FontDiffFamily;
554  }
555 
556  if ( d->styleCheckbox && d->styleCheckbox->isChecked() ) {
557  diffFlags |= FontDiffStyle;
558  }
559 
560  if ( d->sizeCheckbox && d->sizeCheckbox->isChecked() ) {
561  diffFlags |= FontDiffSize;
562  }
563 
564  return diffFlags;
565 }
566 
567 QFont KFontChooser::font() const
568 {
569  return d->selFont;
570 }
571 
572 void KFontChooser::Private::_k_toggled_checkbox()
573 {
574  familyListBox->setEnabled( familyCheckbox->isChecked() );
575  styleListBox->setEnabled( styleCheckbox->isChecked() );
576  sizeListBox->setEnabled( sizeCheckbox->isChecked() );
577  sizeOfFont->setEnabled( sizeCheckbox->isChecked() );
578 }
579 
580 void KFontChooser::Private::_k_family_chosen_slot(const QString& family)
581 {
582  if ( !signalsAllowed ) {
583  return;
584  }
585  signalsAllowed = false;
586 
587  QString currentFamily;
588  if (family.isEmpty()) {
589  Q_ASSERT( familyListBox->currentItem() );
590  if (familyListBox->currentItem()) {
591  currentFamily = qtFamilies[familyListBox->currentItem()->text()];
592  }
593  }
594  else {
595  currentFamily = qtFamilies[family];
596  }
597 
598  // Get the list of styles available in this family.
599  QFontDatabase dbase;
600  QStringList styles = dbase.styles(currentFamily);
601  if (styles.isEmpty()) {
602  // Avoid extraction, it is in kdeqt.po
603  styles.append(I18NC_NOX("QFontDatabase", "Normal"));
604  }
605 
606  // Filter style strings and add to the listbox.
607  QString pureFamily;
608  splitFontString(family, &pureFamily);
609  QStringList filteredStyles;
610  qtStyles.clear();
611  foreach (const QString &style, styles) {
612  // Sometimes the font database will report an invalid style,
613  // that falls back back to another when set.
614  // Remove such styles, by checking set/get round-trip.
615  if (dbase.styleString(dbase.font(currentFamily, style, 10)) != style) {
616  styles.removeAll(style);
617  continue;
618  }
619 
620  // We don't like Qt's name for some styles.
621  QString styleMod = style;
622  if (style == I18NC_NOX("QFontDatabase", "Normal"))
623  styleMod = i18nc("@item font", "Regular");
624 
625  // i18n: Filtering message, so that translators can script the
626  // style string according to the font family name (e.g. may need
627  // noun-adjective congruence wrt. gender of the family name).
628  // The message provides the dynamic context 'family', which is
629  // the family name to which the style string corresponds.
630  QString fstyle = ki18nc("@item Font style", "%1").subs(styleMod).inContext("family", pureFamily).toString();
631  if (!filteredStyles.contains(fstyle)) {
632  filteredStyles.append(fstyle);
633  qtStyles.insert(fstyle, style);
634  }
635  }
636  styleListBox->clear();
637  styleListBox->addItems(filteredStyles);
638 
639  // Try to set the current style in the listbox to that previous.
640  int listPos = filteredStyles.indexOf(selectedStyle.isEmpty() ? i18nc("@item font", "Regular") : selectedStyle);
641  if (listPos < 0) {
642  // Make extra effort to have Italic selected when Oblique was chosen,
643  // and vice versa, as that is what the user would probably want.
644  QString styleIt = i18nc("@item font", "Italic");
645  QString styleOb = i18nc("@item font", "Oblique");
646  for (int i = 0; i < 2; ++i) {
647  int pos = selectedStyle.indexOf(styleIt);
648  if (pos >= 0) {
649  QString style = selectedStyle;
650  style.replace(pos, styleIt.length(), styleOb);
651  listPos = filteredStyles.indexOf(style);
652  if (listPos >= 0) break;
653  }
654  qSwap(styleIt, styleOb);
655  }
656  }
657  styleListBox->setCurrentRow(listPos >= 0 ? listPos : 0);
658  QString currentStyle = qtStyles[styleListBox->currentItem()->text()];
659 
660  // Recompute the size listbox for this family/style.
661  qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
662  sizeOfFont->setValue(currentSize);
663 
664  selFont = dbase.font(currentFamily, currentStyle, int(currentSize));
665  if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) {
666  selFont.setPointSizeF(currentSize);
667  }
668  emit q->fontSelected(selFont);
669 
670  signalsAllowed = true;
671 }
672 
673 void KFontChooser::Private::_k_style_chosen_slot(const QString& style)
674 {
675  if ( !signalsAllowed ) {
676  return;
677  }
678  signalsAllowed = false;
679 
680  QFontDatabase dbase;
681  QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
682  QString currentStyle;
683  if (style.isEmpty()) {
684  currentStyle = qtStyles[styleListBox->currentItem()->text()];
685  } else {
686  currentStyle = qtStyles[style];
687  }
688 
689  // Recompute the size listbox for this family/style.
690  qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
691  sizeOfFont->setValue(currentSize);
692 
693  selFont = dbase.font(currentFamily, currentStyle, int(currentSize));
694  if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) {
695  selFont.setPointSizeF(currentSize);
696  }
697  emit q->fontSelected(selFont);
698 
699  if (!style.isEmpty()) {
700  selectedStyle = currentStyle;
701  }
702 
703  signalsAllowed = true;
704 }
705 
706 void KFontChooser::Private::_k_size_chosen_slot(const QString& size)
707 {
708  if ( !signalsAllowed ) {
709  return;
710  }
711 
712  signalsAllowed = false;
713 
714  qreal currentSize;
715  if (size.isEmpty()) {
716  currentSize = KGlobal::locale()->readNumber(sizeListBox->currentItem()->text());
717  } else {
718  currentSize = KGlobal::locale()->readNumber(size);
719  }
720 
721  // Reset the customized size slot in the list if not needed.
722  if (customSizeRow >= 0 && selFont.pointSizeF() != currentSize) {
723  sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
724  customSizeRow = -1;
725  }
726 
727  sizeOfFont->setValue(currentSize);
728  selFont.setPointSizeF(currentSize);
729  emit q->fontSelected(selFont);
730 
731  if (!size.isEmpty()) {
732  selectedSize = currentSize;
733  }
734 
735  signalsAllowed = true;
736 }
737 
738 void KFontChooser::Private::_k_size_value_slot(double dval)
739 {
740  if ( !signalsAllowed ) {
741  return;
742  }
743  signalsAllowed = false;
744 
745  // We compare with qreal, so convert for platforms where qreal != double.
746  qreal val = qreal(dval);
747 
748  QFontDatabase dbase;
749  QString family = qtFamilies[familyListBox->currentItem()->text()];
750  QString style = qtStyles[styleListBox->currentItem()->text()];
751 
752  // Reset current size slot in list if it was customized.
753  if (customSizeRow >= 0 && sizeListBox->currentRow() == customSizeRow) {
754  sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
755  customSizeRow = -1;
756  }
757 
758  bool canCustomize = true;
759 
760  // For Qt-bad-sizes workaround: skip this block unconditionally
761  if (!dbase.isSmoothlyScalable(family, style)) {
762  // Bitmap font, allow only discrete sizes.
763  // Determine the nearest in the direction of change.
764  canCustomize = false;
765  int nrows = sizeListBox->count();
766  int row = sizeListBox->currentRow();
767  int nrow;
768  if (val - selFont.pointSizeF() > 0) {
769  for (nrow = row + 1; nrow < nrows; ++nrow)
770  if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) >= val)
771  break;
772  }
773  else {
774  for (nrow = row - 1; nrow >= 0; --nrow)
775  if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) <= val)
776  break;
777  }
778  // Make sure the new row is not out of bounds.
779  nrow = nrow < 0 ? 0 : nrow >= nrows ? nrows - 1 : nrow;
780  // Get the size from the new row and set the spinbox to that size.
781  val = KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text());
782  sizeOfFont->setValue(val);
783  }
784 
785  // Set the current size in the size listbox.
786  int row = nearestSizeRow(val, canCustomize);
787  sizeListBox->setCurrentRow(row);
788 
789  selectedSize = val;
790  selFont.setPointSizeF(val);
791  emit q->fontSelected( selFont );
792 
793  signalsAllowed = true;
794 }
795 
796 void KFontChooser::Private::_k_displaySample( const QFont& font )
797 {
798  sampleEdit->setFont(font);
799  //sampleEdit->setCursorPosition(0);
800 
801  xlfdEdit->setText(font.rawName());
802  xlfdEdit->setCursorPosition(0);
803 
804  //QFontInfo a = QFontInfo(font);
805  //kDebug() << "font: " << a.family () << ", " << a.pointSize ();
806  //kDebug() << " (" << font.toString() << ")\n";
807 }
808 
809 int KFontChooser::Private::nearestSizeRow (qreal val, bool customize)
810 {
811  qreal diff = 1000;
812  int row = 0;
813  for (int r = 0; r < sizeListBox->count(); ++r) {
814  qreal cval = KGlobal::locale()->readNumber(sizeListBox->item(r)->text());
815  if (qAbs(cval - val) < diff) {
816  diff = qAbs(cval - val);
817  row = r;
818  }
819  }
820  // For Qt-bad-sizes workaround: ignore value of customize, use true
821  if (customize && diff > 0) {
822  customSizeRow = row;
823  standardSizeAtCustom = sizeListBox->item(row)->text();
824  sizeListBox->item(row)->setText(formatFontSize(val));
825  }
826  return row;
827 }
828 
829 qreal KFontChooser::Private::fillSizeList (const QList<qreal> &sizes_)
830 {
831  if ( !sizeListBox ) {
832  return 0; //assertion.
833  }
834 
835  QList<qreal> sizes = sizes_;
836  bool canCustomize = false;
837  if (sizes.count() == 0) {
838  static const int c[] = {
839  4, 5, 6, 7,
840  8, 9, 10, 11,
841  12, 13, 14, 15,
842  16, 17, 18, 19,
843  20, 22, 24, 26,
844  28, 32, 48, 64,
845  72, 80, 96, 128,
846  0
847  };
848  for (int i = 0; c[i]; ++i) {
849  sizes.append(c[i]);
850  }
851  // Since sizes were not supplied, this is a vector font,
852  // and size slot customization is allowed.
853  canCustomize = true;
854  }
855 
856  // Insert sizes into the listbox.
857  sizeListBox->clear();
858  qSort(sizes);
859  foreach (qreal size, sizes) {
860  sizeListBox->addItem(formatFontSize(size));
861  }
862 
863  // Return the nearest to selected size.
864  // If the font is vector, the nearest size is always same as selected,
865  // thus size slot customization is allowed.
866  // If the font is bitmap, the nearest size need not be same as selected,
867  // thus size slot customization is not allowed.
868  customSizeRow = -1;
869  int row = nearestSizeRow(selectedSize, canCustomize);
870  return KGlobal::locale()->readNumber(sizeListBox->item(row)->text());
871 }
872 
873 qreal KFontChooser::Private::setupSizeListBox (const QString& family, const QString& style)
874 {
875  QFontDatabase dbase;
876  QList<qreal> sizes;
877  if (dbase.isSmoothlyScalable(family, style)) {
878  // A vector font.
879  //>sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO
880  }
881  else {
882  // A bitmap font.
883  //sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO
884  QList<int> smoothSizes = dbase.smoothSizes(family, style);
885  foreach (int size, smoothSizes) {
886  sizes.append(size);
887  }
888  }
889 
890  // Fill the listbox (uses default list of sizes if the given is empty).
891  // Collect the best fitting size to selected size, to use if not smooth.
892  qreal bestFitSize = fillSizeList(sizes);
893 
894  // Set the best fit size as current in the listbox if available.
895  const QList<QListWidgetItem*> selectedSizeList =
896  sizeListBox->findItems( formatFontSize(bestFitSize),
897  Qt::MatchExactly );
898  if ( !selectedSizeList.isEmpty() ) {
899  sizeListBox->setCurrentItem(selectedSizeList.first());
900  }
901  //TODO - KDE4 : sizeListBox->scrollTo(sizeListBox->currentItem());
902 
903  return bestFitSize;
904 }
905 
906 void KFontChooser::Private::setupDisplay()
907 {
908  QFontDatabase dbase;
909  QString family = selFont.family().toLower();
910  QString style = dbase.styleString(selFont).toLower();
911  qreal size = selFont.pointSizeF();
912  if (size == -1)
913  size = QFontInfo( selFont ).pointSizeF();
914 
915  int numEntries, i;
916 
917  // Direct family match.
918  numEntries = familyListBox->count();
919  for (i = 0; i < numEntries; i++) {
920  if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) {
921  familyListBox->setCurrentRow(i);
922  break;
923  }
924  }
925 
926  // 1st family fallback.
927  if ( i == numEntries )
928  {
929  if (family.contains('['))
930  {
931  family = family.left(family.indexOf('[')).trimmed();
932  for (i = 0; i < numEntries; i++) {
933  if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) {
934  familyListBox->setCurrentRow(i);
935  break;
936  }
937  }
938  }
939  }
940 
941  // 2nd family fallback.
942  if ( i == numEntries )
943  {
944  QString fallback = family+" [";
945  for (i = 0; i < numEntries; i++) {
946  if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(fallback)) {
947  familyListBox->setCurrentRow(i);
948  break;
949  }
950  }
951  }
952 
953  // 3rd family fallback.
954  if ( i == numEntries )
955  {
956  for (i = 0; i < numEntries; i++) {
957  if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(family)) {
958  familyListBox->setCurrentRow(i);
959  break;
960  }
961  }
962  }
963 
964  // Family fallback in case nothing matched. Otherwise, diff doesn't work
965  if ( i == numEntries ) {
966  familyListBox->setCurrentRow( 0 );
967  }
968 
969  // By setting the current item in the family box, the available
970  // styles and sizes for that family have been collected.
971  // Try now to set the current items in the style and size boxes.
972 
973  // Set current style in the listbox.
974  numEntries = styleListBox->count();
975  for (i = 0; i < numEntries; i++) {
976  if (style == qtStyles[styleListBox->item(i)->text()].toLower()) {
977  styleListBox->setCurrentRow(i);
978  break;
979  }
980  }
981  if (i == numEntries) {
982  // Style not found, fallback.
983  styleListBox->setCurrentRow(0);
984  }
985 
986  // Set current size in the listbox.
987  // If smoothly scalable, allow customizing one of the standard size slots,
988  // otherwise just select the nearest available size.
989  QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
990  QString currentStyle = qtFamilies[styleListBox->currentItem()->text()];
991  bool canCustomize = dbase.isSmoothlyScalable(currentFamily, currentStyle);
992  sizeListBox->setCurrentRow(nearestSizeRow(size, canCustomize));
993 
994  // Set current size in the spinbox.
995  sizeOfFont->setValue(KGlobal::locale()->readNumber(sizeListBox->currentItem()->text()));
996 }
997 
998 
999 void KFontChooser::getFontList( QStringList &list, uint fontListCriteria)
1000 {
1001  QFontDatabase dbase;
1002  QStringList lstSys(dbase.families());
1003 
1004  // if we have criteria; then check fonts before adding
1005  if (fontListCriteria)
1006  {
1007  QStringList lstFonts;
1008  for (QStringList::const_iterator it = lstSys.constBegin(); it != lstSys.constEnd(); ++it)
1009  {
1010  if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it)) continue;
1011  if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) &&
1012  !dbase.isBitmapScalable(*it)) continue;
1013  if ((fontListCriteria & SmoothScalableFonts) > 0 && !dbase.isSmoothlyScalable(*it)) continue;
1014  lstFonts.append(*it);
1015  }
1016 
1017  if((fontListCriteria & FixedWidthFonts) > 0) {
1018  // Fallback.. if there are no fixed fonts found, it's probably a
1019  // bug in the font server or Qt. In this case, just use 'fixed'
1020  if (lstFonts.count() == 0)
1021  lstFonts.append("fixed");
1022  }
1023 
1024  lstSys = lstFonts;
1025  }
1026 
1027  lstSys.sort();
1028 
1029  list = lstSys;
1030 }
1031 
1032 void KFontChooser::Private::setFamilyBoxItems(const QStringList &fonts)
1033 {
1034  signalsAllowed = false;
1035 
1036  QStringList trfonts = translateFontNameList(fonts, &qtFamilies);
1037  familyListBox->clear();
1038  familyListBox->addItems(trfonts);
1039 
1040  signalsAllowed = true;
1041 }
1042 
1043 void KFontChooser::Private::fillFamilyListBox(bool onlyFixedFonts)
1044 {
1045  QStringList fontList;
1046  getFontList(fontList, onlyFixedFonts?FixedWidthFonts:0);
1047  setFamilyBoxItems(fontList);
1048 }
1049 
1050 void KFontChooser::Private::_k_showXLFDArea(bool show)
1051 {
1052  if( show )
1053  {
1054  xlfdEdit->parentWidget()->show();
1055  }
1056  else
1057  {
1058  xlfdEdit->parentWidget()->hide();
1059  }
1060 }
1061 
1062 #include "kfontchooser.moc"
1063 #include "sampleedit_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Nov 16 2012 15:01:59 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal