8#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
9#include <private/qfontdatabase_p.h>
11#include <QRegularExpression>
15Q_STATIC_LOGGING_CATEGORY(lcAttachedProperty,
"qt.quick.dialogs.quickfontdialogimpl.attachedOrWarn")
17QQuickFontDialogImplPrivate::QQuickFontDialogImplPrivate()
23 Q_Q(QQuickFontDialogImpl);
24 QQuickFontDialogImplAttached *attached =
static_cast<QQuickFontDialogImplAttached *>(
25 qmlAttachedPropertiesObject<QQuickFontDialogImpl>(q));
27 qCWarning(lcAttachedProperty)
28 <<
"Expected FontDialogImpl attached object to be present on" <<
this;
37 Q_Q(QQuickFontDialogImpl);
38 if (buttonRole(button) == QPlatformDialogHelper::AcceptRole) {
40 QQuickDialogPrivate::handleClick(button);
44QQuickFontDialogImpl::QQuickFontDialogImpl(QObject *parent)
45 : QQuickDialog(*(
new QQuickFontDialogImplPrivate), parent)
49QQuickFontDialogImplAttached *QQuickFontDialogImpl::qmlAttachedProperties(QObject *object)
51 return new QQuickFontDialogImplAttached(object);
54QSharedPointer<QFontDialogOptions> QQuickFontDialogImpl::options()
const
56 Q_D(
const QQuickFontDialogImpl);
61void QQuickFontDialogImpl::setOptions(
const QSharedPointer<QFontDialogOptions> &options)
63 Q_D(QQuickFontDialogImpl);
65 if (options == d->options)
70 emit optionsChanged();
73QFont QQuickFontDialogImpl::currentFont()
const
75 Q_D(
const QQuickFontDialogImpl);
76 return d->currentFont;
79void QQuickFontDialogImpl::setCurrentFont(
const QFont &font,
bool selectInListViews)
81 Q_D(QQuickFontDialogImpl);
83 if (font == d->currentFont)
86 d->currentFont = font;
88 emit currentFontChanged(font);
90 if (!selectInListViews)
93 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
97 if (!attached->familyListView()->model().isValid()) {
98 const QSignalBlocker blocker(attached->sampleEdit());
99 attached->updateFamilies();
102 attached->selectFontInListViews(font);
105void QQuickFontDialogImpl::init()
107 Q_D(QQuickFontDialogImpl);
108 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
112 if (!attached->familyListView()->model().isValid())
113 attached->updateFamilies();
115 attached->buttonBox()->setVisible(!(options()->options() & QFontDialogOptions::NoButtons));
118void QQuickFontDialogImpl::keyReleaseEvent(QKeyEvent *event)
120 Q_D(QQuickFontDialogImpl);
122 QQuickDialog::keyReleaseEvent(event);
124 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
131 if (attached->familyEdit()->hasFocus())
132 attached->searchFamily(event->text());
133 else if (attached->styleEdit()->hasFocus())
134 attached->searchStyle(event->text());
137void QQuickFontDialogImpl::focusOutEvent(QFocusEvent *event)
139 Q_D(QQuickFontDialogImpl);
141 QQuickDialog::focusOutEvent(event);
143 QQuickFontDialogImplAttached *attached = d->attachedOrWarn();
147 attached->clearSearch();
150void QQuickFontDialogImpl::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
152 Q_D(QQuickFontDialogImpl);
153 QQuickDialog::itemChange(change, data);
155 if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue)
158 if (QQuickFontDialogImplAttached *attached = d->attachedOrWarn(); attached && attached->buttonBox())
159 attached->buttonBox()->forceActiveFocus(Qt::OtherFocusReason);
162QQuickFontDialogImplAttached::QQuickFontDialogImplAttached(QObject *parent)
163 : QObject(*(
new QQuickFontDialogImplAttachedPrivate), parent),
164 m_writingSystem(QFontDatabase::Any),
166 m_smoothlyScalable(
false),
167 m_ignoreFamilyUpdate(
false),
168 m_ignoreStyleUpdate(
false)
170 if (!qobject_cast<QQuickFontDialogImpl *>(parent)) {
171 qmlWarning(
this) <<
"FontDialogImpl attached properties should only be "
172 <<
"accessed through the root FileDialogImpl instance";
176QQuickListView *QQuickFontDialogImplAttached::familyListView()
const
178 Q_D(
const QQuickFontDialogImplAttached);
179 return d->familyListView;
182void QQuickFontDialogImplAttached::setFamilyListView(QQuickListView *familyListView)
184 Q_D(QQuickFontDialogImplAttached);
185 if (d->familyListView == familyListView)
188 if (d->familyListView) {
189 disconnect(d->familyListView, &QQuickListView::currentIndexChanged,
190 this, &QQuickFontDialogImplAttached::_q_familyChanged);
193 d->familyListView = familyListView;
195 if (familyListView) {
196 connect(d->familyListView, &QQuickListView::currentIndexChanged,
197 this, &QQuickFontDialogImplAttached::_q_familyChanged);
200 emit familyListViewChanged();
203QQuickListView *QQuickFontDialogImplAttached::styleListView()
const
205 Q_D(
const QQuickFontDialogImplAttached);
206 return d->styleListView;
209void QQuickFontDialogImplAttached::setStyleListView(QQuickListView *styleListView)
211 Q_D(QQuickFontDialogImplAttached);
212 if (d->styleListView == styleListView)
215 if (d->styleListView) {
216 disconnect(d->styleListView, &QQuickListView::currentIndexChanged,
217 this, &QQuickFontDialogImplAttached::_q_styleChanged);
220 d->styleListView = styleListView;
223 connect(d->styleListView, &QQuickListView::currentIndexChanged,
224 this, &QQuickFontDialogImplAttached::_q_styleChanged);
227 emit styleListViewChanged();
230QQuickListView *QQuickFontDialogImplAttached::sizeListView()
const
232 Q_D(
const QQuickFontDialogImplAttached);
233 return d->sizeListView;
236void QQuickFontDialogImplAttached::setSizeListView(QQuickListView *sizeListView)
238 Q_D(QQuickFontDialogImplAttached);
239 if (d->sizeListView == sizeListView)
242 if (d->sizeListView) {
243 disconnect(d->sizeListView, &QQuickListView::currentIndexChanged,
244 this, &QQuickFontDialogImplAttached::_q_sizeChanged);
247 d->sizeListView = sizeListView;
249 if (d->sizeListView) {
250 connect(d->sizeListView, &QQuickListView::currentIndexChanged,
251 this, &QQuickFontDialogImplAttached::_q_sizeChanged);
254 emit sizeListViewChanged();
257QQuickTextEdit *QQuickFontDialogImplAttached::sampleEdit()
const
259 Q_D(
const QQuickFontDialogImplAttached);
260 return d->sampleEdit;
263void QQuickFontDialogImplAttached::setSampleEdit(QQuickTextEdit *sampleEdit)
265 Q_D(QQuickFontDialogImplAttached);
267 if (d->sampleEdit == sampleEdit)
271 QObjectPrivate::disconnect(d->sampleEdit, &QQuickTextEdit::fontChanged,
272 d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
275 d->sampleEdit = sampleEdit;
278 QObjectPrivate::connect(d->sampleEdit, &QQuickTextEdit::fontChanged,
279 d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
281 d->sampleEdit->setText(QFontDatabase::writingSystemSample(m_writingSystem));
284 emit sampleEditChanged();
287QQuickDialogButtonBox *QQuickFontDialogImplAttached::buttonBox()
const
289 Q_D(
const QQuickFontDialogImplAttached);
293void QQuickFontDialogImplAttached::setButtonBox(QQuickDialogButtonBox *buttonBox)
295 Q_D(QQuickFontDialogImplAttached);
296 if (buttonBox == d->buttonBox)
300 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent());
301 if (fontDialogImpl) {
302 auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl);
303 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::accepted,
304 dialogPrivate, &QQuickDialogPrivate::handleAccept);
305 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::rejected,
306 dialogPrivate, &QQuickDialogPrivate::handleReject);
307 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
308 &QQuickDialogPrivate::handleClick);
312 d->buttonBox = buttonBox;
315 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent());
316 if (fontDialogImpl) {
317 auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl);
318 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::accepted, dialogPrivate,
319 &QQuickDialogPrivate::handleAccept);
320 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::rejected, dialogPrivate,
321 &QQuickDialogPrivate::handleReject);
322 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
323 &QQuickDialogPrivate::handleClick);
327 emit buttonBoxChanged();
330QQuickComboBox *QQuickFontDialogImplAttached::writingSystemComboBox()
const
332 Q_D(
const QQuickFontDialogImplAttached);
333 return d->writingSystemComboBox;
336void QQuickFontDialogImplAttached::setWritingSystemComboBox(QQuickComboBox *writingSystemComboBox)
338 Q_D(QQuickFontDialogImplAttached);
340 if (d->writingSystemComboBox == writingSystemComboBox)
343 if (d->writingSystemComboBox) {
344 disconnect(d->writingSystemComboBox, &QQuickComboBox::activated,
345 this, &QQuickFontDialogImplAttached::_q_writingSystemChanged);
348 d->writingSystemComboBox = writingSystemComboBox;
350 if (d->writingSystemComboBox) {
351 QStringList writingSystemModel;
352 for (
int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
353 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
354 QString wsName = QFontDatabase::writingSystemName(ws);
355 if (wsName.isEmpty())
357 writingSystemModel.append(wsName);
360 d->writingSystemComboBox->setModel(writingSystemModel);
362 connect(d->writingSystemComboBox, &QQuickComboBox::activated,
363 this, &QQuickFontDialogImplAttached::_q_writingSystemChanged);
366 emit writingSystemComboBoxChanged();
369QQuickCheckBox *QQuickFontDialogImplAttached::underlineCheckBox()
const
371 Q_D(
const QQuickFontDialogImplAttached);
372 return d->underlineCheckBox;
375void QQuickFontDialogImplAttached::setUnderlineCheckBox(QQuickCheckBox *underlineCheckBox)
377 Q_D(QQuickFontDialogImplAttached);
379 if (d->underlineCheckBox == underlineCheckBox)
382 if (d->underlineCheckBox) {
383 disconnect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged,
384 this, &QQuickFontDialogImplAttached::_q_updateSample);
387 d->underlineCheckBox = underlineCheckBox;
389 if (d->underlineCheckBox) {
390 connect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged,
391 this, &QQuickFontDialogImplAttached::_q_updateSample);
394 emit underlineCheckBoxChanged();
397QQuickCheckBox *QQuickFontDialogImplAttached::strikeoutCheckBox()
const
399 Q_D(
const QQuickFontDialogImplAttached);
400 return d->strikeoutCheckBox;
403void QQuickFontDialogImplAttached::setStrikeoutCheckBox(QQuickCheckBox *strikeoutCheckBox)
405 Q_D(QQuickFontDialogImplAttached);
407 if (d->strikeoutCheckBox == strikeoutCheckBox)
410 if (d->strikeoutCheckBox) {
411 disconnect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged,
412 this, &QQuickFontDialogImplAttached::_q_updateSample);
415 d->strikeoutCheckBox = strikeoutCheckBox;
417 if (d->strikeoutCheckBox) {
418 connect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged,
419 this, &QQuickFontDialogImplAttached::_q_updateSample);
422 emit strikeoutCheckBoxChanged();
425QQuickTextField *QQuickFontDialogImplAttached::familyEdit()
const
427 Q_D(
const QQuickFontDialogImplAttached);
428 return d->familyEdit;
431void QQuickFontDialogImplAttached::setFamilyEdit(QQuickTextField *familyEdit)
433 Q_D(QQuickFontDialogImplAttached);
435 if (d->familyEdit == familyEdit)
438 d->familyEdit = familyEdit;
440 emit familyEditChanged();
443QQuickTextField *QQuickFontDialogImplAttached::styleEdit()
const
445 Q_D(
const QQuickFontDialogImplAttached);
449void QQuickFontDialogImplAttached::setStyleEdit(QQuickTextField *styleEdit)
451 Q_D(QQuickFontDialogImplAttached);
453 if (d->styleEdit == styleEdit)
456 d->styleEdit = styleEdit;
458 emit styleEditChanged();
461QQuickTextField *QQuickFontDialogImplAttached::sizeEdit()
const
463 Q_D(
const QQuickFontDialogImplAttached);
467void QQuickFontDialogImplAttached::setSizeEdit(QQuickTextField *sizeEdit)
469 Q_D(QQuickFontDialogImplAttached);
471 if (d->sizeEdit == sizeEdit)
475 disconnect(d->sizeEdit, &QQuickTextField::textChanged,
476 this, &QQuickFontDialogImplAttached::_q_sizeEdited);
479 d->sizeEdit = sizeEdit;
482 connect(d->sizeEdit, &QQuickTextField::textChanged,
483 this, &QQuickFontDialogImplAttached::_q_sizeEdited);
486 emit sizeEditChanged();
491 enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
492 QString foundryName1, familyName1, foundryName2, familyName2;
493 int bestFamilyMatch = -1;
494 match_t bestFamilyType = MATCH_NONE;
497 QFontDatabasePrivate::parseFontName(selectedFamily, foundryName1, familyName1);
500 for (
auto it = model.constBegin(); it != model.constEnd(); ++it, ++i) {
501 QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2);
503 if (familyName1 == familyName2) {
504 bestFamilyType = MATCH_FAMILY;
505 if (foundryName1 == foundryName2)
512 match_t type = MATCH_NONE;
513 if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral(
"helvetica"))
514 type = MATCH_LAST_RESORT;
515 if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().constFirst())
517 if (type != MATCH_NONE) {
518 bestFamilyType = type;
523 return bestFamilyMatch;
531 if (!selectedStyle.isEmpty()) {
532 const int idx = model.indexOf(QRegularExpression(QRegularExpression::escape(selectedStyle), QRegularExpression::CaseInsensitiveOption));
536 enum class StyleClass {Unknown, Normal, Italic};
537 auto classifyStyleFallback = [](
const QString & style) {
538 if (style.toLower() == QLatin1String(
"italic") || style.toLower() == QLatin1String(
"oblique"))
539 return StyleClass::Italic;
540 if (style.toLower() == QLatin1String(
"normal") || style.toLower() == QLatin1String(
"regular"))
541 return StyleClass::Normal;
542 return StyleClass::Unknown;
545 auto styleClass = classifyStyleFallback(selectedStyle);
547 if (styleClass != StyleClass::Unknown)
548 for (
int i = 0; i < model.size(); ++i)
549 if (classifyStyleFallback(model.at(i)) == styleClass)
556
557
558
559
560
561void QQuickFontDialogImplAttached::updateFamilies()
563 const QFontDialogOptions::FontDialogOptions scalableMask(
564 QFontDialogOptions::ScalableFonts | QFontDialogOptions::NonScalableFonts);
566 const QFontDialogOptions::FontDialogOptions spacingMask(QFontDialogOptions::ProportionalFonts
567 | QFontDialogOptions::MonospacedFonts);
569 const auto p = qobject_cast<QQuickFontDialogImpl *>(parent());
571 const auto options = p->options()->options();
573 QStringList familyNames;
574 const auto families = QFontDatabase::families(m_writingSystem);
575 for (
const auto &family : families) {
576 if (QFontDatabase::isPrivateFamily(family))
579 if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
580 if (
bool(options & QFontDialogOptions::ScalableFonts)
581 != QFontDatabase::isSmoothlyScalable(family))
585 if ((options & spacingMask) && (options & scalableMask) != spacingMask) {
586 if (
bool(options & QFontDialogOptions::MonospacedFonts)
587 != QFontDatabase::isFixedPitch(family))
591 familyNames << family;
594 auto listView = familyListView();
597 m_ignoreFamilyUpdate = !m_selectedFamily.isEmpty();
598 listView->setModel(familyNames);
599 m_ignoreFamilyUpdate =
false;
602 listView->setCurrentIndex(findFamilyInModel(m_selectedFamily, familyNames));
604 if (familyNames.isEmpty())
609
610
611
612
613
614
615
616void QQuickFontDialogImplAttached::updateStyles()
618 const QString family = familyListView()->currentIndex() >= 0 ? m_selectedFamily : QString();
619 const QStringList styles = QFontDatabase::styles(family);
621 auto listView = styleListView();
623 m_ignoreStyleUpdate = !m_selectedStyle.isEmpty();
624 listView->setModel(styles);
626 if (styles.isEmpty()) {
627 styleEdit()->clear();
628 m_smoothlyScalable =
false;
630 int newIndex = findStyleInModel(m_selectedStyle, styles);
632 listView->setCurrentIndex(newIndex);
634 m_selectedStyle = styles.at(newIndex);
635 styleEdit()->setText(m_selectedStyle);
637 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(m_selectedFamily, m_selectedStyle);
640 m_ignoreStyleUpdate =
false;
646
647
648
649
650
651void QQuickFontDialogImplAttached::updateSizes()
653 if (!m_selectedFamily.isEmpty()) {
654 const QList<
int> sizes = QFontDatabase::pointSizes(m_selectedFamily, m_selectedStyle);
656 QStringList str_sizes;
658 str_sizes.reserve(sizes.size());
660 int idx = 0, current = -1;
661 for (QList<
int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); it++) {
662 str_sizes.append(QString::number(*it));
663 if (current == -1 && m_selectedSize == *it) {
669 auto listView = sizeListView();
672 listView->setModel(str_sizes);
675 listView->setCurrentIndex(current);
677 sizeEdit()->setText(!m_smoothlyScalable && listView->currentIndex() > 0
678 ? str_sizes.at(listView->currentIndex())
679 : QString::number(m_selectedSize));
681 qCWarning(lcAttachedProperty) <<
"Warning! selectedFamily is empty";
688void QQuickFontDialogImplAttached::_q_updateSample()
690 if (m_selectedFamily.isEmpty())
693 const int pSize = sizeEdit()->text().toInt();
695 QFont newFont = QFontDatabase::font(m_selectedFamily, m_selectedStyle, pSize);
697 newFont.setUnderline(underlineCheckBox()->isChecked());
698 newFont.setStrikeOut(strikeoutCheckBox()->isChecked());
700 sampleEdit()->setFont(newFont);
703void QQuickFontDialogImplAttached::_q_writingSystemChanged(
int index)
705 m_writingSystem = QFontDatabase::WritingSystem(index);
706 sampleEdit()->setText(QFontDatabase::writingSystemSample(m_writingSystem));
711void QQuickFontDialogImplAttached::searchListView(
const QString &s, QQuickListView *listView)
716 const QStringList model = listView->model().toStringList();
723 for (
int i = 0; i < model.size(); ++i) {
724 if (model.at(i).startsWith(m_search, Qt::CaseInsensitive)) {
725 listView->setCurrentIndex(i);
736void QQuickFontDialogImplAttached::clearSearch()
741void QQuickFontDialogImplAttached::_q_familyChanged()
743 if (m_ignoreFamilyUpdate)
746 const int index = familyListView()->currentIndex();
749 familyEdit()->clear();
751 m_selectedFamily = familyListView()->model().toStringList().at(index);
752 familyEdit()->setText(m_selectedFamily);
758void QQuickFontDialogImplAttached::_q_styleChanged()
760 if (m_ignoreStyleUpdate)
763 const int index = styleListView()->currentIndex();
766 qCWarning(lcAttachedProperty) <<
"currentIndex changed to -1";
770 m_selectedStyle = styleListView()->model().toStringList().at(index);
771 styleEdit()->setText(m_selectedStyle);
772 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(m_selectedFamily, m_selectedStyle);
777void QQuickFontDialogImplAttached::_q_sizeEdited()
779 const int size = qAbs(sizeEdit()->text().toInt());
781 if (size == m_selectedSize)
784 m_selectedSize = size;
786 if (sizeListView()->count()) {
787 auto model = sizeListView()->model().toStringList();
790 for (i = 0; i < model.size() - 1; ++i) {
791 if (model.at(i).toInt() >= size)
795 QSignalBlocker blocker(sizeListView());
796 if (model.at(i).toInt() == size)
797 sizeListView()->setCurrentIndex(i);
799 sizeListView()->setCurrentIndex(-1);
805void QQuickFontDialogImplAttached::_q_sizeChanged()
807 const int index = sizeListView()->currentIndex();
810 qCWarning(lcAttachedProperty) <<
"currentIndex changed to -1";
814 const QString s = sizeListView()->model().toStringList().at(index);
815 m_selectedSize = s.toInt();
817 sizeEdit()->setText(s);
824 auto fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent);
826 if (!fontDialogImpl) {
830 fontDialogImpl->setCurrentFont(font);
833void QQuickFontDialogImplAttached::selectFontInListViews(
const QFont &font)
836 QSignalBlocker blocker(sampleEdit());
837 familyListView()->setCurrentIndex(findFamilyInModel(font.families().constFirst(), familyListView()->model().toStringList()));
838 styleListView()->setCurrentIndex(findStyleInModel(QFontDatabase::styleString(font), styleListView()->model().toStringList()));
839 sizeEdit()->setText(QString::number(font.pointSize()));
841 underlineCheckBox()->setChecked(font.underline());
842 strikeoutCheckBox()->setChecked(font.strikeOut());
850#include "moc_qquickfontdialogimpl_p.cpp"
void handleClick(QQuickAbstractButton *button) override
void handleAccept() override
QQuickFontDialogImplAttached * attachedOrWarn()
Combined button and popup list for selecting options.
static int findFamilyInModel(const QString &selectedFamily, const QStringList &model)
static int findStyleInModel(const QString &selectedStyle, const QStringList &model)