1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Torben Weis <weis@kde.org>
3 Copyright (C) 2006 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19#ifndef __kservicetypetrader_h__
20#define __kservicetypetrader_h__
21
22#include "kservice.h"
23
24/**
25 * KDE's trader interface (similar to the CORBA Trader), which provides a way
26 * to query the KDE infrastructure for specific applications or components.
27 *
28 * Basically, KServiceTypeTrader provides a way for an application to query
29 * all KDE services (that is, applications, components, plugins) that match
30 * a specific set of requirements. This allows to find specific services
31 * at run-time without having to hard-code their names and/or paths.
32 *
33 * For anything relating to mimetypes (type of files), ignore KServiceTypeTrader
34 * and use KMimeTypeTrader instead.
35 *
36 * \par Example
37 *
38 * If you want to find all plugins for your application,
39 * you would define a KMyApp/Plugin servicetype, and then you can query
40 * the trader for it:
41 * \code
42 * KService::List offers =
43 * KServiceTypeTrader::self()->query("KMyApp/Plugin");
44 * \endcode
45 *
46 * You can add a constraint in the "trader query language". For instance:
47 * \code
48 * KServiceTypeTrader::self()->query("KMyApp/Plugin",
49 * "[X-KMyApp-InterfaceVersion] > 15");
50 * \endcode
51 *
52 * Please note that when including property names containing arithmetic operators like - or +, then you have
53 * to put brackets around the property name, in order to correctly separate arithmetic operations from
54 * the name. So for example a constraint expression like
55 * \code
56 * X-KMyApp-InterfaceVersion > 4 // wrong!
57 * \endcode
58 * needs to be written as
59 * \code
60 * [X-KMyApp-InterfaceVersion] > 4
61 * \endcode
62 * otherwise it could also be interpreted as
63 * Subtract the numeric value of the property "KMyApp" and "InterfaceVersion" from the
64 * property "X" and make sure it is greater than 4.\n
65 * Instead of the other meaning, make sure that the numeric value of "X-KMyApp-InterfaceVersion" is
66 * greater than 4.
67 *
68 * @see KMimeTypeTrader, KService
69 */
70class KDECORE_EXPORT KServiceTypeTrader
71{
72public:
73 /**
74 * Standard destructor
75 */
76 ~KServiceTypeTrader();
77
78 /**
79 * The main function in the KServiceTypeTrader class.
80 *
81 * It will return a list of services that match your
82 * specifications. The only required parameter is the service
83 * type. This is something like 'text/plain' or 'text/html'. The
84 * constraint parameter is used to limit the possible choices
85 * returned based on the constraints you give it.
86 *
87 * The @p constraint language is rather full. The most common
88 * keywords are AND, OR, NOT, IN, and EXIST, all used in an
89 * almost spoken-word form. An example is:
90 * \code
91 * (Type == 'Service') and (('KParts/ReadOnlyPart' in ServiceTypes) or (exist Exec))
92 * \endcode
93 *
94 * The keys used in the query (Type, ServiceType, Exec) are all
95 * fields found in the .desktop files.
96 *
97 * @param servicetype A service type like 'KMyApp/Plugin' or 'KFilePlugin'.
98 * @param constraint A constraint to limit the choices returned, QString() to
99 * get all services of the given @p servicetype
100 *
101 * @return A list of services that satisfy the query
102 * @see http://techbase.kde.org/Development/Tutorials/Services/Traders#The_KTrader_Query_Language
103 */
104 KService::List query( const QString& servicetype,
105 const QString& constraint = QString() ) const;
106
107 /**
108 * Returns all offers associated with a given servicetype, IGNORING the
109 * user preference. The sorting will be the one coming from the InitialPreference
110 * in the .desktop files, and services disabled by the user will still be listed here.
111 * This is used for "Revert to defaults" buttons in GUIs.
112 */
113 KService::List defaultOffers( const QString& serviceType,
114 const QString& constraint = QString() ) const;
115 /**
116 * Returns the preferred service for @p serviceType.
117 *
118 * @param serviceType the service type (e.g. "KMyApp/Plugin")
119 * @return the preferred service, or 0 if no service is available
120 */
121 KService::Ptr preferredService( const QString & serviceType ) const;
122
123 /**
124 * This is a static pointer to the KServiceTypeTrader singleton.
125 *
126 * You will need to use this to access the KServiceTypeTrader functionality since the
127 * constructors are protected.
128 *
129 * @return Static KServiceTypeTrader instance
130 */
131 static KServiceTypeTrader* self();
132
133 /**
134 * Get a plugin from a trader query
135 *
136 * Example:
137 * \code
138 * KMyAppPlugin* plugin = KServiceTypeTrader::createInstanceFromQuery<KMyAppPlugin>( serviceType, QString(), parentObject );
139 * if ( plugin ) {
140 * ....
141 * }
142 * \endcode
143 *
144 * @param serviceType the type of service for which to find a plugin
145 * @param constraint an optional constraint to pass to the trader (see KTrader)
146 * @param parent the parent object for the part itself
147 * @param args A list of arguments passed to the service component
148 * @param error The string passed here will contain an error description.
149 * @return A pointer to the newly created object or a null pointer if the
150 * factory was unable to create an object of the given type.
151 */
152 template <class T>
153 static T *createInstanceFromQuery(const QString &serviceType,
154 const QString &constraint = QString(), QObject *parent = 0,
155 const QVariantList &args = QVariantList(), QString *error = 0)
156 {
157 return createInstanceFromQuery<T>(serviceType, 0, parent, constraint, args, error);
158 }
159
160 /**
161 * Get a plugin from a trader query
162 *
163 * This method works like
164 * createInstanceFromQuery(const QString&, const QString&, QObject*, const QVariantList&, QString*),
165 * but you can specify an additional parent widget. This is important for
166 * a KPart, for example.
167 *
168 * @param serviceType the type of service for which to find a plugin
169 * @param parentWidget the parent widget for the plugin
170 * @param parent the parent object for the part itself
171 * @param constraint an optional constraint to pass to the trader (see KTrader)
172 * @param args A list of arguments passed to the service component
173 * @param error The string passed here will contain an error description.
174 * @return A pointer to the newly created object or a null pointer if the
175 * factory was unable to create an object of the given type.
176 */
177 template <class T>
178 static T *createInstanceFromQuery(const QString &serviceType,
179 QWidget *parentWidget, QObject *parent, const QString &constraint = QString(),
180 const QVariantList &args = QVariantList(), QString *error = 0)
181 {
182 const KService::List offers = self()->query(serviceType, constraint);
183 if (error)
184 error->clear();
185 Q_FOREACH (const KService::Ptr &ptr, offers) {
186 T *component = ptr->template createInstance<T>(parentWidget, parent, args, error);
187 if (component) {
188 return component;
189 }
190 }
191 if (error && error->isEmpty())
192 *error = i18n("No service matching the requirements was found");
193 return 0;
194 }
195
196 /**
197 * @deprecated Use
198 * createInstanceFromQuery(const QString&, const QString&, QObject*, const QVariantList&, QString*)
199 * instead
200 */
201#ifndef KDE_NO_DEPRECATED
202 template <class T>
203 static KDE_DEPRECATED T *createInstanceFromQuery(const QString &serviceType, const QString &constraint,
204 QObject *parent, const QStringList &args, int *error = 0)
205 {
206 const KService::List offers = KServiceTypeTrader::self()->query(serviceType, constraint);
207 if (offers.isEmpty()) {
208 if (error) {
209 *error = KLibLoader::ErrNoServiceFound;
210 }
211 return 0;
212 }
213
214 return KService::createInstance<T>(offers.begin(), offers.end(), parent, args, error);
215 }
216#endif
217
218
219 /**
220 * @internal (public for KMimeTypeTrader)
221 */
222 static void applyConstraints( KService::List& lst,
223 const QString& constraint );
224
225private:
226 /**
227 * @internal
228 */
229 KServiceTypeTrader();
230
231 // dissalow copy ctor and assignment operator
232 KServiceTypeTrader( const KServiceTypeTrader& other );
233 KServiceTypeTrader& operator=( const KServiceTypeTrader& rhs );
234
235 class Private;
236 Private * const d;
237};
238
239#endif
240