diff --git a/src/platformtheme/kfontsettingsdata.h b/src/platformtheme/kfontsettingsdata.h --- a/src/platformtheme/kfontsettingsdata.h +++ b/src/platformtheme/kfontsettingsdata.h @@ -21,6 +21,7 @@ #ifndef KFONTSETTINGSDATA_H #define KFONTSETTINGSDATA_H +#include #include #include #include @@ -60,11 +61,15 @@ private Q_SLOTS: void delayedDBusConnects(); + void slotPortalSettingChanged(const QString &group, const QString &key, const QDBusVariant &value); public: // access, is not const due to caching QFont *font(FontTypes fontType); private: + QString readConfigValue(const QString &group, const QString &key, const QString &defaultValue = QString()); + + bool mUsePortal; QFont *mFonts[FontTypesCount]; KSharedConfigPtr mKdeGlobals; }; diff --git a/src/platformtheme/kfontsettingsdata.cpp b/src/platformtheme/kfontsettingsdata.cpp --- a/src/platformtheme/kfontsettingsdata.cpp +++ b/src/platformtheme/kfontsettingsdata.cpp @@ -25,14 +25,21 @@ #include #include #include +#include #include #include #include +static inline bool checkUsePortalSupport() +{ + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QStringLiteral("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP"); +} + KFontSettingsData::KFontSettingsData() - : QObject(nullptr), - mKdeGlobals(KSharedConfig::openConfig()) + : QObject(nullptr) + , mUsePortal(checkUsePortalSupport()) + , mKdeGlobals(KSharedConfig::openConfig()) { QMetaObject::invokeMethod(this, "delayedDBusConnects", Qt::QueuedConnection); @@ -71,8 +78,7 @@ cachedFont = new QFont(QLatin1String(fontData.FontName), fontData.Size, fontData.Weight); cachedFont->setStyleHint(fontData.StyleHint); - const KConfigGroup configGroup(mKdeGlobals, fontData.ConfigGroupKey); - QString fontInfo = configGroup.readEntry(fontData.ConfigKey, QString()); + QString fontInfo = readConfigValue(QLatin1String(fontData.ConfigGroupKey), QLatin1String(fontData.ConfigKey)); //If we have serialized information for this font, restore it //NOTE: We are not using KConfig directly because we can't call QFont::QFont from here @@ -111,4 +117,44 @@ { QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KDEPlatformTheme"), QStringLiteral("org.kde.KDEPlatformTheme"), QStringLiteral("refreshFonts"), this, SLOT(dropFontSettingsCache())); + + if (mUsePortal) { + QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/org/freedesktop/portal/desktop"), QStringLiteral("org.freedesktop.portal.Settings"), + QStringLiteral("SettingChanged"), this, SLOT(slotPortalSettingChanged(QString,QString,QDBusVariant))); + } +} + +void KFontSettingsData::slotPortalSettingChanged(const QString &group, const QString &key, const QDBusVariant &value) +{ + Q_UNUSED(value); + + if (group == QStringLiteral("org.kde.kdeglobals.General") && key == QStringLiteral("font")) { + dropFontSettingsCache(); + } +} + +QString KFontSettingsData::readConfigValue(const QString &group, const QString &key, const QString &defaultValue) +{ + if (mUsePortal) { + const QString settingName = QStringLiteral("org.kde.kdeglobals.%1").arg(group); + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.portal.Desktop"), + QStringLiteral("/org/freedesktop/portal/desktop"), + QStringLiteral("org.freedesktop.portal.Settings"), + QStringLiteral("Read")); + message << settingName << key; + + // FIXME: async? + QDBusReply reply = QDBusConnection::sessionBus().call(message); + if (reply.isValid()) { + QDBusVariant result = qvariant_cast(reply.value()); + const QString resultStr = result.variant().toString(); + + if (!resultStr.isEmpty()) { + return resultStr; + } + } + } + + const KConfigGroup configGroup(mKdeGlobals, group); + return configGroup.readEntry(key, defaultValue); } diff --git a/src/platformtheme/khintssettings.h b/src/platformtheme/khintssettings.h --- a/src/platformtheme/khintssettings.h +++ b/src/platformtheme/khintssettings.h @@ -21,6 +21,7 @@ #ifndef KHINTS_SETTINGS_H #define KHINTS_SETTINGS_H +#include #include #include @@ -70,21 +71,26 @@ void setupIconLoader(); void toolbarStyleChanged(); void slotNotifyChange(int type, int arg); + void slotPortalSettingChanged(const QString &group, const QString &key, const QDBusVariant &value); private: QVariant readConfigValue(const QString &group, const QString &key, const QVariant &defaultValue); + QVariant readConfigValue(const KConfigGroup &cg, const QString &key, const QVariant &defaultValue); void loadPalettes(); void iconChanged(int group); void updateQtSettings(KConfigGroup &cg); void updateShowIconsInMenuItems(KConfigGroup &cg); - Qt::ToolButtonStyle toolButtonStyle(const KConfigGroup &cg) const; + Qt::ToolButtonStyle toolButtonStyle(const KConfigGroup &cg); void updateCursorTheme(); + void updatePortalSetting(); QHash m_palettes; QHash m_hints; KSharedConfigPtr mKdeGlobals; KSharedConfigPtr mDefaultLnfConfig; KSharedConfigPtr mLnfConfig; + QMap mKdeGlobalsPortal; + bool mUsePortal; }; #endif //KHINTS_SETTINGS_H diff --git a/src/platformtheme/khintssettings.cpp b/src/platformtheme/khintssettings.cpp --- a/src/platformtheme/khintssettings.cpp +++ b/src/platformtheme/khintssettings.cpp @@ -35,7 +35,9 @@ #include #include #include +#include +#include #include #include @@ -56,35 +58,63 @@ static const QString defaultLookAndFeelPackage = QStringLiteral("org.kde.breeze.desktop"); +const QDBusArgument &operator>>(const QDBusArgument &argument, QMap &map) +{ + argument.beginMap(); + map.clear(); + + while (!argument.atEnd()) { + QString key; + QVariantMap value; + argument.beginMapEntry(); + argument >> key >> value; + argument.endMapEntry(); + map.insert(key, value); + } + + argument.endMap(); + return argument; +} + +static inline bool checkUsePortalSupport() +{ + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QStringLiteral("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP"); +} + KHintsSettings::KHintsSettings(KSharedConfig::Ptr kdeglobals) : QObject(nullptr) , mKdeGlobals(kdeglobals) + , mUsePortal(checkUsePortalSupport()) { if (!mKdeGlobals) { mKdeGlobals = KSharedConfig::openConfig(); } KConfigGroup cg(mKdeGlobals, "KDE"); + if (mUsePortal) { + updatePortalSetting(); + } + // try to extract the proper defaults file from a lookandfeel package - const QString looknfeel = cg.readEntry("LookAndFeelPackage", defaultLookAndFeelPackage); + const QString looknfeel = readConfigValue(cg, QStringLiteral("LookAndFeelPackage"), defaultLookAndFeelPackage).toString(); mDefaultLnfConfig = KSharedConfig::openConfig(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/look-and-feel/") + looknfeel + QStringLiteral("/contents/defaults"))); if (looknfeel != defaultLookAndFeelPackage) { mLnfConfig = KSharedConfig::openConfig(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/look-and-feel/") + defaultLookAndFeelPackage + QStringLiteral("/contents/defaults"))); } - const auto cursorBlinkRate = cg.readEntry("CursorBlinkRate", 1000); + const auto cursorBlinkRate = readConfigValue(cg, QStringLiteral("CursorBlinkRate"), 1000).toInt(); m_hints[QPlatformTheme::CursorFlashTime] = cursorBlinkRate > 0 ? qBound(200, cursorBlinkRate, 2000) : 0; // 0 => no blinking - m_hints[QPlatformTheme::MouseDoubleClickInterval] = cg.readEntry("DoubleClickInterval", 400); - m_hints[QPlatformTheme::StartDragDistance] = cg.readEntry("StartDragDist", 10); - m_hints[QPlatformTheme::StartDragTime] = cg.readEntry("StartDragTime", 500); + m_hints[QPlatformTheme::MouseDoubleClickInterval] = readConfigValue(cg, QStringLiteral("DoubleClickInterval"), 400); + m_hints[QPlatformTheme::StartDragDistance] = readConfigValue(cg, QStringLiteral("StartDragDist"), 10); + m_hints[QPlatformTheme::StartDragTime] = readConfigValue(cg, QStringLiteral("StartDragTime"), 500); KConfigGroup cgToolbar(mKdeGlobals, "Toolbar style"); m_hints[QPlatformTheme::ToolButtonStyle] = toolButtonStyle(cgToolbar); KConfigGroup cgToolbarIcon(mKdeGlobals, "MainToolbarIcons"); - m_hints[QPlatformTheme::ToolBarIconSize] = cgToolbarIcon.readEntry("Size", 22); + m_hints[QPlatformTheme::ToolBarIconSize] = readConfigValue(cgToolbarIcon, QStringLiteral("Size"), 22); - m_hints[QPlatformTheme::ItemViewActivateItemOnSingleClick] = cg.readEntry("SingleClick", true); + m_hints[QPlatformTheme::ItemViewActivateItemOnSingleClick] = readConfigValue(cg, QStringLiteral("SingleClick"), true); m_hints[QPlatformTheme::SystemIconThemeName] = readConfigValue(QStringLiteral("Icons"), QStringLiteral("Theme"), QStringLiteral("breeze")); @@ -97,7 +127,7 @@ QStringLiteral("fusion"), QStringLiteral("windows") }; - const QString configuredStyle = cg.readEntry("widgetStyle", QString()); + const QString configuredStyle = readConfigValue(cg, QStringLiteral("widgetStyle"), QString()).toString(); if (!configuredStyle.isEmpty()) { styleNames.removeOne(configuredStyle); styleNames.prepend(configuredStyle); @@ -110,15 +140,15 @@ m_hints[QPlatformTheme::StyleNames] = styleNames; m_hints[QPlatformTheme::DialogButtonBoxLayout] = QDialogButtonBox::KdeLayout; - m_hints[QPlatformTheme::DialogButtonBoxButtonsHaveIcons] = cg.readEntry("ShowIconsOnPushButtons", true); + m_hints[QPlatformTheme::DialogButtonBoxButtonsHaveIcons] = readConfigValue(cg, QStringLiteral("ShowIconsOnPushButtons"), true); m_hints[QPlatformTheme::UseFullScreenForPopupMenu] = true; m_hints[QPlatformTheme::KeyboardScheme] = QPlatformTheme::KdeKeyboardScheme; - m_hints[QPlatformTheme::UiEffects] = cg.readEntry("GraphicEffectsLevel", 0) != 0 ? QPlatformTheme::GeneralUiEffect : 0; + m_hints[QPlatformTheme::UiEffects] = readConfigValue(cg, QStringLiteral("GraphicEffectsLevel"), 0) != 0 ? QPlatformTheme::GeneralUiEffect : 0; m_hints[QPlatformTheme::IconPixmapSizes] = QVariant::fromValue(QList() << 512 << 256 << 128 << 64 << 32 << 22 << 16 << 8); - m_hints[QPlatformTheme::WheelScrollLines] = cg.readEntry("WheelScrollLines", 3); + m_hints[QPlatformTheme::WheelScrollLines] = readConfigValue(cg, QStringLiteral("WheelScrollLines"), 3); if (qobject_cast(QCoreApplication::instance())) { - QApplication::setWheelScrollLines(cg.readEntry("WheelScrollLines", 3)); + QApplication::setWheelScrollLines(readConfigValue(cg, QStringLiteral("WheelScrollLines"), 3).toInt()); } updateShowIconsInMenuItems(cg); @@ -139,7 +169,7 @@ QVariant KHintsSettings::readConfigValue(const QString &group, const QString &key, const QVariant &defaultValue) { KConfigGroup userCg(mKdeGlobals, group); - QVariant value = userCg.readEntry(key, QString()); + QVariant value = readConfigValue(userCg, key, QString()); if (!value.isNull()) { return value; @@ -160,12 +190,28 @@ KConfigGroup lnfCg(mDefaultLnfConfig, "kdeglobals"); lnfCg = KConfigGroup(&lnfCg, group); if (lnfCg.isValid()) { - return lnfCg.readEntry(key, defaultValue); + return lnfCg.readEntry(key, defaultValue); } return defaultValue; } +QVariant KHintsSettings::readConfigValue(const KConfigGroup &cg, const QString &key, const QVariant &defaultValue) +{ + if (mUsePortal) { + const QString settingName = QStringLiteral("org.kde.kdeglobals.%1").arg(cg.name()); + auto groupIt = mKdeGlobalsPortal.constFind(settingName); + if (groupIt != mKdeGlobalsPortal.constEnd()) { + auto valueIt = groupIt.value().constFind(key); + if (valueIt != groupIt.value().constEnd()) { + return valueIt.value(); + } + } + } + + return cg.readEntry(key, defaultValue); +} + QStringList KHintsSettings::xdgIconThemePaths() const { QStringList paths; @@ -187,6 +233,10 @@ QStringLiteral("styleChanged"), this, SLOT(toolbarStyleChanged())); QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KGlobalSettings"), QStringLiteral("org.kde.KGlobalSettings"), QStringLiteral("notifyChange"), this, SLOT(slotNotifyChange(int,int))); + if (mUsePortal) { + QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/org/freedesktop/portal/desktop"), QStringLiteral("org.freedesktop.portal.Settings"), + QStringLiteral("SettingChanged"), this, SLOT(slotPortalSettingChanged(QString,QString,QDBusVariant))); + } } void KHintsSettings::setupIconLoader() @@ -263,13 +313,13 @@ return; } - const QString theme = cg.readEntry("widgetStyle", QString()); + const QString theme = readConfigValue(cg, QStringLiteral("widgetStyle"), QString()).toString(); if (theme.isEmpty()) { return; } QStringList styleNames; - styleNames << cg.readEntry("widgetStyle", QString()) + styleNames << theme << QStringLiteral(BREEZE_STYLE_NAME) << QStringLiteral("oxygen") << QStringLiteral("fusion") @@ -289,12 +339,32 @@ } } +void KHintsSettings::slotPortalSettingChanged(const QString &group, const QString &key, const QDBusVariant &value) +{ + if (group == QStringLiteral("org.kde.kdeglobals.General") && key == QStringLiteral("ColorScheme")) { + // For colors obtain complete configuration again + updatePortalSetting(); + slotNotifyChange(PaletteChanged, 0); + } else if (group == QStringLiteral("org.kde.kdeglobals.KDE") && key == QStringLiteral("widgetStyle")) { + mKdeGlobalsPortal[group][key] = value.variant().toString(); + slotNotifyChange(StyleChanged, 0); + } else if (group == QStringLiteral("org.kde.kdeglobals.Icons") && key == QStringLiteral("Theme")) { + mKdeGlobalsPortal[group][key] = value.variant().toString(); + // Change icons for each group + for (int i = 0; i <= 5; ++i) { + iconChanged(i); + } + } else if (group == QStringLiteral("org.kde.kdeglobals.Toolbar style") && key == QStringLiteral("ToolButtonStyle")) { + mKdeGlobalsPortal[group][key] = value.variant().toString(); + toolbarStyleChanged(); + } +} + void KHintsSettings::iconChanged(int group) { KIconLoader::Group iconGroup = (KIconLoader::Group) group; if (iconGroup != KIconLoader::MainToolbar) { m_hints[QPlatformTheme::SystemIconThemeName] = readConfigValue(QStringLiteral("Icons"), QStringLiteral("Theme"), QStringLiteral("breeze")); - return; } @@ -347,13 +417,13 @@ void KHintsSettings::updateShowIconsInMenuItems(KConfigGroup &cg) { - bool showIcons = cg.readEntry("ShowIconsInMenuItems", true); + bool showIcons = readConfigValue(cg, QStringLiteral("ShowIconsInMenuItems"), true).toBool(); QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !showIcons); } -Qt::ToolButtonStyle KHintsSettings::toolButtonStyle(const KConfigGroup &cg) const +Qt::ToolButtonStyle KHintsSettings::toolButtonStyle(const KConfigGroup &cg) { - const QString buttonStyle = cg.readEntry("ToolButtonStyle", "TextBesideIcon").toLower(); + const QString buttonStyle = readConfigValue(cg, QStringLiteral("ToolButtonStyle"), QStringLiteral("TextBesideIcon")).toString().toLower(); return buttonStyle == QLatin1String("textbesideicon") ? Qt::ToolButtonTextBesideIcon : buttonStyle == QLatin1String("icontextright") ? Qt::ToolButtonTextBesideIcon : buttonStyle == QLatin1String("textundericon") ? Qt::ToolButtonTextUnderIcon @@ -367,12 +437,26 @@ qDeleteAll(m_palettes); m_palettes.clear(); - if (mKdeGlobals->hasGroup("Colors:View")) { + if (mUsePortal && mKdeGlobalsPortal.contains(QStringLiteral("org.kde.kdeglobals.Colors:View"))) { + // Construct a temporary KConfig file containing color setting so we can create a KColorScheme from it + QTemporaryFile file; + file.open(); + + KSharedConfigPtr tempConfig = KSharedConfig::openConfig(file.fileName(), KConfig::SimpleConfig); + for (auto groupIt = mKdeGlobalsPortal.constBegin(); groupIt != mKdeGlobalsPortal.constEnd(); ++groupIt) { + if (groupIt.key().startsWith(QStringLiteral("org.kde.kdeglobals.Colors:"))) { + KConfigGroup tempGroup(tempConfig, groupIt.key().right(groupIt.key().length() - QStringLiteral("org.kde.kdeglobals.").length())); + for (auto valueIt = groupIt.value().constBegin(); valueIt != groupIt.value().constEnd(); ++valueIt) { + tempGroup.writeEntry(valueIt.key(), valueIt.value()); + } + } + } + m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(tempConfig)); + } else if (mKdeGlobals->hasGroup("Colors:View")) { m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(mKdeGlobals)); } else { - KConfigGroup cg(mKdeGlobals, "KDE"); - const QString looknfeel = cg.readEntry("LookAndFeelPackage", defaultLookAndFeelPackage); + const QString looknfeel = readConfigValue(cg, QStringLiteral("LookAndFeelPackage"), defaultLookAndFeelPackage).toString(); QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/look-and-feel/") + looknfeel + QStringLiteral("/contents/colors")); if (!path.isEmpty()) { m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(KSharedConfig::openConfig(path))); @@ -417,3 +501,21 @@ } #endif } + +void KHintsSettings::updatePortalSetting() +{ + mKdeGlobalsPortal.clear(); + + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.portal.Desktop"), + QStringLiteral("/org/freedesktop/portal/desktop"), + QStringLiteral("org.freedesktop.portal.Settings"), + QStringLiteral("ReadAll")); + message << QStringList{QStringLiteral("org.kde.kdeglobals.*")}; + + // FIXME: async? + QDBusMessage resultMessage = QDBusConnection::sessionBus().call(message); + if (resultMessage.type() == QDBusMessage::ReplyMessage) { + QDBusArgument dbusArgument = resultMessage.arguments().at(0).value(); + dbusArgument >> mKdeGlobalsPortal; + } +}