File indexing completed on 2023-09-24 04:14:56
0001 /* 0002 SPDX-FileCopyrightText: 2006-2007 Aaron Seigo <aseigo@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef PLASMA_DATAENGINE_H 0008 #define PLASMA_DATAENGINE_H 0009 0010 #include <QHash> 0011 #include <QObject> 0012 #include <QStringList> 0013 0014 #include <plasma/plasma_export.h> 0015 #if PLASMA_ENABLE_DEPRECATED_SINCE(5, 94) 0016 #include <KPluginInfo> 0017 #include <KService> 0018 #endif 0019 0020 #include <KPluginFactory> 0021 #include <KPluginMetaData> 0022 #include <plasma/plasma.h> 0023 #include <plasma/service.h> 0024 0025 class QAbstractItemModel; 0026 0027 namespace Plasma 0028 { 0029 class DataContainer; 0030 class DataEngineScript; 0031 class Package; 0032 class Service; 0033 class DataEnginePrivate; 0034 0035 /** 0036 * @class DataEngine plasma/dataengine.h <Plasma/DataEngine> 0037 * 0038 * @short Data provider for plasmoids (Plasma plugins) 0039 * 0040 * This is the base class for DataEngines, which provide access to bodies of 0041 * data via a common and consistent interface. The common use of a DataEngine 0042 * is to provide data to a widget for display. This allows a user interface 0043 * element to show all sorts of data: as long as there is a DataEngine, the 0044 * data is retrievable. 0045 * 0046 * DataEngines are loaded as plugins on demand and provide zero, one or more 0047 * data sources which are identified by name. For instance, a network 0048 * DataEngine might provide a data source for each network interface. 0049 **/ 0050 class PLASMA_EXPORT DataEngine : public QObject 0051 { 0052 Q_OBJECT 0053 0054 public: 0055 typedef QHash<QString, DataEngine *> Dict; 0056 typedef QMap<QString, QVariant> Data; 0057 typedef QMapIterator<QString, QVariant> DataIterator; 0058 typedef QHash<QString, DataContainer *> SourceDict; 0059 0060 #if PLASMA_ENABLE_DEPRECATED_SINCE(5, 67) 0061 /** 0062 * Constructor. 0063 * 0064 * @param parent The parent object. 0065 * @param plugin plugin info that describes the engine 0066 * 0067 * @deprecated since 5.67 0068 **/ 0069 PLASMA_DEPRECATED_VERSION(5, 67, "Use KPluginMetaData") 0070 explicit DataEngine(const KPluginInfo &plugin, QObject *parent = nullptr); 0071 #endif 0072 0073 /** 0074 * Constructor. 0075 * 0076 * @param parent The parent object. 0077 * @param plugin metadata that describes the engine 0078 * 0079 * @since 5.67 0080 */ 0081 explicit DataEngine(const KPluginMetaData &plugin, QObject *parent = nullptr); 0082 0083 explicit DataEngine(QObject *parent = nullptr, const QVariantList &args = QVariantList()); 0084 0085 ~DataEngine() override; 0086 0087 /** 0088 * @return a list of all the data sources available via this DataEngine 0089 * Whether these sources are currently available (which is what 0090 * the default implementation provides) or not is up to the 0091 * DataEngine to decide. 0092 **/ 0093 virtual QStringList sources() const; 0094 0095 /** 0096 * @param source the source to target the Service at 0097 * @return a Service that has the source as a destination. The service 0098 * is parented to the DataEngine, but should be deleted by the 0099 * caller when finished with it 0100 */ 0101 Q_INVOKABLE virtual Service *serviceForSource(const QString &source); 0102 0103 #if PLASMA_ENABLE_DEPRECATED_SINCE(5, 67) 0104 /** 0105 * @return description of the plugin that implements this DataEngine 0106 * 0107 * @deprecated since 5.67, use metadata 0108 */ 0109 PLASMA_DEPRECATED_VERSION(5, 67, "Use metadata()") 0110 KPluginInfo pluginInfo() const; 0111 #endif 0112 0113 /** 0114 * @return description of the plugin that implements this DataEngine 0115 * 0116 * @since 5.67 0117 */ 0118 KPluginMetaData metadata() const; 0119 0120 /** 0121 * Connects a source to an object for data updates. The object must 0122 * have a slot with the following signature: 0123 * @code 0124 * void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data); 0125 * @endcode 0126 * 0127 * The data is a QHash of QVariants keyed by QString names, allowing 0128 * one data source to provide sets of related data. 0129 * 0130 * @param source the name of the data source 0131 * @param visualization the object to connect the data source to 0132 * @param pollingInterval the frequency, in milliseconds, with which to check for updates; 0133 * a value of 0 (the default) means to update only 0134 * when there is new data spontaneously generated 0135 * (e.g. by the engine); any other value results in 0136 * periodic updates from this source. This value is 0137 * per-visualization and can be handy for items that require 0138 * constant updates such as scrolling graphs or clocks. 0139 * If the data has not changed, no update will be sent. 0140 * @param intervalAlignment the number of ms to align the interval to 0141 **/ 0142 Q_INVOKABLE void connectSource(const QString &source, 0143 QObject *visualization, 0144 uint pollingInterval = 0, 0145 Plasma::Types::IntervalAlignment intervalAlignment = Types::NoAlignment) const; 0146 0147 /** 0148 * Connects all currently existing sources to an object for data updates. 0149 * The object must have a slot with the following signature: 0150 * @code 0151 * void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data); 0152 * @endcode 0153 * 0154 * The data is a QHash of QVariants keyed by QString names, allowing 0155 * one data source to provide sets of related data. 0156 * 0157 * This method may be called multiple times for the same visualization 0158 * without side-effects. This can be useful to change the pollingInterval. 0159 * 0160 * Note that this method does not automatically connect sources that 0161 * may appear later on. Connecting and responding to the sourceAdded signal 0162 * is still required to achieve that. 0163 * 0164 * @param visualization the object to connect the data source to 0165 * @param pollingInterval the frequency, in milliseconds, with which to check for updates; 0166 * a value of 0 (the default) means to update only 0167 * when there is new data spontaneously generated 0168 * (e.g. by the engine); any other value results in 0169 * periodic updates from this source. This value is 0170 * per-visualization and can be handy for items that require 0171 * constant updates such as scrolling graphs or clocks. 0172 * If the data has not changed, no update will be sent. 0173 * @param intervalAlignment the number of ms to align the interval to 0174 **/ 0175 Q_INVOKABLE void 0176 connectAllSources(QObject *visualization, uint pollingInterval = 0, Plasma::Types::IntervalAlignment intervalAlignment = Types::NoAlignment) const; 0177 0178 /** 0179 * Disconnects a source from an object that was receiving data updates. 0180 * 0181 * @param source the name of the data source 0182 * @param visualization the object to connect the data source to 0183 **/ 0184 Q_INVOKABLE void disconnectSource(const QString &source, QObject *visualization) const; 0185 0186 /** 0187 * Retrieves a pointer to the DataContainer for a given source. This method 0188 * should not be used if possible. An exception is for script engines that 0189 * can not provide a QMetaObject as required by connectSource for the initial 0190 * call to dataUpdated. Using this method, such engines can provide their own 0191 * connectSource API. 0192 * 0193 * @param source the name of the source. 0194 * @return pointer to a DataContainer, or zero on failure 0195 **/ 0196 Q_INVOKABLE DataContainer *containerForSource(const QString &source); 0197 0198 /** 0199 * @return The model associated to a source if any. The ownership of the model stays with the DataContainer. 0200 * Returns 0 if there isn't any model associated or if the source doesn't exists. 0201 */ 0202 QAbstractItemModel *modelForSource(const QString &source); 0203 0204 /** 0205 * Returns true if this engine is valid, otherwise returns false 0206 * 0207 * @return true if the engine is valid 0208 **/ 0209 bool isValid() const; 0210 0211 /** 0212 * Returns true if the data engine is empty, which is to say that it has no 0213 * data sources currently. 0214 * 0215 * @return true if the engine has no sources currently 0216 */ 0217 bool isEmpty() const; 0218 0219 #if PLASMA_ENABLE_DEPRECATED_SINCE(5, 83) 0220 /** 0221 * Accessor for the associated Package object if any. 0222 * 0223 * @return the Package object, or 0 if none 0224 **/ 0225 PLASMA_DEPRECATED_VERSION(5, 83, "Use kpackage API instead") 0226 Package package() const; 0227 #endif 0228 0229 Q_SIGNALS: 0230 /** 0231 * Emitted when a new data source is created 0232 * 0233 * Note that you do not need to emit this yourself unless 0234 * you are reimplementing sources() and want to advertise 0235 * that a new source is available (but hasn't been created 0236 * yet). 0237 * 0238 * @param source the name of the new data source 0239 **/ 0240 void sourceAdded(const QString &source); 0241 0242 /** 0243 * Emitted when a data source is removed. 0244 * 0245 * Note that you do not need to emit this yourself unless 0246 * you have reimplemented sources() and want to signal that 0247 * a source that was available but was never created is no 0248 * longer available. 0249 * 0250 * @param source the name of the data source that was removed 0251 **/ 0252 void sourceRemoved(const QString &source); 0253 0254 protected: 0255 /** 0256 * When a source that does not currently exist is requested by the 0257 * consumer, this method is called to give the DataEngine the 0258 * opportunity to create one. 0259 * 0260 * The name of the data source (e.g. the source parameter passed into 0261 * setData) must be the same as the name passed to sourceRequestEvent 0262 * otherwise the requesting visualization may not receive notice of a 0263 * data update. 0264 * 0265 * If the source can not be populated with data immediately (e.g. due to 0266 * an asynchronous data acquisition method such as an HTTP request) 0267 * the source must still be created, even if it is empty. This can 0268 * be accomplished in these cases with the follow line: 0269 * 0270 * setData(name, DataEngine::Data()); 0271 * 0272 * @param source the name of the source that has been requested 0273 * @return true if a DataContainer was set up, false otherwise 0274 */ 0275 virtual bool sourceRequestEvent(const QString &source); 0276 0277 /** 0278 * Called by internal updating mechanisms to trigger the engine 0279 * to refresh the data contained in a given source. Reimplement this 0280 * method when using facilities such as setPollingInterval. 0281 * @see setPollingInterval 0282 * 0283 * @param source the name of the source that should be updated 0284 * @return true if the data was changed, or false if there was no 0285 * change or if the change will occur later 0286 **/ 0287 virtual bool updateSourceEvent(const QString &source); 0288 0289 /** 0290 * Sets a value for a data source. If the source 0291 * doesn't exist then it is created. 0292 * 0293 * @param source the name of the data source 0294 * @param value the data to associated with the source 0295 **/ 0296 void setData(const QString &source, const QVariant &value); 0297 0298 /** 0299 * Sets a value for a data source. If the source 0300 * doesn't exist then it is created. 0301 * 0302 * @param source the name of the data source 0303 * @param key the key to use for the data 0304 * @param value the data to associated with the source 0305 **/ 0306 void setData(const QString &source, const QString &key, const QVariant &value); 0307 0308 /** 0309 * Adds a set of data to a data source. If the source 0310 * doesn't exist then it is created. 0311 * 0312 * @param source the name of the data source 0313 * @param data the data to add to the source 0314 **/ 0315 void setData(const QString &source, const QVariantMap &data); 0316 0317 /** 0318 * Removes all the data associated with a data source. 0319 * 0320 * @param source the name of the data source 0321 **/ 0322 void removeAllData(const QString &source); 0323 0324 /** 0325 * Removes a data entry from a source 0326 * 0327 * @param source the name of the data source 0328 * @param key the data entry to remove 0329 **/ 0330 void removeData(const QString &source, const QString &key); 0331 0332 /** 0333 * Associates a model to a data source. If the source 0334 * doesn't exist then it is created. The source will have the key "HasModel" to easily indicate there is a model present. 0335 * 0336 * The ownership of the model is transferred to the DataContainer, 0337 * so the model will be deleted when a new one is set or when the 0338 * DataContainer itself is deleted. As the DataContainer, it will be 0339 * deleted when there won't be any 0340 * visualization associated to this source. 0341 * 0342 * @param source the name of the data source 0343 * @param model the model instance 0344 */ 0345 void setModel(const QString &source, QAbstractItemModel *model); 0346 0347 /** 0348 * Adds an already constructed data source. The DataEngine takes 0349 * ownership of the DataContainer object. The objectName of the source 0350 * is used for the source name. 0351 * 0352 * @param source the DataContainer to add to the DataEngine 0353 **/ 0354 void addSource(DataContainer *source); 0355 0356 /** 0357 * Sets the minimum amount of time, in milliseconds, that must pass between 0358 * successive updates of data. This can help prevent too many updates happening 0359 * due to multiple update requests coming in, which can be useful for 0360 * expensive (time- or resource-wise) update mechanisms. 0361 * 0362 * The default minimumPollingInterval is -1, or "never perform automatic updates" 0363 * 0364 * @param minimumMs the minimum time lapse, in milliseconds, between updates. 0365 * A value less than 0 means to never perform automatic updates, 0366 * a value of 0 means update immediately on every update request, 0367 * a value >0 will result in a minimum time lapse being enforced. 0368 **/ 0369 void setMinimumPollingInterval(int minimumMs); 0370 0371 /** 0372 * @return the minimum time between updates. @see setMinimumPollingInterval 0373 **/ 0374 int minimumPollingInterval() const; 0375 0376 /** 0377 * Sets up an internal update tick for all data sources. On every update, 0378 * updateSourceEvent will be called for each applicable source. 0379 * @see updateSourceEvent 0380 * 0381 * @param frequency the time, in milliseconds, between updates. A value of 0 0382 * will stop internally triggered updates. 0383 **/ 0384 void setPollingInterval(uint frequency); 0385 0386 /** 0387 * Removes all data sources 0388 **/ 0389 void removeAllSources(); 0390 0391 /** 0392 * Sets whether or not this engine is valid, e.g. can be used. 0393 * In practice, only the internal fall-back engine, the NullEngine 0394 * should have need for this. 0395 * 0396 * @param valid whether or not the engine is valid 0397 **/ 0398 void setValid(bool valid); 0399 0400 /** 0401 * @return the list of active DataContainers. 0402 */ 0403 QHash<QString, DataContainer *> containerDict() const; 0404 0405 /** 0406 * Reimplemented from QObject 0407 **/ 0408 void timerEvent(QTimerEvent *event) override; 0409 0410 /** 0411 * Sets a source to be stored for easy retrieval 0412 * when the real source of the data (usually a network connection) 0413 * is unavailable. 0414 * @param source the name of the source 0415 * @param store if source should be stored 0416 * @since 4.6 0417 */ 0418 void setStorageEnabled(const QString &source, bool store); 0419 0420 protected Q_SLOTS: 0421 /** 0422 * Removes a data source. 0423 * @param source the name of the data source to remove 0424 **/ 0425 void removeSource(const QString &source); 0426 0427 /** 0428 * Immediately updates all existing sources when called 0429 */ 0430 void updateAllSources(); 0431 0432 /** 0433 * Forces an immediate update to all connected sources, even those with 0434 * timeouts that haven't yet expired. This should _only_ be used when 0435 * there was no data available, e.g. due to network non-availability, 0436 * and then it becomes available. Normal changes in data values due to 0437 * calls to updateSource or in the natural progression of the monitored 0438 * object (e.g. CPU heat) should not result in a call to this method! 0439 * 0440 * @since 4.4 0441 */ 0442 void forceImmediateUpdateOfAllVisualizations(); 0443 0444 private: 0445 friend class DataEnginePrivate; 0446 friend class DataEngineScript; 0447 friend class DataEngineManager; 0448 friend class PlasmoidServiceJob; 0449 friend class NullEngine; 0450 0451 Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source)) 0452 Q_PRIVATE_SLOT(d, void sourceDestroyed(QObject *object)) 0453 Q_PRIVATE_SLOT(d, void scheduleSourcesUpdated()) 0454 0455 DataEnginePrivate *d; 0456 }; 0457 0458 } // Plasma namespace 0459 0460 #if PLASMA_ENABLE_DEPRECATED_SINCE(5, 88) 0461 /** 0462 * Register a data engine when it is contained in a loadable module 0463 * @deprecated Since 5.88, use K_PLUGIN_CLASS_WITH_JSON instead 0464 */ 0465 /* clang-format off */ 0466 #define K_EXPORT_PLASMA_DATAENGINE(libname, classname) \ 0467 K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) 0468 0469 /// @deprecated Since 5.88, use K_PLUGIN_CLASS_WITH_JSON instead 0470 #define K_EXPORT_PLASMA_DATAENGINE_WITH_JSON(libname, classname, jsonFile) \ 0471 K_PLUGIN_FACTORY_WITH_JSON(factory, jsonFile, registerPlugin<classname>();) 0472 /* clang-format on */ 0473 #endif 0474 0475 #endif // multiple inclusion guard