File indexing completed on 2024-04-28 04:41:57

0001 /* This file is part of the KDE project
0002    Copyright (C) 2010 by Adam Pigg (adam@piggz.co.uk)
0003    Copyright (C) 2015-2016 Jarosław Staniek <staniek@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2.1 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "KReportPluginManager.h"
0022 #include "KReportPluginManagerPrivate.h"
0023 #include "KReportPluginMetaData.h"
0024 #include "KReportUtils_p.h"
0025 
0026 #include "kreport_debug.h"
0027 #include <QAction>
0028 
0029 #include <KPluginMetaData>
0030 #include <KPluginLoader>
0031 
0032 //Include the static items
0033 #include "../items/label/KReportLabelPlugin.h"
0034 #include "../items/check/KReportCheckBoxPlugin.h"
0035 #include "../items/field/KReportFieldPlugin.h"
0036 #include "../items/image/KReportImagePlugin.h"
0037 #include "../items/text/KReportTextPlugin.h"
0038 
0039 KReportPluginManager::Private::Private(KReportPluginManager *qq)
0040     : q(qq), m_parent(new QObject), m_findPlugins(true)
0041 {
0042     Q_UNUSED(q)
0043 }
0044 
0045 // ---
0046 
0047 KReportPluginEntry::KReportPluginEntry()
0048     : m_loader(nullptr), m_interface(nullptr), m_metaData(nullptr)
0049 {
0050 }
0051 
0052 KReportPluginEntry::KReportPluginEntry(KReportPluginInterface *staticInterface)
0053     : m_loader(nullptr), m_interface(staticInterface), m_metaData(nullptr)
0054 {
0055 }
0056 
0057 KReportPluginEntry::~KReportPluginEntry()
0058 {
0059     delete m_metaData;
0060     delete m_interface;
0061 }
0062 
0063 KReportPluginInterface* KReportPluginEntry::plugin()
0064 {
0065     if (m_interface) {
0066         return m_interface;
0067     }
0068     if (!m_loader) {
0069         kreportWarning() << "No such plugin";
0070         return nullptr;
0071     }
0072     if (!m_loader->load()) {
0073         kreportWarning() << "Could not load plugin" << m_loader->fileName();
0074         return nullptr;
0075     }
0076     KPluginFactory *factory = qobject_cast<KPluginFactory*>(m_loader->instance());
0077     if (!factory) {
0078         kreportWarning() << "Could not create factory for plugin" << m_loader->fileName();
0079         return nullptr;
0080     }
0081     m_interface = factory->create<KReportPluginInterface>();
0082     if (!m_interface) {
0083         kreportWarning() << "Could not create instance of plugin" << m_loader->fileName();
0084         return nullptr;
0085     }
0086     m_interface->setMetaData(m_metaData);
0087     return m_interface;
0088 }
0089 
0090 void KReportPluginEntry::setBuiltIn(bool set)
0091 {
0092     m_metaData->setBuiltIn(set);
0093 }
0094 
0095 void KReportPluginEntry::setStatic(bool set)
0096 {
0097     m_metaData->setStatic(set);
0098 }
0099 
0100 const KReportPluginMetaData *KReportPluginEntry::metaData() const
0101 {
0102     return m_metaData;
0103 }
0104 
0105 void KReportPluginEntry::setMetaData(KReportPluginMetaData *metaData)
0106 {
0107     delete m_metaData;
0108     m_metaData = metaData;
0109     if (m_interface) {
0110         m_interface->setMetaData(m_metaData);
0111     }
0112 }
0113 
0114 void KReportPluginEntry::setMetaData(const QJsonObject &metaData)
0115 {
0116     setMetaData(new KReportPluginMetaData(metaData));
0117 }
0118 
0119 void KReportPluginEntry::setMetaData(QPluginLoader *loader)
0120 {
0121     m_loader = loader;
0122     setMetaData(new KReportPluginMetaData(*m_loader));
0123 }
0124 
0125 // ---
0126 
0127 KReportPluginManager::Private::~Private()
0128 {
0129     delete m_parent;
0130 }
0131 
0132 template<class PluginClass>
0133 void KReportPluginManager::Private::addBuiltInPlugin(const QJsonObject &json)
0134 {
0135     KReportPluginEntry *entry = new KReportPluginEntry(new PluginClass(m_parent));
0136     QJsonObject j = json.value(QLatin1String("MetaData")).toObject();
0137     //kreportDebug() << j;
0138     entry->setMetaData(j);
0139     entry->setBuiltIn(true);
0140     if (entry->metaData()->id().isEmpty()) {
0141         kreportWarning() << "Plugin" << entry->metaData()->name() << "has no identifier so won't be added to manager";
0142         delete entry;
0143         return;
0144     }
0145     entry->setStatic(true);
0146     m_plugins.insert(entry->metaData()->id(), entry);
0147     m_pluginsByLegacyName.insert(entry->metaData()->value(QLatin1String("X-KDE-PluginInfo-LegacyName"), entry->metaData()->id()), entry);
0148 }
0149 
0150 #define KREPORT_ADD_BUILTIN_PLUGIN(name) \
0151     addBuiltInPlugin<name>(KREPORT_STATIC_PLUGIN_METADATA(name))
0152 
0153 QMap<QString, KReportPluginEntry*>* KReportPluginManager::Private::plugins()
0154 {
0155     if (m_findPlugins) {
0156         findPlugins();
0157     }
0158     return &m_plugins;
0159 }
0160 
0161 QMap<QString, KReportPluginEntry*>* KReportPluginManager::Private::pluginsByLegacyName()
0162 {
0163     if (m_findPlugins) {
0164         findPlugins();
0165     }
0166     return &m_pluginsByLegacyName;
0167 }
0168 
0169 void KReportPluginManager::Private::findPlugins()
0170 {
0171     KREPORT_ADD_BUILTIN_PLUGIN(KReportLabelPlugin);
0172     KREPORT_ADD_BUILTIN_PLUGIN(KReportCheckBoxPlugin);
0173     KREPORT_ADD_BUILTIN_PLUGIN(KReportFieldPlugin);
0174     KREPORT_ADD_BUILTIN_PLUGIN(KReportImagePlugin);
0175     KREPORT_ADD_BUILTIN_PLUGIN(KReportTextPlugin);
0176 
0177     //kreportDebug() << "Load all plugins";
0178     const QVector<KPluginMetaData> metaDataList = KPluginLoader::findPlugins(QStringLiteral(KREPORT_BASE_NAME_LOWER));
0179     const QString expectedVersion = QString::fromLatin1("%1.%2")
0180             .arg(KREPORT_STABLE_VERSION_MAJOR).arg(KREPORT_STABLE_VERSION_MINOR);
0181     for (const KPluginMetaData &pluginMetaData : metaDataList) {
0182         auto *loader = new QPluginLoader(pluginMetaData.fileName());
0183         QScopedPointer<KReportPluginEntry> entry(new KReportPluginEntry);
0184         entry->setMetaData(loader);
0185         const KReportPluginMetaData *metaData = entry->metaData();
0186         if (metaData->version() != expectedVersion) {
0187             kreportWarning() << "KReport element plugin with ID" << metaData->id()
0188                              << "(" << metaData->fileName() << ")"
0189                              << "has version" << metaData->version() << "but expected version is"
0190                              << expectedVersion
0191                              << "-- skipping it";
0192             continue;
0193         }
0194         if (m_plugins.contains(metaData->id())) {
0195             kreportWarning() << "KReport element plugin with ID" << metaData->id()
0196                              << "already found at"
0197                              << m_plugins.value(metaData->id())->metaData()->fileName()
0198                              << "-- skipping another at" << metaData->fileName();
0199             continue;
0200         }
0201         if (!KReportPrivate::setupPrivateIconsResourceWithMessage(
0202             QLatin1String(KREPORT_BASE_NAME_LOWER),
0203             QString::fromLatin1("icons/%1_%2.rcc")
0204                 .arg(metaData->id()).arg(KReportPrivate::supportedIconTheme),
0205             QtWarningMsg,
0206             QString::fromLatin1(":/icons/%1").arg(metaData->id())))
0207         {
0208             continue;
0209         }
0210         addEntry(entry.take());
0211     }
0212     m_findPlugins = false;
0213 }
0214 
0215 void KReportPluginManager::Private::addEntry(KReportPluginEntry *entry)
0216 {
0217     m_plugins.insert(entry->metaData()->id(), entry);
0218     const QString legacyName(entry->metaData()->value(QLatin1String("X-KDE-PluginInfo-LegacyName"), entry->metaData()->id()));
0219     if (!legacyName.isEmpty() && entry->metaData()->id().startsWith(QLatin1String("org.kde.kreport"))) {
0220         m_pluginsByLegacyName.insert(legacyName, entry);
0221     }
0222 }
0223 
0224 // ---
0225 
0226 //! Class for access to KReportPluginManager constructor
0227 class KReportPluginManagerSingleton
0228 {
0229 public:
0230     KReportPluginManager object;
0231 };
0232 
0233 
0234 KReportPluginManager::KReportPluginManager()
0235     : d(new Private(this))
0236 {
0237     KReportPrivate::setupPrivateIconsResourceWithMessage(
0238         QLatin1String(KREPORT_BASE_NAME_LOWER),
0239         QString::fromLatin1("icons/kreport_%1.rcc").arg(KReportPrivate::supportedIconTheme), QtFatalMsg);
0240 }
0241 
0242 KReportPluginManager::~KReportPluginManager()
0243 {
0244     delete d;
0245 }
0246 
0247 Q_GLOBAL_STATIC(KReportPluginManagerSingleton, s_self)
0248 
0249 KReportPluginManager* KReportPluginManager::self()
0250 {
0251     return &s_self->object;
0252 }
0253 
0254 QStringList KReportPluginManager::pluginIds() const
0255 {
0256     return d->plugins()->keys();
0257 }
0258 
0259 const KReportPluginMetaData *KReportPluginManager::pluginMetaData(const QString& id) const
0260 {
0261     KReportPluginEntry *entry = d->plugins()->value(id);
0262     if (!entry) {
0263         return nullptr;
0264     }
0265     return entry->metaData();
0266 }
0267 
0268 KReportPluginInterface* KReportPluginManager::plugin(const QString& id) const
0269 {
0270     KReportPluginEntry *entry;
0271 
0272     entry = d->plugins()->value(id);
0273 
0274     if (!entry) {
0275         entry = d->pluginsByLegacyName()->value(id);
0276     }
0277 
0278     if (!entry) {
0279         return nullptr;
0280     }
0281     return entry->plugin();
0282 }
0283 
0284 QList<QAction*> KReportPluginManager::createActions(QObject *parent)
0285 {
0286     Q_ASSERT(parent);
0287     const QMap<QString, KReportPluginEntry*> *plugins = d->plugins();
0288     QList<QAction*> actList;
0289     foreach(KReportPluginEntry* plugin, *plugins) {
0290         const KReportPluginMetaData *metaData = plugin->metaData();
0291         if (metaData) {
0292             QAction *act = new QAction(QIcon::fromTheme(metaData->iconName()), metaData->name(), parent);
0293             act->setObjectName(metaData->id());
0294             act->setCheckable(true);
0295 
0296             //Store the order priority in the user data field
0297             act->setData(metaData->priority());
0298             actList << act;
0299         }
0300     }
0301     return actList;
0302 }