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

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

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.5 API Reference

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

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