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

KDEUI

kfontcombobox.cpp
Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002 
00003     Copyright (C) 2008 Chusslove Illich <caslav.ilic@gmx.net>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kfontcombobox.h"
00022 #include "fonthelpers_p.h"
00023 
00024 #include "kdebug.h"
00025 #include "klocale.h"
00026 #include "kcolorscheme.h"
00027 #include "kglobalsettings.h"
00028 #include "kfontchooser.h"
00029 #include "kcompletion.h"
00030 
00031 #include <QEvent>
00032 #include <QListView>
00033 #include <QFontDatabase>
00034 #include <QIcon>
00035 #include <QAbstractItemDelegate>
00036 #include <QStringListModel>
00037 #include <QPainter>
00038 #include <QList>
00039 #include <QHash>
00040 #include <QScrollBar>
00041 
00042 static QString alphabetSample ()
00043 {
00044     return i18nc("short",
00045     // i18n: A shorter version of the alphabet test phrase translated in
00046     // another message. It is displayed in the dropdown list of font previews
00047     // (the font selection combo box), so keep it under the length equivalent
00048     // to 60 or so proportional Latin characters.
00049                  "The Quick Brown Fox Jumps Over The Lazy Dog");
00050 }
00051 
00052 class KFontFamilyDelegate : public QAbstractItemDelegate
00053 {
00054     Q_OBJECT
00055 public:
00056     explicit KFontFamilyDelegate (QObject *parent);
00057 
00058     void paint (QPainter *painter,
00059                 const QStyleOptionViewItem &option,
00060                 const QModelIndex &index) const;
00061 
00062     QSize sizeHint (const QStyleOptionViewItem &option,
00063                     const QModelIndex &index) const;
00064 
00065     QIcon truetype;
00066     QIcon bitmap;
00067     double sizeFactFamily;
00068     double sizeFactSample;
00069 
00070     QHash<QString, QString> fontFamilyTrMap;
00071 };
00072 
00073 KFontFamilyDelegate::KFontFamilyDelegate (QObject *parent)
00074 : QAbstractItemDelegate(parent)
00075 {
00076     truetype = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fonttruetype-16.png"));
00077     bitmap = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fontbitmap-16.png"));
00078 
00079     // Font size factors for family name and text sample in font previes,
00080     // multiplies normal font size.
00081     sizeFactFamily = 1.0;
00082     sizeFactSample = 1.0; // better leave at 1, so that user can relate sizes to default
00083 }
00084 
00085 void KFontFamilyDelegate::paint (QPainter *painter,
00086                                  const QStyleOptionViewItem &option,
00087                                  const QModelIndex &index) const
00088 {
00089     QBrush sampleBrush;
00090     if (option.state & QStyle::State_Selected) {
00091         painter->save();
00092         painter->setBrush(option.palette.highlight());
00093         painter->setPen(Qt::NoPen);
00094         painter->drawRect(option.rect);
00095         painter->setPen(QPen(option.palette.highlightedText(), 0));
00096         sampleBrush = option.palette.highlightedText();
00097     } else {
00098         sampleBrush = KColorScheme(QPalette::Normal).foreground(KColorScheme::InactiveText);
00099     }
00100 
00101     QFont baseFont = KGlobalSettings::generalFont();
00102     QString trFontFamily = index.data(Qt::DisplayRole).toString();
00103     QString fontFamily = fontFamilyTrMap[trFontFamily];
00104 
00105     // Writing systems provided by the font.
00106     QList<QFontDatabase::WritingSystem> availableSystems = QFontDatabase().writingSystems(fontFamily);
00107 
00108     // Intersect font's writing systems with that specified for
00109     // the language's sample text, to see if the sample can be shown.
00110     // If the font reports no writing systems, assume it can show the sample.
00111     bool canShowLanguageSample = true;
00112     if (availableSystems.count() > 0) {
00113         canShowLanguageSample = false;
00114         QString scriptsSpec = i18nc("Numeric IDs of scripts for font previews",
00115         // i18n: Integer which indicates the script you used in the sample text
00116         // for font previews in your language. For the possible values, see
00117         // http://doc.trolltech.com/qfontdatabase.html#WritingSystem-enum
00118         // If the sample text contains several scripts, their IDs can be given
00119         // as a comma-separated list (e.g. for Japanese it is "1,27").
00120                                     "1");
00121         QStringList scriptStrIds = scriptsSpec.split(',');
00122         foreach (const QString &scriptStrId, scriptStrIds) {
00123             bool convOk;
00124             int ws = scriptStrId.toInt(&convOk);
00125             if (   convOk && ws > 0 && ws < QFontDatabase::WritingSystemsCount
00126                 && availableSystems.contains(static_cast<QFontDatabase::WritingSystem>(ws))) {
00127                 canShowLanguageSample = true;
00128                 break;
00129             }
00130         }
00131     }
00132 
00133     // Choose and paint an icon according to the font type, scalable or bitmat.
00134     const QIcon *icon = &bitmap;
00135     if (QFontDatabase().isSmoothlyScalable(fontFamily)) {
00136         icon = &truetype;
00137     }
00138     QRect r = option.rect;
00139     icon->paint(painter, r, Qt::AlignLeft|Qt::AlignTop);
00140 
00141     // Claim space taken up by the icon.
00142     QSize actualSize = icon->actualSize(r.size());
00143     if (option.direction == Qt::RightToLeft) {
00144         r.setRight(r.right() - actualSize.width() - 4);
00145     } else {
00146         r.setLeft(r.left() + actualSize.width() + 4);
00147     }
00148 
00149     // Draw the font family.
00150     QFont oldPainterFont = painter->font();
00151     QFont familyFont = baseFont;
00152     familyFont.setPointSizeF(familyFont.pointSizeF() * sizeFactFamily);
00153     painter->setFont(familyFont);
00154     painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, trFontFamily);
00155 
00156     // Claim space taken up by the font family name.
00157     int h = painter->fontMetrics().lineSpacing();
00158     r.setTop(r.top() + h);
00159 
00160     // Show text sample in user's language if the writing system is supported,
00161     // otherwise show a collage of generic script samples provided by Qt.
00162     // If the font does not report what it supports, assume all.
00163     QString sample;
00164     if (canShowLanguageSample) {
00165         sample = alphabetSample();
00166     } else {
00167         foreach (const QFontDatabase::WritingSystem &ws, availableSystems) {
00168             sample += QFontDatabase::writingSystemSample(ws) + "  ";
00169             if (sample.length() > 40) { // do not let the sample be too long
00170                 break;
00171             }
00172         }
00173         sample = sample.trimmed();
00174     }
00175     QFont sampleFont;
00176     sampleFont.setFamily(fontFamily);
00177     sampleFont.setPointSizeF(sampleFont.pointSizeF() * sizeFactSample);
00178     painter->setFont(sampleFont);
00179     QPen oldPen = painter->pen();
00180     painter->setPen(sampleBrush.color());
00181     painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, sample);
00182     painter->setFont(oldPainterFont);
00183     painter->setPen(oldPen);
00184 
00185     if (option.state & QStyle::State_Selected) {
00186         painter->restore();
00187     }
00188 }
00189 
00190 QSize KFontFamilyDelegate::sizeHint (const QStyleOptionViewItem &option,
00191                                      const QModelIndex &index) const
00192 {
00193     Q_UNUSED(option);
00194 
00195     QFont baseFont = KGlobalSettings::generalFont();
00196     QString trFontFamily = index.data(Qt::DisplayRole).toString();
00197     QString fontFamily = fontFamilyTrMap[trFontFamily];
00198 
00199     QFont familyFont = baseFont;
00200     familyFont.setPointSizeF(familyFont.pointSizeF() * sizeFactFamily);
00201     QFontMetrics familyMetrics(familyFont);
00202 
00203     QFont sampleFont = baseFont;
00204     sampleFont.setFamily(fontFamily);
00205     sampleFont.setPointSizeF(sampleFont.pointSizeF() * sizeFactSample);
00206     QFontMetrics sampleMetrics(sampleFont);
00207     QString sample = alphabetSample();
00208 
00209     // Only the hight matters here, the width is mandated by KFontComboBox::event()
00210     return QSize(qMax(familyMetrics.width(trFontFamily), sampleMetrics.width(sample)),
00211                  qRound(familyMetrics.lineSpacing() + sampleMetrics.lineSpacing() * 1.2));
00212 }
00213 
00214 class KFontComboBoxPrivate
00215 {
00216 public:
00217     KFontComboBoxPrivate (KFontComboBox *parent);
00218     void updateDatabase ();
00219     void updateIndexToFont ();
00220     void _k_currentFontChanged (int index);
00221 
00222     KFontComboBox *k;
00223     QFont currentFont;
00224     bool onlyFixed;
00225     bool signalsAllowed;
00226     KFontFamilyDelegate *delegate;
00227     QStringListModel *model;
00228     QStringList fontList;
00229 };
00230 
00231 KFontComboBoxPrivate::KFontComboBoxPrivate (KFontComboBox *parent)
00232 {
00233     k = parent;
00234     currentFont = KGlobalSettings::generalFont();
00235     onlyFixed = false;
00236     signalsAllowed = true;
00237 }
00238 
00239 void KFontComboBoxPrivate::updateDatabase ()
00240 {
00241     QStringList fontFamilies = fontList;
00242     if (fontList.isEmpty()) {
00243         KFontChooser::getFontList(fontFamilies,
00244                                   onlyFixed ? KFontChooser::FixedWidthFonts : 0);
00245     }
00246 
00247     // Translate font families for the list model.
00248     delegate->fontFamilyTrMap.clear();
00249     QStringList trFontFamilies =
00250         translateFontNameList(fontFamilies, &(delegate->fontFamilyTrMap));
00251 
00252     // Add families to the list model and completion.
00253     model->setStringList(trFontFamilies);
00254     KCompletion *completion = k->completionObject();
00255     if (completion) {
00256         completion->setItems(trFontFamilies);
00257         completion->setIgnoreCase(true);
00258     }
00259 }
00260 
00261 void KFontComboBoxPrivate::updateIndexToFont ()
00262 {
00263     // QFontInfo necessary to return the family with proper casing.
00264     QString selectedFontFamily = QFontInfo(currentFont).family();
00265     QString trSelectedFontFamily = translateFontName(selectedFontFamily);
00266     const QStringList trFontFamilies = model->stringList();
00267     if (!trFontFamilies.count()) {
00268         return;
00269     }
00270 
00271     // Match the font's family with an item in the list.
00272     int index = 0;
00273     foreach (const QString &trFontFamily, trFontFamilies) {
00274         if (trSelectedFontFamily == trFontFamily) {
00275             break;
00276         }
00277         ++index;
00278     }
00279     if (index == trFontFamilies.count()) {
00280         // If no family matched, change font to first on the list.
00281         index = 0;
00282         currentFont = QFont(delegate->fontFamilyTrMap[trFontFamilies[0]]);
00283         emit k->currentFontChanged(currentFont);
00284     }
00285 
00286     // Set the new list item.
00287     signalsAllowed = false;
00288     k->setCurrentIndex(index);
00289     signalsAllowed = true;
00290 }
00291 
00292 void KFontComboBoxPrivate::_k_currentFontChanged (int index)
00293 {
00294     if (!signalsAllowed) {
00295         return;
00296     }
00297 
00298     QString trFontFamily = k->itemText(index);
00299     QString fontFamily = delegate->fontFamilyTrMap[trFontFamily];
00300     if (!fontFamily.isEmpty()) {
00301         currentFont = QFont(fontFamily);
00302         emit k->currentFontChanged(currentFont);
00303     } else {
00304         // Unknown font family given. Just remove from the list.
00305         // This should not happen, as adding arbitrary font names is prevented.
00306         QStringList lst = model->stringList();
00307         lst.removeAll(trFontFamily);
00308         model->setStringList(lst);
00309     }
00310 }
00311 
00312 KFontComboBox::KFontComboBox (QWidget *parent)
00313 : KComboBox(true, parent), d(new KFontComboBoxPrivate(this))
00314 {
00315     // Inputing arbitrary font names does not make sense.
00316     setInsertPolicy(QComboBox::NoInsert);
00317 
00318     // Special list item painter showing font previews and its list model.
00319     d->delegate = new KFontFamilyDelegate(this);
00320     setItemDelegate(d->delegate);
00321     d->model = new QStringListModel(this);
00322     setModel(d->model);
00323 
00324     // Set current font when a new family has been chosen in the combo.
00325     connect(this, SIGNAL(currentIndexChanged(int)),
00326             this, SLOT(_k_currentFontChanged(int)));
00327 
00328     // Initialize font selection and list of available fonts.
00329     d->updateDatabase();
00330     d->updateIndexToFont();
00331 }
00332 
00333 KFontComboBox::~KFontComboBox ()
00334 {
00335     delete d;
00336 }
00337 
00338 void KFontComboBox::setOnlyFixed (bool onlyFixed)
00339 {
00340     if (onlyFixed != d->onlyFixed) {
00341         d->onlyFixed = onlyFixed;
00342         d->updateDatabase();
00343     }
00344 }
00345 
00346 void KFontComboBox::setFontList (const QStringList &fontList)
00347 {
00348     if (fontList != d->fontList) {
00349         d->fontList = fontList;
00350         d->updateDatabase();
00351     }
00352 }
00353 
00354 QFont KFontComboBox::currentFont () const
00355 {
00356     return d->currentFont;
00357 }
00358 
00359 void KFontComboBox::setCurrentFont (const QFont &font)
00360 {
00361     if (font != d->currentFont) {
00362         d->currentFont = font;
00363         emit currentFontChanged(d->currentFont);
00364         d->updateIndexToFont();
00365     }
00366 }
00367 
00368 bool KFontComboBox::event (QEvent *e)
00369 {
00370     if (e->type() == QEvent::Resize) {
00371         QListView *lview = qobject_cast<QListView*>(view());
00372         if (lview) {
00373             QString sample = alphabetSample();
00374             // Limit text sample length to avoid too wide list view.
00375             if (sample.length() > 60) {
00376                 sample = sample.left(57) + "...";
00377             }
00378             QFont approxFont = KGlobalSettings::generalFont();
00379             approxFont.setPointSizeF(approxFont.pointSizeF()
00380                                            * d->delegate->sizeFactSample);
00381             int widgetWidth = width();
00382             int sampleWidth = QFontMetrics(approxFont).width(sample);
00383             sampleWidth = qRound(sampleWidth * 1.1); // extra for wider fonts
00384             int iconWidth = d->delegate->truetype.actualSize(size()).width();
00385             int vsbarWidth = 0;
00386             if (lview->verticalScrollBar()) {
00387                 vsbarWidth = lview->verticalScrollBar()->width();
00388             }
00389             lview->window()->setFixedWidth(  qMax(widgetWidth, sampleWidth)
00390                                            + iconWidth + vsbarWidth);
00391         }
00392     }
00393     return KComboBox::event(e);
00394 }
00395 
00396 QSize KFontComboBox::sizeHint() const
00397 {
00398     QSize sz = KComboBox::sizeHint();
00399     QFontMetrics fm(KGlobalSettings::generalFont());
00400     sz.setWidth(fm.width("m") * 14);
00401     return sz;
00402 }
00403 
00404 #include "kfontcombobox.moc"
00405 #include "moc_kfontcombobox.moc"
00406 
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