File indexing completed on 2024-05-12 15:59:03
0001 /* 0002 * SPDX-FileCopyrightText: 2006-2016 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "KoPluginLoader.h" 0008 0009 #include <KoJsonTrader.h> 0010 0011 #include <QJsonObject> 0012 #include <QPluginLoader> 0013 0014 #include "kis_debug.h" 0015 0016 #include <kis_debug.h> 0017 0018 #include <KConfig> 0019 #include <KSharedConfig> 0020 #include <KConfigGroup> 0021 #include <KPluginFactory> 0022 0023 class Q_DECL_HIDDEN KoPluginLoader::Private 0024 { 0025 public: 0026 QStringList loadedServiceTypes; 0027 }; 0028 0029 KoPluginLoader::KoPluginLoader() 0030 : d(new Private()) 0031 { 0032 } 0033 0034 KoPluginLoader::~KoPluginLoader() 0035 { 0036 delete d; 0037 } 0038 0039 Q_GLOBAL_STATIC(KoPluginLoader, pluginLoaderInstance) 0040 0041 KoPluginLoader* KoPluginLoader::instance() 0042 { 0043 return pluginLoaderInstance(); 0044 } 0045 0046 void KoPluginLoader::load(const QString & serviceType, const QString & versionString, const PluginsConfig &config, QObject* owner, bool cache) 0047 { 0048 0049 // Don't load the same plugins again 0050 if (cache && d->loadedServiceTypes.contains(serviceType)) { 0051 return; 0052 } 0053 d->loadedServiceTypes << serviceType; 0054 QString query = QString::fromLatin1("(Type == 'Service')"); 0055 if (!versionString.isEmpty()) { 0056 query += QString::fromLatin1(" and (%1)").arg(versionString); 0057 } 0058 0059 QList<KoJsonTrader::Plugin> offers = KoJsonTrader::instance()->query(serviceType, QString()); 0060 0061 QList<KoJsonTrader::Plugin> plugins; 0062 0063 bool configChanged = false; 0064 QList<QString> blacklist; // what we will save out afterwards 0065 if (config.whiteList && config.blacklist && config.group) { 0066 dbgPlugins << "Loading" << serviceType << "with checking the config"; 0067 KConfigGroup configGroup(KSharedConfig::openConfig(), config.group); 0068 QList<QString> whiteList = configGroup.readEntry(config.whiteList, config.defaults); 0069 QList<QString> knownList; 0070 0071 // if there was no list of defaults; all plugins are loaded. 0072 const bool firstStart = !config.defaults.isEmpty() && !configGroup.hasKey(config.whiteList); 0073 knownList = configGroup.readEntry(config.blacklist, knownList); 0074 if (firstStart) { 0075 configChanged = true; 0076 } 0077 Q_FOREACH (const KoJsonTrader::Plugin &loader, offers) { 0078 QJsonObject json = loader.metaData().value("MetaData").toObject(); 0079 if (json.contains("KPlugin")) { 0080 json = json.value("KPlugin").toObject(); 0081 } 0082 const QString pluginName = json.value("Id").toString(); 0083 if (pluginName.isEmpty()) { 0084 qWarning() << "Loading plugin" << loader.fileName() << "failed, has no X-KDE-PluginInfo-Name."; 0085 continue; 0086 } 0087 0088 if (whiteList.contains(pluginName)) { 0089 plugins.append(loader); 0090 } 0091 else if (!firstStart && !knownList.contains(pluginName)) { // also load newly installed plugins. 0092 plugins.append(loader); 0093 configChanged = true; 0094 } 0095 else { 0096 blacklist << pluginName; 0097 } 0098 } 0099 } else { 0100 plugins = offers; 0101 } 0102 0103 QMap<QString, KoJsonTrader::Plugin> serviceNames; 0104 Q_FOREACH (const KoJsonTrader::Plugin &loader, plugins) { 0105 if (serviceNames.contains(loader.fileName())) { // duplicate 0106 QJsonObject json2 = loader.metaData().value("MetaData").toObject(); 0107 QVariant pluginVersion2 = json2.value("X-Flake-PluginVersion").toVariant(); 0108 if (pluginVersion2.isNull()) { // just take the first one found... 0109 continue; 0110 } 0111 KoJsonTrader::Plugin currentLoader = serviceNames.value(loader.fileName()); 0112 QJsonObject json = currentLoader.metaData().value("MetaData").toObject(); 0113 QVariant pluginVersion = json.value("X-Flake-PluginVersion").toVariant(); 0114 if (!(pluginVersion.isNull() || pluginVersion.toInt() < pluginVersion2.toInt())) { 0115 continue; // replace the old one with this one, since its newer. 0116 } 0117 } 0118 serviceNames.insert(loader.fileName(), loader); 0119 } 0120 0121 QList<QString> whiteList; 0122 Q_FOREACH (const QString &serviceName, serviceNames.keys()) { 0123 dbgPlugins << "loading" << serviceName; 0124 KoJsonTrader::Plugin loader = serviceNames[serviceName]; 0125 KPluginFactory *factory = qobject_cast<KPluginFactory *>(loader.instance()); 0126 QObject *plugin = 0; 0127 if (factory) { 0128 plugin = factory->create<QObject>(owner ? owner : this, QVariantList()); 0129 } 0130 if (plugin) { 0131 QJsonObject json = loader.metaData().value("MetaData").toObject(); 0132 json = json.value("KPlugin").toObject(); 0133 const QString pluginName = json.value("Id").toString(); 0134 whiteList << pluginName; 0135 dbgPlugins << "\tLoaded plugin" << loader.fileName() << owner; 0136 if (!owner) { 0137 delete plugin; 0138 } 0139 } else { 0140 qWarning() << "Loading plugin" << loader.fileName() << "failed, " << loader.errorString(); 0141 } 0142 } 0143 0144 if (configChanged && config.whiteList && config.blacklist && config.group) { 0145 KConfigGroup configGroup(KSharedConfig::openConfig(), config.group); 0146 configGroup.writeEntry(config.whiteList, whiteList); 0147 configGroup.writeEntry(config.blacklist, blacklist); 0148 } 0149 }