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

KDE's Doxygen guidelines are available online.