• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 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 
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(familyFont);
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 };
229 
230 KFontComboBoxPrivate::KFontComboBoxPrivate (KFontComboBox *parent)
231 {
232  k = parent;
233  currentFont = KGlobalSettings::generalFont();
234  onlyFixed = false;
235  signalsAllowed = true;
236 }
237 
238 void KFontComboBoxPrivate::updateDatabase ()
239 {
240  QStringList fontFamilies;
241  KFontChooser::getFontList(fontFamilies,
242  onlyFixed ? KFontChooser::FixedWidthFonts : 0);
243 
244  // Translate font families for the list model.
245  delegate->fontFamilyTrMap.clear();
246  QStringList trFontFamilies =
247  translateFontNameList(fontFamilies, &(delegate->fontFamilyTrMap));
248 
249  // Add families to the list model and completion.
250  model->setStringList(trFontFamilies);
251  KCompletion *completion = k->completionObject();
252  if (completion) {
253  completion->insertItems(trFontFamilies);
254  completion->setIgnoreCase(true);
255  }
256 }
257 
258 void KFontComboBoxPrivate::updateIndexToFont ()
259 {
260  // QFontInfo necessary to return the family with proper casing.
261  QString selectedFontFamily = QFontInfo(currentFont).family();
262  QString trSelectedFontFamily = translateFontName(selectedFontFamily);
263  const QStringList trFontFamilies = model->stringList();
264  if (!trFontFamilies.count()) {
265  return;
266  }
267 
268  // Match the font's family with an item in the list.
269  int index = 0;
270  foreach (const QString &trFontFamily, trFontFamilies) {
271  if (trSelectedFontFamily == trFontFamily) {
272  break;
273  }
274  ++index;
275  }
276  if (index == trFontFamilies.count()) {
277  // If no family matched, change font to first on the list.
278  index = 0;
279  currentFont = QFont(delegate->fontFamilyTrMap[trFontFamilies[0]]);
280  emit k->currentFontChanged(currentFont);
281  }
282 
283  // Set the new list item.
284  signalsAllowed = false;
285  k->setCurrentIndex(index);
286  signalsAllowed = true;
287 }
288 
289 void KFontComboBoxPrivate::_k_currentFontChanged (int index)
290 {
291  if (!signalsAllowed) {
292  return;
293  }
294 
295  QString trFontFamily = k->itemText(index);
296  QString fontFamily = delegate->fontFamilyTrMap[trFontFamily];
297  if (!fontFamily.isEmpty()) {
298  currentFont = QFont(fontFamily);
299  emit k->currentFontChanged(currentFont);
300  } else {
301  // Unknown font family given. Just remove from the list.
302  // This should not happen, as adding arbitrary font names is prevented.
303  QStringList lst = model->stringList();
304  lst.removeAll(trFontFamily);
305  model->setStringList(lst);
306  }
307 }
308 
309 KFontComboBox::KFontComboBox (QWidget *parent)
310 : KComboBox(true, parent), d(new KFontComboBoxPrivate(this))
311 {
312  // Inputing arbitrary font names does not make sense.
313  setInsertPolicy(QComboBox::NoInsert);
314 
315  // Special list item painter showing font previews and its list model.
316  d->delegate = new KFontFamilyDelegate(this);
317  setItemDelegate(d->delegate);
318  d->model = new QStringListModel(this);
319  setModel(d->model);
320 
321  // Set current font when a new family has been chosen in the combo.
322  connect(this, SIGNAL(currentIndexChanged(int)),
323  this, SLOT(_k_currentFontChanged(int)));
324 
325  // Initialize font selection and list of available fonts.
326  d->updateDatabase();
327  d->updateIndexToFont();
328 }
329 
330 KFontComboBox::~KFontComboBox ()
331 {
332  delete d;
333 }
334 
335 void KFontComboBox::setOnlyFixed (bool onlyFixed)
336 {
337  if (onlyFixed != d->onlyFixed) {
338  d->onlyFixed = onlyFixed;
339  d->updateDatabase();
340  }
341 }
342 
343 QFont KFontComboBox::currentFont () const
344 {
345  return d->currentFont;
346 }
347 
348 void KFontComboBox::setCurrentFont (const QFont &font)
349 {
350  if (font != d->currentFont) {
351  d->currentFont = font;
352  emit currentFontChanged(d->currentFont);
353  d->updateIndexToFont();
354  }
355 }
356 
357 bool KFontComboBox::event (QEvent *e)
358 {
359  if (e->type() == QEvent::Resize) {
360  QListView *lview = qobject_cast<QListView*>(view());
361  if (lview) {
362  QString sample = alphabetSample();
363  // Limit text sample length to avoid too wide list view.
364  if (sample.length() > 60) {
365  sample = sample.left(57) + "...";
366  }
367  QFont approxFont = KGlobalSettings::generalFont();
368  approxFont.setPointSizeF(approxFont.pointSizeF()
369  * d->delegate->sizeFactSample);
370  int widgetWidth = width();
371  int sampleWidth = QFontMetrics(approxFont).width(sample);
372  sampleWidth = qRound(sampleWidth * 1.1); // extra for wider fonts
373  int iconWidth = d->delegate->truetype.actualSize(size()).width();
374  int vsbarWidth = 0;
375  if (lview->verticalScrollBar()) {
376  vsbarWidth = lview->verticalScrollBar()->width();
377  }
378  lview->window()->setFixedWidth( qMax(widgetWidth, sampleWidth)
379  + iconWidth + vsbarWidth);
380  }
381  }
382  return KComboBox::event(e);
383 }
384 
385 QSize KFontComboBox::sizeHint() const
386 {
387  QSize sz = KComboBox::sizeHint();
388  QFontMetrics fm(KGlobalSettings::generalFont());
389  sz.setWidth(fm.width("m") * 14);
390  return sz;
391 }
392 
393 #include "kfontcombobox.moc"
394 #include "moc_kfontcombobox.moc"
395 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:04:39 by doxygen 1.8.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.8.5 API Reference

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