1 | /* |
2 | * Copyright 2006-2007 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_DATAENGINE_H |
21 | #define PLASMA_DATAENGINE_H |
22 | |
23 | #include <QtCore/QHash> |
24 | #include <QtCore/QObject> |
25 | #include <QtCore/QStringList> |
26 | |
27 | #include <kgenericfactory.h> |
28 | #include <kservice.h> |
29 | |
30 | #include <plasma/version.h> |
31 | #include <plasma/plasma.h> |
32 | #include <plasma/service.h> |
33 | |
34 | namespace Plasma |
35 | { |
36 | |
37 | class DataContainer; |
38 | class DataEngineScript; |
39 | class Package; |
40 | class Service; |
41 | class DataEnginePrivate; |
42 | |
43 | /** |
44 | * @class DataEngine plasma/dataengine.h <Plasma/DataEngine> |
45 | * |
46 | * @short Data provider for plasmoids (Plasma plugins) |
47 | * |
48 | * This is the base class for DataEngines, which provide access to bodies of |
49 | * data via a common and consistent interface. The common use of a DataEngine |
50 | * is to provide data to a widget for display. This allows a user interface |
51 | * element to show all sorts of data: as long as there is a DataEngine, the |
52 | * data is retrievable. |
53 | * |
54 | * DataEngines are loaded as plugins on demand and provide zero, one or more |
55 | * data sources which are identified by name. For instance, a network |
56 | * DataEngine might provide a data source for each network interface. |
57 | **/ |
58 | class PLASMA_EXPORT DataEngine : public QObject |
59 | { |
60 | Q_OBJECT |
61 | Q_PROPERTY(QStringList sources READ sources) |
62 | Q_PROPERTY(bool valid READ isValid) |
63 | Q_PROPERTY(QString icon READ icon WRITE setIcon) |
64 | Q_PROPERTY(QString name READ name) |
65 | |
66 | public: |
67 | typedef QHash<QString, DataEngine*> Dict; |
68 | typedef QHash<QString, QVariant> Data; |
69 | typedef QHashIterator<QString, QVariant> DataIterator; |
70 | typedef QHash<QString, DataContainer*> SourceDict; |
71 | |
72 | /** |
73 | * Constructor. |
74 | * |
75 | * @param parent The parent object. |
76 | * @param service pointer to the service that describes the engine |
77 | **/ |
78 | explicit DataEngine(QObject *parent = 0, KService::Ptr service = KService::Ptr(0)); |
79 | DataEngine(QObject *parent, const QVariantList &args); |
80 | ~DataEngine(); |
81 | |
82 | /** |
83 | * This method is called when the DataEngine is started. When this |
84 | * method is called the DataEngine is fully constructed and ready to be |
85 | * used. This method should be reimplemented by DataEngine subclasses |
86 | * which need to perform a startup routine. |
87 | * |
88 | * The default implementation does nothing. Reimplementations in |
89 | * subclasses don't need to call this one. |
90 | **/ |
91 | virtual void init(); |
92 | |
93 | /** |
94 | * @return a list of all the data sources available via this DataEngine |
95 | * Whether these sources are currently available (which is what |
96 | * the default implementation provides) or not is up to the |
97 | * DataEngine to decide. |
98 | **/ |
99 | virtual QStringList sources() const; |
100 | |
101 | /** |
102 | * @param source the source to target the Service at |
103 | * @return a Service that has the source as a destination. The service |
104 | * is parented to the DataEngine, but should be deleted by the |
105 | * caller when finished with it |
106 | */ |
107 | Q_INVOKABLE virtual Service *serviceForSource(const QString &source); |
108 | |
109 | /** |
110 | * Returns the engine name for the DataEngine |
111 | */ |
112 | QString name() const; |
113 | |
114 | /** |
115 | * Connects a source to an object for data updates. The object must |
116 | * have a slot with the following signature: |
117 | * |
118 | * dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) |
119 | * |
120 | * The data is a QHash of QVariants keyed by QString names, allowing |
121 | * one data source to provide sets of related data. |
122 | * |
123 | * @param source the name of the data source |
124 | * @param visualization the object to connect the data source to |
125 | * @param pollingInterval the frequency, in milliseconds, with which to check for updates; |
126 | * a value of 0 (the default) means to update only |
127 | * when there is new data spontaneously generated |
128 | * (e.g. by the engine); any other value results in |
129 | * periodic updates from this source. This value is |
130 | * per-visualization and can be handy for items that require |
131 | * constant updates such as scrolling graphs or clocks. |
132 | * If the data has not changed, no update will be sent. |
133 | * @param intervalAlignment the number of ms to align the interval to |
134 | **/ |
135 | Q_INVOKABLE void connectSource( |
136 | const QString &source, QObject *visualization, |
137 | uint pollingInterval = 0, |
138 | Plasma::IntervalAlignment intervalAlignment = NoAlignment) const; |
139 | |
140 | /** |
141 | * Connects all currently existing sources to an object for data updates. |
142 | * The object must have a slot with the following signature: |
143 | * |
144 | * SLOT(dataUpdated(QString,Plasma::DataEngine::Data)) |
145 | * |
146 | * The data is a QHash of QVariants keyed by QString names, allowing |
147 | * one data source to provide sets of related data. |
148 | * |
149 | * This method may be called multiple times for the same visualization |
150 | * without side-effects. This can be useful to change the pollingInterval. |
151 | * |
152 | * Note that this method does not automatically connect sources that |
153 | * may appear later on. Connecting and responding to the sourceAdded signal |
154 | * is still required to achieve that. |
155 | * |
156 | * @param visualization the object to connect the data source to |
157 | * @param pollingInterval the frequency, in milliseconds, with which to check for updates; |
158 | * a value of 0 (the default) means to update only |
159 | * when there is new data spontaneously generated |
160 | * (e.g. by the engine); any other value results in |
161 | * periodic updates from this source. This value is |
162 | * per-visualization and can be handy for items that require |
163 | * constant updates such as scrolling graphs or clocks. |
164 | * If the data has not changed, no update will be sent. |
165 | * @param intervalAlignment the number of ms to align the interval to |
166 | **/ |
167 | Q_INVOKABLE void connectAllSources(QObject *visualization, uint pollingInterval = 0, |
168 | Plasma::IntervalAlignment intervalAlignment = |
169 | NoAlignment) const; |
170 | |
171 | /** |
172 | * Disconnects a source from an object that was receiving data updates. |
173 | * |
174 | * @param source the name of the data source |
175 | * @param visualization the object to connect the data source to |
176 | **/ |
177 | Q_INVOKABLE void disconnectSource(const QString &source, QObject *visualization) const; |
178 | |
179 | /** |
180 | * Retrieves a pointer to the DataContainer for a given source. This method |
181 | * should not be used if possible. An exception is for script engines that |
182 | * can not provide a QMetaObject as required by connectSource for the initial |
183 | * call to dataUpdated. Using this method, such engines can provide their own |
184 | * connectSource API. |
185 | * |
186 | * @param source the name of the source. |
187 | * @return pointer to a DataContainer, or zero on failure |
188 | **/ |
189 | Q_INVOKABLE DataContainer *containerForSource(const QString &source); |
190 | |
191 | /** |
192 | * Gets the Data associated with a data source. |
193 | * |
194 | * The data is a QHash of QVariants keyed by QString names, allowing |
195 | * one data source to provide sets of related data. |
196 | * |
197 | * @param source the data source to retrieve the data for |
198 | * @return the Data associated with the source; if the source doesn't |
199 | * exist an empty data set is returned |
200 | **/ |
201 | Q_INVOKABLE DataEngine::Data query(const QString &source) const; |
202 | |
203 | /** |
204 | * Returns true if this engine is valid, otherwise returns false |
205 | * |
206 | * @return true if the engine is valid |
207 | **/ |
208 | bool isValid() const; |
209 | |
210 | /** |
211 | * Returns true if the data engine is empty, which is to say that it has no |
212 | * data sources currently. |
213 | * |
214 | * @return true if the engine has no sources currently |
215 | */ |
216 | bool isEmpty() const; |
217 | |
218 | /** |
219 | * Returns the maximum number of sources this DataEngine will have |
220 | * at any given time. |
221 | * |
222 | * @return the maximum number of sources; zero means no limit. |
223 | */ |
224 | uint maxSourceCount() const; |
225 | |
226 | /** |
227 | * @return the name of the icon for this data engine; and empty string |
228 | * is returned if there is no associated icon. |
229 | **/ |
230 | QString icon() const; |
231 | |
232 | /** |
233 | * Accessor for the associated Package object if any. |
234 | * |
235 | * @return the Package object, or 0 if none |
236 | **/ |
237 | const Package *package() const; |
238 | |
239 | /** |
240 | * @return the plugin name for the applet |
241 | */ |
242 | QString pluginName() const; |
243 | |
244 | /** |
245 | * Initializes and returns a new service from the name that was set |
246 | * with setDefaultService. (service name is set internally). Remember to dispose |
247 | * of the Service* when you are finished with it (even if a parent is passed) |
248 | * A DataEngine* is sent to the created service via the QVariantList arguments. |
249 | * |
250 | * @see setDefaultService |
251 | * @param the parent of the object, if any, for the returned service |
252 | * @return the newly created service |
253 | * @since 4.5 |
254 | */ |
255 | Q_INVOKABLE Service* createDefaultService(QObject *parent = 0); |
256 | |
257 | Q_SIGNALS: |
258 | /** |
259 | * Emitted when a new data source is created |
260 | * |
261 | * Note that you do not need to emit this yourself unless |
262 | * you are reimplementing sources() and want to advertise |
263 | * that a new source is available (but hasn't been created |
264 | * yet). |
265 | * |
266 | * @param source the name of the new data source |
267 | **/ |
268 | void sourceAdded(const QString &source); |
269 | |
270 | /** |
271 | * Emitted when a data source is removed. |
272 | * |
273 | * Note that you do not need to emit this yourself unless |
274 | * you have reimplemented sources() and want to signal that |
275 | * a source that was available but was never created is no |
276 | * longer available. |
277 | * |
278 | * @param source the name of the data source that was removed |
279 | **/ |
280 | void sourceRemoved(const QString &source); |
281 | |
282 | protected: |
283 | /** |
284 | * When a source that does not currently exist is requested by the |
285 | * consumer, this method is called to give the DataEngine the |
286 | * opportunity to create one. |
287 | * |
288 | * The name of the data source (e.g. the source parameter passed into |
289 | * setData) must be the same as the name passed to sourceRequestEvent |
290 | * otherwise the requesting visualization may not receive notice of a |
291 | * data update. |
292 | * |
293 | * If the source can not be populated with data immediately (e.g. due to |
294 | * an asynchronous data acquisition method such as an HTTP request) |
295 | * the source must still be created, even if it is empty. This can |
296 | * be accomplished in these cases with the follow line: |
297 | * |
298 | * setData(name, DataEngine::Data()); |
299 | * |
300 | * @param source the name of the source that has been requested |
301 | * @return true if a DataContainer was set up, false otherwise |
302 | */ |
303 | virtual bool sourceRequestEvent(const QString &source); |
304 | |
305 | /** |
306 | * Called by internal updating mechanisms to trigger the engine |
307 | * to refresh the data contained in a given source. Reimplement this |
308 | * method when using facilities such as setPollingInterval. |
309 | * @see setPollingInterval |
310 | * |
311 | * @param source the name of the source that should be updated |
312 | * @return true if the data was changed, or false if there was no |
313 | * change or if the change will occur later |
314 | **/ |
315 | virtual bool updateSourceEvent(const QString &source); |
316 | |
317 | /** |
318 | * Sets a value for a data source. If the source |
319 | * doesn't exist then it is created. |
320 | * |
321 | * @param source the name of the data source |
322 | * @param value the data to associated with the source |
323 | **/ |
324 | void setData(const QString &source, const QVariant &value); |
325 | |
326 | /** |
327 | * Sets a value for a data source. If the source |
328 | * doesn't exist then it is created. |
329 | * |
330 | * @param source the name of the data source |
331 | * @param key the key to use for the data |
332 | * @param value the data to associated with the source |
333 | **/ |
334 | void setData(const QString &source, const QString &key, const QVariant &value); |
335 | |
336 | /** |
337 | * Adds a set of data to a data source. If the source |
338 | * doesn't exist then it is created. |
339 | * |
340 | * @param source the name of the data source |
341 | * @param data the data to add to the source |
342 | **/ |
343 | void setData(const QString &source, const Data &data); |
344 | |
345 | /** |
346 | * Removes all the data associated with a data source. |
347 | * |
348 | * @param source the name of the data source |
349 | **/ |
350 | void removeAllData(const QString &source); |
351 | |
352 | /** |
353 | * Removes a data entry from a source |
354 | * |
355 | * @param source the name of the data source |
356 | * @param key the data entry to remove |
357 | **/ |
358 | void removeData(const QString &source, const QString &key); |
359 | |
360 | /** |
361 | * Adds an already constructed data source. The DataEngine takes |
362 | * ownership of the DataContainer object. The objectName of the source |
363 | * is used for the source name. |
364 | * |
365 | * @param source the DataContainer to add to the DataEngine |
366 | **/ |
367 | void addSource(DataContainer *source); |
368 | |
369 | /** |
370 | * Sets an upper limit on the number of data sources to keep in this engine. |
371 | * If the limit is exceeded, then the oldest data source, as defined by last |
372 | * update, is dropped. |
373 | * |
374 | * @param limit the maximum number of sources to keep active |
375 | **/ |
376 | void setMaxSourceCount(uint limit); |
377 | |
378 | /** |
379 | * Sets the minimum amount of time, in milliseconds, that must pass between |
380 | * successive updates of data. This can help prevent too many updates happening |
381 | * due to multiple update requests coming in, which can be useful for |
382 | * expensive (time- or resource-wise) update mechanisms. |
383 | * |
384 | * The default minimumPollingInterval is -1, or "never perform automatic updates" |
385 | * |
386 | * @param minimumMs the minimum time lapse, in milliseconds, between updates. |
387 | * A value less than 0 means to never perform automatic updates, |
388 | * a value of 0 means update immediately on every update request, |
389 | * a value >0 will result in a minimum time lapse being enforced. |
390 | **/ |
391 | void setMinimumPollingInterval(int minimumMs); |
392 | |
393 | /** |
394 | * @return the minimum time between updates. @see setMinimumPollingInterval |
395 | **/ |
396 | int minimumPollingInterval() const; |
397 | |
398 | /** |
399 | * Sets up an internal update tick for all data sources. On every update, |
400 | * updateSourceEvent will be called for each applicable source. |
401 | * @see updateSourceEvent |
402 | * |
403 | * @param frequency the time, in milliseconds, between updates. A value of 0 |
404 | * will stop internally triggered updates. |
405 | **/ |
406 | void setPollingInterval(uint frequency); |
407 | |
408 | /** |
409 | * Removes all data sources |
410 | **/ |
411 | void removeAllSources(); |
412 | |
413 | /** |
414 | * Sets whether or not this engine is valid, e.g. can be used. |
415 | * In practice, only the internal fall-back engine, the NullEngine |
416 | * should have need for this. |
417 | * |
418 | * @param valid whether or not the engine is valid |
419 | **/ |
420 | void setValid(bool valid); |
421 | |
422 | /** |
423 | * @return the list of active DataContainers. |
424 | */ |
425 | SourceDict containerDict() const; |
426 | |
427 | /** |
428 | * Reimplemented from QObject |
429 | **/ |
430 | void timerEvent(QTimerEvent *event); |
431 | |
432 | /** |
433 | * Sets the engine name for the DataEngine |
434 | */ |
435 | void setName(const QString &name); |
436 | |
437 | /** |
438 | * Sets the icon for this data engine |
439 | **/ |
440 | void setIcon(const QString &icon); |
441 | |
442 | /** |
443 | * Should be set if there will be 1 main service. |
444 | * This saves any users of this DataEngine from having to know the service name to load. |
445 | * It is not created until createDefaultService is called. |
446 | * |
447 | * @code |
448 | * DataEngine *engine = dataEngine("foo"); |
449 | * Service *service = engine->createDefaultService(this); |
450 | * @endcode |
451 | * |
452 | * @see createDefaultService |
453 | * @param serviceName the name of the service to load (plugin name) |
454 | * @since 4.5 |
455 | */ |
456 | void setDefaultService(const QString &serviceName); |
457 | |
458 | /** |
459 | * Sets a source to be stored for easy retrieval |
460 | * when the real source of the data (usually a network connection) |
461 | * is unavailable. |
462 | * @param source the name of the source |
463 | * @param store if source should be stored |
464 | * @since 4.6 |
465 | */ |
466 | void setStorageEnabled(const QString &source, bool store); |
467 | |
468 | protected Q_SLOTS: |
469 | /** |
470 | * Call this method when you call setData directly on a DataContainer instead |
471 | * of using the DataEngine::setData methods. |
472 | * If this method is not called, no dataUpdated(..) signals will be emitted! |
473 | */ |
474 | void scheduleSourcesUpdated(); |
475 | |
476 | /** |
477 | * Removes a data source. |
478 | * @param source the name of the data source to remove |
479 | **/ |
480 | void removeSource(const QString &source); |
481 | |
482 | /** |
483 | * Immediately updates all existing sources when called |
484 | */ |
485 | void updateAllSources(); |
486 | |
487 | /** |
488 | * Forces an immediate update to all connected sources, even those with |
489 | * timeouts that haven't yet expired. This should _only_ be used when |
490 | * there was no data available, e.g. due to network non-availability, |
491 | * and then it becomes available. Normal changes in data values due to |
492 | * calls to updateSource or in the natural progression of the monitored |
493 | * object (e.g. CPU heat) should not result in a call to this method! |
494 | * |
495 | * @since 4.4 |
496 | */ |
497 | void forceImmediateUpdateOfAllVisualizations(); |
498 | |
499 | private: |
500 | friend class DataEnginePrivate; |
501 | friend class DataEngineScript; |
502 | friend class DataEngineManager; |
503 | friend class PlasmoidServiceJob; |
504 | friend class NullEngine; |
505 | |
506 | Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source)) |
507 | Q_PRIVATE_SLOT(d, void sourceDestroyed(QObject *object)) |
508 | |
509 | DataEnginePrivate *const d; |
510 | }; |
511 | |
512 | } // Plasma namespace |
513 | |
514 | /** |
515 | * Register a data engine when it is contained in a loadable module |
516 | */ |
517 | #define K_EXPORT_PLASMA_DATAENGINE(libname, classname) \ |
518 | K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \ |
519 | K_EXPORT_PLUGIN(factory("plasma_engine_" #libname)) \ |
520 | K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) |
521 | |
522 | Q_DECLARE_METATYPE(Plasma::DataEngine*) |
523 | |
524 | #endif // multiple inclusion guard |
525 | |