• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
datacontainer.cpp
Go to the documentation of this file.
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 #include "datacontainer.h"
20 #include "private/datacontainer_p.h"
21 #include "private/storage_p.h"
22 
23 #include <kdebug.h>
24 
25 #include "plasma.h"
26 
27 namespace Plasma
28 {
29 
30 DataContainer::DataContainer(QObject *parent)
31  : QObject(parent),
32  d(new DataContainerPrivate(this))
33 {
34 }
35 
36 DataContainer::~DataContainer()
37 {
38  delete d;
39 }
40 
41 const DataEngine::Data DataContainer::data() const
42 {
43  return d->data;
44 }
45 
46 void DataContainer::setData(const QString &key, const QVariant &value)
47 {
48  if (!value.isValid()) {
49  d->data.remove(key);
50  } else {
51  d->data.insert(key, value);
52  }
53 
54  d->dirty = true;
55  d->updateTs.start();
56 
57  //check if storage is enabled and if storage is needed.
58  //If it is not set to be stored,then this is the first
59  //setData() since the last time it was stored. This
60  //gives us only one singleShot timer.
61  if (isStorageEnabled() || !needsToBeStored()) {
62  d->storageTimer.start(180000, this);
63  }
64 
65  setNeedsToBeStored(true);
66 }
67 
68 void DataContainer::removeAllData()
69 {
70  if (d->data.isEmpty()) {
71  // avoid an update if we don't have any data anyways
72  return;
73  }
74 
75  d->data.clear();
76  d->dirty = true;
77  d->updateTs.start();
78 }
79 
80 bool DataContainer::visualizationIsConnected(QObject *visualization) const
81 {
82  return d->relayObjects.contains(visualization);
83 }
84 
85 void DataContainer::connectVisualization(QObject *visualization, uint pollingInterval,
86  Plasma::IntervalAlignment alignment)
87 {
88  //kDebug() << "connecting visualization" << visualization << "at interval of"
89  // << pollingInterval << "to" << objectName();
90  QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
91  bool connected = objIt != d->relayObjects.end();
92  if (connected) {
93  // this visualization is already connected. just adjust the update
94  // frequency if necessary
95  SignalRelay *relay = objIt.value();
96  if (relay) {
97  // connected to a relay
98  //kDebug() << " already connected, but to a relay";
99  if (relay->m_interval == pollingInterval) {
100  //kDebug() << " already connected to a relay of the same interval of"
101  // << pollingInterval << ", nothing to do";
102  return;
103  }
104 
105  if (relay->receiverCount() == 1) {
106  //kDebug() << " removing relay, as it is now unused";
107  d->relays.remove(relay->m_interval);
108  delete relay;
109  } else {
110  disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
111  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
112  //relay->isUnused();
113  }
114  } else if (pollingInterval < 1) {
115  // the visualization was connected already, but not to a relay
116  // and it still doesn't want to connect to a relay, so we have
117  // nothing to do!
118  //kDebug() << " already connected, nothing to do";
119  return;
120  } else {
121  disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
122  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
123  }
124  } else {
125  connect(visualization, SIGNAL(destroyed(QObject*)),
126  this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
127  }
128 
129  if (pollingInterval < 1) {
130  //kDebug() << " connecting directly";
131  d->relayObjects[visualization] = 0;
132  connect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
133  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
134  } else {
135  //kDebug() << " connecting to a relay";
136  // we only want to do an imediate update if this is not the first object to connect to us
137  // if it is the first visualization, then the source will already have been populated
138  // engine's sourceRequested method
139  bool immediateUpdate = connected || d->relayObjects.count() > 1;
140  SignalRelay *relay = d->signalRelay(this, visualization, pollingInterval,
141  alignment, immediateUpdate);
142  connect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
143  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
144  }
145 }
146 
147 void DataContainer::setStorageEnabled(bool store)
148 {
149  QTime time = QTime::currentTime();
150  qsrand((uint)time.msec());
151  d->enableStorage = store;
152  if (store) {
153  QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve()));
154  }
155 }
156 
157 bool DataContainer::isStorageEnabled() const
158 {
159  return d->enableStorage;
160 }
161 
162 bool DataContainer::needsToBeStored() const
163 {
164  return !d->isStored;
165 }
166 
167 void DataContainer::setNeedsToBeStored(bool store)
168 {
169  d->isStored = !store;
170 }
171 
172 DataEngine* DataContainer::getDataEngine()
173 {
174  QObject *o = this;
175  DataEngine *de = NULL;
176  while (de == NULL)
177  {
178  o = dynamic_cast<QObject *> (o->parent());
179  if (o == NULL) {
180  return NULL;
181  }
182  de = dynamic_cast<DataEngine *> (o);
183  }
184  return de;
185 }
186 
187 void DataContainerPrivate::store()
188 {
189  if (!q->needsToBeStored() || !q->isStorageEnabled()) {
190  return;
191  }
192 
193  DataEngine* de = q->getDataEngine();
194  if (!de) {
195  return;
196  }
197 
198  q->setNeedsToBeStored(false);
199 
200  if (!storage) {
201  storage = new Storage(q);
202  }
203 
204  KConfigGroup op = storage->operationDescription("save");
205  op.writeEntry("group", q->objectName());
206  StorageJob *job = static_cast<StorageJob *>(storage->startOperationCall(op));
207  job->setData(data);
208  storageCount++;
209  QObject::connect(job, SIGNAL(finished(KJob*)), q, SLOT(storeJobFinished(KJob*)));
210 }
211 
212 void DataContainerPrivate::storeJobFinished(KJob* )
213 {
214  --storageCount;
215  if (storageCount < 1) {
216  storage->deleteLater();
217  storage = 0;
218  }
219 }
220 
221 void DataContainerPrivate::retrieve()
222 {
223  DataEngine* de = q->getDataEngine();
224  if (de == NULL) {
225  return;
226  }
227 
228  if (!storage) {
229  storage = new Storage(q);
230  }
231 
232  KConfigGroup retrieveGroup = storage->operationDescription("retrieve");
233  retrieveGroup.writeEntry("group", q->objectName());
234  ServiceJob* retrieveJob = storage->startOperationCall(retrieveGroup);
235  QObject::connect(retrieveJob, SIGNAL(result(KJob*)), q,
236  SLOT(populateFromStoredData(KJob*)));
237 }
238 
239 void DataContainerPrivate::populateFromStoredData(KJob *job)
240 {
241  if (job->error()) {
242  return;
243  }
244 
245  StorageJob *ret = dynamic_cast<StorageJob*>(job);
246  if (!ret) {
247  return;
248  }
249 
250  // Only fill the source with old stored
251  // data if it is not already populated with new data.
252  if (data.isEmpty() && !ret->data().isEmpty()) {
253  data = ret->data();
254  dirty = true;
255  q->forceImmediateUpdate();
256  }
257 
258  KConfigGroup expireGroup = storage->operationDescription("expire");
259  //expire things older than 4 days
260  expireGroup.writeEntry("age", 345600);
261  storage->startOperationCall(expireGroup);
262 }
263 
264 void DataContainer::disconnectVisualization(QObject *visualization)
265 {
266  QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
267  disconnect(visualization, SIGNAL(destroyed(QObject*)),
268  this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
269 
270  if (objIt == d->relayObjects.end() || !objIt.value()) {
271  // it is connected directly to the DataContainer itself
272  disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
273  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
274  } else {
275  SignalRelay *relay = objIt.value();
276 
277  if (relay->receiverCount() == 1) {
278  d->relays.remove(relay->m_interval);
279  delete relay;
280  } else {
281  disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
282  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
283  }
284  }
285 
286  d->relayObjects.erase(objIt);
287  checkUsage();
288 }
289 
290 void DataContainer::checkForUpdate()
291 {
292  //kDebug() << objectName() << d->dirty;
293  if (d->dirty) {
294  emit dataUpdated(objectName(), d->data);
295 
296  foreach (SignalRelay *relay, d->relays) {
297  relay->checkQueueing();
298  }
299 
300  d->dirty = false;
301  }
302 }
303 
304 void DataContainer::forceImmediateUpdate()
305 {
306  if (d->dirty) {
307  d->dirty = false;
308  emit dataUpdated(objectName(), d->data);
309  }
310 
311  foreach (SignalRelay *relay, d->relays) {
312  relay->forceImmediateUpdate();
313  }
314 }
315 
316 uint DataContainer::timeSinceLastUpdate() const
317 {
318  //FIXME: we still assume it's been <24h
319  //and ignore possible daylight savings changes
320  return d->updateTs.elapsed();
321 }
322 
323 void DataContainer::setNeedsUpdate(bool update)
324 {
325  d->cached = update;
326 }
327 
328 void DataContainer::checkUsage()
329 {
330  if (!d->checkUsageTimer.isActive()) {
331  d->checkUsageTimer.start(10, this);
332  }
333 }
334 
335 void DataContainer::timerEvent(QTimerEvent * event)
336 {
337  if (event->timerId() == d->checkUsageTimer.timerId()) {
338  if (d->relays.count() < 1 &&
339  receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data))) < 1) {
340  // DO NOT CALL ANYTHING AFTER THIS LINE AS IT MAY GET DELETED!
341  kDebug() << objectName() << "is unused";
342  emit becameUnused(objectName());
343  }
344  d->checkUsageTimer.stop();
345  } else if (event->timerId() == d->storageTimer.timerId()) {
346  d->store();
347  d->storageTimer.stop();
348  }
349 }
350 
351 } // Plasma namespace
352 
353 #include "datacontainer.moc"
354 
Plasma::DataContainer::disconnectVisualization
void disconnectVisualization(QObject *visualization)
Disconnects an object from this DataContainer.
Definition: datacontainer.cpp:264
Plasma::DataContainer::timerEvent
void timerEvent(QTimerEvent *event)
Definition: datacontainer.cpp:335
Plasma::DataContainer::checkForUpdate
void checkForUpdate()
Checks whether any data has changed and, if so, emits dataUpdated().
Definition: datacontainer.cpp:290
Plasma::DataContainer::visualizationIsConnected
bool visualizationIsConnected(QObject *visualization) const
Definition: datacontainer.cpp:80
Plasma::DataContainer::~DataContainer
virtual ~DataContainer()
Definition: datacontainer.cpp:36
Plasma::DataEngine::Data
QHash< QString, QVariant > Data
Definition: dataengine.h:68
QObject
Plasma::DataContainer::dataUpdated
void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data)
Emitted when the data has been updated, allowing visualizations to reflect the new data...
Plasma::DataContainer::SignalRelay
friend class SignalRelay
Definition: datacontainer.h:254
Plasma::DataContainer::setNeedsToBeStored
void setNeedsToBeStored(bool store)
sets that the data container needs to be stored or not.
Definition: datacontainer.cpp:167
Plasma::DataContainer::DataContainer
DataContainer(QObject *parent=0)
Constructs a default DataContainer that has no name or data associated with it.
Definition: datacontainer.cpp:30
Plasma::DataContainer::isStorageEnabled
bool isStorageEnabled() const
Definition: datacontainer.cpp:157
Plasma::DataContainer::data
const DataEngine::Data data() const
Returns the data for this DataContainer.
Definition: datacontainer.cpp:41
Plasma::DataContainer::timeSinceLastUpdate
uint timeSinceLastUpdate() const
Returns how long ago, in msecs, that the data in this container was last updated. ...
Definition: datacontainer.cpp:316
Plasma::DataContainer::checkUsage
void checkUsage()
Check if the DataContainer is still in use.
Definition: datacontainer.cpp:328
Plasma::IntervalAlignment
IntervalAlignment
Possible timing alignments.
Definition: plasma.h:181
Plasma::DataEngine
Data provider for plasmoids (Plasma plugins)
Definition: dataengine.h:58
Plasma::DataContainer::forceImmediateUpdate
void forceImmediateUpdate()
Forces immediate update signals to all visualizations.
Definition: datacontainer.cpp:304
Plasma::DataContainer::connectVisualization
void connectVisualization(QObject *visualization, uint pollingInterval, Plasma::IntervalAlignment alignment)
Connects an object to this DataContainer.
Definition: datacontainer.cpp:85
datacontainer.h
Plasma::DataContainer::setNeedsUpdate
void setNeedsUpdate(bool update=true)
Indicates that the data should be treated as dirty the next time hasUpdates() is called.
Definition: datacontainer.cpp:323
plasma.h
Plasma::DataContainer::setData
void setData(const QString &key, const QVariant &value)
Set a value for a key.
Definition: datacontainer.cpp:46
Plasma::DataContainer::becameUnused
void becameUnused(const QString &source)
Emitted when the last visualization is disconnected.
Plasma::DataContainer::needsToBeStored
bool needsToBeStored() const
Definition: datacontainer.cpp:162
Plasma::DataContainer::setStorageEnabled
void setStorageEnabled(bool store)
sets this data container to be automatically stored.
Definition: datacontainer.cpp:147
KJob
Plasma::DataContainer::removeAllData
void removeAllData()
Removes all data currently associated with this source.
Definition: datacontainer.cpp:68
Plasma::DataContainer::getDataEngine
DataEngine * getDataEngine()
Definition: datacontainer.cpp:172
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:33 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal