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