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-2023 Alexander Lohnau <alexander.lohnau@gmx.de>
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 <QVariant>
19
20#include <memory>
21#include <type_traits>
22
23class QWidget;
24class KPluginFactoryPrivate;
25
26namespace KParts
27{
28class Part;
29}
30
31#define KPluginFactory_iid "org.kde.KPluginFactory"
32
33// Internal macro that generated the KPluginFactory subclass
34#define __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, ...) \
35 class name : public KPluginFactory \
36 { \
37 Q_OBJECT \
38 Q_INTERFACES(KPluginFactory) \
39 Q_PLUGIN_METADATA(__VA_ARGS__) \
40 public: \
41 explicit name() \
42 { \
43 pluginRegistrations \
44 } \
45 ~name() { }; \
46 };
47
48/*!
49 * \macro K_PLUGIN_FACTORY
50 * \relates KPluginFactory
51 *
52 * Create a KPluginFactory subclass and export it as the root plugin object.
53 *
54 * \a name the name of the KPluginFactory derived class.
55 *
56 * \a pluginRegistrations code to be inserted into the constructor of the
57 * class. Usually a series of registerPlugin() calls.
58 *
59 * \note K_PLUGIN_FACTORY declares the subclass including a Q_OBJECT macro.
60 * So you need to make sure to have Qt's moc run also for the source file
61 * where you use the macro. E.g. in projects using CMake and it's automoc feature,
62 * as usual you need to have a line
63 * \code
64 * #include <myplugin.moc>
65 * \endcode
66 * in the same source file when that one has the name "myplugin.cpp".
67 *
68 * Example:
69 * \code
70 * #include <KPluginFactory>
71 * #include <plugininterface.h>
72 *
73 * class MyPlugin : public PluginInterface
74 * {
75 * public:
76 * MyPlugin(QObject *parent, const QVariantList &args)
77 * : PluginInterface(parent)
78 * {}
79 * };
80 *
81 * K_PLUGIN_FACTORY(MyPluginFactory, registerPlugin<MyPlugin>();)
82 *
83 * #include <myplugin.moc>
84 * \endcode
85 *
86 * If you want to compile a .json file into the plugin, use K_PLUGIN_FACTORY_WITH_JSON.
87 *
88 * \sa K_PLUGIN_FACTORY_WITH_JSON
89 */
90#define K_PLUGIN_FACTORY(name, pluginRegistrations) __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, IID KPluginFactory_iid)
91
92/*!
93 * \macro K_PLUGIN_FACTORY_WITH_JSON
94 * \relates KPluginFactory
95 *
96 * Create a KPluginFactory subclass and export it as the root plugin object with
97 * JSON metadata.
98 *
99 * This macro does the same as K_PLUGIN_FACTORY, but adds a JSON file as plugin
100 * metadata. See Q_PLUGIN_METADATA() for more information.
101 *
102 * \a name the name of the KPluginFactory derived class.
103 *
104 * \a pluginRegistrations code to be inserted into the constructor of the
105 * class. Usually a series of registerPlugin() calls.
106 *
107 * \a jsonFile name of the JSON file to be compiled into the plugin as metadata
108 *
109 * \note K_PLUGIN_FACTORY_WITH_JSON declares the subclass including a Q_OBJECT macro.
110 * So you need to make sure to have Qt's moc run also for the source file
111 * where you use the macro. E.g. in projects using CMake and its automoc feature,
112 * as usual you need to have a line
113 * \code
114 * #include <myplugin.moc>
115 * \endcode
116 * in the same source file when that one has the name "myplugin.cpp".
117 *
118 * Example:
119 * \code
120 * #include <KPluginFactory>
121 * #include <plugininterface.h>
122 *
123 * class MyPlugin : public PluginInterface
124 * {
125 * public:
126 * MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
127 * : PluginInterface(parent)
128 * {}
129 * };
130 *
131 * K_PLUGIN_FACTORY_WITH_JSON(MyPluginFactory,
132 * "metadata.json",
133 * registerPlugin<MyPlugin>();
134 * )
135 *
136 * #include <myplugin.moc>
137 * \endcode
138 *
139 * \sa K_PLUGIN_FACTORY
140 *
141 * \since 5.0
142 */
143#define K_PLUGIN_FACTORY_WITH_JSON(name, jsonFile, pluginRegistrations) \
144 __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, IID KPluginFactory_iid FILE jsonFile)
145
146/*!
147 * \macro K_PLUGIN_CLASS_WITH_JSON
148 * \relates KPluginFactory
149 *
150 * Create a KPluginFactory subclass and export it as the root plugin object with
151 * JSON metadata.
152 *
153 * This macro does the same as K_PLUGIN_FACTORY_WITH_JSON, but you only have to pass the class name and the json file.
154 * The factory name and registerPlugin call are deduced from the class name.
155 *
156 * \code
157 * #include <myplugin.moc>
158 * \endcode
159 * in the same source file when that one has the name "myplugin.cpp".
160 *
161 * Example:
162 * \code
163 * #include <KPluginFactory>
164 * #include <plugininterface.h>
165 *
166 * class MyPlugin : public PluginInterface
167 * {
168 * public:
169 * MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
170 * : PluginInterface(parent)
171 * {}
172 * };
173 *
174 * K_PLUGIN_CLASS_WITH_JSON(MyPlugin, "metadata.json")
175 *
176 * #include <myplugin.moc>
177 * \endcode
178 *
179 * \sa K_PLUGIN_FACTORY_WITH_JSON
180 *
181 * \since 5.44
182 */
183#ifdef KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME
184#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile) \
185 K_PLUGIN_FACTORY_WITH_JSON(KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME, jsonFile, registerPlugin<classname>();)
186#else
187#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile) K_PLUGIN_FACTORY_WITH_JSON(classname##Factory, jsonFile, registerPlugin<classname>();)
188#endif
189
190/*!
191 * \macro K_PLUGIN_CLASS
192 * \relates KPluginFactory
193 *
194 * Creates a KPluginFactory subclass and exports it as the root plugin object.
195 * Unlike K_PLUGIN_CLASS_WITH_JSON, this macro does not require json meta data.
196 *
197 * This macro does the same as K_PLUGIN_FACTORY, but you only have to pass the class name.
198 * The factory name and registerPlugin call are deduced from the class name.
199 * This is also useful if you want to use static plugins, see the kcoreaddons_add_plugin CMake method.
200 * \since 5.90
201 */
202#ifdef KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME
203#define K_PLUGIN_CLASS(classname) K_PLUGIN_FACTORY(KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME, registerPlugin<classname>();)
204#else
205#define K_PLUGIN_CLASS(classname) K_PLUGIN_FACTORY(classname##Factory, registerPlugin<classname>();)
206#endif
207
208/*!
209 * \class KPluginFactory
210 * \inmodule KCoreAddons
211 *
212 * \brief KPluginFactory provides a convenient way to provide factory-style plugins.
213 *
214 * Qt plugins provide a singleton object, but a common pattern is for plugins
215 * to generate as many objects of a particular type as the application requires.
216 * By using KPluginFactory, you can avoid implementing the factory pattern
217 * yourself.
218 *
219 * KPluginFactory also allows plugins to provide multiple different object
220 * types, indexed by keywords.
221 *
222 * The objects created by KPluginFactory must inherit QObject, and must have a
223 * standard constructor pattern:
224 * \list
225 * \li if the object is a KPart::Part, it must be of the form
226 * \code
227 * T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
228 * \endcode
229 * or
230 * \code
231 * T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
232 * \endcode
233 * \li if it is a QWidget, it must be of the form
234 * \code
235 * T(QWidget *parent, const QVariantList &args)
236 * \endcode
237 * or
238 * \code
239 * T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
240 * \endcode
241 * \li otherwise it must be of the form
242 * \code
243 * T(QObject *parent, const QVariantList &args)
244 * \endcode
245 * or
246 * \code
247 * T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
248 * \endcode
249 * \endlist
250 * You should typically use either K_PLUGIN_CLASS() or
251 * K_PLUGIN_CLASS_WITH_JSON() in your plugin code to generate a factory.
252 * The typical pattern is:
253 *
254 * \code
255 * #include <KPluginFactory>
256 * #include <plugininterface.h>
257 *
258 * class MyPlugin : public PluginInterface
259 * {
260 * public:
261 * MyPlugin(QObject *parent, const QVariantList &args)
262 * : PluginInterface(parent)
263 * {}
264 * };
265 *
266 * K_PLUGIN_CLASS(MyPlugin)
267 * #include <myplugin.moc>
268 * \endcode
269 *
270 * If you want to write a custom KPluginFactory not using the standard macro(s)
271 * you can reimplement the
272 * create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
273 * method.
274 *
275 * Example:
276 * \code
277 * class SomeScriptLanguageFactory : public KPluginFactory
278 * {
279 * Q_OBJECT
280 * public:
281 * SomeScriptLanguageFactory()
282 * {}
283 *
284 * protected:
285 * virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
286 * {
287 * // Create an identifier based on the iface and given pluginId
288 * const QString identifier = QLatin1String(iface) + QLatin1Char('_') + metaData().pluginId();
289 * // load scripting language module from the information in identifier and return it:
290 * return object;
291 * }
292 * };
293 * \endcode
294 *
295 * To load the KPluginFactory from an installed plugin you can use loadFactory() and for
296 * directly creating a plugin instance from it instantiatePlugin()
297 *
298 */
299class KCOREADDONS_EXPORT KPluginFactory : public QObject
300{
301 Q_OBJECT
302
303public:
304 /*!
305 *
306 */
307 explicit KPluginFactory();
308
309 ~KPluginFactory() override;
310
311 /*!
312 * \since 5.86
313 *
314 * \value NO_PLUGIN_ERROR No error
315 * \value INVALID_PLUGIN The plugin could not be loaded
316 * \value INVALID_FACTORY The factory object could not be loaded
317 * \value INVALID_KPLUGINFACTORY_INSTANTIATION The target object could not be instantiated
318 */
319 enum ResultErrorReason {
320 NO_PLUGIN_ERROR = 0,
321 INVALID_PLUGIN,
322 INVALID_FACTORY,
323 INVALID_KPLUGINFACTORY_INSTANTIATION,
324 };
325 /*!
326 * \class KPluginFactory::Result
327 * \inmodule KCoreAddons
328 * Holds the result of a plugin load operation, i.e. the loaded plugin on success or information about the error on failure
329 * \since 5.86
330 */
331 template<typename T>
332 class Result
333 {
334 public:
335 /*!
336 * \variable KPluginFactory::Result::plugin
337 * \brief The loaded object, or \c nullptr if loading fails
338 */
339 T *plugin = nullptr;
340
341 /*!
342 * \variable KPluginFactory::Result::errorString
343 * \brief The translated, user-visible error string
344 */
345 QString errorString;
346
347 /*!
348 * \variable KPluginFactory::Result::errorText
349 * \brief The untranslated error text
350 */
351 QString errorText;
352
353 /*!
354 * \variable KPluginFactory::Result::errorReason
355 * \brief The error reason
356 */
357 ResultErrorReason errorReason = NO_PLUGIN_ERROR;
358
359 /*!
360 *
361 */
362 explicit operator bool() const
363 {
364 return plugin != nullptr;
365 }
366 };
367
368 /*!
369 * Attempts to load the KPluginFactory from the given metadata.
370 *
371 * The errors will be logged using the kf.coreaddons debug category.
372 *
373 * \a data KPluginMetaData from which the plugin should be loaded
374 *
375 * Returns a result object which contains the plugin instance and potentially error information
376 *
377 * \since 5.86
378 */
379 static Result<KPluginFactory> loadFactory(const KPluginMetaData &data);
380
381 /*!
382 * Attempts to load the KPluginFactory and create a T instance from the given metadata.
383 *
384 * KCoreAddons will log error messages automatically, meaning you only need to implement your
385 * own logging in case you want to give it more context info or have a custom category.
386 *
387 * \code
388 * if (auto result = KPluginFactory::instantiatePlugin<MyClass>(metaData, parent, args)) {
389 * // The plugin is valid and result.plugin contains the object
390 * } else {
391 * // We can access the error related properties, but result.plugin is a nullptr
392 * qCWarning(MYCATEGORY) << result.errorString;
393 * }
394 * \endcode
395 *
396 * If there is no extra error handling needed the plugin can be directly accessed and checked if it is a nullptr
397 * \code
398 * if (auto plugin = KPluginFactory::instantiatePlugin<MyClass>(metaData, parent, args).plugin) {
399 * }
400 * \endcode
401 *
402 * \a data KPluginMetaData from which the plugin should be loaded
403 *
404 * \a args arguments which get passed to the plugin's constructor
405 *
406 * Returns a Result object which contains the plugin instance and potentially error information
407 *
408 * \since 5.86
409 */
410 template<typename T>
411 static Result<T> instantiatePlugin(const KPluginMetaData &data, QObject *parent = nullptr, const QVariantList &args = {})
412 {
413 Result<T> result;
414 KPluginFactory::Result<KPluginFactory> factoryResult = loadFactory(data);
415 if (!factoryResult.plugin) {
416 result.errorString = factoryResult.errorString;
417 result.errorText = factoryResult.errorText;
418 result.errorReason = factoryResult.errorReason;
419 return result;
420 }
421 T *instance = factoryResult.plugin->create<T>(parent, args);
422 if (!instance) {
423 const QLatin1String className(T::staticMetaObject.className());
424 result.errorString = tr(s: "KPluginFactory could not create a %1 instance from %2").arg(args: className, args: data.fileName());
425 result.errorText = QStringLiteral("KPluginFactory could not create a %1 instance from %2").arg(args: className, args: data.fileName());
426 result.errorReason = INVALID_KPLUGINFACTORY_INSTANTIATION;
427 logFailedInstantiationMessage(T::staticMetaObject.className(), data);
428 } else {
429 result.plugin = instance;
430 }
431 return result;
432 }
433
434 /*!
435 * Use this method to create an object.
436 *
437 * It will try to create an object which inherits T.
438 *
439 * If it has multiple choices it's not defined which object will be returned, so be careful
440 * to request a unique interface or use keywords.
441 *
442 * T the interface for which an object should be created. The object will inherit T.
443 *
444 * \a parent the parent of the object. If \a parent is a widget type, it will also passed
445 * to the parentWidget argument of the CreateInstanceFunction for the object.
446 *
447 * \a args additional arguments which will be passed to the object.
448 *
449 * Returns a pointer to the created object is returned, or \c nullptr if an error occurred.
450 */
451 template<typename T>
452 T *create(QObject *parent = nullptr, const QVariantList &args = {});
453
454 /*!
455 * Use this method to create an object. It will try to create an object which inherits T
456 * This overload has an additional \a parentWidget argument, which is used by some plugins (e.g. Parts).
457 *
458 * T the interface for which an object should be created. The object will inherit T.
459 *
460 * \a parentWidget an additional parent widget.
461 *
462 * \a parent the parent of the object. If \a parent is a widget type, it will also passed
463 * to the parentWidget argument of the CreateInstanceFunction for the object.
464 *
465 * \a args additional arguments which will be passed to the object. Since 5.93 this has a default arg.
466 * Returns a pointer to the created object is returned, or \c nullptr if an error occurred.
467 */
468 template<typename T>
469 T *create(QWidget *parentWidget, QObject *parent, const QVariantList &args = {});
470
471 /*!
472 * Returns the metadata of the plugin
473 *
474 * \since 5.77
475 */
476 KPluginMetaData metaData() const;
477
478 /*!
479 * Set the metadata about the plugin this factory generates.
480 *
481 * \a metaData the metadata about the plugin
482 *
483 * \since 5.77
484 */
485 void setMetaData(const KPluginMetaData &metaData);
486
487protected:
488 /*!
489 * Function pointer type to a function that instantiates a plugin
490 *
491 * For plugins that don't support a KPluginMetaData parameter it is discarded
492 * \since 5.77
493 */
494 using CreateInstanceWithMetaDataFunction = QObject *(*)(QWidget *, QObject *, const KPluginMetaData &, const QVariantList &);
495
496 /*
497 * This is used to detect the arguments need for the constructor of metadata-taking plugin classes.
498 * You can inherit it, if you want to add new classes and still keep support for the old ones.
499 */
500 template<class impl>
501 struct InheritanceWithMetaDataChecker {
502 /// property to control the availability of the registerPlugin overload taking default values
503 static constexpr bool enabled = std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData, QVariantList>::value // KParts
504 || std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData>::value
505 || std::is_constructible<impl, QWidget *, KPluginMetaData, QVariantList>::value // QWidgets
506 || std::is_constructible<impl, QWidget *, KPluginMetaData>::value
507 || std::is_constructible<impl, QObject *, KPluginMetaData, QVariantList>::value // Nomal QObjects
508 || std::is_constructible<impl, QObject *, KPluginMetaData>::value;
509
510 CreateInstanceWithMetaDataFunction createInstanceFunction(KParts::Part *)
511 {
512 return &createPartWithMetaDataInstance<impl>;
513 }
514 CreateInstanceWithMetaDataFunction createInstanceFunction(QWidget *)
515 {
516 return &createWithMetaDataInstance<impl, QWidget>;
517 }
518 CreateInstanceWithMetaDataFunction createInstanceFunction(...)
519 {
520 return &createWithMetaDataInstance<impl, QObject>;
521 }
522 };
523
524 /*
525 * This is used to detect the arguments need for the constructor of metadata-less plugin classes.
526 * You can inherit it, if you want to add new classes and still keep support for the old ones.
527 */
528 template<class impl>
529 struct InheritanceChecker {
530 /// property to control the availability of the registerPlugin overload taking default values
531 static constexpr bool _canConstruct = std::is_constructible<impl, QWidget *, QVariantList>::value // QWidget plugin
532 || std::is_constructible<impl, QWidget *>::value //
533 || std::is_constructible<impl, QObject *, QVariantList>::value // QObject plugins
534 || std::is_constructible<impl, QObject *>::value;
535 static constexpr bool enabled = _canConstruct && !InheritanceWithMetaDataChecker<impl>::enabled; // Avoid ambiguity in case of default arguments
536
537 CreateInstanceWithMetaDataFunction createInstanceFunction(QWidget *)
538 {
539 return &createInstance<impl, QWidget>;
540 }
541 CreateInstanceWithMetaDataFunction createInstanceFunction(...)
542 {
543 return &createInstance<impl, QObject>;
544 }
545 };
546
547 // Use std::enable_if_t once C++14 can be relied on
548 template<bool B, class T = void>
549 using enable_if_t = typename std::enable_if<B, T>::type;
550
551 /*!
552 * Uses a default instance creation function depending on the type of interface. If the
553 * interface inherits from
554 * \c KParts::Part the function will call
555 * \code
556 * new T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
557 * \endcode
558 * \c QWidget the function will call
559 * \code
560 * new T(QWidget *parent, const QVariantList &args)
561 * \endcode
562 * else the function will call
563 * \code
564 * new T(QObject *parent, const QVariantList &args)
565 * \endcode
566 *
567 * If those constructor methods are not callable this overload is not available.
568 */
569 template<class T, enable_if_t<InheritanceChecker<T>::enabled, int> = 0>
570 void registerPlugin()
571 {
572 CreateInstanceWithMetaDataFunction instanceFunction = InheritanceChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
573 registerPlugin(&T::staticMetaObject, instanceFunction);
574 }
575
576 /*!
577 * Uses a default instance creation function depending on the type of interface. If the
578 * interface inherits from
579 * \c KParts::Part the function will call
580 * \code
581 * new T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
582 * \endcode
583 * \c QWidget the function will call
584 * \code
585 * new T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
586 * \endcode
587 * else the function will call
588 * \code
589 * new T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
590 * \endcode
591 *
592 * If those constructor methods are not callable this overload is not available.
593 */
594 template<class T, enable_if_t<InheritanceWithMetaDataChecker<T>::enabled, int> = 0>
595 void registerPlugin()
596 {
597 CreateInstanceWithMetaDataFunction instanceFunction = InheritanceWithMetaDataChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
598 registerPlugin(&T::staticMetaObject, instanceFunction);
599 }
600
601 /*!
602 * Registers a plugin with the factory. Call this function from the constructor of the
603 * KPluginFactory subclass to make the create function able to instantiate the plugin when asked
604 * for an interface the plugin implements.
605 *
606 * \a T the name of the plugin class
607 *
608 * \a instanceFunction A function pointer to a function that creates an instance of the plugin.
609 *
610 * \since 5.96
611 */
612 template<class T>
613 void registerPlugin(CreateInstanceWithMetaDataFunction instanceFunction)
614 {
615 registerPlugin(&T::staticMetaObject, instanceFunction);
616 }
617
618 /*!
619 * This function is called when the factory asked to create an Object.
620 *
621 * You may reimplement it to provide a very flexible factory. This is especially useful to
622 * provide generic factories for plugins implemented using a scripting language.
623 *
624 * \a iface the staticMetaObject::className() string identifying the plugin interface that
625 * was requested. E.g. for KCModule plugins this string will be "KCModule".
626 *
627 * \a parentWidget only used if the requested plugin is a KPart.
628 *
629 * \a parent the parent object for the plugin object.
630 *
631 * \a args a plugin specific list of arbitrary arguments.
632 */
633 virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args);
634
635 template<class impl, class ParentType>
636 static QObject *createInstance(QWidget * /*parentWidget*/, QObject *parent, const KPluginMetaData & /*metaData*/, const QVariantList &args)
637 {
638 ParentType *p = nullptr;
639 if (parent) {
640 p = qobject_cast<ParentType *>(parent);
641 Q_ASSERT(p);
642 }
643 if constexpr (std::is_constructible<impl, ParentType *, QVariantList>::value) {
644 return new impl(p, args);
645 } else {
646 return new impl(p);
647 }
648 }
649
650 template<class impl, class ParentType>
651 static QObject *createWithMetaDataInstance(QWidget * /*parentWidget*/, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
652 {
653 ParentType *p = nullptr;
654 if (parent) {
655 p = qobject_cast<ParentType *>(parent);
656 Q_ASSERT(p);
657 }
658 if constexpr (std::is_constructible<impl, ParentType *, KPluginMetaData, QVariantList>::value) {
659 return new impl(p, metaData, args);
660 } else {
661 return new impl(p, metaData);
662 }
663 }
664
665 template<class impl>
666 static QObject *createPartWithMetaDataInstance(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
667 {
668 if constexpr (std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData, QVariantList>::value) {
669 return new impl(parentWidget, parent, metaData, args);
670 } else {
671 return new impl(parentWidget, parent, metaData);
672 }
673 }
674
675private:
676 friend KPluginFactoryPrivate;
677 std::unique_ptr<KPluginFactoryPrivate> const d;
678 void registerPlugin(const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction);
679 // The logging categories are not part of the public API, consequently this needs to be a private function
680 static void logFailedInstantiationMessage(KPluginMetaData data);
681 static void logFailedInstantiationMessage(const char *className, KPluginMetaData data);
682};
683
684template<typename T>
685inline T *KPluginFactory::create(QObject *parent, const QVariantList &args)
686{
687 QObject *o = create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent) : nullptr, parent, args);
688
689 T *t = qobject_cast<T *>(o);
690 if (!t) {
691 delete o;
692 }
693 return t;
694}
695
696template<typename T>
697inline T *KPluginFactory::create(QWidget *parentWidget, QObject *parent, const QVariantList &args)
698{
699 QObject *o = create(T::staticMetaObject.className(), parentWidget, parent, args);
700
701 T *t = qobject_cast<T *>(o);
702 if (!t) {
703 delete o;
704 }
705 return t;
706}
707
708Q_DECLARE_INTERFACE(KPluginFactory, KPluginFactory_iid)
709
710#endif // KPLUGINFACTORY_H
711

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