File indexing completed on 2023-10-01 04:11:43

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_DATACONTAINER_H
0008 #define PLASMA_DATACONTAINER_H
0009 
0010 #include <QHash>
0011 #include <QObject>
0012 #include <QTimer>
0013 
0014 #include <KJob>
0015 #include <plasma/dataengine.h>
0016 #include <plasma/plasma_export.h>
0017 
0018 class QAbstractItemModel;
0019 
0020 namespace Plasma
0021 {
0022 class DataContainerPrivate;
0023 
0024 /**
0025  * @class DataContainer plasma/datacontainer.h <Plasma/DataContainer>
0026  *
0027  * @brief A set of data exported via a DataEngine
0028  *
0029  * Plasma::DataContainer wraps the data exported by a DataEngine
0030  * implementation, providing a generic wrapper for the data.
0031  *
0032  * A DataContainer may have zero or more associated pieces of data which
0033  * are keyed by strings. The data itself is stored as QVariants. This allows
0034  * easy and flexible retrieval of the information associated with this object
0035  * without writing DataContainer or DataEngine specific code in visualizations.
0036  *
0037  * If you are creating your own DataContainer objects (and are passing them to
0038  * DataEngine::addSource()), you normally just need to listen to the
0039  * updateRequested() signal (as well as any other methods you might have of
0040  * being notified of new data) and call setData() to actually update the data.
0041  * Then you need to either trigger the scheduleSourcesUpdated signal of the
0042  * parent DataEngine or call checkForUpdate() on the DataContainer.
0043  *
0044  * You also need to set a suitable name for the source with setObjectName().
0045  * See DataEngine::addSource() for more information.
0046  *
0047  * Note that there is normally no need to subclass DataContainer, except as
0048  * a way of encapsulating the data retrieval for a source, since all notifications
0049  * are done via signals rather than virtual methods.
0050  **/
0051 class PLASMA_EXPORT DataContainer : public QObject
0052 {
0053     friend class DataEngine;
0054     friend class DataEnginePrivate;
0055     Q_OBJECT
0056 
0057 public:
0058     /**
0059      * Constructs a default DataContainer that has no name or data
0060      * associated with it
0061      **/
0062     explicit DataContainer(QObject *parent = nullptr);
0063     ~DataContainer() override;
0064 
0065     /**
0066      * Returns the data for this DataContainer
0067      **/
0068     const DataEngine::Data data() const;
0069 
0070     /**
0071      * Set a value for a key.
0072      *
0073      * This also marks this source as needing to signal an update.
0074      *
0075      * If you call setData() directly on a DataContainer, you need to
0076      * either trigger the scheduleSourcesUpdated() slot for the
0077      * data engine it belongs to or call checkForUpdate() on the
0078      * DataContainer.
0079      *
0080      * @param key a string used as the key for the data
0081      * @param value a QVariant holding the actual data. If a invalid
0082      *              QVariant is passed in and the key currently exists in the
0083      *              data, then the data entry is removed
0084      **/
0085     void setData(const QString &key, const QVariant &value);
0086 
0087     /**
0088      * Removes all data currently associated with this source
0089      *
0090      * If you call removeAllData() on a DataContainer, you need to
0091      * either trigger the scheduleSourcesUpdated() slot for the
0092      * data engine it belongs to or call checkForUpdate() on the
0093      * DataContainer.
0094      **/
0095     void removeAllData();
0096 
0097     /**
0098      * Associates a model with this DataContainer. Use this for data
0099      * that is intended to be a long list of items.
0100      *
0101      * The ownership of the model is transferred to the DataContainer,
0102      * so the model will be deleted when a new one is set or when the
0103      * DataContainer itself is deleted, so it will be deleted when there won't be any
0104      * visualization associated to this source.
0105      *
0106      * Normally you should set the model from DataEngine::setModel instead from here.
0107      *
0108      * @param model the model that will be associated with this DataContainer
0109      */
0110     void setModel(QAbstractItemModel *model);
0111 
0112     /**
0113      * @return the model owned by this DataSource
0114      */
0115     QAbstractItemModel *model();
0116 
0117     /**
0118      * @return true if the visualization is currently connected
0119      */
0120     bool visualizationIsConnected(QObject *visualization) const;
0121 
0122     /**
0123      * Connects an object to this DataContainer.
0124      *
0125      * May be called repeatedly for the same visualization without
0126      * side effects
0127      *
0128      * @param visualization the object to connect to this DataContainer
0129      * @param pollingInterval the time in milliseconds between updates
0130      * @param alignment the clock position to align updates to
0131      **/
0132     void connectVisualization(QObject *visualization, uint pollingInterval, Plasma::Types::IntervalAlignment alignment);
0133 
0134     /**
0135      * sets this data container to be automatically stored.
0136      * @param whether this data container should be stored
0137      * @since 4.6
0138      */
0139     void setStorageEnabled(bool store);
0140 
0141     /**
0142      * @return true if the data container has been marked for storage
0143      * @since 4.6
0144      */
0145     bool isStorageEnabled() const;
0146 
0147     /**
0148      * @return true if the data container has been updated, but not stored
0149      */
0150     bool needsToBeStored() const;
0151 
0152     /**
0153      * sets that the data container needs to be stored or not.
0154      * @param whether the data container needs to be stored
0155      */
0156     void setNeedsToBeStored(bool store);
0157 
0158     /**
0159      * @return the DataEngine that the DataContainer is
0160      * a child of.
0161      */
0162     DataEngine *getDataEngine();
0163 
0164     /**
0165      * @return true if one or more visualizations is connected to this DataContainer
0166      */
0167     bool isUsed() const;
0168 
0169 public Q_SLOTS:
0170     /**
0171      * Disconnects an object from this DataContainer.
0172      *
0173      * Note that if this source was created by DataEngine::sourceRequestEvent(),
0174      * it will be deleted by DataEngine once control returns to the event loop.
0175      **/
0176     void disconnectVisualization(QObject *visualization);
0177 
0178     /**
0179      * Forces immediate update signals to all visualizations
0180      * @since 4.4
0181      */
0182     void forceImmediateUpdate();
0183 
0184 Q_SIGNALS:
0185     /**
0186      * Emitted when the data has been updated, allowing visualizations to
0187      * reflect the new data.
0188      *
0189      * Note that you should not normally emit this directly.  Instead, use
0190      * checkForUpdate() or the DataEngine::scheduleSourcesUpdated() slot.
0191      *
0192      * @param source the objectName() of the DataContainer (and hence the name
0193      *               of the source) that updated its data
0194      * @param data   the updated data
0195      **/
0196     void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data);
0197 
0198     /**
0199      * A new model has been associated to this source,
0200      * visualizations can safely use it as long they are connected to this source.
0201      *
0202      * @param source the objectName() of the DataContainer (and hence the name
0203      *               of the source) that owns the model
0204      * @param model the QAbstractItemModel instance
0205      */
0206     void modelChanged(const QString &source, QAbstractItemModel *model);
0207 
0208     /**
0209      * Emitted when the last visualization is disconnected.
0210      *
0211      * Note that if this source was created by DataEngine::sourceRequestEvent(),
0212      * it will be deleted by DataEngine once control returns to the event loop
0213      * after this signal is emitted.
0214      *
0215      * @param source  the name of the source that became unused
0216      **/
0217     void becameUnused(const QString &source);
0218 
0219     /**
0220      * Emitted when an update is requested.
0221      *
0222      * If a polling interval was passed connectVisualization(), this signal
0223      * will be emitted every time the interval expires.
0224      *
0225      * Note that if you create your own DataContainer (and pass it to
0226      * DataEngine::addSource()), you will need to listen to this signal
0227      * and refresh the data when it is triggered.
0228      *
0229      * @param source  the datacontainer the update was requested for.  Useful
0230      *                for classes that update the data for several containers.
0231      **/
0232     void updateRequested(DataContainer *source);
0233 
0234 protected:
0235     /**
0236      * Checks whether any data has changed and, if so, emits dataUpdated().
0237      **/
0238     void checkForUpdate();
0239 
0240     /**
0241      * Returns how long ago, in msecs, that the data in this container was last updated.
0242      *
0243      * This is used by DataEngine to compress updates that happen more quickly than the
0244      * minimum polling interval by calling setNeedsUpdate() instead of calling
0245      * updateSourceEvent() immediately.
0246      **/
0247     uint timeSinceLastUpdate() const;
0248 
0249     /**
0250      * Indicates that the data should be treated as dirty the next time hasUpdates() is called.
0251      *
0252      * This is needed for the case where updateRequested() is triggered but we don't want to
0253      * update the data immediately because it has just been updated.  The second request won't
0254      * be fulfilled in this case, because we never updated the data and so never called
0255      * checkForUpdate().  So we claim it needs an update anyway.
0256      **/
0257     void setNeedsUpdate(bool update = true);
0258 
0259 protected Q_SLOTS:
0260     /**
0261      * @reimp from QObject
0262      */
0263     void timerEvent(QTimerEvent *event) override;
0264 
0265 private:
0266     friend class SignalRelay;
0267     friend class DataContainerPrivate;
0268     friend class DataEngineManager;
0269     DataContainerPrivate *const d;
0270 
0271     Q_PRIVATE_SLOT(d, void storeJobFinished(KJob *job))
0272     Q_PRIVATE_SLOT(d, void populateFromStoredData(KJob *job))
0273     Q_PRIVATE_SLOT(d, void retrieve())
0274 };
0275 
0276 } // Plasma namespace
0277 
0278 #endif // multiple inclusion guard