KDEUI
kfontchooser.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@kde.org> 00003 Copyright (c) 1999 Preston Brown <pbrown@kde.org> 00004 Copyright (c) 1999 Mario Weilguni <mweilguni@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kfontchooser.h" 00023 #include "fonthelpers_p.h" 00024 #include "sampleedit_p.h" 00025 00026 #include <QtGui/QCheckBox> 00027 #include <QtGui/QLabel> 00028 #include <QtGui/QLayout> 00029 #include <QtGui/QSplitter> 00030 #include <QtGui/QScrollBar> 00031 #include <QtGui/QFontDatabase> 00032 #include <QtGui/QGroupBox> 00033 #include <kcharsets.h> 00034 #include <kconfig.h> 00035 #include <kdialog.h> 00036 #include <kglobal.h> 00037 #include <kglobalsettings.h> 00038 #include <klineedit.h> 00039 #include <klistwidget.h> 00040 #include <klocale.h> 00041 #include <kstandarddirs.h> 00042 #include <kdebug.h> 00043 #include <knuminput.h> 00044 #include <kconfiggroup.h> 00045 00046 #include <cmath> 00047 00048 // When message extraction needs to be avoided. 00049 #define I18NC_NOX i18nc 00050 00051 static int minimumListWidth( const QListWidget *list ) 00052 { 00053 int w=0; 00054 for( int i=0; i<list->count(); i++ ) 00055 { 00056 int itemWidth = list->visualItemRect(list->item(i)).width(); 00057 // ...and add a space on both sides for not too tight look. 00058 itemWidth += list->fontMetrics().width(' ') * 2; 00059 w = qMax(w,itemWidth); 00060 } 00061 if( w == 0 ) { w = 40; } 00062 w += list->frameWidth() * 2; 00063 w += list->verticalScrollBar()->sizeHint().width(); 00064 return w; 00065 } 00066 00067 static int minimumListHeight( const QListWidget *list, int numVisibleEntry ) 00068 { 00069 int w = list->count() > 0 ? list->visualItemRect(list->item(0)).height() : 00070 list->fontMetrics().lineSpacing(); 00071 00072 if( w < 0 ) { w = 10; } 00073 if( numVisibleEntry <= 0 ) { numVisibleEntry = 4; } 00074 return ( w * numVisibleEntry + 2 * list->frameWidth() ); 00075 } 00076 00077 static QString formatFontSize(qreal size) 00078 { 00079 return KGlobal::locale()->formatNumber(size, (size == floor(size)) ? 0 : 1); 00080 } 00081 00082 class KFontChooser::Private 00083 { 00084 public: 00085 Private( KFontChooser* qq ) 00086 : q( qq ) 00087 { 00088 m_palette.setColor(QPalette::Active, QPalette::Text, Qt::black); 00089 m_palette.setColor(QPalette::Active, QPalette::Base, Qt::white); 00090 signalsAllowed = true; 00091 selectedSize = -1; 00092 customSizeRow = -1; 00093 } 00094 00095 // pointer to an optinally supplied list of fonts to 00096 // inserted into the fontdialog font-family combo-box 00097 // QStringList fontList; 00098 00099 void setFamilyBoxItems(const QStringList &fonts); 00100 void fillFamilyListBox(bool onlyFixedFonts = false); 00101 int nearestSizeRow(qreal val, bool customize); 00102 qreal fillSizeList(const QList<qreal> &sizes = QList<qreal>()); 00103 qreal setupSizeListBox(const QString& family, const QString& style); 00104 00105 void setupDisplay(); 00106 QString styleIdentifier (const QFont &font); 00107 00108 void _k_toggled_checkbox(); 00109 void _k_family_chosen_slot(const QString&); 00110 void _k_size_chosen_slot(const QString&); 00111 void _k_style_chosen_slot(const QString&); 00112 void _k_displaySample(const QFont &font); 00113 void _k_showXLFDArea(bool); 00114 void _k_size_value_slot(double); 00115 00116 KFontChooser *q; 00117 00118 QPalette m_palette; 00119 bool signalsAllowed:1; 00120 00121 bool usingFixed:1; 00122 00123 KDoubleNumInput *sizeOfFont; 00124 00125 SampleEdit *sampleEdit; 00126 KLineEdit *xlfdEdit; 00127 00128 QLabel *familyLabel; 00129 QLabel *styleLabel; 00130 QCheckBox *familyCheckbox; 00131 QCheckBox *styleCheckbox; 00132 QCheckBox *sizeCheckbox; 00133 QLabel *sizeLabel; 00134 KListWidget *familyListBox; 00135 KListWidget *styleListBox; 00136 KListWidget *sizeListBox; 00137 QCheckBox *sizeIsRelativeCheckBox; 00138 00139 QFont selFont; 00140 00141 QString selectedStyle; 00142 qreal selectedSize; 00143 00144 int customSizeRow; 00145 QString standardSizeAtCustom; 00146 00147 // Mappings of translated to Qt originated family and style strings. 00148 QHash<QString, QString> qtFamilies; 00149 QHash<QString, QString> qtStyles; 00150 // Mapping of translated style strings to internal style identifiers. 00151 QHash<QString, QString> styleIDs; 00152 00153 }; 00154 00155 00156 KFontChooser::KFontChooser( QWidget *parent, 00157 const DisplayFlags& flags, 00158 const QStringList &fontList, 00159 int visibleListSize, 00160 Qt::CheckState *sizeIsRelativeState ) 00161 : QWidget(parent), 00162 d( new KFontChooser::Private( this ) ) 00163 { 00164 d->usingFixed = flags & FixedFontsOnly; 00165 setWhatsThis(i18nc("@info:whatsthis", "Here you can choose the font to be used." )); 00166 00167 // The top layout is divided vertically into a splitter with font 00168 // attribute widgets and preview on the top, and XLFD data at the bottom. 00169 QVBoxLayout *topLayout = new QVBoxLayout( this ); 00170 topLayout->setMargin( 0 ); 00171 int checkBoxGap = KDialog::spacingHint() / 2; 00172 00173 // The splitter contains font attribute widgets in the top part, 00174 // and the font preview in the bottom part. 00175 // The splitter is there to allow the user to resize the font preview. 00176 QSplitter *splitter = new QSplitter(Qt::Vertical, this); 00177 splitter->setChildrenCollapsible(false); 00178 topLayout->addWidget(splitter); 00179 00180 // Build the grid of font attribute widgets for the upper splitter part. 00181 // 00182 QWidget *page; 00183 QGridLayout *gridLayout; 00184 int row = 0; 00185 if( flags & DisplayFrame ) 00186 { 00187 page = new QGroupBox( i18n("Requested Font"), this ); 00188 splitter->addWidget(page); 00189 gridLayout = new QGridLayout( page ); 00190 row = 1; 00191 } 00192 else 00193 { 00194 page = new QWidget( this ); 00195 splitter->addWidget(page); 00196 gridLayout = new QGridLayout( page ); 00197 gridLayout->setMargin( 0 ); 00198 } 00199 00200 // 00201 // first, create the labels across the top 00202 // 00203 QHBoxLayout *familyLayout = new QHBoxLayout(); 00204 familyLayout->addSpacing( checkBoxGap ); 00205 if ( flags & ShowDifferences ) { 00206 d->familyCheckbox = new QCheckBox(i18nc("@option:check","Font"), page); 00207 connect(d->familyCheckbox, SIGNAL(toggled(bool)), 00208 this, SLOT(_k_toggled_checkbox())); 00209 familyLayout->addWidget(d->familyCheckbox, 0, Qt::AlignLeft); 00210 d->familyCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font family settings.")); 00211 d->familyCheckbox->setToolTip(i18nc("@info:tooltip","Change font family?") ); 00212 d->familyLabel = 0; 00213 } else { 00214 d->familyCheckbox = 0; 00215 d->familyLabel = new QLabel( i18nc("@label","Font:"), page ); 00216 familyLayout->addWidget(d->familyLabel, 1, Qt::AlignLeft); 00217 } 00218 gridLayout->addLayout(familyLayout, row, 0 ); 00219 00220 QHBoxLayout *styleLayout = new QHBoxLayout(); 00221 if ( flags & ShowDifferences ) { 00222 d->styleCheckbox = new QCheckBox(i18nc("@option:check","Font style"), page); 00223 connect(d->styleCheckbox, SIGNAL(toggled(bool)), 00224 this, SLOT(_k_toggled_checkbox())); 00225 styleLayout->addWidget(d->styleCheckbox, 0, Qt::AlignLeft); 00226 d->styleCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font style settings.")); 00227 d->styleCheckbox->setToolTip(i18nc("@info:tooltip","Change font style?")); 00228 d->styleLabel = 0; 00229 } else { 00230 d->styleCheckbox = 0; 00231 d->styleLabel = new QLabel(i18n("Font style:"), page ); 00232 styleLayout->addWidget(d->styleLabel, 1, Qt::AlignLeft); 00233 } 00234 styleLayout->addSpacing( checkBoxGap ); 00235 gridLayout->addLayout(styleLayout, row, 1 ); 00236 00237 QHBoxLayout *sizeLayout = new QHBoxLayout(); 00238 if ( flags & ShowDifferences ) { 00239 d->sizeCheckbox = new QCheckBox(i18nc("@option:check","Size"),page); 00240 connect(d->sizeCheckbox, SIGNAL(toggled(bool)), 00241 this, SLOT(_k_toggled_checkbox())); 00242 sizeLayout->addWidget(d->sizeCheckbox, 0, Qt::AlignLeft); 00243 d->sizeCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font size settings.")); 00244 d->sizeCheckbox->setToolTip(i18nc("@info:tooltip","Change font size?")); 00245 d->sizeLabel = 0; 00246 } else { 00247 d->sizeCheckbox = 0; 00248 d->sizeLabel = new QLabel(i18nc("@label:listbox Font size", "Size:"), page ); 00249 sizeLayout->addWidget(d->sizeLabel, 1, Qt::AlignLeft); 00250 } 00251 sizeLayout->addSpacing( checkBoxGap ); 00252 sizeLayout->addSpacing( checkBoxGap ); // prevent label from eating border 00253 gridLayout->addLayout(sizeLayout, row, 2 ); 00254 00255 row ++; 00256 00257 // 00258 // now create the actual boxes that hold the info 00259 // 00260 d->familyListBox = new KListWidget( page ); 00261 d->familyListBox->setEnabled( flags ^ ShowDifferences ); 00262 gridLayout->addWidget( d->familyListBox, row, 0 ); 00263 QString fontFamilyWhatsThisText ( 00264 i18nc("@info:whatsthis","Here you can choose the font family to be used." )); 00265 d->familyListBox->setWhatsThis(fontFamilyWhatsThisText ); 00266 00267 if ( flags & ShowDifferences ) { 00268 d->familyCheckbox->setWhatsThis(fontFamilyWhatsThisText ); 00269 } else { 00270 d->familyLabel->setWhatsThis(fontFamilyWhatsThisText ); 00271 } 00272 00273 connect(d->familyListBox, SIGNAL(currentTextChanged(QString)), 00274 this, SLOT(_k_family_chosen_slot(QString))); 00275 if ( !fontList.isEmpty() ) { 00276 d->setFamilyBoxItems(fontList); 00277 } 00278 else 00279 { 00280 d->fillFamilyListBox( flags & FixedFontsOnly ); 00281 } 00282 00283 d->familyListBox->setMinimumWidth( minimumListWidth( d->familyListBox ) ); 00284 d->familyListBox->setMinimumHeight( 00285 minimumListHeight( d->familyListBox, visibleListSize ) ); 00286 00287 d->styleListBox = new KListWidget( page ); 00288 d->styleListBox->setEnabled( flags ^ ShowDifferences ); 00289 gridLayout->addWidget(d->styleListBox, row, 1); 00290 d->styleListBox->setWhatsThis(i18nc("@info:whatsthis","Here you can choose the font style to be used." )); 00291 if ( flags & ShowDifferences ) { 00292 ((QWidget *)d->styleCheckbox)->setWhatsThis(fontFamilyWhatsThisText ); 00293 } else { 00294 ((QWidget *)d->styleLabel)->setWhatsThis( fontFamilyWhatsThisText ); 00295 } 00296 // Populate usual styles, to determine minimum list width; 00297 // will be replaced later with correct styles. 00298 d->styleListBox->addItem(i18nc("@item font","Regular")); 00299 d->styleListBox->addItem(i18nc("@item font","Italic")); 00300 d->styleListBox->addItem(i18nc("@item font","Oblique")); 00301 d->styleListBox->addItem(i18nc("@item font","Bold")); 00302 d->styleListBox->addItem(i18nc("@item font","Bold Italic")); 00303 d->styleListBox->setMinimumWidth( minimumListWidth( d->styleListBox ) ); 00304 d->styleListBox->setMinimumHeight( 00305 minimumListHeight( d->styleListBox, visibleListSize ) ); 00306 00307 connect(d->styleListBox, SIGNAL(currentTextChanged(QString)), 00308 this, SLOT(_k_style_chosen_slot(QString))); 00309 00310 00311 d->sizeListBox = new KListWidget( page ); 00312 d->sizeOfFont = new KDoubleNumInput(page); 00313 d->sizeOfFont->setMinimum(4); 00314 d->sizeOfFont->setMaximum(999); 00315 d->sizeOfFont->setDecimals(1); 00316 d->sizeOfFont->setSingleStep(1); 00317 d->sizeOfFont->setSliderEnabled(false); 00318 00319 d->sizeListBox->setEnabled( flags ^ ShowDifferences ); 00320 d->sizeOfFont->setEnabled( flags ^ ShowDifferences ); 00321 if( sizeIsRelativeState ) { 00322 QString sizeIsRelativeCBText = 00323 i18nc("@item font size","Relative"); 00324 QString sizeIsRelativeCBToolTipText = 00325 i18n("Font size<br /><i>fixed</i> or <i>relative</i><br />to environment"); 00326 QString sizeIsRelativeCBWhatsThisText = 00327 i18n("Here you can switch between fixed font size and font size " 00328 "to be calculated dynamically and adjusted to changing " 00329 "environment (e.g. widget dimensions, paper size)." ); 00330 d->sizeIsRelativeCheckBox = new QCheckBox( sizeIsRelativeCBText, 00331 page ); 00332 d->sizeIsRelativeCheckBox->setTristate( flags & ShowDifferences ); 00333 QGridLayout *sizeLayout2 = new QGridLayout(); 00334 sizeLayout2->setSpacing( KDialog::spacingHint()/2 ); 00335 gridLayout->addLayout(sizeLayout2, row, 2); 00336 sizeLayout2->setColumnStretch( 1, 1 ); // to prevent text from eating the right border 00337 sizeLayout2->addWidget( d->sizeOfFont, 0, 0, 1, 2); 00338 sizeLayout2->addWidget(d->sizeListBox, 1,0, 1,2); 00339 sizeLayout2->addWidget(d->sizeIsRelativeCheckBox, 2, 0, Qt::AlignLeft); 00340 d->sizeIsRelativeCheckBox->setWhatsThis(sizeIsRelativeCBWhatsThisText ); 00341 d->sizeIsRelativeCheckBox->setToolTip( sizeIsRelativeCBToolTipText ); 00342 } 00343 else { 00344 d->sizeIsRelativeCheckBox = 0L; 00345 QGridLayout *sizeLayout2 = new QGridLayout(); 00346 sizeLayout2->setSpacing( KDialog::spacingHint()/2 ); 00347 gridLayout->addLayout(sizeLayout2, row, 2); 00348 sizeLayout2->addWidget( d->sizeOfFont, 0, 0); 00349 sizeLayout2->addWidget(d->sizeListBox, 1,0); 00350 } 00351 QString fontSizeWhatsThisText = 00352 i18n("Here you can choose the font size to be used." ); 00353 d->sizeListBox->setWhatsThis(fontSizeWhatsThisText ); 00354 00355 if ( flags & ShowDifferences ) { 00356 ((QWidget *)d->sizeCheckbox)->setWhatsThis(fontSizeWhatsThisText ); 00357 } else { 00358 ((QWidget *)d->sizeLabel)->setWhatsThis( fontSizeWhatsThisText ); 00359 } 00360 00361 // Populate with usual sizes, to determine minimum list width; 00362 // will be replaced later with correct sizes. 00363 d->fillSizeList(); 00364 d->sizeListBox->setMinimumWidth( minimumListWidth(d->sizeListBox) + 00365 d->sizeListBox->fontMetrics().maxWidth() ); 00366 d->sizeListBox->setMinimumHeight( 00367 minimumListHeight( d->sizeListBox, visibleListSize ) ); 00368 00369 connect( d->sizeOfFont, SIGNAL(valueChanged(double)), 00370 this, SLOT(_k_size_value_slot(double))); 00371 00372 connect( d->sizeListBox, SIGNAL(currentTextChanged(QString)), 00373 this, SLOT(_k_size_chosen_slot(QString)) ); 00374 00375 row ++; 00376 // 00377 // Completed the font attribute grid. 00378 00379 // Add the font preview into the lower part of the splitter. 00380 // 00381 d->sampleEdit = new SampleEdit(page); 00382 d->sampleEdit->setAcceptRichText(false); 00383 QFont tmpFont( KGlobalSettings::generalFont().family(), 64, QFont::Black ); 00384 d->sampleEdit->setFont(tmpFont); 00385 d->sampleEdit->setMinimumHeight( d->sampleEdit->fontMetrics().lineSpacing() ); 00386 // i18n: A classical test phrase, with all letters of the English alphabet. 00387 // Replace it with a sample text in your language, such that it is 00388 // representative of language's writing system. 00389 // If you wish, you can input several lines of text separated by \n. 00390 setSampleText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog")); 00391 d->sampleEdit->setTextCursor(QTextCursor(d->sampleEdit->document())); 00392 QString sampleEditWhatsThisText = 00393 i18n("This sample text illustrates the current settings. " 00394 "You may edit it to test special characters." ); 00395 d->sampleEdit->setWhatsThis(sampleEditWhatsThisText ); 00396 00397 connect(this, SIGNAL(fontSelected(QFont)), 00398 this, SLOT(_k_displaySample(QFont))); 00399 00400 splitter->addWidget(d->sampleEdit); 00401 // 00402 // Finished setting up the splitter. 00403 00404 // Add XLFD data below the font attributes/preview splitter. 00405 // 00406 QVBoxLayout *vbox; 00407 if( flags & DisplayFrame ) 00408 { 00409 page = new QGroupBox( i18n("Actual Font"), this ); 00410 topLayout->addWidget(page); 00411 vbox = new QVBoxLayout( page ); 00412 vbox->addSpacing( fontMetrics().lineSpacing() ); 00413 } 00414 else 00415 { 00416 page = new QWidget( this ); 00417 topLayout->addWidget(page); 00418 vbox = new QVBoxLayout( page ); 00419 vbox->setMargin( 0 ); 00420 QLabel *label = new QLabel( i18n("Actual Font"), page ); 00421 vbox->addWidget( label ); 00422 } 00423 00424 d->xlfdEdit = new KLineEdit( page ); 00425 vbox->addWidget( d->xlfdEdit ); 00426 // 00427 // Finished setting up the chooser layout. 00428 00429 // lets initialize the display if possible 00430 setFont( d->usingFixed ? KGlobalSettings::fixedFont() : KGlobalSettings::generalFont(), d->usingFixed ); 00431 00432 // check or uncheck or gray out the "relative" checkbox 00433 if( sizeIsRelativeState && d->sizeIsRelativeCheckBox ) 00434 setSizeIsRelative( *sizeIsRelativeState ); 00435 00436 KConfigGroup cg(KGlobal::config(), QLatin1String("General")); 00437 d->_k_showXLFDArea(cg.readEntry(QLatin1String("fontSelectorShowXLFD"), false)); 00438 00439 // Set focus to the size list as this is the most commonly changed property 00440 d->sizeListBox->setFocus(); 00441 } 00442 00443 KFontChooser::~KFontChooser() 00444 { 00445 delete d; 00446 } 00447 00448 void KFontChooser::setColor( const QColor & col ) 00449 { 00450 d->m_palette.setColor( QPalette::Active, QPalette::Text, col ); 00451 QPalette pal = d->sampleEdit->palette(); 00452 pal.setColor( QPalette::Active, QPalette::Text, col ); 00453 d->sampleEdit->setPalette( pal ); 00454 QTextCursor cursor = d->sampleEdit->textCursor(); 00455 d->sampleEdit->selectAll(); 00456 d->sampleEdit->setTextColor( col ); 00457 d->sampleEdit->setTextCursor( cursor ); 00458 } 00459 00460 QColor KFontChooser::color() const 00461 { 00462 return d->m_palette.color( QPalette::Active, QPalette::Text ); 00463 } 00464 00465 void KFontChooser::setBackgroundColor( const QColor & col ) 00466 { 00467 d->m_palette.setColor( QPalette::Active, QPalette::Base, col ); 00468 QPalette pal = d->sampleEdit->palette(); 00469 pal.setColor( QPalette::Active, QPalette::Base, col ); 00470 d->sampleEdit->setPalette( pal ); 00471 } 00472 00473 QColor KFontChooser::backgroundColor() const 00474 { 00475 return d->m_palette.color( QPalette::Active, QPalette::Base ); 00476 } 00477 00478 void KFontChooser::setSizeIsRelative( Qt::CheckState relative ) 00479 { 00480 // check or uncheck or gray out the "relative" checkbox 00481 if( d->sizeIsRelativeCheckBox ) { 00482 if( Qt::PartiallyChecked == relative ) 00483 d->sizeIsRelativeCheckBox->setCheckState(Qt::PartiallyChecked); 00484 else 00485 d->sizeIsRelativeCheckBox->setCheckState( (Qt::Checked == relative ) ? Qt::Checked : Qt::Unchecked); 00486 } 00487 } 00488 00489 Qt::CheckState KFontChooser::sizeIsRelative() const 00490 { 00491 return d->sizeIsRelativeCheckBox 00492 ? d->sizeIsRelativeCheckBox->checkState() 00493 : Qt::PartiallyChecked; 00494 } 00495 00496 QString KFontChooser::sampleText() const 00497 { 00498 return d->sampleEdit->toPlainText(); 00499 } 00500 00501 void KFontChooser::setSampleText( const QString &text ) 00502 { 00503 d->sampleEdit->setPlainText(text); 00504 } 00505 00506 void KFontChooser::setSampleBoxVisible( bool visible ) 00507 { 00508 d->sampleEdit->setVisible( visible ); 00509 } 00510 00511 QSize KFontChooser::sizeHint( void ) const 00512 { 00513 return minimumSizeHint(); 00514 } 00515 00516 00517 void KFontChooser::enableColumn( int column, bool state ) 00518 { 00519 if( column & FamilyList ) 00520 { 00521 d->familyListBox->setEnabled(state); 00522 } 00523 if( column & StyleList ) 00524 { 00525 d->styleListBox->setEnabled(state); 00526 } 00527 if( column & SizeList ) 00528 { 00529 d->sizeListBox->setEnabled(state); 00530 d->sizeOfFont->setEnabled(state); 00531 } 00532 } 00533 00534 00535 void KFontChooser::setFont( const QFont& aFont, bool onlyFixed ) 00536 { 00537 d->selFont = aFont; 00538 d->selectedSize=aFont.pointSizeF(); 00539 if (d->selectedSize == -1) 00540 d->selectedSize = QFontInfo(aFont).pointSizeF(); 00541 00542 if( onlyFixed != d->usingFixed) 00543 { 00544 d->usingFixed = onlyFixed; 00545 d->fillFamilyListBox(d->usingFixed); 00546 } 00547 d->setupDisplay(); 00548 } 00549 00550 00551 KFontChooser::FontDiffFlags KFontChooser::fontDiffFlags() const 00552 { 00553 FontDiffFlags diffFlags = NoFontDiffFlags; 00554 00555 if ( d->familyCheckbox && d->familyCheckbox->isChecked() ) { 00556 diffFlags |= FontDiffFamily; 00557 } 00558 00559 if ( d->styleCheckbox && d->styleCheckbox->isChecked() ) { 00560 diffFlags |= FontDiffStyle; 00561 } 00562 00563 if ( d->sizeCheckbox && d->sizeCheckbox->isChecked() ) { 00564 diffFlags |= FontDiffSize; 00565 } 00566 00567 return diffFlags; 00568 } 00569 00570 QFont KFontChooser::font() const 00571 { 00572 return d->selFont; 00573 } 00574 00575 void KFontChooser::Private::_k_toggled_checkbox() 00576 { 00577 familyListBox->setEnabled( familyCheckbox->isChecked() ); 00578 styleListBox->setEnabled( styleCheckbox->isChecked() ); 00579 sizeListBox->setEnabled( sizeCheckbox->isChecked() ); 00580 sizeOfFont->setEnabled( sizeCheckbox->isChecked() ); 00581 } 00582 00583 void KFontChooser::Private::_k_family_chosen_slot(const QString& family) 00584 { 00585 if ( !signalsAllowed ) { 00586 return; 00587 } 00588 signalsAllowed = false; 00589 00590 QString currentFamily; 00591 if (family.isEmpty()) { 00592 Q_ASSERT( familyListBox->currentItem() ); 00593 if (familyListBox->currentItem()) { 00594 currentFamily = qtFamilies[familyListBox->currentItem()->text()]; 00595 } 00596 } 00597 else { 00598 currentFamily = qtFamilies[family]; 00599 } 00600 00601 // Get the list of styles available in this family. 00602 QFontDatabase dbase; 00603 QStringList styles = dbase.styles(currentFamily); 00604 if (styles.isEmpty()) { 00605 // Avoid extraction, it is in kdeqt.po 00606 styles.append(I18NC_NOX("QFontDatabase", "Normal")); 00607 } 00608 00609 // Filter style strings and add to the listbox. 00610 QString pureFamily; 00611 splitFontString(family, &pureFamily); 00612 QStringList filteredStyles; 00613 qtStyles.clear(); 00614 styleIDs.clear(); 00615 foreach (const QString &style, styles) { 00616 // Sometimes the font database will report an invalid style, 00617 // that falls back back to another when set. 00618 // Remove such styles, by checking set/get round-trip. 00619 QFont testFont = dbase.font(currentFamily, style, 10); 00620 if (dbase.styleString(testFont) != style) { 00621 styles.removeAll(style); 00622 continue; 00623 } 00624 00625 // We don't like Qt's name for some styles. 00626 // FIXME: Actually "Normal" is better, remove this in KF5. 00627 QString styleMod = style; 00628 if (style == I18NC_NOX("QFontDatabase", "Normal")) 00629 styleMod = i18nc("@item font", "Regular"); 00630 00631 // i18n: Filtering message, so that translators can script the 00632 // style string according to the font family name (e.g. may need 00633 // noun-adjective congruence wrt. gender of the family name). 00634 // The message provides the dynamic context 'family', which is 00635 // the family name to which the style string corresponds. 00636 QString fstyle = ki18nc("@item Font style", "%1").subs(styleMod).inContext("family", pureFamily).toString(); 00637 if (!filteredStyles.contains(fstyle)) { 00638 filteredStyles.append(fstyle); 00639 qtStyles.insert(fstyle, style); 00640 styleIDs.insert(fstyle, styleIdentifier(testFont)); 00641 } 00642 } 00643 styleListBox->clear(); 00644 styleListBox->addItems(filteredStyles); 00645 00646 // Try to set the current style in the listbox to that previous. 00647 int listPos = filteredStyles.indexOf(selectedStyle.isEmpty() ? i18nc("@item font", "Regular") : selectedStyle); 00648 if (listPos < 0) { 00649 // Make extra effort to have Italic selected when Oblique was chosen, 00650 // and vice versa, as that is what the user would probably want. 00651 QString styleIt = i18nc("@item font", "Italic"); 00652 QString styleOb = i18nc("@item font", "Oblique"); 00653 for (int i = 0; i < 2; ++i) { 00654 int pos = selectedStyle.indexOf(styleIt); 00655 if (pos >= 0) { 00656 QString style = selectedStyle; 00657 style.replace(pos, styleIt.length(), styleOb); 00658 listPos = filteredStyles.indexOf(style); 00659 if (listPos >= 0) break; 00660 } 00661 qSwap(styleIt, styleOb); 00662 } 00663 } 00664 styleListBox->setCurrentRow(listPos >= 0 ? listPos : 0); 00665 QString currentStyle = qtStyles[styleListBox->currentItem()->text()]; 00666 00667 // Recompute the size listbox for this family/style. 00668 qreal currentSize = setupSizeListBox(currentFamily, currentStyle); 00669 sizeOfFont->setValue(currentSize); 00670 00671 selFont = dbase.font(currentFamily, currentStyle, int(currentSize)); 00672 if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) { 00673 selFont.setPointSizeF(currentSize); 00674 } 00675 emit q->fontSelected(selFont); 00676 00677 signalsAllowed = true; 00678 } 00679 00680 void KFontChooser::Private::_k_style_chosen_slot(const QString& style) 00681 { 00682 if ( !signalsAllowed ) { 00683 return; 00684 } 00685 signalsAllowed = false; 00686 00687 QFontDatabase dbase; 00688 QString currentFamily = qtFamilies[familyListBox->currentItem()->text()]; 00689 QString currentStyle; 00690 if (style.isEmpty()) { 00691 currentStyle = qtStyles[styleListBox->currentItem()->text()]; 00692 } else { 00693 currentStyle = qtStyles[style]; 00694 } 00695 00696 // Recompute the size listbox for this family/style. 00697 qreal currentSize = setupSizeListBox(currentFamily, currentStyle); 00698 sizeOfFont->setValue(currentSize); 00699 00700 selFont = dbase.font(currentFamily, currentStyle, int(currentSize)); 00701 if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) { 00702 selFont.setPointSizeF(currentSize); 00703 } 00704 emit q->fontSelected(selFont); 00705 00706 if (!style.isEmpty()) { 00707 selectedStyle = currentStyle; 00708 } 00709 00710 signalsAllowed = true; 00711 } 00712 00713 void KFontChooser::Private::_k_size_chosen_slot(const QString& size) 00714 { 00715 if ( !signalsAllowed ) { 00716 return; 00717 } 00718 00719 signalsAllowed = false; 00720 00721 qreal currentSize; 00722 if (size.isEmpty()) { 00723 currentSize = KGlobal::locale()->readNumber(sizeListBox->currentItem()->text()); 00724 } else { 00725 currentSize = KGlobal::locale()->readNumber(size); 00726 } 00727 00728 // Reset the customized size slot in the list if not needed. 00729 if (customSizeRow >= 0 && selFont.pointSizeF() != currentSize) { 00730 sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom); 00731 customSizeRow = -1; 00732 } 00733 00734 sizeOfFont->setValue(currentSize); 00735 selFont.setPointSizeF(currentSize); 00736 emit q->fontSelected(selFont); 00737 00738 if (!size.isEmpty()) { 00739 selectedSize = currentSize; 00740 } 00741 00742 signalsAllowed = true; 00743 } 00744 00745 void KFontChooser::Private::_k_size_value_slot(double dval) 00746 { 00747 if ( !signalsAllowed ) { 00748 return; 00749 } 00750 signalsAllowed = false; 00751 00752 // We compare with qreal, so convert for platforms where qreal != double. 00753 qreal val = qreal(dval); 00754 00755 QFontDatabase dbase; 00756 QString family = qtFamilies[familyListBox->currentItem()->text()]; 00757 QString style = qtStyles[styleListBox->currentItem()->text()]; 00758 00759 // Reset current size slot in list if it was customized. 00760 if (customSizeRow >= 0 && sizeListBox->currentRow() == customSizeRow) { 00761 sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom); 00762 customSizeRow = -1; 00763 } 00764 00765 bool canCustomize = true; 00766 00767 // For Qt-bad-sizes workaround: skip this block unconditionally 00768 if (!dbase.isSmoothlyScalable(family, style)) { 00769 // Bitmap font, allow only discrete sizes. 00770 // Determine the nearest in the direction of change. 00771 canCustomize = false; 00772 int nrows = sizeListBox->count(); 00773 int row = sizeListBox->currentRow(); 00774 int nrow; 00775 if (val - selFont.pointSizeF() > 0) { 00776 for (nrow = row + 1; nrow < nrows; ++nrow) 00777 if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) >= val) 00778 break; 00779 } 00780 else { 00781 for (nrow = row - 1; nrow >= 0; --nrow) 00782 if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) <= val) 00783 break; 00784 } 00785 // Make sure the new row is not out of bounds. 00786 nrow = nrow < 0 ? 0 : nrow >= nrows ? nrows - 1 : nrow; 00787 // Get the size from the new row and set the spinbox to that size. 00788 val = KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()); 00789 sizeOfFont->setValue(val); 00790 } 00791 00792 // Set the current size in the size listbox. 00793 int row = nearestSizeRow(val, canCustomize); 00794 sizeListBox->setCurrentRow(row); 00795 00796 selectedSize = val; 00797 selFont.setPointSizeF(val); 00798 emit q->fontSelected( selFont ); 00799 00800 signalsAllowed = true; 00801 } 00802 00803 void KFontChooser::Private::_k_displaySample( const QFont& font ) 00804 { 00805 sampleEdit->setFont(font); 00806 //sampleEdit->setCursorPosition(0); 00807 00808 xlfdEdit->setText(font.rawName()); 00809 xlfdEdit->setCursorPosition(0); 00810 00811 //QFontInfo a = QFontInfo(font); 00812 //kDebug() << "font: " << a.family () << ", " << a.pointSize (); 00813 //kDebug() << " (" << font.toString() << ")\n"; 00814 } 00815 00816 int KFontChooser::Private::nearestSizeRow (qreal val, bool customize) 00817 { 00818 qreal diff = 1000; 00819 int row = 0; 00820 for (int r = 0; r < sizeListBox->count(); ++r) { 00821 qreal cval = KGlobal::locale()->readNumber(sizeListBox->item(r)->text()); 00822 if (qAbs(cval - val) < diff) { 00823 diff = qAbs(cval - val); 00824 row = r; 00825 } 00826 } 00827 // For Qt-bad-sizes workaround: ignore value of customize, use true 00828 if (customize && diff > 0) { 00829 customSizeRow = row; 00830 standardSizeAtCustom = sizeListBox->item(row)->text(); 00831 sizeListBox->item(row)->setText(formatFontSize(val)); 00832 } 00833 return row; 00834 } 00835 00836 qreal KFontChooser::Private::fillSizeList (const QList<qreal> &sizes_) 00837 { 00838 if ( !sizeListBox ) { 00839 return 0; //assertion. 00840 } 00841 00842 QList<qreal> sizes = sizes_; 00843 bool canCustomize = false; 00844 if (sizes.count() == 0) { 00845 static const int c[] = { 00846 4, 5, 6, 7, 00847 8, 9, 10, 11, 00848 12, 13, 14, 15, 00849 16, 17, 18, 19, 00850 20, 22, 24, 26, 00851 28, 32, 48, 64, 00852 72, 80, 96, 128, 00853 0 00854 }; 00855 for (int i = 0; c[i]; ++i) { 00856 sizes.append(c[i]); 00857 } 00858 // Since sizes were not supplied, this is a vector font, 00859 // and size slot customization is allowed. 00860 canCustomize = true; 00861 } 00862 00863 // Insert sizes into the listbox. 00864 sizeListBox->clear(); 00865 qSort(sizes); 00866 foreach (qreal size, sizes) { 00867 sizeListBox->addItem(formatFontSize(size)); 00868 } 00869 00870 // Return the nearest to selected size. 00871 // If the font is vector, the nearest size is always same as selected, 00872 // thus size slot customization is allowed. 00873 // If the font is bitmap, the nearest size need not be same as selected, 00874 // thus size slot customization is not allowed. 00875 customSizeRow = -1; 00876 int row = nearestSizeRow(selectedSize, canCustomize); 00877 return KGlobal::locale()->readNumber(sizeListBox->item(row)->text()); 00878 } 00879 00880 qreal KFontChooser::Private::setupSizeListBox (const QString& family, const QString& style) 00881 { 00882 QFontDatabase dbase; 00883 QList<qreal> sizes; 00884 if (dbase.isSmoothlyScalable(family, style)) { 00885 // A vector font. 00886 //>sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO 00887 } 00888 else { 00889 // A bitmap font. 00890 //sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO 00891 QList<int> smoothSizes = dbase.smoothSizes(family, style); 00892 foreach (int size, smoothSizes) { 00893 sizes.append(size); 00894 } 00895 } 00896 00897 // Fill the listbox (uses default list of sizes if the given is empty). 00898 // Collect the best fitting size to selected size, to use if not smooth. 00899 qreal bestFitSize = fillSizeList(sizes); 00900 00901 // Set the best fit size as current in the listbox if available. 00902 const QList<QListWidgetItem*> selectedSizeList = 00903 sizeListBox->findItems( formatFontSize(bestFitSize), 00904 Qt::MatchExactly ); 00905 if ( !selectedSizeList.isEmpty() ) { 00906 sizeListBox->setCurrentItem(selectedSizeList.first()); 00907 } 00908 //TODO - KDE4 : sizeListBox->scrollTo(sizeListBox->currentItem()); 00909 00910 return bestFitSize; 00911 } 00912 00913 void KFontChooser::Private::setupDisplay() 00914 { 00915 QFontDatabase dbase; 00916 QString family = selFont.family().toLower(); 00917 QString styleID = styleIdentifier(selFont); 00918 qreal size = selFont.pointSizeF(); 00919 if (size == -1) 00920 size = QFontInfo( selFont ).pointSizeF(); 00921 00922 int numEntries, i; 00923 00924 // Direct family match. 00925 numEntries = familyListBox->count(); 00926 for (i = 0; i < numEntries; i++) { 00927 if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) { 00928 familyListBox->setCurrentRow(i); 00929 break; 00930 } 00931 } 00932 00933 // 1st family fallback. 00934 if ( i == numEntries ) 00935 { 00936 if (family.contains('[')) 00937 { 00938 family = family.left(family.indexOf('[')).trimmed(); 00939 for (i = 0; i < numEntries; i++) { 00940 if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) { 00941 familyListBox->setCurrentRow(i); 00942 break; 00943 } 00944 } 00945 } 00946 } 00947 00948 // 2nd family fallback. 00949 if ( i == numEntries ) 00950 { 00951 QString fallback = family+" ["; 00952 for (i = 0; i < numEntries; i++) { 00953 if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(fallback)) { 00954 familyListBox->setCurrentRow(i); 00955 break; 00956 } 00957 } 00958 } 00959 00960 // 3rd family fallback. 00961 if ( i == numEntries ) 00962 { 00963 for (i = 0; i < numEntries; i++) { 00964 if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(family)) { 00965 familyListBox->setCurrentRow(i); 00966 break; 00967 } 00968 } 00969 } 00970 00971 // Family fallback in case nothing matched. Otherwise, diff doesn't work 00972 if ( i == numEntries ) { 00973 familyListBox->setCurrentRow( 0 ); 00974 } 00975 00976 // By setting the current item in the family box, the available 00977 // styles and sizes for that family have been collected. 00978 // Try now to set the current items in the style and size boxes. 00979 00980 // Set current style in the listbox. 00981 numEntries = styleListBox->count(); 00982 for (i = 0; i < numEntries; i++) { 00983 if (styleID == styleIDs[styleListBox->item(i)->text()]) { 00984 styleListBox->setCurrentRow(i); 00985 break; 00986 } 00987 } 00988 if (i == numEntries) { 00989 // Style not found, fallback. 00990 styleListBox->setCurrentRow(0); 00991 } 00992 00993 // Set current size in the listbox. 00994 // If smoothly scalable, allow customizing one of the standard size slots, 00995 // otherwise just select the nearest available size. 00996 QString currentFamily = qtFamilies[familyListBox->currentItem()->text()]; 00997 QString currentStyle = qtStyles[styleListBox->currentItem()->text()]; 00998 bool canCustomize = dbase.isSmoothlyScalable(currentFamily, currentStyle); 00999 sizeListBox->setCurrentRow(nearestSizeRow(size, canCustomize)); 01000 01001 // Set current size in the spinbox. 01002 sizeOfFont->setValue(KGlobal::locale()->readNumber(sizeListBox->currentItem()->text())); 01003 } 01004 01005 01006 void KFontChooser::getFontList( QStringList &list, uint fontListCriteria) 01007 { 01008 QFontDatabase dbase; 01009 QStringList lstSys(dbase.families()); 01010 01011 // if we have criteria; then check fonts before adding 01012 if (fontListCriteria) 01013 { 01014 QStringList lstFonts; 01015 for (QStringList::const_iterator it = lstSys.constBegin(); it != lstSys.constEnd(); ++it) 01016 { 01017 if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it)) continue; 01018 if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) && 01019 !dbase.isBitmapScalable(*it)) continue; 01020 if ((fontListCriteria & SmoothScalableFonts) > 0 && !dbase.isSmoothlyScalable(*it)) continue; 01021 lstFonts.append(*it); 01022 } 01023 01024 if((fontListCriteria & FixedWidthFonts) > 0) { 01025 // Fallback.. if there are no fixed fonts found, it's probably a 01026 // bug in the font server or Qt. In this case, just use 'fixed' 01027 if (lstFonts.count() == 0) 01028 lstFonts.append("fixed"); 01029 } 01030 01031 lstSys = lstFonts; 01032 } 01033 01034 lstSys.sort(); 01035 01036 list = lstSys; 01037 } 01038 01039 void KFontChooser::Private::setFamilyBoxItems(const QStringList &fonts) 01040 { 01041 signalsAllowed = false; 01042 01043 QStringList trfonts = translateFontNameList(fonts, &qtFamilies); 01044 familyListBox->clear(); 01045 familyListBox->addItems(trfonts); 01046 01047 signalsAllowed = true; 01048 } 01049 01050 void KFontChooser::Private::fillFamilyListBox(bool onlyFixedFonts) 01051 { 01052 QStringList fontList; 01053 getFontList(fontList, onlyFixedFonts?FixedWidthFonts:0); 01054 setFamilyBoxItems(fontList); 01055 } 01056 01057 void KFontChooser::Private::_k_showXLFDArea(bool show) 01058 { 01059 if( show ) 01060 { 01061 xlfdEdit->parentWidget()->show(); 01062 } 01063 else 01064 { 01065 xlfdEdit->parentWidget()->hide(); 01066 } 01067 } 01068 01069 // Human-readable style identifiers returned by QFontDatabase::styleString() 01070 // do not always survive round trip of QFont serialization/deserialization, 01071 // causing wrong style in the style box to be highlighted when 01072 // the chooser dialog is opened. This will cause the style to be changed 01073 // when the dialog is closed and the user did not touch the style box. 01074 // Hence, construct custom style identifiers sufficient for the purpose. 01075 QString KFontChooser::Private::styleIdentifier(const QFont &font) 01076 { 01077 const QChar comma(QLatin1Char(',')); 01078 return QString::number(font.weight()) + comma 01079 + QString::number((int)font.style()) + comma 01080 + QString::number(font.stretch()); 01081 } 01082 01083 #include "kfontchooser.moc" 01084 #include "sampleedit_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:32:39 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:32:39 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.