1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 1999 Reginald Stadlbauer <reggie@kde.org> |
4 | SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org> |
5 | SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org> |
6 | SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org> |
7 | SPDX-FileCopyrightText: 2000 Michael Koch <koch@kde.org> |
8 | SPDX-FileCopyrightText: 2001 Holger Freyther <freyther@kde.org> |
9 | SPDX-FileCopyrightText: 2002 Ellis Whitehead <ellis@kde.org> |
10 | SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org> |
11 | SPDX-FileCopyrightText: 2003 Andras Mantia <amantia@kde.org> |
12 | SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org> |
13 | SPDX-FileCopyrightText: 2007 Clarence Dang <dang@kde.org> |
14 | |
15 | SPDX-License-Identifier: LGPL-2.0-only |
16 | */ |
17 | |
18 | #include "kfontaction.h" |
19 | |
20 | #include "kselectaction_p.h" |
21 | |
22 | #include <QFontComboBox> |
23 | |
24 | #include <kfontchooser.h> |
25 | |
26 | class KFontActionPrivate : public KSelectActionPrivate |
27 | { |
28 | Q_DECLARE_PUBLIC(KFontAction) |
29 | |
30 | public: |
31 | KFontActionPrivate(KFontAction *qq) |
32 | : KSelectActionPrivate(qq) |
33 | { |
34 | } |
35 | |
36 | void slotFontChanged(const QFont &font) |
37 | { |
38 | Q_Q(KFontAction); |
39 | |
40 | // qCDebug(KWidgetsAddonsLog) << "QFontComboBox - slotFontChanged(" |
41 | // << font.family() << ") settingFont=" << settingFont; |
42 | if (settingFont) { |
43 | return; |
44 | } |
45 | |
46 | const QString fontFamily = font.family(); |
47 | q->setFont(fontFamily); |
48 | Q_EMIT q->textTriggered(text: fontFamily); |
49 | |
50 | // qCDebug(KWidgetsAddonsLog) << "\tslotFontChanged done"; |
51 | } |
52 | |
53 | int settingFont = 0; |
54 | QFontComboBox::FontFilters fontFilters = QFontComboBox::AllFonts; |
55 | }; |
56 | |
57 | QStringList fontList(const QFontComboBox::FontFilters &fontFilters = QFontComboBox::AllFonts) |
58 | { |
59 | QStringList families; |
60 | if (fontFilters == QFontComboBox::AllFonts) { |
61 | families = QFontDatabase::families(); |
62 | } else { |
63 | const QFontComboBox::FontFilters scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts); |
64 | const QFontComboBox::FontFilters spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts); |
65 | |
66 | const auto allFamilies = QFontDatabase::families(); |
67 | for (const QString &family : allFamilies) { |
68 | if ((fontFilters & scalableMask) && (fontFilters & scalableMask) != scalableMask) { |
69 | if (bool(fontFilters & QFontComboBox::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family)) { |
70 | continue; |
71 | } |
72 | } |
73 | if ((fontFilters & spacingMask) && (fontFilters & spacingMask) != spacingMask) { |
74 | if (bool(fontFilters & QFontComboBox::MonospacedFonts) != QFontDatabase::isFixedPitch(family)) { |
75 | continue; |
76 | } |
77 | } |
78 | |
79 | families << family; |
80 | } |
81 | } |
82 | |
83 | families.sort(); |
84 | return families; |
85 | } |
86 | |
87 | KFontAction::KFontAction(uint fontListCriteria, QObject *parent) |
88 | : KSelectAction(*new KFontActionPrivate(this), parent) |
89 | { |
90 | Q_D(KFontAction); |
91 | |
92 | if (fontListCriteria & KFontChooser::FixedWidthFonts) { |
93 | d->fontFilters |= QFontComboBox::MonospacedFonts; |
94 | } |
95 | |
96 | if (fontListCriteria & KFontChooser::SmoothScalableFonts) { |
97 | d->fontFilters |= QFontComboBox::ScalableFonts; |
98 | } |
99 | |
100 | KSelectAction::setItems(fontList(fontFilters: d->fontFilters)); |
101 | setEditable(true); |
102 | } |
103 | |
104 | KFontAction::KFontAction(QObject *parent) |
105 | : KSelectAction(*new KFontActionPrivate(this), parent) |
106 | { |
107 | KSelectAction::setItems(fontList()); |
108 | setEditable(true); |
109 | } |
110 | |
111 | KFontAction::KFontAction(const QString &text, QObject *parent) |
112 | : KSelectAction(*new KFontActionPrivate(this), parent) |
113 | { |
114 | setText(text); |
115 | KSelectAction::setItems(fontList()); |
116 | setEditable(true); |
117 | } |
118 | |
119 | KFontAction::KFontAction(const QIcon &icon, const QString &text, QObject *parent) |
120 | : KSelectAction(*new KFontActionPrivate(this), parent) |
121 | { |
122 | setIcon(icon); |
123 | setText(text); |
124 | KSelectAction::setItems(fontList()); |
125 | setEditable(true); |
126 | } |
127 | |
128 | KFontAction::~KFontAction() = default; |
129 | |
130 | QString KFontAction::font() const |
131 | { |
132 | return currentText(); |
133 | } |
134 | |
135 | QWidget *KFontAction::createWidget(QWidget *parent) |
136 | { |
137 | Q_D(KFontAction); |
138 | |
139 | // qCDebug(KWidgetsAddonsLog) << "KFontAction::createWidget()"; |
140 | |
141 | // This is the visual element on the screen. This method overrides |
142 | // the KSelectAction one, preventing KSelectAction from creating its |
143 | // regular KComboBox. |
144 | QFontComboBox *cb = new QFontComboBox(parent); |
145 | cb->setFontFilters(d->fontFilters); |
146 | |
147 | // qCDebug(KWidgetsAddonsLog) << "\tset=" << font(); |
148 | // Do this before connecting the signal so that nothing will fire. |
149 | cb->setCurrentFont(QFont(font().toLower())); |
150 | // qCDebug(KWidgetsAddonsLog) << "\tspit back=" << cb->currentFont().family(); |
151 | |
152 | connect(sender: cb, signal: &QFontComboBox::currentFontChanged, context: this, slot: [this](const QFont &ft) { |
153 | Q_D(KFontAction); |
154 | d->slotFontChanged(font: ft); |
155 | }); |
156 | cb->setMinimumWidth(cb->sizeHint().width()); |
157 | return cb; |
158 | } |
159 | |
160 | /* |
161 | * Maintenance note: Keep in sync with QFontComboBox::setCurrentFont() |
162 | */ |
163 | void KFontAction::setFont(const QString &family) |
164 | { |
165 | Q_D(KFontAction); |
166 | |
167 | // qCDebug(KWidgetsAddonsLog) << "KFontAction::setFont(" << family << ")"; |
168 | |
169 | // Suppress triggered(QString) signal and prevent recursive call to ourself. |
170 | d->settingFont++; |
171 | |
172 | const auto createdWidgets = this->createdWidgets(); |
173 | for (QWidget *w : createdWidgets) { |
174 | QFontComboBox *cb = qobject_cast<QFontComboBox *>(object: w); |
175 | // qCDebug(KWidgetsAddonsLog) << "\tw=" << w << "cb=" << cb; |
176 | |
177 | if (!cb) { |
178 | continue; |
179 | } |
180 | |
181 | cb->setCurrentFont(QFont(family.toLower())); |
182 | // qCDebug(KWidgetsAddonsLog) << "\t\tw spit back=" << cb->currentFont().family(); |
183 | } |
184 | |
185 | d->settingFont--; |
186 | |
187 | // qCDebug(KWidgetsAddonsLog) << "\tcalling setCurrentAction()"; |
188 | |
189 | QString lowerName = family.toLower(); |
190 | if (setCurrentAction(text: lowerName, cs: Qt::CaseInsensitive)) { |
191 | return; |
192 | } |
193 | |
194 | int i = lowerName.indexOf(s: QLatin1String(" [" )); |
195 | if (i > -1) { |
196 | lowerName.truncate(pos: i); |
197 | i = 0; |
198 | if (setCurrentAction(text: lowerName, cs: Qt::CaseInsensitive)) { |
199 | return; |
200 | } |
201 | } |
202 | |
203 | lowerName += QLatin1String(" [" ); |
204 | if (setCurrentAction(text: lowerName, cs: Qt::CaseInsensitive)) { |
205 | return; |
206 | } |
207 | |
208 | // TODO: Inconsistent state if QFontComboBox::setCurrentFont() succeeded |
209 | // but setCurrentAction() did not and vice-versa. |
210 | // qCDebug(KWidgetsAddonsLog) << "Font not found " << family.toLower(); |
211 | } |
212 | |
213 | #include "moc_kfontaction.cpp" |
214 | |