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_DATACONTAINER_H |
21 | #define PLASMA_DATACONTAINER_H |
22 | |
23 | #include <QtCore/QHash> |
24 | #include <QtCore/QObject> |
25 | #include <QtCore/QTimer> |
26 | |
27 | #include <kjob.h> |
28 | #include <plasma/plasma_export.h> |
29 | #include <plasma/dataengine.h> |
30 | |
31 | namespace Plasma |
32 | { |
33 | |
34 | class DataContainerPrivate; |
35 | |
36 | /** |
37 | * @class DataContainer plasma/datacontainer.h <Plasma/DataContainer> |
38 | * |
39 | * @brief A set of data exported via a DataEngine |
40 | * |
41 | * Plasma::DataContainer wraps the data exported by a DataEngine |
42 | * implementation, providing a generic wrapper for the data. |
43 | * |
44 | * A DataContainer may have zero or more associated pieces of data which |
45 | * are keyed by strings. The data itself is stored as QVariants. This allows |
46 | * easy and flexible retrieval of the information associated with this object |
47 | * without writing DataContainer or DataEngine specific code in visualizations. |
48 | * |
49 | * If you are creating your own DataContainer objects (and are passing them to |
50 | * DataEngine::addSource()), you normally just need to listen to the |
51 | * updateRequested() signal (as well as any other methods you might have of |
52 | * being notified of new data) and call setData() to actually update the data. |
53 | * Then you need to either trigger the scheduleSourcesUpdated signal of the |
54 | * parent DataEngine or call checkForUpdate() on the DataContainer. |
55 | * |
56 | * You also need to set a suitable name for the source with setObjectName(). |
57 | * See DataEngine::addSource() for more information. |
58 | * |
59 | * Note that there is normally no need to subclass DataContainer, except as |
60 | * a way of encapsulating the data retrieval for a source, since all notifications |
61 | * are done via signals rather than virtual methods. |
62 | **/ |
63 | class PLASMA_EXPORT DataContainer : public QObject |
64 | { |
65 | friend class DataEngine; |
66 | friend class DataEnginePrivate; |
67 | Q_OBJECT |
68 | |
69 | public: |
70 | /** |
71 | * Constructs a default DataContainer that has no name or data |
72 | * associated with it |
73 | **/ |
74 | explicit DataContainer(QObject *parent = 0); |
75 | virtual ~DataContainer(); |
76 | |
77 | /** |
78 | * Returns the data for this DataContainer |
79 | **/ |
80 | const DataEngine::Data data() const; |
81 | |
82 | /** |
83 | * Set a value for a key. |
84 | * |
85 | * This also marks this source as needing to signal an update. |
86 | * |
87 | * If you call setData() directly on a DataContainer, you need to |
88 | * either trigger the scheduleSourcesUpdated() slot for the |
89 | * data engine it belongs to or call checkForUpdate() on the |
90 | * DataContainer. |
91 | * |
92 | * @param key a string used as the key for the data |
93 | * @param value a QVariant holding the actual data. If a invalid |
94 | * QVariant is passed in and the key currently exists in the |
95 | * data, then the data entry is removed |
96 | **/ |
97 | void setData(const QString &key, const QVariant &value); |
98 | |
99 | /** |
100 | * Removes all data currently associated with this source |
101 | * |
102 | * If you call removeAllData() on a DataContainer, you need to |
103 | * either trigger the scheduleSourcesUpdated() slot for the |
104 | * data engine it belongs to or call checkForUpdate() on the |
105 | * DataContainer. |
106 | **/ |
107 | void removeAllData(); |
108 | |
109 | /** |
110 | * @return true if the visualization is currently connected |
111 | */ |
112 | bool visualizationIsConnected(QObject *visualization) const; |
113 | |
114 | /** |
115 | * Connects an object to this DataContainer. |
116 | * |
117 | * May be called repeatedly for the same visualization without |
118 | * side effects |
119 | * |
120 | * @param visualization the object to connect to this DataContainer |
121 | * @param pollingInterval the time in milliseconds between updates |
122 | * @param alignment the clock position to align updates to |
123 | **/ |
124 | void connectVisualization(QObject *visualization, uint pollingInterval, |
125 | Plasma::IntervalAlignment alignment); |
126 | |
127 | /** |
128 | * sets this data container to be automatically stored. |
129 | * @param whether this data container should be stored |
130 | * @since 4.6 |
131 | */ |
132 | void setStorageEnabled(bool store); |
133 | |
134 | /** |
135 | * @return true if the data container has been marked for storage |
136 | * @since 4.6 |
137 | */ |
138 | bool isStorageEnabled() const; |
139 | |
140 | /** |
141 | * @return true if the data container has been updated, but not stored |
142 | */ |
143 | bool needsToBeStored() const; |
144 | |
145 | /** |
146 | * sets that the data container needs to be stored or not. |
147 | * @param whether the data container needs to be stored |
148 | */ |
149 | void setNeedsToBeStored(bool store); |
150 | |
151 | /** |
152 | * @return the DataEngine that the DataContainer is |
153 | * a child of. |
154 | */ |
155 | DataEngine* getDataEngine(); |
156 | |
157 | public Q_SLOTS: |
158 | /** |
159 | * Disconnects an object from this DataContainer. |
160 | * |
161 | * Note that if this source was created by DataEngine::sourceRequestEvent(), |
162 | * it will be deleted by DataEngine once control returns to the event loop. |
163 | **/ |
164 | void disconnectVisualization(QObject *visualization); |
165 | |
166 | /** |
167 | * Forces immediate update signals to all visualizations |
168 | * @since 4.4 |
169 | */ |
170 | void forceImmediateUpdate(); |
171 | |
172 | Q_SIGNALS: |
173 | /** |
174 | * Emitted when the data has been updated, allowing visualizations to |
175 | * reflect the new data. |
176 | * |
177 | * Note that you should not normally emit this directly. Instead, use |
178 | * checkForUpdate() or the DataEngine::scheduleSourcesUpdated() slot. |
179 | * |
180 | * @param source the objectName() of the DataContainer (and hence the name |
181 | * of the source) that updated its data |
182 | * @param data the updated data |
183 | **/ |
184 | void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data); |
185 | |
186 | /** |
187 | * Emitted when the last visualization is disconnected. |
188 | * |
189 | * Note that if this source was created by DataEngine::sourceRequestEvent(), |
190 | * it will be deleted by DataEngine once control returns to the event loop |
191 | * after this signal is emitted. |
192 | * |
193 | * @param source the name of the source that became unused |
194 | **/ |
195 | void becameUnused(const QString &source); |
196 | |
197 | /** |
198 | * Emitted when an update is requested. |
199 | * |
200 | * If a polling interval was passed connectVisualization(), this signal |
201 | * will be emitted every time the interval expires. |
202 | * |
203 | * Note that if you create your own DataContainer (and pass it to |
204 | * DataEngine::addSource()), you will need to listen to this signal |
205 | * and refresh the data when it is triggered. |
206 | * |
207 | * @param source the datacontainer the update was requested for. Useful |
208 | * for classes that update the data for several containers. |
209 | **/ |
210 | void updateRequested(DataContainer *source); |
211 | |
212 | protected: |
213 | /** |
214 | * Checks whether any data has changed and, if so, emits dataUpdated(). |
215 | **/ |
216 | void checkForUpdate(); |
217 | |
218 | /** |
219 | * Returns how long ago, in msecs, that the data in this container was last updated. |
220 | * |
221 | * This is used by DataEngine to compress updates that happen more quickly than the |
222 | * minimum polling interval by calling setNeedsUpdate() instead of calling |
223 | * updateSourceEvent() immediately. |
224 | **/ |
225 | uint timeSinceLastUpdate() const; |
226 | |
227 | /** |
228 | * Indicates that the data should be treated as dirty the next time hasUpdates() is called. |
229 | * |
230 | * This is needed for the case where updateRequested() is triggered but we don't want to |
231 | * update the data immediately because it has just been updated. The second request won't |
232 | * be fulfilled in this case, because we never updated the data and so never called |
233 | * checkForUpdate(). So we claim it needs an update anyway. |
234 | **/ |
235 | void setNeedsUpdate(bool update = true); |
236 | |
237 | protected Q_SLOTS: |
238 | /** |
239 | * Check if the DataContainer is still in use. |
240 | * |
241 | * If not the signal "becameUnused" will be emitted. |
242 | * |
243 | * Warning: The DataContainer may be invalid after calling this function, because a listener |
244 | * to becameUnused() may have deleted it. |
245 | **/ |
246 | void checkUsage(); |
247 | |
248 | /** |
249 | * @reimp from QObject |
250 | */ |
251 | void timerEvent(QTimerEvent * event); |
252 | |
253 | private: |
254 | friend class SignalRelay; |
255 | friend class DataContainerPrivate; |
256 | friend class DataEngineManager; |
257 | DataContainerPrivate *const d; |
258 | |
259 | Q_PRIVATE_SLOT(d, void storeJobFinished(KJob *job)) |
260 | Q_PRIVATE_SLOT(d, void populateFromStoredData(KJob *job)) |
261 | Q_PRIVATE_SLOT(d, void retrieve()) |
262 | }; |
263 | |
264 | } // Plasma namespace |
265 | |
266 | #endif // multiple inclusion guard |
267 | |