15
15
* <a href="mailto:andi dot clemens at googlemail dot com">andi dot clemens at googlemail dot com</a>
16
16
* @author Copyright (C) 2009 by Aleix Pol Gonzalez
17
17
* <a href="mailto:aleixpol at kde dot org">aleixpol at kde dot org</a>
18
* @author Copyright (C) 2012 by Victor Dodon
19
* <a href="mailto:dodonvictor at gmail dot com">dodonvictor at gmail dot com</a>
19
21
* This program is free software; you can redistribute it
20
22
* and/or modify it under the terms of the GNU General
32
34
#include "pluginloader.moc"
36
38
#include <QStringList>
39
41
#include <QVariantList>
43
46
#include <kservicetypetrader.h>
44
47
#include <kdebug.h>
45
48
#include <kdialog.h>
49
#include <kdeversion.h>
46
50
#include <ksharedconfig.h>
51
#include <kdesktopfile.h>
47
52
#include <kconfig.h>
48
53
#include <kglobal.h>
49
54
#include <klibloader.h>
50
55
#include <kaction.h>
56
#include <kxmlguifactory.h>
58
#include <kstandarddirs.h>
59
#include <kactioncollection.h>
54
63
#include "plugin.h"
55
64
#include "interface.h"
56
65
#include "version.h"
66
#include "configwidget.h"
61
class PluginLoader::Info::InfoPrivate
71
class PluginLoader::Info::Private
67
77
shouldLoad = false;
72
KService::Ptr service;
83
KService::Ptr service;
85
KXmlGuiWindow* parent;
76
PluginLoader::Info::Info(const KService::Ptr& service, bool shouldLoad)
88
PluginLoader::Info::Info(KXmlGuiWindow* const parent, const KService::Ptr& service, bool shouldLoad)
79
91
d->service = service;
80
92
d->shouldLoad = shouldLoad;
83
96
PluginLoader::Info::~Info()
98
if (d->parent && d->plugin)
100
d->parent->guiFactory()->removeClient(d->plugin);
101
#if KDE_IS_VERSION(4,8,5)
102
foreach(KToolBar* const toolbar, d->parent->toolBars())
104
toolbar->removeXMLGUIClient(d->plugin);
130
159
if (!d->plugin && shouldLoad())
133
Plugin* plugin = d->service->createInstance<Plugin>(PluginLoader::instance()->interface(), QVariantList(), &error);
163
d->plugin = d->service->createInstance<Plugin>(PluginLoader::instance()->interface(), QVariantList(), &error);
137
kDebug(51001) << "Loaded plugin " << plugin->objectName();
139
QVariant binaryVersion = plugin->property("KipiBinaryVersion");
141
if (!binaryVersion.isValid() || binaryVersion.toInt() != kipi_binary_version)
143
kDebug(51001) << "Plugin " << plugin->objectName()
144
<< "is compiled for a different libkipi ABI version."
145
<< "Refusing to load.";
167
kDebug(51001) << "Loaded plugin " << d->plugin->objectName();
169
emit (PluginLoader::instance()->plug(const_cast<Info*>(this)));
152
kWarning(51001) << "CreateInstance returned 0 for "
173
kWarning(51001) << "Cannot create instance for plugin "
154
175
<< " (" << library() << ")"
155
176
<< " with error: "
161
if (d->plugin) // Do not emit if we had trouble loading the plugin.
163
emit (PluginLoader::instance()->plug(const_cast<Info*>(this)));
167
181
return d->plugin;
184
QStringList PluginLoader::Info::pluginCategories() const
186
return d->service->property(QString::fromLatin1("X-KIPI-PluginCategories")).toStringList();
170
189
void PluginLoader::Info::reload()
193
d->parent->guiFactory()->removeClient(d->plugin);
194
#if KDE_IS_VERSION(4,8,5)
195
foreach(KToolBar* const toolbar, d->parent->toolBars())
197
toolbar->removeXMLGUIClient(d->plugin);
172
202
delete d->plugin;
186
216
//---------------------------------------------------------------------
188
218
static PluginLoader* s_instance = 0;
219
static bool s_loaded = false;
190
class PluginLoader::PluginLoaderPrivate
221
class PluginLoader::Private
194
PluginLoaderPrivate()
231
QStringList ignoredPlugins;
232
QStringList disabledActions;
234
KXmlGuiWindow* parent;
199
236
PluginLoader::PluginList pluginList;
200
237
Interface* interface;
203
PluginLoader::PluginLoader(const QStringList& ignores, Interface* const interface)
204
: d(new PluginLoaderPrivate)
206
construct(ignores, interface, QString());
209
PluginLoader::PluginLoader(const QStringList& ignores, Interface* const interface, const QString& constraint)
210
: d(new PluginLoaderPrivate)
212
construct(ignores, interface, constraint);
215
void PluginLoader::construct(const QStringList& ignores, Interface* const interface, const QString& constraint)
217
Q_ASSERT(s_instance == 0);
219
d->interface = interface;
220
const KService::List offers = KServiceTypeTrader::self()->query("KIPI/Plugin", constraint);
240
PluginLoader::PluginLoader()
243
Q_ASSERT((s_instance == 0) && (!s_loaded));
246
KGlobal::dirs()->addResourceDir("data", KStandardDirs::installPath("data") + QString("kipi"));
249
PluginLoader::PluginLoader(KXmlGuiWindow* const parent)
252
Q_ASSERT((s_instance == 0) && (!s_loaded));
255
KGlobal::dirs()->addResourceDir("data", KStandardDirs::installPath("data") + QString("kipi"));
259
kWarning() << "KDE XML application instance is null...";
265
void PluginLoader::setInterface(Interface* const interface)
267
d->interface = interface;
268
setParent(interface);
271
void PluginLoader::setIgnoredPluginsList(const QStringList& ignores)
273
d->ignoredPlugins = ignores;
276
void PluginLoader::setDisabledPluginActions(const QStringList& disabledActions)
278
d->disabledActions = disabledActions;
281
QStringList PluginLoader::disabledPluginActions() const
283
return d->disabledActions;
286
void PluginLoader::init()
288
Q_ASSERT((s_instance != 0) && (!s_loaded));
292
kWarning() << "KIPI host interface instance is null. No plugin will be loaded...";
297
const KService::List offers = KServiceTypeTrader::self()->query("KIPI/Plugin");
221
298
KSharedConfigPtr config = KGlobal::config();
222
299
KConfigGroup group = config->group(QString::fromLatin1("KIPI/EnabledPlugin"));
237
if (ignores.contains(name))
315
if (d->ignoredPlugins.contains(name))
239
317
kDebug(51001) << "Plugin " << name << " is in the ignore list from host application";
321
if (binVersion != kipi_binary_version)
323
kDebug(51001) << "Plugin " << name
324
<< "has a SO version (" << binVersion
325
<< ") which is different than libkipi ABI version (" << kipi_binary_version << "). "
326
<< "Refusing to load.";
243
330
bool appHasAllReqFeatures = true;
245
332
for (QStringList::const_iterator featureIt = reqFeatures.constBegin();
302
388
return new ConfigWidget(parent);
305
// ---------------------------------------------------------------------
307
class PluginCheckBox : public QListWidgetItem
311
PluginCheckBox(PluginLoader::Info* const info, QListWidget* const parent)
312
: QListWidgetItem(parent, QListWidgetItem::UserType),
315
setText(QString("%1 (%2)").arg(info->name(), info->comment()));
316
setIcon(info->icon());
317
setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
318
setCheckState(info->shouldLoad() ? Qt::Checked : Qt::Unchecked);
321
PluginLoader::Info* info;
324
// ---------------------------------------------------------------------
326
class ConfigWidget::ConfigWidgetPrivate
330
ConfigWidgetPrivate()
334
QList<PluginCheckBox*> boxes;
337
ConfigWidget::ConfigWidget(QWidget* const parent)
338
: QListWidget(parent),
339
d(new ConfigWidgetPrivate)
341
setAutoFillBackground(false);
342
setSortingEnabled(true);
343
viewport()->setAutoFillBackground(false);
345
foreach(PluginLoader::Info* info, PluginLoader::instance()->pluginList())
347
PluginCheckBox* cb = new PluginCheckBox(info, this);
352
ConfigWidget::~ConfigWidget()
357
void ConfigWidget::apply()
359
KSharedConfigPtr config = KGlobal::config();
360
KConfigGroup group = config->group(QString::fromLatin1("KIPI/EnabledPlugin"));
362
for (QList<PluginCheckBox*>::Iterator it = d->boxes.begin(); it != d->boxes.end(); ++it)
364
bool orig = (*it)->info->shouldLoad();
365
bool load = ((*it)->checkState() == Qt::Checked);
369
group.writeEntry((*it)->info->name(), load);
370
(*it)->info->setShouldLoad(load);
372
// Bugfix #289779 - Plugins are not really freed / unplugged when disabled in the kipi setup dialog, always call reload()
373
// to reload plugins properly when the replug() signal is send.
377
(*it)->info->reload();
379
else if ((*it)->info->plugin()) // Do not emit if we had trouble loading plugin.
381
emit PluginLoader::instance()->unplug((*it)->info);
384
(*it)->info->reload();
388
emit PluginLoader::instance()->replug();
391
void ConfigWidget::slotCheckAll()
393
for (int i = 0; i < count(); ++i)
395
item(i)->setCheckState(Qt::Checked);
399
void ConfigWidget::slotClear()
401
for (int i = 0; i < count(); ++i)
403
item(i)->setCheckState(Qt::Unchecked);
391
QString PluginLoader::kipiPluginsVersion() const
393
QString ver = i18nc("Version unavailable", "unavailable");
394
QString path = KGlobal::dirs()->installPath("xdgdata-apps") + QString("kipiplugins.desktop");
395
KDesktopFile desk(path);
396
QMap<QString, QString> map = desk.entryMap("X-KipiPlugins Entry");
400
QString val = map["Version"];
407
409
} // namespace KIPI