KCoreAddons

kpluginfactory.h
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 #ifndef KPLUGINFACTORY_H
11 #define KPLUGINFACTORY_H
12 
13 #include "kcoreaddons_export.h"
14 
15 #include <QObject>
16 #include <QStringList>
17 #include <QVariant>
18 #include <kexportplugin.h> // for source compat
19 
20 #include <memory>
21 #include <type_traits>
22 
23 class QWidget;
24 
25 class KPluginFactoryPrivate;
26 namespace KParts
27 {
28 class Part;
29 }
30 class KPluginMetaData;
31 
32 #define KPluginFactory_iid "org.kde.KPluginFactory"
33 
34 /**
35  * @relates KPluginFactory
36  *
37  * Declare a KPluginFactory subclass of the given base factory.
38  *
39  * @param name the name of the KPluginFactory derived class.
40  *
41  * @param baseFactory the name of the base class (base factory) to use.
42  * This must be a KPluginFactory subclass with
43  * a default constructor.
44  *
45  * Additional parameters may be additional Qt properties, such as
46  * Q_PLUGIN_METADATA.
47  *
48  * @note The base factory must be a subclass of KPluginFactory.
49  * While this macro is largely an implementation detail, factories
50  * that have a different create() interface can be declared through
51  * this macro. Normal use through other K_PLUGIN_FACTORY macros
52  * uses KPluginFactory as a base.
53  *
54  * @note This macro is usually only an implementation detail
55  * for K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY or
56  * K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_JSON .
57  *
58  * @since 5.80
59  *
60  */
61 #define K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, ...) \
62  class name : public baseFactory \
63  { \
64  Q_OBJECT \
65  Q_INTERFACES(KPluginFactory) \
66  __VA_ARGS__ \
67  public: \
68  explicit name(); \
69  ~name(); \
70  };
71 
72 #define K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_JSON(name, baseFactory, json) \
73  K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, Q_PLUGIN_METADATA(IID KPluginFactory_iid FILE json))
74 
75 #define K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \
76  K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name, baseFactory, Q_PLUGIN_METADATA(IID KPluginFactory_iid))
77 
78 #define K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \
79  name::name(){pluginRegistrations} name::~name() \
80  { \
81  }
82 
83 #define K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations) \
84  K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, baseFactory) \
85  K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations)
86 
87 #define K_PLUGIN_FACTORY_WITH_BASEFACTORY_JSON(name, baseFactory, jsonFile, pluginRegistrations) \
88  K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_JSON(name, baseFactory, jsonFile) \
89  K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, baseFactory, pluginRegistrations)
90 
91 /**
92  * @relates KPluginFactory
93  *
94  * Create a KPluginFactory subclass and export it as the root plugin object.
95  *
96  * @param name the name of the KPluginFactory derived class.
97  *
98  * @param pluginRegistrations code to be inserted into the constructor of the
99  * class. Usually a series of registerPlugin() calls.
100  *
101  * @note K_PLUGIN_FACTORY declares the subclass including a Q_OBJECT macro.
102  * So you need to make sure to have Qt's moc run also for the source file
103  * where you use the macro. E.g. in projects using CMake and it's automoc feature,
104  * as usual you need to have a line
105  * @code
106  * #include <myplugin.moc>
107  * @endcode
108  * in the same source file when that one has the name "myplugin.cpp".
109  *
110  * Example:
111  * @code
112  * #include <KPluginFactory>
113  * #include <plugininterface.h>
114  *
115  * class MyPlugin : public PluginInterface
116  * {
117  * public:
118  * MyPlugin(QObject *parent, const QVariantList &args)
119  * : PluginInterface(parent)
120  * {}
121  * };
122  *
123  * K_PLUGIN_FACTORY(MyPluginFactory,
124  * registerPlugin<MyPlugin>();
125  * )
126  *
127  * #include <myplugin.moc>
128  * @endcode
129  *
130  * If you want to compile a .json file into the plugin, use K_PLUGIN_FACTORY_WITH_JSON.
131  *
132  * @see K_PLUGIN_FACTORY_WITH_JSON
133  * @see K_PLUGIN_FACTORY_DECLARATION
134  * @see K_PLUGIN_FACTORY_DEFINITION
135  */
136 #define K_PLUGIN_FACTORY(name, pluginRegistrations) K_PLUGIN_FACTORY_WITH_BASEFACTORY(name, KPluginFactory, pluginRegistrations)
137 
138 /**
139  * @relates KPluginFactory
140  *
141  * Create a KPluginFactory subclass and export it as the root plugin object with
142  * JSON metadata.
143  *
144  * This macro does the same as K_PLUGIN_FACTORY, but adds a JSON file as plugin
145  * metadata. See Q_PLUGIN_METADATA() for more information.
146  *
147  * @param name the name of the KPluginFactory derived class.
148  *
149  * @param pluginRegistrations code to be inserted into the constructor of the
150  * class. Usually a series of registerPlugin() calls.
151  *
152  * @param jsonFile name of the JSON file to be compiled into the plugin as metadata
153  *
154  * @note K_PLUGIN_FACTORY_WITH_JSON declares the subclass including a Q_OBJECT macro.
155  * So you need to make sure to have Qt's moc run also for the source file
156  * where you use the macro. E.g. in projects using CMake and its automoc feature,
157  * as usual you need to have a line
158  * @code
159  * #include <myplugin.moc>
160  * @endcode
161  * in the same source file when that one has the name "myplugin.cpp".
162  *
163  * Example (KF >= 5.77):
164  * @code
165  * #include <KPluginFactory>
166  * #include <plugininterface.h>
167  *
168  * class MyPlugin : public PluginInterface
169  * {
170  * public:
171  * MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
172  * : PluginInterface(parent)
173  * {}
174  * };
175  *
176  * K_PLUGIN_FACTORY_WITH_JSON(MyPluginFactory,
177  * "metadata.json",
178  * registerPlugin<MyPlugin>();
179  * )
180  *
181  * #include <myplugin.moc>
182  * @endcode
183  *
184  * Example (backward-compatible with KF < 5.77):
185  * @code
186  * #include <KPluginFactory>
187  * #include <plugininterface.h>
188  *
189  * class MyPlugin : public PluginInterface
190  * {
191  * public:
192  * MyPlugin(QObject *parent, const QVariantList &args)
193  * : PluginInterface(parent)
194  * {}
195  * };
196  *
197  * K_PLUGIN_FACTORY_WITH_JSON(MyPluginFactory,
198  * "metadata.json",
199  * registerPlugin<MyPlugin>();
200  * )
201  *
202  * #include <myplugin.moc>
203  * @endcode
204  *
205  * @see K_PLUGIN_FACTORY
206  * @see K_PLUGIN_FACTORY_DECLARATION
207  * @see K_PLUGIN_FACTORY_DEFINITION
208  *
209  * @since 5.0
210  */
211 #define K_PLUGIN_FACTORY_WITH_JSON(name, jsonFile, pluginRegistrations) \
212  K_PLUGIN_FACTORY_WITH_BASEFACTORY_JSON(name, KPluginFactory, jsonFile, pluginRegistrations)
213 
214 /**
215  * @relates KPluginFactory
216  *
217  * Create a KPluginFactory subclass and export it as the root plugin object with
218  * JSON metadata.
219  *
220  * This macro does the same as K_PLUGIN_FACTORY_WITH_JSON, but you only have to pass the class name and the json file.
221  * The factory name and registerPlugin call are deduced from the class name.
222  *
223  * @code
224  * #include <myplugin.moc>
225  * @endcode
226  * in the same source file when that one has the name "myplugin.cpp".
227  *
228  * Example (KF >= 5.77):
229  * @code
230  * #include <KPluginFactory>
231  * #include <plugininterface.h>
232  *
233  * class MyPlugin : public PluginInterface
234  * {
235  * public:
236  * MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
237  * : PluginInterface(parent)
238  * {}
239  * };
240  *
241  * K_PLUGIN_CLASS_WITH_JSON(MyPlugin, "metadata.json")
242  *
243  * #include <myplugin.moc>
244  * @endcode
245  *
246  * Example (backward-compatible with KF < 5.77):
247  * @code
248  * #include <KPluginFactory>
249  * #include <plugininterface.h>
250  *
251  * class MyPlugin : public PluginInterface
252  * {
253  * public:
254  * MyPlugin(QObject *parent, const QVariantList &args)
255  * : PluginInterface(parent)
256  * {}
257  * };
258  *
259  * K_PLUGIN_CLASS_WITH_JSON(MyPlugin, "metadata.json")
260  *
261  * #include <myplugin.moc>
262  * @endcode
263  *
264  * @see K_PLUGIN_FACTORY_WITH_JSON
265  *
266  * @since 5.44
267  */
268 #define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile) K_PLUGIN_FACTORY_WITH_JSON(classname##Factory, jsonFile, registerPlugin<classname>();)
269 
270 /**
271  * @relates KPluginFactory
272  *
273  * K_PLUGIN_FACTORY_DECLARATION declares the KPluginFactory subclass. This macro
274  * can be used in a header file.
275  *
276  * @param name the name of the KPluginFactory derived class.
277  *
278  * @see K_PLUGIN_FACTORY
279  * @see K_PLUGIN_FACTORY_DEFINITION
280  */
281 #define K_PLUGIN_FACTORY_DECLARATION(name) K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY(name, KPluginFactory)
282 
283 /**
284  * @relates KPluginFactory
285  * K_PLUGIN_FACTORY_DEFINITION defines the KPluginFactory subclass. This macro
286  * can <b>not</b> be used in a header file.
287  *
288  * @param name the name of the KPluginFactory derived class.
289  *
290  * @param pluginRegistrations code to be inserted into the constructor of the
291  * class. Usually a series of registerPlugin() calls.
292  *
293  * @see K_PLUGIN_FACTORY
294  * @see K_PLUGIN_FACTORY_DECLARATION
295  */
296 #define K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name, KPluginFactory, pluginRegistrations)
297 
298 /**
299  * @class KPluginFactory kpluginfactory.h <KPluginFactory>
300  *
301  * KPluginFactory provides a convenient way to provide factory-style plugins.
302  * Qt plugins provide a singleton object, but a common pattern is for plugins
303  * to generate as many objects of a particular type as the application requires.
304  * By using KPluginFactory, you can avoid implementing the factory pattern
305  * yourself.
306  *
307  * KPluginFactory also allows plugins to provide multiple different object
308  * types, indexed by keywords.
309  *
310  * The objects created by KPluginFactory must inherit QObject, and must have a
311  * standard constructor pattern:
312  * @li if the object is a KPart::Part, it must be of the form
313  * @code
314  * T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
315  * @endcode
316  * or, since KF 5.77,
317  * @code
318  * T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
319  * @endcode
320  * @li if it is a QWidget, it must be of the form
321  * @code
322  * T(QWidget *parent, const QVariantList &args)
323  * @endcode
324  * or, since KF 5.77,
325  * @code
326  * T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
327  * @endcode
328  * @li otherwise it must be of the form
329  * @code
330  * T(QObject *parent, const QVariantList &args)
331  * @endcode
332  * or, since KF 5.77,
333  * @code
334  * T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
335  * @endcode
336  *
337  * You should typically use either K_PLUGIN_FACTORY() or
338  * K_PLUGIN_FACTORY_WITH_JSON() in your plugin code to create the factory. The
339  * typical pattern is
340  *
341  * @code
342  * #include <KPluginFactory>
343  * #include <plugininterface.h>
344  *
345  * class MyPlugin : public PluginInterface
346  * {
347  * public:
348  * MyPlugin(QObject *parent, const QVariantList &args)
349  * : PluginInterface(parent)
350  * {}
351  * };
352  *
353  * K_PLUGIN_FACTORY(MyPluginFactory,
354  * registerPlugin<MyPlugin>();
355  * )
356  * #include <myplugin.moc>
357  * @endcode
358  *
359  * If you want to write a custom KPluginFactory not using the standard macro(s)
360  * you can reimplement the
361  * create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
362  * method.
363  *
364  * Example:
365  * @code
366  * class SomeScriptLanguageFactory : public KPluginFactory
367  * {
368  * Q_OBJECT
369  * public:
370  * SomeScriptLanguageFactory()
371  * {}
372  *
373  * protected:
374  * virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
375  * {
376  * const QString identifier = QLatin1String(iface) + QLatin1Char('_') + keyword;
377  * // load scripting language module from the information in identifier
378  * // and return it:
379  * return object;
380  * }
381  * };
382  * @endcode
383  *
384  * To use such a custom KPluginFactory, use the K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY
385  * and K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY macros, passing in the
386  * name of the custom subclass as @p baseFactory .
387  *
388  * If you want to load a library use KPluginLoader.
389  * The application that wants to instantiate plugin classes can do the following:
390  * @code
391  * KPluginFactory *factory = KPluginLoader("libraryname").factory();
392  * if (factory) {
393  * PluginInterface *p1 = factory->create<PluginInterface>(parent);
394  * OtherInterface *p2 = factory->create<OtherInterface>(parent);
395  * NextInterface *p3 = factory->create<NextInterface>("keyword1", parent);
396  * NextInterface *p3 = factory->create<NextInterface>("keyword2", parent);
397  * }
398  * @endcode
399  *
400  * @author Matthias Kretz <[email protected]>
401  * @author Bernhard Loos <[email protected]>
402  */
403 class KCOREADDONS_EXPORT KPluginFactory : public QObject
404 {
405  Q_OBJECT
406  Q_DECLARE_PRIVATE(KPluginFactory)
407 public:
408  /**
409  * This constructor creates a factory for a plugin.
410  */
411  explicit KPluginFactory();
412 
413  /**
414  * This destroys the PluginFactory.
415  */
416  ~KPluginFactory() override;
417 
418  /**
419  * Use this method to create an object. It will try to create an object which inherits
420  * @p T. If it has multiple choices it's not defined which object will be returned, so be careful
421  * to request a unique interface or use keywords.
422  *
423  * @tparam T the interface for which an object should be created. The object will inherit @p T.
424  * @param parent the parent of the object. If @p parent is a widget type, it will also passed
425  * to the parentWidget argument of the CreateInstanceFunction for the object.
426  * @param args additional arguments which will be passed to the object.
427  * @returns pointer to the created object is returned, or @c nullptr if an error occurred.
428  */
429  template<typename T>
430  T *create(QObject *parent = nullptr, const QVariantList &args = QVariantList());
431 
432  /**
433  * Use this method to create an object. It will try to create an object which inherits
434  * @p T and was registered with @p keyword.
435  *
436  * @tparam T the interface for which an object should be created. The object will inherit @p T.
437  * @param keyword the keyword of the object.
438  * @param parent the parent of the object. If @p parent is a widget type, it will also passed
439  * to the parentWidget argument of the CreateInstanceFunction for the object.
440  * @param args additional arguments which will be passed to the object.
441  * @returns pointer to the created object is returned, or @c nullptr if an error occurred.
442  */
443  template<typename T>
444  T *create(const QString &keyword, QObject *parent = nullptr, const QVariantList &args = QVariantList());
445 
446  /**
447  * Use this method to create an object. It will try to create an object which inherits
448  * @p T and was registered with @p keyword.
449  * This overload has an additional @p parentWidget argument, which is used by some plugins (e.g. Parts).
450 
451  * @tparam T the interface for which an object should be created. The object will inherit @p T.
452  * @param parentWidget an additional parent widget.
453  * @param parent the parent of the object. If @p parent is a widget type, it will also passed
454  * to the parentWidget argument of the CreateInstanceFunction for the object.
455  * @param keyword the keyword of the object.
456  * @param args additional arguments which will be passed to the object.
457  * @returns pointer to the created object is returned, or @c nullptr if an error occurred.
458  */
459  template<typename T>
460  T *create(QWidget *parentWidget, QObject *parent, const QString &keyword = QString(), const QVariantList &args = QVariantList());
461 
462 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(4, 0)
463  /**
464  * @deprecated since 4.0 use create<T>(QObject *parent, const QVariantList &args)
465  */
466  template<typename T>
467  KCOREADDONS_DEPRECATED_VERSION(4, 0, "Use KPluginFactory::create<T>(QObject *parent, const QVariantList &args)")
468  T *create(QObject *parent, const QStringList &args)
469  {
470  return create<T>(parent, stringListToVariantList(args));
471  }
472 
473  /**
474  * @deprecated since 4.0 use create<T>(QObject *parent, const QVariantList &args)
475  */
476  KCOREADDONS_DEPRECATED_VERSION(4, 0, "Use KPluginFactory::create<T>(QObject *parent, const QVariantList &args)")
477  QObject *create(QObject *parent = nullptr, const char *classname = "QObject", const QStringList &args = QStringList())
478  {
479  return create(classname, nullptr, parent, stringListToVariantList(args), QString());
480  }
481 #endif
482 
483  /**
484  * @returns the metadata of the plugin
485  *
486  * @since 5.77
487  */
488  KPluginMetaData metaData() const;
489 
490  /**
491  * Set the metadata about the plugin this factory generates.
492  *
493  * @param metaData the metadata about the plugin
494  *
495  * @since 5.77
496  */
497  void setMetaData(const KPluginMetaData &metaData);
498 
499  /**
500  * @internal
501  * Converts a QStringList to a QVariantList
502  */
503  static QVariantList stringListToVariantList(const QStringList &list);
504 
505  /**
506  * @internal
507  * Converts a QVariantList of strings to a QStringList
508  */
509  static QStringList variantListToStringList(const QVariantList &list);
510 
511 Q_SIGNALS:
512  void objectCreated(QObject *object);
513 
514 protected:
515  /**
516  * Function pointer type to a function that instantiates a plugin.
517  */
518  typedef QObject *(*CreateInstanceFunction)(QWidget *, QObject *, const QVariantList &);
519 
520  /**
521  * This is used to detect the arguments need for the constructor of metadata-less plugin classes.
522  * You can inherit it, if you want to add new classes and still keep support for the old ones.
523  */
524  template<class impl>
526  /// property to control the availability of the registerPlugin overload taking default values
527  static constexpr bool enabled = std::is_constructible<impl, QWidget *, QObject *, const QVariantList &>::value
528  || std::is_constructible<impl, QWidget *, const QVariantList &>::value || std::is_constructible<impl, QObject *, const QVariantList &>::value;
529 
530  CreateInstanceFunction createInstanceFunction(KParts::Part *)
531  {
532  return &createPartInstance<impl>;
533  }
534  CreateInstanceFunction createInstanceFunction(QWidget *)
535  {
536  return &createInstance<impl, QWidget>;
537  }
538  CreateInstanceFunction createInstanceFunction(...)
539  {
540  return &createInstance<impl, QObject>;
541  }
542  };
543 
544  /**
545  * Function pointer type to a function that instantiates a plugin, also taking a plugin metadata argument.
546  * @since 5.77
547  */
548  using CreateInstanceWithMetaDataFunction = QObject *(*)(QWidget *, QObject *, const KPluginMetaData &, const QVariantList &);
549 
550  /**
551  * This is used to detect the arguments need for the constructor of metadata-taking plugin classes.
552  * You can inherit it, if you want to add new classes and still keep support for the old ones.
553  */
554  template<class impl>
556  /// property to control the availability of the registerPlugin overload taking default values
557  static constexpr bool enabled = std::is_constructible<impl, QWidget *, QObject *, const KPluginMetaData &, const QVariantList &>::value
558  || std::is_constructible<impl, QWidget *, const KPluginMetaData &, const QVariantList &>::value
559  || std::is_constructible<impl, QObject *, const KPluginMetaData &, const QVariantList &>::value;
560 
561  CreateInstanceWithMetaDataFunction createInstanceFunction(KParts::Part *)
562  {
563  return &createPartWithMetaDataInstance<impl>;
564  }
565  CreateInstanceWithMetaDataFunction createInstanceFunction(QWidget *)
566  {
567  return &createWithMetaDataInstance<impl, QWidget>;
568  }
569  CreateInstanceWithMetaDataFunction createInstanceFunction(...)
570  {
571  return &createWithMetaDataInstance<impl, QObject>;
572  }
573  };
574 
575  explicit KPluginFactory(KPluginFactoryPrivate &dd);
576 
577  // Use std::enable_if_t once C++14 can be relied on
578  template<bool B, class T = void>
579  using enable_if_t = typename std::enable_if<B, T>::type;
580 
581  /**
582  * Registers a metadata-less plugin with the factory. Call this function from the constructor of the
583  * KPluginFactory subclass to make the create function able to instantiate the plugin when asked
584  * for an interface the plugin implements.
585  *
586  * You can register as many plugin classes as you want as long as either the plugin interface or
587  * the @p keyword makes it unique. E.g. it is possible to register a KCModule and a
588  * KParts::Part without having to specify keywords since their interfaces differ.
589  *
590  * @tparam T the name of the plugin class
591  *
592  * @param keyword an optional keyword as unique identifier for the plugin. This allows you to
593  * put more than one plugin with the same interface into the same library using the same
594  * factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file.
595  *
596  * @param instanceFunction A function pointer to a function that creates an instance of the
597  * plugin.
598  */
599  template<class T>
600  void registerPlugin(const QString &keyword, CreateInstanceFunction instanceFunction)
601  {
602  registerPlugin(keyword, &T::staticMetaObject, instanceFunction);
603  }
604 
605  /**
606  * Overload for registerPlugin<T>(const QString &keyword, CreateInstanceFunction instanceFunction)
607  *
608  * Uses a default instance creation function depending on the type of interface. If the
609  * interface inherits from
610  * @li @c KParts::Part the function will call
611  * @code
612  * new T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
613  * @endcode
614  * @li @c QWidget the function will call
615  * @code
616  * new T(QWidget *parent, const QVariantList &args)
617  * @endcode
618  * @li else the function will call
619  * @code
620  * new T(QObject *parent, const QVariantList &args)
621  * @endcode
622  *
623  * If those constructor methods are not callable this overload is not available.
624  */
625  template<class T, enable_if_t<InheritanceChecker<T>::enabled, int> = 0>
626  void registerPlugin(const QString &keyword = QString())
627  {
628  CreateInstanceFunction instanceFunction = InheritanceChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
629  registerPlugin<T>(keyword, instanceFunction);
630  }
631 
632  /**
633  * Registers a metadata-taking plugin with the factory. Call this function from the constructor of the
634  * KPluginFactory subclass to make the create function able to instantiate the plugin when asked
635  * for an interface the plugin implements.
636  *
637  * You can register as many plugin classes as you want as long as either the plugin interface or
638  * the @p keyword makes it unique. E.g. it is possible to register a KCModule and a
639  * KParts::Part without having to specify keywords since their interfaces differ.
640  *
641  * @tparam T the name of the plugin class
642  *
643  * @param keyword An optional keyword as unique identifier for the plugin. This allows you to
644  * put more than one plugin with the same interface into the same library using the same
645  * factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file.
646  *
647  * @param instanceFunction A function pointer to a function that creates an instance of the
648  * plugin.
649  */
650  template<class T>
651  void registerPlugin(const QString &keyword, CreateInstanceWithMetaDataFunction instanceFunction)
652  {
653  registerPlugin(keyword, &T::staticMetaObject, instanceFunction);
654  }
655 
656  /**
657  * Overload for registerPlugin<T>(const QString &keyword, CreateInstanceWithMetaDataFunction instanceFunction)
658  *
659  * Uses a default instance creation function depending on the type of interface. If the
660  * interface inherits from
661  * @li @c KParts::Part the function will call
662  * @code
663  * new T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
664  * @endcode
665  * @li @c QWidget the function will call
666  * @code
667  * new T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
668  * @endcode
669  * @li else the function will call
670  * @code
671  * new T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
672  * @endcode
673  *
674  * If those constructor methods are not callable this overload is not available.
675  */
676  template<class T, enable_if_t<InheritanceWithMetaDataChecker<T>::enabled, int> = 0>
677  void registerPlugin(const QString &keyword = QString())
678  {
679  CreateInstanceWithMetaDataFunction instanceFunction = InheritanceWithMetaDataChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
680  registerPlugin<T>(keyword, instanceFunction);
681  }
682 
683  std::unique_ptr<KPluginFactoryPrivate> const d_ptr;
684 
685 #if KCOREADDONS_BUILD_DEPRECATED_SINCE(4, 0)
686  /**
687  * @deprecated since 4.0 use create<T>(QObject *parent, const QVariantList &args)
688  */
689  KCOREADDONS_DEPRECATED_VERSION(4, 0, "Use KPluginFactory::create<T>(QObject *parent, const QVariantList &args)")
690  virtual QObject *createObject(QObject *parent, const char *className, const QStringList &args);
691 
692  /**
693  * @deprecated since 4.0 use create<T>(QWidget *parentWidget, QObject *parent, const QString &keyword, const QVariantList &args)
694  */
695  KCOREADDONS_DEPRECATED_VERSION(4,
696  0,
697  "Use KPluginFactory::create<T>(QWidget *parentWidget, QObject *parent, const QString &keyword, const QVariantList &args)")
698  virtual KParts::Part *createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args);
699 #endif
700 
701  /**
702  * This function is called when the factory asked to create an Object.
703  *
704  * You may reimplement it to provide a very flexible factory. This is especially useful to
705  * provide generic factories for plugins implemented using a scripting language.
706  *
707  * @param iface the staticMetaObject::className() string identifying the plugin interface that
708  * was requested. E.g. for KCModule plugins this string will be "KCModule".
709  * @param parentWidget only used if the requested plugin is a KPart.
710  * @param parent the parent object for the plugin object.
711  * @param args a plugin specific list of arbitrary arguments.
712  * @param keyword a string that uniquely identifies the plugin. If a KService is used this
713  * keyword is read from the X-KDE-PluginKeyword entry in the .desktop file.
714  */
715  virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword);
716 
717  template<class impl, class ParentType>
718  static QObject *createInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args)
719  {
720  Q_UNUSED(parentWidget)
721  ParentType *p = nullptr;
722  if (parent) {
723  p = qobject_cast<ParentType *>(parent);
724  Q_ASSERT(p);
725  }
726  return new impl(p, args);
727  }
728 
729  template<class impl>
730  static QObject *createPartInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args)
731  {
732  return new impl(parentWidget, parent, args);
733  }
734 
735  template<class impl, class ParentType>
736  static QObject *createWithMetaDataInstance(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
737  {
738  Q_UNUSED(parentWidget)
739  ParentType *p = nullptr;
740  if (parent) {
741  p = qobject_cast<ParentType *>(parent);
742  Q_ASSERT(p);
743  }
744  return new impl(p, metaData, args);
745  }
746 
747  template<class impl>
748  static QObject *createPartWithMetaDataInstance(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
749  {
750  return new impl(parentWidget, parent, metaData, args);
751  }
752 
753 private:
754  void registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction);
755  void registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction);
756 };
757 
758 // Deprecation wrapper macro added only for 5.70, while backward typedef added in 4.0
759 #if KCOREADDONS_ENABLE_DEPRECATED_SINCE(5, 70)
760 /**
761  * Backward compatibility typedef for KPluginFactory
762  * @deprecated since 4.0, use KPluginFactory
763  */
765 #endif
766 
767 template<typename T>
768 inline T *KPluginFactory::create(QObject *parent, const QVariantList &args)
769 {
770  QObject *o =
771  create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent) : nullptr, parent, args, QString());
772 
773  T *t = qobject_cast<T *>(o);
774  if (!t) {
775  delete o;
776  }
777  return t;
778 }
779 
780 template<typename T>
781 inline T *KPluginFactory::create(const QString &keyword, QObject *parent, const QVariantList &args)
782 {
783  QObject *o =
784  create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent) : nullptr, parent, args, keyword);
785 
786  T *t = qobject_cast<T *>(o);
787  if (!t) {
788  delete o;
789  }
790  return t;
791 }
792 
793 template<typename T>
794 inline T *KPluginFactory::create(QWidget *parentWidget, QObject *parent, const QString &keyword, const QVariantList &args)
795 {
796  QObject *o = create(T::staticMetaObject.className(), parentWidget, parent, args, keyword);
797 
798  T *t = qobject_cast<T *>(o);
799  if (!t) {
800  delete o;
801  }
802  return t;
803 }
804 
805 Q_DECLARE_INTERFACE(KPluginFactory, KPluginFactory_iid)
806 
807 #endif // KPLUGINFACTORY_H
void registerPlugin(const QString &keyword, CreateInstanceWithMetaDataFunction instanceFunction)
Registers a metadata-taking plugin with the factory.
T * create(QObject *parent=nullptr, const QVariantList &args=QVariantList())
Use this method to create an object.
This is used to detect the arguments need for the constructor of metadata-less plugin classes...
This is used to detect the arguments need for the constructor of metadata-taking plugin classes...
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=QString())
Overload for registerPlugin<T>(const QString &keyword, CreateInstanceFunction instanceFunction) ...
void registerPlugin(const QString &keyword, CreateInstanceFunction instanceFunction)
Registers a metadata-less plugin with the factory.
This class allows easily accessing some standardized values from the JSON metadata that can be embedd...
bool isWidgetType() const const
KPluginFactory provides a convenient way to provide factory-style plugins.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Mar 3 2021 00:00:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.