7#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
8#include <private/qfontdatabase_p.h>
10#include <QRegularExpression>
14Q_STATIC_LOGGING_CATEGORY(lcAttachedProperty,
"qt.quick.dialogs.quickfontdialogimpl.attachedOrWarn")
16QQuickFontDialogImplPrivate::QQuickFontDialogImplPrivate()
22 Q_Q(QQuickFontDialogImpl);
23 QQuickFontDialogImplAttached *attached =
static_cast<QQuickFontDialogImplAttached *>(
24 qmlAttachedPropertiesObject<QQuickFontDialogImpl>(q));
26 qCWarning(lcAttachedProperty)
27 <<
"Expected FontDialogImpl attached object to be present on" <<
this;
36 Q_Q(QQuickFontDialogImpl);
37 if (buttonRole(button) == QPlatformDialogHelper::AcceptRole) {
39 QQuickDialogPrivate::handleClick(button);
43QQuickFontDialogImpl::QQuickFontDialogImpl(QObject *parent)
44 : QQuickDialog(*(
new QQuickFontDialogImplPrivate), parent)
46 setPopupType(QQuickPopup::Window);
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();
150QQuickFontDialogImplAttached::QQuickFontDialogImplAttached(QObject *parent)
151 : QObject(*(
new QQuickFontDialogImplAttachedPrivate), parent),
152 m_writingSystem(QFontDatabase::Any),
154 m_smoothlyScalable(
false),
155 m_ignoreFamilyUpdate(
false),
156 m_ignoreStyleUpdate(
false)
158 if (!qobject_cast<QQuickFontDialogImpl *>(parent)) {
159 qmlWarning(
this) <<
"FontDialogImpl attached properties should only be "
160 <<
"accessed through the root FileDialogImpl instance";
164QQuickListView *QQuickFontDialogImplAttached::familyListView()
const
166 Q_D(
const QQuickFontDialogImplAttached);
167 return d->familyListView;
170void QQuickFontDialogImplAttached::setFamilyListView(QQuickListView *familyListView)
172 Q_D(QQuickFontDialogImplAttached);
173 if (d->familyListView == familyListView)
176 if (d->familyListView) {
177 disconnect(d->familyListView, &QQuickListView::currentIndexChanged,
178 this, &QQuickFontDialogImplAttached::_q_familyChanged);
181 d->familyListView = familyListView;
183 if (familyListView) {
184 connect(d->familyListView, &QQuickListView::currentIndexChanged,
185 this, &QQuickFontDialogImplAttached::_q_familyChanged);
188 emit familyListViewChanged();
191QQuickListView *QQuickFontDialogImplAttached::styleListView()
const
193 Q_D(
const QQuickFontDialogImplAttached);
194 return d->styleListView;
197void QQuickFontDialogImplAttached::setStyleListView(QQuickListView *styleListView)
199 Q_D(QQuickFontDialogImplAttached);
200 if (d->styleListView == styleListView)
203 if (d->styleListView) {
204 disconnect(d->styleListView, &QQuickListView::currentIndexChanged,
205 this, &QQuickFontDialogImplAttached::_q_styleChanged);
208 d->styleListView = styleListView;
211 connect(d->styleListView, &QQuickListView::currentIndexChanged,
212 this, &QQuickFontDialogImplAttached::_q_styleChanged);
215 emit styleListViewChanged();
218QQuickListView *QQuickFontDialogImplAttached::sizeListView()
const
220 Q_D(
const QQuickFontDialogImplAttached);
221 return d->sizeListView;
224void QQuickFontDialogImplAttached::setSizeListView(QQuickListView *sizeListView)
226 Q_D(QQuickFontDialogImplAttached);
227 if (d->sizeListView == sizeListView)
230 if (d->sizeListView) {
231 disconnect(d->sizeListView, &QQuickListView::currentIndexChanged,
232 this, &QQuickFontDialogImplAttached::_q_sizeChanged);
235 d->sizeListView = sizeListView;
237 if (d->sizeListView) {
238 connect(d->sizeListView, &QQuickListView::currentIndexChanged,
239 this, &QQuickFontDialogImplAttached::_q_sizeChanged);
242 emit sizeListViewChanged();
245QQuickTextEdit *QQuickFontDialogImplAttached::sampleEdit()
const
247 Q_D(
const QQuickFontDialogImplAttached);
248 return d->sampleEdit;
251void QQuickFontDialogImplAttached::setSampleEdit(QQuickTextEdit *sampleEdit)
253 Q_D(QQuickFontDialogImplAttached);
255 if (d->sampleEdit == sampleEdit)
259 QObjectPrivate::disconnect(d->sampleEdit, &QQuickTextEdit::fontChanged,
260 d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
263 d->sampleEdit = sampleEdit;
266 QObjectPrivate::connect(d->sampleEdit, &QQuickTextEdit::fontChanged,
267 d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged);
269 d->sampleEdit->setText(QFontDatabase::writingSystemSample(m_writingSystem));
272 emit sampleEditChanged();
275QQuickDialogButtonBox *QQuickFontDialogImplAttached::buttonBox()
const
277 Q_D(
const QQuickFontDialogImplAttached);
281void QQuickFontDialogImplAttached::setButtonBox(QQuickDialogButtonBox *buttonBox)
283 Q_D(QQuickFontDialogImplAttached);
284 if (buttonBox == d->buttonBox)
288 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent());
289 if (fontDialogImpl) {
290 auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl);
291 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::accepted,
292 dialogPrivate, &QQuickDialogPrivate::handleAccept);
293 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::rejected,
294 dialogPrivate, &QQuickDialogPrivate::handleReject);
295 QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
296 &QQuickDialogPrivate::handleClick);
300 d->buttonBox = buttonBox;
303 QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent());
304 if (fontDialogImpl) {
305 auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl);
306 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::accepted, dialogPrivate,
307 &QQuickDialogPrivate::handleAccept);
308 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::rejected, dialogPrivate,
309 &QQuickDialogPrivate::handleReject);
310 QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::clicked, dialogPrivate,
311 &QQuickDialogPrivate::handleClick);
315 emit buttonBoxChanged();
318QQuickComboBox *QQuickFontDialogImplAttached::writingSystemComboBox()
const
320 Q_D(
const QQuickFontDialogImplAttached);
321 return d->writingSystemComboBox;
324void QQuickFontDialogImplAttached::setWritingSystemComboBox(QQuickComboBox *writingSystemComboBox)
326 Q_D(QQuickFontDialogImplAttached);
328 if (d->writingSystemComboBox == writingSystemComboBox)
331 if (d->writingSystemComboBox) {
332 disconnect(d->writingSystemComboBox, &QQuickComboBox::activated,
333 this, &QQuickFontDialogImplAttached::_q_writingSystemChanged);
336 d->writingSystemComboBox = writingSystemComboBox;
338 if (d->writingSystemComboBox) {
339 QStringList writingSystemModel;
340 for (
int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
341 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
342 QString wsName = QFontDatabase::writingSystemName(ws);
343 if (wsName.isEmpty())
345 writingSystemModel.append(wsName);
348 d->writingSystemComboBox->setModel(writingSystemModel);
350 connect(d->writingSystemComboBox, &QQuickComboBox::activated,
351 this, &QQuickFontDialogImplAttached::_q_writingSystemChanged);
354 emit writingSystemComboBoxChanged();
357QQuickCheckBox *QQuickFontDialogImplAttached::underlineCheckBox()
const
359 Q_D(
const QQuickFontDialogImplAttached);
360 return d->underlineCheckBox;
363void QQuickFontDialogImplAttached::setUnderlineCheckBox(QQuickCheckBox *underlineCheckBox)
365 Q_D(QQuickFontDialogImplAttached);
367 if (d->underlineCheckBox == underlineCheckBox)
370 if (d->underlineCheckBox) {
371 disconnect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged,
372 this, &QQuickFontDialogImplAttached::_q_updateSample);
375 d->underlineCheckBox = underlineCheckBox;
377 if (d->underlineCheckBox) {
378 connect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged,
379 this, &QQuickFontDialogImplAttached::_q_updateSample);
382 emit underlineCheckBoxChanged();
385QQuickCheckBox *QQuickFontDialogImplAttached::strikeoutCheckBox()
const
387 Q_D(
const QQuickFontDialogImplAttached);
388 return d->strikeoutCheckBox;
391void QQuickFontDialogImplAttached::setStrikeoutCheckBox(QQuickCheckBox *strikeoutCheckBox)
393 Q_D(QQuickFontDialogImplAttached);
395 if (d->strikeoutCheckBox == strikeoutCheckBox)
398 if (d->strikeoutCheckBox) {
399 disconnect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged,
400 this, &QQuickFontDialogImplAttached::_q_updateSample);
403 d->strikeoutCheckBox = strikeoutCheckBox;
405 if (d->strikeoutCheckBox) {
406 connect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged,
407 this, &QQuickFontDialogImplAttached::_q_updateSample);
410 emit strikeoutCheckBoxChanged();
413QQuickTextField *QQuickFontDialogImplAttached::familyEdit()
const
415 Q_D(
const QQuickFontDialogImplAttached);
416 return d->familyEdit;
419void QQuickFontDialogImplAttached::setFamilyEdit(QQuickTextField *familyEdit)
421 Q_D(QQuickFontDialogImplAttached);
423 if (d->familyEdit == familyEdit)
426 d->familyEdit = familyEdit;
428 emit familyEditChanged();
431QQuickTextField *QQuickFontDialogImplAttached::styleEdit()
const
433 Q_D(
const QQuickFontDialogImplAttached);
437void QQuickFontDialogImplAttached::setStyleEdit(QQuickTextField *styleEdit)
439 Q_D(QQuickFontDialogImplAttached);
441 if (d->styleEdit == styleEdit)
444 d->styleEdit = styleEdit;
446 emit styleEditChanged();
449QQuickTextField *QQuickFontDialogImplAttached::sizeEdit()
const
451 Q_D(
const QQuickFontDialogImplAttached);
455void QQuickFontDialogImplAttached::setSizeEdit(QQuickTextField *sizeEdit)
457 Q_D(QQuickFontDialogImplAttached);
459 if (d->sizeEdit == sizeEdit)
463 disconnect(d->sizeEdit, &QQuickTextField::textChanged,
464 this, &QQuickFontDialogImplAttached::_q_sizeEdited);
467 d->sizeEdit = sizeEdit;
470 connect(d->sizeEdit, &QQuickTextField::textChanged,
471 this, &QQuickFontDialogImplAttached::_q_sizeEdited);
474 emit sizeEditChanged();
479 enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
480 QString foundryName1, familyName1, foundryName2, familyName2;
481 int bestFamilyMatch = -1;
482 match_t bestFamilyType = MATCH_NONE;
485 QFontDatabasePrivate::parseFontName(selectedFamily, foundryName1, familyName1);
488 for (
auto it = model.constBegin(); it != model.constEnd(); ++it, ++i) {
489 QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2);
491 if (familyName1 == familyName2) {
492 bestFamilyType = MATCH_FAMILY;
493 if (foundryName1 == foundryName2)
500 match_t type = MATCH_NONE;
501 if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral(
"helvetica"))
502 type = MATCH_LAST_RESORT;
503 if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().constFirst())
505 if (type != MATCH_NONE) {
506 bestFamilyType = type;
511 return bestFamilyMatch;
519 if (!selectedStyle.isEmpty()) {
520 const int idx = model.indexOf(QRegularExpression(QRegularExpression::escape(selectedStyle), QRegularExpression::CaseInsensitiveOption));
524 enum class StyleClass {Unknown, Normal, Italic};
525 auto classifyStyleFallback = [](
const QString & style) {
526 if (style.toLower() == QLatin1String(
"italic") || style.toLower() == QLatin1String(
"oblique"))
527 return StyleClass::Italic;
528 if (style.toLower() == QLatin1String(
"normal") || style.toLower() == QLatin1String(
"regular"))
529 return StyleClass::Normal;
530 return StyleClass::Unknown;
533 auto styleClass = classifyStyleFallback(selectedStyle);
535 if (styleClass != StyleClass::Unknown)
536 for (
int i = 0; i < model.size(); ++i)
537 if (classifyStyleFallback(model.at(i)) == styleClass)
544
545
546
547
548
549void QQuickFontDialogImplAttached::updateFamilies()
551 const QFontDialogOptions::FontDialogOptions scalableMask(
552 QFontDialogOptions::ScalableFonts | QFontDialogOptions::NonScalableFonts);
554 const QFontDialogOptions::FontDialogOptions spacingMask(QFontDialogOptions::ProportionalFonts
555 | QFontDialogOptions::MonospacedFonts);
557 const auto p = qobject_cast<QQuickFontDialogImpl *>(parent());
559 const auto options = p->options()->options();
561 QStringList familyNames;
562 const auto families = QFontDatabase::families(m_writingSystem);
563 for (
const auto &family : families) {
564 if (QFontDatabase::isPrivateFamily(family))
567 if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
568 if (
bool(options & QFontDialogOptions::ScalableFonts)
569 != QFontDatabase::isSmoothlyScalable(family))
573 if ((options & spacingMask) && (options & scalableMask) != spacingMask) {
574 if (
bool(options & QFontDialogOptions::MonospacedFonts)
575 != QFontDatabase::isFixedPitch(family))
579 familyNames << family;
582 auto listView = familyListView();
585 m_ignoreFamilyUpdate = !m_selectedFamily.isEmpty();
586 listView->setModel(familyNames);
587 m_ignoreFamilyUpdate =
false;
590 listView->setCurrentIndex(findFamilyInModel(m_selectedFamily, familyNames));
592 if (familyNames.isEmpty())
597
598
599
600
601
602
603
604void QQuickFontDialogImplAttached::updateStyles()
606 const QString family = familyListView()->currentIndex() >= 0 ? m_selectedFamily : QString();
607 const QStringList styles = QFontDatabase::styles(family);
609 auto listView = styleListView();
611 m_ignoreStyleUpdate = !m_selectedStyle.isEmpty();
612 listView->setModel(styles);
614 if (styles.isEmpty()) {
615 styleEdit()->clear();
616 m_smoothlyScalable =
false;
618 int newIndex = findStyleInModel(m_selectedStyle, styles);
620 listView->setCurrentIndex(newIndex);
622 m_selectedStyle = styles.at(newIndex);
623 styleEdit()->setText(m_selectedStyle);
625 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(m_selectedFamily, m_selectedStyle);
628 m_ignoreStyleUpdate =
false;
634
635
636
637
638
639void QQuickFontDialogImplAttached::updateSizes()
641 if (!m_selectedFamily.isEmpty()) {
642 const QList<
int> sizes = QFontDatabase::pointSizes(m_selectedFamily, m_selectedStyle);
644 QStringList str_sizes;
646 str_sizes.reserve(sizes.size());
648 int idx = 0, current = -1;
649 for (QList<
int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); it++) {
650 str_sizes.append(QString::number(*it));
651 if (current == -1 && m_selectedSize == *it) {
657 auto listView = sizeListView();
660 listView->setModel(str_sizes);
663 listView->setCurrentIndex(current);
665 sizeEdit()->setText(!m_smoothlyScalable && listView->currentIndex() > 0
666 ? str_sizes.at(listView->currentIndex())
667 : QString::number(m_selectedSize));
669 qCWarning(lcAttachedProperty) <<
"Warning! selectedFamily is empty";
676void QQuickFontDialogImplAttached::_q_updateSample()
678 if (m_selectedFamily.isEmpty())
681 const int pSize = sizeEdit()->text().toInt();
683 QFont newFont = QFontDatabase::font(m_selectedFamily, m_selectedStyle, pSize);
685 newFont.setUnderline(underlineCheckBox()->isChecked());
686 newFont.setStrikeOut(strikeoutCheckBox()->isChecked());
688 sampleEdit()->setFont(newFont);
691void QQuickFontDialogImplAttached::_q_writingSystemChanged(
int index)
693 m_writingSystem = QFontDatabase::WritingSystem(index);
694 sampleEdit()->setText(QFontDatabase::writingSystemSample(m_writingSystem));
699void QQuickFontDialogImplAttached::searchListView(
const QString &s, QQuickListView *listView)
704 const QStringList model = listView->model().toStringList();
711 for (
int i = 0; i < model.size(); ++i) {
712 if (model.at(i).startsWith(m_search, Qt::CaseInsensitive)) {
713 listView->setCurrentIndex(i);
724void QQuickFontDialogImplAttached::clearSearch()
729void QQuickFontDialogImplAttached::_q_familyChanged()
731 if (m_ignoreFamilyUpdate)
734 const int index = familyListView()->currentIndex();
737 familyEdit()->clear();
739 m_selectedFamily = familyListView()->model().toStringList().at(index);
740 familyEdit()->setText(m_selectedFamily);
746void QQuickFontDialogImplAttached::_q_styleChanged()
748 if (m_ignoreStyleUpdate)
751 const int index = styleListView()->currentIndex();
754 qCWarning(lcAttachedProperty) <<
"currentIndex changed to -1";
758 m_selectedStyle = styleListView()->model().toStringList().at(index);
759 styleEdit()->setText(m_selectedStyle);
760 m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(m_selectedFamily, m_selectedStyle);
765void QQuickFontDialogImplAttached::_q_sizeEdited()
767 const int size = qAbs(sizeEdit()->text().toInt());
769 if (size == m_selectedSize)
772 m_selectedSize = size;
774 if (sizeListView()->count()) {
775 auto model = sizeListView()->model().toStringList();
778 for (i = 0; i < model.size() - 1; ++i) {
779 if (model.at(i).toInt() >= size)
783 QSignalBlocker blocker(sizeListView());
784 if (model.at(i).toInt() == size)
785 sizeListView()->setCurrentIndex(i);
787 sizeListView()->setCurrentIndex(-1);
793void QQuickFontDialogImplAttached::_q_sizeChanged()
795 const int index = sizeListView()->currentIndex();
798 qCWarning(lcAttachedProperty) <<
"currentIndex changed to -1";
802 const QString s = sizeListView()->model().toStringList().at(index);
803 m_selectedSize = s.toInt();
805 sizeEdit()->setText(s);
812 auto fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent);
814 if (!fontDialogImpl) {
818 fontDialogImpl->setCurrentFont(font);
821void QQuickFontDialogImplAttached::selectFontInListViews(
const QFont &font)
824 QSignalBlocker blocker(sampleEdit());
825 familyListView()->setCurrentIndex(findFamilyInModel(font.families().constFirst(), familyListView()->model().toStringList()));
826 styleListView()->setCurrentIndex(findStyleInModel(QFontDatabase::styleString(font), styleListView()->model().toStringList()));
827 sizeEdit()->setText(QString::number(font.pointSize()));
829 underlineCheckBox()->setChecked(font.underline());
830 strikeoutCheckBox()->setChecked(font.strikeOut());
838#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)