Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfontdialog.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// Qt-Security score:significant reason:default
4
5#include "qwindowdefs.h"
6#include "qfontdialog.h"
7
9
10#include <qapplication.h>
11#include <qcheckbox.h>
12#include <qcombobox.h>
13#include <qevent.h>
14#include <qgroupbox.h>
15#include <qlabel.h>
16#include <qlayout.h>
17#include <qlineedit.h>
18#include <qpushbutton.h>
19#include <qstyle.h>
20#include <qdialogbuttonbox.h>
21#include <qheaderview.h>
22#include <qlistview.h>
23#include <qstringlistmodel.h>
24#include <qvalidator.h>
25#include <private/qfontdatabase_p.h>
26#include <private/qdialog_p.h>
27#include <private/qfont_p.h>
28
30
31using namespace Qt::StringLiterals;
32
34{
36public:
38 inline QStringListModel *model() const {
39 return static_cast<QStringListModel *>(QListView::model());
40 }
41 inline void setCurrentItem(int item) {
42 QListView::setCurrentIndex(static_cast<QAbstractListModel*>(model())->index(item));
43 }
44 inline int currentItem() const {
45 return QListView::currentIndex().row();
46 }
47 inline int count() const {
48 return model()->rowCount();
49 }
50 inline QString currentText() const {
51 int row = QListView::currentIndex().row();
52 return row < 0 ? QString() : model()->stringList().at(row);
53 }
54 void currentChanged(const QModelIndex &current, const QModelIndex &previous) override {
55 QListView::currentChanged(current, previous);
56 if (current.isValid())
57 emit highlighted(current.row());
58 }
59 QString text(int i) const {
60 return model()->stringList().at(i);
61 }
63 void highlighted(int);
64};
65
66QFontListView::QFontListView(QWidget *parent)
67 : QListView(parent)
68{
69 setModel(new QStringListModel(parent));
70 setEditTriggers(NoEditTriggers);
71}
72
74 Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
75
76QFontDialogPrivate::QFontDialogPrivate()
77 : writingSystem(QFontDatabase::Any),
78 options(QFontDialogOptions::create())
79{
80}
81
82QFontDialogPrivate::~QFontDialogPrivate()
83{
84}
85
86/*!
87 \class QFontDialog
88 \ingroup standard-dialogs
89 \inmodule QtWidgets
90
91 \brief The QFontDialog class provides a dialog widget for selecting a font.
92
93 A font dialog is created through one of the static getFont()
94 functions.
95
96 Examples:
97
98 \snippet code/src_gui_dialogs_qfontdialog.cpp 0
99
100 The dialog can also be used to set a widget's font directly:
101 \snippet code/src_gui_dialogs_qfontdialog.cpp 1
102 If the user clicks OK the font they chose will be used for myWidget,
103 and if they click Cancel the original font is used.
104
105 \image fusion-fontdialog.png A font dialog in the Fusion widget style.
106
107 \sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog,
108 {Standard Dialogs Example}
109*/
110
111/*
112 Internal event filter used to adjust dialog options during widget polish.
113
114 Enables DontUseNativeDialog automatically when QFontDialog is subclassed
115 and no explicit options were set by the user.
116*/
117
119{
120public:
121 explicit QFontPolishFilter(QFontDialog *fd) : QObject(fd)
122 {
123 fd->installEventFilter(this);
124 }
125
126 bool eventFilter(QObject *obj, QEvent *event) override
127 {
128 if (event->type() == QEvent::Polish ) {
129 Q_ASSERT(qobject_cast<QFontDialog *>(obj));
130 auto *fd = static_cast<QFontDialog *>(obj);
131 auto *d = static_cast<QFontDialogPrivate *>(QObjectPrivate::get(fd));
132
133 if (fd->metaObject() != &QFontDialog::staticMetaObject && !d->optionsExplicitlySet)
134 fd->setOption(QFontDialog::DontUseNativeDialog);
135
136 deleteLater(); // no longer needed after first polish
137 }
138 return false;
139 }
140};
141
142/*!
143 Constructs a standard font dialog.
144
145 Use setCurrentFont() to set the initial font attributes.
146
147 The \a parent parameter is passed to the QDialog constructor.
148
149 \sa getFont()
150*/
151QFontDialog::QFontDialog(QWidget *parent)
152 : QDialog(*new QFontDialogPrivate, parent, qfd_DefaultWindowFlags)
153{
154 Q_D(QFontDialog);
155 new QFontPolishFilter(this);
156 d->init();
157}
158
159/*!
160 Constructs a standard font dialog with the given \a parent and specified
161 \a initial font.
162*/
163QFontDialog::QFontDialog(const QFont &initial, QWidget *parent)
164 : QFontDialog(parent)
165{
166 setCurrentFont(initial);
167 new QFontPolishFilter(this);
168}
169
170void QFontDialogPrivate::init()
171{
172 Q_Q(QFontDialog);
173
174 q->setSizeGripEnabled(true);
175 q->setWindowTitle(QFontDialog::tr("Select Font"));
176
177 // grid
178 familyEdit = new QLineEdit(q);
179 familyEdit->setReadOnly(true);
180 familyList = new QFontListView(q);
181 familyEdit->setFocusProxy(familyList);
182
183 familyAccel = new QLabel(q);
184#ifndef QT_NO_SHORTCUT
185 familyAccel->setBuddy(familyList);
186#endif
187 familyAccel->setIndent(2);
188
189 styleEdit = new QLineEdit(q);
190 styleEdit->setReadOnly(true);
191 styleList = new QFontListView(q);
192 styleEdit->setFocusProxy(styleList);
193
194 styleAccel = new QLabel(q);
195#ifndef QT_NO_SHORTCUT
196 styleAccel->setBuddy(styleList);
197#endif
198 styleAccel->setIndent(2);
199
200 sizeEdit = new QLineEdit(q);
201 sizeEdit->setFocusPolicy(Qt::ClickFocus);
202 QIntValidator *validator = new QIntValidator(1, 512, q);
203 sizeEdit->setValidator(validator);
204 sizeList = new QFontListView(q);
205
206 sizeAccel = new QLabel(q);
207#ifndef QT_NO_SHORTCUT
208 sizeAccel->setBuddy(sizeList);
209#endif
210 sizeAccel->setIndent(2);
211
212 // effects box
213 effects = new QGroupBox(q);
214 QVBoxLayout *vbox = new QVBoxLayout(effects);
215 strikeout = new QCheckBox(effects);
216 vbox->addWidget(strikeout);
217 underline = new QCheckBox(effects);
218 vbox->addWidget(underline);
219
220 sample = new QGroupBox(q);
221 QHBoxLayout *hbox = new QHBoxLayout(sample);
222 sampleEdit = new QLineEdit(sample);
223 sampleEdit->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
224 sampleEdit->setAlignment(Qt::AlignCenter);
225 // Note that the sample text is *not* translated with tr(), as the
226 // characters used depend on the charset encoding.
227 sampleEdit->setText("AaBbYyZz"_L1);
228 hbox->addWidget(sampleEdit);
229
230 writingSystemCombo = new QComboBox(q);
231
232 writingSystemAccel = new QLabel(q);
233#ifndef QT_NO_SHORTCUT
234 writingSystemAccel->setBuddy(writingSystemCombo);
235#endif
236 writingSystemAccel->setIndent(2);
237
238 size = 0;
239 smoothScalable = false;
240
241 QObjectPrivate::connect(writingSystemCombo, &QComboBox::activated,
242 this, &QFontDialogPrivate::writingSystemHighlighted);
243 QObjectPrivate::connect(familyList, &QFontListView::highlighted,
244 this, &QFontDialogPrivate::familyHighlighted);
245 QObjectPrivate::connect(styleList, &QFontListView::highlighted,
246 this, &QFontDialogPrivate::styleHighlighted);
247 QObjectPrivate::connect(sizeList, &QFontListView::highlighted,
248 this, &QFontDialogPrivate::sizeHighlighted);
249 QObjectPrivate::connect(sizeEdit, &QLineEdit::textChanged,
250 this, &QFontDialogPrivate::sizeChanged);
251
252 QObjectPrivate::connect(strikeout, &QCheckBox::clicked,
253 this, &QFontDialogPrivate::updateSample);
254 QObjectPrivate::connect(underline, &QCheckBox::clicked, this,
255 &QFontDialogPrivate::updateSample);
256
257 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
258 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
259 QString writingSystemName = QFontDatabase::writingSystemName(ws);
260 if (writingSystemName.isEmpty())
261 break;
262 writingSystemCombo->addItem(writingSystemName);
263 }
264
265 updateFamilies();
266 if (familyList->count() != 0) {
267 familyList->setCurrentItem(0);
268 sizeList->setCurrentItem(0);
269 }
270
271 // grid layout
272 QGridLayout *mainGrid = new QGridLayout(q);
273
274 int spacing = mainGrid->spacing();
275 if (spacing >= 0) { // uniform spacing
276 mainGrid->setSpacing(0);
277
278 mainGrid->setColumnMinimumWidth(1, spacing);
279 mainGrid->setColumnMinimumWidth(3, spacing);
280
281 int margin = 0;
282 mainGrid->getContentsMargins(nullptr, nullptr, nullptr, &margin);
283
284 mainGrid->setRowMinimumHeight(3, margin);
285 mainGrid->setRowMinimumHeight(6, 2);
286 mainGrid->setRowMinimumHeight(8, margin);
287 }
288
289 mainGrid->addWidget(familyAccel, 0, 0);
290 mainGrid->addWidget(familyEdit, 1, 0);
291 mainGrid->addWidget(familyList, 2, 0);
292
293 mainGrid->addWidget(styleAccel, 0, 2);
294 mainGrid->addWidget(styleEdit, 1, 2);
295 mainGrid->addWidget(styleList, 2, 2);
296
297 mainGrid->addWidget(sizeAccel, 0, 4);
298 mainGrid->addWidget(sizeEdit, 1, 4);
299 mainGrid->addWidget(sizeList, 2, 4);
300
301 mainGrid->setColumnStretch(0, 38);
302 mainGrid->setColumnStretch(2, 24);
303 mainGrid->setColumnStretch(4, 10);
304
305 mainGrid->addWidget(effects, 4, 0);
306
307 mainGrid->addWidget(sample, 4, 2, 4, 3);
308
309 mainGrid->addWidget(writingSystemAccel, 5, 0);
310 mainGrid->addWidget(writingSystemCombo, 7, 0);
311
312 buttonBox = new QDialogButtonBox(q);
313 mainGrid->addWidget(buttonBox, 9, 0, 1, 5);
314
315 QPushButton *button
316 = static_cast<QPushButton *>(buttonBox->addButton(QDialogButtonBox::Ok));
317 QObject::connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);
318 button->setDefault(true);
319
320 buttonBox->addButton(QDialogButtonBox::Cancel);
321 QObject::connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
322
323 q->resize(500, 360);
324
325 sizeEdit->installEventFilter(q);
326 familyList->installEventFilter(q);
327 styleList->installEventFilter(q);
328 sizeList->installEventFilter(q);
329
330 familyList->setFocus();
331 retranslateStrings();
332 sampleEdit->setObjectName("qt_fontDialog_sampleEdit"_L1);
333}
334
335/*!
336 \internal
337 Destroys the font dialog and frees up its storage.
338*/
339
340QFontDialog::~QFontDialog()
341{
342}
343
344/*!
345 Executes a modal font dialog and returns a font.
346
347 If the user clicks \uicontrol OK, the selected font is returned. If the user
348 clicks \uicontrol Cancel, the \a initial font is returned.
349
350 The dialog is constructed with the given \a parent and the options specified
351 in \a options. \a title is shown as the window title of the dialog and \a
352 initial is the initially selected font. If the \a ok parameter is not-null,
353 the value it refers to is set to true if the user clicks \uicontrol OK, and set to
354 false if the user clicks \uicontrol Cancel.
355
356 Examples:
357 \snippet code/src_gui_dialogs_qfontdialog.cpp 2
358
359 The dialog can also be used to set a widget's font directly:
360 \snippet code/src_gui_dialogs_qfontdialog.cpp 3
361 In this example, if the user clicks OK the font they chose will be
362 used, and if they click Cancel the original font is used.
363*/
364QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title,
365 FontDialogOptions options)
366{
367 return QFontDialogPrivate::getFont(ok, initial, parent, title, options);
368}
369
370/*!
371 \overload
372
373 Executes a modal font dialog and returns a font.
374
375 If the user clicks \uicontrol OK, the selected font is returned. If the user
376 clicks \uicontrol Cancel, the Qt default font is returned.
377
378 The dialog is constructed with the given \a parent.
379 If the \a ok parameter is not-null, the value it refers to is set
380 to true if the user clicks \uicontrol OK, and false if the user clicks
381 \uicontrol Cancel.
382
383 Example:
384 \snippet code/src_gui_dialogs_qfontdialog.cpp 4
385*/
386QFont QFontDialog::getFont(bool *ok, QWidget *parent)
387{
388 QFont initial;
389 return QFontDialogPrivate::getFont(ok, initial, parent, QString(), { });
390}
391
392QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
393 const QString &title, QFontDialog::FontDialogOptions options)
394{
395 QAutoPointer<QFontDialog> dlg(new QFontDialog(parent));
396 dlg->setOptions(options);
397 dlg->setCurrentFont(initial);
398 if (!title.isEmpty())
399 dlg->setWindowTitle(title);
400
401 int ret = (dlg->exec() || (options & QFontDialog::NoButtons));
402 if (ok)
403 *ok = !!ret;
404 if (ret && bool(dlg)) {
405 return dlg->selectedFont();
406 } else {
407 return initial;
408 }
409}
410
411/*!
412 \internal
413 An event filter to make the Up, Down, PageUp and PageDown keys work
414 correctly in the line edits. The source of the event is the object
415 \a o and the event is \a e.
416*/
417
418bool QFontDialog::eventFilter(QObject *o , QEvent *e)
419{
420 Q_D(QFontDialog);
421 if (e->type() == QEvent::KeyPress) {
422 QKeyEvent *k = static_cast<QKeyEvent *>(e);
423 if (o == d->sizeEdit &&
424 (k->key() == Qt::Key_Up ||
425 k->key() == Qt::Key_Down ||
426 k->key() == Qt::Key_PageUp ||
427 k->key() == Qt::Key_PageDown)) {
428
429 int ci = d->sizeList->currentItem();
430 QCoreApplication::sendEvent(d->sizeList, k);
431
432 if (ci != d->sizeList->currentItem()
433 && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this))
434 d->sizeEdit->selectAll();
435 return true;
436 } else if ((o == d->familyList || o == d->styleList) &&
437 (k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter)) {
438 k->accept();
439 accept();
440 return true;
441 }
442 } else if (e->type() == QEvent::FocusIn
443 && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this)) {
444 if (o == d->familyList)
445 d->familyEdit->selectAll();
446 else if (o == d->styleList)
447 d->styleEdit->selectAll();
448 else if (o == d->sizeList)
449 d->sizeEdit->selectAll();
450 } else if (e->type() == QEvent::MouseButtonPress && o == d->sizeList) {
451 d->sizeEdit->setFocus();
452 }
453 return QDialog::eventFilter(o, e);
454}
455
456void QFontDialogPrivate::initHelper(QPlatformDialogHelper *h)
457{
458 Q_Q(QFontDialog);
459 auto *fontDialogHelper = static_cast<QPlatformFontDialogHelper *>(h);
460 fontDialogHelper->setOptions(options);
461 fontDialogHelper->setCurrentFont(q->currentFont());
462 QObject::connect(fontDialogHelper, &QPlatformFontDialogHelper::currentFontChanged,
463 q, &QFontDialog::currentFontChanged);
464 QObject::connect(fontDialogHelper, &QPlatformFontDialogHelper::fontSelected,
465 q, &QFontDialog::fontSelected);
466}
467
468void QFontDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
469{
470 options->setWindowTitle(q_func()->windowTitle());
471}
472
473/*
474 Updates the contents of the "font family" list box. This
475 function can be reimplemented if you have special requirements.
476*/
477
478void QFontDialogPrivate::updateFamilies()
479{
480 Q_Q(QFontDialog);
481
482 enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
483
484 const QFontDialog::FontDialogOptions scalableMask = (QFontDialog::ScalableFonts | QFontDialog::NonScalableFonts);
485 const QFontDialog::FontDialogOptions spacingMask = (QFontDialog::ProportionalFonts | QFontDialog::MonospacedFonts);
486 const QFontDialog::FontDialogOptions options = q->options();
487
488 QStringList familyNames;
489 const auto families = QFontDatabase::families(writingSystem);
490 for (const QString &family : families) {
491 if (QFontDatabase::isPrivateFamily(family))
492 continue;
493
494 if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
495 if (bool(options & QFontDialog::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family))
496 continue;
497 }
498 if ((options & spacingMask) && (options & spacingMask) != spacingMask) {
499 if (bool(options & QFontDialog::MonospacedFonts) != QFontDatabase::isFixedPitch(family))
500 continue;
501 }
502 familyNames << family;
503 }
504
505 familyList->model()->setStringList(familyNames);
506
507 QString foundryName1, familyName1, foundryName2, familyName2;
508 int bestFamilyMatch = -1;
509 match_t bestFamilyType = MATCH_NONE;
510
511 QFont f;
512
513 // ##### do the right thing for a list of family names in the font.
514 QFontDatabasePrivate::parseFontName(family, foundryName1, familyName1);
515
516 QStringList::const_iterator it = familyNames.constBegin();
517 int i = 0;
518 for(; it != familyNames.constEnd(); ++it, ++i) {
519 QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2);
520
521 //try to match...
522 if (familyName1 == familyName2) {
523 bestFamilyType = MATCH_FAMILY;
524 if (foundryName1 == foundryName2) {
525 bestFamilyMatch = i;
526 break;
527 }
528 if (bestFamilyMatch < MATCH_FAMILY)
529 bestFamilyMatch = i;
530 }
531
532 //and try some fall backs
533 match_t type = MATCH_NONE;
534 if (bestFamilyType <= MATCH_NONE && familyName2 == "helvetica"_L1)
535 type = MATCH_LAST_RESORT;
536 if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family())
537 type = MATCH_APP;
538 // ### add fallback for writingSystem
539 if (type != MATCH_NONE) {
540 bestFamilyType = type;
541 bestFamilyMatch = i;
542 }
543 }
544
545 if (i != -1 && bestFamilyType != MATCH_NONE)
546 familyList->setCurrentItem(bestFamilyMatch);
547 else
548 familyList->setCurrentItem(0);
549 familyEdit->setText(familyList->currentText());
550 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
551 && familyList->hasFocus())
552 familyEdit->selectAll();
553
554 updateStyles();
555}
556
557/*
558 Updates the contents of the "font style" list box. This
559 function can be reimplemented if you have special requirements.
560*/
561void QFontDialogPrivate::updateStyles()
562{
563 Q_Q(QFontDialog);
564 QStringList styles = QFontDatabase::styles(familyList->currentText());
565 styleList->model()->setStringList(styles);
566
567 if (styles.isEmpty()) {
568 styleEdit->clear();
569 smoothScalable = false;
570 } else {
571 if (!style.isEmpty()) {
572 bool found = false;
573 bool first = true;
574 QString cstyle = style;
575
576 redo:
577 for (int i = 0; i < static_cast<int>(styleList->count()); i++) {
578 if (cstyle == styleList->text(i)) {
579 styleList->setCurrentItem(i);
580 found = true;
581 break;
582 }
583 }
584 if (!found && first) {
585 if (cstyle.contains("Italic"_L1)) {
586 cstyle.replace("Italic"_L1, "Oblique"_L1);
587 first = false;
588 goto redo;
589 } else if (cstyle.contains("Oblique"_L1)) {
590 cstyle.replace("Oblique"_L1, "Italic"_L1);
591 first = false;
592 goto redo;
593 } else if (cstyle.contains("Regular"_L1)) {
594 cstyle.replace("Regular"_L1, "Normal"_L1);
595 first = false;
596 goto redo;
597 } else if (cstyle.contains("Normal"_L1)) {
598 cstyle.replace("Normal"_L1, "Regular"_L1);
599 first = false;
600 goto redo;
601 }
602 }
603 if (!found)
604 styleList->setCurrentItem(0);
605 } else {
606 styleList->setCurrentItem(0);
607 }
608
609 styleEdit->setText(styleList->currentText());
610 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
611 && styleList->hasFocus())
612 styleEdit->selectAll();
613
614 smoothScalable = QFontDatabase::isSmoothlyScalable(familyList->currentText(), styleList->currentText());
615 }
616
617 updateSizes();
618}
619
620/*!
621 \internal
622 Updates the contents of the "font size" list box. This
623 function can be reimplemented if you have special requirements.
624*/
625
626void QFontDialogPrivate::updateSizes()
627{
628 Q_Q(QFontDialog);
629
630 if (!familyList->currentText().isEmpty()) {
631 QList<int> sizes = QFontDatabase::pointSizes(familyList->currentText(), styleList->currentText());
632
633 int i = 0;
634 int current = -1;
635 QStringList str_sizes;
636 str_sizes.reserve(sizes.size());
637 for(QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {
638 str_sizes.append(QString::number(*it));
639 if (current == -1 && *it == size)
640 current = i;
641 ++i;
642 }
643 sizeList->model()->setStringList(str_sizes);
644 if (current != -1)
645 sizeList->setCurrentItem(current);
646
647 const QSignalBlocker blocker(sizeEdit);
648 sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText()));
649 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
650 && sizeList->hasFocus())
651 sizeEdit->selectAll();
652 } else {
653 sizeEdit->clear();
654 }
655
656 updateSample();
657}
658
659void QFontDialogPrivate::updateSample()
660{
661 // compute new font
662 int pSize = sizeEdit->text().toInt();
663 QFont newFont(QFontDatabase::font(familyList->currentText(), style, pSize));
664 newFont.setStrikeOut(strikeout->isChecked());
665 newFont.setUnderline(underline->isChecked());
666
667 if (familyList->currentText().isEmpty())
668 sampleEdit->clear();
669
670 updateSampleFont(newFont);
671}
672
673void QFontDialogPrivate::updateSampleFont(const QFont &newFont)
674{
675 Q_Q(QFontDialog);
676 if (newFont != sampleEdit->font()) {
677 sampleEdit->setFont(newFont);
678 emit q->currentFontChanged(newFont);
679 }
680}
681
682/*!
683 \internal
684*/
685void QFontDialogPrivate::writingSystemHighlighted(int index)
686{
687 writingSystem = QFontDatabase::WritingSystem(index);
688 sampleEdit->setText(QFontDatabase::writingSystemSample(writingSystem));
689 updateFamilies();
690}
691
692/*!
693 \internal
694*/
695void QFontDialogPrivate::familyHighlighted(int i)
696{
697 Q_Q(QFontDialog);
698 family = familyList->text(i);
699 familyEdit->setText(family);
700 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
701 && familyList->hasFocus())
702 familyEdit->selectAll();
703
704 updateStyles();
705}
706
707
708/*!
709 \internal
710*/
711
712void QFontDialogPrivate::styleHighlighted(int index)
713{
714 Q_Q(QFontDialog);
715 QString s = styleList->text(index);
716 styleEdit->setText(s);
717 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
718 && styleList->hasFocus())
719 styleEdit->selectAll();
720
721 style = s;
722
723 updateSizes();
724}
725
726
727/*!
728 \internal
729*/
730
731void QFontDialogPrivate::sizeHighlighted(int index)
732{
733 Q_Q(QFontDialog);
734 QString s = sizeList->text(index);
735 sizeEdit->setText(s);
736 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
737 && sizeEdit->hasFocus())
738 sizeEdit->selectAll();
739
740 size = s.toInt();
741 updateSample();
742}
743
744/*!
745 \internal
746 This slot is called if the user changes the font size.
747 The size is passed in the \a s argument as a \e string.
748*/
749
750void QFontDialogPrivate::sizeChanged(const QString &s)
751{
752 // no need to check if the conversion is valid, since we have an QIntValidator in the size edit
753 int size = s.toInt();
754 if (this->size == size)
755 return;
756
757 this->size = size;
758 if (sizeList->count() != 0) {
759 int i;
760 for (i = 0; i < sizeList->count() - 1; i++) {
761 if (sizeList->text(i).toInt() >= this->size)
762 break;
763 }
764 const QSignalBlocker blocker(sizeList);
765 if (sizeList->text(i).toInt() == this->size)
766 sizeList->setCurrentItem(i);
767 else
768 sizeList->clearSelection();
769 }
770 updateSample();
771}
772
773void QFontDialogPrivate::retranslateStrings()
774{
775 familyAccel->setText(QFontDialog::tr("&Font"));
776 styleAccel->setText(QFontDialog::tr("Font st&yle"));
777 sizeAccel->setText(QFontDialog::tr("&Size"));
778 effects->setTitle(QFontDialog::tr("Effects"));
779 strikeout->setText(QFontDialog::tr("Stri&keout"));
780 underline->setText(QFontDialog::tr("&Underline"));
781 sample->setTitle(QFontDialog::tr("Sample"));
782 writingSystemAccel->setText(QFontDialog::tr("Wr&iting System"));
783}
784
785/*!
786 \reimp
787*/
788void QFontDialog::changeEvent(QEvent *e)
789{
790 Q_D(QFontDialog);
791 if (e->type() == QEvent::LanguageChange) {
792 d->retranslateStrings();
793 }
794 QDialog::changeEvent(e);
795}
796
797/*!
798 \property QFontDialog::currentFont
799 \brief the current font of the dialog.
800*/
801
802/*!
803 Sets the font highlighted in the QFontDialog to the given \a font.
804
805 \sa selectedFont()
806*/
807void QFontDialog::setCurrentFont(const QFont &font)
808{
809 Q_D(QFontDialog);
810 d->family = font.families().value(0);
811 d->style = QFontDatabase::styleString(font);
812 d->size = font.pointSize();
813 if (d->size == -1) {
814 QFontInfo fi(font);
815 d->size = fi.pointSize();
816 }
817 d->strikeout->setChecked(font.strikeOut());
818 d->underline->setChecked(font.underline());
819 d->updateFamilies();
820
821 if (d->nativeDialogInUse) {
822 if (QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())
823 helper->setCurrentFont(font);
824 }
825}
826
827/*!
828 Returns the current font.
829
830 \sa selectedFont()
831*/
832QFont QFontDialog::currentFont() const
833{
834 Q_D(const QFontDialog);
835
836 if (d->nativeDialogInUse) {
837 if (const QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())
838 return helper->currentFont();
839 }
840 return d->sampleEdit->font();
841}
842
843/*!
844 Returns the font that the user selected by clicking the \uicontrol{OK}
845 or equivalent button.
846
847 \note This font is not always the same as the font held by the
848 \l currentFont property since the user can choose different fonts
849 before finally selecting the one to use.
850*/
851QFont QFontDialog::selectedFont() const
852{
853 Q_D(const QFontDialog);
854 return d->selectedFont;
855}
856
857/*!
858 \enum QFontDialog::FontDialogOption
859
860 This enum specifies various options that affect the look and feel
861 of a font dialog.
862
863 For instance, it allows to specify which type of font should be
864 displayed. If none are specified all fonts available will be listed.
865
866 Note that the font filtering options might not be supported on some
867 platforms (e.g. Mac). They are always supported by the non native
868 dialog (used on Windows or Linux).
869
870 \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".)
871 \value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's
872 native font panel.
873 \value ScalableFonts Show scalable fonts
874 \value NonScalableFonts Show non scalable fonts
875 \value MonospacedFonts Show monospaced fonts
876 \value ProportionalFonts Show proportional fonts
877
878 \sa options, setOption(), testOption()
879*/
880
881/*!
882 Sets the given \a option to be enabled if \a on is true;
883 otherwise, clears the given \a option.
884
885 \sa options, testOption()
886*/
887void QFontDialog::setOption(FontDialogOption option, bool on)
888{
889 Q_D(QFontDialog);
890 d->optionsExplicitlySet = true;
891
892 const QFontDialog::FontDialogOptions previousOptions = options();
893 if (!(previousOptions & option) != !on)
894 setOptions(previousOptions ^ option);
895}
896
897/*!
898 Returns \c true if the given \a option is enabled; otherwise, returns
899 false.
900
901 \sa options, setOption()
902*/
903bool QFontDialog::testOption(FontDialogOption option) const
904{
905 Q_D(const QFontDialog);
906 return d->options->testOption(static_cast<QFontDialogOptions::FontDialogOption>(option));
907}
908
909/*!
910 \property QFontDialog::options
911 \brief the various options that affect the look and feel of the dialog
912
913 By default, all options are disabled.
914
915 Options should be set before showing the dialog. Setting them while the
916 dialog is visible is not guaranteed to have an immediate effect on the
917 dialog (depending on the option and on the platform).
918
919 \sa setOption(), testOption()
920*/
921void QFontDialog::setOptions(FontDialogOptions options)
922{
923 Q_D(QFontDialog);
924 d->optionsExplicitlySet = true;
925
926 if (QFontDialog::options() == options)
927 return;
928
929 d->options->setOptions(QFontDialogOptions::FontDialogOptions(int(options)));
930 d->buttonBox->setVisible(!(options & NoButtons));
931}
932
933QFontDialog::FontDialogOptions QFontDialog::options() const
934{
935 Q_D(const QFontDialog);
936 return QFontDialog::FontDialogOptions(int(d->options->options()));
937}
938
939/*!
940 Opens the dialog and connects its fontSelected() signal to the slot specified
941 by \a receiver and \a member.
942
943 The signal will be disconnected from the slot when the dialog is closed.
944*/
945void QFontDialog::open(QObject *receiver, const char *member)
946{
947 Q_D(QFontDialog);
948 connect(this, SIGNAL(fontSelected(QFont)), receiver, member);
949 d->receiverToDisconnectOnClose = receiver;
950 d->memberToDisconnectOnClose = member;
951 QDialog::open();
952}
953
954/*!
955 \fn void QFontDialog::currentFontChanged(const QFont &font)
956
957 This signal is emitted when the current font is changed. The new font is
958 specified in \a font.
959
960 The signal is emitted while a user is selecting a font. Ultimately, the
961 chosen font may differ from the font currently selected.
962
963 \sa currentFont, fontSelected(), selectedFont()
964*/
965
966/*!
967 \fn void QFontDialog::fontSelected(const QFont &font)
968
969 This signal is emitted when a font has been selected. The selected font is
970 specified in \a font.
971
972 The signal is only emitted when a user has chosen the final font to be
973 used. It is not emitted while the user is changing the current font in the
974 font dialog.
975
976 \sa selectedFont(), currentFontChanged(), currentFont
977*/
978
979/*!
980 \reimp
981*/
982void QFontDialog::setVisible(bool visible)
983{
984 // will call QFontDialogPrivate::setVisible
985 QDialog::setVisible(visible);
986}
987
988/*!
989 \internal
990
991 The implementation of QFontDialog::setVisible() has to live here so that the call
992 to hide() in ~QDialog calls this function; it wouldn't call the override of
993 QDialog::setVisible().
994*/
995void QFontDialogPrivate::setVisible(bool visible)
996{
997 // Don't use Q_Q here! This function is called from ~QDialog,
998 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
999 const auto q = static_cast<QDialog *>(q_ptr);
1000
1001 if (canBeNativeDialog())
1002 setNativeDialogVisible(visible);
1003 if (nativeDialogInUse) {
1004 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
1005 // updates the state correctly, but skips showing the non-native version:
1006 q->setAttribute(Qt::WA_DontShowOnScreen, true);
1007 } else {
1008 q->setAttribute(Qt::WA_DontShowOnScreen, false);
1009 }
1010 QDialogPrivate::setVisible(visible);
1011}
1012
1013/*!
1014 Closes the dialog and sets its result code to \a result. If this dialog
1015 is shown with exec(), done() causes the local event loop to finish,
1016 and exec() to return \a result.
1017
1018 \sa QDialog::done()
1019*/
1020void QFontDialog::done(int result)
1021{
1022 Q_D(QFontDialog);
1023 if (result == Accepted) {
1024 // We check if this is the same font we had before, if so we emit currentFontChanged
1025 QFont selectedFont = currentFont();
1026 if (selectedFont != d->selectedFont)
1027 emit(currentFontChanged(selectedFont));
1028 d->selectedFont = selectedFont;
1029 emit fontSelected(d->selectedFont);
1030 } else
1031 d->selectedFont = QFont();
1032 if (d->receiverToDisconnectOnClose) {
1033 disconnect(this, SIGNAL(fontSelected(QFont)),
1034 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
1035 d->receiverToDisconnectOnClose = nullptr;
1036 }
1037 d->memberToDisconnectOnClose.clear();
1038 QDialog::done(result);
1039}
1040
1041bool QFontDialogPrivate::canBeNativeDialog() const
1042{
1043 // Don't use Q_Q here! This function is called from ~QDialog,
1044 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
1045 const QDialog * const q = static_cast<const QDialog*>(q_ptr);
1046 if (nativeDialogInUse)
1047 return true;
1048 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
1049 || q->testAttribute(Qt::WA_DontShowOnScreen)
1050 || (options->options() & QFontDialog::DontUseNativeDialog)) {
1051 return false;
1052 }
1053
1054 return strcmp(QFontDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
1055}
1056
1057QT_END_NAMESPACE
1058
1059#include "qfontdialog.moc"
1060#include "moc_qfontdialog.cpp"
QStringListModel * model() const
int count() const
void setCurrentItem(int item)
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override
This slot is called when a new item becomes the current item.
QString currentText() const
int currentItem() const
QString text(int i) const
QFontPolishFilter(QFontDialog *fd)
bool eventFilter(QObject *obj, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.
friend class QWidget
Definition qpainter.h:432
Combined button and popup list for selecting options.
static const Qt::WindowFlags qfd_DefaultWindowFlags