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

KDEUI

  • sources
  • kde-4.12
  • kdelibs
  • 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 
42 static 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 
52 class KFontFamilyDelegate : public QAbstractItemDelegate
53 {
54  Q_OBJECT
55 public:
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 
73 KFontFamilyDelegate::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 
85 void 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 
190 QSize 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 
214 class KFontComboBoxPrivate
215 {
216 public:
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 
231 KFontComboBoxPrivate::KFontComboBoxPrivate (KFontComboBox *parent)
232  : k(parent),
233  currentFont(KGlobalSettings::generalFont()),
234  onlyFixed(false),
235  signalsAllowed(true)
236 {
237 }
238 
239 void 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 
261 void 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 
292 void 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 
312 KFontComboBox::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 
333 KFontComboBox::~KFontComboBox ()
334 {
335  delete d;
336 }
337 
338 void KFontComboBox::setOnlyFixed (bool onlyFixed)
339 {
340  if (onlyFixed != d->onlyFixed) {
341  d->onlyFixed = onlyFixed;
342  d->updateDatabase();
343  }
344 }
345 
346 void KFontComboBox::setFontList (const QStringList &fontList)
347 {
348  if (fontList != d->fontList) {
349  d->fontList = fontList;
350  d->updateDatabase();
351  }
352 }
353 
354 QFont KFontComboBox::currentFont () const
355 {
356  return d->currentFont;
357 }
358 
359 void 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 
368 bool 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 
396 QSize 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 
KFontComboBox::sizeHint
virtual QSize sizeHint() const
The recommended size of the widget.
Definition: kfontcombobox.cpp:396
kdebug.h
kglobalsettings.h
KFontComboBox
A lightweight font selection widget.
Definition: kfontcombobox.h:49
KFontComboBox::setOnlyFixed
void setOnlyFixed(bool onlyFixed)
Toggle selectable fonts to be only those of fixed width or all.
Definition: kfontcombobox.cpp:338
KFontChooser::getFontList
static void getFontList(QStringList &list, uint fontListCriteria)
Creates a list of font strings.
Definition: kfontchooser.cpp:1000
QWidget
KColorScheme::InactiveText
Second color; for example, comments, items which are old, inactive or disabled.
Definition: kcolorscheme.h:210
QString
QHash< QString, QString >
QObject
klocale.h
i18nc
QString i18nc(const char *ctxt, const char *text)
kfontcombobox.h
KColorScheme::foreground
QBrush foreground(ForegroundRole=NormalText) const
Retrieve the requested foreground brush.
Definition: kcolorscheme.cpp:459
KFontComboBox::event
bool event(QEvent *e)
Definition: kfontcombobox.cpp:368
QStringList
KCompletion
A generic class for completing QStrings.
Definition: kcompletion.h:130
KStandardAction::actualSize
KAction * actualSize(const QObject *recvr, const char *slot, QObject *parent)
View the document at its actual size.
Definition: kstandardaction.cpp:349
KFontComboBox::setFontList
void setFontList(const QStringList &fontList)
Set selectable fonts to be only those present in the list.
Definition: kfontcombobox.cpp:346
KCompletion::setIgnoreCase
virtual void setIgnoreCase(bool ignoreCase)
Setting this to true makes KCompletion behave case insensitively.
Definition: kcompletion.cpp:89
kfontchooser.h
KCompletion::setItems
virtual void setItems(const QStringList &list)
Sets the list of items available for completion.
Definition: kcompletion.cpp:99
kcompletion.h
KFontComboBox::currentFontChanged
void currentFontChanged(const QFont &font)
Emitted when a new font has been selected, either through user input or by setFont().
KGlobalSettings
Access the KDE global configuration.
Definition: kglobalsettings.h:58
QListView
QFont
KGlobalSettings::generalFont
static QFont generalFont()
Returns the default general font.
Definition: kglobalsettings.cpp:446
translateFontNameList
QStringList translateFontNameList(const QStringList &names, QHash< QString, QString > *trToRawNames)
Definition: fonthelpers.cpp:96
KColorScheme
A set of methods used to work with colors.
Definition: kcolorscheme.h:71
KFontComboBox::KFontComboBox
KFontComboBox(QWidget *parent=0)
Constructor.
Definition: kfontcombobox.cpp:312
QRect
KComboBox
An enhanced combo box.
Definition: kcombobox.h:148
KFontChooser::FixedWidthFonts
Definition: kfontchooser.h:232
QSize
translateFontName
QString translateFontName(const QString &name)
Definition: fonthelpers.cpp:64
alphabetSample
static QString alphabetSample()
Definition: kfontcombobox.cpp:42
KFontComboBox::~KFontComboBox
virtual ~KFontComboBox()
Destructor.
Definition: kfontcombobox.cpp:333
KFontComboBox::setCurrentFont
void setCurrentFont(const QFont &font)
Set the font to show as selected in the combobox.
Definition: kfontcombobox.cpp:359
KStandardShortcut::completion
const KShortcut & completion()
Complete text in input widgets.
Definition: kstandardshortcut.cpp:363
kcolorscheme.h
KFontComboBox::currentFont
QFont currentFont() const
The font currently selected from the list.
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:49:14 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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