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