Changeset View
Changeset View
Standalone View
Standalone View
kcms/fonts/fonts.cpp
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | Copyright 1997 Mark Donohoe | 2 | Copyright 1997 Mark Donohoe | ||
3 | Copyright 1999 Lars Knoll | 3 | Copyright 1999 Lars Knoll | ||
4 | Copyright 2000 Rik Hemsley | 4 | Copyright 2000 Rik Hemsley | ||
5 | Copyright 2015 Antonis Tsiapaliokas <antonis.tsiapaliokas@kde.org> | ||||
6 | Copyright 2017 Marco Martin <mart@kde.org> | ||||
5 | 7 | | |||
6 | Ported to kcontrol2 by Geert Jansen. | 8 | Ported to kcontrol2 by Geert Jansen. | ||
7 | 9 | | |||
8 | This library is free software; you can redistribute it and/or | 10 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Library General Public | 11 | modify it under the terms of the GNU Library General Public | ||
10 | License as published by the Free Software Foundation; either | 12 | License as published by the Free Software Foundation; either | ||
11 | version 2 of the License, or (at your option) any later version. | 13 | version 2 of the License, or (at your option) any later version. | ||
12 | 14 | | |||
13 | This library is distributed in the hope that it will be useful, | 15 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Library General Public License for more details. | 18 | Library General Public License for more details. | ||
17 | 19 | | |||
18 | You should have received a copy of the GNU Library General Public License | 20 | You should have received a copy of the GNU Library General Public License | ||
19 | along with this library; see the file COPYING.LIB. If not, write to | 21 | along with this library; see the file COPYING.LIB. If not, write to | ||
20 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 22 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
21 | Boston, MA 02110-1301, USA. | 23 | Boston, MA 02110-1301, USA. | ||
22 | */ | 24 | */ | ||
23 | 25 | | |||
24 | #include <config-workspace.h> | | |||
25 | 26 | | |||
26 | #include "fonts.h" | 27 | #include "fonts.h" | ||
27 | 28 | | |||
28 | #include <stdlib.h> | 29 | #include <QQuickItem> | ||
29 | 30 | #include <QWindow> | |||
31 | #include <QQmlEngine> | ||||
32 | #include <QQuickView> | ||||
33 | #include <QDebug> | ||||
34 | #include <QFontDialog> | ||||
30 | #include <QApplication> | 35 | #include <QApplication> | ||
31 | #include <QCheckBox> | 36 | #include <QFontDatabase> | ||
32 | #include <QComboBox> | | |||
33 | #include <QDialogButtonBox> | | |||
34 | #include <QDoubleSpinBox> | | |||
35 | #include <QLabel> | | |||
36 | #include <QProcess> | | |||
37 | #include <QPushButton> | | |||
38 | #include <QSpinBox> | | |||
39 | #include <qplatformdefs.h> | | |||
40 | | ||||
41 | //Added by qt3to4: | | |||
42 | #include <QPixmap> | | |||
43 | #include <QByteArray> | | |||
44 | #include <QGridLayout> | | |||
45 | #include <QHBoxLayout> | | |||
46 | #include <QVBoxLayout> | | |||
47 | #include <QFormLayout> | | |||
48 | 37 | | |||
49 | #include <KFontDialog> | | |||
50 | #include <KAcceleratorManager> | 38 | #include <KAcceleratorManager> | ||
51 | #include <KGlobalSettings> | 39 | #include <KGlobalSettings> | ||
52 | #include <KMessageBox> | | |||
53 | #include <KConfig> | | |||
54 | #include <KConfigGroup> | 40 | #include <KConfigGroup> | ||
41 | #include <KConfig> | ||||
42 | #include <KAboutData> | ||||
55 | #include <KLocalizedString> | 43 | #include <KLocalizedString> | ||
56 | #include <KPluginFactory> | 44 | #include <KPluginFactory> | ||
45 | #include <KFontDialog> | ||||
57 | #include <KWindowSystem> | 46 | #include <KWindowSystem> | ||
47 | #include <KMessageBox> | ||||
58 | 48 | | |||
59 | #include "../krdb/krdb.h" | 49 | #include "../krdb/krdb.h" | ||
60 | 50 | | |||
61 | #ifdef HAVE_FREETYPE | | |||
62 | #include <ft2build.h> | | |||
63 | #ifdef FT_LCD_FILTER_H | | |||
64 | #include FT_FREETYPE_H | | |||
65 | #include FT_LCD_FILTER_H | | |||
66 | #endif | | |||
67 | #endif | | |||
68 | | ||||
69 | #if HAVE_X11 | | |||
70 | #include <X11/Xlib.h> | | |||
71 | #endif | | |||
72 | | ||||
73 | #if HAVE_X11 | | |||
74 | // X11 headers | | |||
75 | #undef Bool | | |||
76 | #undef Unsorted | | |||
77 | #undef None | | |||
78 | #endif | | |||
79 | | ||||
80 | static const char *const aa_rgb_xpm[] = { | | |||
81 | "12 12 3 1", | | |||
82 | "a c #0000ff", | | |||
83 | "# c #00ff00", | | |||
84 | ". c #ff0000", | | |||
85 | "....####aaaa", | | |||
86 | "....####aaaa", | | |||
87 | "....####aaaa", | | |||
88 | "....####aaaa", | | |||
89 | "....####aaaa", | | |||
90 | "....####aaaa", | | |||
91 | "....####aaaa", | | |||
92 | "....####aaaa", | | |||
93 | "....####aaaa", | | |||
94 | "....####aaaa", | | |||
95 | "....####aaaa", | | |||
96 | "....####aaaa" | | |||
97 | }; | | |||
98 | static const char *const aa_bgr_xpm[] = { | | |||
99 | "12 12 3 1", | | |||
100 | ". c #0000ff", | | |||
101 | "# c #00ff00", | | |||
102 | "a c #ff0000", | | |||
103 | "....####aaaa", | | |||
104 | "....####aaaa", | | |||
105 | "....####aaaa", | | |||
106 | "....####aaaa", | | |||
107 | "....####aaaa", | | |||
108 | "....####aaaa", | | |||
109 | "....####aaaa", | | |||
110 | "....####aaaa", | | |||
111 | "....####aaaa", | | |||
112 | "....####aaaa", | | |||
113 | "....####aaaa", | | |||
114 | "....####aaaa" | | |||
115 | }; | | |||
116 | static const char *const aa_vrgb_xpm[] = { | | |||
117 | "12 12 3 1", | | |||
118 | "a c #0000ff", | | |||
119 | "# c #00ff00", | | |||
120 | ". c #ff0000", | | |||
121 | "............", | | |||
122 | "............", | | |||
123 | "............", | | |||
124 | "............", | | |||
125 | "############", | | |||
126 | "############", | | |||
127 | "############", | | |||
128 | "############", | | |||
129 | "aaaaaaaaaaaa", | | |||
130 | "aaaaaaaaaaaa", | | |||
131 | "aaaaaaaaaaaa", | | |||
132 | "aaaaaaaaaaaa" | | |||
133 | }; | | |||
134 | static const char *const aa_vbgr_xpm[] = { | | |||
135 | "12 12 3 1", | | |||
136 | ". c #0000ff", | | |||
137 | "# c #00ff00", | | |||
138 | "a c #ff0000", | | |||
139 | "............", | | |||
140 | "............", | | |||
141 | "............", | | |||
142 | "............", | | |||
143 | "############", | | |||
144 | "############", | | |||
145 | "############", | | |||
146 | "############", | | |||
147 | "aaaaaaaaaaaa", | | |||
148 | "aaaaaaaaaaaa", | | |||
149 | "aaaaaaaaaaaa", | | |||
150 | "aaaaaaaaaaaa" | | |||
151 | }; | | |||
152 | | ||||
153 | static const char *const *const aaPixmaps[] = { 0, 0, aa_rgb_xpm, aa_bgr_xpm, aa_vrgb_xpm, aa_vbgr_xpm }; | | |||
154 | | ||||
155 | /**** DLL Interface ****/ | 51 | /**** DLL Interface ****/ | ||
156 | K_PLUGIN_FACTORY(FontFactory, registerPlugin<KFonts>();) | 52 | K_PLUGIN_FACTORY_WITH_JSON(KFontsFactory, "kcm_fonts.json", registerPlugin<KFonts>();) | ||
157 | | ||||
158 | /**** FontUseItem ****/ | | |||
159 | | ||||
160 | FontUseItem::FontUseItem( | | |||
161 | QWidget *parent, | | |||
162 | const QString &name, | | |||
163 | const QString &grp, | | |||
164 | const QString &key, | | |||
165 | const QString &rc, | | |||
166 | const QFont &default_fnt, | | |||
167 | bool f | | |||
168 | ) | | |||
169 | : KFontRequester(parent, f), | | |||
170 | _rcfile(rc), | | |||
171 | _rcgroup(grp), | | |||
172 | _rckey(key), | | |||
173 | _default(default_fnt) | | |||
174 | { | | |||
175 | KAcceleratorManager::setNoAccel(this); | | |||
176 | setTitle(name); | | |||
177 | readFont(); | | |||
178 | } | | |||
179 | 53 | | |||
180 | void FontUseItem::setDefault() | 54 | //from KFontRequester | ||
55 | // Determine if the font with given properties is available on the system, | ||||
56 | // otherwise find and return the best fitting combination. | ||||
57 | static QFont nearestExistingFont(const QFont &font) | ||||
181 | { | 58 | { | ||
182 | setFont(_default, isFixedOnly()); | 59 | QFontDatabase dbase; | ||
183 | } | | |||
184 | 60 | | |||
185 | void FontUseItem::readFont() | 61 | // Initialize font data accoring to given font object. | ||
186 | { | 62 | QString family = font.family(); | ||
187 | const KConfig *config = KSharedConfig::openConfig(_rcfile).data(); | 63 | QString style = dbase.styleString(font); | ||
188 | const KConfigGroup group(config, _rcgroup); | 64 | qreal size = font.pointSizeF(); | ||
189 | QFont tmpFnt(_default); | | |||
190 | setFont(group.readEntry(_rckey, tmpFnt), isFixedOnly()); | | |||
191 | } | | |||
192 | 65 | | |||
193 | void FontUseItem::writeFont() | 66 | // Check if the family exists. | ||
194 | { | 67 | const QStringList families = dbase.families(); | ||
195 | KConfig *config = KSharedConfig::openConfig(_rcfile).data(); | 68 | if (!families.contains(family)) { | ||
196 | if (_rcfile.isEmpty()) { | 69 | // Chose another family. | ||
197 | KConfigGroup(config, _rcgroup).writeEntry(_rckey, font(), KConfig::Normal | KConfig::Global); | 70 | family = QFontInfo(font).family(); // the nearest match | ||
198 | } else { | 71 | if (!families.contains(family)) { | ||
199 | KConfigGroup(config, _rcgroup).writeEntry(_rckey, font()); | 72 | family = families.count() ? families.at(0) : QStringLiteral("fixed"); | ||
200 | config->sync(); | | |||
201 | } | 73 | } | ||
202 | } | 74 | } | ||
203 | 75 | | |||
204 | void FontUseItem::applyFontDiff(const QFont &fnt, int fontDiffFlags) | 76 | // Check if the family has the requested style. | ||
205 | { | 77 | // Easiest by piping it through font selection in the database. | ||
206 | QFont _font(font()); | 78 | QString retStyle = dbase.styleString(dbase.font(family, style, 10)); | ||
79 | style = retStyle; | ||||
207 | 80 | | |||
208 | if (fontDiffFlags & KFontChooser::FontDiffSize) { | 81 | // Check if the family has the requested size. | ||
209 | _font.setPointSizeF(fnt.pointSizeF()); | 82 | // Only for bitmap fonts. | ||
83 | if (!dbase.isSmoothlyScalable(family, style)) { | ||||
84 | QList<int> sizes = dbase.smoothSizes(family, style); | ||||
85 | if (!sizes.contains(size)) { | ||||
86 | // Find nearest available size. | ||||
87 | int mindiff = 1000; | ||||
88 | int refsize = size; | ||||
89 | Q_FOREACH (int lsize, sizes) { | ||||
90 | int diff = qAbs(refsize - lsize); | ||||
91 | if (mindiff > diff) { | ||||
92 | mindiff = diff; | ||||
93 | size = lsize; | ||||
210 | } | 94 | } | ||
211 | if (fontDiffFlags & KFontChooser::FontDiffFamily) { | | |||
212 | if (!isFixedOnly() || QFontInfo(fnt).fixedPitch()) { | | |||
213 | _font.setFamily(fnt.family()); | | |||
214 | } | 95 | } | ||
215 | } | 96 | } | ||
216 | if (fontDiffFlags & KFontChooser::FontDiffStyle) { | | |||
217 | _font.setWeight(fnt.weight()); | | |||
218 | _font.setStyle(fnt.style()); | | |||
219 | _font.setUnderline(fnt.underline()); | | |||
220 | #if QT_VERSION >= 0x040800 | | |||
221 | _font.setStyleName(fnt.styleName()); | | |||
222 | #endif | | |||
223 | } | 97 | } | ||
224 | 98 | | |||
225 | setFont(_font, isFixedOnly()); | 99 | // Select the font with confirmed properties. | ||
100 | QFont result = dbase.font(family, style, int(size)); | ||||
101 | if (dbase.isSmoothlyScalable(family, style) && result.pointSize() == floor(size)) { | ||||
102 | result.setPointSizeF(size); | ||||
103 | } | ||||
104 | return result; | ||||
226 | } | 105 | } | ||
227 | 106 | | |||
228 | /**** FontAASettings ****/ | 107 | /**** FontAASettings ****/ | ||
229 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 108 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | ||
230 | FontAASettings::FontAASettings(QWidget *parent) | 109 | FontAASettings::FontAASettings(QObject *parent) | ||
231 | : QDialog(parent), | 110 | : QObject(parent) | ||
232 | changesMade(false) | 111 | , m_subPixelOptionsModel(new QStandardItemModel(this)) | ||
233 | { | 112 | , m_hintingOptionsModel(new QStandardItemModel(this)) | ||
234 | setObjectName("FontAASettings"); | 113 | { | ||
235 | setModal(true); | | |||
236 | setWindowTitle(i18n("Configure Anti-Alias Settings")); | | |||
237 | | ||||
238 | QVBoxLayout *mainLayout = new QVBoxLayout(this); | | |||
239 | | ||||
240 | QFormLayout *layout = new QFormLayout(); | | |||
241 | layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); | | |||
242 | | ||||
243 | excludeRange = new QCheckBox(i18n("E&xclude range:"), this); | | |||
244 | QHBoxLayout *rangeLayout = new QHBoxLayout(); | | |||
245 | | ||||
246 | excludeFrom = new QDoubleSpinBox(this); | | |||
247 | excludeFrom->setRange(0.0, 72.0); | | |||
248 | excludeFrom->setValue(8.0); | | |||
249 | excludeFrom->setSingleStep(1.0); | | |||
250 | excludeFrom->setDecimals(1); | | |||
251 | excludeFrom->setSuffix(i18nc("abbreviation for unit of points", " pt")); | | |||
252 | rangeLayout->addWidget(excludeFrom); | | |||
253 | | ||||
254 | excludeToLabel = new QLabel(i18n(" to "), this); | | |||
255 | rangeLayout->addWidget(excludeToLabel); | | |||
256 | | ||||
257 | excludeTo = new QDoubleSpinBox(this); | | |||
258 | excludeTo->setRange(0.0, 72.0); | | |||
259 | excludeTo->setValue(15.0); | | |||
260 | excludeTo->setSingleStep(1.0); | | |||
261 | excludeTo->setDecimals(1); | | |||
262 | excludeTo->setSuffix(i18nc("abbreviation for unit of points", " pt")); | | |||
263 | rangeLayout->addWidget(excludeTo); | | |||
264 | | ||||
265 | layout->addRow(excludeRange, rangeLayout); | | |||
266 | | ||||
267 | QString subPixelWhatsThis = i18n("<p>If you have a TFT or LCD screen you" | | |||
268 | " can further improve the quality of displayed fonts by selecting" | | |||
269 | " this option.<br />Sub-pixel rendering is also known as ClearType(tm).<br />" | | |||
270 | " In order for sub-pixel rendering to" | | |||
271 | " work correctly you need to know how the sub-pixels of your display" | | |||
272 | " are aligned.</p>" | | |||
273 | " <p>On TFT or LCD displays a single pixel is actually composed of" | | |||
274 | " three sub-pixels, red, green and blue. Most displays" | | |||
275 | " have a linear ordering of RGB sub-pixel, some have BGR.<br />" | | |||
276 | " This feature does not work with CRT monitors.</p>"); | | |||
277 | | ||||
278 | subPixelLabel = new QLabel(i18n("Sub-pixel rendering type:"), this); | | |||
279 | subPixelLabel->setWhatsThis(subPixelWhatsThis); | | |||
280 | | ||||
281 | subPixelType = new QComboBox(this); | | |||
282 | layout->addRow(subPixelLabel, subPixelType); | | |||
283 | | ||||
284 | subPixelType->setEditable(false); | | |||
285 | subPixelType->setWhatsThis(subPixelWhatsThis); | | |||
286 | | ||||
287 | for (int t = KXftConfig::SubPixel::NotSet; t <= KXftConfig::SubPixel::Vbgr; ++t) { | 114 | for (int t = KXftConfig::SubPixel::NotSet; t <= KXftConfig::SubPixel::Vbgr; ++t) { | ||
288 | subPixelType->addItem(QPixmap(aaPixmaps[t]), i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8())); | 115 | QStandardItem *item = new QStandardItem(KXftConfig::description((KXftConfig::SubPixel::Type)t)); | ||
116 | m_subPixelOptionsModel->appendRow(item); | ||||
289 | } | 117 | } | ||
290 | 118 | | |||
291 | QLabel *hintingLabel = new QLabel(i18n("Hinting style:"), this); | | |||
292 | hintingStyle = new QComboBox(this); | | |||
293 | hintingStyle->setEditable(false); | | |||
294 | layout->addRow(hintingLabel, hintingStyle); | | |||
295 | for (int s = KXftConfig::Hint::NotSet; s <= KXftConfig::Hint::Full; ++s) { | 119 | for (int s = KXftConfig::Hint::NotSet; s <= KXftConfig::Hint::Full; ++s) { | ||
296 | hintingStyle->addItem(i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8())); | 120 | QStandardItem * item = new QStandardItem(KXftConfig::description((KXftConfig::Hint::Style)s)); | ||
121 | m_hintingOptionsModel->appendRow(item); | ||||
297 | } | 122 | } | ||
298 | | ||||
299 | QString hintingText(i18n("Hinting is a process used to enhance the quality of fonts at small sizes.")); | | |||
300 | hintingStyle->setWhatsThis(hintingText); | | |||
301 | hintingLabel->setWhatsThis(hintingText); | | |||
302 | load(); | | |||
303 | enableWidgets(); | | |||
304 | | ||||
305 | QHBoxLayout *outerLayout = new QHBoxLayout(); | | |||
306 | outerLayout->addLayout(layout); | | |||
307 | outerLayout->addStretch(1); | | |||
308 | | ||||
309 | mainLayout->addLayout(outerLayout); | | |||
310 | mainLayout->addStretch(1); | | |||
311 | mainLayout->addSpacing(style()->pixelMetric(QStyle::PM_LayoutBottomMargin)); | | |||
312 | | ||||
313 | QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, this); | | |||
314 | buttonBox->button(QDialogButtonBox::Ok)->setShortcut(Qt::CTRL|Qt::Key_Return); | | |||
315 | connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); | | |||
316 | connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); | | |||
317 | mainLayout->addWidget(buttonBox); | | |||
318 | | ||||
319 | connect(excludeRange, &QAbstractButton::toggled, this, &FontAASettings::changed); | | |||
320 | connect(excludeFrom, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), | | |||
321 | this, &FontAASettings::changed); | | |||
322 | connect(excludeTo, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), | | |||
323 | this, &FontAASettings::changed); | | |||
324 | connect(subPixelType, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated), | | |||
325 | this, &FontAASettings::changed); | | |||
326 | connect(hintingStyle, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated), | | |||
327 | this, &FontAASettings::changed); | | |||
328 | } | 123 | } | ||
329 | 124 | | |||
330 | bool FontAASettings::load() | 125 | void FontAASettings::load() | ||
331 | { | 126 | { | ||
332 | double from, to; | 127 | double from, to; | ||
333 | KXftConfig xft; | 128 | KXftConfig xft; | ||
334 | 129 | | |||
335 | if (xft.getExcludeRange(from, to)) { | 130 | if (xft.getExcludeRange(from, to)) { | ||
336 | excludeRange->setChecked(true); | 131 | m_excludeFrom = from; | ||
132 | m_excludeTo = to; | ||||
133 | setExclude(true); | ||||
337 | } else { | 134 | } else { | ||
338 | excludeRange->setChecked(false); | 135 | m_excludeFrom = 8; | ||
339 | from = 8.0; | 136 | m_excludeTo = 15; | ||
340 | to = 15.0; | 137 | setExclude(false); | ||
341 | } | 138 | } | ||
342 | 139 | excludeToChanged(); | |||
343 | excludeFrom->setValue(from); | 140 | excludeFromChanged(); | ||
344 | excludeTo->setValue(to); | | |||
345 | 141 | | |||
346 | KXftConfig::SubPixel::Type spType; | 142 | KXftConfig::SubPixel::Type spType; | ||
347 | | ||||
348 | xft.getSubPixelType(spType); | 143 | xft.getSubPixelType(spType); | ||
349 | int idx = getIndex(spType); | | |||
350 | 144 | | |||
351 | subPixelType->setCurrentIndex(idx); | 145 | setSubPixelCurrentIndex(spType); | ||
352 | 146 | | |||
353 | KXftConfig::Hint::Style hStyle; | 147 | KXftConfig::Hint::Style hStyle; | ||
354 | 148 | | |||
355 | if (!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet == hStyle) { | 149 | if (!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet == hStyle) { | ||
150 | KConfig kglobals("kdeglobals", KConfig::NoGlobals); | ||||
151 | | ||||
356 | hStyle = KXftConfig::Hint::NotSet; | 152 | hStyle = KXftConfig::Hint::NotSet; | ||
357 | xft.setHintStyle(hStyle); | 153 | xft.setHintStyle(hStyle); | ||
154 | KConfigGroup(&kglobals, "General").writeEntry("XftHintStyle", KXftConfig::toStr(hStyle)); | ||||
155 | kglobals.sync(); | ||||
358 | runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); | 156 | runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); | ||
359 | } | 157 | } | ||
360 | 158 | | |||
361 | hintingStyle->setCurrentIndex(getIndex(hStyle)); | 159 | setHintingCurrentIndex(hStyle); | ||
362 | 160 | | |||
363 | enableWidgets(); | 161 | KConfig _cfgfonts("kcmfonts"); | ||
162 | KConfigGroup cfgfonts(&_cfgfonts, "General"); | ||||
364 | 163 | | |||
365 | return xft.aliasingEnabled(); | 164 | int dpicfg; | ||
165 | if (KWindowSystem::isPlatformWayland()) { | ||||
166 | dpicfg = cfgfonts.readEntry("forceFontDPIWayland", 0); | ||||
167 | } else { | ||||
168 | dpicfg = cfgfonts.readEntry("forceFontDPI", 0); | ||||
169 | } | ||||
170 | | ||||
171 | if (dpicfg <= 0) { | ||||
172 | m_dpiOriginal = 0; | ||||
173 | } else { | ||||
174 | m_dpiOriginal = dpicfg; | ||||
175 | }; | ||||
176 | | ||||
177 | setDpi(dpicfg); | ||||
178 | | ||||
179 | KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); | ||||
180 | KConfigGroup cg(config, "General"); | ||||
181 | | ||||
182 | if (cfgfonts.readEntry("dontChangeAASettings", true)) { | ||||
183 | setAntiAliasing(1); //AASystem | ||||
184 | } else if (cg.readEntry("XftAntialias", true)) { | ||||
185 | setAntiAliasing(0); //AAEnabled | ||||
186 | } else { | ||||
187 | setAntiAliasing(2); //AADisabled | ||||
188 | } | ||||
189 | m_antiAliasingOriginal = m_antiAliasing; | ||||
366 | } | 190 | } | ||
367 | 191 | | |||
368 | bool FontAASettings::save(KXftConfig::AntiAliasing::State aaState) | 192 | bool FontAASettings::save(KXftConfig::AntiAliasing::State aaState) | ||
369 | { | 193 | { | ||
370 | KXftConfig xft; | 194 | KXftConfig xft; | ||
371 | KConfig kglobals("kdeglobals", KConfig::NoGlobals); | 195 | KConfig kglobals("kdeglobals", KConfig::NoGlobals); | ||
372 | KConfigGroup grp(&kglobals, "General"); | 196 | KConfigGroup grp(&kglobals, "General"); | ||
373 | 197 | | |||
374 | xft.setAntiAliasing(aaState); | 198 | xft.setAntiAliasing(aaState); | ||
375 | 199 | if (m_exclude) { | |||
376 | if (excludeRange->isChecked()) { | 200 | xft.setExcludeRange(m_excludeFrom, m_excludeTo); | ||
377 | xft.setExcludeRange(excludeFrom->value(), excludeTo->value()); | | |||
378 | } else { | 201 | } else { | ||
379 | xft.setExcludeRange(0, 0); | 202 | xft.setExcludeRange(0, 0); | ||
380 | } | 203 | } | ||
381 | 204 | | |||
382 | KXftConfig::SubPixel::Type spType(getSubPixelType()); | 205 | KXftConfig::SubPixel::Type spType = (KXftConfig::SubPixel::Type)m_subPixelCurrentIndex; | ||
383 | 206 | | |||
384 | xft.setSubPixelType(spType); | 207 | xft.setSubPixelType(spType); | ||
385 | if (KXftConfig::SubPixel::NotSet == spType) { | | |||
386 | grp.revertToDefault("XftSubPixel"); | | |||
387 | } else { | | |||
388 | grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType)); | 208 | grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType)); | ||
389 | } | 209 | if (aaState == KXftConfig::AntiAliasing::NotSet) { | ||
390 | | ||||
391 | if (KXftConfig::AntiAliasing::NotSet == aaState) { | | |||
392 | grp.revertToDefault("XftAntialias"); | 210 | grp.revertToDefault("XftAntialias"); | ||
393 | } else { | 211 | } else { | ||
394 | grp.writeEntry("XftAntialias", aaState == KXftConfig::AntiAliasing::Enabled); | 212 | grp.writeEntry("XftAntialias", aaState == KXftConfig::AntiAliasing::Enabled); | ||
395 | } | 213 | } | ||
396 | 214 | | |||
397 | bool mod = false; | 215 | bool mod = false; | ||
398 | KXftConfig::Hint::Style hStyle(getHintStyle()); | 216 | KXftConfig::Hint::Style hStyle = (KXftConfig::Hint::Style)m_hintingCurrentIndex; | ||
399 | 217 | | |||
400 | xft.setHintStyle(hStyle); | 218 | xft.setHintStyle(hStyle); | ||
401 | 219 | | |||
402 | QString hs(KXftConfig::toStr(hStyle)); | 220 | QString hs(KXftConfig::toStr(hStyle)); | ||
221 | | ||||
403 | if (hs != grp.readEntry("XftHintStyle")) { | 222 | if (hs != grp.readEntry("XftHintStyle")) { | ||
404 | if (KXftConfig::Hint::NotSet == hStyle) { | 223 | if (KXftConfig::Hint::NotSet == hStyle) { | ||
405 | grp.revertToDefault("XftHintStyle"); | 224 | grp.revertToDefault("XftHintStyle"); | ||
406 | } else { | 225 | } else { | ||
407 | grp.writeEntry("XftHintStyle", hs); | 226 | grp.writeEntry("XftHintStyle", hs); | ||
408 | } | 227 | } | ||
409 | } | 228 | } | ||
410 | mod = true; | 229 | mod = true; | ||
411 | kglobals.sync(); | 230 | kglobals.sync(); | ||
412 | 231 | | |||
413 | if (!mod) { | 232 | if (!mod) { | ||
414 | mod = xft.changed(); | 233 | mod = xft.changed(); | ||
415 | } | 234 | } | ||
416 | 235 | | |||
417 | xft.apply(); | 236 | xft.apply(); | ||
418 | 237 | | |||
238 | KConfig _cfgfonts("kcmfonts"); | ||||
239 | KConfigGroup cfgfonts(&_cfgfonts, "General"); | ||||
240 | | ||||
241 | if (KWindowSystem::isPlatformWayland()) { | ||||
242 | cfgfonts.writeEntry("forceFontDPIWayland", m_dpi); | ||||
243 | } else { | ||||
244 | cfgfonts.writeEntry("forceFontDPI", m_dpi); | ||||
245 | } | ||||
246 | | ||||
247 | cfgfonts.sync(); | ||||
248 | | ||||
249 | #if HAVE_X11 | ||||
250 | // if the setting is reset in the module, remove the dpi value, | ||||
251 | // otherwise don't explicitly remove it and leave any possible system-wide value | ||||
252 | if (m_dpi == 0 && m_dpiOriginal != 0 && !KWindowSystem::isPlatformWayland()) { | ||||
253 | QProcess proc; | ||||
254 | proc.setProcessChannelMode(QProcess::ForwardedChannels); | ||||
255 | proc.start("xrdb", QStringList() << "-quiet" << "-remove" << "-nocpp"); | ||||
256 | if (proc.waitForStarted()) { | ||||
257 | proc.write(QByteArray("Xft.dpi\n")); | ||||
258 | proc.closeWriteChannel(); | ||||
259 | proc.waitForFinished(); | ||||
260 | } | ||||
261 | } | ||||
262 | #endif | ||||
263 | | ||||
264 | QApplication::processEvents(); // Process font change ourselves | ||||
265 | | ||||
266 | // Don't overwrite global settings unless explicitly asked for - e.g. the system | ||||
267 | // fontconfig setup may be much more complex than this module can provide. | ||||
268 | // TODO: With AASystem the changes already made by this module should be reverted somehow. | ||||
269 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | ||||
270 | if (mod || (m_antiAliasing != m_antiAliasingOriginal) || m_dpi != m_dpiOriginal) { | ||||
271 | KMessageBox::information(0, | ||||
272 | i18n( | ||||
273 | "<p>Some changes such as anti-aliasing or DPI will only affect newly started applications.</p>" | ||||
274 | ), i18n("Font Settings Changed"), "FontSettingsChanged"); | ||||
275 | m_antiAliasingOriginal = m_antiAliasing; | ||||
276 | m_dpiOriginal = m_dpi; | ||||
277 | } | ||||
278 | #else | ||||
279 | #if HAVE_X11 | ||||
280 | if (m_dpi != m_dpiOriginal) { | ||||
281 | KMessageBox::information(0, | ||||
282 | i18n( | ||||
283 | "<p>Some changes such as DPI will only affect newly started applications.</p>" | ||||
284 | ), i18n("Font Settings Changed"), "FontSettingsChanged"); | ||||
285 | m_dpiOriginal = m_dpi; | ||||
286 | } | ||||
287 | #endif | ||||
288 | #endif | ||||
289 | | ||||
419 | return mod; | 290 | return mod; | ||
420 | } | 291 | } | ||
421 | 292 | | |||
422 | void FontAASettings::defaults() | 293 | void FontAASettings::defaults() | ||
423 | { | 294 | { | ||
424 | excludeRange->setChecked(false); | 295 | setExcludeTo(15); | ||
425 | excludeFrom->setValue(8.0); | 296 | setExcludeFrom(8); | ||
426 | excludeTo->setValue(15.0); | 297 | setAntiAliasing(1); | ||
427 | subPixelType->setCurrentIndex(getIndex(KXftConfig::SubPixel::NotSet)); | 298 | m_antiAliasingOriginal = m_antiAliasing; | ||
428 | hintingStyle->setCurrentIndex(getIndex(KXftConfig::Hint::NotSet)); | 299 | setDpi(96); | ||
429 | enableWidgets(); | 300 | setSubPixelCurrentIndex(KXftConfig::SubPixel::NotSet); | ||
301 | setHintingCurrentIndex(KXftConfig::Hint::NotSet); | ||||
430 | } | 302 | } | ||
431 | 303 | | |||
432 | int FontAASettings::getIndex(KXftConfig::SubPixel::Type spType) | 304 | #endif | ||
305 | | ||||
306 | void FontAASettings::setExclude(bool exclude) | ||||
433 | { | 307 | { | ||
434 | int pos = -1; | 308 | if (exclude == m_exclude) { | ||
435 | int index; | 309 | return; | ||
310 | } | ||||
436 | 311 | | |||
437 | for (index = 0; index < subPixelType->count(); ++index) | 312 | m_exclude = exclude; | ||
438 | if (subPixelType->itemText(index) == i18n(KXftConfig::description(spType).toUtf8())) { | 313 | emit excludeChanged(); | ||
439 | pos = index; | | |||
440 | break; | | |||
441 | } | 314 | } | ||
442 | 315 | | |||
443 | return pos; | 316 | bool FontAASettings::exclude() const | ||
317 | { | ||||
318 | return m_exclude; | ||||
444 | } | 319 | } | ||
445 | 320 | | |||
446 | KXftConfig::SubPixel::Type FontAASettings::getSubPixelType() | 321 | void FontAASettings::setExcludeTo(const int &excludeTo) | ||
447 | { | 322 | { | ||
448 | int t; | 323 | if (m_excludeTo == excludeTo) { | ||
324 | return; | ||||
325 | } | ||||
449 | 326 | | |||
450 | for (t = KXftConfig::SubPixel::NotSet; t <= KXftConfig::SubPixel::Vbgr; ++t) | 327 | m_excludeTo = excludeTo; | ||
451 | if (subPixelType->currentText() == i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8())) { | 328 | emit excludeToChanged(); | ||
452 | return (KXftConfig::SubPixel::Type)t; | | |||
453 | } | 329 | } | ||
454 | 330 | | |||
455 | return KXftConfig::SubPixel::NotSet; | 331 | int FontAASettings::excludeTo() const | ||
332 | { | ||||
333 | return m_excludeTo; | ||||
456 | } | 334 | } | ||
457 | 335 | | |||
458 | int FontAASettings::getIndex(KXftConfig::Hint::Style hStyle) | 336 | void FontAASettings::setExcludeFrom(const int &excludeTo) | ||
459 | { | 337 | { | ||
460 | int pos = -1; | 338 | if (m_excludeFrom == excludeTo) { | ||
461 | int index; | 339 | return; | ||
340 | } | ||||
462 | 341 | | |||
463 | for (index = 0; index < hintingStyle->count(); ++index) | 342 | m_excludeFrom = excludeTo; | ||
464 | if (hintingStyle->itemText(index) == i18n(KXftConfig::description(hStyle).toUtf8())) { | 343 | emit excludeToChanged(); | ||
465 | pos = index; | | |||
466 | break; | | |||
467 | } | 344 | } | ||
468 | 345 | | |||
469 | return pos; | 346 | int FontAASettings::excludeFrom() const | ||
347 | { | ||||
348 | return m_excludeFrom; | ||||
470 | } | 349 | } | ||
471 | 350 | | |||
472 | KXftConfig::Hint::Style FontAASettings::getHintStyle() | 351 | void FontAASettings::setAntiAliasing(const int &antiAliasing) | ||
473 | { | 352 | { | ||
474 | int s; | 353 | if (m_antiAliasing == antiAliasing) { | ||
354 | return; | ||||
355 | } | ||||
475 | 356 | | |||
476 | for (s = KXftConfig::Hint::NotSet; s <= KXftConfig::Hint::Full; ++s) | 357 | m_antiAliasing = antiAliasing; | ||
477 | if (hintingStyle->currentText() == i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8())) { | 358 | emit aliasingChanged(); | ||
478 | return (KXftConfig::Hint::Style)s; | | |||
479 | } | 359 | } | ||
480 | 360 | | |||
481 | return KXftConfig::Hint::Medium; | 361 | int FontAASettings::antiAliasing() const | ||
362 | { | ||||
363 | return m_antiAliasing; | ||||
482 | } | 364 | } | ||
483 | 365 | | |||
484 | void FontAASettings::enableWidgets() | 366 | void FontAASettings::setDpi(const int &dpi) | ||
485 | { | 367 | { | ||
486 | excludeFrom->setEnabled(excludeRange->isChecked()); | 368 | if (m_dpi == dpi) { | ||
487 | excludeTo->setEnabled(excludeRange->isChecked()); | 369 | return; | ||
488 | excludeToLabel->setEnabled(excludeRange->isChecked()); | | |||
489 | #ifdef FT_LCD_FILTER_H | | |||
490 | static int ft_has_subpixel = -1; | | |||
491 | if (ft_has_subpixel == -1) { | | |||
492 | FT_Library ftLibrary; | | |||
493 | if (FT_Init_FreeType(&ftLibrary) == 0) { | | |||
494 | ft_has_subpixel = (FT_Library_SetLcdFilter(ftLibrary, FT_LCD_FILTER_DEFAULT) | | |||
495 | == FT_Err_Unimplemented_Feature) ? 0 : 1; | | |||
496 | FT_Done_FreeType(ftLibrary); | | |||
497 | } | 370 | } | ||
371 | | ||||
372 | m_dpi = dpi; | ||||
373 | emit dpiChanged(); | ||||
498 | } | 374 | } | ||
499 | subPixelType->setEnabled(ft_has_subpixel); | 375 | | ||
500 | #endif | 376 | int FontAASettings::dpi() const | ||
377 | { | ||||
378 | return m_dpi; | ||||
501 | } | 379 | } | ||
502 | #endif | | |||
503 | 380 | | |||
504 | void FontAASettings::changed() | 381 | void FontAASettings::setSubPixelCurrentIndex(int idx) | ||
505 | { | 382 | { | ||
506 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 383 | if (m_subPixelCurrentIndex == idx) { | ||
507 | changesMade = true; | 384 | return; | ||
508 | enableWidgets(); | | |||
509 | #endif | | |||
510 | } | 385 | } | ||
511 | 386 | | |||
512 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 387 | m_subPixelCurrentIndex = idx; | ||
513 | int FontAASettings::exec() | 388 | emit subPixelCurrentIndexChanged(); | ||
389 | } | ||||
390 | | ||||
391 | int FontAASettings::subPixelCurrentIndex() | ||||
514 | { | 392 | { | ||
515 | const int i = QDialog::exec(); | 393 | return m_subPixelCurrentIndex; | ||
394 | } | ||||
516 | 395 | | |||
517 | if (!i) { | 396 | void FontAASettings::setHintingCurrentIndex(int idx) | ||
518 | load(); // Reset settings... | 397 | { | ||
398 | if (m_hintingCurrentIndex == idx) { | ||||
399 | return; | ||||
519 | } | 400 | } | ||
520 | 401 | | |||
521 | return i && changesMade; | 402 | m_hintingCurrentIndex = idx; | ||
403 | emit hintingCurrentIndexChanged(); | ||||
522 | } | 404 | } | ||
523 | #endif | 405 | | ||
406 | int FontAASettings::hintingCurrentIndex() | ||||
407 | { | ||||
408 | return m_hintingCurrentIndex; | ||||
409 | } | ||||
410 | | ||||
524 | 411 | | |||
525 | /**** KFonts ****/ | 412 | /**** KFonts ****/ | ||
526 | 413 | | |||
527 | KFonts::KFonts(QWidget *parent, const QVariantList &args) | 414 | KFonts::KFonts(QObject *parent, const QVariantList &args) | ||
528 | : KCModule(parent, args) | 415 | : KQuickAddons::ConfigModule(parent, args) | ||
416 | , m_fontAASettings(new FontAASettings(this)) | ||||
417 | { | ||||
418 | qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); | ||||
419 | KAboutData* about = new KAboutData("kcm_fonts", i18n("Configure Fonts"), | ||||
420 | "0.1", QString(), KAboutLicense::LGPL); | ||||
421 | about->addAuthor(i18n("Antonis Tsiapaliokas"), QString(), "antonis.tsiapaliokas@kde.org"); | ||||
422 | setAboutData(about); | ||||
423 | qmlRegisterType<QStandardItemModel>(); | ||||
424 | setButtons(Apply | Default); | ||||
425 | | ||||
426 | auto updateState = [this]() { | ||||
427 | setNeedsSave(true); | ||||
428 | }; | ||||
429 | | ||||
430 | connect(m_fontAASettings, &FontAASettings::subPixelCurrentIndexChanged, this, updateState); | ||||
431 | connect(m_fontAASettings, &FontAASettings::hintingCurrentIndexChanged, this, updateState); | ||||
432 | connect(m_fontAASettings, &FontAASettings::excludeToChanged, this, updateState); | ||||
433 | connect(m_fontAASettings, &FontAASettings::antiAliasingChanged, this, updateState); | ||||
434 | connect(m_fontAASettings, &FontAASettings::aliasingChanged, this, updateState); | ||||
435 | connect(m_fontAASettings, &FontAASettings::dpiChanged, this, updateState); | ||||
436 | } | ||||
437 | | ||||
438 | KFonts::~KFonts() | ||||
529 | { | 439 | { | ||
530 | QStringList nameGroupKeyRc; | 440 | } | ||
531 | 441 | | |||
532 | nameGroupKeyRc | 442 | void KFonts::defaults() | ||
533 | << i18nc("font usage", "General") << "General" << "font" << "" | 443 | { | ||
534 | << i18nc("font usage", "Fixed width") << "General" << "fixed" << "" | 444 | #ifdef Q_OS_MAC | ||
535 | << i18nc("font usage", "Small") << "General" << "smallestReadableFont" << "" | 445 | setGeneralFont(QFont("Lucida Grande", 13)); | ||
536 | << i18nc("font usage", "Toolbar") << "General" << "toolBarFont" << "" | 446 | setMenuFont(QFont("Lucida Grande", 13)); | ||
537 | << i18nc("font usage", "Menu") << "General" << "menuFont" << "" | 447 | setFixedWidthFont(QFont("Monaco", 10)); | ||
538 | << i18nc("font usage", "Window title") << "WM" << "activeFont" << ""; | 448 | setToolbarFont(QFont("Lucida Grande", 11)); | ||
539 | 449 | setSmallFont(QFont("Lucida Grande", 9)); | |||
540 | QList<QFont> defaultFontList; | 450 | setWindowTitleFont(QFont("Lucida Grande", 14)); | ||
541 | | ||||
542 | // NOTE: keep in sync with plasma-integration/src/platformtheme/kfontsettingsdata.cpp | | |||
543 | | ||||
544 | #ifdef Q_OS_MACOS | | |||
545 | QFont f0("Lucida Grande", 13); // general/menu/desktop | | |||
546 | QFont f1("Monaco", 10); | | |||
547 | QFont f2("Lucida Grande", 11); // toolbar | | |||
548 | #elif defined(Q_WS_MAEMO_5) || defined(MEEGO_EDITION_HARMATTAN) | | |||
549 | QFont f0("Sans Serif", 16); // general/menu/desktop | | |||
550 | QFont f1("Monospace", 16; | | |||
551 | QFont f2("Sans Serif", 16); // toolbar | | |||
552 | #else | | |||
553 | QFont f0("Noto Sans", 10); // general/menu/desktop | | |||
554 | QFont f1("Hack", 9); // fixed font | | |||
555 | QFont f2("Noto Sans", 10); // toolbar | | |||
556 | #endif | | |||
557 | #ifdef Q_OS_MACOS | | |||
558 | QFont f3("Lucida Grande", 14); // window title | | |||
559 | QFont f5("Lucida Grande", 9); // smallestReadableFont | | |||
560 | #else | 451 | #else | ||
561 | QFont f3("Noto Sans", 10); // window title | 452 | setGeneralFont(QFont("Noto Sans", 10)); | ||
562 | QFont f5("Noto Sans", 8); // smallestReadableFont | 453 | setMenuFont(QFont("Noto Sans", 10)); | ||
454 | setFixedWidthFont(QFont("Hack", 9)); | ||||
455 | setToolbarFont(QFont("Noto Sans", 10)); | ||||
456 | setSmallFont(QFont("Noto Sans", 8)); | ||||
457 | setWindowTitleFont(QFont("Noto Sans", 10)); | ||||
563 | #endif | 458 | #endif | ||
564 | 459 | | |||
565 | defaultFontList << f0 << f1 << f5 << f2 << f0 << f3; | 460 | m_fontAASettings->defaults(); | ||
461 | } | ||||
566 | 462 | | |||
567 | QList<bool> fixedList; | 463 | void KFonts::load() | ||
464 | { | ||||
465 | KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); | ||||
568 | 466 | | |||
569 | fixedList | 467 | KConfigGroup cg(config, "General"); | ||
570 | << false | 468 | QFont font; | ||
571 | << true | 469 | font = nearestExistingFont(cg.readEntry("font", m_defaultFont)); | ||
572 | << false | 470 | setGeneralFont(font); | ||
573 | << false | | |||
574 | << false | | |||
575 | << false; | | |||
576 | | ||||
577 | QStringList quickHelpList; | | |||
578 | | ||||
579 | quickHelpList | | |||
580 | << i18n("Used for normal text (e.g. button labels, list items).") | | |||
581 | << i18n("A non-proportional font (i.e. typewriter font).") | | |||
582 | << i18n("Smallest font that is still readable well.") | | |||
583 | << i18n("Used to display text beside toolbar icons.") | | |||
584 | << i18n("Used by menu bars and popup menus.") | | |||
585 | << i18n("Used by the window titlebar."); | | |||
586 | | ||||
587 | QVBoxLayout *layout = new QVBoxLayout(this); | | |||
588 | layout->setMargin(0); | | |||
589 | | ||||
590 | QGridLayout *fontUseLayout = new QGridLayout(); | | |||
591 | layout->addLayout(fontUseLayout); | | |||
592 | fontUseLayout->setColumnStretch(0, 0); | | |||
593 | fontUseLayout->setColumnStretch(1, 1); | | |||
594 | fontUseLayout->setColumnStretch(2, 0); | | |||
595 | | ||||
596 | QList<QFont>::ConstIterator defaultFontIt(defaultFontList.begin()); | | |||
597 | QList<bool>::ConstIterator fixedListIt(fixedList.begin()); | | |||
598 | QStringList::ConstIterator quickHelpIt(quickHelpList.begin()); | | |||
599 | QStringList::ConstIterator it(nameGroupKeyRc.begin()); | | |||
600 | | ||||
601 | unsigned int count = 0; | | |||
602 | | ||||
603 | while (it != nameGroupKeyRc.constEnd()) { | | |||
604 | QString name = *it; it++; | | |||
605 | QString group = *it; it++; | | |||
606 | QString key = *it; it++; | | |||
607 | QString file = *it; it++; | | |||
608 | | ||||
609 | FontUseItem *i = | | |||
610 | new FontUseItem( | | |||
611 | this, | | |||
612 | name, | | |||
613 | group, | | |||
614 | key, | | |||
615 | file, | | |||
616 | *defaultFontIt++, | | |||
617 | *fixedListIt++ | | |||
618 | ); | | |||
619 | | ||||
620 | fontUseList.append(i); | | |||
621 | connect(i, &KFontRequester::fontSelected, this, &KFonts::fontSelected); | | |||
622 | | ||||
623 | QLabel *fontUse = new QLabel(i18nc("Font role", "%1: ", name), this); | | |||
624 | fontUse->setAlignment(Qt::AlignRight | Qt::AlignVCenter); | | |||
625 | fontUse->setWhatsThis(*quickHelpIt++); | | |||
626 | | ||||
627 | fontUse->setBuddy(i); | | |||
628 | | ||||
629 | fontUseLayout->addWidget(fontUse, count, 0); | | |||
630 | fontUseLayout->addWidget(i, count, 1); | | |||
631 | | ||||
632 | ++count; | | |||
633 | } | | |||
634 | | ||||
635 | QHBoxLayout *hblay = new QHBoxLayout(); | | |||
636 | layout->addLayout(hblay); | | |||
637 | hblay->addStretch(); | | |||
638 | QPushButton *fontAdjustButton = new QPushButton(i18n("Ad&just All Fonts..."), this); | | |||
639 | fontAdjustButton->setWhatsThis(i18n("Click to change all fonts")); | | |||
640 | hblay->addWidget(fontAdjustButton); | | |||
641 | connect(fontAdjustButton, &QAbstractButton::clicked, this, &KFonts::slotApplyFontDiff); | | |||
642 | | ||||
643 | layout->addSpacing(style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); | | |||
644 | | ||||
645 | QGridLayout *lay = new QGridLayout(); | | |||
646 | layout->addLayout(lay); | | |||
647 | lay->setColumnStretch(3, 10); | | |||
648 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | | |||
649 | QLabel *label = 0L; | | |||
650 | label = new QLabel(i18n("Use a&nti-aliasing:"), this); | | |||
651 | label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); | | |||
652 | lay->addWidget(label, 0, 0); | | |||
653 | cbAA = new QComboBox(this); | | |||
654 | cbAA->insertItem(AAEnabled, i18nc("Use anti-aliasing", "Enabled")); // change AASetting type if order changes | | |||
655 | cbAA->insertItem(AASystem, i18nc("Use anti-aliasing", "System Settings")); | | |||
656 | cbAA->insertItem(AADisabled, i18nc("Use anti-aliasing", "Disabled")); | | |||
657 | cbAA->setWhatsThis(i18n("Select this option to smooth the edges of curves in fonts.")); | | |||
658 | aaSettingsButton = new QPushButton(i18n("Configure..."), this); | | |||
659 | connect(aaSettingsButton, &QAbstractButton::clicked, this, &KFonts::slotCfgAa); | | |||
660 | label->setBuddy(cbAA); | | |||
661 | lay->addWidget(cbAA, 0, 1); | | |||
662 | lay->addWidget(aaSettingsButton, 0, 2); | | |||
663 | // Initialize aaSettingsButton state based on the current cbAA->currentIndex value, will be eventually updated at load() | | |||
664 | slotUseAntiAliasing(); | | |||
665 | 471 | | |||
666 | connect(cbAA, SIGNAL(currentIndexChanged(int)), SLOT(slotUseAntiAliasing())); | | |||
667 | #endif | | |||
668 | checkboxForceDpi = new QCheckBox(i18n("Force fonts DPI:"), this); | | |||
669 | lay->addWidget(checkboxForceDpi, 1, 0); | | |||
670 | spinboxDpi = new QSpinBox(this); | | |||
671 | spinboxDpi->setRange(1, 1000); | | |||
672 | spinboxDpi->setSingleStep(24); // The common DPI values 72, 96 and 120 are multiples of 24 | | |||
673 | QString whatsthis = i18n( | | |||
674 | "<p>This option forces a specific DPI value for fonts. It may be useful" | | |||
675 | " when the real DPI of the hardware is not detected properly and it" | | |||
676 | " is also often misused when poor quality fonts are used that do not" | | |||
677 | " look well with DPI values other than 96 or 120 DPI.</p>" | | |||
678 | "<p>The use of this option is generally discouraged. For selecting proper DPI" | | |||
679 | " value a better option is explicitly configuring it for the whole X server if" | | |||
680 | " possible (e.g. DisplaySize in xorg.conf). When fonts do not render" | | |||
681 | " properly with real DPI value better fonts should be used or configuration" | | |||
682 | " of font hinting should be checked.</p>"); | | |||
683 | spinboxDpi->setWhatsThis(whatsthis); | | |||
684 | #if !defined(HAVE_X11) || !HAVE_X11 | | |||
685 | QString nothere = i18n("This property has no effect on this platform"); | | |||
686 | spinboxDpi->setToolTip(nothere); | | |||
687 | checkboxForceDpi->setToolTip(nothere); | | |||
688 | #endif | | |||
689 | checkboxForceDpi->setChecked(false); | | |||
690 | spinboxDpi->setEnabled(false); | | |||
691 | connect(spinboxDpi, SIGNAL(valueChanged(int)), SLOT(changed())); | | |||
692 | connect(checkboxForceDpi, SIGNAL(toggled(bool)), SLOT(changed())); | | |||
693 | connect(checkboxForceDpi, &QAbstractButton::toggled, spinboxDpi, &QWidget::setEnabled); | | |||
694 | lay->addWidget(spinboxDpi, 1, 1); | | |||
695 | layout->addStretch(1); | | |||
696 | 472 | | |||
697 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 473 | font = nearestExistingFont(cg.readEntry("fixed", m_defaultFont)); | ||
698 | aaSettings = new FontAASettings(this); | 474 | setFixedWidthFont(font); | ||
699 | #endif | 475 | | ||
476 | font = nearestExistingFont(cg.readEntry("smallestReadableFont", m_defaultFont)); | ||||
477 | setSmallFont(font); | ||||
478 | | ||||
479 | font = nearestExistingFont(cg.readEntry("toolBarFont", m_defaultFont)); | ||||
480 | setToolbarFont(font); | ||||
481 | | ||||
482 | font = nearestExistingFont(cg.readEntry("menuFont", m_defaultFont)); | ||||
483 | setMenuFont(font); | ||||
700 | 484 | | |||
485 | cg = KConfigGroup(config, "WM"); | ||||
486 | font = nearestExistingFont(cg.readEntry("activeFont", m_defaultFont)); | ||||
487 | setWindowTitleFont(font); | ||||
488 | | ||||
489 | m_fontAASettings->load(); | ||||
490 | setNeedsSave(false); | ||||
701 | } | 491 | } | ||
702 | 492 | | |||
703 | KFonts::~KFonts() | 493 | void KFonts::save() | ||
704 | { | 494 | { | ||
705 | QList<FontUseItem *>::Iterator it(fontUseList.begin()), | 495 | KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); | ||
706 | end(fontUseList.end()); | | |||
707 | 496 | | |||
708 | for (; it != end; ++it) { | 497 | KConfigGroup cg(config, "General"); | ||
709 | delete(*it); | 498 | cg.writeEntry("font", m_generalFont.toString()); | ||
710 | } | 499 | cg.writeEntry("fixed", m_fixedWidthFont.toString()); | ||
711 | fontUseList.clear(); | 500 | cg.writeEntry("smallestReadableFont", m_smallFont.toString()); | ||
501 | cg.writeEntry("toolBarFont", m_toolbarFont.toString()); | ||||
502 | cg.writeEntry("menuFont", m_menuFont.toString()); | ||||
503 | cg.sync(); | ||||
504 | cg = KConfigGroup(config, "WM"); | ||||
505 | cg.writeEntry("activeFont", m_windowTitleFont.toString()); | ||||
506 | cg.sync(); | ||||
507 | | ||||
508 | KConfig _cfgfonts("kcmfonts"); | ||||
509 | KConfigGroup cfgfonts(&_cfgfonts, "General"); | ||||
510 | | ||||
511 | FontAASettings::AASetting aaSetting = (FontAASettings::AASetting)m_fontAASettings->antiAliasing(); | ||||
512 | cfgfonts.writeEntry("dontChangeAASettings", aaSetting == FontAASettings::AASystem); | ||||
513 | | ||||
514 | if (aaSetting == FontAASettings::AAEnabled) { | ||||
515 | m_fontAASettings->save(KXftConfig::AntiAliasing::Enabled); | ||||
516 | } else if (aaSetting == FontAASettings::AADisabled) { | ||||
517 | m_fontAASettings->save(KXftConfig::AntiAliasing::Disabled); | ||||
518 | } else { | ||||
519 | m_fontAASettings->save(KXftConfig::AntiAliasing::NotSet); | ||||
712 | } | 520 | } | ||
713 | 521 | | |||
714 | void KFonts::fontSelected() | 522 | KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged); | ||
715 | { | 523 | | ||
716 | emit changed(true); | 524 | runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); | ||
525 | | ||||
526 | emit fontsHaveChanged(); | ||||
527 | setNeedsSave(false); | ||||
717 | } | 528 | } | ||
718 | 529 | | |||
719 | void KFonts::defaults() | 530 | void KFonts::setGeneralFont(const QFont &font) | ||
720 | { | 531 | { | ||
721 | for (int i = 0; i < (int) fontUseList.count(); i++) { | 532 | if (m_generalFont == font) { | ||
722 | fontUseList.at(i)->setDefault(); | 533 | return; | ||
723 | } | 534 | } | ||
724 | 535 | | |||
725 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 536 | m_generalFont = font; | ||
726 | useAA = AASystem; | 537 | emit generalFontChanged(); | ||
727 | cbAA->setCurrentIndex(useAA); | 538 | setNeedsSave(true); | ||
728 | aaSettings->defaults(); | | |||
729 | #endif | | |||
730 | checkboxForceDpi->setChecked(false); | | |||
731 | spinboxDpi->setValue(96); | | |||
732 | emit changed(true); | | |||
733 | } | 539 | } | ||
734 | 540 | | |||
735 | void KFonts::load() | 541 | QFont KFonts::generalFont() const | ||
736 | { | 542 | { | ||
737 | QList<FontUseItem *>::Iterator it(fontUseList.begin()), | 543 | return m_generalFont; | ||
738 | end(fontUseList.end()); | | |||
739 | | ||||
740 | for (; it != end; ++it) { | | |||
741 | (*it)->readFont(); | | |||
742 | } | 544 | } | ||
743 | 545 | | |||
744 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 546 | void KFonts::setFixedWidthFont(const QFont &font) | ||
745 | useAA_original = useAA = aaSettings->load() ? AAEnabled : AADisabled; | 547 | { | ||
746 | cbAA->setCurrentIndex(useAA); | 548 | if (m_fixedWidthFont == font) { | ||
747 | #endif | 549 | return; | ||
748 | | ||||
749 | KConfig _cfgfonts("kcmfonts"); | | |||
750 | KConfigGroup cfgfonts(&_cfgfonts, "General"); | | |||
751 | int dpicfg; | | |||
752 | if (KWindowSystem::isPlatformWayland()) { | | |||
753 | dpicfg = cfgfonts.readEntry("forceFontDPIWayland", 0); | | |||
754 | } else { | | |||
755 | dpicfg = cfgfonts.readEntry("forceFontDPI", 0); | | |||
756 | } | 550 | } | ||
757 | 551 | | |||
758 | if (dpicfg <= 0) { | 552 | m_fixedWidthFont = font; | ||
759 | checkboxForceDpi->setChecked(false); | 553 | emit fixedWidthFontChanged(); | ||
760 | spinboxDpi->setValue(96); | 554 | setNeedsSave(true); | ||
761 | dpi_original = 0; | | |||
762 | } else { | | |||
763 | checkboxForceDpi->setChecked(true); | | |||
764 | spinboxDpi->setValue(dpicfg); | | |||
765 | dpi_original = dpicfg; | | |||
766 | }; | | |||
767 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | | |||
768 | if (cfgfonts.readEntry("dontChangeAASettings", true)) { | | |||
769 | useAA_original = useAA = AASystem; | | |||
770 | cbAA->setCurrentIndex(useAA); | | |||
771 | } | 555 | } | ||
772 | #endif | | |||
773 | 556 | | |||
774 | emit changed(false); | 557 | QFont KFonts::fixedWidthFont() const | ||
558 | { | ||||
559 | return m_fixedWidthFont; | ||||
775 | } | 560 | } | ||
776 | 561 | | |||
777 | void KFonts::save() | 562 | void KFonts::setSmallFont(const QFont &font) | ||
778 | { | 563 | { | ||
779 | QList<FontUseItem *>::Iterator it(fontUseList.begin()), | 564 | if (m_smallFont == font) { | ||
780 | end(fontUseList.end()); | 565 | return; | ||
566 | } | ||||
781 | 567 | | |||
782 | for (; it != end; ++it) { | 568 | m_smallFont = font; | ||
783 | (*it)->writeFont(); | 569 | emit smallFontChanged(); | ||
570 | setNeedsSave(true); | ||||
784 | } | 571 | } | ||
785 | 572 | | |||
786 | KSharedConfig::openConfig()->sync(); | 573 | QFont KFonts::smallFont() const | ||
574 | { | ||||
575 | return m_smallFont; | ||||
576 | } | ||||
787 | 577 | | |||
788 | KConfig _cfgfonts("kcmfonts"); | 578 | void KFonts::setToolbarFont(const QFont &font) | ||
789 | KConfigGroup cfgfonts(&_cfgfonts, "General"); | 579 | { | ||
790 | int dpi = (checkboxForceDpi->isChecked() ? spinboxDpi->value() : 0); | 580 | if (m_toolbarFont == font) { | ||
791 | if (KWindowSystem::isPlatformWayland()) { | 581 | return; | ||
792 | cfgfonts.writeEntry("forceFontDPIWayland", dpi); | | |||
793 | } else { | | |||
794 | cfgfonts.writeEntry("forceFontDPI", dpi); | | |||
795 | } | 582 | } | ||
796 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 583 | | ||
797 | cfgfonts.writeEntry("dontChangeAASettings", cbAA->currentIndex() == AASystem); | 584 | m_toolbarFont = font; | ||
798 | #endif | 585 | emit toolbarFontChanged(); | ||
799 | cfgfonts.sync(); | 586 | setNeedsSave(true); | ||
800 | #if HAVE_X11 | | |||
801 | // if the setting is reset in the module, remove the dpi value, | | |||
802 | // otherwise don't explicitly remove it and leave any possible system-wide value | | |||
803 | if (dpi == 0 && dpi_original != 0 && !KWindowSystem::isPlatformWayland()) { | | |||
804 | QProcess proc; | | |||
805 | proc.setProcessChannelMode(QProcess::ForwardedChannels); | | |||
806 | proc.start("xrdb", QStringList() << "-quiet" << "-remove" << "-nocpp"); | | |||
807 | if (proc.waitForStarted()) { | | |||
808 | proc.write(QByteArray("Xft.dpi\n")); | | |||
809 | proc.closeWriteChannel(); | | |||
810 | proc.waitForFinished(); | | |||
811 | } | 587 | } | ||
588 | | ||||
589 | QFont KFonts::toolbarFont() const | ||||
590 | { | ||||
591 | return m_toolbarFont; | ||||
812 | } | 592 | } | ||
813 | #endif | | |||
814 | 593 | | |||
815 | KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged); | 594 | void KFonts::setMenuFont(const QFont &font) | ||
595 | { | ||||
596 | if (m_menuFont == font) { | ||||
597 | return; | ||||
598 | } | ||||
816 | 599 | | |||
817 | QApplication::processEvents(); // Process font change ourselves | 600 | m_menuFont = font; | ||
601 | emit menuFontChanged(); | ||||
602 | setNeedsSave(true); | ||||
603 | } | ||||
818 | 604 | | |||
819 | // Don't overwrite global settings unless explicitly asked for - e.g. the system | 605 | QFont KFonts::menuFont() const | ||
820 | // fontconfig setup may be much more complex than this module can provide. | 606 | { | ||
821 | // TODO: With AASystem the changes already made by this module should be reverted somehow. | 607 | return m_menuFont; | ||
822 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | | |||
823 | bool aaSave = false; | | |||
824 | if (cbAA->currentIndex() == AAEnabled ) { | | |||
825 | aaSave = aaSettings->save(KXftConfig::AntiAliasing::Enabled); | | |||
826 | } else if (cbAA->currentIndex() == AADisabled) { | | |||
827 | aaSave = aaSettings->save(KXftConfig::AntiAliasing::Disabled); | | |||
828 | } else { | | |||
829 | // If AASystem is selected, this removes all fontconfig settings made by | | |||
830 | // this module. | | |||
831 | aaSettings->defaults(); | | |||
832 | aaSave = aaSettings->save(KXftConfig::AntiAliasing::NotSet); | | |||
833 | } | 608 | } | ||
834 | 609 | | |||
835 | if (aaSave || (useAA != useAA_original) || dpi != dpi_original) { | 610 | void KFonts::setWindowTitleFont(const QFont &font) | ||
836 | KMessageBox::information(this, | 611 | { | ||
837 | i18n( | 612 | if (m_windowTitleFont == font) { | ||
838 | "<p>Some changes such as anti-aliasing or DPI will only affect newly started applications.</p>" | 613 | return; | ||
839 | ), i18n("Font Settings Changed"), "FontSettingsChanged"); | | |||
840 | useAA_original = useAA; | | |||
841 | dpi_original = dpi; | | |||
842 | } | 614 | } | ||
843 | #else | 615 | | ||
844 | #if HAVE_X11 | 616 | m_windowTitleFont = font; | ||
845 | if (dpi != dpi_original) { | 617 | emit windowTitleFontChanged(); | ||
846 | KMessageBox::information(this, | 618 | setNeedsSave(true); | ||
847 | i18n( | | |||
848 | "<p>Some changes such as DPI will only affect newly started applications.</p>" | | |||
849 | ), i18n("Font Settings Changed"), "FontSettingsChanged"); | | |||
850 | dpi_original = dpi; | | |||
851 | } | 619 | } | ||
852 | #endif | | |||
853 | #endif | | |||
854 | runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); | | |||
855 | 620 | | |||
856 | emit changed(false); | 621 | QFont KFonts::windowTitleFont() const | ||
622 | { | ||||
623 | return m_windowTitleFont; | ||||
857 | } | 624 | } | ||
858 | 625 | | |||
859 | void KFonts::slotApplyFontDiff() | 626 | void KFonts::adjustAllFonts() | ||
860 | { | 627 | { | ||
861 | QFont font = QFont(fontUseList.first()->font()); | 628 | QFont font = m_generalFont; | ||
862 | KFontChooser::FontDiffFlags fontDiffFlags = 0; | 629 | KFontChooser::FontDiffFlags fontDiffFlags = 0; | ||
863 | int ret = KFontDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags, this); | 630 | int ret = KFontDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags); | ||
864 | 631 | | |||
865 | if (ret == KDialog::Accepted && fontDiffFlags) { | 632 | if (ret == KDialog::Accepted && fontDiffFlags) { | ||
866 | for (int i = 0; i < (int) fontUseList.count(); i++) { | 633 | setGeneralFont(applyFontDiff(m_generalFont, font, fontDiffFlags)); | ||
867 | fontUseList.at(i)->applyFontDiff(font, fontDiffFlags); | 634 | setMenuFont(applyFontDiff(m_menuFont, font, fontDiffFlags)); | ||
635 | { | ||||
636 | const QFont adjustedFont = applyFontDiff(m_fixedWidthFont, font, fontDiffFlags); | ||||
637 | if (QFontInfo(adjustedFont).fixedPitch()) { | ||||
638 | setFixedWidthFont(adjustedFont); | ||||
868 | } | 639 | } | ||
869 | emit changed(true); | | |||
870 | } | 640 | } | ||
641 | setToolbarFont(applyFontDiff(m_toolbarFont, font, fontDiffFlags)); | ||||
642 | setSmallFont(applyFontDiff(m_smallFont, font, fontDiffFlags)); | ||||
643 | setWindowTitleFont(applyFontDiff(m_windowTitleFont, font, fontDiffFlags)); | ||||
871 | } | 644 | } | ||
872 | | ||||
873 | void KFonts::slotUseAntiAliasing() | | |||
874 | { | | |||
875 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | | |||
876 | useAA = static_cast< AASetting >(cbAA->currentIndex()); | | |||
877 | aaSettingsButton->setEnabled(useAA == AAEnabled); | | |||
878 | emit changed(true); | | |||
879 | #endif | | |||
880 | } | 645 | } | ||
881 | 646 | | |||
882 | void KFonts::slotCfgAa() | 647 | QFont KFonts::applyFontDiff(const QFont &fnt, const QFont &newFont, int fontDiffFlags) | ||
883 | { | 648 | { | ||
884 | #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) | 649 | QFont font(fnt); | ||
885 | if (aaSettings->exec()) { | 650 | | ||
886 | emit changed(true); | 651 | if (fontDiffFlags & KFontChooser::FontDiffSize) { | ||
652 | font.setPointSizeF(newFont.pointSizeF()); | ||||
887 | } | 653 | } | ||
888 | #endif | 654 | if ((fontDiffFlags & KFontChooser::FontDiffFamily)) { | ||
655 | font.setFamily(newFont.family()); | ||||
656 | } | ||||
657 | if (fontDiffFlags & KFontChooser::FontDiffStyle) { | ||||
658 | font.setWeight(newFont.weight()); | ||||
659 | font.setStyle(newFont.style()); | ||||
660 | font.setUnderline(newFont.underline()); | ||||
661 | font.setStyleName(newFont.styleName()); | ||||
662 | } | ||||
663 | | ||||
664 | return font; | ||||
889 | } | 665 | } | ||
890 | 666 | | |||
891 | #include "fonts.moc" | 667 | #include "fonts.moc" | ||
892 | 668 | |