Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfontcombobox.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfontcombobox.h"
5
7#include <qaccessible.h>
8#include <qstringlistmodel.h>
9#include <qlistview.h>
10#include <qpainter.h>
11#include <qevent.h>
12#include <qapplication.h>
13#include <private/qcombobox_p.h>
14#include <qdebug.h>
15
16#include <array>
17
19
20using namespace Qt::StringLiterals;
21
23{
24 switch (script) {
60 return QFontDatabase::Lao;
86 return QFontDatabase::Nko;
87 default:
88 return QFontDatabase::Any;
89 }
90}
91
93{
94 QStringList uiLanguages = QLocale::system().uiLanguages();
95 QLocale::Script script;
96 if (!uiLanguages.isEmpty())
97 script = QLocale(uiLanguages.at(0)).script();
98 else
99 script = QLocale::system().script();
100
101 return writingSystemFromScript(script);
102}
103
105{
106 QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase::writingSystems(font.families().constFirst());
107// qDebug() << font.families().first() << writingSystems;
108
109 // this just confuses the algorithm below. Vietnamese is Latin with lots of special chars
110 writingSystems.removeOne(QFontDatabase::Vietnamese);
111 *hasLatin = writingSystems.removeOne(QFontDatabase::Latin);
112
113 if (writingSystems.isEmpty())
114 return QFontDatabase::Any;
115
117
118 if (writingSystems.contains(system))
119 return system;
120
122 && writingSystems.contains(QFontDatabase::SimplifiedChinese)) {
124 }
125
127 && writingSystems.contains(QFontDatabase::TraditionalChinese)) {
129 }
130
131 system = writingSystems.constLast();
132
133 if (!*hasLatin) {
134 // we need to show something
135 return system;
136 }
137
138 if (writingSystems.size() == 1 && system > QFontDatabase::Cyrillic)
139 return system;
140
141 if (writingSystems.size() <= 2 && system > QFontDatabase::Armenian && system < QFontDatabase::Vietnamese)
142 return system;
143
144 if (writingSystems.size() <= 5 && system >= QFontDatabase::SimplifiedChinese && system <= QFontDatabase::Korean)
145 return system;
146
147 return QFontDatabase::Any;
148}
149
151{
152public:
153 QFontComboBox::FontFilters filters = QFontComboBox::AllFonts;
155 QHash<QFontDatabase::WritingSystem, QString> sampleTextForWritingSystem;
156 QHash<QString, QString> sampleTextForFontFamily;
157 QHash<QString, QFont> displayFontForFontFamily;
158 std::array<QMetaObject::Connection, 2> connections;
159
160 void updateModel();
161 void currentChanged(const QString &);
162
163 Q_DECLARE_PUBLIC(QFontComboBox)
164};
165
167{
169public:
171
172 // painting
173 void paint(QPainter *painter,
174 const QStyleOptionViewItem &option,
175 const QModelIndex &index) const override;
176
177 QSize sizeHint(const QStyleOptionViewItem &option,
178 const QModelIndex &index) const override;
179
184};
185
187 : QAbstractItemDelegate(parent),
188 truetype(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fonttruetype-16.png")),
189 bitmap(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fontbitmap-16.png")),
190 writingSystem(QFontDatabase::Any),
191 comboPrivate(comboP)
192{
193}
194
196 const QStyleOptionViewItem &option,
197 const QModelIndex &index) const
198{
199 QString text = index.data(Qt::DisplayRole).toString();
200 QFont font(option.font);
201 font.setPointSize(QFontInfo(font).pointSize() * 3 / 2);
202 QFont font2 = font;
204
205 bool hasLatin;
206 QFontDatabase::WritingSystem system = writingSystemForFont(font2, &hasLatin);
207 if (hasLatin)
208 font = font2;
209
211
212 QRect r = option.rect;
213
214 if (option.state & QStyle::State_Selected) {
215 painter->save();
216 painter->setBrush(option.palette.highlight());
218 painter->drawRect(option.rect);
219 painter->setPen(QPen(option.palette.highlightedText(), 0));
220 }
221
222 const QIcon *icon = &bitmap;
224 icon = &truetype;
225 }
226 const QSize actualSize = icon->actualSize(r.size());
227 const QRect iconRect = QStyle::alignedRect(option.direction, option.displayAlignment,
228 actualSize, r);
230 if (option.direction == Qt::RightToLeft)
231 r.setRight(r.right() - actualSize.width() - 4);
232 else
233 r.setLeft(r.left() + actualSize.width() + 4);
234
235 QFont old = painter->font();
237
238 const Qt::Alignment textAlign = QStyle::visualAlignment(option.direction, option.displayAlignment);
239 // If the ascent of the font is larger than the height of the rect,
240 // we will clip the text, so it's better to align the tight bounding rect in this case
241 // This is specifically for fonts where the ascent is very large compared to
242 // the descent, like certain of the Stix family.
244 if (fontMetrics.ascent() > r.height()) {
245 QRectF tbr = fontMetrics.tightBoundingRect(text);
247 textRect.setHeight(textRect.height() + (r.height() - tbr.height()));
249 } else {
251 }
252
254 system = writingSystem;
255
257 if (system != QFontDatabase::Any || !sampleText.isEmpty()) {
258 int w = painter->fontMetrics().horizontalAdvance(text + " "_L1);
259 painter->setFont(font2);
260 const QString sample = !sampleText.isEmpty() ? sampleText : QFontDatabase::writingSystemSample(system);
261 if (option.direction == Qt::RightToLeft)
262 r.setRight(r.right() - w);
263 else
264 r.setLeft(r.left() + w);
266 }
267 painter->setFont(old);
268
269 if (option.state & QStyle::State_Selected)
270 painter->restore();
271
272}
273
274QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,
275 const QModelIndex &index) const
276{
277 QString text = index.data(Qt::DisplayRole).toString();
278 QFont font(option.font);
279// font.setFamilies(QStringList{text});
280 font.setPointSize(QFontInfo(font).pointSize() * 3/2);
282 return QSize(fontMetrics.horizontalAdvance(text), fontMetrics.height());
283}
284
285
287{
288 Q_Q(QFontComboBox);
289
291 return;
292
295
296 QStringListModel *m = qobject_cast<QStringListModel *>(q->model());
297 if (!m)
298 return;
299 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(q->view()->itemDelegate());
300 QFontDatabase::WritingSystem system = delegate ? delegate->writingSystem : QFontDatabase::Any;
301
304
305 int offset = 0;
307
308 for (const auto &family : list) {
310 continue;
311
312 if ((filters & scalableMask) && (filters & scalableMask) != scalableMask) {
314 continue;
315 }
316 if ((filters & spacingMask) && (filters & spacingMask) != spacingMask) {
318 continue;
319 }
320 result += family;
321 if (family == fi.family() || family.startsWith(fi.family() + " ["_L1))
322 offset = result.size() - 1;
323 }
324
325 //we need to block the signals so that the model doesn't emit reset
326 //this prevents the current index from changing
327 //it will be updated just after this
329 {
330 const QSignalBlocker blocker(m);
331 m->setStringList(result);
332 // Since the modelReset signal is blocked the view will not emit an accessibility event
333 #if QT_CONFIG(accessibility)
334 if (QAccessible::isActive()) {
335 QAccessibleTableModelChangeEvent accessibleEvent(q->view(), QAccessibleTableModelChangeEvent::ModelReset);
336 QAccessible::updateAccessibility(&accessibleEvent);
337 }
338 #endif
339 }
340
341 if (result.isEmpty()) {
342 if (currentFont != QFont()) {
343 currentFont = QFont();
344 emit q->currentFontChanged(currentFont);
345 }
346 } else {
347 q->setCurrentIndex(offset);
348 }
349}
350
351
353{
354 Q_Q(QFontComboBox);
355 const QStringList families = currentFont.families();
356 if (families.isEmpty() || families.first() != text) {
358 emit q->currentFontChanged(currentFont);
359 }
360}
361
399 : QComboBox(*new QFontComboBoxPrivate, parent)
400{
401 Q_D(QFontComboBox);
402 d->currentFont = font();
403 setEditable(true);
404
406 setModel(m);
408 QListView *lview = qobject_cast<QListView*>(view());
409 if (lview)
410 lview->setUniformItemSizes(true);
412
413 d->connections = {
418 };
419}
420
421
426{
427 Q_D(const QFontComboBox);
428 for (const QMetaObject::Connection &connection : d->connections)
430}
431
443{
444 Q_D(QFontComboBox);
445 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(view()->itemDelegate());
446 if (delegate)
447 delegate->writingSystem = script;
448 d->updateModel();
449}
450
452{
453 QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(view()->itemDelegate());
454 if (delegate)
455 return delegate->writingSystem;
456 return QFontDatabase::Any;
457}
458
459
481{
482 Q_D(QFontComboBox);
483 d->filters = filters;
484 d->updateModel();
485}
486
487QFontComboBox::FontFilters QFontComboBox::fontFilters() const
488{
489 Q_D(const QFontComboBox);
490 return d->filters;
491}
492
500{
501 Q_D(const QFontComboBox);
502 return d->currentFont;
503}
504
506{
507 Q_D(QFontComboBox);
508 if (font != d->currentFont) {
509 d->currentFont = font;
510 d->updateModel();
511 if (d->currentFont == font) { //else the signal has already be emitted by updateModel
512 emit currentFontChanged(d->currentFont);
513 }
514 }
515}
516
530{
531 if (e->type() == QEvent::Resize) {
532 QListView *lview = qobject_cast<QListView*>(view());
533 if (lview) {
534 lview->window()->setFixedWidth(qMin(width() * 5 / 3,
536 }
537 }
538 return QComboBox::event(e);
539}
540
545{
547 QFontMetrics fm(font());
548 sz.setWidth(fm.horizontalAdvance(u'm') * 14);
549 return sz;
550}
551
560{
561 Q_D(QFontComboBox);
562 d->sampleTextForWritingSystem[writingSystem] = sampleText;
563}
564
565
572{
573 Q_D(const QFontComboBox);
574 return d->sampleTextForWritingSystem.value(writingSystem);
575}
576
584void QFontComboBox::setSampleTextForFont(const QString &fontFamily, const QString &sampleText)
585{
586 Q_D(QFontComboBox);
587 d->sampleTextForFontFamily[fontFamily] = sampleText;
588}
589
596{
597 Q_D(const QFontComboBox);
598 return d->sampleTextForFontFamily.value(fontFamily);
599}
600
606void QFontComboBox::setDisplayFont(const QString &fontFamily, const QFont &font)
607{
608 Q_D(QFontComboBox);
609 d->displayFontForFontFamily[fontFamily] = font;
610}
611
617std::optional<QFont> QFontComboBox::displayFont(const QString &fontFamily) const
618{
619 Q_D(const QFontComboBox);
620 return d->displayFontForFontFamily.value(fontFamily, {});
621}
622
624
625#include "qfontcombobox.moc"
626#include "moc_qfontcombobox.cpp"
The QAbstractItemDelegate class is used to display and edit data items from a model.
The QComboBox widget combines a button with a dropdown list.
Definition qcombobox.h:24
QAbstractItemView * view() const
Returns the list view used for the combobox popup.
void setItemDelegate(QAbstractItemDelegate *delegate)
Sets the item delegate for the popup list view.
bool event(QEvent *event) override
\reimp
void currentTextChanged(const QString &)
QAbstractItemDelegate * itemDelegate() const
Returns the item delegate used by the popup list view.
virtual void setModel(QAbstractItemModel *model)
Sets the model to be model.
QSize sizeHint() const override
\reimp
void setEditable(bool editable)
static bool closingDown()
Returns true if the application objects are being destroyed; otherwise returns false.
\inmodule QtCore
Definition qcoreevent.h:45
Type type() const
Returns the event type.
Definition qcoreevent.h:304
QHash< QString, QFont > displayFontForFontFamily
void currentChanged(const QString &)
QFontComboBox::FontFilters filters
QHash< QString, QString > sampleTextForFontFamily
QHash< QFontDatabase::WritingSystem, QString > sampleTextForWritingSystem
std::array< QMetaObject::Connection, 2 > connections
The QFontComboBox widget is a combobox that lets the user select a font family.
void setDisplayFont(const QString &fontFamily, const QFont &font)
Sets the font to be used to display a given fontFamily (when the combo is open).
QFontComboBox(QWidget *parent=nullptr)
Constructs a font combobox with the given parent.
QFont currentFont
the currently selected font
bool event(QEvent *e) override
\reimp
QSize sizeHint() const override
\reimp
~QFontComboBox()
Destroys the combobox.
QString sampleTextForSystem(QFontDatabase::WritingSystem writingSystem) const
Returns the sample text to show after the font name (when the combo is open) for a given writingSyste...
QString sampleTextForFont(const QString &fontFamily) const
Returns the sample text to show after the font name (when the combo is open) for a given fontFamily.
std::optional< QFont > displayFont(const QString &fontFamily) const
Returns the font (if set) to be used to display a given fontFamily (when the combo is open).
void setFontFilters(FontFilters filters)
void currentFontChanged(const QFont &f)
This signal is emitted whenever the current font changes, with the new font.
void setSampleTextForSystem(QFontDatabase::WritingSystem writingSystem, const QString &sampleText)
Sets the sampleText to show after the font name (when the combo is open) for a given writingSystem.
void setWritingSystem(QFontDatabase::WritingSystem)
QFontDatabase::WritingSystem writingSystem
the writing system that serves as a filter for the combobox
FontFilters fontFilters
the filter for the combobox
void setCurrentFont(const QFont &f)
void setSampleTextForFont(const QString &fontFamily, const QString &sampleText)
Sets the sampleText to show after the font name (when the combo is open) for a given fontFamily.
\threadsafe \inmodule QtGui
WritingSystem
\value Any \value Latin \value Greek \value Cyrillic \value Armenian \value Hebrew \value Arabic \val...
static bool isSmoothlyScalable(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is smoothly scalable; otherwise retur...
static bool isPrivateFamily(const QString &family)
static QString writingSystemSample(WritingSystem writingSystem)
Returns a string with sample characters from writingSystem.
static QStringList families(WritingSystem writingSystem=Any)
Returns a sorted list of the available font families which support the writingSystem.
static QList< WritingSystem > writingSystems()
Returns a sorted list of the available writing systems.
static bool isFixedPitch(const QString &family, const QString &style=QString())
Returns true if the font that has family family and style style is fixed pitch; otherwise returns fal...
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
QFontComboBoxPrivate * comboPrivate
QFontFamilyDelegate(QObject *parent, QFontComboBoxPrivate *comboP)
QFontDatabase::WritingSystem writingSystem
\reentrant
Definition qfontinfo.h:16
\reentrant \inmodule QtGui
\reentrant \inmodule QtGui
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
\reentrant
Definition qfont.h:22
void setPointSize(int)
Sets the point size to pointSize.
Definition qfont.cpp:985
void setFamilies(const QStringList &)
Definition qfont.cpp:2721
QStringList families() const
Definition qfont.cpp:2699
void fontDatabaseChanged()
This signal is emitted when the available fonts have changed.
T value(const Key &key) const noexcept
Definition qhash.h:1054
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment=Qt::AlignCenter, Mode mode=Normal, State state=Off) const
Uses the painter to paint the icon with specified alignment, required mode, and state into the rectan...
Definition qicon.cpp:977
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
Definition qicon.cpp:926
The QListView class provides a list or icon view onto a model.
Definition qlistview.h:17
@ JapaneseScript
Definition qlocale.h:466
@ OghamScript
Definition qlocale.h:505
@ OriyaScript
Definition qlocale.h:559
@ TibetanScript
Definition qlocale.h:547
@ GurmukhiScript
Definition qlocale.h:454
@ ThaiScript
Definition qlocale.h:546
@ SimplifiedHanScript
Definition qlocale.h:531
@ LaoScript
Definition qlocale.h:478
@ GujaratiScript
Definition qlocale.h:453
@ KoreanScript
Definition qlocale.h:476
@ NkoScript
Definition qlocale.h:503
@ GreekScript
Definition qlocale.h:452
@ KhmerScript
Definition qlocale.h:473
@ MalayalamScript
Definition qlocale.h:487
@ RunicScript
Definition qlocale.h:524
@ ThaanaScript
Definition qlocale.h:545
@ CyrillicScript
Definition qlocale.h:440
@ TamilScript
Definition qlocale.h:542
@ TeluguScript
Definition qlocale.h:544
@ ArmenianScript
Definition qlocale.h:418
@ SinhalaScript
Definition qlocale.h:532
@ HebrewScript
Definition qlocale.h:460
@ TraditionalHanScript
Definition qlocale.h:550
@ DevanagariScript
Definition qlocale.h:442
@ BengaliScript
Definition qlocale.h:557
@ SyriacScript
Definition qlocale.h:536
@ MyanmarScript
Definition qlocale.h:499
@ KannadaScript
Definition qlocale.h:469
@ GeorgianScript
Definition qlocale.h:448
@ LatinScript
Definition qlocale.h:479
@ ArabicScript
Definition qlocale.h:417
Script script() const
Definition qlocale.cpp:1329
static QLocale system()
Returns a QLocale object initialized to the system locale.
Definition qlocale.cpp:2862
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
\inmodule QtCore
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition qpainter.h:519
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const QFont & font() const
Returns the currently set font used for drawing text.
void restore()
Restores the current painter state (pops a saved state off the stack).
QFontMetrics fontMetrics() const
Returns the font metrics for the painter if the painter is active.
void save()
Saves the current painter state (pushes the state onto a stack).
void setFont(const QFont &f)
Sets the painter's font to the given font.
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position.
void setBrush(const QBrush &brush)
Sets the painter's brush to the given brush.
\inmodule QtGui
Definition qpen.h:28
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:384
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:483
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
@ State_Selected
Definition qstyle.h:82
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
Transforms an alignment of Qt::AlignLeft or Qt::AlignRight without Qt::AlignAbsolute into Qt::AlignLe...
Definition qstyle.cpp:2202
static QRect alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle)
Returns a new rectangle of the specified size that is aligned to the given rectangle according to the...
Definition qstyle.cpp:2173
static QRect availableScreenGeometry(const QWidget *widget)
Definition qwidget_p.h:474
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
QFont font
the font currently set for the widget
Definition qwidget.h:133
QPainter paint
QString text
fontMetrics
QRect textRect
Combined button and popup list for selecting options.
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignLeft
Definition qnamespace.h:144
@ RightToLeft
@ TextSingleLine
Definition qnamespace.h:170
@ NoPen
@ DisplayRole
#define qApp
DBusConnection * connection
static QFontDatabase::WritingSystem writingSystemFromLocale()
static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script)
static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLuint index
[2]
GLboolean r
[2]
GLenum GLuint GLintptr offset
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLuint GLenum option
#define QStringLiteral(str)
#define Q_OBJECT
#define emit
QList< int > list
[14]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
QPainter painter(this)
[7]