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

KDEUI

  • kdeui
  • fonts
kfontcombobox.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2
3 Copyright (C) 2008 Chusslove Illich <caslav.ilic@gmx.net>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "kfontcombobox.h"
22#include "fonthelpers_p.h"
23
24#include "kdebug.h"
25#include "klocale.h"
26#include "kcolorscheme.h"
27#include "kglobalsettings.h"
28#include "kfontchooser.h"
29#include "kcompletion.h"
30
31#include <QEvent>
32#include <QListView>
33#include <QFontDatabase>
34#include <QIcon>
35#include <QAbstractItemDelegate>
36#include <QStringListModel>
37#include <QPainter>
38#include <QList>
39#include <QHash>
40#include <QScrollBar>
41
42static QString alphabetSample ()
43{
44 return i18nc("short",
45 // i18n: A shorter version of the alphabet test phrase translated in
46 // another message. It is displayed in the dropdown list of font previews
47 // (the font selection combo box), so keep it under the length equivalent
48 // to 60 or so proportional Latin characters.
49 "The Quick Brown Fox Jumps Over The Lazy Dog");
50}
51
52class KFontFamilyDelegate : public QAbstractItemDelegate
53{
54 Q_OBJECT
55public:
56 explicit KFontFamilyDelegate (QObject *parent);
57
58 void paint (QPainter *painter,
59 const QStyleOptionViewItem &option,
60 const QModelIndex &index) const;
61
62 QSize sizeHint (const QStyleOptionViewItem &option,
63 const QModelIndex &index) const;
64
65 QIcon truetype;
66 QIcon bitmap;
67 double sizeFactFamily;
68 double sizeFactSample;
69
70 QHash<QString, QString> fontFamilyTrMap;
71};
72
73KFontFamilyDelegate::KFontFamilyDelegate (QObject *parent)
74: QAbstractItemDelegate(parent)
75{
76 truetype = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fonttruetype-16.png"));
77 bitmap = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fontbitmap-16.png"));
78
79 // Font size factors for family name and text sample in font previes,
80 // multiplies normal font size.
81 sizeFactFamily = 1.0;
82 sizeFactSample = 1.0; // better leave at 1, so that user can relate sizes to default
83}
84
85void KFontFamilyDelegate::paint (QPainter *painter,
86 const QStyleOptionViewItem &option,
87 const QModelIndex &index) const
88{
89 QBrush sampleBrush;
90 if (option.state & QStyle::State_Selected) {
91 painter->save();
92 painter->setBrush(option.palette.highlight());
93 painter->setPen(Qt::NoPen);
94 painter->drawRect(option.rect);
95 painter->setPen(QPen(option.palette.highlightedText(), 0));
96 sampleBrush = option.palette.highlightedText();
97 } else {
98 sampleBrush = KColorScheme(QPalette::Normal).foreground(KColorScheme::InactiveText);
99 }
100
101 QFont baseFont = KGlobalSettings::generalFont();
102 QString trFontFamily = index.data(Qt::DisplayRole).toString();
103 QString fontFamily = fontFamilyTrMap[trFontFamily];
104
105 // Writing systems provided by the font.
106 QList<QFontDatabase::WritingSystem> availableSystems = QFontDatabase().writingSystems(fontFamily);
107
108 // Intersect font's writing systems with that specified for
109 // the language's sample text, to see if the sample can be shown.
110 // If the font reports no writing systems, assume it can show the sample.
111 bool canShowLanguageSample = true;
112 if (availableSystems.count() > 0) {
113 canShowLanguageSample = false;
114 QString scriptsSpec = i18nc("Numeric IDs of scripts for font previews",
115 // i18n: Integer which indicates the script you used in the sample text
116 // for font previews in your language. For the possible values, see
117 // http://doc.trolltech.com/qfontdatabase.html#WritingSystem-enum
118 // If the sample text contains several scripts, their IDs can be given
119 // as a comma-separated list (e.g. for Japanese it is "1,27").
120 "1");
121 QStringList scriptStrIds = scriptsSpec.split(',');
122 foreach (const QString &scriptStrId, scriptStrIds) {
123 bool convOk;
124 int ws = scriptStrId.toInt(&convOk);
125 if ( convOk && ws > 0 && ws < QFontDatabase::WritingSystemsCount
126 && availableSystems.contains(static_cast<QFontDatabase::WritingSystem>(ws))) {
127 canShowLanguageSample = true;
128 break;
129 }
130 }
131 }
132
133 // Choose and paint an icon according to the font type, scalable or bitmat.
134 const QIcon *icon = &bitmap;
135 if (QFontDatabase().isSmoothlyScalable(fontFamily)) {
136 icon = &truetype;
137 }
138 QRect r = option.rect;
139 icon->paint(painter, r, Qt::AlignLeft|Qt::AlignTop);
140
141 // Claim space taken up by the icon.
142 QSize actualSize = icon->actualSize(r.size());
143 if (option.direction == Qt::RightToLeft) {
144 r.setRight(r.right() - actualSize.width() - 4);
145 } else {
146 r.setLeft(r.left() + actualSize.width() + 4);
147 }
148
149 // Draw the font family.
150 QFont oldPainterFont = painter->font();
151 QFont familyFont = baseFont;
152 familyFont.setPointSizeF(familyFont.pointSizeF() * sizeFactFamily);
153 painter->setFont(familyFont);
154 painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, trFontFamily);
155
156 // Claim space taken up by the font family name.
157 int h = painter->fontMetrics().lineSpacing();
158 r.setTop(r.top() + h);
159
160 // Show text sample in user's language if the writing system is supported,
161 // otherwise show a collage of generic script samples provided by Qt.
162 // If the font does not report what it supports, assume all.
163 QString sample;
164 if (canShowLanguageSample) {
165 sample = alphabetSample();
166 } else {
167 foreach (const QFontDatabase::WritingSystem &ws, availableSystems) {
168 sample += QFontDatabase::writingSystemSample(ws) + " ";
169 if (sample.length() > 40) { // do not let the sample be too long
170 break;
171 }
172 }
173 sample = sample.trimmed();
174 }
175 QFont sampleFont;
176 sampleFont.setFamily(fontFamily);
177 sampleFont.setPointSizeF(sampleFont.pointSizeF() * sizeFactSample);
178 painter->setFont(sampleFont);
179 QPen oldPen = painter->pen();
180 painter->setPen(sampleBrush.color());
181 painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, sample);
182 painter->setFont(oldPainterFont);
183 painter->setPen(oldPen);
184
185 if (option.state & QStyle::State_Selected) {
186 painter->restore();
187 }
188}
189
190QSize KFontFamilyDelegate::sizeHint (const QStyleOptionViewItem &option,
191 const QModelIndex &index) const
192{
193 Q_UNUSED(option);
194
195 QFont baseFont = KGlobalSettings::generalFont();
196 QString trFontFamily = index.data(Qt::DisplayRole).toString();
197 QString fontFamily = fontFamilyTrMap[trFontFamily];
198
199 QFont familyFont = baseFont;
200 familyFont.setPointSizeF(familyFont.pointSizeF() * sizeFactFamily);
201 QFontMetrics familyMetrics(familyFont);
202
203 QFont sampleFont = baseFont;
204 sampleFont.setFamily(fontFamily);
205 sampleFont.setPointSizeF(sampleFont.pointSizeF() * sizeFactSample);
206 QFontMetrics sampleMetrics(sampleFont);
207 QString sample = alphabetSample();
208
209 // Only the hight matters here, the width is mandated by KFontComboBox::event()
210 return QSize(qMax(familyMetrics.width(trFontFamily), sampleMetrics.width(sample)),
211 qRound(familyMetrics.lineSpacing() + sampleMetrics.lineSpacing() * 1.2));
212}
213
214class KFontComboBoxPrivate
215{
216public:
217 KFontComboBoxPrivate (KFontComboBox *parent);
218 void updateDatabase ();
219 void updateIndexToFont ();
220 void _k_currentFontChanged (int index);
221
222 KFontComboBox *k;
223 QFont currentFont;
224 bool onlyFixed;
225 bool signalsAllowed;
226 KFontFamilyDelegate *delegate;
227 QStringListModel *model;
228 QStringList fontList;
229};
230
231KFontComboBoxPrivate::KFontComboBoxPrivate (KFontComboBox *parent)
232 : k(parent),
233 currentFont(KGlobalSettings::generalFont()),
234 onlyFixed(false),
235 signalsAllowed(true)
236{
237}
238
239void KFontComboBoxPrivate::updateDatabase ()
240{
241 QStringList fontFamilies = fontList;
242 if (fontList.isEmpty()) {
243 KFontChooser::getFontList(fontFamilies,
244 onlyFixed ? KFontChooser::FixedWidthFonts : 0);
245 }
246
247 // Translate font families for the list model.
248 delegate->fontFamilyTrMap.clear();
249 QStringList trFontFamilies =
250 translateFontNameList(fontFamilies, &(delegate->fontFamilyTrMap));
251
252 // Add families to the list model and completion.
253 model->setStringList(trFontFamilies);
254 KCompletion *completion = k->completionObject();
255 if (completion) {
256 completion->setItems(trFontFamilies);
257 completion->setIgnoreCase(true);
258 }
259}
260
261void KFontComboBoxPrivate::updateIndexToFont ()
262{
263 // QFontInfo necessary to return the family with proper casing.
264 QString selectedFontFamily = QFontInfo(currentFont).family();
265 QString trSelectedFontFamily = translateFontName(selectedFontFamily);
266 const QStringList trFontFamilies = model->stringList();
267 if (!trFontFamilies.count()) {
268 return;
269 }
270
271 // Match the font's family with an item in the list.
272 int index = 0;
273 foreach (const QString &trFontFamily, trFontFamilies) {
274 if (trSelectedFontFamily == trFontFamily) {
275 break;
276 }
277 ++index;
278 }
279 if (index == trFontFamilies.count()) {
280 // If no family matched, change font to first on the list.
281 index = 0;
282 currentFont = QFont(delegate->fontFamilyTrMap[trFontFamilies[0]]);
283 emit k->currentFontChanged(currentFont);
284 }
285
286 // Set the new list item.
287 signalsAllowed = false;
288 k->setCurrentIndex(index);
289 signalsAllowed = true;
290}
291
292void KFontComboBoxPrivate::_k_currentFontChanged (int index)
293{
294 if (!signalsAllowed) {
295 return;
296 }
297
298 QString trFontFamily = k->itemText(index);
299 QString fontFamily = delegate->fontFamilyTrMap[trFontFamily];
300 if (!fontFamily.isEmpty()) {
301 currentFont = QFont(fontFamily);
302 emit k->currentFontChanged(currentFont);
303 } else {
304 // Unknown font family given. Just remove from the list.
305 // This should not happen, as adding arbitrary font names is prevented.
306 QStringList lst = model->stringList();
307 lst.removeAll(trFontFamily);
308 model->setStringList(lst);
309 }
310}
311
312KFontComboBox::KFontComboBox (QWidget *parent)
313: KComboBox(true, parent), d(new KFontComboBoxPrivate(this))
314{
315 // Inputing arbitrary font names does not make sense.
316 setInsertPolicy(QComboBox::NoInsert);
317
318 // Special list item painter showing font previews and its list model.
319 d->delegate = new KFontFamilyDelegate(this);
320 setItemDelegate(d->delegate);
321 d->model = new QStringListModel(this);
322 setModel(d->model);
323
324 // Set current font when a new family has been chosen in the combo.
325 connect(this, SIGNAL(currentIndexChanged(int)),
326 this, SLOT(_k_currentFontChanged(int)));
327
328 // Initialize font selection and list of available fonts.
329 d->updateDatabase();
330 d->updateIndexToFont();
331}
332
333KFontComboBox::~KFontComboBox ()
334{
335 delete d;
336}
337
338void KFontComboBox::setOnlyFixed (bool onlyFixed)
339{
340 if (onlyFixed != d->onlyFixed) {
341 d->onlyFixed = onlyFixed;
342 d->updateDatabase();
343 }
344}
345
346void KFontComboBox::setFontList (const QStringList &fontList)
347{
348 if (fontList != d->fontList) {
349 d->fontList = fontList;
350 d->updateDatabase();
351 }
352}
353
354QFont KFontComboBox::currentFont () const
355{
356 return d->currentFont;
357}
358
359void KFontComboBox::setCurrentFont (const QFont &font)
360{
361 if (font != d->currentFont) {
362 d->currentFont = font;
363 emit currentFontChanged(d->currentFont);
364 d->updateIndexToFont();
365 }
366}
367
368bool KFontComboBox::event (QEvent *e)
369{
370 if (e->type() == QEvent::Resize) {
371 QListView *lview = qobject_cast<QListView*>(view());
372 if (lview) {
373 QString sample = alphabetSample();
374 // Limit text sample length to avoid too wide list view.
375 if (sample.length() > 60) {
376 sample = sample.left(57) + "...";
377 }
378 QFont approxFont = KGlobalSettings::generalFont();
379 approxFont.setPointSizeF(approxFont.pointSizeF()
380 * d->delegate->sizeFactSample);
381 int widgetWidth = width();
382 int sampleWidth = QFontMetrics(approxFont).width(sample);
383 sampleWidth = qRound(sampleWidth * 1.1); // extra for wider fonts
384 int iconWidth = d->delegate->truetype.actualSize(size()).width();
385 int vsbarWidth = 0;
386 if (lview->verticalScrollBar()) {
387 vsbarWidth = lview->verticalScrollBar()->width();
388 }
389 lview->window()->setFixedWidth( qMax(widgetWidth, sampleWidth)
390 + iconWidth + vsbarWidth);
391 }
392 }
393 return KComboBox::event(e);
394}
395
396QSize KFontComboBox::sizeHint() const
397{
398 QSize sz = KComboBox::sizeHint();
399 QFontMetrics fm(KGlobalSettings::generalFont());
400 sz.setWidth(fm.width("m") * 14);
401 return sz;
402}
403
404#include "kfontcombobox.moc"
405#include "moc_kfontcombobox.moc"
406
KColorScheme
A set of methods used to work with colors.
Definition: kcolorscheme.h:71
KColorScheme::InactiveText
@ InactiveText
Second color; for example, comments, items which are old, inactive or disabled.
Definition: kcolorscheme.h:210
KColorScheme::foreground
QBrush foreground(ForegroundRole=NormalText) const
Retrieve the requested foreground brush.
Definition: kcolorscheme.cpp:459
KComboBox
An enhanced combo box.
Definition: kcombobox.h:149
KCompletion
A generic class for completing QStrings.
Definition: kcompletion.h:131
KFontChooser::FixedWidthFonts
@ FixedWidthFonts
Definition: kfontchooser.h:232
KFontChooser::getFontList
static void getFontList(QStringList &list, uint fontListCriteria)
Creates a list of font strings.
Definition: kfontchooser.cpp:1000
KFontComboBox
A lightweight font selection widget.
Definition: kfontcombobox.h:50
KFontComboBox::setOnlyFixed
void setOnlyFixed(bool onlyFixed)
Toggle selectable fonts to be only those of fixed width or all.
Definition: kfontcombobox.cpp:338
KFontComboBox::currentFontChanged
void currentFontChanged(const QFont &font)
Emitted when a new font has been selected, either through user input or by setFont().
KFontComboBox::sizeHint
virtual QSize sizeHint() const
The recommended size of the widget.
Definition: kfontcombobox.cpp:396
KFontComboBox::~KFontComboBox
virtual ~KFontComboBox()
Destructor.
Definition: kfontcombobox.cpp:333
KFontComboBox::KFontComboBox
KFontComboBox(QWidget *parent=0)
Constructor.
Definition: kfontcombobox.cpp:312
KFontComboBox::setCurrentFont
void setCurrentFont(const QFont &font)
Set the font to show as selected in the combobox.
Definition: kfontcombobox.cpp:359
KFontComboBox::currentFont
QFont currentFont
Definition: kfontcombobox.h:53
KFontComboBox::setFontList
void setFontList(const QStringList &fontList)
Set selectable fonts to be only those present in the list.
Definition: kfontcombobox.cpp:346
KFontComboBox::event
bool event(QEvent *e)
Definition: kfontcombobox.cpp:368
KGlobalSettings
Access the KDE global configuration.
Definition: kglobalsettings.h:59
KGlobalSettings::generalFont
static QFont generalFont()
Returns the default general font.
Definition: kglobalsettings.cpp:446
QHash
QListView
QList
QObject
QWidget
translateFontName
QString translateFontName(const QString &name)
Definition: fonthelpers.cpp:64
translateFontNameList
QStringList translateFontNameList(const QStringList &names, QHash< QString, QString > *trToRawNames)
Definition: fonthelpers.cpp:96
kcolorscheme.h
kcompletion.h
kdebug.h
kfontchooser.h
alphabetSample
static QString alphabetSample()
Definition: kfontcombobox.cpp:42
kfontcombobox.h
kglobalsettings.h
klocale.h
i18nc
QString i18nc(const char *ctxt, const char *text)
KStandardAction::actualSize
KAction * actualSize(const QObject *recvr, const char *slot, QObject *parent)
View the document at its actual size.
Definition: kstandardaction.cpp:349
KStandardShortcut::completion
const KShortcut & completion()
Complete text in input widgets.
Definition: kstandardshortcut.cpp:363
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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.14.38 API Reference

Skip menu "kdelibs-4.14.38 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