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