2023-02-23 16:43:38 +00:00
|
|
|
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
|
2024-12-20 12:59:06 +00:00
|
|
|
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
|
2023-02-23 16:43:38 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
|
|
#include "settings.h"
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
|
|
#include <KRuntimePlatform>
|
|
|
|
|
|
|
|
|
|
#include <QDBusConnection>
|
|
|
|
|
#include <QDBusMessage>
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QProcess>
|
|
|
|
|
|
2024-01-17 00:07:31 +00:00
|
|
|
using namespace Qt::Literals::StringLiterals;
|
|
|
|
|
|
|
|
|
|
const QString CONFIG_FILE = u"plasmamobilerc"_s;
|
|
|
|
|
const QString SAVED_CONFIG_GROUP = u"SavedConfig"_s;
|
2023-02-23 16:43:38 +00:00
|
|
|
|
|
|
|
|
Settings::Settings(QObject *parent)
|
|
|
|
|
: QObject{parent}
|
2024-01-17 00:07:31 +00:00
|
|
|
, m_isMobilePlatform{KRuntimePlatform::runtimePlatform().contains(u"phone"_s)}
|
2023-03-30 02:40:47 +00:00
|
|
|
, m_mobileConfig{KSharedConfig::openConfig(CONFIG_FILE, KConfig::SimpleConfig)}
|
2024-01-17 00:07:31 +00:00
|
|
|
, m_kwinrcConfig{KSharedConfig::openConfig(u"kwinrc"_s, KConfig::SimpleConfig)}
|
|
|
|
|
, m_appBlacklistConfig{KSharedConfig::openConfig(u"applications-blacklistrc"_s, KConfig::SimpleConfig)}
|
|
|
|
|
, m_kdeglobalsConfig{KSharedConfig::openConfig(u"kdeglobals"_s, KConfig::SimpleConfig)}
|
2024-12-20 12:59:06 +00:00
|
|
|
, m_ksmServerConfig{KSharedConfig::openConfig(u"ksmserverrc"_s, KConfig::SimpleConfig)}
|
2024-11-15 21:12:22 +00:00
|
|
|
, m_kwinrulesrcConfig{KSharedConfig::openConfig(u"kwinrulesrc"_s, KConfig::SimpleConfig)}
|
2023-03-30 02:40:47 +00:00
|
|
|
, m_configWatcher{KConfigWatcher::create(m_mobileConfig)}
|
2023-02-23 16:43:38 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-17 00:02:51 +00:00
|
|
|
Settings &Settings::self()
|
2023-02-23 16:43:38 +00:00
|
|
|
{
|
2024-01-17 00:02:51 +00:00
|
|
|
static Settings settings;
|
2023-02-23 16:43:38 +00:00
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Settings::applyConfiguration()
|
|
|
|
|
{
|
|
|
|
|
if (!m_isMobilePlatform) {
|
|
|
|
|
qCDebug(LOGGING_CATEGORY) << "Configuration will not be applied, as the session is not Plasma Mobile.";
|
|
|
|
|
qCDebug(LOGGING_CATEGORY) << "Restoring any previously saved configuration...";
|
|
|
|
|
loadSavedConfiguration();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qCDebug(LOGGING_CATEGORY) << "Checking and applying mobile configuration...";
|
|
|
|
|
applyMobileConfiguration();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Settings::loadSavedConfiguration()
|
|
|
|
|
{
|
|
|
|
|
// kwinrc
|
2024-01-17 00:07:31 +00:00
|
|
|
loadKeys(u"kwinrc"_s, m_kwinrcConfig, getKwinrcSettings(m_mobileConfig));
|
2023-02-23 16:43:38 +00:00
|
|
|
m_kwinrcConfig->sync();
|
2024-11-15 21:12:22 +00:00
|
|
|
|
|
|
|
|
// kwinrules
|
|
|
|
|
for (const auto &groupName : KWIN_RULES) {
|
|
|
|
|
m_kwinrulesrcConfig->deleteGroup(groupName);
|
|
|
|
|
}
|
|
|
|
|
writeKeys(u"kwinrulesrc"_s, m_kwinrulesrcConfig, getKwinrulesrcSettings(m_mobileConfig, false), false, false);
|
|
|
|
|
m_kwinrulesrcConfig->sync();
|
|
|
|
|
|
2023-02-23 16:43:38 +00:00
|
|
|
reloadKWinConfig();
|
|
|
|
|
|
|
|
|
|
// applications-blacklistrc
|
2024-01-17 00:07:31 +00:00
|
|
|
loadKeys(u"applications-blacklistrc"_s, m_appBlacklistConfig, APPLICATIONS_BLACKLIST_DEFAULT_SETTINGS);
|
2023-02-23 16:43:38 +00:00
|
|
|
m_appBlacklistConfig->sync();
|
|
|
|
|
|
|
|
|
|
// kdeglobals
|
2024-01-17 00:07:31 +00:00
|
|
|
loadKeys(u"kdeglobals"_s, m_kdeglobalsConfig, KDEGLOBALS_DEFAULT_SETTINGS);
|
|
|
|
|
loadKeys(u"kdeglobals"_s, m_kdeglobalsConfig, KDEGLOBALS_SETTINGS);
|
2023-02-23 16:43:38 +00:00
|
|
|
m_kdeglobalsConfig->sync();
|
|
|
|
|
|
|
|
|
|
// save our changes
|
2023-03-30 02:40:47 +00:00
|
|
|
m_mobileConfig->sync();
|
2023-02-23 16:43:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Settings::applyMobileConfiguration()
|
|
|
|
|
{
|
|
|
|
|
// kwinrc
|
2024-01-17 00:07:31 +00:00
|
|
|
writeKeys(u"kwinrc"_s, m_kwinrcConfig, getKwinrcSettings(m_mobileConfig), false);
|
2023-02-23 16:43:38 +00:00
|
|
|
m_kwinrcConfig->sync();
|
2024-11-15 21:12:22 +00:00
|
|
|
|
|
|
|
|
// kwinrules
|
|
|
|
|
for (const auto &groupName : KWIN_RULES) {
|
|
|
|
|
m_kwinrulesrcConfig->deleteGroup(groupName);
|
|
|
|
|
}
|
|
|
|
|
writeKeys(u"kwinrulesrc"_s, m_kwinrulesrcConfig, getKwinrulesrcSettings(m_mobileConfig, true), false, false);
|
|
|
|
|
m_kwinrulesrcConfig->sync();
|
|
|
|
|
|
2023-02-23 16:43:38 +00:00
|
|
|
reloadKWinConfig();
|
|
|
|
|
|
|
|
|
|
// applications-blacklistrc
|
2024-01-17 00:07:31 +00:00
|
|
|
writeKeys(u"applications-blacklistrc"_s,
|
2023-12-09 03:09:26 +00:00
|
|
|
m_appBlacklistConfig,
|
|
|
|
|
APPLICATIONS_BLACKLIST_DEFAULT_SETTINGS,
|
|
|
|
|
true); // only write entries if they are not already defined in the config
|
2023-02-23 16:43:38 +00:00
|
|
|
m_appBlacklistConfig->sync();
|
|
|
|
|
|
|
|
|
|
// kdeglobals
|
2024-01-17 00:07:31 +00:00
|
|
|
writeKeys(u"kdeglobals"_s, m_kdeglobalsConfig, KDEGLOBALS_DEFAULT_SETTINGS,
|
2023-12-09 03:09:26 +00:00
|
|
|
true); // only write entries if they are not already defined in the config
|
2024-01-17 00:07:31 +00:00
|
|
|
writeKeys(u"kdeglobals"_s, m_kdeglobalsConfig, KDEGLOBALS_SETTINGS, false);
|
2023-02-23 16:43:38 +00:00
|
|
|
m_kdeglobalsConfig->sync();
|
|
|
|
|
|
2024-12-20 12:59:06 +00:00
|
|
|
// ksmserver
|
|
|
|
|
writeKeys(u"ksmserverrc"_s, m_ksmServerConfig, KSMSERVER_SETTINGS, false);
|
|
|
|
|
m_ksmServerConfig->sync();
|
|
|
|
|
|
2023-02-23 16:43:38 +00:00
|
|
|
// save our changes
|
2023-03-30 02:40:47 +00:00
|
|
|
m_mobileConfig->sync();
|
2023-02-23 16:43:38 +00:00
|
|
|
}
|
|
|
|
|
|
2024-11-15 21:12:22 +00:00
|
|
|
void Settings::writeKeys(const QString &fileName,
|
|
|
|
|
KSharedConfig::Ptr &config,
|
|
|
|
|
const QMap<QString, QMap<QString, QVariant>> &settings,
|
|
|
|
|
bool overwriteOnlyIfEmpty,
|
|
|
|
|
bool saveSettings)
|
2023-02-23 16:43:38 +00:00
|
|
|
{
|
2024-01-22 15:33:41 +00:00
|
|
|
const auto groupNames = settings.keys();
|
|
|
|
|
for (const auto &groupName : groupNames) {
|
2023-02-23 16:43:38 +00:00
|
|
|
auto group = KConfigGroup{config, groupName};
|
|
|
|
|
|
2024-01-22 15:33:41 +00:00
|
|
|
const auto keys = settings[groupName].keys();
|
|
|
|
|
for (const auto &key : keys) {
|
2023-02-23 16:43:38 +00:00
|
|
|
if (!group.hasKey(key) || !overwriteOnlyIfEmpty) {
|
|
|
|
|
// save key
|
2024-11-15 21:12:22 +00:00
|
|
|
if (saveSettings) {
|
|
|
|
|
saveConfigSetting(fileName, groupName, key, group.readEntry(key));
|
|
|
|
|
}
|
2023-02-23 16:43:38 +00:00
|
|
|
|
|
|
|
|
// overwrite with mobile setting
|
|
|
|
|
group.writeEntry(key, settings[groupName][key], KConfigGroup::Notify);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Settings::loadKeys(const QString &fileName, KSharedConfig::Ptr &config, const QMap<QString, QMap<QString, QVariant>> &settings)
|
|
|
|
|
{
|
2024-01-22 15:33:41 +00:00
|
|
|
const auto groupNames = settings.keys();
|
|
|
|
|
for (const auto &groupName : groupNames) {
|
|
|
|
|
const auto group = KConfigGroup{config, groupName};
|
2023-02-23 16:43:38 +00:00
|
|
|
|
2024-01-22 15:33:41 +00:00
|
|
|
const auto keys = settings[groupName].keys();
|
|
|
|
|
for (const auto &key : keys) {
|
2023-02-23 16:43:38 +00:00
|
|
|
loadSavedConfigSetting(config, fileName, groupName, key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: this only saves a value if it hasn't already been saved
|
|
|
|
|
void Settings::saveConfigSetting(const QString &fileName, const QString &group, const QString &key, const QVariant value)
|
|
|
|
|
{
|
2024-06-26 17:15:57 +00:00
|
|
|
// These are not const because we are writing an entry
|
|
|
|
|
auto savedGroup = KConfigGroup{m_mobileConfig, SAVED_CONFIG_GROUP};
|
|
|
|
|
auto fileGroup = KConfigGroup{&savedGroup, fileName};
|
2023-02-23 16:43:38 +00:00
|
|
|
auto keyGroup = KConfigGroup{&fileGroup, group};
|
|
|
|
|
|
|
|
|
|
if (!keyGroup.hasKey(key)) {
|
2023-12-09 03:09:26 +00:00
|
|
|
qCDebug(LOGGING_CATEGORY) << "In" << fileName << "saved" << key << "=" << value;
|
2023-02-23 16:43:38 +00:00
|
|
|
keyGroup.writeEntry(key, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: this deletes the stored value from the config after loading
|
2023-03-30 05:43:44 +00:00
|
|
|
const QString Settings::loadSavedConfigSetting(KSharedConfig::Ptr &config, const QString &fileName, const QString &group, const QString &key, bool write)
|
2023-02-23 16:43:38 +00:00
|
|
|
{
|
2024-01-20 23:18:13 +00:00
|
|
|
auto savedGroup = KConfigGroup{m_mobileConfig, SAVED_CONFIG_GROUP};
|
|
|
|
|
auto fileGroup = KConfigGroup{&savedGroup, fileName};
|
2023-02-23 16:43:38 +00:00
|
|
|
auto keyGroup = KConfigGroup{&fileGroup, group};
|
|
|
|
|
|
|
|
|
|
if (!keyGroup.hasKey(key)) {
|
2023-03-30 05:43:44 +00:00
|
|
|
return {};
|
2023-02-23 16:43:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto value = keyGroup.readEntry(key);
|
|
|
|
|
|
|
|
|
|
// write to real config
|
|
|
|
|
auto configGroup = KConfigGroup{config, group};
|
|
|
|
|
|
2023-03-30 05:43:44 +00:00
|
|
|
if ((!configGroup.hasKey(key) || configGroup.readEntry(key) != value) && write) {
|
2024-01-22 15:33:41 +00:00
|
|
|
qCDebug(LOGGING_CATEGORY) << "In" << fileName << "loading saved value of" << key << "which is" << value << "in" << group;
|
2023-02-23 16:43:38 +00:00
|
|
|
|
|
|
|
|
if (value.isEmpty()) { // delete blank entries!
|
|
|
|
|
configGroup.deleteEntry(key);
|
|
|
|
|
} else {
|
|
|
|
|
configGroup.writeEntry(key, value, KConfigGroup::Notify);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove saved config option
|
2023-03-30 15:42:28 +00:00
|
|
|
keyGroup.deleteEntry(key);
|
2023-03-30 05:43:44 +00:00
|
|
|
return value;
|
2023-02-23 16:43:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Settings::reloadKWinConfig()
|
|
|
|
|
{
|
2024-11-14 17:18:23 +00:00
|
|
|
// Reload config
|
|
|
|
|
QDBusMessage reloadMessage = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
|
|
|
|
|
QDBusConnection::sessionBus().send(reloadMessage);
|
|
|
|
|
|
|
|
|
|
// Effects need to manually be loaded/unloaded in a live KWin session.
|
2024-10-31 06:32:30 +00:00
|
|
|
|
|
|
|
|
KConfigGroup pluginsGroup{m_kwinrcConfig, QStringLiteral("Plugins")};
|
|
|
|
|
|
|
|
|
|
for (const auto &effect : KWIN_EFFECTS) {
|
|
|
|
|
// Read from the config whether the effect is enabled (settings are suffixed with "Enabled", ex. blurEnabled)
|
|
|
|
|
bool status = pluginsGroup.readEntry(effect + u"Enabled"_s, false);
|
|
|
|
|
const QString method = status ? u"loadEffect"_s : u"unloadEffect"_s;
|
|
|
|
|
|
|
|
|
|
QDBusMessage message = QDBusMessage::createMethodCall(u"org.kde.KWin"_s, u"/Effects"_s, u"org.kde.kwin.Effects"_s, method);
|
|
|
|
|
message.setArguments({effect});
|
|
|
|
|
QDBusConnection::sessionBus().send(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unload KWin scripts that are now disabled.
|
|
|
|
|
for (const auto &script : KWIN_SCRIPTS) {
|
|
|
|
|
// Read from the config whether the effect is enabled (settings are suffixed with "Enabled", ex. blurEnabled)
|
|
|
|
|
bool status = pluginsGroup.readEntry(script + u"Enabled"_s, false);
|
|
|
|
|
|
|
|
|
|
if (!status) {
|
|
|
|
|
QDBusMessage message = QDBusMessage::createMethodCall(u"org.kde.KWin"_s, u"/Scripting"_s, u"org.kde.kwin.Scripting"_s, u"unloadScript"_s);
|
|
|
|
|
message.setArguments({script});
|
|
|
|
|
QDBusConnection::sessionBus().send(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call "start" to load enabled KWin scripts.
|
2024-11-15 21:12:22 +00:00
|
|
|
QDBusMessage startScriptsMessage = QDBusMessage::createMethodCall(u"org.kde.KWin"_s, u"/Scripting"_s, u"org.kde.kwin.Scripting"_s, u"start"_s);
|
|
|
|
|
QDBusConnection::sessionBus().send(startScriptsMessage);
|
|
|
|
|
|
|
|
|
|
// Call reconfigure
|
|
|
|
|
QDBusMessage reconfigureMessage = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reconfigure");
|
|
|
|
|
QDBusConnection::sessionBus().send(reconfigureMessage);
|
2023-02-23 16:43:38 +00:00
|
|
|
}
|