Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPluginLoader.cpp
Go to the documentation of this file.
1
2/*
3 * SPDX-FileCopyrightText: 2006-2016 Boudewijn Rempt <boud@valdyas.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "KoPluginLoader.h"
9
10#include <KoJsonTrader.h>
11
12#include <QJsonObject>
13#include <QPluginLoader>
14
15#include "kis_debug.h"
16
17#include <kis_debug.h>
18
19#include <KConfig>
20#include <KSharedConfig>
21#include <KConfigGroup>
22#include <KPluginFactory>
23
24namespace
25{
26int versionFromPlugin(const KoJsonTrader::Plugin &plugin)
27{
28 QJsonObject json = plugin.metaData().value("MetaData").toObject();
29 QVariant version = json.value("X-Krita-Version");
30 return version.toString().toInt();
31};
32
33QString idFromPlugin(const KoJsonTrader::Plugin &plugin)
34{
35 QJsonObject json = plugin.metaData().value("MetaData").toObject();
36 return json.value("Id").toString();
37};
38
39bool versionCompareLess(const KoJsonTrader::Plugin &lhs, const KoJsonTrader::Plugin &rhs)
40{
41 return versionFromPlugin(lhs) < versionFromPlugin(rhs);
42};
43
44bool idCompareEqual(const KoJsonTrader::Plugin &lhs, const KoJsonTrader::Plugin &rhs)
45{
46 return idFromPlugin(lhs) == idFromPlugin(rhs);
47};
48
49bool sortByIdAndReversedVersion(const KoJsonTrader::Plugin &lhs, const KoJsonTrader::Plugin &rhs)
50{
51 const QString lhsId = idFromPlugin(lhs);
52 const QString rhsId = idFromPlugin(rhs);
53 return lhsId < rhsId ||
54 (lhsId == rhsId && versionCompareLess(rhs, lhs));
55};
56
57} // namespace
58
59
60class Q_DECL_HIDDEN KoPluginLoader::Private
61{
62public:
64};
65
70
75
76Q_GLOBAL_STATIC(KoPluginLoader, pluginLoaderInstance)
77
79{
80 return pluginLoaderInstance();
81}
82
83void KoPluginLoader::load(const QString & serviceType, const PluginsConfig &config, QObject* owner, bool cache)
84{
85 // Don't load the same plugins again
86 if (cache && d->loadedServiceTypes.contains(serviceType)) {
87 return;
88 }
89 d->loadedServiceTypes << serviceType;
90
91 QList<KoJsonTrader::Plugin> plugins = KoJsonTrader::instance()->query(serviceType, QString());
92
93 {
98 std::sort(plugins.begin(), plugins.end(), &sortByIdAndReversedVersion);
99 auto it = plugins.begin();
100 while ((it = std::adjacent_find(it, plugins.end(), &idCompareEqual)) != plugins.end()) {
101 warnPlugins << "Skipping duplicated plugin, id:" << idFromPlugin(*it)
102 << "version:" << versionFromPlugin(*it) << "filename:" << it->fileName();
108 it = std::prev(plugins.erase(std::next(it)));
109 }
110 }
111
112 if (config.isValid()) {
116 KConfigGroup configGroup(KSharedConfig::openConfig(), config.group);
117 QStringList blackList = configGroup.readEntry(config.blacklist, QStringList());
118
119 auto it = plugins.begin();
120 while (it != plugins.end()) {
121 if (blackList.contains(idFromPlugin(*it))) {
122 it = plugins.erase(it);
123 } else {
124 ++it;
125 }
126 }
127 }
128
135 for (KoJsonTrader::Plugin &plugin : plugins) {
136 const QString pluginName = idFromPlugin(plugin);
137 dbgPlugins << "loading" << pluginName;
138
139 QObject *object = 0;
140
141 KPluginFactory *factory = qobject_cast<KPluginFactory *>(plugin.instance());
142 if (factory) {
143 object = factory->create<QObject>(owner ? owner : this, QVariantList());
144 }
145
146 if (object) {
147 dbgPlugins << "\tLoaded plugin" << plugin.fileName() << "owner:" << owner;
148 if (!owner) {
149 delete object;
150 }
151 } else {
152 qWarning() << "\tLoading plugin" << plugin.fileName() << "failed, " << plugin.errorString();
153 }
154 }
155}
156
157KPluginFactory* KoPluginLoader::loadSinglePlugin(const std::vector<std::pair<QString, QString>> &predicates, const QString &serviceType)
158{
159 QList<KoJsonTrader::Plugin> offers = KoJsonTrader::instance()->query(serviceType, QString());
160
161 offers.erase(std::remove_if(offers.begin(),
162 offers.end(),
163 [&](const KoJsonTrader::Plugin &plugin) {
164 QJsonObject json = plugin.metaData().value("MetaData").toObject();
165 Q_FOREACH(const auto &predicate, predicates) {
166 if (json.value(predicate.first).toString() != predicate.second) {
167 return true;
168 }
169 }
170 return false;
171 }),
172 offers.end());
173
174 auto it = std::max_element(offers.begin(), offers.end(), versionCompareLess);
175
176 if (it != offers.end()) {
177 KPluginFactory *factory = qobject_cast<KPluginFactory *>(it->instance());
178 return factory;
179 }
180
181 return nullptr;
182}
183
184KPluginFactory* KoPluginLoader::loadSinglePlugin(const std::pair<QString, QString> &predicates, const QString & serviceType)
185{
186 return loadSinglePlugin(std::vector<std::pair<QString, QString>>{predicates}, serviceType);
187}
188
189KPluginFactory* KoPluginLoader::loadSinglePlugin(const QString &id, const QString &serviceType)
190{
191 return loadSinglePlugin({"Id", id}, serviceType);
192}
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
PythonPluginManager * instance
static KoJsonTrader * instance()
QList< Plugin > query(const QString &servicetype, const QString &mimetype)
Private *const d
void load(const QString &serviceType, const PluginsConfig &config=PluginsConfig(), QObject *owner=0, bool cache=true)
~KoPluginLoader() override
QStringList loadedServiceTypes
KPluginFactory * loadSinglePlugin(const std::vector< std::pair< QString, QString > > &predicates, const QString &serviceType)
KoPluginLoader()
DO NOT USE! Use instance() instead.
#define warnPlugins
Definition kis_debug.h:93
#define dbgPlugins
Definition kis_debug.h:51
QObject * instance() const
QString fileName() const
QJsonObject metaData() const
QString errorString() const
const char * blacklist
This contains the variable name for the list of plugins (by library name) that will not be loaded.