qfontcombobox.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/widgets/qfontcombobox.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtWidgets module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qfontcombobox.h"-
41-
42#ifndef QT_NO_FONTCOMBOBOX-
43-
44#include <qstringlistmodel.h>-
45#include <qitemdelegate.h>-
46#include <qlistview.h>-
47#include <qpainter.h>-
48#include <qevent.h>-
49#include <qapplication.h>-
50#include <private/qcombobox_p.h>-
51#include <QDesktopWidget>-
52#include <qdebug.h>-
53-
54QT_BEGIN_NAMESPACE-
55-
56static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script)-
57{-
58 switch (script) {-
59 case QLocale::ArabicScript:-
60 return QFontDatabase::Arabic;-
61 case QLocale::CyrillicScript:-
62 return QFontDatabase::Cyrillic;-
63 case QLocale::GurmukhiScript:-
64 return QFontDatabase::Gurmukhi;-
65 case QLocale::SimplifiedHanScript:-
66 return QFontDatabase::SimplifiedChinese;-
67 case QLocale::TraditionalHanScript:-
68 return QFontDatabase::TraditionalChinese;-
69 case QLocale::LatinScript:-
70 return QFontDatabase::Latin;-
71 case QLocale::ArmenianScript:-
72 return QFontDatabase::Armenian;-
73 case QLocale::BengaliScript:-
74 return QFontDatabase::Bengali;-
75 case QLocale::DevanagariScript:-
76 return QFontDatabase::Devanagari;-
77 case QLocale::GeorgianScript:-
78 return QFontDatabase::Georgian;-
79 case QLocale::GreekScript:-
80 return QFontDatabase::Greek;-
81 case QLocale::GujaratiScript:-
82 return QFontDatabase::Gujarati;-
83 case QLocale::HebrewScript:-
84 return QFontDatabase::Hebrew;-
85 case QLocale::JapaneseScript:-
86 return QFontDatabase::Japanese;-
87 case QLocale::KhmerScript:-
88 return QFontDatabase::Khmer;-
89 case QLocale::KannadaScript:-
90 return QFontDatabase::Kannada;-
91 case QLocale::KoreanScript:-
92 return QFontDatabase::Korean;-
93 case QLocale::LaoScript:-
94 return QFontDatabase::Lao;-
95 case QLocale::MalayalamScript:-
96 return QFontDatabase::Malayalam;-
97 case QLocale::MyanmarScript:-
98 return QFontDatabase::Myanmar;-
99 case QLocale::TamilScript:-
100 return QFontDatabase::Tamil;-
101 case QLocale::TeluguScript:-
102 return QFontDatabase::Telugu;-
103 case QLocale::ThaanaScript:-
104 return QFontDatabase::Thaana;-
105 case QLocale::ThaiScript:-
106 return QFontDatabase::Thai;-
107 case QLocale::TibetanScript:-
108 return QFontDatabase::Tibetan;-
109 case QLocale::SinhalaScript:-
110 return QFontDatabase::Sinhala;-
111 case QLocale::SyriacScript:-
112 return QFontDatabase::Syriac;-
113 case QLocale::OriyaScript:-
114 return QFontDatabase::Oriya;-
115 case QLocale::OghamScript:-
116 return QFontDatabase::Ogham;-
117 case QLocale::RunicScript:-
118 return QFontDatabase::Runic;-
119 case QLocale::NkoScript:-
120 return QFontDatabase::Nko;-
121 default:-
122 return QFontDatabase::Any;-
123 }-
124}-
125-
126static QFontDatabase::WritingSystem writingSystemFromLocale()-
127{-
128 QStringList uiLanguages = QLocale::system().uiLanguages();-
129 QLocale::Script script;-
130 if (!uiLanguages.isEmpty())-
131 script = QLocale(uiLanguages.at(0)).script();-
132 else-
133 script = QLocale::system().script();-
134-
135 return writingSystemFromScript(script);-
136}-
137-
138static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin)-
139{-
140 QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase().writingSystems(font.family());-
141// qDebug() << font.family() << writingSystems;-
142-
143 // this just confuses the algorithm below. Vietnamese is Latin with lots of special chars-
144 writingSystems.removeOne(QFontDatabase::Vietnamese);-
145 *hasLatin = writingSystems.removeOne(QFontDatabase::Latin);-
146-
147 if (writingSystems.isEmpty())
writingSystems.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
148 return QFontDatabase::Any;
never executed: return QFontDatabase::Any;
0
149-
150 QFontDatabase::WritingSystem system = writingSystemFromLocale();-
151-
152 if (writingSystems.contains(system))
writingSystems...ntains(system)Description
TRUEnever evaluated
FALSEnever evaluated
0
153 return system;
never executed: return system;
0
154-
155 if (system == QFontDatabase::TraditionalChinese
system == QFon...itionalChineseDescription
TRUEnever evaluated
FALSEnever evaluated
0
156 && writingSystems.contains(QFontDatabase::SimplifiedChinese)) {
writingSystems...lifiedChinese)Description
TRUEnever evaluated
FALSEnever evaluated
0
157 return QFontDatabase::SimplifiedChinese;
never executed: return QFontDatabase::SimplifiedChinese;
0
158 }-
159-
160 if (system == QFontDatabase::SimplifiedChinese
system == QFon...plifiedChineseDescription
TRUEnever evaluated
FALSEnever evaluated
0
161 && writingSystems.contains(QFontDatabase::TraditionalChinese)) {
writingSystems...tionalChinese)Description
TRUEnever evaluated
FALSEnever evaluated
0
162 return QFontDatabase::TraditionalChinese;
never executed: return QFontDatabase::TraditionalChinese;
0
163 }-
164-
165 system = writingSystems.lastconstLast();-
166-
167 if (!*hasLatin) {
!*hasLatinDescription
TRUEnever evaluated
FALSEnever evaluated
0
168 // we need to show something-
169 return system;
never executed: return system;
0
170 }-
171-
172 if (writingSystems.count() == 1 && system > QFontDatabase::Cyrillic)
writingSystems.count() == 1Description
TRUEnever evaluated
FALSEnever evaluated
system > QFont...base::CyrillicDescription
TRUEnever evaluated
FALSEnever evaluated
0
173 return system;
never executed: return system;
0
174-
175 if (writingSystems.count() <= 2 && system > QFontDatabase::Armenian && system < QFontDatabase::Vietnamese)
writingSystems.count() <= 2Description
TRUEnever evaluated
FALSEnever evaluated
system > QFont...base::ArmenianDescription
TRUEnever evaluated
FALSEnever evaluated
system < QFont...se::VietnameseDescription
TRUEnever evaluated
FALSEnever evaluated
0
176 return system;
never executed: return system;
0
177-
178 if (writingSystems.count() <= 5 && system >= QFontDatabase::SimplifiedChinese && system <= QFontDatabase::Korean)
writingSystems.count() <= 5Description
TRUEnever evaluated
FALSEnever evaluated
system >= QFon...plifiedChineseDescription
TRUEnever evaluated
FALSEnever evaluated
system <= QFon...tabase::KoreanDescription
TRUEnever evaluated
FALSEnever evaluated
0
179 return system;
never executed: return system;
0
180-
181 return QFontDatabase::Any;
never executed: return QFontDatabase::Any;
0
182}-
183-
184class QFontFamilyDelegate : public QAbstractItemDelegate-
185{-
186 Q_OBJECT-
187public:-
188 explicit QFontFamilyDelegate(QObject *parent);-
189-
190 // painting-
191 void paint(QPainter *painter,-
192 const QStyleOptionViewItem &option,-
193 const QModelIndex &index) const Q_DECL_OVERRIDE;-
194-
195 QSize sizeHint(const QStyleOptionViewItem &option,-
196 const QModelIndex &index) const Q_DECL_OVERRIDE;-
197-
198 const QIcon truetype;-
199 const QIcon bitmap;-
200 QFontDatabase::WritingSystem writingSystem;-
201};-
202-
203QFontFamilyDelegate::QFontFamilyDelegate(QObject *parent)-
204 : QAbstractItemDelegate(parent)-
{),
205 truetype= QIcon(QLatin1StringQStringLiteral(":/qt-project.org/styles/commonstyle/images/fonttruetype-16.png"));)),-
206 bitmap= QIcon(QLatin1StringQStringLiteral(":/qt-project.org/styles/commonstyle/images/fontbitmap-16.png"));)),-
207 writingSystem=(QFontDatabase::Any;)-
208{-
209}
never executed: end of block
0
210-
211void QFontFamilyDelegate::paint(QPainter *painter,-
212 const QStyleOptionViewItem &option,-
213 const QModelIndex &index) const-
214{-
215 QString text = index.data(Qt::DisplayRole).toString();-
216 QFont font(option.font);-
217 font.setPointSize(QFontInfo(font).pointSize() * 3 / 2);-
218 QFont font2 = font;-
219 font2.setFamily(text);-
220-
221 bool hasLatin;-
222 QFontDatabase::WritingSystem system = writingSystemForFont(font2, &hasLatin);-
223 if (hasLatin)-
224 font = font2;-
225-
226 QRect r = option.rect;-
227-
228 if (option.state & QStyle::State_Selected) {-
229 painter->save();-
230 painter->setBrush(option.palette.highlight());-
231 painter->setPen(Qt::NoPen);-
232 painter->drawRect(option.rect);-
233 painter->setPen(QPen(option.palette.highlightedText(), 0));-
234 }-
235-
236 const QIcon *icon = &bitmap;-
237 if (QFontDatabase().isSmoothlyScalable(text)) {-
238 icon = &truetype;-
239 }-
240 QSize actualSize = icon->actualSize(r.size());-
241-
242 icon->paint(painter, r, Qt::AlignLeft|Qt::AlignVCenter);-
243 if (option.direction == Qt::RightToLeft)-
244 r.setRight(r.right() - actualSize.width() - 4);-
245 else-
246 r.setLeft(r.left() + actualSize.width() + 4);-
247-
248 QFont old = painter->font();-
249 painter->setFont(font);-
250-
251 // If the ascent of the font is larger than the height of the rect,-
252 // we will clip the text, so it's better to align the tight bounding rect in this case-
253 // This is specifically for fonts where the ascent is very large compared to-
254 // the descent, like certain of the Stix family.-
255 QFontMetricsF fontMetrics(font);-
256 if (fontMetrics.ascent() > r.height()) {-
257 QRectF tbr = fontMetrics.tightBoundingRect(text);-
258 painter->drawText(r.x(), r.y() + (r.height() + tbr.height()) / 2.0, text);-
259 } else {-
260 painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeading|Qt::TextSingleLine, text);-
261 }-
262-
263 if (writingSystem != QFontDatabase::Any)-
264 system = writingSystem;-
265-
266 if (system != QFontDatabase::Any) {-
267 int w = painter->fontMetrics().width(text + QLatin1String(" "));-
268 painter->setFont(font2);-
269 QString sample = QFontDatabase().writingSystemSample(system);-
270 if (option.direction == Qt::RightToLeft)-
271 r.setRight(r.right() - w);-
272 else-
273 r.setLeft(r.left() + w);-
274 painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeading|Qt::TextSingleLine, sample);-
275 }-
276 painter->setFont(old);-
277-
278 if (option.state & QStyle::State_Selected)-
279 painter->restore();-
280-
281}-
282-
283QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,-
284 const QModelIndex &index) const-
285{-
286 QString text = index.data(Qt::DisplayRole).toString();-
287 QFont font(option.font);-
288// font.setFamily(text);-
289 font.setPointSize(QFontInfo(font).pointSize() * 3/2);-
290 QFontMetrics fontMetrics(font);-
291 return QSize(fontMetrics.width(text), fontMetrics.height());-
292}-
293-
294-
295class QFontComboBoxPrivate : public QComboBoxPrivate-
296{-
297public:-
298 inline QFontComboBoxPrivate() { filters = QFontComboBox::AllFonts; }-
299-
300 QFontComboBox::FontFilters filters;-
301 QFont currentFont;-
302-
303 void _q_updateModel();-
304 void _q_currentChanged(const QString &);-
305-
306 Q_DECLARE_PUBLIC(QFontComboBox)-
307};-
308-
309-
310void QFontComboBoxPrivate::_q_updateModel()-
311{-
312 Q_Q(QFontComboBox);-
313 const int scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);-
314 const int spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);-
315-
316 QStringListModel *m = qobject_cast<QStringListModel *>(q->model());-
317 if (!m)-
318 return;-
319 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(q->view()->itemDelegate());-
320 QFontDatabase::WritingSystem system = delegate ? delegate->writingSystem : QFontDatabase::Any;-
321-
322 QFontDatabase fdb;-
323 QStringList list = fdb.families(system);-
324 QStringList result;-
325-
326 int offset = 0;-
327 QFontInfo fi(currentFont);-
328-
329 for (int i = 0; i < list.size(); ++i) {-
330 if (fdb.isPrivateFamily(list.at(i)))-
331 continue;-
332-
333 if ((filters & scalableMask) && (filters & scalableMask) != scalableMask) {-
334 if (bool(filters & QFontComboBox::ScalableFonts) != fdb.isSmoothlyScalable(list.at(i)))-
335 continue;-
336 }-
337 if ((filters & spacingMask) && (filters & spacingMask) != spacingMask) {-
338 if (bool(filters & QFontComboBox::MonospacedFonts) != fdb.isFixedPitch(list.at(i)))-
339 continue;-
340 }-
341 result += list.at(i);-
342 if (list.at(i) == fi.family() || list.at(i).startsWith(fi.family() + QLatin1String(" [")))-
343 offset = result.count() - 1;-
344 }-
345 list = result;-
346-
347 //we need to block the signals so that the model doesn't emit reset-
348 //this prevents the current index from changing-
349 //it will be updated just after this-
350 ///TODO: we should finda way to avoid blocking signals and have a real update of the model-
351 {-
352 const QSignalBlocker blocker(m);-
353 m->setStringList(list);-
354 }-
355-
356 if (list.isEmpty()) {-
357 if (currentFont != QFont()) {-
358 currentFont = QFont();-
359 emit q->currentFontChanged(currentFont);-
360 }-
361 } else {-
362 q->setCurrentIndex(offset);-
363 }-
364}-
365-
366-
367void QFontComboBoxPrivate::_q_currentChanged(const QString &text)-
368{-
369 Q_Q(QFontComboBox);-
370 if (currentFont.family() != text) {-
371 currentFont.setFamily(text);-
372 emit q->currentFontChanged(currentFont);-
373 }-
374}-
375-
376/*!-
377 \class QFontComboBox-
378 \brief The QFontComboBox widget is a combobox that lets the user-
379 select a font family.-
380-
381 \since 4.2-
382 \ingroup basicwidgets-
383 \inmodule QtWidgets-
384-
385 The combobox is populated with an alphabetized list of font-
386 family names, such as Arial, Helvetica, and Times New Roman.-
387 Family names are displayed using the actual font when possible.-
388 For fonts such as Symbol, where the name is not representable in-
389 the font itself, a sample of the font is displayed next to the-
390 family name.-
391-
392 QFontComboBox is often used in toolbars, in conjunction with a-
393 QComboBox for controlling the font size and two \l{QToolButton}s-
394 for bold and italic.-
395-
396 When the user selects a new font, the currentFontChanged() signal-
397 is emitted in addition to currentIndexChanged().-
398-
399 Call setWritingSystem() to tell QFontComboBox to show only fonts-
400 that support a given writing system, and setFontFilters() to-
401 filter out certain types of fonts as e.g. non scalable fonts or-
402 monospaced fonts.-
403-
404 \image windowsvista-fontcombobox.png Screenshot of QFontComboBox on Windows Vista-
405-
406 \sa QComboBox, QFont, QFontInfo, QFontMetrics, QFontDatabase, {Character Map Example}-
407*/-
408-
409/*!-
410 Constructs a font combobox with the given \a parent.-
411*/-
412QFontComboBox::QFontComboBox(QWidget *parent)-
413 : QComboBox(*new QFontComboBoxPrivate, parent)-
414{-
415 Q_D(QFontComboBox);-
416 d->currentFont = font();-
417 setEditable(true);-
418-
419 QStringListModel *m = new QStringListModel(this);-
420 setModel(m);-
421 setItemDelegate(new QFontFamilyDelegate(this));-
422 QListView *lview = qobject_cast<QListView*>(view());-
423 if (lview)-
424 lview->setUniformItemSizes(true);-
425 setWritingSystem(QFontDatabase::Any);-
426-
427 connect(this, SIGNAL(currentIndexChanged(QString)),-
428 this, SLOT(_q_currentChanged(QString)));-
429-
430 connect(qApp, SIGNAL(fontDatabaseChanged()),-
431 this, SLOT(_q_updateModel()));-
432}-
433-
434-
435/*!-
436 Destroys the combobox.-
437*/-
438QFontComboBox::~QFontComboBox()-
439{-
440}-
441-
442/*!-
443 \property QFontComboBox::writingSystem-
444 \brief the writing system that serves as a filter for the combobox-
445-
446 If \a script is QFontDatabase::Any (the default), all fonts are-
447 listed.-
448-
449 \sa fontFilters-
450*/-
451-
452void QFontComboBox::setWritingSystem(QFontDatabase::WritingSystem script)-
453{-
454 Q_D(QFontComboBox);-
455 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(view()->itemDelegate());-
456 if (delegate)-
457 delegate->writingSystem = script;-
458 d->_q_updateModel();-
459}-
460-
461QFontDatabase::WritingSystem QFontComboBox::writingSystem() const-
462{-
463 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(view()->itemDelegate());-
464 if (delegate)-
465 return delegate->writingSystem;-
466 return QFontDatabase::Any;-
467}-
468-
469-
470/*!-
471 \enum QFontComboBox::FontFilter-
472-
473 This enum can be used to only show certain types of fonts in the font combo box.-
474-
475 \value AllFonts Show all fonts-
476 \value ScalableFonts Show scalable fonts-
477 \value NonScalableFonts Show non scalable fonts-
478 \value MonospacedFonts Show monospaced fonts-
479 \value ProportionalFonts Show proportional fonts-
480*/-
481-
482/*!-
483 \property QFontComboBox::fontFilters-
484 \brief the filter for the combobox-
485-
486 By default, all fonts are listed.-
487-
488 \sa writingSystem-
489*/-
490void QFontComboBox::setFontFilters(FontFilters filters)-
491{-
492 Q_D(QFontComboBox);-
493 d->filters = filters;-
494 d->_q_updateModel();-
495}-
496-
497QFontComboBox::FontFilters QFontComboBox::fontFilters() const-
498{-
499 Q_D(const QFontComboBox);-
500 return d->filters;-
501}-
502-
503/*!-
504 \property QFontComboBox::currentFont-
505 \brief the currently selected font-
506-
507 \sa currentIndex, currentText-
508*/-
509QFont QFontComboBox::currentFont() const-
510{-
511 Q_D(const QFontComboBox);-
512 return d->currentFont;-
513}-
514-
515void QFontComboBox::setCurrentFont(const QFont &font)-
516{-
517 Q_D(QFontComboBox);-
518 if (font != d->currentFont) {-
519 d->currentFont = font;-
520 d->_q_updateModel();-
521 if (d->currentFont == font) { //else the signal has already be emitted by _q_updateModel-
522 emit currentFontChanged(d->currentFont);-
523 }-
524 }-
525}-
526-
527/*!-
528 \fn QFontComboBox::currentFontChanged(const QFont &font)-
529-
530 This signal is emitted whenever the current font changes, with-
531 the new \a font.-
532-
533 \sa currentFont-
534*/-
535-
536/*!-
537 \reimp-
538*/-
539bool QFontComboBox::event(QEvent *e)-
540{-
541 if (e->type() == QEvent::Resize) {-
542 QListView *lview = qobject_cast<QListView*>(view());-
543 if (lview) {-
544 lview->window()->setFixedWidth(qMin(width() * 5 / 3,-
545 QApplication::desktop()->availableGeometry(lview).width()));-
546 }-
547 }-
548 return QComboBox::event(e);-
549}-
550-
551/*!-
552 \reimp-
553*/-
554QSize QFontComboBox::sizeHint() const-
555{-
556 QSize sz = QComboBox::sizeHint();-
557 QFontMetrics fm(font());-
558 sz.setWidth(fm.width(QLatin1Char('m'))*14);-
559 return sz;-
560}-
561-
562QT_END_NAMESPACE-
563-
564#include "qfontcombobox.moc"-
565#include "moc_qfontcombobox.cpp"-
566-
567#endif // QT_NO_FONTCOMBOBOX-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9