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