diff --git a/core/libs/dplugins/setup/dpluginloader.cpp b/core/libs/dplugins/setup/dpluginloader.cpp index df98f761ab..138f1a2ad0 100644 --- a/core/libs/dplugins/setup/dpluginloader.cpp +++ b/core/libs/dplugins/setup/dpluginloader.cpp @@ -1,316 +1,316 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 * Description : manager to load external plugins at run-time * * Copyright (C) 2018-2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dpluginloader_p.h" // Qt includes #include // Local includes #include "digikam_config.h" #include "digikam_debug.h" #include "dplugingeneric.h" #include "dplugineditor.h" namespace Digikam { class Q_DECL_HIDDEN DPluginLoaderCreator { public: DPluginLoader object; }; Q_GLOBAL_STATIC(DPluginLoaderCreator, creator) // ----------------------------------------------------- DPluginLoader::DPluginLoader() : QObject(), d(new Private) { } DPluginLoader::~DPluginLoader() { delete d; } DPluginLoader* DPluginLoader::instance() { return &creator->object; } void DPluginLoader::init() { d->loadPlugins(); } void DPluginLoader::cleanUp() { foreach (QPluginLoader* const loader, d->allLoaders) { loader->unload(); } d->allLoaders.clear(); } QString DPluginLoader::configGroupName() const { return QLatin1String("EnabledDPlugins"); } QList DPluginLoader::allPlugins() const { return d->allPlugins; } QList DPluginLoader::pluginsActions(DPluginAction::ActionType type, QObject* const parent) const { - QMap list; + QList list; foreach (DPlugin* const p, allPlugins()) { DPluginGeneric* const gene = dynamic_cast(p); if (gene) { foreach (DPluginAction* const ac, gene->actions(parent)) { if (ac && (ac->actionType() == type)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } } } } if (!list.isEmpty()) - return list.values(); + return list; foreach (DPlugin* const p, allPlugins()) { DPluginEditor* const edit = dynamic_cast(p); if (edit) { foreach (DPluginAction* const ac, edit->actions(parent)) { if (ac && (ac->actionType() == type)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } } } } - return list.values(); + return list; } QList DPluginLoader::pluginsActions(DPluginAction::ActionCategory cat, QObject* const parent) const { - QMap list; + QList list; foreach (DPlugin* const p, allPlugins()) { DPluginGeneric* const gene = dynamic_cast(p); if (gene) { foreach (DPluginAction* const ac, gene->actions(parent)) { if (ac && (ac->actionCategory() == cat)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } } } } if (!list.isEmpty()) - return list.values(); + return list; foreach (DPlugin* const p, allPlugins()) { DPluginEditor* const edit = dynamic_cast(p); if (edit) { foreach (DPluginAction* const ac, edit->actions(parent)) { if (ac && (ac->actionCategory() == cat)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } } } } - return list.values(); + return list; } QList DPluginLoader::pluginActions(const QString& pluginIID, QObject* const parent) const { - QMap list; + QList list; foreach (DPlugin* const p, allPlugins()) { DPluginGeneric* const gene = dynamic_cast(p); if (gene) { if (p->iid() == pluginIID) { foreach (DPluginAction* const ac, gene->actions(parent)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } break; } } } if (!list.isEmpty()) - return list.values(); + return list; foreach (DPlugin* const p, allPlugins()) { DPluginEditor* const edit = dynamic_cast(p); if (edit) { if (p->iid() == pluginIID) { foreach (DPluginAction* const ac, edit->actions(parent)) { - list.insert(d->cleanText(ac->text()), ac); + list << ac; } break; } } } - return list.values(); + return list; } DPluginAction* DPluginLoader::pluginAction(const QString& actionName, QObject* const parent) const { foreach (DPlugin* const p, allPlugins()) { DPluginGeneric* const gene = dynamic_cast(p); if (gene) { foreach (DPluginAction* const ac, gene->actions(parent)) { if (ac && (ac->objectName() == actionName)) { return ac; } } } DPluginEditor* const edit = dynamic_cast(p); if (edit) { foreach (DPluginAction* const ac, edit->actions(parent)) { if (ac && (ac->objectName() == actionName)) { return ac; } } } } qCCritical(DIGIKAM_GENERAL_LOG) << "DPluginAction named" << actionName << "not found in" << parent->objectName() << "(" << parent << ")"; return 0; } QString DPluginLoader::pluginXmlSections(DPluginAction::ActionCategory cat, QObject* const parent) const { QString xml; foreach (DPluginAction* const ac, pluginsActions(cat, parent)) { xml.append(ac->xmlSection()); } return xml; } void DPluginLoader::appendPluginToBlackList(const QString& filename) { d->blacklist << filename; } void DPluginLoader::appendPluginToWhiteList(const QString& filename) { d->whitelist << filename; } void DPluginLoader::registerGenericPlugins(QObject* const parent) { foreach (DPlugin* const plugin, d->allPlugins) { DPluginGeneric* const gene = dynamic_cast(plugin); if (gene) { gene->setup(parent); gene->setVisible(plugin->shouldLoaded()); qCDebug(DIGIKAM_GENERAL_LOG) << "Generic plugin named" << gene->name() << "registered to" << parent; } } } void DPluginLoader::registerEditorPlugins(QObject* const parent) { foreach (DPlugin* const plugin, d->allPlugins) { DPluginEditor* const edit = dynamic_cast(plugin); if (edit) { edit->setup(parent); edit->setVisible(plugin->shouldLoaded()); qCDebug(DIGIKAM_GENERAL_LOG) << "Editor plugin named" << edit->name() << "registered to" << parent; } } } } // namepace Digikam diff --git a/core/libs/dplugins/setup/dpluginloader_p.cpp b/core/libs/dplugins/setup/dpluginloader_p.cpp index 03269323cb..e6b92e91f4 100644 --- a/core/libs/dplugins/setup/dpluginloader_p.cpp +++ b/core/libs/dplugins/setup/dpluginloader_p.cpp @@ -1,210 +1,211 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 * Description : manager to load external plugins at run-time: private container * * Copyright (C) 2018-2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dpluginloader_p.h" // Qt includes #include #include #include #include #include #include #include // KDE includes #include #include // Local includes #include "digikam_debug.h" #include "digikam_version.h" namespace Digikam { +static bool pluginNameLessThan(DPlugin* const a, DPlugin* const b) +{ + return a->name() < b->name(); +} + DPluginLoader::Private::Private() : pluginsLoaded(false) { } DPluginLoader::Private::~Private() { } QFileInfoList DPluginLoader::Private::pluginEntriesList() const { QString path; // First we try to load in first the local plugin if DK_PLUG_PATH variable is declared. // Else, we will load plusing from the system using the standard Qt plugin path. QByteArray dkenv = qgetenv("DK_PLUGIN_PATH"); if (!dkenv.isEmpty()) { qCWarning(DIGIKAM_GENERAL_LOG) << "DK_PLUGIN_PATH env.variable detected. We will use it to load plugin..."; path = QString::fromUtf8(dkenv); } else { path = QLibraryInfo::location(QLibraryInfo::PluginsPath); path.append(QLatin1String("/digikam/")); } qCDebug(DIGIKAM_GENERAL_LOG) << "Parsing plugins from" << path; QDirIterator it(path, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); QFileInfoList allFiles; QStringList dupFiles; while (it.hasNext()) { QFileInfo info(it.next()); if (!dupFiles.contains(info.baseName())) { dupFiles << info.baseName(); allFiles << info; } } qCDebug(DIGIKAM_GENERAL_LOG) << "Plugins found:" << allFiles.count(); return allFiles; } /** Append object to the given plugins list. */ bool DPluginLoader::Private::appendPlugin(QObject* const obj, QPluginLoader* const loader) { DPlugin* const plugin = qobject_cast(obj); if (plugin) { Q_ASSERT(obj->metaObject()->superClass()); // all our plugins have a super class if (plugin->version() == QLatin1String(digikam_version_short)) { qCDebug(DIGIKAM_GENERAL_LOG) << "Plugin of type" << obj->metaObject()->superClass()->className() << "loaded from" << loader->fileName(); KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup group = config->group(DPluginLoader::instance()->configGroupName()); plugin->setShouldLoaded(group.readEntry(plugin->iid(), true)); plugin->setLibraryFileName(loader->fileName()); allPlugins << plugin; allLoaders << loader; return true; } } return false; } void DPluginLoader::Private::loadPlugins() { if (pluginsLoaded) { return; } QTime t; t.start(); qCDebug(DIGIKAM_GENERAL_LOG) << "Starting to load external tools."; Q_ASSERT(allPlugins.isEmpty() && allLoaders.isEmpty()); for (const QFileInfo& info : pluginEntriesList()) { if (!whitelist.isEmpty() && !whitelist.contains(info.baseName())) { qCDebug(DIGIKAM_GENERAL_LOG) << "Ignoring non-whitelisted plugin" << info.filePath(); continue; } if (blacklist.contains(info.baseName())) { qCDebug(DIGIKAM_GENERAL_LOG) << "Ignoring blacklisted plugin" << info.filePath(); continue; } // qCDebug(DIGIKAM_GENERAL_LOG) << info.baseName() << "-" << info.canonicalPath(); const QString path = info.canonicalFilePath(); QPluginLoader* const loader = new QPluginLoader(path, DPluginLoader::instance()); QObject* const obj = loader->instance(); if (obj) { bool isPlugin = appendPlugin(obj, loader); if (!isPlugin) { qCWarning(DIGIKAM_GENERAL_LOG) << "Ignoring the following plugin since it couldn't be loaded:" << path; qCDebug(DIGIKAM_GENERAL_LOG) << "External plugin failure:" << path << "is a plugin, but it does not implement the" << "right interface or it was compiled against" << "an old version of digiKam. Ignoring it."; delete loader; } } else { qCWarning(DIGIKAM_GENERAL_LOG) << "Ignoring to load the following file since it doesn't look like " "a valid digiKam external plugin:" << path << endl << "Reason:" << loader->errorString(); delete loader; } } if (allPlugins.isEmpty()) { qCWarning(DIGIKAM_GENERAL_LOG) << "No plugins loaded. Please check if the plugins were installed in the correct path," << "or if any errors occurred while loading plugins."; } + else + { + std::sort(allPlugins.begin(), allPlugins.end(), pluginNameLessThan); + } pluginsLoaded = true; qCDebug(DIGIKAM_GENERAL_LOG) << Q_FUNC_INFO << "Time elapsed:" << t.elapsed() << "ms"; } -QString DPluginLoader::Private::cleanText(const QString& text) const -{ - QString clean(text); - - clean.remove(QLatin1Char('&')); - return clean; -} - } // namepace Digikam diff --git a/core/libs/dplugins/setup/dpluginloader_p.h b/core/libs/dplugins/setup/dpluginloader_p.h index 26258eccef..b1df37ea11 100644 --- a/core/libs/dplugins/setup/dpluginloader_p.h +++ b/core/libs/dplugins/setup/dpluginloader_p.h @@ -1,67 +1,65 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 * Description : manager to load external plugins at run-time: private container * * Copyright (C) 2018-2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DPLUGIN_LOADER_P_H #define DIGIKAM_DPLUGIN_LOADER_P_H #include "dpluginloader.h" // Qt includes #include #include namespace Digikam { class Q_DECL_HIDDEN DPluginLoader::Private { public: explicit Private(); ~Private(); /** Try to find plugin files from Qt5 plugins install dir: */ QFileInfoList pluginEntriesList() const; /** Stage to load plugins in memory */ bool appendPlugin(QObject* const obj, QPluginLoader* const loader); void loadPlugins(); - QString cleanText(const QString& text) const; - public: bool pluginsLoaded; QList allPlugins; QList allLoaders; QStringList blacklist; QStringList whitelist; }; } // namepace Digikam #endif // DIGIKAM_DPLUGIN_LOADER_P_H