Warning, file /plasma/plasma-workspace/kcms/lookandfeel/lookandfeelmanager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2014 Marco Martin <mart@kde.org>
0003     SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in>
0004     SPDX-FileCopyrightText: 2019 Cyril Rossi <cyril.rossi@enioka.com>
0005     SPDX-FileCopyrightText: 2021 Benjamin Port <benjamin.port@enioka.com>
0006     SPDX-FileCopyrightText: 2022 Dominic Hayes <ferenosdev@outlook.com>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-only
0009 */
0010 
0011 #include "lookandfeelmanager.h"
0012 #include "../../startkde/plasmaautostart/plasmaautostart.h"
0013 #include "../colors/colorsapplicator.h"
0014 #include "config-kcm.h"
0015 #include "lookandfeeldata.h"
0016 #include "lookandfeelsettings.h"
0017 #include <KIO/CommandLauncherJob>
0018 #include <KSharedConfig>
0019 #include <QDBusConnection>
0020 #include <QDBusMessage>
0021 
0022 #ifdef HAVE_XCURSOR
0023 #include "../cursortheme/xcursor/xcursortheme.h"
0024 #include <X11/Xcursor/Xcursor.h>
0025 #endif
0026 
0027 LookAndFeelManager::LookAndFeelManager(QObject *parent)
0028     : QObject(parent)
0029     , m_data(new LookAndFeelData(this))
0030     , m_appearanceToApply(LookAndFeelManager::AppearanceToApply(LookAndFeelManager::AppearanceSettings))
0031     , m_layoutToApply(LookAndFeelManager::LayoutToApply(LookAndFeelManager::LayoutSettings))
0032     , m_plasmashellChanged(false)
0033     , m_fontsChanged(false)
0034 {
0035     m_applyLatteLayout = (KService::serviceByDesktopName("org.kde.latte-dock") != nullptr);
0036 }
0037 
0038 LookAndFeelSettings *LookAndFeelManager::settings() const
0039 {
0040     return m_data->settings();
0041 }
0042 
0043 void LookAndFeelManager::setAppearanceToApply(AppearanceToApply items)
0044 {
0045     if (m_appearanceToApply == items) {
0046         return;
0047     }
0048     m_appearanceToApply = items;
0049     Q_EMIT appearanceToApplyChanged();
0050 }
0051 
0052 LookAndFeelManager::AppearanceToApply LookAndFeelManager::appearanceToApply() const
0053 {
0054     return m_appearanceToApply;
0055 }
0056 
0057 void LookAndFeelManager::setLayoutToApply(LayoutToApply items)
0058 {
0059     if (m_layoutToApply == items) {
0060         return;
0061     }
0062     m_layoutToApply = items;
0063     Q_EMIT layoutToApplyChanged();
0064 }
0065 
0066 LookAndFeelManager::LayoutToApply LookAndFeelManager::layoutToApply() const
0067 {
0068     return m_layoutToApply;
0069 }
0070 
0071 void LookAndFeelManager::setSplashScreen(const QString &theme)
0072 {
0073     if (theme.isEmpty()) {
0074         return;
0075     }
0076 
0077     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("ksplashrc"));
0078     KConfigGroup group(config, QStringLiteral("KSplash"));
0079 
0080     KConfig configDefault(configDefaults(QStringLiteral("ksplashrc")));
0081     KConfigGroup defaultGroup(&configDefault, QStringLiteral("KSplash"));
0082     writeNewDefaults(group, defaultGroup, QStringLiteral("Theme"), theme);
0083     // TODO: a way to set none as spash in the l&f
0084     writeNewDefaults(group, defaultGroup, QStringLiteral("Engine"), QStringLiteral("KSplashQML"));
0085 }
0086 
0087 void LookAndFeelManager::setLockScreen(const QString &theme)
0088 {
0089     if (theme.isEmpty()) {
0090         return;
0091     }
0092 
0093     writeNewDefaults(QStringLiteral("kscreenlockerrc"), QStringLiteral("Greeter"), QStringLiteral("Theme"), theme);
0094 }
0095 
0096 void LookAndFeelManager::setWindowSwitcher(const QString &theme)
0097 {
0098     if (theme.isEmpty()) {
0099         return;
0100     }
0101 
0102     writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("TabBox"), QStringLiteral("LayoutName"), theme);
0103 }
0104 
0105 void LookAndFeelManager::setDesktopSwitcher(const QString &theme)
0106 {
0107     if (theme.isEmpty()) {
0108         return;
0109     }
0110 
0111     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kwinrc"));
0112     KConfigGroup group(config, QStringLiteral("TabBox"));
0113 
0114     KConfig configDefault(configDefaults(QStringLiteral("kwinrc")));
0115     KConfigGroup defaultGroup(&configDefault, QStringLiteral("TabBox"));
0116     writeNewDefaults(group, defaultGroup, QStringLiteral("DesktopLayout"), theme);
0117     writeNewDefaults(group, defaultGroup, QStringLiteral("DesktopListLayout"), theme);
0118 }
0119 
0120 void LookAndFeelManager::setWindowPlacement(const QString &value)
0121 {
0122     if (value.isEmpty()) {
0123         return;
0124     }
0125 
0126     writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("Windows"), QStringLiteral("Placement"), value);
0127 }
0128 
0129 void LookAndFeelManager::setShellPackage(const QString &value)
0130 {
0131     if (value.isEmpty()) {
0132         return;
0133     }
0134 
0135     writeNewDefaults(QStringLiteral("plasmashellrc"), QStringLiteral("Shell"), QStringLiteral("ShellPackage"), value);
0136     m_plasmashellChanged = true;
0137 }
0138 
0139 void LookAndFeelManager::setWindowDecoration(const QString &library, const QString &theme, bool noPlugin)
0140 {
0141     if (library.isEmpty()) {
0142         return;
0143     }
0144 
0145     KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("kwinrc"));
0146     KConfigGroup group(config, QStringLiteral("org.kde.kdecoration2"));
0147 
0148     KConfig configDefault(configDefaults(QStringLiteral("kwinrc")));
0149     KConfigGroup defaultGroup(&configDefault, QStringLiteral("org.kde.kdecoration2"));
0150     writeNewDefaults(group, defaultGroup, QStringLiteral("library"), library);
0151     writeNewDefaults(group, defaultGroup, QStringLiteral("theme"), theme, KConfig::Notify);
0152     writeNewDefaults(group, defaultGroup, QStringLiteral("NoPlugin"), noPlugin ? "true" : "false", KConfig::Notify);
0153 }
0154 
0155 void LookAndFeelManager::setTitlebarLayout(const QString &leftbtns, const QString &rightbtns)
0156 {
0157     if (leftbtns.isEmpty() && rightbtns.isEmpty()) {
0158         return;
0159     }
0160 
0161     writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("org.kde.kdecoration2"), QStringLiteral("ButtonsOnLeft"), leftbtns, KConfig::Notify);
0162     writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("org.kde.kdecoration2"), QStringLiteral("ButtonsOnRight"), rightbtns, KConfig::Notify);
0163 }
0164 
0165 void LookAndFeelManager::setBorderlessMaximized(const QString &value)
0166 {
0167     if (value.isEmpty()) { // Turn borderless off for unsupported LNFs to prevent issues
0168         writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("Windows"), QStringLiteral("BorderlessMaximizedWindows"), "false", KConfig::Notify);
0169         return;
0170     }
0171 
0172     writeNewDefaults(QStringLiteral("kwinrc"), QStringLiteral("Windows"), QStringLiteral("BorderlessMaximizedWindows"), value, KConfig::Notify);
0173 }
0174 
0175 void LookAndFeelManager::setWidgetStyle(const QString &style)
0176 {
0177     if (style.isEmpty()) {
0178         return;
0179     }
0180 
0181     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("KDE"), QStringLiteral("widgetStyle"), style, KConfig::Notify);
0182     Q_EMIT styleChanged(style);
0183 }
0184 
0185 void LookAndFeelManager::setColors(const QString &scheme, const QString &colorFile)
0186 {
0187     if (scheme.isEmpty() && colorFile.isEmpty()) {
0188         return;
0189     }
0190 
0191     KConfig configDefault(configDefaults(QStringLiteral("kdeglobals")));
0192     auto kdeGlobalsCfg = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::FullConfig);
0193 
0194     if (m_mode == Mode::Apply) {
0195         applyScheme(colorFile, kdeGlobalsCfg.data(), KConfig::Notify);
0196     }
0197 
0198     writeNewDefaults(*kdeGlobalsCfg, configDefault, QStringLiteral("General"), QStringLiteral("ColorScheme"), scheme, KConfig::Notify);
0199 
0200     Q_EMIT colorsChanged();
0201 }
0202 
0203 void LookAndFeelManager::setIcons(const QString &theme)
0204 {
0205     if (theme.isEmpty()) {
0206         return;
0207     }
0208 
0209     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("Icons"), QStringLiteral("Theme"), theme, KConfig::Notify);
0210 
0211     Q_EMIT iconsChanged();
0212 }
0213 
0214 void LookAndFeelManager::setLatteLayout(const QString &filepath, const QString &name)
0215 {
0216     if (filepath.isEmpty()) {
0217         // there is no latte layout
0218         KIO::CommandLauncherJob latteapp(QStringLiteral("latte-dock"), {QStringLiteral("--disable-autostart")});
0219         latteapp.setDesktopName("org.kde.latte-dock");
0220         latteapp.start();
0221 
0222         QDBusMessage quitmessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.lattedock"),
0223                                                                   QStringLiteral("/MainApplication"),
0224                                                                   QStringLiteral("org.qtproject.Qt.QCoreApplication"),
0225                                                                   QStringLiteral("quit"));
0226         QDBusConnection::sessionBus().call(quitmessage, QDBus::NoBlock);
0227     } else {
0228         KIO::CommandLauncherJob latteapp(
0229             QStringLiteral("latte-dock"),
0230             {QStringLiteral("--enable-autostart"), QStringLiteral("--import-layout"), filepath, QStringLiteral("--suggested-layout-name"), name});
0231         latteapp.setDesktopName("org.kde.latte-dock");
0232         latteapp.start();
0233     }
0234 }
0235 
0236 void LookAndFeelManager::setPlasmaTheme(const QString &theme)
0237 {
0238     if (theme.isEmpty()) {
0239         return;
0240     }
0241 
0242     writeNewDefaults(QStringLiteral("plasmarc"), QStringLiteral("Theme"), QStringLiteral("name"), theme);
0243 }
0244 
0245 void LookAndFeelManager::setGeneralFont(const QString &font)
0246 {
0247     if (font.isEmpty()) {
0248         return;
0249     }
0250 
0251     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("General"), QStringLiteral("font"), font, KConfig::Notify);
0252     m_fontsChanged = true;
0253 }
0254 
0255 void LookAndFeelManager::setFixedFont(const QString &font)
0256 {
0257     if (font.isEmpty()) {
0258         return;
0259     }
0260 
0261     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("General"), QStringLiteral("fixed"), font, KConfig::Notify);
0262     m_fontsChanged = true;
0263 }
0264 
0265 void LookAndFeelManager::setSmallestReadableFont(const QString &font)
0266 {
0267     if (font.isEmpty()) {
0268         return;
0269     }
0270 
0271     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("General"), QStringLiteral("smallestReadableFont"), font, KConfig::Notify);
0272     m_fontsChanged = true;
0273 }
0274 
0275 void LookAndFeelManager::setToolbarFont(const QString &font)
0276 {
0277     if (font.isEmpty()) {
0278         return;
0279     }
0280 
0281     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("General"), QStringLiteral("toolBarFont"), font, KConfig::Notify);
0282     m_fontsChanged = true;
0283 }
0284 
0285 void LookAndFeelManager::setMenuFont(const QString &font)
0286 {
0287     if (font.isEmpty()) {
0288         return;
0289     }
0290 
0291     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("General"), QStringLiteral("menuFont"), font, KConfig::Notify);
0292     m_fontsChanged = true;
0293 }
0294 
0295 void LookAndFeelManager::setWindowTitleFont(const QString &font)
0296 {
0297     if (font.isEmpty()) {
0298         return;
0299     }
0300 
0301     writeNewDefaults(QStringLiteral("kdeglobals"), QStringLiteral("WM"), QStringLiteral("activeFont"), font, KConfig::Notify);
0302     m_fontsChanged = true;
0303 }
0304 
0305 void LookAndFeelManager::writeNewDefaults(const QString &filename,
0306                                           const QString &group,
0307                                           const QString &key,
0308                                           const QString &value,
0309                                           KConfig::WriteConfigFlags writeFlags)
0310 {
0311     KSharedConfigPtr config = KSharedConfig::openConfig(filename);
0312     KConfigGroup configGroup(config, group);
0313 
0314     KConfig configDefault(configDefaults(filename));
0315     KConfigGroup defaultGroup(&configDefault, group);
0316 
0317     writeNewDefaults(configGroup, defaultGroup, key, value, writeFlags);
0318 }
0319 
0320 void LookAndFeelManager::writeNewDefaults(KConfig &config,
0321                                           KConfig &configDefault,
0322                                           const QString &group,
0323                                           const QString &key,
0324                                           const QString &value,
0325                                           KConfig::WriteConfigFlags writeFlags)
0326 {
0327     KConfigGroup configGroup(&config, group);
0328     KConfigGroup defaultGroup(&configDefault, group);
0329 
0330     writeNewDefaults(configGroup, defaultGroup, key, value, writeFlags);
0331 }
0332 
0333 void LookAndFeelManager::writeNewDefaults(KConfigGroup &group,
0334                                           KConfigGroup &defaultGroup,
0335                                           const QString &key,
0336                                           const QString &value,
0337                                           KConfig::WriteConfigFlags writeFlags)
0338 {
0339     defaultGroup.writeEntry(key, value, writeFlags);
0340     defaultGroup.sync();
0341 
0342     if (m_mode == Mode::Apply) {
0343         group.revertToDefault(key, writeFlags);
0344         group.sync();
0345     }
0346 }
0347 
0348 KConfig LookAndFeelManager::configDefaults(const QString &filename)
0349 {
0350     return KConfig(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/kdedefaults/") + filename, KConfig::SimpleConfig);
0351 }
0352 
0353 QString LookAndFeelManager::colorSchemeFile(const QString &schemeName) const
0354 {
0355     QString colorScheme(schemeName);
0356     colorScheme.remove(QLatin1Char('\'')); // So Foo's does not become FooS
0357     QRegularExpression fixer(QStringLiteral("[\\W,.-]+(.?)"));
0358     for (auto match = fixer.match(colorScheme); match.hasMatch(); match = fixer.match(colorScheme)) {
0359         colorScheme.replace(match.capturedStart(), match.capturedLength(), match.captured(1).toUpper());
0360     }
0361     colorScheme.replace(0, 1, colorScheme.at(0).toUpper());
0362 
0363     // NOTE: why this loop trough all the scheme files?
0364     // the scheme theme name is an heuristic, there is no plugin metadata whatsoever.
0365     // is based on the file name stripped from weird characters or the
0366     // eventual id- prefix store.kde.org puts, so we can just find a
0367     // theme that ends as the specified name
0368     const QStringList schemeDirs =
0369         QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes"), QStandardPaths::LocateDirectory);
0370     for (const QString &dir : schemeDirs) {
0371         const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.colors"));
0372         for (const QString &file : fileNames) {
0373             if (file.endsWith(colorScheme + QStringLiteral(".colors"))) {
0374                 return dir + QLatin1Char('/') + file;
0375             }
0376         }
0377     }
0378     return QString();
0379 }
0380 
0381 void LookAndFeelManager::save(const KPackage::Package &package, const KPackage::Package &previousPackage)
0382 {
0383     if (m_layoutToApply.testFlag(LookAndFeelManager::DesktopLayout) && m_mode == Mode::Apply) {
0384         QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.plasmashell"),
0385                                                               QStringLiteral("/PlasmaShell"),
0386                                                               QStringLiteral("org.kde.PlasmaShell"),
0387                                                               QStringLiteral("loadLookAndFeelDefaultLayout"));
0388 
0389         QList<QVariant> args;
0390         args << m_data->settings()->lookAndFeelPackage();
0391         message.setArguments(args);
0392 
0393         QDBusConnection::sessionBus().call(message, QDBus::NoBlock);
0394 
0395         if (m_applyLatteLayout) {
0396             //! latte exists in system and user has chosen to update desktop layout
0397             setLatteLayout(package.filePath("layouts", "looknfeel.layout.latte"), package.metadata().name());
0398         }
0399     }
0400 
0401     if (!package.filePath("layoutdefaults").isEmpty()) {
0402         KSharedConfigPtr conf = KSharedConfig::openConfig(package.filePath("layoutdefaults"));
0403         KConfigGroup group(conf, "kwinrc");
0404         if (m_layoutToApply.testFlag(LookAndFeelManager::TitlebarLayout)) {
0405             group = KConfigGroup(&group, "org.kde.kdecoration2");
0406             setTitlebarLayout(group.readEntry("ButtonsOnLeft", QString()), group.readEntry("ButtonsOnRight", QString()));
0407         }
0408         if (m_layoutToApply.testFlag(LookAndFeelManager::DesktopLayout) && m_mode == Mode::Apply) {
0409             group = KConfigGroup(conf, "kwinrc");
0410             group = KConfigGroup(&group, "Windows");
0411             setBorderlessMaximized(group.readEntry("BorderlessMaximizedWindows", QString()));
0412         }
0413     }
0414     if (!package.filePath("defaults").isEmpty()) {
0415         KSharedConfigPtr conf = KSharedConfig::openConfig(package.filePath("defaults"));
0416         KConfigGroup group(conf, "kdeglobals");
0417         group = KConfigGroup(&group, "KDE");
0418         if (m_appearanceToApply.testFlag(LookAndFeelManager::WidgetStyle)) {
0419             QString widgetStyle = group.readEntry("widgetStyle", QString());
0420             // Some global themes refer to breeze's widgetStyle with a lowercase b.
0421             if (widgetStyle == QStringLiteral("breeze")) {
0422                 widgetStyle = QStringLiteral("Breeze");
0423             }
0424 
0425             setWidgetStyle(widgetStyle);
0426         }
0427 
0428         if (m_appearanceToApply.testFlag(LookAndFeelManager::Colors)) {
0429             QString colorsFile = package.filePath("colors");
0430             KConfigGroup group(conf, "kdeglobals");
0431             group = KConfigGroup(&group, "General");
0432             QString colorScheme = group.readEntry("ColorScheme", QString());
0433 
0434             if (!colorsFile.isEmpty()) {
0435                 if (!colorScheme.isEmpty()) {
0436                     setColors(colorScheme, colorsFile);
0437                 } else {
0438                     setColors(package.metadata().name(), colorsFile);
0439                 }
0440             } else if (!colorScheme.isEmpty()) {
0441                 QString path = colorSchemeFile(colorScheme);
0442                 if (!path.isEmpty()) {
0443                     setColors(colorScheme, path);
0444                 }
0445             }
0446         }
0447 
0448         if (m_appearanceToApply.testFlag(LookAndFeelManager::Icons)) {
0449             group = KConfigGroup(conf, "kdeglobals");
0450             group = KConfigGroup(&group, "Icons");
0451             setIcons(group.readEntry("Theme", QString()));
0452         }
0453 
0454         if (m_appearanceToApply.testFlag(LookAndFeelManager::PlasmaTheme)) {
0455             group = KConfigGroup(conf, "plasmarc");
0456             group = KConfigGroup(&group, "Theme");
0457             setPlasmaTheme(group.readEntry("name", QString()));
0458         }
0459 
0460         if (m_appearanceToApply.testFlag(LookAndFeelManager::Cursors)) {
0461             group = KConfigGroup(conf, "kcminputrc");
0462             group = KConfigGroup(&group, "Mouse");
0463             setCursorTheme(group.readEntry("cursorTheme", QString()));
0464         }
0465 
0466         if (m_appearanceToApply.testFlag(LookAndFeelManager::WindowSwitcher)) {
0467             group = KConfigGroup(conf, "kwinrc");
0468             group = KConfigGroup(&group, "WindowSwitcher");
0469             setWindowSwitcher(group.readEntry("LayoutName", QString()));
0470         }
0471 
0472         if (m_layoutToApply.testFlag(LookAndFeelManager::DesktopSwitcher)) {
0473             group = KConfigGroup(conf, "kwinrc");
0474             group = KConfigGroup(&group, "DesktopSwitcher");
0475             setDesktopSwitcher(group.readEntry("LayoutName", QString()));
0476         }
0477 
0478         if (m_layoutToApply.testFlag(LookAndFeelManager::WindowPlacement)) {
0479             group = KConfigGroup(conf, "kwinrc");
0480             group = KConfigGroup(&group, "Windows");
0481             setWindowPlacement(group.readEntry("Placement", QStringLiteral("Centered")));
0482         }
0483 
0484         if (m_layoutToApply.testFlag(LookAndFeelManager::ShellPackage)) {
0485             group = KConfigGroup(conf, "plasmashellrc");
0486             group = KConfigGroup(&group, "Shell");
0487             setShellPackage(group.readEntry("ShellPackage", QString()));
0488         }
0489 
0490         if (m_appearanceToApply.testFlag(LookAndFeelManager::WindowDecoration)) {
0491             group = KConfigGroup(conf, "kwinrc");
0492             group = KConfigGroup(&group, "org.kde.kdecoration2");
0493 
0494 #ifdef HAVE_BREEZE_DECO
0495             setWindowDecoration(group.readEntry("library", QStringLiteral(BREEZE_KDECORATION_PLUGIN_ID)),
0496                                 group.readEntry("theme", QStringLiteral("Breeze")),
0497                                 group.readEntry("NoPlugin", false));
0498 #else
0499             setWindowDecoration(group.readEntry("library", QStringLiteral("org.kde.kwin.aurorae")),
0500                                 group.readEntry("theme", QStringLiteral("kwin4_decoration_qml_plastik")),
0501                                 group.readEntry("NoPlugin", false));
0502 #endif
0503         }
0504 
0505         if (m_appearanceToApply.testFlag(LookAndFeelManager::Fonts)) {
0506             group = KConfigGroup(conf, "kdeglobals");
0507             group = KConfigGroup(&group, "General");
0508             setGeneralFont(group.readEntry("font", QString()));
0509             setFixedFont(group.readEntry("fixed", QString()));
0510             setSmallestReadableFont(group.readEntry("smallestReadableFont", QString()));
0511             setToolbarFont(group.readEntry("toolBarFont", QString()));
0512             setMenuFont(group.readEntry("menuFont", QString()));
0513             group = KConfigGroup(conf, "kdeglobals");
0514             group = KConfigGroup(&group, "WM");
0515             setWindowTitleFont(group.readEntry("activeFont"));
0516             if (m_fontsChanged) {
0517                 Q_EMIT fontsChanged();
0518                 m_fontsChanged = false;
0519             }
0520         }
0521 
0522         if (m_appearanceToApply.testFlag(LookAndFeelManager::SplashScreen)) {
0523             group = KConfigGroup(conf, "ksplashrc");
0524             group = KConfigGroup(&group, "KSplash");
0525             QString splashScreen = (group.readEntry("Theme", QString()));
0526             if (!splashScreen.isEmpty()) {
0527                 setSplashScreen(splashScreen);
0528             } else {
0529                 setSplashScreen(m_data->settings()->lookAndFeelPackage());
0530             }
0531         }
0532         if (m_appearanceToApply.testFlag(LookAndFeelManager::LockScreen)) {
0533             setLockScreen(m_data->settings()->lookAndFeelPackage());
0534         }
0535 
0536         QFile packageFile(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/kdedefaults/package"));
0537         packageFile.open(QIODevice::WriteOnly);
0538         packageFile.write(m_data->settings()->lookAndFeelPackage().toUtf8());
0539 
0540         if (m_mode == Mode::Defaults) {
0541             return;
0542         }
0543 
0544         if (m_plasmashellChanged) {
0545             QDBusMessage message =
0546                 QDBusMessage::createSignal(QStringLiteral("/PlasmaShell"), QStringLiteral("org.kde.PlasmaShell"), QStringLiteral("refreshCurrentShell"));
0547             QDBusConnection::sessionBus().send(message);
0548         }
0549 
0550         // autostart
0551         if (m_layoutToApply.testFlag(LookAndFeelManager::DesktopLayout)) {
0552             QStringList toStop;
0553             KService::List toStart;
0554             // remove all the old package to autostart
0555             {
0556                 KSharedConfigPtr oldConf = KSharedConfig::openConfig(previousPackage.filePath("defaults"));
0557                 group = KConfigGroup(oldConf, QStringLiteral("Autostart"));
0558                 const QStringList autostartServices = group.readEntry("Services", QStringList());
0559 
0560                 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION")) {
0561                     for (const QString &serviceFile : autostartServices) {
0562                         KService service(serviceFile + QStringLiteral(".desktop"));
0563                         PlasmaAutostart as(serviceFile);
0564                         as.setAutostarts(false);
0565                         QString serviceName = service.property(QStringLiteral("X-DBUS-ServiceName")).toString();
0566                         toStop.append(serviceName);
0567                     }
0568                 }
0569             }
0570             // Set all the stuff in the new lnf to autostart
0571             {
0572                 group = KConfigGroup(conf, QStringLiteral("Autostart"));
0573                 const QStringList autostartServices = group.readEntry("Services", QStringList());
0574 
0575                 for (const QString &serviceFile : autostartServices) {
0576                     KService::Ptr service(new KService(serviceFile + QStringLiteral(".desktop")));
0577                     PlasmaAutostart as(serviceFile);
0578                     as.setCommand(service->exec());
0579                     as.setAutostarts(true);
0580                     const QString serviceName = service->property(QStringLiteral("X-DBUS-ServiceName")).toString();
0581                     toStop.removeAll(serviceName);
0582                     if (qEnvironmentVariableIsSet("KDE_FULL_SESSION")) {
0583                         toStart += service;
0584                     }
0585                 }
0586             }
0587             Q_EMIT refreshServices(toStop, toStart);
0588         }
0589     }
0590     // Reload KWin if something changed, but only once.
0591     if (m_appearanceToApply.testFlag(LookAndFeelManager::WindowSwitcher) || m_layoutToApply.testFlag(LookAndFeelManager::DesktopSwitcher)
0592         || m_appearanceToApply.testFlag(LookAndFeelManager::WindowDecoration) || m_layoutToApply.testFlag(LookAndFeelManager::WindowPlacement)
0593         || m_layoutToApply.testFlag(LookAndFeelManager::WindowPlacement) || m_layoutToApply.testFlag(LookAndFeelManager::TitlebarLayout)) {
0594         QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"));
0595         QDBusConnection::sessionBus().send(message);
0596     }
0597 }
0598 
0599 void LookAndFeelManager::setCursorTheme(const QString themeName)
0600 {
0601     // TODO: use pieces of cursor kcm when moved to plasma-desktop
0602     if (themeName.isEmpty()) {
0603         return;
0604     }
0605 
0606     writeNewDefaults(QStringLiteral("kcminputrc"), QStringLiteral("Mouse"), QStringLiteral("cursorTheme"), themeName, KConfig::Notify);
0607     Q_EMIT cursorsChanged(themeName);
0608 }
0609 
0610 void LookAndFeelManager::setMode(LookAndFeelManager::Mode mode)
0611 {
0612     m_mode = mode;
0613 }