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 <QObjectCleanupHandler>
14 #include "kcoreaddons_debug.h"
15 
16 Q_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup)
17 
18 extern int kLibraryDebugArea();
19 
21  : d_ptr(new KPluginFactoryPrivate)
22 {
23  Q_D(KPluginFactory);
24  d->q_ptr = this;
25 
26  factorycleanup()->add(this);
27 }
28 
29 KPluginFactory::KPluginFactory(KPluginFactoryPrivate &d)
30  : d_ptr(&d)
31 {
32  factorycleanup()->add(this);
33 }
34 
36 {
37  delete d_ptr;
38 }
39 
40 void KPluginFactory::registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction)
41 {
42  Q_D(KPluginFactory);
43 
44  Q_ASSERT(metaObject);
45 
46  // we allow different interfaces to be registered without keyword
47  if (!keyword.isEmpty()) {
48  if (d->createInstanceHash.contains(keyword)) {
49  qCWarning(KCOREADDONS_DEBUG) << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!";
50  }
51  d->createInstanceHash.insert(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction));
52  } else {
53  const QList<KPluginFactoryPrivate::Plugin> clashes(d->createInstanceHash.values(keyword));
54  const QMetaObject *superClass = metaObject->superClass();
55  if (superClass) {
56  for (const KPluginFactoryPrivate::Plugin &plugin : clashes) {
57  for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper;
58  otherSuper = otherSuper->superClass()) {
59  if (superClass == otherSuper) {
60  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins.";
61  }
62  }
63  }
64  }
65  for (const KPluginFactoryPrivate::Plugin &plugin : clashes) {
66  superClass = plugin.first->superClass();
67  if (superClass) {
68  for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper;
69  otherSuper = otherSuper->superClass()) {
70  if (superClass == otherSuper) {
71  qCWarning(KCOREADDONS_DEBUG) << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins.";
72  }
73  }
74  }
75  }
76  d->createInstanceHash.insert(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction));
77  }
78 }
79 
80 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
81 QObject *KPluginFactory::createObject(QObject *parent, const char *className, const QStringList &args)
82 {
83  Q_UNUSED(parent);
84  Q_UNUSED(className);
85  Q_UNUSED(args);
86  return nullptr;
87 }
88 #endif
89 
90 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
91 KParts::Part *KPluginFactory::createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args)
92 {
93  Q_UNUSED(parent);
94  Q_UNUSED(parentWidget);
95  Q_UNUSED(classname);
96  Q_UNUSED(args);
97  return nullptr;
98 }
99 #endif
100 
101 QObject *KPluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
102 {
103  Q_D(KPluginFactory);
104 
105  QObject *obj = nullptr;
106 
107 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
108  if (keyword.isEmpty()) {
109 
110  const QStringList argsStringList = variantListToStringList(args);
111 
112  if ((obj = reinterpret_cast<QObject *>(createPartObject(parentWidget, parent, iface, argsStringList)))) {
113  Q_EMIT objectCreated(obj);
114  return obj;
115  }
116 
117  if ((obj = createObject(parent, iface, argsStringList))) {
118  Q_EMIT objectCreated(obj);
119  return obj;
120  }
121  }
122 #endif
123 
124  const QList<KPluginFactoryPrivate::Plugin> candidates(d->createInstanceHash.values(keyword));
125  // for !keyword.isEmpty() candidates.count() is 0 or 1
126 
127  for (const KPluginFactoryPrivate::Plugin &plugin : candidates) {
128  for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
129  if (0 == qstrcmp(iface, current->className())) {
130  if (obj) {
131  qCWarning(KCOREADDONS_DEBUG) << "ambiguous interface requested from a DSO containing more than one plugin";
132  }
133  obj = plugin.second(parentWidget, parent, args);
134  break;
135  }
136  }
137  }
138 
139  if (obj) {
140  emit objectCreated(obj);
141  }
142  return obj;
143 }
144 
146 {
147  QStringList stringlist;
148  for (const QVariant &var : list) {
149  stringlist << var.toString();
150  }
151  return stringlist;
152 }
153 
155 {
156  QVariantList variantlist;
157  for (const QString &str : list) {
158  variantlist << QVariant(str);
159  }
160  return variantlist;
161 }
162 
static QVariantList stringListToVariantList(const QStringList &list)
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()
virtual KParts::Part * createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args)
void registerPlugin(const QString &keyword=QString(), CreateInstanceFunction instanceFunction=InheritanceChecker< T >().createInstanceFunction(static_cast< T * >(nullptr)))
Registers a plugin with the factory.
void insert(int i, const T &value)
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-2020 The KDE developers.
Generated on Sat May 30 2020 23:10:51 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.