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