1 /* This file is part of the KDE libraries
2 Copyright (C) 2000, 2006 David Faure <faure@kde.org>
3 Copyright 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18 */
19
20 #include "kglobalsettings.h"
21
22 #include <ktoolbar.h>
23 #include <kconfig.h>
24 #include <kcolorscheme.h>
25
26 //#include <kstyle.h>
27
28 #include <QColor>
29 #include <QCursor>
30 #include <QDesktopWidget>
31 #include <QDir>
32 #include <QFont>
33 #include <QFontDatabase>
34 #include <QFontInfo>
35 #include <QKeySequence>
36 #include <QPixmap>
37 #include <QPixmapCache>
38 #include <QApplication>
39 #include <QDBusConnection>
40 #include <QStyleFactory>
41 #include <QDebug>
42 #include <qstandardpaths.h>
43
44 // next two needed so we can set their palettes
45 #include <QDBusMessage>
46 #include <QToolTip>
47 #include <QUrl>
48 #include <QWhatsThis>
49
50 #ifdef Q_OS_WIN
51 #include <windows.h>
52
qt_colorref2qrgb(COLORREF col)53 static QRgb qt_colorref2qrgb(COLORREF col)
54 {
55 return qRgb(GetRValue(col), GetGValue(col), GetBValue(col));
56 }
57 #endif
58 #include <config-kdelibs4support.h>
59 #if HAVE_X11
60 #include <X11/Xlib.h>
61 #ifdef HAVE_XCURSOR // TODO NOT DEFINED ANYMORE. Can we drop X cursor themes?
62 #include <X11/Xcursor/Xcursor.h>
63 #endif
64 //#include "fixx11h.h"
65 #include <QX11Info>
66 #endif
67
68 #include <stdlib.h>
69 #include <kconfiggroup.h>
70 #include <kiconloader.h>
71
72 //static QColor *_buttonBackground = 0;
73 static KGlobalSettings::GraphicEffects _graphicEffects = KGlobalSettings::NoEffects;
74
75 class Q_DECL_HIDDEN KGlobalSettings::Private
76 {
77 public:
Private(KGlobalSettings * q)78 Private(KGlobalSettings *q)
79 : q(q), activated(false), paletteCreated(false), mMouseSettings(nullptr), mLargeFont(nullptr)
80 #if HAVE_X11
81 , isX11(QX11Info::isPlatformX11())
82 #endif
83 {
84 kdeFullSession = !qgetenv("KDE_FULL_SESSION").isEmpty();
85 }
86
87 QPalette createApplicationPalette(const KSharedConfigPtr &config);
88 QPalette createNewApplicationPalette(const KSharedConfigPtr &config);
89 void _k_slotNotifyChange(int, int);
90 void _k_slotIconChange(int);
91
92 void propagateQtSettings();
93 void kdisplaySetPalette();
94 void kdisplaySetStyle();
95 void kdisplaySetFont();
96 void applyGUIStyle();
97 void dropMouseSettingsCache();
98 KGlobalSettings::KMouseSettings &mouseSettings();
99
100 /**
101 * @internal
102 *
103 * Ensures that cursors are loaded from the theme KDE is configured
104 * to use. Note that calling this function doesn't cause existing
105 * cursors to be reloaded. Reloading already created cursors is
106 * handled by the KCM when a cursor theme is applied.
107 *
108 * It is not necessary to call this function when KGlobalSettings
109 * is initialized.
110 */
111 void applyCursorTheme();
112
113 static void reloadStyleSettings();
114
115 QFont largeFont(const QString &text);
116
117 KGlobalSettings *q;
118 bool activated;
119 bool paletteCreated;
120 bool kdeFullSession;
121 QPalette applicationPalette;
122 KGlobalSettings::KMouseSettings *mMouseSettings;
123 QFont *mLargeFont;
124 #if HAVE_X11
125 bool isX11;
126 #endif
127 };
128
129 // class for access to KGlobalSettings constructor
130 class KGlobalSettingsSingleton
131 {
132 public:
133 KGlobalSettings object;
134 };
135
Q_GLOBAL_STATIC(KGlobalSettingsSingleton,s_self)136 Q_GLOBAL_STATIC(KGlobalSettingsSingleton, s_self)
137
138 KGlobalSettings *KGlobalSettings::self()
139 {
140 return &s_self()->object;
141 }
142
KGlobalSettings()143 KGlobalSettings::KGlobalSettings()
144 : QObject(nullptr), d(new Private(this))
145 {
146 connect(this, SIGNAL(kdisplayFontChanged()), SIGNAL(appearanceChanged()));
147 }
148
~KGlobalSettings()149 KGlobalSettings::~KGlobalSettings()
150 {
151 delete d;
152 }
153
activate()154 void KGlobalSettings::activate()
155 {
156 activate(ApplySettings | ListenForChanges);
157 }
158
activate(ActivateOptions options)159 void KGlobalSettings::activate(ActivateOptions options)
160 {
161 if (!d->activated) {
162 d->activated = true;
163
164 if (options & ListenForChanges) {
165 QDBusConnection::sessionBus().connect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
166 "notifyChange", this, SLOT(_k_slotNotifyChange(int,int)));
167 QDBusConnection::sessionBus().connect(QString(), "/KIconLoader", "org.kde.KIconLoader",
168 "iconChanged", this, SLOT(_k_slotIconChange(int)));
169 QDBusConnection::sessionBus().connect(QString(), "/KDEPlatformTheme", "org.kde.KDEPlatformTheme",
170 "refreshFonts", this, SLOT(kdisplayFontChanged()));
171 }
172
173 if (options & ApplySettings) {
174 d->kdisplaySetStyle(); // implies palette setup
175 d->propagateQtSettings();
176 }
177 }
178 }
179
180 // Qt5 TODO: implement QPlatformIntegration::styleHint so that it reads a Qt or KDE setting,
181 // so that apps can just use QApplication::startDragDistance().
dndEventDelay()182 int KGlobalSettings::dndEventDelay()
183 {
184 KConfigGroup g(KSharedConfig::openConfig(), "General");
185 return g.readEntry("StartDragDist", QApplication::startDragDistance());
186 }
187
singleClick()188 bool KGlobalSettings::singleClick()
189 {
190 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
191 return g.readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK);
192 }
193
changeCursorOverIcon()194 bool KGlobalSettings::changeCursorOverIcon()
195 {
196 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
197 return g.readEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR);
198 }
199
autoSelectDelay()200 int KGlobalSettings::autoSelectDelay()
201 {
202 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
203 return g.readEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY);
204 }
205
completionMode()206 KGlobalSettings::Completion KGlobalSettings::completionMode()
207 {
208 int completion;
209 KConfigGroup g(KSharedConfig::openConfig(), "General");
210 completion = g.readEntry("completionMode", -1);
211 if ((completion < (int) CompletionNone) ||
212 (completion > (int) CompletionPopupAuto)) {
213 completion = (int) CompletionPopup; // Default
214 }
215 return (Completion) completion;
216 }
217
showContextMenusOnPress()218 bool KGlobalSettings::showContextMenusOnPress()
219 {
220 KConfigGroup g(KSharedConfig::openConfig(), "ContextMenus");
221 return g.readEntry("ShowOnPress", true);
222 }
223
224 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
inactiveTitleColor()225 QColor KGlobalSettings::inactiveTitleColor()
226 {
227 #ifdef Q_OS_WIN
228 return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION));
229 #else
230 KConfigGroup g(KSharedConfig::openConfig(), "WM");
231 return g.readEntry("inactiveBackground", QColor(224, 223, 222));
232 #endif
233 }
234
235 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
inactiveTextColor()236 QColor KGlobalSettings::inactiveTextColor()
237 {
238 #ifdef Q_OS_WIN
239 return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
240 #else
241 KConfigGroup g(KSharedConfig::openConfig(), "WM");
242 return g.readEntry("inactiveForeground", QColor(75, 71, 67));
243 #endif
244 }
245
246 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
activeTitleColor()247 QColor KGlobalSettings::activeTitleColor()
248 {
249 #ifdef Q_OS_WIN
250 return qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION));
251 #else
252 KConfigGroup g(KSharedConfig::openConfig(), "WM");
253 return g.readEntry("activeBackground", QColor(48, 174, 232));
254 #endif
255 }
256
257 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
activeTextColor()258 QColor KGlobalSettings::activeTextColor()
259 {
260 #ifdef Q_OS_WIN
261 return qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT));
262 #else
263 KConfigGroup g(KSharedConfig::openConfig(), "WM");
264 return g.readEntry("activeForeground", QColor(255, 255, 255));
265 #endif
266 }
267
contrast()268 int KGlobalSettings::contrast()
269 {
270 return KColorScheme::contrast();
271 }
272
contrastF(const KSharedConfigPtr & config)273 qreal KGlobalSettings::contrastF(const KSharedConfigPtr &config)
274 {
275 return KColorScheme::contrastF(config);
276 }
277
shadeSortColumn()278 bool KGlobalSettings::shadeSortColumn()
279 {
280 KConfigGroup g(KSharedConfig::openConfig(), "General");
281 return g.readEntry("shadeSortColumn", KDE_DEFAULT_SHADE_SORT_COLUMN);
282 }
283
allowDefaultBackgroundImages()284 bool KGlobalSettings::allowDefaultBackgroundImages()
285 {
286 KConfigGroup g(KSharedConfig::openConfig(), "General");
287 return g.readEntry("allowDefaultBackgroundImages", KDE_DEFAULT_ALLOW_DEFAULT_BACKGROUND_IMAGES);
288 }
289
290 //inspired in old KGlobalSettingsData code
constructFontFromConfig(const char * groupKey,const char * configKey)291 QFont constructFontFromConfig(const char *groupKey, const char *configKey)
292 {
293 const KConfigGroup configGroup(KSharedConfig::openConfig(), groupKey);
294 QFont ret;
295 ret.setStyleHint(QFont::SansSerif);
296 ret = configGroup.readEntry(configKey, ret);
297 return ret;
298 }
299
generalFont()300 QFont KGlobalSettings::generalFont()
301 {
302 return QFontDatabase::systemFont(QFontDatabase::GeneralFont);
303 }
fixedFont()304 QFont KGlobalSettings::fixedFont()
305 {
306 return QFontDatabase::systemFont(QFontDatabase::FixedFont);
307 }
windowTitleFont()308 QFont KGlobalSettings::windowTitleFont()
309 {
310 return QFontDatabase::systemFont(QFontDatabase::TitleFont);
311 }
smallestReadableFont()312 QFont KGlobalSettings::smallestReadableFont()
313 {
314 return QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
315 }
toolBarFont()316 QFont KGlobalSettings::toolBarFont()
317 {
318 return constructFontFromConfig("General", "toolBarFont");
319 }
menuFont()320 QFont KGlobalSettings::menuFont()
321 {
322 return constructFontFromConfig("General", "menuFont");
323 }
taskbarFont()324 QFont KGlobalSettings::taskbarFont()
325 {
326 return constructFontFromConfig("General", "taskbarFont");
327 }
328
largeFont(const QString & text)329 QFont KGlobalSettings::Private::largeFont(const QString &text)
330 {
331 QFontDatabase db;
332 QStringList fam = db.families();
333
334 // Move a bunch of preferred fonts to the front.
335 // most preferred last
336 static const char *const PreferredFontNames[] = {
337 "Arial",
338 "Sans Serif",
339 "Verdana",
340 "Tahoma",
341 "Lucida Sans",
342 "Lucidux Sans",
343 "Nimbus Sans",
344 "Gothic I"
345 };
346 static const unsigned int PreferredFontNamesCount = sizeof(PreferredFontNames) / sizeof(const char *);
347 for (unsigned int i = 0; i < PreferredFontNamesCount; ++i) {
348 const QString fontName(PreferredFontNames[i]);
349 if (fam.removeAll(fontName) > 0) {
350 fam.prepend(fontName);
351 }
352 }
353
354 if (mLargeFont) {
355 fam.prepend(mLargeFont->family());
356 delete mLargeFont;
357 }
358
359 for (QStringList::ConstIterator it = fam.constBegin();
360 it != fam.constEnd(); ++it) {
361 if (db.isSmoothlyScalable(*it) && !db.isFixedPitch(*it)) {
362 QFont font(*it);
363 font.setPixelSize(75);
364 QFontMetrics metrics(font);
365 int h = metrics.height();
366 if ((h < 60) || (h > 90)) {
367 continue;
368 }
369
370 bool ok = true;
371 for (int i = 0; i < text.length(); i++) {
372 if (!metrics.inFont(text[i])) {
373 ok = false;
374 break;
375 }
376 }
377 if (!ok) {
378 continue;
379 }
380
381 font.setPointSize(48);
382 mLargeFont = new QFont(font);
383 return *mLargeFont;
384 }
385 }
386 mLargeFont = new QFont(q->generalFont());
387 mLargeFont->setPointSize(48);
388 return *mLargeFont;
389 }
390
largeFont(const QString & text)391 QFont KGlobalSettings::largeFont(const QString &text)
392 {
393 return self()->d->largeFont(text);
394 }
395
mouseSettings()396 KGlobalSettings::KMouseSettings &KGlobalSettings::Private::mouseSettings()
397 {
398 if (!mMouseSettings) {
399 mMouseSettings = new KGlobalSettings::KMouseSettings;
400 KGlobalSettings::KMouseSettings &s = *mMouseSettings; // for convenience
401
402 #ifndef Q_OS_WIN
403 KConfigGroup g(KSharedConfig::openConfig(), "Mouse");
404 QString setting = g.readEntry("MouseButtonMapping");
405 if (setting == "RightHanded") {
406 s.handed = KGlobalSettings::KMouseSettings::RightHanded;
407 } else if (setting == "LeftHanded") {
408 s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
409 } else {
410 #if HAVE_X11
411 if (isX11) {
412 // get settings from X server
413 // This is a simplified version of the code in input/mouse.cpp
414 // Keep in sync !
415 s.handed = KGlobalSettings::KMouseSettings::RightHanded;
416 unsigned char map[20];
417 int num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
418 if (num_buttons == 2) {
419 if ((int)map[0] == 1 && (int)map[1] == 2) {
420 s.handed = KGlobalSettings::KMouseSettings::RightHanded;
421 } else if ((int)map[0] == 2 && (int)map[1] == 1) {
422 s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
423 }
424 } else if (num_buttons >= 3) {
425 if ((int)map[0] == 1 && (int)map[2] == 3) {
426 s.handed = KGlobalSettings::KMouseSettings::RightHanded;
427 } else if ((int)map[0] == 3 && (int)map[2] == 1) {
428 s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
429 }
430 }
431 }
432 #else
433 // FIXME: Implement on other platforms
434 #endif
435 }
436 #endif //Q_OS_WIN
437 }
438 #ifdef Q_OS_WIN
439 //not cached
440 #ifndef _WIN32_WCE
441 mMouseSettings->handed = (GetSystemMetrics(SM_SWAPBUTTON) ?
442 KGlobalSettings::KMouseSettings::LeftHanded :
443 KGlobalSettings::KMouseSettings::RightHanded);
444 #else
445 // There is no mice under wince
446 mMouseSettings->handed = KGlobalSettings::KMouseSettings::RightHanded;
447 #endif
448 #endif
449 return *mMouseSettings;
450 }
451 // KDE5: make this a const return?
mouseSettings()452 KGlobalSettings::KMouseSettings &KGlobalSettings::mouseSettings()
453 {
454 return self()->d->mouseSettings();
455 }
456
desktopPath()457 QString KGlobalSettings::desktopPath()
458 {
459 QString path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
460 return path.isEmpty() ? QDir::homePath() : path;
461 }
462
463 // This was the KDE-specific autostart folder in KDEHOME.
464 // KDE 5 : re-evaluate this, I'd say the xdg autostart spec supersedes this, and is sufficient
465 // (since there's a GUI for creating the necessary desktop files)
466 #if 0
467 QString KGlobalSettings::autostartPath()
468 {
469 QString s_autostartPath;
470 KConfigGroup g(KSharedConfig::openConfig(), "Paths");
471 s_autostartPath = KGlobal::dirs()->localkdedir() + "Autostart/";
472 s_autostartPath = g.readPathEntry("Autostart", s_autostartPath);
473 s_autostartPath = QDir::cleanPath(s_autostartPath);
474 if (!s_autostartPath.endsWith('/')) {
475 s_autostartPath.append(QLatin1Char('/'));
476 }
477 return s_autostartPath;
478 }
479 #endif
480
documentPath()481 QString KGlobalSettings::documentPath()
482 {
483 QString path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
484 return path.isEmpty() ? QDir::homePath() : path;
485 }
486
downloadPath()487 QString KGlobalSettings::downloadPath()
488 {
489 QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
490 return path.isEmpty() ? QDir::homePath() : path;
491 }
492
videosPath()493 QString KGlobalSettings::videosPath()
494 {
495 QString path = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
496 return path.isEmpty() ? QDir::homePath() : path;
497 }
498
picturesPath()499 QString KGlobalSettings::picturesPath()
500 {
501 QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
502 return path.isEmpty() ? QDir::homePath() : path;
503 }
504
musicPath()505 QString KGlobalSettings::musicPath()
506 {
507 QString path = QStandardPaths::writableLocation(QStandardPaths::MusicLocation);
508 return path.isEmpty() ? QDir::homePath() : path;
509 }
510
isMultiHead()511 bool KGlobalSettings::isMultiHead()
512 {
513 #ifdef Q_OS_WIN
514 return GetSystemMetrics(SM_CMONITORS) > 1;
515 #else
516 QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
517 if (!multiHead.isEmpty()) {
518 return (multiHead.toLower() == "true");
519 }
520 return false;
521 #endif
522 }
523
wheelMouseZooms()524 bool KGlobalSettings::wheelMouseZooms()
525 {
526 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
527 return g.readEntry("WheelMouseZooms", KDE_DEFAULT_WHEEL_ZOOM);
528 }
529
splashScreenDesktopGeometry()530 QRect KGlobalSettings::splashScreenDesktopGeometry()
531 {
532 return QApplication::desktop()->screenGeometry(QCursor::pos());
533 }
534
desktopGeometry(const QPoint & point)535 QRect KGlobalSettings::desktopGeometry(const QPoint &point)
536 {
537 return QApplication::desktop()->screenGeometry(point);
538 }
539
desktopGeometry(const QWidget * w)540 QRect KGlobalSettings::desktopGeometry(const QWidget *w)
541 {
542 return QApplication::desktop()->screenGeometry(w);
543 }
544
showIconsOnPushButtons()545 bool KGlobalSettings::showIconsOnPushButtons()
546 {
547 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
548 return g.readEntry("ShowIconsOnPushButtons",
549 KDE_DEFAULT_ICON_ON_PUSHBUTTON);
550 }
551
naturalSorting()552 bool KGlobalSettings::naturalSorting()
553 {
554 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
555 return g.readEntry("NaturalSorting",
556 KDE_DEFAULT_NATURAL_SORTING);
557 }
558
graphicEffectsLevel()559 KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevel()
560 {
561 // This variable stores whether _graphicEffects has the default value because it has not been
562 // loaded yet, or if it has been loaded from the user settings or defaults and contains a valid
563 // value.
564 static bool _graphicEffectsInitialized = false;
565
566 if (!_graphicEffectsInitialized) {
567 _graphicEffectsInitialized = true;
568 Private::reloadStyleSettings();
569 }
570
571 return _graphicEffects;
572 }
573
graphicEffectsLevelDefault()574 KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevelDefault()
575 {
576 // For now, let always enable animations by default. The plan is to make
577 // this code a bit smarter. (ereslibre)
578
579 return ComplexAnimationEffects;
580 }
581
582 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
showFilePreview(const QUrl & url)583 bool KGlobalSettings::showFilePreview(const QUrl &url)
584 {
585 KConfigGroup g(KSharedConfig::openConfig(), "PreviewSettings");
586 bool defaultSetting = url.isLocalFile(); // ## incorrect, use KProtocolInfo::showFilePreview instead
587 return g.readEntry(url.scheme(), defaultSetting);
588 }
589 #endif
590
opaqueResize()591 bool KGlobalSettings::opaqueResize()
592 {
593 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
594 return g.readEntry("OpaqueResize", KDE_DEFAULT_OPAQUE_RESIZE);
595 }
596
buttonLayout()597 int KGlobalSettings::buttonLayout()
598 {
599 KConfigGroup g(KSharedConfig::openConfig(), "KDE");
600 return g.readEntry("ButtonLayout", KDE_DEFAULT_BUTTON_LAYOUT);
601 }
602
603 #if 0 // HAVE_X11 && QT_VERSION >= QT_VERSION_CHECK(5,0,0)
604 // Taken from Qt-4.x qt_x11_apply_settings_in_all_apps since Qt5 doesn't have it anymore.
605 // TODO: evaluate if this is still needed
606 // TODO: if yes, this code should be an invokable method of the qxcb platform plugin?
607 // TODO: it looks like the handling code for this in QPA is missing, too...
608 static void x11_apply_settings_in_all_apps()
609 {
610 QByteArray stamp;
611 QDataStream s(&stamp, QIODevice::WriteOnly);
612 s << QDateTime::currentDateTime();
613
614 QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
615 settings_atom_name += XDisplayString(QX11Info::display());
616
617 xcb_connection_t *xcb_conn = QX11Info::connection();
618 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData());
619 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0);
620 xcb_atom_t atom = reply->atom;
621 free(reply);
622
623 xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, QX11Info::appRootWindow(), atom, XCB_ATOM_ATOM,
624 8, stamp.size(), (const void *)stamp.constData());
625
626 //XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
627 //ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
628 //PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
629 }
630 #endif
631
emitChange(ChangeType changeType,int arg)632 void KGlobalSettings::emitChange(ChangeType changeType, int arg)
633 {
634 switch (changeType) {
635 case IconChanged:
636 KIconLoader::emitChange(KIconLoader::Group(arg));
637 break;
638 case ToolbarStyleChanged:
639 KToolBar::emitToolbarStyleChanged();
640 break;
641 case FontChanged:
642 self()->d->kdisplaySetFont();
643 break;
644 default: {
645 QDBusMessage message = QDBusMessage::createSignal("/KGlobalSettings", "org.kde.KGlobalSettings", "notifyChange");
646 QList<QVariant> args;
647 args.append(static_cast<int>(changeType));
648 args.append(arg);
649 message.setArguments(args);
650 QDBusConnection::sessionBus().send(message);
651 } break;
652
653 }
654 }
655
_k_slotIconChange(int arg)656 void KGlobalSettings::Private::_k_slotIconChange(int arg)
657 {
658 _k_slotNotifyChange(IconChanged, arg);
659 }
660
_k_slotNotifyChange(int changeType,int arg)661 void KGlobalSettings::Private::_k_slotNotifyChange(int changeType, int arg)
662 {
663 switch (changeType) {
664 case StyleChanged:
665 if (activated) {
666 KSharedConfig::openConfig()->reparseConfiguration();
667 kdisplaySetStyle();
668 }
669 break;
670
671 case ToolbarStyleChanged:
672 KSharedConfig::openConfig()->reparseConfiguration();
673 emit q->toolbarAppearanceChanged(arg);
674 break;
675
676 case PaletteChanged:
677 if (activated) {
678 KSharedConfig::openConfig()->reparseConfiguration();
679 paletteCreated = false;
680 kdisplaySetPalette();
681 }
682 break;
683
684 case FontChanged:
685 Q_ASSERT(false && "shouldn't get here now...");
686 break;
687
688 case SettingsChanged: {
689 KSharedConfig::openConfig()->reparseConfiguration();
690 SettingsCategory category = static_cast<SettingsCategory>(arg);
691 if (category == SETTINGS_QT) {
692 if (activated) {
693 propagateQtSettings();
694 }
695 } else {
696 switch (category) {
697 case SETTINGS_STYLE:
698 reloadStyleSettings();
699 break;
700 case SETTINGS_MOUSE:
701 self()->d->dropMouseSettingsCache();
702 break;
703 case SETTINGS_LOCALE:
704 // QT5 TODO REPLACEMENT ? KLocale::global()->reparseConfiguration();
705 break;
706 default:
707 break;
708 }
709 emit q->settingsChanged(category);
710 }
711 break;
712 }
713 case IconChanged:
714 QPixmapCache::clear();
715 KSharedConfig::openConfig()->reparseConfiguration();
716 emit q->iconChanged(arg);
717 break;
718
719 case CursorChanged:
720 applyCursorTheme();
721 break;
722
723 case BlockShortcuts:
724 // FIXME KAccel port
725 //KGlobalAccel::blockShortcuts(arg);
726 emit q->blockShortcuts(arg); // see kwin
727 break;
728
729 case NaturalSortingChanged:
730 emit q->naturalSortingChanged();
731 break;
732
733 default:
734 qWarning() << "Unknown type of change in KGlobalSettings::slotNotifyChange: " << changeType;
735 }
736 }
737
738 // Set by KApplication
739 QString kde_overrideStyle;
740
applyGUIStyle()741 void KGlobalSettings::Private::applyGUIStyle()
742 {
743 #if 0 // Disabled for KF5. TODO Qt5: check that the KDE style is correctly applied.
744 //Platform plugin only loaded on X11 systems
745 #if HAVE_X11
746 if (!kde_overrideStyle.isEmpty()) {
747 const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
748 if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
749 0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
750 qApp->setStyle(kde_overrideStyle);
751 }
752 } else {
753 emit q->kdisplayStyleChanged();
754 }
755 #else
756 const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
757
758 if (kde_overrideStyle.isEmpty()) {
759 const QString &defaultStyle = KStyle::defaultStyle();
760 const KConfigGroup pConfig(KSharedConfig::openConfig(), "General");
761 const QString &styleStr = pConfig.readEntry("widgetStyle", defaultStyle);
762
763 if (styleStr.isEmpty() ||
764 // check whether we already use the correct style to return then
765 // (workaround for Qt misbehavior to avoid double style initialization)
766 0 == (QString(styleStr + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive) ||
767 0 == styleStr.compare(currentStyleName, Qt::CaseInsensitive)) {
768 return;
769 }
770
771 QStyle *sp = QStyleFactory::create(styleStr);
772 if (sp && currentStyleName == sp->metaObject()->className()) {
773 delete sp;
774 return;
775 }
776
777 // If there is no default style available, try falling back any available style
778 if (!sp && styleStr != defaultStyle) {
779 sp = QStyleFactory::create(defaultStyle);
780 }
781 if (!sp) {
782 sp = QStyleFactory::create(QStyleFactory::keys().first());
783 }
784 qApp->setStyle(sp);
785 } else if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
786 0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
787 qApp->setStyle(kde_overrideStyle);
788 }
789 emit q->kdisplayStyleChanged();
790 #endif //HAVE_X11
791 #endif
792 }
793
createApplicationPalette(const KSharedConfigPtr & config)794 QPalette KGlobalSettings::createApplicationPalette(const KSharedConfigPtr &config)
795 {
796 return self()->d->createApplicationPalette(config);
797 }
798
createNewApplicationPalette(const KSharedConfigPtr & config)799 QPalette KGlobalSettings::createNewApplicationPalette(const KSharedConfigPtr &config)
800 {
801 return self()->d->createNewApplicationPalette(config);
802 }
803
createApplicationPalette(const KSharedConfigPtr & config)804 QPalette KGlobalSettings::Private::createApplicationPalette(const KSharedConfigPtr &config)
805 {
806 // This method is typically called once by KQGuiPlatformPlugin::palette and once again
807 // by kdisplaySetPalette(), so we cache the palette to save time.
808 if (config == KSharedConfig::openConfig() && paletteCreated) {
809 return applicationPalette;
810 }
811 return createNewApplicationPalette(config);
812 }
813
createNewApplicationPalette(const KSharedConfigPtr & config)814 QPalette KGlobalSettings::Private::createNewApplicationPalette(const KSharedConfigPtr &config)
815 {
816 QPalette palette = KColorScheme::createApplicationPalette(config);
817
818 if (config == KSharedConfig::openConfig()) {
819 paletteCreated = true;
820 applicationPalette = palette;
821 }
822
823 return palette;
824 }
825
kdisplaySetPalette()826 void KGlobalSettings::Private::kdisplaySetPalette()
827 {
828 #if !defined(Q_OS_WINCE)
829 if (!kdeFullSession) {
830 return;
831 }
832
833 QApplication::setPalette(q->createApplicationPalette());
834 emit q->kdisplayPaletteChanged();
835 emit q->appearanceChanged();
836 #endif
837 }
838
kdisplaySetFont()839 void KGlobalSettings::Private::kdisplaySetFont()
840 {
841 #if !defined(Q_OS_WINCE)
842 if (!kdeFullSession) {
843 return;
844 }
845
846 QDBusMessage message = QDBusMessage::createSignal("/KDEPlatformTheme", "org.kde.KDEPlatformTheme", "refreshFonts");
847 QDBusConnection::sessionBus().send(message);
848 emit q->kdisplayFontChanged();
849 #endif
850 }
851
kdisplaySetStyle()852 void KGlobalSettings::Private::kdisplaySetStyle()
853 {
854 applyGUIStyle();
855
856 // Reread palette from config file.
857 kdisplaySetPalette();
858 }
859
reloadStyleSettings()860 void KGlobalSettings::Private::reloadStyleSettings()
861 {
862 KConfigGroup g(KSharedConfig::openConfig(), "KDE-Global GUI Settings");
863
864 // Asking for hasKey we do not ask for graphicEffectsLevelDefault() that can
865 // contain some very slow code. If we can save that time, do it. (ereslibre)
866
867 if (g.hasKey("GraphicEffectsLevel")) {
868 _graphicEffects = ((GraphicEffects) g.readEntry("GraphicEffectsLevel", QVariant((int) NoEffects)).toInt());
869
870 return;
871 }
872
873 _graphicEffects = KGlobalSettings::graphicEffectsLevelDefault();
874 }
875
applyCursorTheme()876 void KGlobalSettings::Private::applyCursorTheme()
877 {
878 #if HAVE_X11 && defined(HAVE_XCURSOR)
879 if (!isX11) {
880 return;
881 }
882 KConfig config("kcminputrc");
883 KConfigGroup g(&config, "Mouse");
884
885 QString theme = g.readEntry("cursorTheme", QString());
886 int size = g.readEntry("cursorSize", -1);
887
888 // Default cursor size is 16 points
889 if (size == -1) {
890 QApplication *app = static_cast<QApplication *>(QApplication::instance());
891 size = app->desktop()->screen(0)->logicalDpiY() * 16 / 72;
892 }
893
894 // Note that in X11R7.1 and earlier, calling XcursorSetTheme()
895 // with a NULL theme would cause Xcursor to use "default", but
896 // in 7.2 and later it will cause it to revert to the theme that
897 // was configured when the application was started.
898 XcursorSetTheme(QX11Info::display(), theme.isNull() ?
899 "default" : QFile::encodeName(theme));
900 XcursorSetDefaultSize(QX11Info::display(), size);
901
902 emit q->cursorChanged();
903 #endif
904 }
905
propagateQtSettings()906 void KGlobalSettings::Private::propagateQtSettings()
907 {
908 KConfigGroup cg(KSharedConfig::openConfig(), "KDE");
909
910 #ifndef Q_OS_WIN
911 int num = cg.readEntry("CursorBlinkRate", QApplication::cursorFlashTime());
912 if ((num != 0) && (num < 200)) {
913 num = 200;
914 }
915 if (num > 2000) {
916 num = 2000;
917 }
918 QApplication::setCursorFlashTime(num);
919 #else
920 int num;
921 #endif
922 num = cg.readEntry("DoubleClickInterval", QApplication::doubleClickInterval());
923 QApplication::setDoubleClickInterval(num);
924 num = cg.readEntry("StartDragTime", QApplication::startDragTime());
925 QApplication::setStartDragTime(num);
926 num = cg.readEntry("StartDragDist", QApplication::startDragDistance());
927 QApplication::setStartDragDistance(num);
928 num = cg.readEntry("WheelScrollLines", QApplication::wheelScrollLines());
929 QApplication::setWheelScrollLines(num);
930 bool showIcons = cg.readEntry("ShowIconsInMenuItems", !QApplication::testAttribute(Qt::AA_DontShowIconsInMenus));
931 QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !showIcons);
932
933 // KDE5: this seems fairly pointless
934 emit q->settingsChanged(SETTINGS_QT);
935 }
936
dropMouseSettingsCache()937 void KGlobalSettings::Private::dropMouseSettingsCache()
938 {
939 #ifndef Q_OS_WIN
940 delete self()->d->mMouseSettings;
941 self()->d->mMouseSettings = nullptr;
942 #endif
943 }
944
945 #include "moc_kglobalsettings.cpp"
946