File indexing completed on 2025-03-23 11:14:12
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "genericscriptedconfig.h" 0010 0011 #include "config-kwin.h" 0012 0013 #include <kwineffects_interface.h> 0014 0015 #include <KAboutData> 0016 #define TRANSLATION_DOMAIN "kwin_scripting" 0017 #include <KLocalizedString> 0018 #include <KLocalizedTranslator> 0019 #include <kconfigloader.h> 0020 0021 #include <QFile> 0022 #include <QLabel> 0023 #include <QStandardPaths> 0024 #include <QUiLoader> 0025 #include <QVBoxLayout> 0026 0027 namespace KWin 0028 { 0029 0030 QObject *GenericScriptedConfigFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword) 0031 { 0032 // the plugin id is in the args when created by desktop effects kcm or EffectsModel in general 0033 QString pluginId = args.isEmpty() ? QString() : args.first().toString(); 0034 0035 // If we do not get the id of the effect we want to load from the args, we have to check our metadata. 0036 // This can be the case if the factory gets loaded from a KPluginSelector 0037 // the plugin id is in plugin factory metadata when created by scripts kcm 0038 // (because it uses kpluginselector, which doesn't pass the plugin id as the first arg), 0039 // can be dropped once the scripts kcm is ported to qtquick (because then we could pass the plugin id via the args) 0040 if (pluginId.isEmpty()) { 0041 pluginId = metaData().pluginId(); 0042 } 0043 if (pluginId.startsWith(QLatin1String("kwin4_effect_"))) { 0044 return new ScriptedEffectConfig(pluginId, parentWidget, args); 0045 } else { 0046 return new ScriptingConfig(pluginId, parentWidget, args); 0047 } 0048 } 0049 0050 GenericScriptedConfig::GenericScriptedConfig(const QString &keyword, QWidget *parent, const QVariantList &args) 0051 : KCModule(parent, args) 0052 , m_packageName(keyword) 0053 , m_translator(new KLocalizedTranslator(this)) 0054 { 0055 QCoreApplication::instance()->installTranslator(m_translator); 0056 } 0057 0058 GenericScriptedConfig::~GenericScriptedConfig() 0059 { 0060 } 0061 0062 void GenericScriptedConfig::createUi() 0063 { 0064 QVBoxLayout *layout = new QVBoxLayout(this); 0065 0066 const QString packageRoot = QStandardPaths::locate(QStandardPaths::GenericDataLocation, 0067 QLatin1String("kwin/") + typeName() + QLatin1Char('/') + m_packageName, 0068 QStandardPaths::LocateDirectory); 0069 if (packageRoot.isEmpty()) { 0070 layout->addWidget(new QLabel(i18nc("Error message", "Could not locate package metadata"))); 0071 return; 0072 } 0073 0074 KPluginMetaData metaData(packageRoot + QLatin1String("/metadata.json")); 0075 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0076 if (!metaData.isValid()) { 0077 metaData = KPluginMetaData::fromDesktopFile(packageRoot + QLatin1String("/metadata.desktop")); 0078 if (metaData.isValid()) { 0079 qWarning("metadata.desktop format is obsolete. Please convert %s to JSON metadata", qPrintable(metaData.fileName())); 0080 } 0081 } 0082 #endif 0083 if (!metaData.isValid()) { 0084 layout->addWidget(new QLabel(i18nc("Required file does not exist", "%1 does not contain a valid metadata.json file", qPrintable(packageRoot)))); 0085 return; 0086 } 0087 0088 const QString kconfigXTFile = packageRoot + QLatin1String("/contents/config/main.xml"); 0089 if (!QFileInfo::exists(kconfigXTFile)) { 0090 layout->addWidget(new QLabel(i18nc("Required file does not exist", "%1 does not exist", qPrintable(kconfigXTFile)))); 0091 return; 0092 } 0093 0094 const QString uiPath = packageRoot + QLatin1String("/contents/ui/config.ui"); 0095 if (!QFileInfo::exists(uiPath)) { 0096 layout->addWidget(new QLabel(i18nc("Required file does not exist", "%1 does not exist", qPrintable(uiPath)))); 0097 return; 0098 } 0099 0100 const QString localePath = packageRoot + QLatin1String("/contents/locale"); 0101 if (QFileInfo::exists(localePath)) { 0102 KLocalizedString::addDomainLocaleDir(metaData.value("X-KWin-Config-TranslationDomain").toUtf8(), localePath); 0103 } 0104 0105 QFile xmlFile(kconfigXTFile); 0106 KConfigGroup cg = configGroup(); 0107 KConfigLoader *configLoader = new KConfigLoader(cg, &xmlFile, this); 0108 // load the ui file 0109 QUiLoader *loader = new QUiLoader(this); 0110 loader->setLanguageChangeEnabled(true); 0111 QFile uiFile(uiPath); 0112 m_translator->setTranslationDomain(metaData.value("X-KWin-Config-TranslationDomain")); 0113 0114 uiFile.open(QFile::ReadOnly); 0115 QWidget *customConfigForm = loader->load(&uiFile, this); 0116 m_translator->addContextToMonitor(customConfigForm->objectName()); 0117 uiFile.close(); 0118 0119 // send a custom event to the translator to retranslate using our translator 0120 QEvent le(QEvent::LanguageChange); 0121 QCoreApplication::sendEvent(customConfigForm, &le); 0122 0123 layout->addWidget(customConfigForm); 0124 addConfig(configLoader, customConfigForm); 0125 } 0126 0127 void GenericScriptedConfig::save() 0128 { 0129 KCModule::save(); 0130 reload(); 0131 } 0132 0133 void GenericScriptedConfig::reload() 0134 { 0135 } 0136 0137 ScriptedEffectConfig::ScriptedEffectConfig(const QString &keyword, QWidget *parent, const QVariantList &args) 0138 : GenericScriptedConfig(keyword, parent, args) 0139 { 0140 createUi(); 0141 } 0142 0143 ScriptedEffectConfig::~ScriptedEffectConfig() 0144 { 0145 } 0146 0147 QString ScriptedEffectConfig::typeName() const 0148 { 0149 return QStringLiteral("effects"); 0150 } 0151 0152 KConfigGroup ScriptedEffectConfig::configGroup() 0153 { 0154 return KSharedConfig::openConfig(QStringLiteral(KWIN_CONFIG))->group(QLatin1String("Effect-") + packageName()); 0155 } 0156 0157 void ScriptedEffectConfig::reload() 0158 { 0159 OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), 0160 QStringLiteral("/Effects"), 0161 QDBusConnection::sessionBus()); 0162 interface.reconfigureEffect(packageName()); 0163 } 0164 0165 ScriptingConfig::ScriptingConfig(const QString &keyword, QWidget *parent, const QVariantList &args) 0166 : GenericScriptedConfig(keyword, parent, args) 0167 { 0168 createUi(); 0169 } 0170 0171 ScriptingConfig::~ScriptingConfig() 0172 { 0173 } 0174 0175 KConfigGroup ScriptingConfig::configGroup() 0176 { 0177 return KSharedConfig::openConfig(QStringLiteral(KWIN_CONFIG))->group(QLatin1String("Script-") + packageName()); 0178 } 0179 0180 QString ScriptingConfig::typeName() const 0181 { 0182 return QStringLiteral("scripts"); 0183 } 0184 0185 void ScriptingConfig::reload() 0186 { 0187 // TODO: what to call 0188 } 0189 0190 } // namespace