• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • 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     d->storageTimer = new QTimer(this);
00035     QObject::connect(d->storageTimer, SIGNAL(timeout()), this, SLOT(store()));
00036 }
00037 
00038 DataContainer::~DataContainer()
00039 {
00040     delete d;
00041 }
00042 
00043 const DataEngine::Data DataContainer::data() const
00044 {
00045     return d->data;
00046 }
00047 
00048 void DataContainer::setData(const QString &key, const QVariant &value)
00049 {
00050     if (!value.isValid()) {
00051         d->data.remove(key);
00052     } else {
00053         d->data.insert(key, value);
00054     }
00055 
00056     d->dirty = true;
00057     d->updateTs.start();
00058 
00059     //check if storage is enabled and if storage is needed.
00060     //If it is not set to be stored,then this is the first
00061     //setData() since the last time it was stored. This
00062     //gives us only one singleShot timer.
00063     if (isStorageEnabled() || !needsToBeStored()) {
00064         d->storageTimer->start(180000);
00065     }
00066 
00067     setNeedsToBeStored(true);
00068 }
00069 
00070 void DataContainer::removeAllData()
00071 {
00072     if (d->data.isEmpty()) {
00073         // avoid an update if we don't have any data anyways
00074         return;
00075     }
00076 
00077     d->data.clear();
00078     d->dirty = true;
00079     d->updateTs.start();
00080 }
00081 
00082 bool DataContainer::visualizationIsConnected(QObject *visualization) const
00083 {
00084     return d->relayObjects.contains(visualization);
00085 }
00086 
00087 void DataContainer::connectVisualization(QObject *visualization, uint pollingInterval,
00088                                          Plasma::IntervalAlignment alignment)
00089 {
00090     //kDebug() << "connecting visualization" << visualization << "at interval of"
00091     //         << pollingInterval << "to" << objectName();
00092     QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
00093     bool connected = objIt != d->relayObjects.end();
00094     if (connected) {
00095         // this visualization is already connected. just adjust the update
00096         // frequency if necessary
00097         SignalRelay *relay = objIt.value();
00098         if (relay) {
00099             // connected to a relay
00100             //kDebug() << "     already connected, but to a relay";
00101             if (relay->m_interval == pollingInterval) {
00102                 //kDebug() << "    already connected to a relay of the same interval of"
00103                 //          << pollingInterval << ", nothing to do";
00104                 return;
00105             }
00106 
00107             if (relay->receiverCount() == 1) {
00108                 //kDebug() << "    removing relay, as it is now unused";
00109                 d->relays.remove(relay->m_interval);
00110                 delete relay;
00111             } else {
00112                 disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00113                            visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00114                 //relay->isUnused();
00115             }
00116         } else if (pollingInterval < 1) {
00117             // the visualization was connected already, but not to a relay
00118             // and it still doesn't want to connect to a relay, so we have
00119             // nothing to do!
00120             //kDebug() << "     already connected, nothing to do";
00121             return;
00122         } else {
00123             disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00124                        visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00125         }
00126     } else {
00127         connect(visualization, SIGNAL(destroyed(QObject*)),
00128                 this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
00129     }
00130 
00131     if (pollingInterval < 1) {
00132         //kDebug() << "    connecting directly";
00133         d->relayObjects[visualization] = 0;
00134         connect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00135                 visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00136     } else {
00137         //kDebug() << "    connecting to a relay";
00138         // we only want to do an imediate update if this is not the first object to connect to us
00139         // if it is the first visualization, then the source will already have been populated
00140         // engine's sourceRequested method
00141         bool immediateUpdate = connected || d->relayObjects.count() > 1;
00142         SignalRelay *relay = d->signalRelay(this, visualization, pollingInterval,
00143                                             alignment, immediateUpdate);
00144         connect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00145                 visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00146     }
00147 }
00148 
00149 void DataContainer::setStorageEnabled(bool store)
00150 {
00151     QTime time = QTime::currentTime();
00152     qsrand((uint)time.msec());
00153     d->enableStorage = store;
00154     if (store) {
00155         QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve()));
00156     }
00157 }
00158 
00159 bool DataContainer::isStorageEnabled() const
00160 {
00161     return d->enableStorage;
00162 }
00163 
00164 bool DataContainer::needsToBeStored() const
00165 {
00166     return !d->isStored;
00167 }
00168 
00169 void DataContainer::setNeedsToBeStored(bool store)
00170 {
00171     d->isStored = !store;
00172 }
00173 
00174 DataEngine* DataContainer::getDataEngine()
00175 {
00176     QObject *o = NULL;
00177     DataEngine *de = NULL;
00178     o = this;
00179     while (de == NULL)
00180     {
00181         o = dynamic_cast<QObject *> (o->parent());
00182         if (o == NULL) {
00183             return NULL;
00184         }
00185         de = dynamic_cast<DataEngine *> (o);
00186     }
00187     return de;
00188 }
00189 
00190 void DataContainerPrivate::store()
00191 {
00192     if (!q->needsToBeStored() || !q->isStorageEnabled()) {
00193         return;
00194     }
00195 
00196     DataEngine* de = q->getDataEngine();
00197     if (!de) {
00198         return;
00199     }
00200 
00201     q->setNeedsToBeStored(false);
00202 
00203     if (!storage) {
00204         storage = new Storage(q);
00205     }
00206 
00207     KConfigGroup op = storage->operationDescription("save");
00208     op.writeEntry("group", q->objectName());
00209     StorageJob *job = static_cast<StorageJob *>(storage->startOperationCall(op));
00210     job->setData(data);
00211     storageCount++;
00212     QObject::connect(job, SIGNAL(finished(KJob*)), q, SLOT(storeJobFinished(KJob*)));
00213 }
00214 
00215 void DataContainerPrivate::storeJobFinished(KJob* )
00216 {
00217     --storageCount;
00218     if (storageCount < 1) {
00219         storage->deleteLater();
00220         storage = 0;
00221     }
00222 }
00223 
00224 void DataContainerPrivate::retrieve()
00225 {
00226     DataEngine* de = q->getDataEngine();
00227     if (de == NULL) {
00228         return;
00229     }
00230 
00231     if (!storage) {
00232         storage = new Storage(q);
00233     }
00234 
00235     KConfigGroup retrieveGroup = storage->operationDescription("retrieve");
00236     retrieveGroup.writeEntry("group", q->objectName());
00237     ServiceJob* retrieveJob = storage->startOperationCall(retrieveGroup);
00238     QObject::connect(retrieveJob, SIGNAL(result(KJob*)), q,
00239             SLOT(populateFromStoredData(KJob*)));
00240 }
00241 
00242 void DataContainerPrivate::populateFromStoredData(KJob *job)
00243 {
00244     if (job->error()) {
00245         return;
00246     }
00247 
00248     StorageJob *ret = dynamic_cast<StorageJob*>(job);
00249     if (!ret) {
00250         return;
00251     }
00252 
00253     // Only fill the source with old stored
00254     // data if it is not already populated with new data.
00255     if (data.isEmpty() && !ret->data().isEmpty()) {
00256         data = ret->data();
00257         dirty = true;
00258         q->forceImmediateUpdate();
00259     }
00260 
00261     KConfigGroup expireGroup = storage->operationDescription("expire");
00262     //expire things older than 4 days
00263     expireGroup.writeEntry("age", 345600);
00264     storage->startOperationCall(expireGroup);
00265 }
00266 
00267 void DataContainer::disconnectVisualization(QObject *visualization)
00268 {
00269     QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
00270     disconnect(visualization, SIGNAL(destroyed(QObject*)),
00271               this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
00272 
00273     if (objIt == d->relayObjects.end() || !objIt.value()) {
00274         // it is connected directly to the DataContainer itself
00275         disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00276                    visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00277     } else {
00278         SignalRelay *relay = objIt.value();
00279 
00280         if (relay->receiverCount() == 1) {
00281             d->relays.remove(relay->m_interval);
00282             delete relay;
00283         } else {
00284             disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
00285                        visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
00286         }
00287     }
00288 
00289     d->relayObjects.erase(objIt);
00290     checkUsage();
00291 }
00292 
00293 void DataContainer::checkForUpdate()
00294 {
00295     //kDebug() << objectName() << d->dirty;
00296     if (d->dirty) {
00297         emit dataUpdated(objectName(), d->data);
00298 
00299         foreach (SignalRelay *relay, d->relays) {
00300             relay->checkQueueing();
00301         }
00302 
00303         d->dirty = false;
00304     }
00305 }
00306 
00307 void DataContainer::forceImmediateUpdate()
00308 {
00309     if (d->dirty) {
00310         d->dirty = false;
00311         emit dataUpdated(objectName(), d->data);
00312     }
00313 
00314     foreach (SignalRelay *relay, d->relays) {
00315         relay->forceImmediateUpdate();
00316     }
00317 }
00318 
00319 uint DataContainer::timeSinceLastUpdate() const
00320 {
00321     //FIXME: we still assume it's been <24h
00322     //and ignore possible daylight savings changes
00323     return d->updateTs.elapsed();
00324 }
00325 
00326 void DataContainer::setNeedsUpdate(bool update)
00327 {
00328     d->cached = update;
00329 }
00330 
00331 void DataContainer::checkUsage()
00332 {
00333     if (d->relays.count() < 1 &&
00334         receivers(SIGNAL(dataUpdated(QString, Plasma::DataEngine::Data))) < 1) {
00335         // DO NOT CALL ANYTHING AFTER THIS LINE AS IT MAY GET DELETED!
00336         kDebug() << objectName() << "is unused";
00337         emit becameUnused(objectName());
00338     }
00339 }
00340 
00341 } // Plasma namespace
00342 
00343 #include "datacontainer.moc"
00344 

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

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal