~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/libkipi/libkipi/pluginloader.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2012-11-26 18:24:20 UTC
  • mfrom: (1.9.1) (3.1.23 experimental)
  • Revision ID: package-import@ubuntu.com-20121126182420-qoy6z0nx4ai0wzcl
Tags: 4:3.0.0~beta3-0ubuntu1
* New upstream release
  - Add build-deps :  libhupnp-dev, libqtgstreamer-dev, libmagickcore-dev
* Merge from debian, remaining changes:
  - Make sure libqt4-opengl-dev, libgl1-mesa-dev and libglu1-mesa-dev only
    install on i386,amd64 and powerpc
  - Depend on libtiff-dev instead of libtiff4-dev
  - Drop digikam breaks/replaces kipi-plugins-common since we're past the
    LTS release now
  - digikam to recommend mplayerthumbs | ffmpegthumbs. We currently only
    have latter in the archives, even though former is also supposed to
    be part of kdemultimedia. (LP: #890059)
  - kipi-plugins to recommend www-browser rather than konqueror directly
    since 2.8 no direct usage of konqueror is present in the flickr
    plugin anymore (LP: #1011211)
  - Keep kubuntu_mysqld_executable_name.diff
  - Don't install libkipi translations
  - Keep deps on libcv-dev, libcvaux-dev
  - Keep split packaging of libraries
  - Replace icons from KDE 3 time in debian/xpm.d/*.xpm with the new
    versions (LP: #658047)
* Update debian/not-installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
18
20
 *
19
21
 * This program is free software; you can redistribute it
20
22
 * and/or modify it under the terms of the GNU General
31
33
 
32
34
#include "pluginloader.moc"
33
35
 
34
 
// Qt include.
 
36
// Qt includes
35
37
 
36
38
#include <QStringList>
37
39
#include <QLayout>
38
40
#include <QList>
39
41
#include <QVariantList>
 
42
#include <QVariant>
40
43
 
41
44
// KDE includes
42
45
 
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>
 
57
#include <ktoolbar.h>
 
58
#include <kstandarddirs.h>
 
59
#include <kactioncollection.h>
51
60
 
52
61
// Local includes
53
62
 
54
63
#include "plugin.h"
55
64
#include "interface.h"
56
65
#include "version.h"
 
66
#include "configwidget.h"
57
67
 
58
68
namespace KIPI
59
69
{
60
70
 
61
 
class PluginLoader::Info::InfoPrivate
 
71
class PluginLoader::Info::Private
62
72
{
63
73
public:
64
74
 
65
 
    InfoPrivate()
 
75
    Private()
66
76
    {
67
77
        shouldLoad = false;
68
78
        plugin     = 0;
69
 
    };
 
79
        parent     = 0;
 
80
    }
70
81
 
71
 
    bool          shouldLoad;
72
 
    KService::Ptr service;
73
 
    Plugin*       plugin;
 
82
    bool           shouldLoad;
 
83
    KService::Ptr  service;
 
84
    Plugin*        plugin;
 
85
    KXmlGuiWindow* parent;
74
86
};
75
87
 
76
 
PluginLoader::Info::Info(const KService::Ptr& service, bool shouldLoad)
77
 
    : d(new InfoPrivate)
 
88
PluginLoader::Info::Info(KXmlGuiWindow* const parent, const KService::Ptr& service, bool shouldLoad)
 
89
    : d(new Private)
78
90
{
79
91
    d->service    = service;
80
92
    d->shouldLoad = shouldLoad;
 
93
    d->parent     = parent;
81
94
}
82
95
 
83
96
PluginLoader::Info::~Info()
84
97
{
 
98
    if (d->parent && d->plugin)
 
99
    {
 
100
        d->parent->guiFactory()->removeClient(d->plugin);
 
101
#if KDE_IS_VERSION(4,8,5)
 
102
        foreach(KToolBar* const toolbar, d->parent->toolBars())
 
103
        {
 
104
            toolbar->removeXMLGUIClient(d->plugin);
 
105
        }
 
106
#endif
 
107
    }
 
108
 
85
109
    delete d->plugin;
86
110
    delete d;
87
111
}
96
120
    return d->service->name();
97
121
}
98
122
 
 
123
QString PluginLoader::Info::author()  const
 
124
{
 
125
    return d->service->property(QString("author"), QVariant::String).toString();
 
126
}
 
127
 
99
128
QString PluginLoader::Info::comment() const
100
129
{
101
130
    return d->service->comment();
130
159
    if (!d->plugin && shouldLoad())
131
160
    {
132
161
        QString error;
133
 
        Plugin* plugin = d->service->createInstance<Plugin>(PluginLoader::instance()->interface(), QVariantList(), &error);
134
 
 
135
 
        if (plugin)
 
162
 
 
163
        d->plugin = d->service->createInstance<Plugin>(PluginLoader::instance()->interface(), QVariantList(), &error);
 
164
 
 
165
        if (d->plugin)
136
166
        {
137
 
            kDebug(51001) << "Loaded plugin " << plugin->objectName();
138
 
 
139
 
            QVariant binaryVersion = plugin->property("KipiBinaryVersion");
140
 
 
141
 
            if (!binaryVersion.isValid() || binaryVersion.toInt() != kipi_binary_version)
142
 
            {
143
 
                kDebug(51001) << "Plugin " << plugin->objectName()
144
 
                              << "is compiled for a different libkipi ABI version."
145
 
                              << "Refusing to load.";
146
 
                delete plugin;
147
 
                plugin = 0;
148
 
            }
 
167
            kDebug(51001) << "Loaded plugin " << d->plugin->objectName();
 
168
 
 
169
            emit (PluginLoader::instance()->plug(const_cast<Info*>(this)));
149
170
        }
150
171
        else
151
172
        {
152
 
            kWarning(51001) << "CreateInstance returned 0 for "
 
173
            kWarning(51001) << "Cannot create instance for plugin "
153
174
                            << name()
154
175
                            << " (" << library() << ")"
155
176
                            << " with error: "
156
177
                            << error;
157
178
        }
158
 
 
159
 
        d->plugin = plugin;
160
 
 
161
 
        if (d->plugin)   // Do not emit if we had trouble loading the plugin.
162
 
        {
163
 
            emit (PluginLoader::instance()->plug(const_cast<Info*>(this)));
164
 
        }
165
179
    }
166
180
 
167
181
    return d->plugin;
168
182
}
169
183
 
 
184
QStringList PluginLoader::Info::pluginCategories() const
 
185
{
 
186
    return d->service->property(QString::fromLatin1("X-KIPI-PluginCategories")).toStringList();
 
187
}
 
188
 
170
189
void PluginLoader::Info::reload()
171
190
{
 
191
    if (d->parent)
 
192
    {
 
193
        d->parent->guiFactory()->removeClient(d->plugin);
 
194
#if KDE_IS_VERSION(4,8,5)
 
195
        foreach(KToolBar* const toolbar, d->parent->toolBars())
 
196
        {
 
197
            toolbar->removeXMLGUIClient(d->plugin);
 
198
        }
 
199
#endif
 
200
    }
 
201
 
172
202
    delete d->plugin;
173
203
    d->plugin = 0;
174
204
}
186
216
//---------------------------------------------------------------------
187
217
 
188
218
static PluginLoader* s_instance = 0;
 
219
static bool          s_loaded   = false;
189
220
 
190
 
class PluginLoader::PluginLoaderPrivate
 
221
class PluginLoader::Private
191
222
{
192
223
public:
193
224
 
194
 
    PluginLoaderPrivate()
 
225
    Private()
195
226
    {
196
227
        interface = 0;
 
228
        parent    = 0;
197
229
    };
198
230
 
 
231
    QStringList              ignoredPlugins;
 
232
    QStringList              disabledActions;
 
233
 
 
234
    KXmlGuiWindow*           parent;
 
235
 
199
236
    PluginLoader::PluginList pluginList;
200
237
    Interface*               interface;
201
238
};
202
239
 
203
 
PluginLoader::PluginLoader(const QStringList& ignores, Interface* const interface)
204
 
    : d(new PluginLoaderPrivate)
205
 
{
206
 
    construct(ignores, interface, QString());
207
 
}
208
 
 
209
 
PluginLoader::PluginLoader(const QStringList& ignores, Interface* const interface, const QString& constraint)
210
 
    : d(new PluginLoaderPrivate)
211
 
{
212
 
    construct(ignores, interface, constraint);
213
 
}
214
 
 
215
 
void PluginLoader::construct(const QStringList& ignores, Interface* const interface, const QString& constraint)
216
 
{
217
 
    Q_ASSERT(s_instance == 0);
218
 
    s_instance                  = this;
219
 
    d->interface                = interface;
220
 
    const KService::List offers = KServiceTypeTrader::self()->query("KIPI/Plugin", constraint);
 
240
PluginLoader::PluginLoader()
 
241
    : d(new Private)
 
242
{
 
243
    Q_ASSERT((s_instance == 0) && (!s_loaded));
 
244
    s_instance = this;
 
245
 
 
246
    KGlobal::dirs()->addResourceDir("data", KStandardDirs::installPath("data") + QString("kipi"));
 
247
}
 
248
 
 
249
PluginLoader::PluginLoader(KXmlGuiWindow* const parent)
 
250
    : d(new Private)
 
251
{
 
252
    Q_ASSERT((s_instance == 0) && (!s_loaded));
 
253
    s_instance = this;
 
254
 
 
255
    KGlobal::dirs()->addResourceDir("data", KStandardDirs::installPath("data") + QString("kipi"));
 
256
 
 
257
    if (!parent)
 
258
    {
 
259
        kWarning() << "KDE XML application instance is null...";
 
260
    }
 
261
 
 
262
    d->parent = parent;
 
263
}
 
264
 
 
265
void PluginLoader::setInterface(Interface* const interface)
 
266
{
 
267
    d->interface = interface;
 
268
    setParent(interface);
 
269
}
 
270
 
 
271
void PluginLoader::setIgnoredPluginsList(const QStringList& ignores)
 
272
{
 
273
    d->ignoredPlugins = ignores;
 
274
}
 
275
 
 
276
void PluginLoader::setDisabledPluginActions(const QStringList& disabledActions)
 
277
{
 
278
    d->disabledActions = disabledActions;
 
279
}
 
280
 
 
281
QStringList PluginLoader::disabledPluginActions() const
 
282
{
 
283
    return d->disabledActions;
 
284
}
 
285
 
 
286
void PluginLoader::init()
 
287
{
 
288
    Q_ASSERT((s_instance != 0) && (!s_loaded));
 
289
 
 
290
    if (!d->interface)
 
291
    {
 
292
        kWarning() << "KIPI host interface instance is null. No plugin will be loaded...";
 
293
        return;
 
294
    }
 
295
 
 
296
    s_loaded                    = true;
 
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"));
223
300
 
227
304
        QString name            = service->name();
228
305
        QString library         = service->library();
229
306
        QStringList reqFeatures = service->property(QString::fromLatin1("X-KIPI-ReqFeatures")).toStringList();
 
307
        int binVersion          = service->property(QString::fromLatin1("X-KIPI-BinaryVersion")).toInt();
230
308
 
231
309
        if (library.isEmpty() || name.isEmpty())
232
310
        {
234
312
            continue;
235
313
        }
236
314
 
237
 
        if (ignores.contains(name))
 
315
        if (d->ignoredPlugins.contains(name))
238
316
        {
239
317
            kDebug(51001) << "Plugin " << name << " is in the ignore list from host application";
240
318
            continue;
241
319
        }
242
320
 
 
321
        if (binVersion != kipi_binary_version)
 
322
        {
 
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.";
 
327
            continue;
 
328
        }
 
329
 
243
330
        bool appHasAllReqFeatures = true;
244
331
 
245
332
        for (QStringList::const_iterator featureIt = reqFeatures.constBegin();
261
348
            continue;
262
349
        }
263
350
 
264
 
        Info* info = new Info(service, load);
 
351
        Info* const info = new Info(d->parent, service, load);
265
352
        d->pluginList.append(info);
266
353
    }
267
354
}
268
355
 
269
356
PluginLoader::~PluginLoader()
270
357
{
271
 
    qDeleteAll(d->pluginList);
272
358
    delete d;
273
359
}
274
360
 
302
388
    return new ConfigWidget(parent);
303
389
}
304
390
 
305
 
// ---------------------------------------------------------------------
306
 
 
307
 
class PluginCheckBox : public QListWidgetItem
308
 
{
309
 
public:
310
 
 
311
 
    PluginCheckBox(PluginLoader::Info* const info, QListWidget* const parent)
312
 
        : QListWidgetItem(parent, QListWidgetItem::UserType),
313
 
          info(info)
314
 
    {
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);
319
 
    }
320
 
 
321
 
    PluginLoader::Info* info;
322
 
};
323
 
 
324
 
// ---------------------------------------------------------------------
325
 
 
326
 
class ConfigWidget::ConfigWidgetPrivate
327
 
{
328
 
public:
329
 
 
330
 
    ConfigWidgetPrivate()
331
 
    {
332
 
    };
333
 
 
334
 
    QList<PluginCheckBox*> boxes;
335
 
};
336
 
 
337
 
ConfigWidget::ConfigWidget(QWidget* const parent)
338
 
    : QListWidget(parent),
339
 
      d(new ConfigWidgetPrivate)
340
 
{
341
 
    setAutoFillBackground(false);
342
 
    setSortingEnabled(true);
343
 
    viewport()->setAutoFillBackground(false);
344
 
 
345
 
    foreach(PluginLoader::Info* info, PluginLoader::instance()->pluginList())
346
 
    {
347
 
        PluginCheckBox* cb = new PluginCheckBox(info, this);
348
 
        d->boxes.append(cb);
349
 
    }
350
 
}
351
 
 
352
 
ConfigWidget::~ConfigWidget()
353
 
{
354
 
    delete d;
355
 
}
356
 
 
357
 
void ConfigWidget::apply()
358
 
{
359
 
    KSharedConfigPtr config = KGlobal::config();
360
 
    KConfigGroup group      = config->group(QString::fromLatin1("KIPI/EnabledPlugin"));
361
 
 
362
 
    for (QList<PluginCheckBox*>::Iterator it = d->boxes.begin(); it != d->boxes.end(); ++it)
363
 
    {
364
 
        bool orig = (*it)->info->shouldLoad();
365
 
        bool load = ((*it)->checkState() == Qt::Checked);
366
 
 
367
 
        if (orig != load)
368
 
        {
369
 
            group.writeEntry((*it)->info->name(), load);
370
 
            (*it)->info->setShouldLoad(load);
371
 
 
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.
374
 
            /*
375
 
            if (load)
376
 
            {
377
 
                (*it)->info->reload();
378
 
            }
379
 
            else if ((*it)->info->plugin())   // Do not emit if we had trouble loading plugin.
380
 
            {
381
 
                emit PluginLoader::instance()->unplug((*it)->info);
382
 
            }
383
 
            */
384
 
            (*it)->info->reload();
385
 
        }
386
 
    }
387
 
 
388
 
    emit PluginLoader::instance()->replug();
389
 
}
390
 
 
391
 
void ConfigWidget::slotCheckAll()
392
 
{
393
 
    for (int i = 0; i < count(); ++i)
394
 
    {
395
 
        item(i)->setCheckState(Qt::Checked);
396
 
    }
397
 
}
398
 
 
399
 
void ConfigWidget::slotClear()
400
 
{
401
 
    for (int i = 0; i < count(); ++i)
402
 
    {
403
 
        item(i)->setCheckState(Qt::Unchecked);
404
 
    }
 
391
QString PluginLoader::kipiPluginsVersion() const
 
392
{
 
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");
 
397
 
 
398
    if (!map.isEmpty())
 
399
    {
 
400
        QString val = map["Version"];
 
401
 
 
402
        if (!val.isEmpty())
 
403
            ver = val;
 
404
    }
 
405
 
 
406
    return ver;
405
407
}
406
408
 
407
409
} // namespace KIPI