• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • 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 
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"

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal