KService

kplugintrader.h
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Torben Weis <[email protected]>
4  SPDX-FileCopyrightText: 2006 David Faure <[email protected]>
5  SPDX-FileCopyrightText: 2013 Sebastian K├╝gler <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-only
8 */
9 
10 #ifndef __kplugintrader_h__
11 #define __kplugintrader_h__
12 
13 #include "kplugininfo.h"
14 class KPluginTraderPrivate;
15 /**
16  * \class KPluginTrader kplugintrader.h <KPluginTrader>
17  *
18  * A trader interface which provides a way to query specific subdirectories in the Qt
19  * plugin paths for plugins. KPluginTrader provides an easy way to load a plugin
20  * instance from a KPluginFactory, or just querying for existing plugins.
21  *
22  * KPluginTrader provides a way for an application to query directories in the
23  * Qt plugin paths, accessed through QCoreApplication::libraryPaths().
24  * Plugins may match a specific set of requirements. This allows to find
25  * specific plugins at run-time without having to hard-code their names and/or
26  * paths. KPluginTrader does not search recursively, you are rather encouraged
27  * to install plugins into specific subdirectories to further speed searching.
28  *
29  * KPluginTrader exclusively searches within the plugin binaries' metadata
30  * (via QPluginLoader::metaData()). It does not search these directories recursively.
31  *
32  * KPluginTrader does not use KServiceTypeTrader or KSyCoCa. As such, it will
33  * only find binary plugins. If you are looking for a generic way to query for
34  * services, use KServiceTypeTrader. For anything relating to MIME types (type
35  * of files), use KMimeTypeTrader.
36  *
37  * \par Example
38  *
39  * If you want to find all plugins for your application,
40  * you would define a KMyApp/Plugin servicetype, and then you can query
41  * the trader for it:
42  * \code
43  * KPluginInfo::List offers =
44  * KPluginTrader::self()->query("KMyApp/Plugin", "kf5");
45  * \endcode
46  *
47  * You can add a constraint in the "trader query language". For instance:
48  * \code
49  * KPluginTrader::self()->query("KMyApp/Plugin", "kf5",
50  * "[X-KMyApp-InterfaceVersion] > 15");
51  * \endcode
52  *
53  * Please note that when including property names containing arithmetic operators like - or +, then you have
54  * to put brackets around the property name, in order to correctly separate arithmetic operations from
55  * the name. So for example a constraint expression like
56  * \code
57  * X-KMyApp-InterfaceVersion > 4 // wrong!
58  * \endcode
59  * needs to be written as
60  * \code
61  * [X-KMyApp-InterfaceVersion] > 4
62  * \endcode
63  * otherwise it could also be interpreted as
64  * Subtract the numeric value of the property "KMyApp" and "InterfaceVersion" from the
65  * property "X" and make sure it is greater than 4.\n
66  * Instead of the other meaning, make sure that the numeric value of "X-KMyApp-InterfaceVersion" is
67  * greater than 4.
68  *
69  * @see KMimeTypeTrader, KServiceTypeTrader, KPluginInfo
70  * @see QCoreApplication::libraryPaths
71  * @see QT_PLUGIN_PATH (env variable)
72  * @see KPluginFactory
73  * @see kservice_desktop_to_json (Cmake macro)
74  * @see K_PLUGIN_FACTORY_WITH_JSON (macro defined in KPluginFactory)
75  *
76  * @since 5.0
77  */
78 class KSERVICE_EXPORT KPluginTrader
79 {
80 public:
81  /**
82  * Standard destructor
83  */
84  ~KPluginTrader();
85 
86  /**
87  * The main function in the KPluginTrader class.
88  *
89  * It will return a list of plugins that match your specifications. Required parameter is the
90  * service type and subdirectory. This method will append the subDirectory to every path found
91  * in QCoreApplication::libraryPaths(), append the subDirectory parameter, and search through
92  * the plugin's metadata
93  *
94  * KPluginTrader exclusively searches within the plugin binaries' metadata
95  * (via QPluginLoader::metaData()). It does not search these directories recursively.
96  *
97  * The constraint parameter is used to limit the possible choices returned based on the
98  * constraints you give it.
99  *
100  * The @p constraint language is rather full. The most common
101  * keywords are AND, OR, NOT, IN, and EXIST, all used in an
102  * almost spoken-word form. An example is:
103  * \code
104  * (Type == 'Service') and (('KParts/ReadOnlyPart' in ServiceTypes) or (exist Exec))
105  * \endcode
106  *
107  * If you want to load a list of plugins from a specific subdirectory, you can do the following:
108  *
109  * \code
110  *
111  * const KPluginInfo::List plugins = KPluginTrader::self()->query("plasma/engines");
112  *
113  * for (const KPluginInfo &info : plugins) {
114  * KPluginLoader loader(info.libraryPath());
115  * const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap();
116  * // In many cases, plugins are actually based on KPluginFactory, this is how that works:
117  * KPluginFactory* factory = loader.factory();
118  * if (factory) {
119  * Engine* component = factory->create<Engine>(parent, argsWithMetaData);
120  * if (component) {
121  * // Do whatever you want to do with the resulting object
122  * }
123  * }
124  * // Otherwise, just use the normal QPluginLoader methods
125  * Engine *myengine = qobject_cast<Engine*>(loader.instance());
126  * if (myengine) {
127  * // etc. ...
128  * }
129  * }
130  * \endcode
131  *
132  * If you have a specific query for just one plugin, use the createInstanceFromQuery method.
133  *
134  * The keys used in the query (Type, ServiceType, Exec) are all fields found in the .json files
135  * which are compiled into the plugin binaries.
136  *
137  * @param subDirectory The subdirectory under the Qt plugin path
138  * @param servicetype A service type like 'KMyApp/Plugin' or 'KFilePlugin'
139  * @param constraint A constraint to limit the choices returned, QString() to
140  * get all services of the given @p servicetype
141  *
142  * @return A list of services that satisfy the query
143  * @see http://techbase.kde.org/Development/Tutorials/Services/Traders#The_KTrader_Query_Language
144  */
145  KPluginInfo::List query(const QString &subDirectory, const QString &serviceType = QString(),
146  const QString &constraint = QString());
147 
148  /**
149  * This is a static pointer to the KPluginTrader singleton.
150  *
151  * You will need to use this to access the KPluginTrader functionality since the
152  * constructors are protected.
153  *
154  * @return Static KPluginTrader instance
155  */
156  static KPluginTrader *self();
157 
158  /**
159  * Get a plugin from a trader query
160  *
161  * Example:
162  * \code
163  * KMyAppPlugin* plugin = KPluginTrader::createInstanceFromQuery<KMyAppPlugin>(subDirectory, serviceType, QString(), parentObject );
164  * if ( plugin ) {
165  * ....
166  * }
167  * \endcode
168  *
169  * @param subDirectory The subdirectory under the Qt plugin pathes to search in
170  * @param serviceType The type of service for which to find a plugin
171  * @param constraint An optional constraint to pass to the trader (see KTrader)
172  * @param parent The parent object for the part itself
173  * @param args A list of arguments passed to the service component
174  * @param error The string passed here will contain an error description.
175  * @return A pointer to the newly created object or a null pointer if the
176  * factory was unable to create an object of the given type.
177  */
178  template <class T>
179  static T *createInstanceFromQuery(const QString &subDirectory,
180  const QString &serviceType = QString(),
181  const QString &constraint = QString(),
182  QObject *parent = nullptr,
183  const QVariantList &args = QVariantList(),
184  QString *error = nullptr)
185  {
186  return createInstanceFromQuery<T>(subDirectory, serviceType, constraint, parent, nullptr, args, error);
187  }
188 
189  /**
190  * Get a plugin from a trader query
191  *
192  * This method works like
193  * createInstanceFromQuery(const QString&, const QString& ,const QString&, QObject*,
194  * const QVariantList&, QString*),
195  * but you can specify an additional parent widget. This is important for a KPart, for example.
196  *
197  * @param subDirectory The subdirectory under the Qt plugin pathes to search in
198  * @param serviceType the type of service for which to find a plugin
199  * @param constraint an optional constraint to pass to the trader (see KTrader)
200  * @param parent the parent object for the part itself
201  * @param parentWidget the parent widget for the plugin
202  * @param args A list of arguments passed to the service component
203  * @param error The string passed here will contain an error description.
204  * @return A pointer to the newly created object or a null pointer if the
205  * factory was unable to create an object of the given type.
206  */
207  template <class T>
208  static T *createInstanceFromQuery(const QString &subDirectory,
209  const QString &serviceType,
210  const QString &constraint,
211  QObject *parent,
212  QWidget *parentWidget,
213  const QVariantList &args = QVariantList(),
214  QString *error = nullptr)
215  {
216  Q_UNUSED(parentWidget)
217  Q_UNUSED(args)
218  if (error) {
219  error->clear();
220  }
221  const KPluginInfo::List offers = self()->query(subDirectory, serviceType, constraint);
222 
223  for (const KPluginInfo &info : offers) {
224  KPluginLoader loader(info.libraryPath());
225  const QVariantList argsWithMetaData = QVariantList() << loader.metaData().toVariantMap();
226  KPluginFactory *factory = loader.factory();
227  if (factory) {
228  T *component = factory->create<T>(parent, argsWithMetaData);
229  if (component) {
230  return component;
231  }
232  }
233  }
234  if (error && error->isEmpty()) {
235  *error = QCoreApplication::translate("", "No service matching the requirements was found");
236  }
237  return nullptr;
238  }
239 
240  static void applyConstraints(KPluginInfo::List &lst,
241  const QString &constraint);
242 
243 private:
244  /**
245  * @internal
246  */
247  KPluginTrader();
248 
249  // disallow copy ctor and assignment operator
250  KPluginTrader(const KPluginTrader &other);
251  KPluginTrader &operator=(const KPluginTrader &rhs);
252 
253  KPluginTraderPrivate *const d;
254 };
255 
256 #endif
Information about a plugin.
Definition: kplugininfo.h:32
A trader interface which provides a way to query specific subdirectories in the Qt plugin paths for p...
Definition: kplugintrader.h:78
T * create(QObject *parent=nullptr, const QVariantList &args=QVariantList())
QVariantMap toVariantMap() const const
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
static T * createInstanceFromQuery(const QString &subDirectory, const QString &serviceType, const QString &constraint, QObject *parent, QWidget *parentWidget, const QVariantList &args=QVariantList(), QString *error=nullptr)
Get a plugin from a trader query.
QJsonObject metaData() const
static T * createInstanceFromQuery(const QString &subDirectory, const QString &serviceType=QString(), const QString &constraint=QString(), QObject *parent=nullptr, const QVariantList &args=QVariantList(), QString *error=nullptr)
Get a plugin from a trader query.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Mar 2 2021 23:45:00 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.