File indexing completed on 2024-04-21 14:55:54

0001 /* This file is part of the KDE libraries
0002    Copyright (C) 2000, 2006 David Faure <faure@kde.org>
0003    Copyright 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License version 2 as published by the Free Software Foundation.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "kglobalsettings.h"
0021 
0022 #include <ktoolbar.h>
0023 #include <kconfig.h>
0024 #include <kcolorscheme.h>
0025 
0026 //#include <kstyle.h>
0027 
0028 #include <QColor>
0029 #include <QCursor>
0030 #include <QDesktopWidget>
0031 #include <QDir>
0032 #include <QFont>
0033 #include <QFontDatabase>
0034 #include <QFontInfo>
0035 #include <QKeySequence>
0036 #include <QPixmap>
0037 #include <QPixmapCache>
0038 #include <QApplication>
0039 #include <QDBusConnection>
0040 #include <QStyleFactory>
0041 #include <QDebug>
0042 #include <qstandardpaths.h>
0043 
0044 // next two needed so we can set their palettes
0045 #include <QDBusMessage>
0046 #include <QToolTip>
0047 #include <QUrl>
0048 #include <QWhatsThis>
0049 
0050 #ifdef Q_OS_WIN
0051 #include <windows.h>
0052 
0053 static QRgb qt_colorref2qrgb(COLORREF col)
0054 {
0055     return qRgb(GetRValue(col), GetGValue(col), GetBValue(col));
0056 }
0057 #endif
0058 #include <config-kdelibs4support.h>
0059 #if HAVE_X11
0060 #include <X11/Xlib.h>
0061 #ifdef HAVE_XCURSOR // TODO NOT DEFINED ANYMORE. Can we drop X cursor themes?
0062 #include <X11/Xcursor/Xcursor.h>
0063 #endif
0064 //#include "fixx11h.h"
0065 #include <QX11Info>
0066 #endif
0067 
0068 #include <stdlib.h>
0069 #include <kconfiggroup.h>
0070 #include <kiconloader.h>
0071 
0072 //static QColor *_buttonBackground = 0;
0073 static KGlobalSettings::GraphicEffects _graphicEffects = KGlobalSettings::NoEffects;
0074 
0075 class Q_DECL_HIDDEN KGlobalSettings::Private
0076 {
0077 public:
0078     Private(KGlobalSettings *q)
0079     : q(q), activated(false), paletteCreated(false), mMouseSettings(nullptr), mLargeFont(nullptr)
0080 #if HAVE_X11
0081         , isX11(QX11Info::isPlatformX11())
0082 #endif
0083     {
0084         kdeFullSession = !qgetenv("KDE_FULL_SESSION").isEmpty();
0085     }
0086 
0087     QPalette createApplicationPalette(const KSharedConfigPtr &config);
0088     QPalette createNewApplicationPalette(const KSharedConfigPtr &config);
0089     void _k_slotNotifyChange(int, int);
0090     void _k_slotIconChange(int);
0091 
0092     void propagateQtSettings();
0093     void kdisplaySetPalette();
0094     void kdisplaySetStyle();
0095     void kdisplaySetFont();
0096     void applyGUIStyle();
0097     void dropMouseSettingsCache();
0098     KGlobalSettings::KMouseSettings &mouseSettings();
0099 
0100     /**
0101      * @internal
0102      *
0103      * Ensures that cursors are loaded from the theme KDE is configured
0104      * to use. Note that calling this function doesn't cause existing
0105      * cursors to be reloaded. Reloading already created cursors is
0106      * handled by the KCM when a cursor theme is applied.
0107      *
0108      * It is not necessary to call this function when KGlobalSettings
0109      * is initialized.
0110      */
0111     void applyCursorTheme();
0112 
0113     static void reloadStyleSettings();
0114 
0115     QFont largeFont(const QString &text);
0116 
0117     KGlobalSettings *q;
0118     bool activated;
0119     bool paletteCreated;
0120     bool kdeFullSession;
0121     QPalette applicationPalette;
0122     KGlobalSettings::KMouseSettings *mMouseSettings;
0123     QFont *mLargeFont;
0124 #if HAVE_X11
0125     bool isX11;
0126 #endif
0127 };
0128 
0129 // class for access to KGlobalSettings constructor
0130 class KGlobalSettingsSingleton
0131 {
0132 public:
0133     KGlobalSettings object;
0134 };
0135 
0136 Q_GLOBAL_STATIC(KGlobalSettingsSingleton, s_self)
0137 
0138 KGlobalSettings *KGlobalSettings::self()
0139 {
0140     return &s_self()->object;
0141 }
0142 
0143 KGlobalSettings::KGlobalSettings()
0144     : QObject(nullptr), d(new Private(this))
0145 {
0146     connect(this, SIGNAL(kdisplayFontChanged()), SIGNAL(appearanceChanged()));
0147 }
0148 
0149 KGlobalSettings::~KGlobalSettings()
0150 {
0151     delete d;
0152 }
0153 
0154 void KGlobalSettings::activate()
0155 {
0156     activate(ApplySettings | ListenForChanges);
0157 }
0158 
0159 void KGlobalSettings::activate(ActivateOptions options)
0160 {
0161     if (!d->activated) {
0162         d->activated = true;
0163 
0164         if (options & ListenForChanges) {
0165             QDBusConnection::sessionBus().connect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
0166                                                   "notifyChange", this, SLOT(_k_slotNotifyChange(int,int)));
0167             QDBusConnection::sessionBus().connect(QString(), "/KIconLoader", "org.kde.KIconLoader",
0168                                                   "iconChanged", this, SLOT(_k_slotIconChange(int)));
0169             QDBusConnection::sessionBus().connect(QString(), "/KDEPlatformTheme", "org.kde.KDEPlatformTheme",
0170                                                   "refreshFonts", this, SLOT(kdisplayFontChanged()));
0171         }
0172 
0173         if (options & ApplySettings) {
0174             d->kdisplaySetStyle(); // implies palette setup
0175             d->propagateQtSettings();
0176         }
0177     }
0178 }
0179 
0180 // Qt5 TODO: implement QPlatformIntegration::styleHint so that it reads a Qt or KDE setting,
0181 // so that apps can just use QApplication::startDragDistance().
0182 int KGlobalSettings::dndEventDelay()
0183 {
0184     KConfigGroup g(KSharedConfig::openConfig(), "General");
0185     return g.readEntry("StartDragDist", QApplication::startDragDistance());
0186 }
0187 
0188 bool KGlobalSettings::singleClick()
0189 {
0190     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0191     return g.readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK);
0192 }
0193 
0194 bool KGlobalSettings::changeCursorOverIcon()
0195 {
0196     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0197     return g.readEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR);
0198 }
0199 
0200 int KGlobalSettings::autoSelectDelay()
0201 {
0202     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0203     return g.readEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY);
0204 }
0205 
0206 KGlobalSettings::Completion KGlobalSettings::completionMode()
0207 {
0208     int completion;
0209     KConfigGroup g(KSharedConfig::openConfig(), "General");
0210     completion = g.readEntry("completionMode", -1);
0211     if ((completion < (int) CompletionNone) ||
0212             (completion > (int) CompletionPopupAuto)) {
0213         completion = (int) CompletionPopup; // Default
0214     }
0215     return (Completion) completion;
0216 }
0217 
0218 bool KGlobalSettings::showContextMenusOnPress()
0219 {
0220     KConfigGroup g(KSharedConfig::openConfig(), "ContextMenus");
0221     return g.readEntry("ShowOnPress", true);
0222 }
0223 
0224 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0225 QColor KGlobalSettings::inactiveTitleColor()
0226 {
0227 #ifdef Q_OS_WIN
0228     return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION));
0229 #else
0230     KConfigGroup g(KSharedConfig::openConfig(), "WM");
0231     return g.readEntry("inactiveBackground", QColor(224, 223, 222));
0232 #endif
0233 }
0234 
0235 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0236 QColor KGlobalSettings::inactiveTextColor()
0237 {
0238 #ifdef Q_OS_WIN
0239     return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
0240 #else
0241     KConfigGroup g(KSharedConfig::openConfig(), "WM");
0242     return g.readEntry("inactiveForeground", QColor(75, 71, 67));
0243 #endif
0244 }
0245 
0246 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0247 QColor KGlobalSettings::activeTitleColor()
0248 {
0249 #ifdef Q_OS_WIN
0250     return qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION));
0251 #else
0252     KConfigGroup g(KSharedConfig::openConfig(), "WM");
0253     return g.readEntry("activeBackground", QColor(48, 174, 232));
0254 #endif
0255 }
0256 
0257 // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
0258 QColor KGlobalSettings::activeTextColor()
0259 {
0260 #ifdef Q_OS_WIN
0261     return qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT));
0262 #else
0263     KConfigGroup g(KSharedConfig::openConfig(), "WM");
0264     return g.readEntry("activeForeground", QColor(255, 255, 255));
0265 #endif
0266 }
0267 
0268 int KGlobalSettings::contrast()
0269 {
0270     return KColorScheme::contrast();
0271 }
0272 
0273 qreal KGlobalSettings::contrastF(const KSharedConfigPtr &config)
0274 {
0275     return KColorScheme::contrastF(config);
0276 }
0277 
0278 bool KGlobalSettings::shadeSortColumn()
0279 {
0280     KConfigGroup g(KSharedConfig::openConfig(), "General");
0281     return g.readEntry("shadeSortColumn", KDE_DEFAULT_SHADE_SORT_COLUMN);
0282 }
0283 
0284 bool KGlobalSettings::allowDefaultBackgroundImages()
0285 {
0286     KConfigGroup g(KSharedConfig::openConfig(), "General");
0287     return g.readEntry("allowDefaultBackgroundImages", KDE_DEFAULT_ALLOW_DEFAULT_BACKGROUND_IMAGES);
0288 }
0289 
0290 //inspired in old KGlobalSettingsData code
0291 QFont constructFontFromConfig(const char *groupKey, const char *configKey)
0292 {
0293     const KConfigGroup configGroup(KSharedConfig::openConfig(), groupKey);
0294     QFont ret;
0295     ret.setStyleHint(QFont::SansSerif);
0296     ret = configGroup.readEntry(configKey, ret);
0297     return ret;
0298 }
0299 
0300 QFont KGlobalSettings::generalFont()
0301 {
0302     return QFontDatabase::systemFont(QFontDatabase::GeneralFont);
0303 }
0304 QFont KGlobalSettings::fixedFont()
0305 {
0306     return QFontDatabase::systemFont(QFontDatabase::FixedFont);
0307 }
0308 QFont KGlobalSettings::windowTitleFont()
0309 {
0310     return QFontDatabase::systemFont(QFontDatabase::TitleFont);
0311 }
0312 QFont KGlobalSettings::smallestReadableFont()
0313 {
0314     return QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
0315 }
0316 QFont KGlobalSettings::toolBarFont()
0317 {
0318     return constructFontFromConfig("General", "toolBarFont");
0319 }
0320 QFont KGlobalSettings::menuFont()
0321 {
0322     return constructFontFromConfig("General", "menuFont");
0323 }
0324 QFont KGlobalSettings::taskbarFont()
0325 {
0326     return constructFontFromConfig("General", "taskbarFont");
0327 }
0328 
0329 QFont KGlobalSettings::Private::largeFont(const QString &text)
0330 {
0331     QFontDatabase db;
0332     QStringList fam = db.families();
0333 
0334     // Move a bunch of preferred fonts to the front.
0335     // most preferred last
0336     static const char *const PreferredFontNames[] = {
0337         "Arial",
0338         "Sans Serif",
0339         "Verdana",
0340         "Tahoma",
0341         "Lucida Sans",
0342         "Lucidux Sans",
0343         "Nimbus Sans",
0344         "Gothic I"
0345     };
0346     static const unsigned int PreferredFontNamesCount = sizeof(PreferredFontNames) / sizeof(const char *);
0347     for (unsigned int i = 0; i < PreferredFontNamesCount; ++i) {
0348         const QString fontName(PreferredFontNames[i]);
0349         if (fam.removeAll(fontName) > 0) {
0350             fam.prepend(fontName);
0351         }
0352     }
0353 
0354     if (mLargeFont) {
0355         fam.prepend(mLargeFont->family());
0356         delete mLargeFont;
0357     }
0358 
0359     for (QStringList::ConstIterator it = fam.constBegin();
0360             it != fam.constEnd(); ++it) {
0361         if (db.isSmoothlyScalable(*it) && !db.isFixedPitch(*it)) {
0362             QFont font(*it);
0363             font.setPixelSize(75);
0364             QFontMetrics metrics(font);
0365             int h = metrics.height();
0366             if ((h < 60) || (h > 90)) {
0367                 continue;
0368             }
0369 
0370             bool ok = true;
0371             for (int i = 0; i < text.length(); i++) {
0372                 if (!metrics.inFont(text[i])) {
0373                     ok = false;
0374                     break;
0375                 }
0376             }
0377             if (!ok) {
0378                 continue;
0379             }
0380 
0381             font.setPointSize(48);
0382             mLargeFont = new QFont(font);
0383             return *mLargeFont;
0384         }
0385     }
0386     mLargeFont = new QFont(q->generalFont());
0387     mLargeFont->setPointSize(48);
0388     return *mLargeFont;
0389 }
0390 
0391 QFont KGlobalSettings::largeFont(const QString &text)
0392 {
0393     return self()->d->largeFont(text);
0394 }
0395 
0396 KGlobalSettings::KMouseSettings &KGlobalSettings::Private::mouseSettings()
0397 {
0398     if (!mMouseSettings) {
0399         mMouseSettings = new KGlobalSettings::KMouseSettings;
0400         KGlobalSettings::KMouseSettings &s = *mMouseSettings; // for convenience
0401 
0402 #ifndef Q_OS_WIN
0403         KConfigGroup g(KSharedConfig::openConfig(), "Mouse");
0404         QString setting = g.readEntry("MouseButtonMapping");
0405         if (setting == "RightHanded") {
0406             s.handed = KGlobalSettings::KMouseSettings::RightHanded;
0407         } else if (setting == "LeftHanded") {
0408             s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
0409         } else {
0410 #if HAVE_X11
0411         if (isX11) {
0412             // get settings from X server
0413             // This is a simplified version of the code in input/mouse.cpp
0414             // Keep in sync !
0415             s.handed = KGlobalSettings::KMouseSettings::RightHanded;
0416             unsigned char map[20];
0417             int num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
0418             if (num_buttons == 2) {
0419                 if ((int)map[0] == 1 && (int)map[1] == 2) {
0420                     s.handed = KGlobalSettings::KMouseSettings::RightHanded;
0421                 } else if ((int)map[0] == 2 && (int)map[1] == 1) {
0422                     s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
0423                 }
0424             } else if (num_buttons >= 3) {
0425                 if ((int)map[0] == 1 && (int)map[2] == 3) {
0426                     s.handed = KGlobalSettings::KMouseSettings::RightHanded;
0427                 } else if ((int)map[0] == 3 && (int)map[2] == 1) {
0428                     s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
0429                 }
0430             }
0431         }
0432 #else
0433             // FIXME: Implement on other platforms
0434 #endif
0435         }
0436 #endif //Q_OS_WIN
0437     }
0438 #ifdef Q_OS_WIN
0439     //not cached
0440 #ifndef _WIN32_WCE
0441     mMouseSettings->handed = (GetSystemMetrics(SM_SWAPBUTTON) ?
0442                               KGlobalSettings::KMouseSettings::LeftHanded :
0443                               KGlobalSettings::KMouseSettings::RightHanded);
0444 #else
0445 // There is no mice under wince
0446     mMouseSettings->handed = KGlobalSettings::KMouseSettings::RightHanded;
0447 #endif
0448 #endif
0449     return *mMouseSettings;
0450 }
0451 // KDE5: make this a const return?
0452 KGlobalSettings::KMouseSettings &KGlobalSettings::mouseSettings()
0453 {
0454     return self()->d->mouseSettings();
0455 }
0456 
0457 QString KGlobalSettings::desktopPath()
0458 {
0459     QString path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
0460     return path.isEmpty() ? QDir::homePath() : path;
0461 }
0462 
0463 // This was the KDE-specific autostart folder in KDEHOME.
0464 // KDE 5 : re-evaluate this, I'd say the xdg autostart spec supersedes this, and is sufficient
0465 // (since there's a GUI for creating the necessary desktop files)
0466 #if 0
0467 QString KGlobalSettings::autostartPath()
0468 {
0469     QString s_autostartPath;
0470     KConfigGroup g(KSharedConfig::openConfig(), "Paths");
0471     s_autostartPath = KGlobal::dirs()->localkdedir() + "Autostart/";
0472     s_autostartPath = g.readPathEntry("Autostart", s_autostartPath);
0473     s_autostartPath = QDir::cleanPath(s_autostartPath);
0474     if (!s_autostartPath.endsWith('/')) {
0475         s_autostartPath.append(QLatin1Char('/'));
0476     }
0477     return s_autostartPath;
0478 }
0479 #endif
0480 
0481 QString KGlobalSettings::documentPath()
0482 {
0483     QString path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
0484     return path.isEmpty() ? QDir::homePath() : path;
0485 }
0486 
0487 QString KGlobalSettings::downloadPath()
0488 {
0489     QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
0490     return path.isEmpty() ? QDir::homePath() : path;
0491 }
0492 
0493 QString KGlobalSettings::videosPath()
0494 {
0495     QString path = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
0496     return path.isEmpty() ? QDir::homePath() : path;
0497 }
0498 
0499 QString KGlobalSettings::picturesPath()
0500 {
0501     QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
0502     return path.isEmpty() ? QDir::homePath() : path;
0503 }
0504 
0505 QString KGlobalSettings::musicPath()
0506 {
0507     QString path = QStandardPaths::writableLocation(QStandardPaths::MusicLocation);
0508     return path.isEmpty() ? QDir::homePath() : path;
0509 }
0510 
0511 bool KGlobalSettings::isMultiHead()
0512 {
0513 #ifdef Q_OS_WIN
0514     return GetSystemMetrics(SM_CMONITORS) > 1;
0515 #else
0516     QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
0517     if (!multiHead.isEmpty()) {
0518         return (multiHead.toLower() == "true");
0519     }
0520     return false;
0521 #endif
0522 }
0523 
0524 bool KGlobalSettings::wheelMouseZooms()
0525 {
0526     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0527     return g.readEntry("WheelMouseZooms", KDE_DEFAULT_WHEEL_ZOOM);
0528 }
0529 
0530 QRect KGlobalSettings::splashScreenDesktopGeometry()
0531 {
0532     return QApplication::desktop()->screenGeometry(QCursor::pos());
0533 }
0534 
0535 QRect KGlobalSettings::desktopGeometry(const QPoint &point)
0536 {
0537     return QApplication::desktop()->screenGeometry(point);
0538 }
0539 
0540 QRect KGlobalSettings::desktopGeometry(const QWidget *w)
0541 {
0542     return QApplication::desktop()->screenGeometry(w);
0543 }
0544 
0545 bool KGlobalSettings::showIconsOnPushButtons()
0546 {
0547     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0548     return g.readEntry("ShowIconsOnPushButtons",
0549                        KDE_DEFAULT_ICON_ON_PUSHBUTTON);
0550 }
0551 
0552 bool KGlobalSettings::naturalSorting()
0553 {
0554     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0555     return g.readEntry("NaturalSorting",
0556                        KDE_DEFAULT_NATURAL_SORTING);
0557 }
0558 
0559 KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevel()
0560 {
0561     // This variable stores whether _graphicEffects has the default value because it has not been
0562     // loaded yet, or if it has been loaded from the user settings or defaults and contains a valid
0563     // value.
0564     static bool _graphicEffectsInitialized = false;
0565 
0566     if (!_graphicEffectsInitialized) {
0567         _graphicEffectsInitialized = true;
0568         Private::reloadStyleSettings();
0569     }
0570 
0571     return _graphicEffects;
0572 }
0573 
0574 KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevelDefault()
0575 {
0576     // For now, let always enable animations by default. The plan is to make
0577     // this code a bit smarter. (ereslibre)
0578 
0579     return ComplexAnimationEffects;
0580 }
0581 
0582 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
0583 bool KGlobalSettings::showFilePreview(const QUrl &url)
0584 {
0585     KConfigGroup g(KSharedConfig::openConfig(), "PreviewSettings");
0586     bool defaultSetting = url.isLocalFile(); // ## incorrect, use KProtocolInfo::showFilePreview instead
0587     return g.readEntry(url.scheme(), defaultSetting);
0588 }
0589 #endif
0590 
0591 bool KGlobalSettings::opaqueResize()
0592 {
0593     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0594     return g.readEntry("OpaqueResize", KDE_DEFAULT_OPAQUE_RESIZE);
0595 }
0596 
0597 int KGlobalSettings::buttonLayout()
0598 {
0599     KConfigGroup g(KSharedConfig::openConfig(), "KDE");
0600     return g.readEntry("ButtonLayout", KDE_DEFAULT_BUTTON_LAYOUT);
0601 }
0602 
0603 #if 0 // HAVE_X11 && QT_VERSION >= QT_VERSION_CHECK(5,0,0)
0604 // Taken from Qt-4.x qt_x11_apply_settings_in_all_apps since Qt5 doesn't have it anymore.
0605 // TODO: evaluate if this is still needed
0606 // TODO: if yes, this code should be an invokable method of the qxcb platform plugin?
0607 // TODO: it looks like the handling code for this in QPA is missing, too...
0608 static void x11_apply_settings_in_all_apps()
0609 {
0610     QByteArray stamp;
0611     QDataStream s(&stamp, QIODevice::WriteOnly);
0612     s << QDateTime::currentDateTime();
0613 
0614     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
0615     settings_atom_name += XDisplayString(QX11Info::display());
0616 
0617     xcb_connection_t *xcb_conn = QX11Info::connection();
0618     xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData());
0619     xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0);
0620     xcb_atom_t atom = reply->atom;
0621     free(reply);
0622 
0623     xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, QX11Info::appRootWindow(), atom, XCB_ATOM_ATOM,
0624                         8, stamp.size(), (const void *)stamp.constData());
0625 
0626     //XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
0627     //ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
0628     //PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
0629 }
0630 #endif
0631 
0632 void KGlobalSettings::emitChange(ChangeType changeType, int arg)
0633 {
0634     switch (changeType) {
0635     case IconChanged:
0636         KIconLoader::emitChange(KIconLoader::Group(arg));
0637         break;
0638     case ToolbarStyleChanged:
0639         KToolBar::emitToolbarStyleChanged();
0640         break;
0641     case FontChanged:
0642         self()->d->kdisplaySetFont();
0643         break;
0644     default: {
0645         QDBusMessage message = QDBusMessage::createSignal("/KGlobalSettings", "org.kde.KGlobalSettings", "notifyChange");
0646         QList<QVariant> args;
0647         args.append(static_cast<int>(changeType));
0648         args.append(arg);
0649         message.setArguments(args);
0650         QDBusConnection::sessionBus().send(message);
0651     }   break;
0652 
0653     }
0654 }
0655 
0656 void KGlobalSettings::Private::_k_slotIconChange(int arg)
0657 {
0658     _k_slotNotifyChange(IconChanged, arg);
0659 }
0660 
0661 void KGlobalSettings::Private::_k_slotNotifyChange(int changeType, int arg)
0662 {
0663     switch (changeType) {
0664     case StyleChanged:
0665         if (activated) {
0666             KSharedConfig::openConfig()->reparseConfiguration();
0667             kdisplaySetStyle();
0668         }
0669         break;
0670 
0671     case ToolbarStyleChanged:
0672         KSharedConfig::openConfig()->reparseConfiguration();
0673         emit q->toolbarAppearanceChanged(arg);
0674         break;
0675 
0676     case PaletteChanged:
0677         if (activated) {
0678             KSharedConfig::openConfig()->reparseConfiguration();
0679             paletteCreated = false;
0680             kdisplaySetPalette();
0681         }
0682         break;
0683 
0684     case FontChanged:
0685         Q_ASSERT(false && "shouldn't get here now...");
0686         break;
0687 
0688     case SettingsChanged: {
0689         KSharedConfig::openConfig()->reparseConfiguration();
0690         SettingsCategory category = static_cast<SettingsCategory>(arg);
0691         if (category == SETTINGS_QT) {
0692             if (activated) {
0693                 propagateQtSettings();
0694             }
0695         } else {
0696             switch (category) {
0697             case SETTINGS_STYLE:
0698                 reloadStyleSettings();
0699                 break;
0700             case SETTINGS_MOUSE:
0701                 self()->d->dropMouseSettingsCache();
0702                 break;
0703             case SETTINGS_LOCALE:
0704                 // QT5 TODO REPLACEMENT ? KLocale::global()->reparseConfiguration();
0705                 break;
0706             default:
0707                 break;
0708             }
0709             emit q->settingsChanged(category);
0710         }
0711         break;
0712     }
0713     case IconChanged:
0714         QPixmapCache::clear();
0715         KSharedConfig::openConfig()->reparseConfiguration();
0716         emit q->iconChanged(arg);
0717         break;
0718 
0719     case CursorChanged:
0720         applyCursorTheme();
0721         break;
0722 
0723     case BlockShortcuts:
0724         // FIXME KAccel port
0725         //KGlobalAccel::blockShortcuts(arg);
0726         emit q->blockShortcuts(arg); // see kwin
0727         break;
0728 
0729     case NaturalSortingChanged:
0730         emit q->naturalSortingChanged();
0731         break;
0732 
0733     default:
0734         qWarning() << "Unknown type of change in KGlobalSettings::slotNotifyChange: " << changeType;
0735     }
0736 }
0737 
0738 // Set by KApplication
0739 QString kde_overrideStyle;
0740 
0741 void KGlobalSettings::Private::applyGUIStyle()
0742 {
0743 #if 0 // Disabled for KF5. TODO Qt5: check that the KDE style is correctly applied.
0744     //Platform plugin only loaded on X11 systems
0745 #if HAVE_X11
0746     if (!kde_overrideStyle.isEmpty()) {
0747         const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
0748         if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
0749                 0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
0750             qApp->setStyle(kde_overrideStyle);
0751         }
0752     } else {
0753         emit q->kdisplayStyleChanged();
0754     }
0755 #else
0756     const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
0757 
0758     if (kde_overrideStyle.isEmpty()) {
0759         const QString &defaultStyle = KStyle::defaultStyle();
0760         const KConfigGroup pConfig(KSharedConfig::openConfig(), "General");
0761         const QString &styleStr = pConfig.readEntry("widgetStyle", defaultStyle);
0762 
0763         if (styleStr.isEmpty() ||
0764                 // check whether we already use the correct style to return then
0765                 // (workaround for Qt misbehavior to avoid double style initialization)
0766                 0 == (QString(styleStr + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive) ||
0767                 0 == styleStr.compare(currentStyleName, Qt::CaseInsensitive)) {
0768             return;
0769         }
0770 
0771         QStyle *sp = QStyleFactory::create(styleStr);
0772         if (sp && currentStyleName == sp->metaObject()->className()) {
0773             delete sp;
0774             return;
0775         }
0776 
0777         // If there is no default style available, try falling back any available style
0778         if (!sp && styleStr != defaultStyle) {
0779             sp = QStyleFactory::create(defaultStyle);
0780         }
0781         if (!sp) {
0782             sp = QStyleFactory::create(QStyleFactory::keys().first());
0783         }
0784         qApp->setStyle(sp);
0785     } else if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
0786                0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
0787         qApp->setStyle(kde_overrideStyle);
0788     }
0789     emit q->kdisplayStyleChanged();
0790 #endif //HAVE_X11
0791 #endif
0792 }
0793 
0794 QPalette KGlobalSettings::createApplicationPalette(const KSharedConfigPtr &config)
0795 {
0796     return self()->d->createApplicationPalette(config);
0797 }
0798 
0799 QPalette KGlobalSettings::createNewApplicationPalette(const KSharedConfigPtr &config)
0800 {
0801     return self()->d->createNewApplicationPalette(config);
0802 }
0803 
0804 QPalette KGlobalSettings::Private::createApplicationPalette(const KSharedConfigPtr &config)
0805 {
0806     // This method is typically called once by KQGuiPlatformPlugin::palette and once again
0807     // by kdisplaySetPalette(), so we cache the palette to save time.
0808     if (config == KSharedConfig::openConfig() && paletteCreated) {
0809         return applicationPalette;
0810     }
0811     return createNewApplicationPalette(config);
0812 }
0813 
0814 QPalette KGlobalSettings::Private::createNewApplicationPalette(const KSharedConfigPtr &config)
0815 {
0816     QPalette palette = KColorScheme::createApplicationPalette(config);
0817 
0818     if (config == KSharedConfig::openConfig()) {
0819         paletteCreated = true;
0820         applicationPalette = palette;
0821     }
0822 
0823     return palette;
0824 }
0825 
0826 void KGlobalSettings::Private::kdisplaySetPalette()
0827 {
0828 #if !defined(Q_OS_WINCE)
0829     if (!kdeFullSession) {
0830         return;
0831     }
0832 
0833     QApplication::setPalette(q->createApplicationPalette());
0834     emit q->kdisplayPaletteChanged();
0835     emit q->appearanceChanged();
0836 #endif
0837 }
0838 
0839 void KGlobalSettings::Private::kdisplaySetFont()
0840 {
0841 #if !defined(Q_OS_WINCE)
0842     if (!kdeFullSession) {
0843         return;
0844     }
0845 
0846     QDBusMessage message = QDBusMessage::createSignal("/KDEPlatformTheme", "org.kde.KDEPlatformTheme", "refreshFonts");
0847     QDBusConnection::sessionBus().send(message);
0848     emit q->kdisplayFontChanged();
0849 #endif
0850 }
0851 
0852 void KGlobalSettings::Private::kdisplaySetStyle()
0853 {
0854     applyGUIStyle();
0855 
0856     // Reread palette from config file.
0857     kdisplaySetPalette();
0858 }
0859 
0860 void KGlobalSettings::Private::reloadStyleSettings()
0861 {
0862     KConfigGroup g(KSharedConfig::openConfig(), "KDE-Global GUI Settings");
0863 
0864     // Asking for hasKey we do not ask for graphicEffectsLevelDefault() that can
0865     // contain some very slow code. If we can save that time, do it. (ereslibre)
0866 
0867     if (g.hasKey("GraphicEffectsLevel")) {
0868         _graphicEffects = ((GraphicEffects) g.readEntry("GraphicEffectsLevel", QVariant((int) NoEffects)).toInt());
0869 
0870         return;
0871     }
0872 
0873     _graphicEffects = KGlobalSettings::graphicEffectsLevelDefault();
0874 }
0875 
0876 void KGlobalSettings::Private::applyCursorTheme()
0877 {
0878 #if HAVE_X11 && defined(HAVE_XCURSOR)
0879     if (!isX11) {
0880         return;
0881     }
0882     KConfig config("kcminputrc");
0883     KConfigGroup g(&config, "Mouse");
0884 
0885     QString theme = g.readEntry("cursorTheme", QString());
0886     int size      = g.readEntry("cursorSize", -1);
0887 
0888     // Default cursor size is 16 points
0889     if (size == -1) {
0890         QApplication *app = static_cast<QApplication *>(QApplication::instance());
0891         size = app->desktop()->screen(0)->logicalDpiY() * 16 / 72;
0892     }
0893 
0894     // Note that in X11R7.1 and earlier, calling XcursorSetTheme()
0895     // with a NULL theme would cause Xcursor to use "default", but
0896     // in 7.2 and later it will cause it to revert to the theme that
0897     // was configured when the application was started.
0898     XcursorSetTheme(QX11Info::display(), theme.isNull() ?
0899                     "default" : QFile::encodeName(theme));
0900     XcursorSetDefaultSize(QX11Info::display(), size);
0901 
0902     emit q->cursorChanged();
0903 #endif
0904 }
0905 
0906 void KGlobalSettings::Private::propagateQtSettings()
0907 {
0908     KConfigGroup cg(KSharedConfig::openConfig(), "KDE");
0909 
0910 #ifndef Q_OS_WIN
0911     int num = cg.readEntry("CursorBlinkRate", QApplication::cursorFlashTime());
0912     if ((num != 0) && (num < 200)) {
0913         num = 200;
0914     }
0915     if (num > 2000) {
0916         num = 2000;
0917     }
0918     QApplication::setCursorFlashTime(num);
0919 #else
0920     int num;
0921 #endif
0922     num = cg.readEntry("DoubleClickInterval", QApplication::doubleClickInterval());
0923     QApplication::setDoubleClickInterval(num);
0924     num = cg.readEntry("StartDragTime", QApplication::startDragTime());
0925     QApplication::setStartDragTime(num);
0926     num = cg.readEntry("StartDragDist", QApplication::startDragDistance());
0927     QApplication::setStartDragDistance(num);
0928     num = cg.readEntry("WheelScrollLines", QApplication::wheelScrollLines());
0929     QApplication::setWheelScrollLines(num);
0930     bool showIcons = cg.readEntry("ShowIconsInMenuItems", !QApplication::testAttribute(Qt::AA_DontShowIconsInMenus));
0931     QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !showIcons);
0932 
0933     // KDE5: this seems fairly pointless
0934     emit q->settingsChanged(SETTINGS_QT);
0935 }
0936 
0937 void KGlobalSettings::Private::dropMouseSettingsCache()
0938 {
0939 #ifndef Q_OS_WIN
0940     delete self()->d->mMouseSettings;
0941     self()->d->mMouseSettings = nullptr;
0942 #endif
0943 }
0944 
0945 #include "moc_kglobalsettings.cpp"