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