1// Copyright (C) 2021 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 "qquickfontdialogimpl_p.h"
5#include "qquickfontdialogimpl_p_p.h"
6
7#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
8#include <private/qfontdatabase_p.h>
9
10#include <QRegularExpression>
11
12QT_BEGIN_NAMESPACE
13
14Q_LOGGING_CATEGORY(lcAttachedProperty, "qt.quick.dialogs.quickfontdialogimpl.attachedOrWarn")
15
16QQuickFontDialogImplPrivate::QQuickFontDialogImplPrivate()
17{
18}
19
20QQuickFontDialogImplAttached *QQuickFontDialogImplPrivate::attachedOrWarn()
21{
22 Q_Q(QQuickFontDialogImpl);
23 QQuickFontDialogImplAttached *attached = static_cast<QQuickFontDialogImplAttached *>(
24 qmlAttachedPropertiesObject<QQuickFontDialogImpl>(obj: q));
25 if (!attached) {
26 qCWarning(lcAttachedProperty)
27 << "Expected FontDialogImpl attached object to be present on" << this;
28 }
29 return attached;
30}
31
32void QQuickFontDialogImplPrivate::handleAccept() { }
33
34void QQuickFontDialogImplPrivate::handleClick(QQuickAbstractButton *button)
35{
36 Q_Q(QQuickFontDialogImpl);
37 if (buttonRole(button) == QPlatformDialogHelper::AcceptRole) {
38 q->accept();
39 QQuickDialogPrivate::handleClick(button);
40 }
41}
42
43QQuickFontDialogImpl::QQuickFontDialogImpl(QObject *parent)
44 : QQuickDialog(*(new QQuickFontDialogImplPrivate), parent)
45{
46}
47
48QQuickFontDialogImplAttached *QQuickFontDialogImpl::qmlAttachedProperties(QObject *object)
49{
50 return new QQuickFontDialogImplAttached(object);
51}
52
53QSharedPointer<QFontDialogOptions> QQuickFontDialogImpl::options() const
54{
55 Q_D(const QQuickFontDialogImpl);
56
57 return d->options;
58}
59
60void QQuickFontDialogImpl::setOptions(const QSharedPointer<QFontDialogOptions> &options)
61{
62 Q_D(QQuickFontDialogImpl);
63
64 if (options == d->options)
65 return;
66
67 d->options = options;
68
69 emit optionsChanged();
70}
71
72QFont QQuickFontDialogImpl::currentFont() const
73{
74 Q_D(const QQuickFontDialogImpl);
75 return d->currentFont;
76}
77
78void QQuickFontDialogImpl::setCurrentFont(const QFont &font, bool selectInListViews)
79{
80 Q_D(QQuickFontDialogImpl);
81
82 if (font == d->currentFont)
83 return;
84
85 d->currentFont = font;
86
87 emit currentFontChanged(font);
88
89 if (!selectInListViews)
90 return;
91
92 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
93 if (!attached)
94 return;
95
96 if (!attached->familyListView()->model().isValid()) {
97 const QSignalBlocker blocker(attached->sampleEdit());
98 attached->updateFamilies();
99 }
100
101 attached->selectFontInListViews(font);
102}
103
104void QQuickFontDialogImpl::init()
105{
106 Q_D(QQuickFontDialogImpl);
107 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
108 if (!attached)
109 return;
110
111 if (!attached->familyListView()->model().isValid())
112 attached->updateFamilies();
113
114 attached->buttonBox()->setVisible(!(options()->options() & QFontDialogOptions::NoButtons));
115}
116
117void QQuickFontDialogImpl::keyReleaseEvent(QKeyEvent *event)
118{
119 Q_D(QQuickFontDialogImpl);
120
121 QQuickDialog::keyReleaseEvent(event);
122
123 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
124 if (!attached)
125 return;
126
127 // The family and style text edits are read-only so that they
128 // can show the current selection but also allow key input to "search".
129 // This is why we handle just the release event, and don't accept it.
130 if (window()->activeFocusItem() == attached->familyEdit())
131 attached->searchFamily(s: event->text());
132 else if (window()->activeFocusItem() == attached->styleEdit())
133 attached->searchStyle(s: event->text());
134}
135
136void QQuickFontDialogImpl::focusOutEvent(QFocusEvent *event)
137{
138 Q_D(QQuickFontDialogImpl);
139
140 QQuickDialog::focusOutEvent(event);
141
142 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
143 if (!attached)
144 return;
145
146 attached->clearSearch();
147}
148
149QQuickFontDialogImplAttached::QQuickFontDialogImplAttached(QObject *parent)
150 : QObject(*(new QQuickFontDialogImplAttachedPrivate), parent),
151 m_writingSystem(QFontDatabase::Any),
152 m_selectedSize(-1),
153 m_smoothlyScalable(false),
154 m_ignoreFamilyUpdate(false),
155 m_ignoreStyleUpdate(false)
156{
157 if (!qobject_cast<QQuickFontDialogImpl *>(object: parent)) {
158 qmlWarning(me: this) << "FontDialogImpl attached properties should only be "
159 << "accessed through the root FileDialogImpl instance";
160 }
161}
162
163QQuickListView *QQuickFontDialogImplAttached::familyListView() const
164{
165 Q_D(const QQuickFontDialogImplAttached);
166 return d->familyListView;
167}
168
169void QQuickFontDialogImplAttached::setFamilyListView(QQuickListView *familyListView)
170{
171 Q_D(QQuickFontDialogImplAttached);
172 if (d->familyListView == familyListView)
173 return;
174
175 if (d->familyListView) {
176 disconnect(sender: d->familyListView, signal: &QQuickListView::currentIndexChanged,
177 receiver: this, slot: &QQuickFontDialogImplAttached::_q_familyChanged);
178 }
179
180 d->familyListView = familyListView;
181
182 if (familyListView) {
183 connect(sender: d->familyListView, signal: &QQuickListView::currentIndexChanged,
184 context: this, slot: &QQuickFontDialogImplAttached::_q_familyChanged);
185 }
186
187 emit familyListViewChanged();
188}
189
190QQuickListView *QQuickFontDialogImplAttached::styleListView() const
191{
192 Q_D(const QQuickFontDialogImplAttached);
193 return d->styleListView;
194}
195
196void QQuickFontDialogImplAttached::setStyleListView(QQuickListView *styleListView)
197{
198 Q_D(QQuickFontDialogImplAttached);
199 if (d->styleListView == styleListView)
200 return;
201
202 if (d->styleListView) {
203 disconnect(sender: d->styleListView, signal: &QQuickListView::currentIndexChanged,
204 receiver: this, slot: &QQuickFontDialogImplAttached::_q_styleChanged);
205 }
206
207 d->styleListView = styleListView;
208
209 if (styleListView) {
210 connect(sender: d->styleListView, signal: &QQuickListView::currentIndexChanged,
211 context: this, slot: &QQuickFontDialogImplAttached::_q_styleChanged);
212 }
213
214 emit styleListViewChanged();
215}
216
217QQuickListView *QQuickFontDialogImplAttached::sizeListView() const
218{
219 Q_D(const QQuickFontDialogImplAttached);
220 return d->sizeListView;
221}
222
223void QQuickFontDialogImplAttached::setSizeListView(QQuickListView *sizeListView)
224{
225 Q_D(QQuickFontDialogImplAttached);
226 if (d->sizeListView == sizeListView)
227 return;
228
229 if (d->sizeListView) {
230 disconnect(sender: d->sizeListView, signal: &QQuickListView::currentIndexChanged,
231 receiver: this, slot: &QQuickFontDialogImplAttached::_q_sizeChanged);
232 }
233
234 d->sizeListView = sizeListView;
235
236 if (d->sizeListView) {
237 connect(sender: d->sizeListView, signal: &QQuickListView::currentIndexChanged,
238 context: this, slot: &QQuickFontDialogImplAttached::_q_sizeChanged);
239 }
240
241 emit sizeListViewChanged();
242}
243
244QQuickTextEdit *QQuickFontDialogImplAttached::sampleEdit() const
245{
246 Q_D(const QQuickFontDialogImplAttached);
247 return d->sampleEdit;
248}
249
250void QQuickFontDialogImplAttached::setSampleEdit(QQuickTextEdit *sampleEdit)
251{
252 Q_D(QQuickFontDialogImplAttached);
253
254 if (d->sampleEdit == sampleEdit)
255 return;
256
257 if (d->sampleEdit) {
258 QObjectPrivate::disconnect(sender: d->sampleEdit, signal: &QQuickTextEdit::fontChanged,
259 receiverPrivate: d, slot: &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
260 }
261
262 d->sampleEdit = sampleEdit;
263
264 if (d->sampleEdit) {
265 QObjectPrivate::connect(sender: d->sampleEdit, signal: &QQuickTextEdit::fontChanged,
266 receiverPrivate: d, slot: &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
267
268 d->sampleEdit->setText(QFontDatabase::writingSystemSample(writingSystem: m_writingSystem));
269 }
270
271 emit sampleEditChanged();
272}
273
274QQuickDialogButtonBox *QQuickFontDialogImplAttached::buttonBox() const
275{
276 Q_D(const QQuickFontDialogImplAttached);
277 return d->buttonBox;
278}
279
280void QQuickFontDialogImplAttached::setButtonBox(QQuickDialogButtonBox *buttonBox)
281{
282 Q_D(QQuickFontDialogImplAttached);
283 if (buttonBox == d->buttonBox)
284 return;
285
286 if (d->buttonBox) {
287 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(object: parent());
288 if (fontDialogImpl) {
289 auto dialogPrivate = QQuickDialogPrivate::get(dialog: fontDialogImpl);
290 QObjectPrivate::disconnect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::accepted,
291 receiverPrivate: dialogPrivate, slot: &QQuickDialogPrivate::handleAccept);
292 QObjectPrivate::disconnect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::rejected,
293 receiverPrivate: dialogPrivate, slot: &QQuickDialogPrivate::handleReject);
294 QObjectPrivate::disconnect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::clicked, receiverPrivate: dialogPrivate,
295 slot: &QQuickDialogPrivate::handleClick);
296 }
297 }
298
299 d->buttonBox = buttonBox;
300
301 if (buttonBox) {
302 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(object: parent());
303 if (fontDialogImpl) {
304 auto dialogPrivate = QQuickDialogPrivate::get(dialog: fontDialogImpl);
305 QObjectPrivate::connect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::accepted, receiverPrivate: dialogPrivate,
306 slot: &QQuickDialogPrivate::handleAccept);
307 QObjectPrivate::connect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::rejected, receiverPrivate: dialogPrivate,
308 slot: &QQuickDialogPrivate::handleReject);
309 QObjectPrivate::connect(sender: d->buttonBox, signal: &QQuickDialogButtonBox::clicked, receiverPrivate: dialogPrivate,
310 slot: &QQuickDialogPrivate::handleClick);
311 }
312 }
313
314 emit buttonBoxChanged();
315}
316
317QQuickComboBox *QQuickFontDialogImplAttached::writingSystemComboBox() const
318{
319 Q_D(const QQuickFontDialogImplAttached);
320 return d->writingSystemComboBox;
321}
322
323void QQuickFontDialogImplAttached::setWritingSystemComboBox(QQuickComboBox *writingSystemComboBox)
324{
325 Q_D(QQuickFontDialogImplAttached);
326
327 if (d->writingSystemComboBox == writingSystemComboBox)
328 return;
329
330 if (d->writingSystemComboBox) {
331 disconnect(sender: d->writingSystemComboBox, signal: &QQuickComboBox::activated,
332 receiver: this, slot: &QQuickFontDialogImplAttached::_q_writingSystemChanged);
333 }
334
335 d->writingSystemComboBox = writingSystemComboBox;
336
337 if (d->writingSystemComboBox) {
338 QStringList writingSystemModel;
339 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
340 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
341 QString wsName = QFontDatabase::writingSystemName(writingSystem: ws);
342 if (wsName.isEmpty())
343 break;
344 writingSystemModel.append(t: wsName);
345 }
346
347 d->writingSystemComboBox->setModel(writingSystemModel);
348
349 connect(sender: d->writingSystemComboBox, signal: &QQuickComboBox::activated,
350 context: this, slot: &QQuickFontDialogImplAttached::_q_writingSystemChanged);
351 }
352
353 emit writingSystemComboBoxChanged();
354}
355
356QQuickCheckBox *QQuickFontDialogImplAttached::underlineCheckBox() const
357{
358 Q_D(const QQuickFontDialogImplAttached);
359 return d->underlineCheckBox;
360}
361
362void QQuickFontDialogImplAttached::setUnderlineCheckBox(QQuickCheckBox *underlineCheckBox)
363{
364 Q_D(QQuickFontDialogImplAttached);
365
366 if (d->underlineCheckBox == underlineCheckBox)
367 return;
368
369 if (d->underlineCheckBox) {
370 disconnect(sender: d->underlineCheckBox, signal: &QQuickCheckBox::checkStateChanged,
371 receiver: this, slot: &QQuickFontDialogImplAttached::_q_updateSample);
372 }
373
374 d->underlineCheckBox = underlineCheckBox;
375
376 if (d->underlineCheckBox) {
377 connect(sender: d->underlineCheckBox, signal: &QQuickCheckBox::checkStateChanged,
378 context: this, slot: &QQuickFontDialogImplAttached::_q_updateSample);
379 }
380
381 emit underlineCheckBoxChanged();
382}
383
384QQuickCheckBox *QQuickFontDialogImplAttached::strikeoutCheckBox() const
385{
386 Q_D(const QQuickFontDialogImplAttached);
387 return d->strikeoutCheckBox;
388}
389
390void QQuickFontDialogImplAttached::setStrikeoutCheckBox(QQuickCheckBox *strikeoutCheckBox)
391{
392 Q_D(QQuickFontDialogImplAttached);
393
394 if (d->strikeoutCheckBox == strikeoutCheckBox)
395 return;
396
397 if (d->strikeoutCheckBox) {
398 disconnect(sender: d->strikeoutCheckBox, signal: &QQuickCheckBox::checkStateChanged,
399 receiver: this, slot: &QQuickFontDialogImplAttached::_q_updateSample);
400 }
401
402 d->strikeoutCheckBox = strikeoutCheckBox;
403
404 if (d->strikeoutCheckBox) {
405 connect(sender: d->strikeoutCheckBox, signal: &QQuickCheckBox::checkStateChanged,
406 context: this, slot: &QQuickFontDialogImplAttached::_q_updateSample);
407 }
408
409 emit strikeoutCheckBoxChanged();
410}
411
412QQuickTextField *QQuickFontDialogImplAttached::familyEdit() const
413{
414 Q_D(const QQuickFontDialogImplAttached);
415 return d->familyEdit;
416}
417
418void QQuickFontDialogImplAttached::setFamilyEdit(QQuickTextField *familyEdit)
419{
420 Q_D(QQuickFontDialogImplAttached);
421
422 if (d->familyEdit == familyEdit)
423 return;
424
425 d->familyEdit = familyEdit;
426
427 emit familyEditChanged();
428}
429
430QQuickTextField *QQuickFontDialogImplAttached::styleEdit() const
431{
432 Q_D(const QQuickFontDialogImplAttached);
433 return d->styleEdit;
434}
435
436void QQuickFontDialogImplAttached::setStyleEdit(QQuickTextField *styleEdit)
437{
438 Q_D(QQuickFontDialogImplAttached);
439
440 if (d->styleEdit == styleEdit)
441 return;
442
443 d->styleEdit = styleEdit;
444
445 emit styleEditChanged();
446}
447
448QQuickTextField *QQuickFontDialogImplAttached::sizeEdit() const
449{
450 Q_D(const QQuickFontDialogImplAttached);
451 return d->sizeEdit;
452}
453
454void QQuickFontDialogImplAttached::setSizeEdit(QQuickTextField *sizeEdit)
455{
456 Q_D(QQuickFontDialogImplAttached);
457
458 if (d->sizeEdit == sizeEdit)
459 return;
460
461 if (d->sizeEdit) {
462 disconnect(sender: d->sizeEdit, signal: &QQuickTextField::textChanged,
463 receiver: this, slot: &QQuickFontDialogImplAttached::_q_sizeEdited);
464 }
465
466 d->sizeEdit = sizeEdit;
467
468 if (d->sizeEdit) {
469 connect(sender: d->sizeEdit, signal: &QQuickTextField::textChanged,
470 context: this, slot: &QQuickFontDialogImplAttached::_q_sizeEdited);
471 }
472
473 emit sizeEditChanged();
474}
475
476static int findFamilyInModel(const QString &selectedFamily, const QStringList &model)
477{
478 enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
479 QString foundryName1, familyName1, foundryName2, familyName2;
480 int bestFamilyMatch = -1;
481 match_t bestFamilyType = MATCH_NONE;
482 const QFont f;
483
484 QFontDatabasePrivate::parseFontName(name: selectedFamily, foundry&: foundryName1, family&: familyName1);
485
486 int i = 0;
487 for (auto it = model.constBegin(); it != model.constEnd(); ++it, ++i) {
488 QFontDatabasePrivate::parseFontName(name: *it, foundry&: foundryName2, family&: familyName2);
489
490 if (familyName1 == familyName2) {
491 bestFamilyType = MATCH_FAMILY;
492 if (foundryName1 == foundryName2)
493 return i;
494 else
495 bestFamilyMatch = i;
496 }
497
498 // fallbacks
499 match_t type = MATCH_NONE;
500 if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral("helvetica"))
501 type = MATCH_LAST_RESORT;
502 if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().constFirst())
503 type = MATCH_APP;
504 if (type != MATCH_NONE) {
505 bestFamilyType = type;
506 bestFamilyMatch = i;
507 }
508 }
509
510 return bestFamilyMatch;
511}
512
513static int findStyleInModel(const QString &selectedStyle, const QStringList &model)
514{
515 if (model.isEmpty())
516 return -1;
517
518 if (!selectedStyle.isEmpty()) {
519 const int idx = model.indexOf(re: QRegularExpression(QRegularExpression::escape(str: selectedStyle), QRegularExpression::CaseInsensitiveOption));
520 if (idx >= 0)
521 return idx;
522
523 enum class StyleClass {Unknown, Normal, Italic};
524 auto classifyStyleFallback = [](const QString & style) {
525 if (style.toLower() == QLatin1String("italic") || style.toLower() == QLatin1String("oblique"))
526 return StyleClass::Italic;
527 if (style.toLower() == QLatin1String("normal") || style.toLower() == QLatin1String("regular"))
528 return StyleClass::Normal;
529 return StyleClass::Unknown;
530 };
531
532 auto styleClass = classifyStyleFallback(selectedStyle);
533
534 if (styleClass != StyleClass::Unknown)
535 for (int i = 0; i < model.size(); ++i)
536 if (classifyStyleFallback(model.at(i)) == styleClass)
537 return i;
538 }
539 return 0;
540}
541
542/*!
543 \internal
544
545 Updates the model for the family list view, and attempt
546 to reselect the previously selected font family.
547 */
548void QQuickFontDialogImplAttached::updateFamilies()
549{
550 const QFontDialogOptions::FontDialogOptions scalableMask(
551 QFontDialogOptions::ScalableFonts | QFontDialogOptions::NonScalableFonts);
552
553 const QFontDialogOptions::FontDialogOptions spacingMask(QFontDialogOptions::ProportionalFonts
554 | QFontDialogOptions::MonospacedFonts);
555
556 const auto p = qobject_cast<QQuickFontDialogImpl *>(object: parent());
557
558 const auto options = p->options()->options();
559
560 QStringList familyNames;
561 const auto families = QFontDatabase::families(writingSystem: m_writingSystem);
562 for (const auto &family : families) {
563 if (QFontDatabase::isPrivateFamily(family))
564 continue;
565
566 if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
567 if (bool(options & QFontDialogOptions::ScalableFonts)
568 != QFontDatabase::isSmoothlyScalable(family))
569 continue;
570 }
571
572 if ((options & spacingMask) && (options & scalableMask) != spacingMask) {
573 if (bool(options & QFontDialogOptions::MonospacedFonts)
574 != QFontDatabase::isFixedPitch(family))
575 continue;
576 }
577
578 familyNames << family;
579 }
580
581 auto listView = familyListView();
582
583 // Index will be set to -1 on empty model, and 0 for non empty models.
584 m_ignoreFamilyUpdate = !m_selectedFamily.isEmpty();
585 listView->setModel(familyNames);
586 m_ignoreFamilyUpdate = false;
587
588 // Will overwrite selectedFamily and selectedStyle
589 listView->setCurrentIndex(findFamilyInModel(selectedFamily: m_selectedFamily, model: familyNames));
590
591 if (familyNames.isEmpty())
592 _q_familyChanged();
593}
594
595/*!
596 \internal
597
598 Updates the model for the style list view, and
599 attempt to reselect the style that was previously selected.
600
601 Calls updateSizes()
602 */
603void QQuickFontDialogImplAttached::updateStyles()
604{
605 const QString family = familyListView()->currentIndex() >= 0 ? m_selectedFamily : QString();
606 const QStringList styles = QFontDatabase::styles(family);
607
608 auto listView = styleListView();
609
610 m_ignoreStyleUpdate = !m_selectedStyle.isEmpty();
611 listView->setModel(styles);
612
613 if (styles.isEmpty()) {
614 styleEdit()->clear();
615 m_smoothlyScalable = false;
616 } else {
617 int newIndex = findStyleInModel(selectedStyle: m_selectedStyle, model: styles);
618
619 listView->setCurrentIndex(newIndex);
620
621 m_selectedStyle = styles.at(i: newIndex);
622 styleEdit()->setText(m_selectedStyle);
623
624 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(family: m_selectedFamily, style: m_selectedStyle);
625 }
626
627 m_ignoreStyleUpdate = false;
628
629 updateSizes();
630}
631
632/*!
633 \internal
634
635 Updates the model for the size list view,
636 and attempts to reselect the size that was previously selected
637 */
638void QQuickFontDialogImplAttached::updateSizes()
639{
640 if (!m_selectedFamily.isEmpty()) {
641 const QList<int> sizes = QFontDatabase::pointSizes(family: m_selectedFamily, style: m_selectedStyle);
642
643 QStringList str_sizes;
644
645 str_sizes.reserve(size: sizes.size());
646
647 int idx = 0, current = -1;
648 for (QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); it++) {
649 str_sizes.append(t: QString::number(*it));
650 if (current == -1 && m_selectedSize == *it) {
651 current = idx;
652 }
653 ++idx;
654 }
655
656 auto listView = sizeListView();
657
658 // only select the first element in the model when this function is first called and the new model isn't empty
659 listView->setModel(str_sizes);
660
661 if (current != -1)
662 listView->setCurrentIndex(current);
663
664 sizeEdit()->setText(!m_smoothlyScalable && listView->currentIndex() > 0
665 ? str_sizes.at(i: listView->currentIndex())
666 : QString::number(m_selectedSize));
667 } else {
668 qCWarning(lcAttachedProperty) << "Warning! selectedFamily is empty";
669 sizeEdit()->clear();
670 }
671
672 _q_updateSample();
673}
674
675void QQuickFontDialogImplAttached::_q_updateSample()
676{
677 if (m_selectedFamily.isEmpty())
678 return;
679
680 const int pSize = sizeEdit()->text().toInt();
681
682 QFont newFont = QFontDatabase::font(family: m_selectedFamily, style: m_selectedStyle, pointSize: pSize);
683
684 newFont.setUnderline(underlineCheckBox()->isChecked());
685 newFont.setStrikeOut(strikeoutCheckBox()->isChecked());
686
687 sampleEdit()->setFont(newFont);
688}
689
690void QQuickFontDialogImplAttached::_q_writingSystemChanged(int index)
691{
692 m_writingSystem = QFontDatabase::WritingSystem(index);
693 sampleEdit()->setText(QFontDatabase::writingSystemSample(writingSystem: m_writingSystem));
694
695 updateFamilies();
696}
697
698void QQuickFontDialogImplAttached::searchListView(const QString &s, QQuickListView *listView)
699{
700 if (s.isEmpty())
701 return;
702
703 const QStringList model = listView->model().toStringList();
704
705 bool redo = false;
706
707 do {
708 m_search.append(s);
709
710 for (int i = 0; i < model.size(); ++i) {
711 if (model.at(i).startsWith(s: m_search, cs: Qt::CaseInsensitive)) {
712 listView->setCurrentIndex(i);
713 return;
714 }
715 }
716
717 clearSearch();
718
719 redo = !redo;
720 } while (redo);
721}
722
723void QQuickFontDialogImplAttached::clearSearch()
724{
725 m_search.clear();
726}
727
728void QQuickFontDialogImplAttached::_q_familyChanged()
729{
730 if (m_ignoreFamilyUpdate)
731 return;
732
733 const int index = familyListView()->currentIndex();
734
735 if (index < 0) {
736 familyEdit()->clear();
737 } else {
738 m_selectedFamily = familyListView()->model().toStringList().at(i: index);
739 familyEdit()->setText(m_selectedFamily);
740 }
741
742 updateStyles();
743}
744
745void QQuickFontDialogImplAttached::_q_styleChanged()
746{
747 if (m_ignoreStyleUpdate)
748 return;
749
750 const int index = styleListView()->currentIndex();
751
752 if (index < 0) {
753 qCWarning(lcAttachedProperty) << "currentIndex changed to -1";
754 return;
755 }
756
757 m_selectedStyle = styleListView()->model().toStringList().at(i: index);
758 styleEdit()->setText(m_selectedStyle);
759 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(family: m_selectedFamily, style: m_selectedStyle);
760
761 updateSizes();
762}
763
764void QQuickFontDialogImplAttached::_q_sizeEdited()
765{
766 const int size = qAbs(t: sizeEdit()->text().toInt());
767
768 if (size == m_selectedSize)
769 return;
770
771 m_selectedSize = size;
772
773 if (sizeListView()->count()) {
774 auto model = sizeListView()->model().toStringList();
775
776 int i;
777 for (i = 0; i < model.size() - 1; ++i) {
778 if (model.at(i).toInt() >= size)
779 break;
780 }
781
782 QSignalBlocker blocker(sizeListView());
783 if (model.at(i).toInt() == size)
784 sizeListView()->setCurrentIndex(i);
785 else
786 sizeListView()->setCurrentIndex(-1);
787 }
788
789 _q_updateSample();
790}
791
792void QQuickFontDialogImplAttached::_q_sizeChanged()
793{
794 const int index = sizeListView()->currentIndex();
795
796 if (index < 0) {
797 qCWarning(lcAttachedProperty) << "currentIndex changed to -1";
798 return;
799 }
800
801 const QString s = sizeListView()->model().toStringList().at(i: index);
802 m_selectedSize = s.toInt();
803
804 sizeEdit()->setText(s);
805
806 _q_updateSample();
807}
808
809void QQuickFontDialogImplAttachedPrivate::currentFontChanged(const QFont &font)
810{
811 auto fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(object: parent);
812
813 if (!fontDialogImpl) {
814 return;
815 }
816
817 fontDialogImpl->setCurrentFont(font);
818}
819
820void QQuickFontDialogImplAttached::selectFontInListViews(const QFont &font)
821{
822 {
823 QSignalBlocker blocker(sampleEdit());
824 familyListView()->setCurrentIndex(findFamilyInModel(selectedFamily: font.families().constFirst(), model: familyListView()->model().toStringList()));
825 styleListView()->setCurrentIndex(findStyleInModel(selectedStyle: QFontDatabase::styleString(font), model: styleListView()->model().toStringList()));
826 sizeEdit()->setText(QString::number(font.pointSize()));
827
828 underlineCheckBox()->setChecked(font.underline());
829 strikeoutCheckBox()->setChecked(font.strikeOut());
830 }
831
832 _q_updateSample();
833}
834
835QT_END_NAMESPACE
836
837#include "moc_qquickfontdialogimpl_p.cpp"
838

source code of qtdeclarative/src/quickdialogs/quickdialogsquickimpl/qquickfontdialogimpl.cpp