File indexing completed on 2024-04-28 03:59:05

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org>
0004     SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
0005     SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
0006     SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org>
0007     SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org>
0008     SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org>
0009     SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org>
0010     SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org>
0011     SPDX-FileCopyrightText: 2003 Andras Mantia <amantia@kde.org>
0012     SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org>
0013     SPDX-FileCopyrightText: 2007 Clarence Dang <dang@kde.org>
0014 
0015     SPDX-License-Identifier: LGPL-2.0-only
0016 */
0017 
0018 #include "kfontaction.h"
0019 
0020 #include "kselectaction_p.h"
0021 
0022 #include <QFontComboBox>
0023 
0024 #include <kfontchooser.h>
0025 
0026 class KFontActionPrivate : public KSelectActionPrivate
0027 {
0028     Q_DECLARE_PUBLIC(KFontAction)
0029 
0030 public:
0031     KFontActionPrivate(KFontAction *qq)
0032         : KSelectActionPrivate(qq)
0033     {
0034     }
0035 
0036     void slotFontChanged(const QFont &font)
0037     {
0038         Q_Q(KFontAction);
0039 
0040         //        qCDebug(KWidgetsAddonsLog) << "QFontComboBox - slotFontChanged("
0041         //                 << font.family() << ") settingFont=" << settingFont;
0042         if (settingFont) {
0043             return;
0044         }
0045 
0046         const QString fontFamily = font.family();
0047         q->setFont(fontFamily);
0048         Q_EMIT q->textTriggered(fontFamily);
0049 
0050         //        qCDebug(KWidgetsAddonsLog) << "\tslotFontChanged done";
0051     }
0052 
0053     int settingFont = 0;
0054     QFontComboBox::FontFilters fontFilters = QFontComboBox::AllFonts;
0055 };
0056 
0057 QStringList fontList(const QFontComboBox::FontFilters &fontFilters = QFontComboBox::AllFonts)
0058 {
0059     QStringList families;
0060     if (fontFilters == QFontComboBox::AllFonts) {
0061         families = QFontDatabase::families();
0062     } else {
0063         const QFontComboBox::FontFilters scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
0064         const QFontComboBox::FontFilters spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
0065 
0066         const auto allFamilies = QFontDatabase::families();
0067         for (const QString &family : allFamilies) {
0068             if ((fontFilters & scalableMask) && (fontFilters & scalableMask) != scalableMask) {
0069                 if (bool(fontFilters & QFontComboBox::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family)) {
0070                     continue;
0071                 }
0072             }
0073             if ((fontFilters & spacingMask) && (fontFilters & spacingMask) != spacingMask) {
0074                 if (bool(fontFilters & QFontComboBox::MonospacedFonts) != QFontDatabase::isFixedPitch(family)) {
0075                     continue;
0076                 }
0077             }
0078 
0079             families << family;
0080         }
0081     }
0082 
0083     families.sort();
0084     return families;
0085 }
0086 
0087 KFontAction::KFontAction(uint fontListCriteria, QObject *parent)
0088     : KSelectAction(*new KFontActionPrivate(this), parent)
0089 {
0090     Q_D(KFontAction);
0091 
0092     if (fontListCriteria & KFontChooser::FixedWidthFonts) {
0093         d->fontFilters |= QFontComboBox::MonospacedFonts;
0094     }
0095 
0096     if (fontListCriteria & KFontChooser::SmoothScalableFonts) {
0097         d->fontFilters |= QFontComboBox::ScalableFonts;
0098     }
0099 
0100     KSelectAction::setItems(fontList(d->fontFilters));
0101     setEditable(true);
0102 }
0103 
0104 KFontAction::KFontAction(QObject *parent)
0105     : KSelectAction(*new KFontActionPrivate(this), parent)
0106 {
0107     KSelectAction::setItems(fontList());
0108     setEditable(true);
0109 }
0110 
0111 KFontAction::KFontAction(const QString &text, QObject *parent)
0112     : KSelectAction(*new KFontActionPrivate(this), parent)
0113 {
0114     setText(text);
0115     KSelectAction::setItems(fontList());
0116     setEditable(true);
0117 }
0118 
0119 KFontAction::KFontAction(const QIcon &icon, const QString &text, QObject *parent)
0120     : KSelectAction(*new KFontActionPrivate(this), parent)
0121 {
0122     setIcon(icon);
0123     setText(text);
0124     KSelectAction::setItems(fontList());
0125     setEditable(true);
0126 }
0127 
0128 KFontAction::~KFontAction() = default;
0129 
0130 QString KFontAction::font() const
0131 {
0132     return currentText();
0133 }
0134 
0135 QWidget *KFontAction::createWidget(QWidget *parent)
0136 {
0137     Q_D(KFontAction);
0138 
0139     //    qCDebug(KWidgetsAddonsLog) << "KFontAction::createWidget()";
0140 
0141     // This is the visual element on the screen.  This method overrides
0142     // the KSelectAction one, preventing KSelectAction from creating its
0143     // regular KComboBox.
0144     QFontComboBox *cb = new QFontComboBox(parent);
0145     cb->setFontFilters(d->fontFilters);
0146 
0147     //    qCDebug(KWidgetsAddonsLog) << "\tset=" << font();
0148     // Do this before connecting the signal so that nothing will fire.
0149     cb->setCurrentFont(QFont(font().toLower()));
0150     //    qCDebug(KWidgetsAddonsLog) << "\tspit back=" << cb->currentFont().family();
0151 
0152     connect(cb, &QFontComboBox::currentFontChanged, this, [this](const QFont &ft) {
0153         Q_D(KFontAction);
0154         d->slotFontChanged(ft);
0155     });
0156     cb->setMinimumWidth(cb->sizeHint().width());
0157     return cb;
0158 }
0159 
0160 /*
0161  * Maintenance note: Keep in sync with QFontComboBox::setCurrentFont()
0162  */
0163 void KFontAction::setFont(const QString &family)
0164 {
0165     Q_D(KFontAction);
0166 
0167     //    qCDebug(KWidgetsAddonsLog) << "KFontAction::setFont(" << family << ")";
0168 
0169     // Suppress triggered(QString) signal and prevent recursive call to ourself.
0170     d->settingFont++;
0171 
0172     const auto createdWidgets = this->createdWidgets();
0173     for (QWidget *w : createdWidgets) {
0174         QFontComboBox *cb = qobject_cast<QFontComboBox *>(w);
0175         //        qCDebug(KWidgetsAddonsLog) << "\tw=" << w << "cb=" << cb;
0176 
0177         if (!cb) {
0178             continue;
0179         }
0180 
0181         cb->setCurrentFont(QFont(family.toLower()));
0182         //        qCDebug(KWidgetsAddonsLog) << "\t\tw spit back=" << cb->currentFont().family();
0183     }
0184 
0185     d->settingFont--;
0186 
0187     //    qCDebug(KWidgetsAddonsLog) << "\tcalling setCurrentAction()";
0188 
0189     QString lowerName = family.toLower();
0190     if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0191         return;
0192     }
0193 
0194     int i = lowerName.indexOf(QLatin1String(" ["));
0195     if (i > -1) {
0196         lowerName.truncate(i);
0197         i = 0;
0198         if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0199             return;
0200         }
0201     }
0202 
0203     lowerName += QLatin1String(" [");
0204     if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0205         return;
0206     }
0207 
0208     // TODO: Inconsistent state if QFontComboBox::setCurrentFont() succeeded
0209     //       but setCurrentAction() did not and vice-versa.
0210     //    qCDebug(KWidgetsAddonsLog) << "Font not found " << family.toLower();
0211 }
0212 
0213 #include "moc_kfontaction.cpp"