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

Plasma

  • 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 = NULL;
175  DataEngine *de = NULL;
176  o = this;
177  while (de == NULL)
178  {
179  o = dynamic_cast<QObject *> (o->parent());
180  if (o == NULL) {
181  return NULL;
182  }
183  de = dynamic_cast<DataEngine *> (o);
184  }
185  return de;
186 }
187 
188 void DataContainerPrivate::store()
189 {
190  if (!q->needsToBeStored() || !q->isStorageEnabled()) {
191  return;
192  }
193 
194  DataEngine* de = q->getDataEngine();
195  if (!de) {
196  return;
197  }
198 
199  q->setNeedsToBeStored(false);
200 
201  if (!storage) {
202  storage = new Storage(q);
203  }
204 
205  KConfigGroup op = storage->operationDescription("save");
206  op.writeEntry("group", q->objectName());
207  StorageJob *job = static_cast<StorageJob *>(storage->startOperationCall(op));
208  job->setData(data);
209  storageCount++;
210  QObject::connect(job, SIGNAL(finished(KJob*)), q, SLOT(storeJobFinished(KJob*)));
211 }
212 
213 void DataContainerPrivate::storeJobFinished(KJob* )
214 {
215  --storageCount;
216  if (storageCount < 1) {
217  storage->deleteLater();
218  storage = 0;
219  }
220 }
221 
222 void DataContainerPrivate::retrieve()
223 {
224  DataEngine* de = q->getDataEngine();
225  if (de == NULL) {
226  return;
227  }
228 
229  if (!storage) {
230  storage = new Storage(q);
231  }
232 
233  KConfigGroup retrieveGroup = storage->operationDescription("retrieve");
234  retrieveGroup.writeEntry("group", q->objectName());
235  ServiceJob* retrieveJob = storage->startOperationCall(retrieveGroup);
236  QObject::connect(retrieveJob, SIGNAL(result(KJob*)), q,
237  SLOT(populateFromStoredData(KJob*)));
238 }
239 
240 void DataContainerPrivate::populateFromStoredData(KJob *job)
241 {
242  if (job->error()) {
243  return;
244  }
245 
246  StorageJob *ret = dynamic_cast<StorageJob*>(job);
247  if (!ret) {
248  return;
249  }
250 
251  // Only fill the source with old stored
252  // data if it is not already populated with new data.
253  if (data.isEmpty() && !ret->data().isEmpty()) {
254  data = ret->data();
255  dirty = true;
256  q->forceImmediateUpdate();
257  }
258 
259  KConfigGroup expireGroup = storage->operationDescription("expire");
260  //expire things older than 4 days
261  expireGroup.writeEntry("age", 345600);
262  storage->startOperationCall(expireGroup);
263 }
264 
265 void DataContainer::disconnectVisualization(QObject *visualization)
266 {
267  QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
268  disconnect(visualization, SIGNAL(destroyed(QObject*)),
269  this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
270 
271  if (objIt == d->relayObjects.end() || !objIt.value()) {
272  // it is connected directly to the DataContainer itself
273  disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
274  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
275  } else {
276  SignalRelay *relay = objIt.value();
277 
278  if (relay->receiverCount() == 1) {
279  d->relays.remove(relay->m_interval);
280  delete relay;
281  } else {
282  disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
283  visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
284  }
285  }
286 
287  d->relayObjects.erase(objIt);
288  checkUsage();
289 }
290 
291 void DataContainer::checkForUpdate()
292 {
293  //kDebug() << objectName() << d->dirty;
294  if (d->dirty) {
295  emit dataUpdated(objectName(), d->data);
296 
297  foreach (SignalRelay *relay, d->relays) {
298  relay->checkQueueing();
299  }
300 
301  d->dirty = false;
302  }
303 }
304 
305 void DataContainer::forceImmediateUpdate()
306 {
307  if (d->dirty) {
308  d->dirty = false;
309  emit dataUpdated(objectName(), d->data);
310  }
311 
312  foreach (SignalRelay *relay, d->relays) {
313  relay->forceImmediateUpdate();
314  }
315 }
316 
317 uint DataContainer::timeSinceLastUpdate() const
318 {
319  //FIXME: we still assume it's been <24h
320  //and ignore possible daylight savings changes
321  return d->updateTs.elapsed();
322 }
323 
324 void DataContainer::setNeedsUpdate(bool update)
325 {
326  d->cached = update;
327 }
328 
329 void DataContainer::checkUsage()
330 {
331  if (!d->checkUsageTimer.isActive()) {
332  d->checkUsageTimer.start(10, this);
333  }
334 }
335 
336 void DataContainer::timerEvent(QTimerEvent * event)
337 {
338  if (event->timerId() == d->checkUsageTimer.timerId()) {
339  if (d->relays.count() < 1 &&
340  receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data))) < 1) {
341  // DO NOT CALL ANYTHING AFTER THIS LINE AS IT MAY GET DELETED!
342  kDebug() << objectName() << "is unused";
343  emit becameUnused(objectName());
344  }
345  d->checkUsageTimer.stop();
346  } else if (event->timerId() == d->storageTimer.timerId()) {
347  d->store();
348  d->storageTimer.stop();
349  }
350 }
351 
352 } // Plasma namespace
353 
354 #include "datacontainer.moc"
355 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Nov 16 2012 14:55:52 by doxygen 1.8.1 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-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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