File indexing completed on 2024-05-19 03:56:22

0001 /*
0002     This file is part of the KDE project
0003 
0004     SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
0005     SPDX-FileCopyrightText: 2007 Bernhard Loos <nhuh.put@web.de>
0006     SPDX-FileCopyrightText: 2021-2023 Alexander Lohnau <alexander.lohnau@gmx.de>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #ifndef KPLUGINFACTORY_H
0012 #define KPLUGINFACTORY_H
0013 
0014 #include "kcoreaddons_export.h"
0015 #include "kpluginmetadata.h"
0016 
0017 #include <QObject>
0018 #include <QVariant>
0019 
0020 #include <memory>
0021 #include <type_traits>
0022 
0023 class QWidget;
0024 class KPluginFactoryPrivate;
0025 
0026 namespace KParts
0027 {
0028 class Part;
0029 }
0030 
0031 #define KPluginFactory_iid "org.kde.KPluginFactory"
0032 
0033 // Internal macro that generated the KPluginFactory subclass
0034 #define __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, ...)                                                                                          \
0035     class name : public KPluginFactory                                                                                                                         \
0036     {                                                                                                                                                          \
0037         Q_OBJECT                                                                                                                                               \
0038         Q_INTERFACES(KPluginFactory)                                                                                                                           \
0039         Q_PLUGIN_METADATA(__VA_ARGS__)                                                                                                                         \
0040     public:                                                                                                                                                    \
0041         explicit name()                                                                                                                                        \
0042         {                                                                                                                                                      \
0043             pluginRegistrations                                                                                                                                \
0044         }                                                                                                                                                      \
0045         ~name(){};                                                                                                                                             \
0046     };
0047 
0048 /**
0049  * @relates KPluginFactory
0050  *
0051  * Create a KPluginFactory subclass and export it as the root plugin object.
0052  *
0053  * @param name the name of the KPluginFactory derived class.
0054  *
0055  * @param pluginRegistrations code to be inserted into the constructor of the
0056  * class. Usually a series of registerPlugin() calls.
0057  *
0058  * @note K_PLUGIN_FACTORY declares the subclass including a Q_OBJECT macro.
0059  * So you need to make sure to have Qt's moc run also for the source file
0060  * where you use the macro. E.g. in projects using CMake and it's automoc feature,
0061  * as usual you need to have a line
0062  * @code
0063  * #include <myplugin.moc>
0064  * @endcode
0065  * in the same source file when that one has the name "myplugin.cpp".
0066  *
0067  * Example:
0068  * @code
0069  * #include <KPluginFactory>
0070  * #include <plugininterface.h>
0071  *
0072  * class MyPlugin : public PluginInterface
0073  * {
0074  * public:
0075  *     MyPlugin(QObject *parent, const QVariantList &args)
0076  *         : PluginInterface(parent)
0077  *     {}
0078  * };
0079  *
0080  * K_PLUGIN_FACTORY(MyPluginFactory, registerPlugin<MyPlugin>();)
0081  *
0082  * #include <myplugin.moc>
0083  * @endcode
0084  *
0085  * If you want to compile a .json file into the plugin, use K_PLUGIN_FACTORY_WITH_JSON.
0086  *
0087  * @see K_PLUGIN_FACTORY_WITH_JSON
0088  * @see K_PLUGIN_FACTORY_DECLARATION
0089  * @see K_PLUGIN_FACTORY_DEFINITION
0090  */
0091 #define K_PLUGIN_FACTORY(name, pluginRegistrations) __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, IID KPluginFactory_iid)
0092 
0093 /**
0094  * @relates KPluginFactory
0095  *
0096  * Create a KPluginFactory subclass and export it as the root plugin object with
0097  * JSON metadata.
0098  *
0099  * This macro does the same as K_PLUGIN_FACTORY, but adds a JSON file as plugin
0100  * metadata.  See Q_PLUGIN_METADATA() for more information.
0101  *
0102  * @param name the name of the KPluginFactory derived class.
0103  *
0104  * @param pluginRegistrations code to be inserted into the constructor of the
0105  * class. Usually a series of registerPlugin() calls.
0106  *
0107  * @param jsonFile name of the JSON file to be compiled into the plugin as metadata
0108  *
0109  * @note K_PLUGIN_FACTORY_WITH_JSON declares the subclass including a Q_OBJECT macro.
0110  * So you need to make sure to have Qt's moc run also for the source file
0111  * where you use the macro. E.g. in projects using CMake and its automoc feature,
0112  * as usual you need to have a line
0113  * @code
0114  * #include <myplugin.moc>
0115  * @endcode
0116  * in the same source file when that one has the name "myplugin.cpp".
0117  *
0118  * Example:
0119  * @code
0120  * #include <KPluginFactory>
0121  * #include <plugininterface.h>
0122  *
0123  * class MyPlugin : public PluginInterface
0124  * {
0125  * public:
0126  *     MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0127  *         : PluginInterface(parent)
0128  *     {}
0129  * };
0130  *
0131  * K_PLUGIN_FACTORY_WITH_JSON(MyPluginFactory,
0132  *                  "metadata.json",
0133  *                  registerPlugin<MyPlugin>();
0134  *                 )
0135  *
0136  * #include <myplugin.moc>
0137  * @endcode
0138  *
0139  * @see K_PLUGIN_FACTORY
0140  * @see K_PLUGIN_FACTORY_DECLARATION
0141  * @see K_PLUGIN_FACTORY_DEFINITION
0142  *
0143  * @since 5.0
0144  */
0145 #define K_PLUGIN_FACTORY_WITH_JSON(name, jsonFile, pluginRegistrations)                                                                                        \
0146     __K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations, IID KPluginFactory_iid FILE jsonFile)
0147 
0148 /**
0149  * @relates KPluginFactory
0150  *
0151  * Create a KPluginFactory subclass and export it as the root plugin object with
0152  * JSON metadata.
0153  *
0154  * This macro does the same as K_PLUGIN_FACTORY_WITH_JSON, but you only have to pass the class name and the json file.
0155  * The factory name and registerPlugin call are deduced from the class name.
0156  *
0157  * @code
0158  * #include <myplugin.moc>
0159  * @endcode
0160  * in the same source file when that one has the name "myplugin.cpp".
0161  *
0162  * Example:
0163  * @code
0164  * #include <KPluginFactory>
0165  * #include <plugininterface.h>
0166  *
0167  * class MyPlugin : public PluginInterface
0168  * {
0169  * public:
0170  *     MyPlugin(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0171  *         : PluginInterface(parent)
0172  *     {}
0173  * };
0174  *
0175  * K_PLUGIN_CLASS_WITH_JSON(MyPlugin, "metadata.json")
0176  *
0177  * #include <myplugin.moc>
0178  * @endcode
0179  *
0180  * @see K_PLUGIN_FACTORY_WITH_JSON
0181  *
0182  * @since 5.44
0183  */
0184 #ifdef KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME
0185 #define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)                                                                                                          \
0186     K_PLUGIN_FACTORY_WITH_JSON(KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME, jsonFile, registerPlugin<classname>();)
0187 #else
0188 #define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile) K_PLUGIN_FACTORY_WITH_JSON(classname##Factory, jsonFile, registerPlugin<classname>();)
0189 #endif
0190 
0191 /**
0192  * @relates KPluginFactory
0193  *
0194  * Creates a KPluginFactory subclass and exports it as the root plugin object.
0195  * Unlike @ref K_PLUGIN_CLASS_WITH_JSON, this macro does not require json meta data.
0196  *
0197  * This macro does the same as K_PLUGIN_FACTORY, but you only have to pass the class name.
0198  * The factory name and registerPlugin call are deduced from the class name.
0199  * This is also useful if you want to use static plugins, see the kcoreaddons_add_plugin CMake method.
0200  * @since 5.90
0201  */
0202 #ifdef KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME
0203 #define K_PLUGIN_CLASS(classname) K_PLUGIN_FACTORY(KPLUGINFACTORY_PLUGIN_CLASS_INTERNAL_NAME, registerPlugin<classname>();)
0204 #else
0205 #define K_PLUGIN_CLASS(classname) K_PLUGIN_FACTORY(classname##Factory, registerPlugin<classname>();)
0206 #endif
0207 
0208 /**
0209  * @class KPluginFactory kpluginfactory.h <KPluginFactory>
0210  *
0211  * KPluginFactory provides a convenient way to provide factory-style plugins.
0212  * Qt plugins provide a singleton object, but a common pattern is for plugins
0213  * to generate as many objects of a particular type as the application requires.
0214  * By using KPluginFactory, you can avoid implementing the factory pattern
0215  * yourself.
0216  *
0217  * KPluginFactory also allows plugins to provide multiple different object
0218  * types, indexed by keywords.
0219  *
0220  * The objects created by KPluginFactory must inherit QObject, and must have a
0221  * standard constructor pattern:
0222  * @li if the object is a KPart::Part, it must be of the form
0223  * @code
0224  * T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
0225  * @endcode
0226  * or
0227  * @code
0228  * T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0229  * @endcode
0230  * @li if it is a QWidget, it must be of the form
0231  * @code
0232  * T(QWidget *parent, const QVariantList &args)
0233  * @endcode
0234  * or
0235  * @code
0236  * T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
0237  * @endcode
0238  * @li otherwise it must be of the form
0239  * @code
0240  * T(QObject *parent, const QVariantList &args)
0241  * @endcode
0242  * or
0243  * @code
0244  * T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0245  * @endcode
0246  *
0247  * You should typically use either K_PLUGIN_CLASS() or
0248  * K_PLUGIN_CLASS_WITH_JSON() in your plugin code to generate a factory.
0249  * The typical pattern is:
0250  *
0251  * @code
0252  * #include <KPluginFactory>
0253  * #include <plugininterface.h>
0254  *
0255  * class MyPlugin : public PluginInterface
0256  * {
0257  * public:
0258  *     MyPlugin(QObject *parent, const QVariantList &args)
0259  *         : PluginInterface(parent)
0260  *     {}
0261  * };
0262  *
0263  * K_PLUGIN_CLASS(MyPlugin)
0264  * #include <myplugin.moc>
0265  * @endcode
0266  *
0267  * If you want to write a custom KPluginFactory not using the standard macro(s)
0268  * you can reimplement the
0269  * create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
0270  * method.
0271  *
0272  * Example:
0273  * @code
0274  * class SomeScriptLanguageFactory : public KPluginFactory
0275  * {
0276  *     Q_OBJECT
0277  * public:
0278  *     SomeScriptLanguageFactory()
0279  *     {}
0280  *
0281  * protected:
0282  *     virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args)
0283  *     {
0284  *         // Create an identifier based on the iface and given pluginId
0285  *         const QString identifier = QLatin1String(iface) + QLatin1Char('_') + metaData().pluginId();
0286  *         // load scripting language module from the information in identifier and return it:
0287  *         return object;
0288  *     }
0289  * };
0290  * @endcode
0291  *
0292  * To load the KPluginFactory from an installed plugin you can use @ref loadFactory and for
0293  * directly creating a plugin instance from it @ref instantiatePlugin
0294  *
0295  * @author Matthias Kretz <kretz@kde.org>
0296  * @author Bernhard Loos <nhuh.put@web.de>
0297  * @author Alexander Lohnau <alexander.lohnau@gmx.de>
0298  */
0299 class KCOREADDONS_EXPORT KPluginFactory : public QObject
0300 {
0301     Q_OBJECT
0302 
0303 public:
0304     /**
0305      * This constructor creates a factory for a plugin.
0306      */
0307     explicit KPluginFactory();
0308 
0309     /**
0310      * This destroys the PluginFactory.
0311      */
0312     ~KPluginFactory() override;
0313 
0314     /// @since 5.86
0315     enum ResultErrorReason {
0316         NO_PLUGIN_ERROR = 0,
0317         INVALID_PLUGIN,
0318         INVALID_FACTORY,
0319         INVALID_KPLUGINFACTORY_INSTANTIATION,
0320     };
0321     /**
0322      * Holds the result of a plugin load operation, i.e. the loaded plugin on success or information about the error on failure
0323      * @since 5.86
0324      */
0325     template<typename T>
0326     class Result
0327     {
0328     public:
0329         T *plugin = nullptr;
0330         /// translated, user-visible error string
0331         QString errorString;
0332         /// untranslated error text
0333         QString errorText;
0334         ResultErrorReason errorReason = NO_PLUGIN_ERROR;
0335         explicit operator bool() const
0336         {
0337             return plugin != nullptr;
0338         }
0339     };
0340 
0341     /**
0342      * Attempts to load the KPluginFactory from the given metadata.
0343      * The errors will be logged using the `kf.coreaddons` debug category.
0344      * @param data KPluginMetaData from which the plugin should be loaded
0345      * @return Result object which contains the plugin instance and potentially error information
0346      * @since 5.86
0347      */
0348     static Result<KPluginFactory> loadFactory(const KPluginMetaData &data);
0349 
0350     /**
0351      * Attempts to load the KPluginFactory and create a @p T instance from the given metadata
0352      * KCoreAddons will log error messages automatically, meaning you only need to implement your
0353      * own logging in case you want to give it more context info or have a custom category.
0354      * @code
0355         if (auto result = KPluginFactory::instantiatePlugin<MyClass>(metaData, parent, args)) {
0356             // The plugin is valid and result.plugin contains the object
0357         } else {
0358             // We can access the error related properties, but result.plugin is a nullptr
0359             qCWarning(MYCATEGORY) << result.errorString;
0360         }
0361      * @endcode
0362      * If there is no extra error handling needed the plugin can be directly accessed and checked if it is a nullptr
0363      * @code
0364         if (auto plugin = KPluginFactory::instantiatePlugin<MyClass>(metaData, parent, args).plugin) {
0365         }
0366      * @endcode
0367      * @param data KPluginMetaData from which the plugin should be loaded
0368      * @param args arguments which get passed to the plugin's constructor
0369      * @return Result object which contains the plugin instance and potentially error information
0370      * @since 5.86
0371      */
0372     template<typename T>
0373     static Result<T> instantiatePlugin(const KPluginMetaData &data, QObject *parent = nullptr, const QVariantList &args = {})
0374     {
0375         Result<T> result;
0376         KPluginFactory::Result<KPluginFactory> factoryResult = loadFactory(data);
0377         if (!factoryResult.plugin) {
0378             result.errorString = factoryResult.errorString;
0379             result.errorText = factoryResult.errorText;
0380             result.errorReason = factoryResult.errorReason;
0381             return result;
0382         }
0383         T *instance = factoryResult.plugin->create<T>(parent, args);
0384         if (!instance) {
0385             const QLatin1String className(T::staticMetaObject.className());
0386             result.errorString = tr("KPluginFactory could not create a %1 instance from %2").arg(className, data.fileName());
0387             result.errorText = QStringLiteral("KPluginFactory could not create a %1 instance from %2").arg(className, data.fileName());
0388             result.errorReason = INVALID_KPLUGINFACTORY_INSTANTIATION;
0389             logFailedInstantiationMessage(T::staticMetaObject.className(), data);
0390         } else {
0391             result.plugin = instance;
0392         }
0393         return result;
0394     }
0395 
0396     /**
0397      * Use this method to create an object. It will try to create an object which inherits
0398      * @p T. If it has multiple choices it's not defined which object will be returned, so be careful
0399      * to request a unique interface or use keywords.
0400      *
0401      * @tparam T the interface for which an object should be created. The object will inherit @p T.
0402      * @param parent the parent of the object. If @p parent is a widget type, it will also passed
0403      *               to the parentWidget argument of the CreateInstanceFunction for the object.
0404      * @param args additional arguments which will be passed to the object.
0405      * @returns pointer to the created object is returned, or @c nullptr if an error occurred.
0406      */
0407     template<typename T>
0408     T *create(QObject *parent = nullptr, const QVariantList &args = {});
0409 
0410     /**
0411      * Use this method to create an object. It will try to create an object which inherits @p T
0412      * This overload has an additional @p parentWidget argument, which is used by some plugins (e.g. Parts).
0413 
0414      * @tparam T the interface for which an object should be created. The object will inherit @p T.
0415      * @param parentWidget an additional parent widget.
0416      * @param parent the parent of the object. If @p parent is a widget type, it will also passed
0417      *               to the parentWidget argument of the CreateInstanceFunction for the object.
0418      * @param args additional arguments which will be passed to the object. Since 5.93 this has a default arg.
0419      * @returns pointer to the created object is returned, or @c nullptr if an error occurred.
0420      */
0421     template<typename T>
0422     T *create(QWidget *parentWidget, QObject *parent, const QVariantList &args = {});
0423 
0424     /**
0425      * @returns the metadata of the plugin
0426      *
0427      * @since 5.77
0428      */
0429     KPluginMetaData metaData() const;
0430 
0431     /**
0432      * Set the metadata about the plugin this factory generates.
0433      *
0434      * @param metaData  the metadata about the plugin
0435      *
0436      * @since 5.77
0437      */
0438     void setMetaData(const KPluginMetaData &metaData);
0439 
0440 protected:
0441     /**
0442      * Function pointer type to a function that instantiates a plugin
0443      * For plugins that don't support a KPluginMetaData parameter it is discarded
0444      * @since 5.77
0445      */
0446     using CreateInstanceWithMetaDataFunction = QObject *(*)(QWidget *, QObject *, const KPluginMetaData &, const QVariantList &);
0447 
0448     /**
0449      * This is used to detect the arguments need for the constructor of metadata-taking plugin classes.
0450      * You can inherit it, if you want to add new classes and still keep support for the old ones.
0451      */
0452     template<class impl>
0453     struct InheritanceWithMetaDataChecker {
0454         /// property to control the availability of the registerPlugin overload taking default values
0455         static constexpr bool enabled = std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData, QVariantList>::value // KParts
0456             || std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData>::value
0457             || std::is_constructible<impl, QWidget *, KPluginMetaData, QVariantList>::value // QWidgets
0458             || std::is_constructible<impl, QWidget *, KPluginMetaData>::value
0459             || std::is_constructible<impl, QObject *, KPluginMetaData, QVariantList>::value // Nomal QObjects
0460             || std::is_constructible<impl, QObject *, KPluginMetaData>::value;
0461 
0462         CreateInstanceWithMetaDataFunction createInstanceFunction(KParts::Part *)
0463         {
0464             return &createPartWithMetaDataInstance<impl>;
0465         }
0466         CreateInstanceWithMetaDataFunction createInstanceFunction(QWidget *)
0467         {
0468             return &createWithMetaDataInstance<impl, QWidget>;
0469         }
0470         CreateInstanceWithMetaDataFunction createInstanceFunction(...)
0471         {
0472             return &createWithMetaDataInstance<impl, QObject>;
0473         }
0474     };
0475 
0476     /**
0477      * This is used to detect the arguments need for the constructor of metadata-less plugin classes.
0478      * You can inherit it, if you want to add new classes and still keep support for the old ones.
0479      */
0480     template<class impl>
0481     struct InheritanceChecker {
0482         /// property to control the availability of the registerPlugin overload taking default values
0483         static constexpr bool _canConstruct = std::is_constructible<impl, QWidget *, QVariantList>::value // QWidget plugin
0484             || std::is_constructible<impl, QWidget *>::value //
0485             || std::is_constructible<impl, QObject *, QVariantList>::value // QObject plugins
0486             || std::is_constructible<impl, QObject *>::value;
0487         static constexpr bool enabled = _canConstruct && !InheritanceWithMetaDataChecker<impl>::enabled; // Avoid ambiguity in case of default arguments
0488 
0489         CreateInstanceWithMetaDataFunction createInstanceFunction(QWidget *)
0490         {
0491             return &createInstance<impl, QWidget>;
0492         }
0493         CreateInstanceWithMetaDataFunction createInstanceFunction(...)
0494         {
0495             return &createInstance<impl, QObject>;
0496         }
0497     };
0498 
0499     // Use std::enable_if_t once C++14 can be relied on
0500     template<bool B, class T = void>
0501     using enable_if_t = typename std::enable_if<B, T>::type;
0502 
0503     /**
0504      * Uses a default instance creation function depending on the type of interface. If the
0505      * interface inherits from
0506      * @li @c KParts::Part the function will call
0507      * @code
0508      * new T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
0509      * @endcode
0510      * @li @c QWidget the function will call
0511      * @code
0512      * new T(QWidget *parent, const QVariantList &args)
0513      * @endcode
0514      * @li else the function will call
0515      * @code
0516      * new T(QObject *parent, const QVariantList &args)
0517      * @endcode
0518      *
0519      * If those constructor methods are not callable this overload is not available.
0520      */
0521     template<class T, enable_if_t<InheritanceChecker<T>::enabled, int> = 0>
0522     void registerPlugin()
0523     {
0524         CreateInstanceWithMetaDataFunction instanceFunction = InheritanceChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
0525         registerPlugin(&T::staticMetaObject, instanceFunction);
0526     }
0527 
0528     /**
0529      * Uses a default instance creation function depending on the type of interface. If the
0530      * interface inherits from
0531      * @li @c KParts::Part the function will call
0532      * @code
0533      * new T(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0534      * @endcode
0535      * @li @c QWidget the function will call
0536      * @code
0537      * new T(QWidget *parent, const KPluginMetaData &metaData, const QVariantList &args)
0538      * @endcode
0539      * @li else the function will call
0540      * @code
0541      * new T(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0542      * @endcode
0543      *
0544      * If those constructor methods are not callable this overload is not available.
0545      */
0546     template<class T, enable_if_t<InheritanceWithMetaDataChecker<T>::enabled, int> = 0>
0547     void registerPlugin()
0548     {
0549         CreateInstanceWithMetaDataFunction instanceFunction = InheritanceWithMetaDataChecker<T>().createInstanceFunction(static_cast<T *>(nullptr));
0550         registerPlugin(&T::staticMetaObject, instanceFunction);
0551     }
0552 
0553     /**
0554      * Registers a plugin with the factory. Call this function from the constructor of the
0555      * KPluginFactory subclass to make the create function able to instantiate the plugin when asked
0556      * for an interface the plugin implements.
0557      *
0558      * @param T the name of the plugin class
0559      * @param instanceFunction A function pointer to a function that creates an instance of the plugin.
0560      * @since 5.96
0561      */
0562     template<class T>
0563     void registerPlugin(CreateInstanceWithMetaDataFunction instanceFunction)
0564     {
0565         registerPlugin(&T::staticMetaObject, instanceFunction);
0566     }
0567 
0568     /**
0569      * This function is called when the factory asked to create an Object.
0570      *
0571      * You may reimplement it to provide a very flexible factory. This is especially useful to
0572      * provide generic factories for plugins implemented using a scripting language.
0573      *
0574      * @param iface the staticMetaObject::className() string identifying the plugin interface that
0575      * was requested. E.g. for KCModule plugins this string will be "KCModule".
0576      * @param parentWidget only used if the requested plugin is a KPart.
0577      * @param parent the parent object for the plugin object.
0578      * @param args a plugin specific list of arbitrary arguments.
0579      */
0580     virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args);
0581 
0582     template<class impl, class ParentType>
0583     static QObject *createInstance(QWidget * /*parentWidget*/, QObject *parent, const KPluginMetaData & /*metaData*/, const QVariantList &args)
0584     {
0585         ParentType *p = nullptr;
0586         if (parent) {
0587             p = qobject_cast<ParentType *>(parent);
0588             Q_ASSERT(p);
0589         }
0590         if constexpr (std::is_constructible<impl, ParentType *, QVariantList>::value) {
0591             return new impl(p, args);
0592         } else {
0593             return new impl(p);
0594         }
0595     }
0596 
0597     template<class impl, class ParentType>
0598     static QObject *createWithMetaDataInstance(QWidget * /*parentWidget*/, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0599     {
0600         ParentType *p = nullptr;
0601         if (parent) {
0602             p = qobject_cast<ParentType *>(parent);
0603             Q_ASSERT(p);
0604         }
0605         if constexpr (std::is_constructible<impl, ParentType *, KPluginMetaData, QVariantList>::value) {
0606             return new impl(p, metaData, args);
0607         } else {
0608             return new impl(p, metaData);
0609         }
0610     }
0611 
0612     template<class impl>
0613     static QObject *createPartWithMetaDataInstance(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
0614     {
0615         if constexpr (std::is_constructible<impl, QWidget *, QObject *, KPluginMetaData, QVariantList>::value) {
0616             return new impl(parentWidget, parent, metaData, args);
0617         } else {
0618             return new impl(parentWidget, parent, metaData);
0619         }
0620     }
0621 
0622 private:
0623     friend KPluginFactoryPrivate;
0624     std::unique_ptr<KPluginFactoryPrivate> const d;
0625     void registerPlugin(const QMetaObject *metaObject, CreateInstanceWithMetaDataFunction instanceFunction);
0626     // The logging categories are not part of the public API, consequently this needs to be a private function
0627     static void logFailedInstantiationMessage(KPluginMetaData data);
0628     static void logFailedInstantiationMessage(const char *className, KPluginMetaData data);
0629 };
0630 
0631 template<typename T>
0632 inline T *KPluginFactory::create(QObject *parent, const QVariantList &args)
0633 {
0634     QObject *o = create(T::staticMetaObject.className(), parent && parent->isWidgetType() ? reinterpret_cast<QWidget *>(parent) : nullptr, parent, args);
0635 
0636     T *t = qobject_cast<T *>(o);
0637     if (!t) {
0638         delete o;
0639     }
0640     return t;
0641 }
0642 
0643 template<typename T>
0644 inline T *KPluginFactory::create(QWidget *parentWidget, QObject *parent, const QVariantList &args)
0645 {
0646     QObject *o = create(T::staticMetaObject.className(), parentWidget, parent, args);
0647 
0648     T *t = qobject_cast<T *>(o);
0649     if (!t) {
0650         delete o;
0651     }
0652     return t;
0653 }
0654 
0655 Q_DECLARE_INTERFACE(KPluginFactory, KPluginFactory_iid)
0656 
0657 #endif // KPLUGINFACTORY_H