1/*
2 This file is part of the KDE project
3
4 SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
5 SPDX-FileCopyrightText: 2007 Bernhard Loos <nhuh.put@web.de>
6 SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "kpluginfactory.h"
12#include "kpluginfactory_p.h"
13
14#include "kcoreaddons_debug.h"
15#include <QPluginLoader>
16#include <algorithm>
17
18KPluginFactory::KPluginFactory()
19 : d(new KPluginFactoryPrivate)
20{
21}
22
23KPluginFactory::~KPluginFactory() = default;
24
25KPluginFactory::Result<KPluginFactory> KPluginFactory::loadFactory(const KPluginMetaData &data)
26{
27 Result<KPluginFactory> result;
28 QObject *obj = nullptr;
29 if (data.isStaticPlugin()) {
30 obj = data.staticPlugin().instance();
31 } else {
32 if (data.fileName().isEmpty()) {
33 result.errorString = tr(s: "Could not find plugin %1").arg(a: data.requestedFileName());
34 result.errorText = QStringLiteral("Could not find plugin %1").arg(a: data.requestedFileName());
35 result.errorReason = INVALID_PLUGIN;
36 qCWarning(KCOREADDONS_DEBUG) << result.errorText;
37 return result;
38 }
39 QPluginLoader loader(data.fileName());
40 obj = loader.instance();
41 if (!obj) {
42 result.errorString = tr(s: "Could not load plugin from %1: %2").arg(args: data.fileName(), args: loader.errorString());
43 result.errorText = QStringLiteral("Could not load plugin from %1: %2").arg(args: data.fileName(), args: loader.errorString());
44 result.errorReason = INVALID_PLUGIN;
45 qCWarning(KCOREADDONS_DEBUG) << result.errorText;
46 return result;
47 }
48 }
49
50 KPluginFactory *factory = qobject_cast<KPluginFactory *>(object: obj);
51
52 if (factory == nullptr) {
53 result.errorString = tr(s: "The library %1 does not offer a KPluginFactory.").arg(a: data.fileName());
54 result.errorReason = INVALID_FACTORY;
55 qCWarning(KCOREADDONS_DEBUG) << "Expected a KPluginFactory, got a" << obj->metaObject()->className();
56 delete obj;
57 return result;
58 }
59
60 factory->setMetaData(data);
61 result.plugin = factory;
62 return result;
63}
64
65KPluginMetaData KPluginFactory::metaData() const
66{
67 return d->metaData;
68}
69
70void KPluginFactory::setMetaData(const KPluginMetaData &metaData)
71{
72 d->metaData = metaData;
73}
74
75void KPluginFactory::registerPlugin(const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction)
76{
77 Q_ASSERT(metaObject);
78 const QMetaObject *superClass = metaObject->superClass();
79 Q_ASSERT(superClass);
80
81 for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
82 for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
83 if (superClass == otherSuper) {
84 qCWarning(KCOREADDONS_DEBUG).nospace() << "Two plugins with the same interface (" << superClass->className()
85 << ") were registered in the KPluginFactory " << this->metaObject()->className() << ". "
86 << "This might be due to a missing Q_OBJECT macro in one of the registered classes";
87 }
88 }
89 }
90 // check hierarchy of newly newly registered plugin against all registered classes
91 for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
92 superClass = plugin.first->superClass();
93 for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
94 if (superClass == otherSuper) {
95 qCWarning(KCOREADDONS_DEBUG).nospace() << "Two plugins with the same interface (" << superClass->className()
96 << ") were registered in the KPluginFactory " << this->metaObject()->className() << ". "
97 << "This might be due to a missing Q_OBJECT macro in one of the registered classes";
98 }
99 }
100 }
101 d->createInstanceWithMetaDataHash.push_back(x: {metaObject, instanceFunction});
102}
103
104void KPluginFactory::logFailedInstantiationMessage(KPluginMetaData data)
105{
106 qCWarning(KCOREADDONS_DEBUG) << "KPluginFactory could not load the plugin" << data.fileName();
107}
108void KPluginFactory::logFailedInstantiationMessage(const char *className, KPluginMetaData data)
109{
110 qCWarning(KCOREADDONS_DEBUG) << "KPluginFactory could not create a" << className << "instance from" << data.fileName();
111}
112
113QObject *KPluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
114{
115 for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : d->createInstanceWithMetaDataHash) {
116 for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
117 if (0 == qstrcmp(str1: iface, str2: current->className())) {
118 return plugin.second(parentWidget, parent, d->metaData, args);
119 }
120 }
121 }
122
123 return nullptr;
124}
125
126#include "moc_kpluginfactory.cpp"
127

source code of kcoreaddons/src/lib/plugin/kpluginfactory.cpp