File indexing completed on 2024-05-19 03:56:22

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
0005     SPDX-FileCopyrightText: 2007 Bernhard Loos <nhuh.put@web.de>
0006     SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "kpluginfactory.h"
0012 #include "kpluginfactory_p.h"
0013 
0014 #include "kcoreaddons_debug.h"
0015 #include <QPluginLoader>
0016 #include <algorithm>
0017 
0018 KPluginFactory::KPluginFactory()
0019     : d(new KPluginFactoryPrivate)
0020 {
0021 }
0022 
0023 KPluginFactory::~KPluginFactory() = default;
0024 
0025 KPluginFactory::Result<KPluginFactory> KPluginFactory::loadFactory(const KPluginMetaData &data)
0026 {
0027     Result<KPluginFactory> result;
0028     QObject *obj = nullptr;
0029     if (data.isStaticPlugin()) {
0030         obj = data.staticPlugin().instance();
0031     } else {
0032         if (data.fileName().isEmpty()) {
0033             result.errorString = tr("Could not find plugin %1").arg(data.requestedFileName());
0034             result.errorText = QStringLiteral("Could not find plugin %1").arg(data.requestedFileName());
0035             result.errorReason = INVALID_PLUGIN;
0036             qCWarning(KCOREADDONS_DEBUG) << result.errorText;
0037             return result;
0038         }
0039         QPluginLoader loader(data.fileName());
0040         obj = loader.instance();
0041         if (!obj) {
0042             result.errorString = tr("Could not load plugin from %1: %2").arg(data.fileName(), loader.errorString());
0043             result.errorText = QStringLiteral("Could not load plugin from %1: %2").arg(data.fileName(), loader.errorString());
0044             result.errorReason = INVALID_PLUGIN;
0045             qCWarning(KCOREADDONS_DEBUG) << result.errorText;
0046             return result;
0047         }
0048     }
0049 
0050     KPluginFactory *factory = qobject_cast<KPluginFactory *>(obj);
0051 
0052     if (factory == nullptr) {
0053         result.errorString = tr("The library %1 does not offer a KPluginFactory.").arg(data.fileName());
0054         result.errorReason = INVALID_FACTORY;
0055         qCWarning(KCOREADDONS_DEBUG) << "Expected a KPluginFactory, got a" << obj->metaObject()->className();
0056         delete obj;
0057         return result;
0058     }
0059 
0060     factory->setMetaData(data);
0061     result.plugin = factory;
0062     return result;
0063 }
0064 
0065 KPluginMetaData KPluginFactory::metaData() const
0066 {
0067     return d->metaData;
0068 }
0069 
0070 void KPluginFactory::setMetaData(const KPluginMetaData &metaData)
0071 {
0072     d->metaData = metaData;
0073 }
0074 
0075 void KPluginFactory::registerPlugin(const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction)
0076 {
0077     Q_ASSERT(metaObject);
0078     const QMetaObject *superClass = metaObject->superClass();
0079     Q_ASSERT(superClass);
0080 
0081     for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
0082         for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
0083             if (superClass == otherSuper) {
0084                 qCWarning(KCOREADDONS_DEBUG).nospace() << "Two plugins with the same interface (" << superClass->className()
0085                                                        << ") were registered in the KPluginFactory " << this->metaObject()->className() << ". "
0086                                                        << "This might be due to a missing Q_OBJECT macro in one of the registered classes";
0087             }
0088         }
0089     }
0090     // check hierarchy of newly newly registered plugin against all registered classes
0091     for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
0092         superClass = plugin.first->superClass();
0093         for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
0094             if (superClass == otherSuper) {
0095                 qCWarning(KCOREADDONS_DEBUG).nospace() << "Two plugins with the same interface (" << superClass->className()
0096                                                        << ") were registered in the KPluginFactory " << this->metaObject()->className() << ". "
0097                                                        << "This might be due to a missing Q_OBJECT macro in one of the registered classes";
0098             }
0099         }
0100     }
0101     d->createInstanceWithMetaDataHash.push_back({metaObject, instanceFunction});
0102 }
0103 
0104 void KPluginFactory::logFailedInstantiationMessage(KPluginMetaData data)
0105 {
0106     qCWarning(KCOREADDONS_DEBUG) << "KPluginFactory could not load the plugin" << data.fileName();
0107 }
0108 void KPluginFactory::logFailedInstantiationMessage(const char *className, KPluginMetaData data)
0109 {
0110     qCWarning(KCOREADDONS_DEBUG) << "KPluginFactory could not create a" << className << "instance from" << data.fileName();
0111 }
0112 
0113 QObject *KPluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
0114 {
0115     for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
0116         for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
0117             if (0 == qstrcmp(iface, current->className())) {
0118                 return plugin.second(parentWidget, parent, d->metaData, args);
0119             }
0120         }
0121     }
0122 
0123     return nullptr;
0124 }
0125 
0126 #include "moc_kpluginfactory.cpp"