File indexing completed on 2025-04-27 10:12:15
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2000 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-only 0008 */ 0009 0010 #ifndef __kplugintrader_h__ 0011 #define __kplugintrader_h__ 0012 0013 #include "kplugininfo.h" 0014 0015 #if KSERVICE_ENABLE_DEPRECATED_SINCE(5, 82) 0016 0017 class KPluginTraderPrivate; 0018 /** 0019 * \class KPluginTrader kplugintrader.h <KPluginTrader> 0020 * 0021 * A trader interface which provides a way to query specific subdirectories in the Qt 0022 * plugin paths for plugins. KPluginTrader provides an easy way to load a plugin 0023 * instance from a KPluginFactory, or just querying for existing plugins. 0024 * 0025 * KPluginTrader provides a way for an application to query directories in the 0026 * Qt plugin paths, accessed through QCoreApplication::libraryPaths(). 0027 * Plugins may match a specific set of requirements. This allows to find 0028 * specific plugins at run-time without having to hard-code their names and/or 0029 * paths. KPluginTrader does not search recursively, you are rather encouraged 0030 * to install plugins into specific subdirectories to further speed searching. 0031 * 0032 * KPluginTrader exclusively searches within the plugin binaries' metadata 0033 * (via QPluginLoader::metaData()). It does not search these directories recursively. 0034 * 0035 * KPluginTrader does not use KServiceTypeTrader or KSyCoCa. As such, it will 0036 * only find binary plugins. If you are looking for a generic way to query for 0037 * services, use KServiceTypeTrader. For anything relating to MIME types (type 0038 * of files), use KMimeTypeTrader. 0039 * 0040 * \par Example 0041 * 0042 * If you want to find all plugins for your application, 0043 * you would define a KMyApp/Plugin servicetype, and then you can query 0044 * the trader for it: 0045 * \code 0046 * KPluginInfo::List offers = 0047 * KPluginTrader::self()->query("KMyApp/Plugin", "kf5"); 0048 * \endcode 0049 * 0050 * You can add a constraint in the "trader query language". For instance: 0051 * \code 0052 * KPluginTrader::self()->query("KMyApp/Plugin", "kf5", 0053 * "[X-KMyApp-InterfaceVersion] > 15"); 0054 * \endcode 0055 * 0056 * Please note that when including property names containing arithmetic operators like - or +, then you have 0057 * to put brackets around the property name, in order to correctly separate arithmetic operations from 0058 * the name. So for example a constraint expression like 0059 * \code 0060 * X-KMyApp-InterfaceVersion > 4 // wrong! 0061 * \endcode 0062 * needs to be written as 0063 * \code 0064 * [X-KMyApp-InterfaceVersion] > 4 0065 * \endcode 0066 * otherwise it could also be interpreted as 0067 * Subtract the numeric value of the property "KMyApp" and "InterfaceVersion" from the 0068 * property "X" and make sure it is greater than 4.\n 0069 * Instead of the other meaning, make sure that the numeric value of "X-KMyApp-InterfaceVersion" is 0070 * greater than 4. 0071 * 0072 * @see KMimeTypeTrader, KServiceTypeTrader, KPluginInfo 0073 * @see QCoreApplication::libraryPaths 0074 * @see QT_PLUGIN_PATH (env variable) 0075 * @see KPluginFactory 0076 * @see kservice_desktop_to_json (Cmake macro) 0077 * @see K_PLUGIN_FACTORY_WITH_JSON (macro defined in KPluginFactory) 0078 * 0079 * @since 5.0 0080 */ 0081 class KSERVICE_EXPORT KPluginTrader 0082 { 0083 public: 0084 /** 0085 * Standard destructor 0086 */ 0087 ~KPluginTrader(); 0088 0089 /** 0090 * The main function in the KPluginTrader class. 0091 * 0092 * It will return a list of plugins that match your specifications. Required parameter is the 0093 * service type and subdirectory. This method will append the subDirectory to every path found 0094 * in QCoreApplication::libraryPaths(), append the subDirectory parameter, and search through 0095 * the plugin's metadata 0096 * 0097 * KPluginTrader exclusively searches within the plugin binaries' metadata 0098 * (via QPluginLoader::metaData()). It does not search these directories recursively. 0099 * 0100 * The constraint parameter is used to limit the possible choices returned based on the 0101 * constraints you give it. 0102 * 0103 * The @p constraint language is rather full. The most common 0104 * keywords are AND, OR, NOT, IN, and EXIST, all used in an 0105 * almost spoken-word form. An example is: 0106 * \code 0107 * (Type == 'Service') and (('KParts/ReadOnlyPart' in ServiceTypes) or (exist Exec)) 0108 * \endcode 0109 * 0110 * If you want to load a list of plugins from a specific subdirectory, you can do the following: 0111 * 0112 * \code 0113 * 0114 * const KPluginInfo::List plugins = KPluginTrader::self()->query("plasma/engines"); 0115 * 0116 * for (const KPluginInfo &info : plugins) { 0117 * KPluginLoader loader(info.libraryPath()); 0118 * const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap(); 0119 * // In many cases, plugins are actually based on KPluginFactory, this is how that works: 0120 * KPluginFactory* factory = loader.factory(); 0121 * if (factory) { 0122 * Engine* component = factory->create<Engine>(parent, argsWithMetaData); 0123 * if (component) { 0124 * // Do whatever you want to do with the resulting object 0125 * } 0126 * } 0127 * // Otherwise, just use the normal QPluginLoader methods 0128 * Engine *myengine = qobject_cast<Engine*>(loader.instance()); 0129 * if (myengine) { 0130 * // etc. ... 0131 * } 0132 * } 0133 * \endcode 0134 * 0135 * If you have a specific query for just one plugin, use the createInstanceFromQuery method. 0136 * 0137 * The keys used in the query (Type, ServiceType, Exec) are all fields found in the .json files 0138 * which are compiled into the plugin binaries. 0139 * 0140 * @param subDirectory The subdirectory under the Qt plugin path 0141 * @param servicetype A service type like 'KMyApp/Plugin' or 'KFilePlugin' 0142 * @param constraint A constraint to limit the choices returned, QString() to 0143 * get all services of the given @p servicetype 0144 * 0145 * @return A list of services that satisfy the query 0146 * @see http://techbase.kde.org/Development/Tutorials/Services/Traders#The_KTrader_Query_Language 0147 * @deprecated since 5.82, use KPluginMetaData::findPlugins. 0148 */ 0149 KSERVICE_DEPRECATED_VERSION(5, 82, "Use KPluginMetaData::findPlugins") 0150 KPluginInfo::List query(const QString &subDirectory, const QString &serviceType = QString(), const QString &constraint = QString()); 0151 0152 /** 0153 * This is a static pointer to the KPluginTrader singleton. 0154 * 0155 * You will need to use this to access the KPluginTrader functionality since the 0156 * constructors are protected. 0157 * 0158 * @deprecated since 5.82, use KPluginMetaData and KPluginFactory. 0159 * 0160 * @return Static KPluginTrader instance 0161 */ 0162 KSERVICE_DEPRECATED_VERSION(5, 82, "Use KPluginMetaData and KPluginFactory") 0163 static KPluginTrader *self(); 0164 0165 /** 0166 * Get a plugin from a trader query 0167 * 0168 * Example: 0169 * \code 0170 * KMyAppPlugin* plugin = KPluginTrader::createInstanceFromQuery<KMyAppPlugin>(subDirectory, serviceType, QString(), parentObject ); 0171 * if ( plugin ) { 0172 * .... 0173 * } 0174 * \endcode 0175 * 0176 * @param subDirectory The subdirectory under the Qt plugin paths to search in 0177 * @param serviceType The type of service for which to find a plugin 0178 * @param constraint An optional constraint to pass to the trader (see KTrader) 0179 * @param parent The parent object for the part itself 0180 * @param args A list of arguments passed to the service component 0181 * @param error The string passed here will contain an error description. 0182 * @return A pointer to the newly created object or a null pointer if the 0183 * factory was unable to create an object of the given type. 0184 * @deprecated since 5.82, use KPluginLoader API. 0185 */ 0186 template<class T> 0187 KSERVICE_DEPRECATED_VERSION(5, 82, "Use KPluginLoader API") 0188 static T *createInstanceFromQuery(const QString &subDirectory, 0189 const QString &serviceType = QString(), 0190 const QString &constraint = QString(), 0191 QObject *parent = nullptr, 0192 const QVariantList &args = QVariantList(), 0193 QString *error = nullptr) 0194 { 0195 return createInstanceFromQuery<T>(subDirectory, serviceType, constraint, parent, nullptr, args, error); 0196 } 0197 0198 /** 0199 * Get a plugin from a trader query 0200 * 0201 * This method works like 0202 * createInstanceFromQuery(const QString&, const QString& ,const QString&, QObject*, 0203 * const QVariantList&, QString*), 0204 * but you can specify an additional parent widget. This is important for a KPart, for example. 0205 * 0206 * @param subDirectory The subdirectory under the Qt plugin paths to search in 0207 * @param serviceType the type of service for which to find a plugin 0208 * @param constraint an optional constraint to pass to the trader (see KTrader) 0209 * @param parent the parent object for the part itself 0210 * @param parentWidget the parent widget for the plugin 0211 * @param args A list of arguments passed to the service component 0212 * @param error The string passed here will contain an error description. 0213 * @return A pointer to the newly created object or a null pointer if the 0214 * factory was unable to create an object of the given type. 0215 * @deprecated since 5.82, use KPluginLoader API. 0216 */ 0217 template<class T> 0218 KSERVICE_DEPRECATED_VERSION(5, 82, "Use KPluginLoader API") 0219 static T *createInstanceFromQuery(const QString &subDirectory, 0220 const QString &serviceType, 0221 const QString &constraint, 0222 QObject *parent, 0223 QWidget *parentWidget, 0224 const QVariantList &args = QVariantList(), 0225 QString *error = nullptr) 0226 { 0227 Q_UNUSED(parentWidget) 0228 Q_UNUSED(args) 0229 if (error) { 0230 error->clear(); 0231 } 0232 const KPluginInfo::List offers = self()->query(subDirectory, serviceType, constraint); 0233 0234 for (const KPluginInfo &info : offers) { 0235 KPluginLoader loader(info.libraryPath()); 0236 const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap(); 0237 KPluginFactory *factory = loader.factory(); 0238 if (factory) { 0239 T *component = factory->create<T>(parent, argsWithMetaData); 0240 if (component) { 0241 return component; 0242 } 0243 } 0244 } 0245 if (error && error->isEmpty()) { 0246 *error = QCoreApplication::translate("", "No service matching the requirements was found"); 0247 } 0248 return nullptr; 0249 } 0250 0251 KSERVICE_DEPRECATED_VERSION(5, 82, "No users.") 0252 static void applyConstraints(KPluginInfo::List &lst, const QString &constraint); 0253 0254 private: 0255 /** 0256 * @internal 0257 */ 0258 KPluginTrader(); 0259 0260 // disallow copy ctor and assignment operator 0261 KPluginTrader(const KPluginTrader &other); 0262 KPluginTrader &operator=(const KPluginTrader &rhs); 0263 0264 KPluginTraderPrivate *const d; 0265 }; 0266 #endif 0267 0268 #endif