File indexing completed on 2024-04-28 15:32:02

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 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 78)
0049         Q_EMIT q->triggered(fontFamily);
0050 #endif
0051         Q_EMIT q->textTriggered(fontFamily);
0052 
0053         //        qCDebug(KWidgetsAddonsLog) << "\tslotFontChanged done";
0054     }
0055 
0056     int settingFont = 0;
0057     QFontComboBox::FontFilters fontFilters = QFontComboBox::AllFonts;
0058 };
0059 
0060 QStringList fontList(const QFontComboBox::FontFilters &fontFilters = QFontComboBox::AllFonts)
0061 {
0062     QFontDatabase dbase;
0063 
0064     QStringList families;
0065     if (fontFilters == QFontComboBox::AllFonts) {
0066         families = dbase.families();
0067     } else {
0068         const QFontComboBox::FontFilters scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
0069         const QFontComboBox::FontFilters spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
0070 
0071         const auto allFamilies = dbase.families();
0072         for (const QString &family : allFamilies) {
0073             if ((fontFilters & scalableMask) && (fontFilters & scalableMask) != scalableMask) {
0074                 if (bool(fontFilters & QFontComboBox::ScalableFonts) != dbase.isSmoothlyScalable(family)) {
0075                     continue;
0076                 }
0077             }
0078             if ((fontFilters & spacingMask) && (fontFilters & spacingMask) != spacingMask) {
0079                 if (bool(fontFilters & QFontComboBox::MonospacedFonts) != dbase.isFixedPitch(family)) {
0080                     continue;
0081                 }
0082             }
0083 
0084             families << family;
0085         }
0086     }
0087 
0088     families.sort();
0089     return families;
0090 }
0091 
0092 KFontAction::KFontAction(uint fontListCriteria, QObject *parent)
0093     : KSelectAction(*new KFontActionPrivate(this), parent)
0094 {
0095     Q_D(KFontAction);
0096 
0097     if (fontListCriteria & KFontChooser::FixedWidthFonts) {
0098         d->fontFilters |= QFontComboBox::MonospacedFonts;
0099     }
0100 
0101     if (fontListCriteria & KFontChooser::SmoothScalableFonts) {
0102         d->fontFilters |= QFontComboBox::ScalableFonts;
0103     }
0104 
0105     KSelectAction::setItems(fontList(d->fontFilters));
0106     setEditable(true);
0107 }
0108 
0109 KFontAction::KFontAction(QObject *parent)
0110     : KSelectAction(*new KFontActionPrivate(this), parent)
0111 {
0112     KSelectAction::setItems(fontList());
0113     setEditable(true);
0114 }
0115 
0116 KFontAction::KFontAction(const QString &text, QObject *parent)
0117     : KSelectAction(*new KFontActionPrivate(this), parent)
0118 {
0119     setText(text);
0120     KSelectAction::setItems(fontList());
0121     setEditable(true);
0122 }
0123 
0124 KFontAction::KFontAction(const QIcon &icon, const QString &text, QObject *parent)
0125     : KSelectAction(*new KFontActionPrivate(this), parent)
0126 {
0127     setIcon(icon);
0128     setText(text);
0129     KSelectAction::setItems(fontList());
0130     setEditable(true);
0131 }
0132 
0133 KFontAction::~KFontAction() = default;
0134 
0135 QString KFontAction::font() const
0136 {
0137     return currentText();
0138 }
0139 
0140 QWidget *KFontAction::createWidget(QWidget *parent)
0141 {
0142     Q_D(KFontAction);
0143 
0144     //    qCDebug(KWidgetsAddonsLog) << "KFontAction::createWidget()";
0145 
0146     // This is the visual element on the screen.  This method overrides
0147     // the KSelectAction one, preventing KSelectAction from creating its
0148     // regular KComboBox.
0149     QFontComboBox *cb = new QFontComboBox(parent);
0150     cb->setFontFilters(d->fontFilters);
0151 
0152     //    qCDebug(KWidgetsAddonsLog) << "\tset=" << font();
0153     // Do this before connecting the signal so that nothing will fire.
0154     cb->setCurrentFont(QFont(font().toLower()));
0155     //    qCDebug(KWidgetsAddonsLog) << "\tspit back=" << cb->currentFont().family();
0156 
0157     connect(cb, &QFontComboBox::currentFontChanged, this, [this](const QFont &ft) {
0158         Q_D(KFontAction);
0159         d->slotFontChanged(ft);
0160     });
0161     cb->setMinimumWidth(cb->sizeHint().width());
0162     return cb;
0163 }
0164 
0165 /*
0166  * Maintenance note: Keep in sync with QFontComboBox::setCurrentFont()
0167  */
0168 void KFontAction::setFont(const QString &family)
0169 {
0170     Q_D(KFontAction);
0171 
0172     //    qCDebug(KWidgetsAddonsLog) << "KFontAction::setFont(" << family << ")";
0173 
0174     // Suppress triggered(QString) signal and prevent recursive call to ourself.
0175     d->settingFont++;
0176 
0177     const auto createdWidgets = this->createdWidgets();
0178     for (QWidget *w : createdWidgets) {
0179         QFontComboBox *cb = qobject_cast<QFontComboBox *>(w);
0180         //        qCDebug(KWidgetsAddonsLog) << "\tw=" << w << "cb=" << cb;
0181 
0182         if (!cb) {
0183             continue;
0184         }
0185 
0186         cb->setCurrentFont(QFont(family.toLower()));
0187         //        qCDebug(KWidgetsAddonsLog) << "\t\tw spit back=" << cb->currentFont().family();
0188     }
0189 
0190     d->settingFont--;
0191 
0192     //    qCDebug(KWidgetsAddonsLog) << "\tcalling setCurrentAction()";
0193 
0194     QString lowerName = family.toLower();
0195     if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0196         return;
0197     }
0198 
0199     int i = lowerName.indexOf(QLatin1String(" ["));
0200     if (i > -1) {
0201         lowerName.truncate(i);
0202         i = 0;
0203         if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0204             return;
0205         }
0206     }
0207 
0208     lowerName += QLatin1String(" [");
0209     if (setCurrentAction(lowerName, Qt::CaseInsensitive)) {
0210         return;
0211     }
0212 
0213     // TODO: Inconsistent state if QFontComboBox::setCurrentFont() succeeded
0214     //       but setCurrentAction() did not and vice-versa.
0215     //    qCDebug(KWidgetsAddonsLog) << "Font not found " << family.toLower();
0216 }
0217 
0218 #include "moc_kfontaction.cpp"