From 37ba0404c8246cf7ba85b8ada97c8ffe2eef93a5 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Wed, 30 Sep 2020 13:53:44 +0200 Subject: [PATCH] [kcms/effectsmodel] Add config module role to effectsmodel and use it to open config For builtin effects the information comes from the EffectData struct. For plugin effects the X-KDE-ConfigModule key is read from the plugin metadata. For plugins that do not yet make use of it we fall back to the old way. For scripted effects this is empty since the config is loaded in a different way. --- kcmkwin/common/effectsmodel.cpp | 73 ++++++++++++++++++++++----------- kcmkwin/common/effectsmodel.h | 12 ++++-- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/kcmkwin/common/effectsmodel.cpp b/kcmkwin/common/effectsmodel.cpp index cfec9e08ed..06a49f25c0 100644 --- a/kcmkwin/common/effectsmodel.cpp +++ b/kcmkwin/common/effectsmodel.cpp @@ -97,6 +97,7 @@ QHash EffectsModel::roleNames() const roleNames[ConfigurableRole] = "ConfigurableRole"; roleNames[ScriptedRole] = QByteArrayLiteral("ScriptedRole"); roleNames[EnabledByDefaultRole] = "EnabledByDefaultRole"; + roleNames[ConfigModuleRole] = "ConfigModuleRole"; return roleNames; } @@ -174,6 +175,8 @@ QVariant EffectsModel::data(const QModelIndex &index, int role) const return effect.kind == Kind::Scripted; case EnabledByDefaultRole: return effect.enabledByDefault; + case ConfigModuleRole: + return effect.configModule; default: return {}; } @@ -215,7 +218,7 @@ bool EffectsModel::setData(const QModelIndex &index, const QVariant &value, int return QAbstractItemModel::setData(index, value, role); } -void EffectsModel::loadBuiltInEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs) +void EffectsModel::loadBuiltInEffects(const KConfigGroup &kwinConfig) { const auto builtins = BuiltInEffects::availableEffects(); for (auto builtin : builtins) { @@ -248,12 +251,9 @@ void EffectsModel::loadBuiltInEffects(const KConfigGroup &kwinConfig, const KPlu effect.exclusiveGroup = data.exclusiveCategory; effect.internal = data.internal; effect.kind = Kind::BuiltIn; + effect.configModule = data.configModule; - effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), - [data](const KPluginInfo &info) { - return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == data.name; - } - ); + effect.configurable = !effect.configModule.isEmpty(); if (shouldStore(effect)) { m_pendingEffects << effect; @@ -306,7 +306,7 @@ void EffectsModel::loadJavascriptEffects(const KConfigGroup &kwinConfig) } } -void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs) +void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig) { const auto pluginEffects = KPluginLoader::findPlugins( QStringLiteral("kwin/effects/plugins/"), @@ -332,6 +332,22 @@ void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig, const KPlug effect.enabledByDefaultFunction = false; effect.internal = false; effect.kind = Kind::Binary; + effect.configModule = pluginEffect.value(QStringLiteral("X-KDE-ConfigModule")); + + // Compatibility with plugins that don't have ConfigModule in their metadata + // TODO KF6 remove + if (effect.configModule.isEmpty()) { + + const QList infos = KPluginTrader::self()->query( + QStringLiteral("kwin/effects/configs/"), + QString(), + QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(pluginEffect.pluginId()) + ); + + if (!infos.isEmpty()) { + effect.configModule = infos.first().pluginName(); + } + } for (int i = 0; i < pluginEffect.authors().count(); ++i) { effect.authorName.append(pluginEffect.authors().at(i).name()); @@ -362,11 +378,7 @@ void EffectsModel::loadPluginEffects(const KConfigGroup &kwinConfig, const KPlug effect.originalStatus = effect.status; - effect.configurable = std::any_of(configs.constBegin(), configs.constEnd(), - [pluginEffect](const KPluginInfo &info) { - return info.property(QStringLiteral("X-KDE-ParentComponents")).toString() == pluginEffect.pluginId(); - } - ); + effect.configurable = !effect.configModule.isEmpty(); if (shouldStore(effect)) { m_pendingEffects << effect; @@ -379,10 +391,9 @@ void EffectsModel::load(LoadOptions options) KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); m_pendingEffects.clear(); - const KPluginInfo::List configs = KPluginTrader::self()->query(QStringLiteral("kwin/effects/configs/")); - loadBuiltInEffects(kwinConfig, configs); + loadBuiltInEffects(kwinConfig); loadJavascriptEffects(kwinConfig); - loadPluginEffects(kwinConfig, configs); + loadPluginEffects(kwinConfig); std::sort(m_pendingEffects.begin(), m_pendingEffects.end(), [](const EffectData &a, const EffectData &b) { @@ -585,14 +596,18 @@ QModelIndex EffectsModel::findByPluginId(const QString &pluginId) const return index(std::distance(m_effects.constBegin(), it), 0); } -static KCModule *findBinaryConfig(const QString &pluginId, QObject *parent) +static KCModule *loadBinaryConfig(const QString &configModule, QObject *parent) { - return KPluginTrader::createInstanceFromQuery( - QStringLiteral("kwin/effects/configs/"), - QString(), - QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(pluginId), - parent - ); + const QVector offers = KPluginLoader::findPluginsById(QStringLiteral("kwin/effects/configs/"), configModule); + + if (offers.isEmpty()) { + return nullptr; + } + + KPluginLoader loader(offers.first().fileName()); + KPluginFactory *factory = loader.factory(); + + return factory->create(parent); } static KCModule *findScriptedConfig(const QString &pluginId, QObject *parent) @@ -621,9 +636,17 @@ void EffectsModel::requestConfigure(const QModelIndex &index, QWindow *transient auto dialog = new QDialog(); - KCModule *module = index.data(ScriptedRole).toBool() - ? findScriptedConfig(index.data(ServiceNameRole).toString(), dialog) - : findBinaryConfig(index.data(ServiceNameRole).toString(), dialog); + const bool scripted = index.data(ScriptedRole).toBool(); + + KCModule *module = nullptr; + + if (scripted) { + module = findScriptedConfig(index.data(ServiceNameRole).toString(), dialog); + } else { + const QString configModule = index.data(ConfigModuleRole).toString(); + module = loadBinaryConfig(configModule, dialog); + } + if (!module) { delete dialog; return; diff --git a/kcmkwin/common/effectsmodel.h b/kcmkwin/common/effectsmodel.h index 2a822327d5..5873fd0f87 100644 --- a/kcmkwin/common/effectsmodel.h +++ b/kcmkwin/common/effectsmodel.h @@ -12,7 +12,6 @@ #include -#include #include #include @@ -105,7 +104,11 @@ public: /** * Whether the effect is enabled by default. */ - EnabledByDefaultRole + EnabledByDefaultRole, + /** + * Id of the effect's config module, empty if the effect has no config. + */ + ConfigModuleRole }; /** @@ -239,6 +242,7 @@ protected: bool configurable; Kind kind; bool changed = false; + QString configModule; }; /** @@ -250,9 +254,9 @@ protected: virtual bool shouldStore(const EffectData &data) const; private: - void loadBuiltInEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs); + void loadBuiltInEffects(const KConfigGroup &kwinConfig); void loadJavascriptEffects(const KConfigGroup &kwinConfig); - void loadPluginEffects(const KConfigGroup &kwinConfig, const KPluginInfo::List &configs); + void loadPluginEffects(const KConfigGroup &kwinConfig); QVector m_effects; QVector m_pendingEffects;