1/*
2 * Copyright 2008 Aaron Seigo <aseigo@kde.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#ifndef PLASMA_SERVICE_H
21#define PLASMA_SERVICE_H
22
23#include <QtCore/QMap>
24#include <QtCore/QObject>
25#include <QtCore/QVariant>
26
27#include <kconfiggroup.h>
28
29#include <plasma/plasma_export.h>
30#include <plasma/plasma.h>
31#include "packagemetadata.h"
32
33class QGraphicsObject;
34class QIODevice;
35class QWidget;
36
37namespace Plasma
38{
39
40class ServiceJob;
41class ServicePrivate;
42
43/**
44 * @class Service plasma/service.h <Plasma/Service>
45 *
46 * @short This class provides a generic API for write access to settings or services.
47 *
48 * Plasma::Service allows interaction with a "destination", the definition of which
49 * depends on the Service itself. For a network settings Service this might be a
50 * profile name ("Home", "Office", "Road Warrior") while a web based Service this
51 * might be a username ("aseigo", "stranger65").
52 *
53 * A Service provides one or more operations, each of which provides some sort
54 * of interaction with the destination. Operations are described using config
55 * XML which is used to create a KConfig object with one group per operation.
56 * The group names are used as the operation names, and the defined items in
57 * the group are the parameters available to be set when using that operation.
58 *
59 * A service is started with a KConfigGroup (representing a ready to be serviced
60 * operation) and automatically deletes itself after completion and signaling
61 * success or failure. See KJob for more information on this part of the process.
62 *
63 * Services may either be loaded "stand alone" from plugins, or from a DataEngine
64 * by passing in a source name to be used as the destination.
65 *
66 * Sample use might look like:
67 *
68 * @code
69 * Plasma::DataEngine *twitter = dataEngine("twitter");
70 * Plasma::Service *service = twitter.serviceForSource("aseigo");
71 * KConfigGroup op = service->operationDescription("update");
72 * op.writeEntry("tweet", "Hacking on plasma!");
73 * Plasma::ServiceJob *job = service->startOperationCall(op);
74 * connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobCompeted()));
75 * @endcode
76 *
77 * Please remember, the service needs to be deleted when it will no longer be
78 * used. This can be done manually or by these (perhaps easier) alternatives:
79 *
80 * If it is needed throughout the lifetime of the object:
81 * @code
82 * service->setParent(this);
83 * @endcode
84 *
85 * If the service will not be used after just one operation call, use:
86 * @code
87 * connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater()));
88 * @endcode
89 *
90 */
91class PLASMA_EXPORT Service : public QObject
92{
93 Q_OBJECT
94 Q_DECLARE_PRIVATE(Service)
95 Q_PROPERTY(QString destination READ destination WRITE setDestination)
96 Q_PROPERTY(QStringList operationNames READ operationNames)
97 Q_PROPERTY(QString name READ name)
98
99public:
100 /**
101 * Destructor
102 */
103 ~Service();
104
105 /**
106 * Used to load a given service from a plugin.
107 *
108 * @param name the plugin name of the service to load
109 * @param args a list of arguments to supply to the service plugin when loading it
110 * @param parent the parent object, if any, for the service
111 *
112 * @return a Service object, guaranteed to be not null.
113 * @since 4.5
114 */
115 static Service *load(const QString &name, const QVariantList &args, QObject *parent = 0);
116
117 /**
118 * Used to load a given service from a plugin.
119 *
120 * @param name the plugin name of the service to load
121 * @param parent the parent object, if any, for the service
122 *
123 * @return a Service object, guaranteed to be not null.
124 */
125 static Service *load(const QString &name, QObject *parent = 0);
126
127 /**
128 * Used to access a service from an url. Always check for the signal serviceReady() that fires
129 * when this service is actually ready for use.
130 */
131 static Service *access(const KUrl &url, QObject *parent = 0);
132
133 /**
134 * Sets the destination for this Service to operate on
135 *
136 * @param destination specific to each Service, this sets which
137 * target or address for ServiceJobs to operate on
138 */
139 Q_INVOKABLE void setDestination(const QString &destination);
140
141 /**
142 * @return the target destination, if any, that this service is associated with
143 */
144 Q_INVOKABLE QString destination() const;
145
146 /**
147 * @return the possible operations for this profile
148 */
149 Q_INVOKABLE QStringList operationNames() const;
150
151 /**
152 * Retrieves the parameters for a given operation
153 *
154 * @param operationName the operation to retrieve parameters for
155 * @return KConfigGroup containing the parameters
156 */
157 Q_INVOKABLE KConfigGroup operationDescription(const QString &operationName);
158
159 /**
160 * Called to create a ServiceJob which is associated with a given
161 * operation and parameter set.
162 *
163 * @return a started ServiceJob; the consumer may connect to relevant
164 * signals before returning to the event loop
165 */
166 Q_INVOKABLE ServiceJob *startOperationCall(const KConfigGroup &description, QObject *parent = 0);
167
168 /**
169 * Query to find if an operation is enabled or not.
170 *
171 * @param operation the name of the operation to check
172 * @return true if the operation is enabled, false otherwise
173 */
174 Q_INVOKABLE bool isOperationEnabled(const QString &operation) const;
175
176 /**
177 * The name of this service
178 */
179 Q_INVOKABLE QString name() const;
180
181 /**
182 * Assoicates a widget with an operation, which allows the service to
183 * automatically manage, for example, the enabled state of a widget.
184 *
185 * This will remove any previous associations the widget had with
186 * operations on this engine.
187 *
188 * @param widget the QWidget to associate with the service
189 * @param operation the operation to associate the widget with
190 */
191 Q_INVOKABLE void associateWidget(QWidget *widget, const QString &operation);
192
193 /**
194 * Disassociates a widget if it has been associated with an operation
195 * on this service.
196 *
197 * This will not change the enabled state of the widget.
198 *
199 * @param widget the QWidget to disassociate.
200 */
201 Q_INVOKABLE void disassociateWidget(QWidget *widget);
202
203 /**
204 * This method only exists to maintain binary compatibility.
205 *
206 * @see associateItem
207 */
208 Q_INVOKABLE void associateWidget(QGraphicsWidget *widget, const QString &operation);
209
210 /**
211 * This method only exists to maintain binary compatibility.
212 *
213 * @see disassociateItem
214 */
215 Q_INVOKABLE void disassociateWidget(QGraphicsWidget *widget);
216
217 /**
218 * Associates a graphics item with an operation, which allows the service to
219 * automatically manage, for example, the enabled state of the item.
220 *
221 * This will remove any previous associations the item had with
222 * operations on this engine.
223 *
224 * @param item the QGraphicsObject to associate with the service
225 * @param operation the operation to associate the item with
226 */
227 Q_INVOKABLE void associateItem(QGraphicsObject *item, const QString &operation);
228
229 /**
230 * Disassociates a graphics item if it has been associated with an operation
231 * on this service.
232 *
233 * This will not change the enabled state of the item.
234 *
235 * @param widget the QGraphicsItem to disassociate.
236 */
237 Q_INVOKABLE void disassociateItem(QGraphicsObject *widget);
238
239 /**
240 * @return a parameter map for the given description
241 * @param description the configuration values to turn into the parameter map
242 * @since 4.4
243 */
244 Q_INVOKABLE QMap<QString, QVariant> parametersFromDescription(const KConfigGroup &description);
245
246Q_SIGNALS:
247 /**
248 * Emitted when a job associated with this Service completes its task
249 */
250 void finished(Plasma::ServiceJob *job);
251
252 /**
253 * Emitted when the Service's operations change. For example, a
254 * media player service may change what operations are available
255 * in response to the state of the player.
256 */
257 void operationsChanged();
258
259 /**
260 * Emitted when this service is ready for use
261 */
262 void serviceReady(Plasma::Service *service);
263
264protected:
265 /**
266 * Default constructor
267 *
268 * @param parent the parent object for this service
269 */
270 explicit Service(QObject *parent = 0);
271
272 /**
273 * Constructor for plugin loading
274 */
275 Service(QObject *parent, const QVariantList &args);
276
277 /**
278 * Called when a job should be created by the Service.
279 *
280 * @param operation which operation to work on
281 * @param parameters the parameters set by the user for the operation
282 * @return a ServiceJob that can be started and monitored by the consumer
283 */
284 virtual ServiceJob *createJob(const QString &operation,
285 QMap<QString, QVariant> &parameters) = 0;
286
287 /**
288 * By default this is based on the file in plasma/services/name.operations, but can be
289 * reimplented to use a different mechanism.
290 *
291 * It should result in a call to setOperationsScheme(QIODevice *);
292 */
293 virtual void registerOperationsScheme();
294
295 /**
296 * Sets the XML used to define the operation schema for
297 * this Service.
298 */
299 void setOperationsScheme(QIODevice *xml);
300
301 /**
302 * Sets the name of the Service; useful for Services not loaded from plugins,
303 * which use the plugin name for this.
304 *
305 * @param name the name to use for this service
306 */
307 void setName(const QString &name);
308
309 /**
310 * Enables a given service by name
311 *
312 * @param operation the name of the operation to enable or disable
313 * @param enable true if the operation should be enabld, false if disabled
314 */
315 void setOperationEnabled(const QString &operation, bool enable);
316
317private:
318 Q_PRIVATE_SLOT(d, void jobFinished(KJob *))
319 Q_PRIVATE_SLOT(d, void associatedWidgetDestroyed(QObject *))
320 Q_PRIVATE_SLOT(d, void associatedGraphicsWidgetDestroyed(QObject *))
321
322 ServicePrivate * const d;
323
324 friend class Applet;
325 friend class DataEnginePrivate;
326 friend class GetSource;
327 friend class PackagePrivate;
328 friend class ServiceProvider;
329 friend class RemoveService;
330 friend class PluginLoader;
331};
332
333} // namespace Plasma
334
335Q_DECLARE_METATYPE(Plasma::Service *)
336
337/**
338 * Register a service when it is contained in a loadable module
339 */
340#define K_EXPORT_PLASMA_SERVICE(libname, classname) \
341K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
342K_EXPORT_PLUGIN(factory("plasma_service_" #libname)) \
343K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
344
345#endif // multiple inclusion guard
346
347