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

Plasma

datacontainer.cpp
Go to the documentation of this file.
00001 /*
00002  *   Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Library General Public License as
00006  *   published by the Free Software Foundation; either version 2, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 #include "datacontainer.h"
00020 #include "private/datacontainer_p.h"
00021 #include "private/storage_p.h"
00022 
00023 #include <kdebug.h>
00024 
00025 #include "plasma.h"
00026 
00027 namespace Plasma
00028 {
00029 
00030 DataContainer::DataContainer(QObject *parent)
00031     : QObject(parent),
00032       d(new DataContainerPrivate(this))
00033 {
00034 }
00035 
00036 DataContainer::~DataContainer()
00037 {
00038     delete d;
00039 }
00040 
00041 const DataEngine::Data DataContainer::data() const
00042 {
00043     return d->data;
00044 }
00045 
00046 void DataContainer::setData(const QString &key, const QVariant &value)
00047 {
00048     if (!value.isValid()) {
00049         d->data.remove(key);
00050     } else {
00051         d->data.insert(key, value);
00052     }
00053 
00054     d->dirty = true;
00055     d->updateTs.start();
00056 
00057     //check if storage is enabled and if storage is needed.
00058     //If it is not set to be stored,then this is the first
00059     //setData() since the last time it was stored. This
00060     //gives us only one singleShot timer.
00061     if (isStorageEnabled() || !needsToBeStored()) {
00062         d->storageTimer.start(180000, this);
00063     }
00064 
00065     setNeedsToBeStored(true);
00066 }
00067 
00068 void DataContainer::removeAllData()
00069 {
00070     if (d->data.isEmpty()) {
00071         // avoid an update if we don't have any data anyways
00072         return;
00073     }
00074 
00075     d->data.clear();
00076     d->dirty = true;
00077     d->updateTs.start();
00078 }
00079 
00080 bool DataContainer::visualizationIsConnected(QObject *visualization) const
00081 {
00082     return d->relayObjects.contains(visualization);
00083 }
00084 
00085 void DataContainer::connectVisualization(QObject *visualization, uint pollingInterval,
00086                                          Plasma::IntervalAlignment alignment)
00087 {
00088     //kDebug() << "connecting visualization" << visualization << "at interval of"
00089     //         << pollingInterval << "to" << objectName();
00090     QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
00091     bool connected = objIt != d->relayObjects.end();
00092     if (connected) {
00093         // this visualization is already connected. just adjust the update
00094         // frequency if necessary
00095         SignalRelay *relay = objIt.value();
00096         if (relay) {
00097             // connected to a relay
00098             //kDebug() << "     already connected, but to a relay";
00099             if (relay->m_interval == pollingInterval) {
00100                 //kDebug() << "    already connected to a relay of the same interval of"
00101                 //          << pollingInterval << ", nothing to do";
00102                 return;
00103             }
00104 
00105             if (relay->receiverCount() == 1) {
00106                 //kDebug() << "    removing relay, as it is now unused";
00107                 d->relays.remove(relay->m_interval);
00108                 delete relay;
00109             } else {
00110                 disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00111                            visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00112                 //relay->isUnused();
00113             }
00114         } else if (pollingInterval < 1) {
00115             // the visualization was connected already, but not to a relay
00116             // and it still doesn't want to connect to a relay, so we have
00117             // nothing to do!
00118             //kDebug() << "     already connected, nothing to do";
00119             return;
00120         } else {
00121             disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00122                        visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00123         }
00124     } else {
00125         connect(visualization, SIGNAL(destroyed(QObject*)),
00126                 this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
00127     }
00128 
00129     if (pollingInterval < 1) {
00130         //kDebug() << "    connecting directly";
00131         d->relayObjects[visualization] = 0;
00132         connect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00133                 visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00134     } else {
00135         //kDebug() << "    connecting to a relay";
00136         // we only want to do an imediate update if this is not the first object to connect to us
00137         // if it is the first visualization, then the source will already have been populated
00138         // engine's sourceRequested method
00139         bool immediateUpdate = connected || d->relayObjects.count() > 1;
00140         SignalRelay *relay = d->signalRelay(this, visualization, pollingInterval,
00141                                             alignment, immediateUpdate);
00142         connect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00143                 visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00144     }
00145 }
00146 
00147 void DataContainer::setStorageEnabled(bool store)
00148 {
00149     QTime time = QTime::currentTime();
00150     qsrand((uint)time.msec());
00151     d->enableStorage = store;
00152     if (store) {
00153         QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve()));
00154     }
00155 }
00156 
00157 bool DataContainer::isStorageEnabled() const
00158 {
00159     return d->enableStorage;
00160 }
00161 
00162 bool DataContainer::needsToBeStored() const
00163 {
00164     return !d->isStored;
00165 }
00166 
00167 void DataContainer::setNeedsToBeStored(bool store)
00168 {
00169     d->isStored = !store;
00170 }
00171 
00172 DataEngine* DataContainer::getDataEngine()
00173 {
00174     QObject *o = NULL;
00175     DataEngine *de = NULL;
00176     o = this;
00177     while (de == NULL)
00178     {
00179         o = dynamic_cast<QObject *> (o->parent());
00180         if (o == NULL) {
00181             return NULL;
00182         }
00183         de = dynamic_cast<DataEngine *> (o);
00184     }
00185     return de;
00186 }
00187 
00188 void DataContainerPrivate::store()
00189 {
00190     if (!q->needsToBeStored() || !q->isStorageEnabled()) {
00191         return;
00192     }
00193 
00194     DataEngine* de = q->getDataEngine();
00195     if (!de) {
00196         return;
00197     }
00198 
00199     q->setNeedsToBeStored(false);
00200 
00201     if (!storage) {
00202         storage = new Storage(q);
00203     }
00204 
00205     KConfigGroup op = storage->operationDescription("save");
00206     op.writeEntry("group", q->objectName());
00207     StorageJob *job = static_cast<StorageJob *>(storage->startOperationCall(op));
00208     job->setData(data);
00209     storageCount++;
00210     QObject::connect(job, SIGNAL(finished(KJob*)), q, SLOT(storeJobFinished(KJob*)));
00211 }
00212 
00213 void DataContainerPrivate::storeJobFinished(KJob* )
00214 {
00215     --storageCount;
00216     if (storageCount < 1) {
00217         storage->deleteLater();
00218         storage = 0;
00219     }
00220 }
00221 
00222 void DataContainerPrivate::retrieve()
00223 {
00224     DataEngine* de = q->getDataEngine();
00225     if (de == NULL) {
00226         return;
00227     }
00228 
00229     if (!storage) {
00230         storage = new Storage(q);
00231     }
00232 
00233     KConfigGroup retrieveGroup = storage->operationDescription("retrieve");
00234     retrieveGroup.writeEntry("group", q->objectName());
00235     ServiceJob* retrieveJob = storage->startOperationCall(retrieveGroup);
00236     QObject::connect(retrieveJob, SIGNAL(result(KJob*)), q,
00237             SLOT(populateFromStoredData(KJob*)));
00238 }
00239 
00240 void DataContainerPrivate::populateFromStoredData(KJob *job)
00241 {
00242     if (job->error()) {
00243         return;
00244     }
00245 
00246     StorageJob *ret = dynamic_cast<StorageJob*>(job);
00247     if (!ret) {
00248         return;
00249     }
00250 
00251     // Only fill the source with old stored
00252     // data if it is not already populated with new data.
00253     if (data.isEmpty() && !ret->data().isEmpty()) {
00254         data = ret->data();
00255         dirty = true;
00256         q->forceImmediateUpdate();
00257     }
00258 
00259     KConfigGroup expireGroup = storage->operationDescription("expire");
00260     //expire things older than 4 days
00261     expireGroup.writeEntry("age", 345600);
00262     storage->startOperationCall(expireGroup);
00263 }
00264 
00265 void DataContainer::disconnectVisualization(QObject *visualization)
00266 {
00267     QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
00268     disconnect(visualization, SIGNAL(destroyed(QObject*)),
00269               this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
00270 
00271     if (objIt == d->relayObjects.end() || !objIt.value()) {
00272         // it is connected directly to the DataContainer itself
00273         disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00274                    visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00275     } else {
00276         SignalRelay *relay = objIt.value();
00277 
00278         if (relay->receiverCount() == 1) {
00279             d->relays.remove(relay->m_interval);
00280             delete relay;
00281         } else {
00282             disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00283                        visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00284         }
00285     }
00286 
00287     d->relayObjects.erase(objIt);
00288     checkUsage();
00289 }
00290 
00291 void DataContainer::checkForUpdate()
00292 {
00293     //kDebug() << objectName() << d->dirty;
00294     if (d->dirty) {
00295         emit dataUpdated(objectName(), d->data);
00296 
00297         foreach (SignalRelay *relay, d->relays) {
00298             relay->checkQueueing();
00299         }
00300 
00301         d->dirty = false;
00302     }
00303 }
00304 
00305 void DataContainer::forceImmediateUpdate()
00306 {
00307     if (d->dirty) {
00308         d->dirty = false;
00309         emit dataUpdated(objectName(), d->data);
00310     }
00311 
00312     foreach (SignalRelay *relay, d->relays) {
00313         relay->forceImmediateUpdate();
00314     }
00315 }
00316 
00317 uint DataContainer::timeSinceLastUpdate() const
00318 {
00319     //FIXME: we still assume it's been <24h
00320     //and ignore possible daylight savings changes
00321     return d->updateTs.elapsed();
00322 }
00323 
00324 void DataContainer::setNeedsUpdate(bool update)
00325 {
00326     d->cached = update;
00327 }
00328 
00329 void DataContainer::checkUsage()
00330 {
00331     if (!d->checkUsageTimer.isActive()) {
00332         d->checkUsageTimer.start(10, this);
00333     }
00334 }
00335 
00336 void DataContainer::timerEvent(QTimerEvent * event)
00337 {
00338     if (event->timerId() == d->checkUsageTimer.timerId()) {
00339         if (d->relays.count() < 1 &&
00340             receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data))) < 1) {
00341             // DO NOT CALL ANYTHING AFTER THIS LINE AS IT MAY GET DELETED!
00342             kDebug() << objectName() << "is unused";
00343             emit becameUnused(objectName());
00344         }
00345         d->checkUsageTimer.stop();
00346     } else if (event->timerId() == d->storageTimer.timerId()) {
00347         d->store();
00348         d->storageTimer.stop();
00349     }
00350 }
00351 
00352 } // Plasma namespace
00353 
00354 #include "datacontainer.moc"
00355 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:51:35 by doxygen 1.8.0 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.3 API Reference

Skip menu "kdelibs-4.8.3 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