KCoreAddons

kpluginfactory.cpp
1 /*
2  This file is part of the KDE project
3 
4  SPDX-FileCopyrightText: 2007 Matthias Kretz <[email protected]>
5  SPDX-FileCopyrightText: 2007 Bernhard Loos <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "kpluginfactory.h"
11 #include "kpluginfactory_p.h"
12 
13 #include "kcoreaddons_debug.h"
14 #include <QObjectCleanupHandler>
15 
16 Q_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup)
17 
19  : d_ptr(new KPluginFactoryPrivate)
20 {
21  factorycleanup()->add(this);
22 }
23 
24 KPluginFactory::KPluginFactory(KPluginFactoryPrivate &d)
25  : d_ptr(&d)
26 {
27  factorycleanup()->add(this);
28 }
29 
31 
33 {
34  Q_D(const KPluginFactory);
35 
36  return d->metaData;
37 }
38 
40 {
41  Q_D(KPluginFactory);
42  d->metaData = metaData;
43 }
44 
45 void KPluginFactory::registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction)
46 {
47  Q_D(KPluginFactory);
48 
49  Q_ASSERT(metaObject);
50 
51  // we allow different interfaces to be registered without keyword
52  if (!keyword.isEmpty()) {
53  if (d->createInstanceHash.contains(keyword)) {
54  qCWarning(KCOREADDONS_DEBUG) << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!";
55  }
56  d->createInstanceHash.insert(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction));
57  } else {
58  const QList<KPluginFactoryPrivate::Plugin> clashes(d->createInstanceHash.values(keyword));
59  const QMetaObject *superClass = metaObject->superClass();
60  if (superClass) {
61  for (const KPluginFactoryPrivate::Plugin &plugin : clashes) {
62  for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
63  if (superClass == otherSuper) {
64  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className()
65  << ") were registered. Use keywords to identify the plugins.";
66  }
67  }
68  }
69  }
70  for (const KPluginFactoryPrivate::Plugin &plugin : clashes) {
71  superClass = plugin.first->superClass();
72  if (superClass) {
73  for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
74  if (superClass == otherSuper) {
75  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className()
76  << ") were registered. Use keywords to identify the plugins.";
77  }
78  }
79  }
80  }
81  d->createInstanceHash.insert(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction));
82  }
83 }
84 
85 void KPluginFactory::registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction)
86 {
87  Q_D(KPluginFactory);
88 
89  Q_ASSERT(metaObject);
90 
91  // we allow different interfaces to be registered without keyword
92  if (!keyword.isEmpty()) {
93  if (d->createInstanceWithMetaDataHash.contains(keyword)) {
94  qCWarning(KCOREADDONS_DEBUG) << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!";
95  }
96  d->createInstanceWithMetaDataHash.insert(keyword, {metaObject, instanceFunction});
97  } else {
98  const QList<KPluginFactoryPrivate::PluginWithMetadata> clashes(d->createInstanceWithMetaDataHash.values(keyword));
99  const QMetaObject *superClass = metaObject->superClass();
100  if (superClass) {
101  for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : clashes) {
102  for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
103  if (superClass == otherSuper) {
104  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className()
105  << ") were registered. Use keywords to identify the plugins.";
106  }
107  }
108  }
109  }
110  for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : clashes) {
111  superClass = plugin.first->superClass();
112  if (superClass) {
113  for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; otherSuper = otherSuper->superClass()) {
114  if (superClass == otherSuper) {
115  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className()
116  << ") were registered. Use keywords to identify the plugins.";
117  }
118  }
119  }
120  }
121  d->createInstanceWithMetaDataHash.insert(keyword, {metaObject, instanceFunction});
122  }
123 }
124 
125 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
126 QObject *KPluginFactory::createObject(QObject *parent, const char *className, const QStringList &args)
127 {
128  Q_UNUSED(parent);
129  Q_UNUSED(className);
130  Q_UNUSED(args);
131  return nullptr;
132 }
133 #endif
134 
135 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
136 KParts::Part *KPluginFactory::createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args)
137 {
138  Q_UNUSED(parent);
139  Q_UNUSED(parentWidget);
140  Q_UNUSED(classname);
141  Q_UNUSED(args);
142  return nullptr;
143 }
144 #endif
145 
146 QObject *KPluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
147 {
148  Q_D(KPluginFactory);
149 
150  QObject *obj = nullptr;
151 
152 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
153  if (keyword.isEmpty()) {
154  const QStringList argsStringList = variantListToStringList(args);
155 
156  if ((obj = reinterpret_cast<QObject *>(createPartObject(parentWidget, parent, iface, argsStringList)))) {
157  Q_EMIT objectCreated(obj);
158  return obj;
159  }
160 
161  if ((obj = createObject(parent, iface, argsStringList))) {
162  Q_EMIT objectCreated(obj);
163  return obj;
164  }
165  }
166 #endif
167 
168  const QList<KPluginFactoryPrivate::Plugin> candidates(d->createInstanceHash.values(keyword));
169  // for !keyword.isEmpty() candidates.count() is 0 or 1
170 
171  for (const KPluginFactoryPrivate::Plugin &plugin : candidates) {
172  for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
173  if (0 == qstrcmp(iface, current->className())) {
174  if (obj) {
175  qCWarning(KCOREADDONS_DEBUG) << "ambiguous interface requested from a DSO containing more than one plugin";
176  }
177  obj = plugin.second(parentWidget, parent, args);
178  break;
179  }
180  }
181  }
182 
183  if (!obj) {
184  const QList<KPluginFactoryPrivate::PluginWithMetadata> candidates = (d->createInstanceWithMetaDataHash.values(keyword));
185  // for !keyword.isEmpty() candidates.count() is 0 or 1
186 
187  for (const KPluginFactoryPrivate::PluginWithMetadata &plugin : candidates) {
188  for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
189  if (0 == qstrcmp(iface, current->className())) {
190  if (obj) {
191  qCWarning(KCOREADDONS_DEBUG) << "ambiguous interface requested from a DSO containing more than one plugin";
192  }
193  obj = plugin.second(parentWidget, parent, d->metaData, args);
194  break;
195  }
196  }
197  }
198  }
199 
200  if (obj) {
201  Q_EMIT objectCreated(obj);
202  }
203  return obj;
204 }
205 
207 {
208  QStringList stringlist;
209  for (const QVariant &var : list) {
210  stringlist << var.toString();
211  }
212  return stringlist;
213 }
214 
216 {
217  QVariantList variantlist;
218  for (const QString &str : list) {
219  variantlist << QVariant(str);
220  }
221  return variantlist;
222 }
static QVariantList stringListToVariantList(const QStringList &list)
void setMetaData(const KPluginMetaData &metaData)
Set the metadata about the plugin this factory generates.
T * create(QObject *parent=nullptr, const QVariantList &args=QVariantList())
Use this method to create an object.
const QMetaObject * superClass() const const
QObject *(* CreateInstanceFunction)(QWidget *, QObject *, const QVariantList &)
Function pointer type to a function that instantiates a plugin.
virtual const QMetaObject * metaObject() const const
~KPluginFactory() override
This destroys the PluginFactory.
KPluginFactory()
This constructor creates a factory for a plugin.
QString & insert(int position, QChar ch)
static QStringList variantListToStringList(const QVariantList &list)
bool isEmpty() const const
T & first()
KPluginMetaData metaData() const
QObject *(*)(QWidget *, QObject *, const KPluginMetaData &, const QVariantList &) CreateInstanceWithMetaDataFunction
Function pointer type to a function that instantiates a plugin, also taking a plugin metadata argumen...
void registerPlugin(const QString &keyword, CreateInstanceFunction instanceFunction)
Registers a metadata-less plugin with the factory.
virtual KParts::Part * createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args)
void insert(int i, const T &value)
This class allows easily accessing some standardized values from the JSON metadata that can be embedd...
QObject * parent() const const
virtual QObject * createObject(QObject *parent, const char *className, const QStringList &args)
KPluginFactory provides a convenient way to provide factory-style plugins.
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Apr 11 2021 23:01:47 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.