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

Skip menu "kdelibs-4.9.4 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