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

Plasma

dataengine.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 
00020 #include "dataengine.h"
00021 #include "private/dataengine_p.h"
00022 #include "private/datacontainer_p.h"
00023 
00024 #include <QQueue>
00025 #include <QTimer>
00026 #include <QTime>
00027 #include <QTimerEvent>
00028 #include <QVariant>
00029 
00030 #include <kdebug.h>
00031 #include <kplugininfo.h>
00032 #include <kservice.h>
00033 #include <kstandarddirs.h>
00034 
00035 #include "authorizationmanager.h"
00036 #include "datacontainer.h"
00037 #include "package.h"
00038 #include "service.h"
00039 #include "scripting/dataenginescript.h"
00040 
00041 #include "private/authorizationmanager_p.h"
00042 #include "private/dataengineservice_p.h"
00043 #include "private/remotedataengine_p.h"
00044 #include "private/service_p.h"
00045 #include "private/storage_p.h"
00046 
00047 namespace Plasma
00048 {
00049 
00050 DataEngine::DataEngine(QObject *parent, KService::Ptr service)
00051     : QObject(parent),
00052       d(new DataEnginePrivate(this, KPluginInfo(service)))
00053 {
00054 }
00055 
00056 DataEngine::DataEngine(QObject *parent, const QVariantList &args)
00057     : QObject(parent),
00058       d(new DataEnginePrivate(this, KPluginInfo(KService::serviceByStorageId(args.count() > 0 ?  args[0].toString() : QString()))))
00059 {
00060 }
00061 
00062 DataEngine::~DataEngine()
00063 {
00064     //kDebug() << objectName() << ": bye bye birdy! ";
00065     delete d;
00066 }
00067 
00068 QStringList DataEngine::sources() const
00069 {
00070     if (d->script) {
00071         return d->script->sources();
00072     } else {
00073         return d->sources.keys();
00074     }
00075 }
00076 
00077 Service *DataEngine::serviceForSource(const QString &source)
00078 {
00079     if (d->script) {
00080         Service * s = d->script->serviceForSource(source);
00081         if (s) {
00082             return s;
00083         }
00084     }
00085 
00086     return new NullService(source, this);
00087 }
00088 
00089 void DataEngine::connectSource(const QString &source, QObject *visualization,
00090                                uint pollingInterval,
00091                                Plasma::IntervalAlignment intervalAlignment) const
00092 {
00093     //kDebug() << "connectSource" << source;
00094     bool newSource;
00095     DataContainer *s = d->requestSource(source, &newSource);
00096 
00097     if (s) {
00098         // we suppress the immediate invocation of dataUpdated here if the
00099         // source was prexisting and they don't request delayed updates
00100         // (we want to do an immediate update in that case so they don't
00101         // have to wait for the first time out)
00102         if (newSource && !s->data().isEmpty()) {
00103             newSource = false;
00104         }
00105         d->connectSource(s, visualization, pollingInterval, intervalAlignment,
00106                          !newSource || pollingInterval > 0);
00107         //kDebug() << " ==> source connected";
00108     }
00109 }
00110 
00111 void DataEngine::connectAllSources(QObject *visualization, uint pollingInterval,
00112                                    Plasma::IntervalAlignment intervalAlignment) const
00113 {
00114     foreach (DataContainer *s, d->sources) {
00115         d->connectSource(s, visualization, pollingInterval, intervalAlignment);
00116     }
00117 }
00118 
00119 void DataEngine::disconnectSource(const QString &source, QObject *visualization) const
00120 {
00121     DataContainer *s = d->source(source, false);
00122 
00123     if (s) {
00124         s->disconnectVisualization(visualization);
00125     }
00126 }
00127 
00128 DataContainer *DataEngine::containerForSource(const QString &source)
00129 {
00130     return d->source(source, false);
00131 }
00132 
00133 DataEngine::Data DataEngine::query(const QString &source) const
00134 {
00135     bool newSource;
00136     DataContainer *s = d->requestSource(source, &newSource);
00137 
00138     if (!s) {
00139         return DataEngine::Data();
00140     } else if (!newSource && d->minPollingInterval >= 0 &&
00141                s->timeSinceLastUpdate() >= uint(d->minPollingInterval)) {
00142         DataEngine *unconstThis = const_cast<DataEngine*>(this);
00143         if (unconstThis->updateSourceEvent(source)) {
00144             unconstThis->scheduleSourcesUpdated();
00145         }
00146     }
00147 
00148     DataEngine::Data data = s->data();
00149     s->checkUsage();
00150     return data;
00151 }
00152 
00153 void DataEngine::init()
00154 {
00155     if (d->script) {
00156         d->setupScriptSupport();
00157         d->script->init();
00158     } else {
00159         // kDebug() << "called";
00160         // default implementation does nothing. this is for engines that have to
00161         // start things in motion external to themselves before they can work
00162     }
00163 }
00164 
00165 bool DataEngine::sourceRequestEvent(const QString &name)
00166 {
00167     if (d->script) {
00168         return d->script->sourceRequestEvent(name);
00169     } else {
00170         return false;
00171     }
00172 }
00173 
00174 bool DataEngine::updateSourceEvent(const QString &source)
00175 {
00176     if (d->script) {
00177         return d->script->updateSourceEvent(source);
00178     } else {
00179         //kDebug() << source;
00180         return false; //TODO: should this be true to trigger, even needless, updates on every tick?
00181     }
00182 }
00183 
00184 void DataEngine::setData(const QString &source, const QVariant &value)
00185 {
00186     setData(source, source, value);
00187 }
00188 
00189 void DataEngine::setData(const QString &source, const QString &key, const QVariant &value)
00190 {
00191     DataContainer *s = d->source(source, false);
00192     bool isNew = !s;
00193 
00194     if (isNew) {
00195         s = d->source(source);
00196     }
00197 
00198     s->setData(key, value);
00199 
00200     if (isNew && source != d->waitingSourceRequest) {
00201         emit sourceAdded(source);
00202     }
00203 
00204     scheduleSourcesUpdated();
00205 }
00206 
00207 void DataEngine::setData(const QString &source, const Data &data)
00208 {
00209     DataContainer *s = d->source(source, false);
00210     bool isNew = !s;
00211 
00212     if (isNew) {
00213         s = d->source(source);
00214     }
00215 
00216     Data::const_iterator it = data.constBegin();
00217     while (it != data.constEnd()) {
00218         s->setData(it.key(), it.value());
00219         ++it;
00220     }
00221 
00222     if (isNew && source != d->waitingSourceRequest) {
00223         emit sourceAdded(source);
00224     }
00225 
00226     scheduleSourcesUpdated();
00227 }
00228 
00229 void DataEngine::removeAllData(const QString &source)
00230 {
00231     DataContainer *s = d->source(source, false);
00232     if (s) {
00233         s->removeAllData();
00234         scheduleSourcesUpdated();
00235     }
00236 }
00237 
00238 void DataEngine::removeData(const QString &source, const QString &key)
00239 {
00240     DataContainer *s = d->source(source, false);
00241     if (s) {
00242         s->setData(key, QVariant());
00243         scheduleSourcesUpdated();
00244     }
00245 }
00246 
00247 void DataEngine::addSource(DataContainer *source)
00248 {
00249     if (d->sources.contains(source->objectName())) {
00250         kDebug() << "source named \"" << source->objectName() << "\" already exists.";
00251         return;
00252     }
00253 
00254     QObject::connect(source, SIGNAL(updateRequested(DataContainer*)),
00255                      this, SLOT(internalUpdateSource(DataContainer*)));
00256     QObject::connect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
00257     d->sources.insert(source->objectName(), source);
00258     emit sourceAdded(source->objectName());
00259     scheduleSourcesUpdated();
00260 }
00261 
00262 void DataEngine::setMaxSourceCount(uint limit)
00263 {
00264     if (d->limit == limit) {
00265         return;
00266     }
00267 
00268     d->limit = limit;
00269 
00270     if (d->limit > 0) {
00271         d->trimQueue();
00272     } else {
00273         d->sourceQueue.clear();
00274     }
00275 }
00276 
00277 uint DataEngine::maxSourceCount() const
00278 {
00279     return d->limit;
00280 }
00281 
00282 void DataEngine::setMinimumPollingInterval(int minimumMs)
00283 {
00284     d->minPollingInterval = minimumMs;
00285 }
00286 
00287 int DataEngine::minimumPollingInterval() const
00288 {
00289     return d->minPollingInterval;
00290 }
00291 
00292 void DataEngine::setPollingInterval(uint frequency)
00293 {
00294     killTimer(d->updateTimerId);
00295     d->updateTimerId = 0;
00296 
00297     if (frequency > 0) {
00298         d->updateTimerId = startTimer(frequency);
00299     }
00300 }
00301 
00302 void DataEngine::removeSource(const QString &source)
00303 {
00304     SourceDict::iterator it = d->sources.find(source);
00305     if (it != d->sources.end()) {
00306         DataContainer *s = it.value();
00307 
00308         // remove it from the limit queue if we're keeping one
00309         if (d->limit > 0) {
00310             QQueue<DataContainer*>::iterator it = d->sourceQueue.begin();
00311             while (it != d->sourceQueue.end()) {
00312                 if (*it == s) {
00313                     d->sourceQueue.erase(it);
00314                     break;
00315                 }
00316                 ++it;
00317             }
00318         }
00319 
00320         s->d->store();
00321         s->disconnect(this);
00322         s->deleteLater();
00323         d->sources.erase(it);
00324         emit sourceRemoved(source);
00325     }
00326 }
00327 
00328 void DataEngine::removeAllSources()
00329 {
00330     QMutableHashIterator<QString, Plasma::DataContainer*> it(d->sources);
00331     while (it.hasNext()) {
00332         it.next();
00333         Plasma::DataContainer *s = it.value();
00334         const QString source = it.key();
00335         it.remove();
00336         s->disconnect(this);
00337         s->deleteLater();
00338         emit sourceRemoved(source);
00339     }
00340 }
00341 
00342 bool DataEngine::isValid() const
00343 {
00344     return d->valid;
00345 }
00346 
00347 bool DataEngine::isEmpty() const
00348 {
00349     return d->sources.isEmpty();
00350 }
00351 
00352 void DataEngine::setValid(bool valid)
00353 {
00354     d->valid = valid;
00355 }
00356 
00357 DataEngine::SourceDict DataEngine::containerDict() const
00358 {
00359     return d->sources;
00360 }
00361 
00362 void DataEngine::timerEvent(QTimerEvent *event)
00363 {
00364     //kDebug();
00365     if (event->timerId() == d->updateTimerId) {
00366         // if the freq update is less than 0, don't bother
00367         if (d->minPollingInterval < 0) {
00368             //kDebug() << "uh oh.. no polling allowed!";
00369             return;
00370         }
00371 
00372         // minPollingInterval
00373         if (d->updateTimestamp.elapsed() < d->minPollingInterval) {
00374             //kDebug() << "hey now.. slow down!";
00375             return;
00376         }
00377 
00378         d->updateTimestamp.restart();
00379         updateAllSources();
00380     } else if (event->timerId() == d->checkSourcesTimerId) {
00381         killTimer(d->checkSourcesTimerId);
00382         d->checkSourcesTimerId = 0;
00383 
00384         QHashIterator<QString, Plasma::DataContainer*> it(d->sources);
00385         while (it.hasNext()) {
00386             it.next();
00387             it.value()->checkForUpdate();
00388         }
00389     } else {
00390         QObject::timerEvent(event);
00391     }
00392 }
00393 
00394 void DataEngine::updateAllSources()
00395 {
00396     QHashIterator<QString, Plasma::DataContainer*> it(d->sources);
00397     while (it.hasNext()) {
00398         it.next();
00399         //kDebug() << "updating" << it.key();
00400         updateSourceEvent(it.key());
00401     }
00402 
00403     scheduleSourcesUpdated();
00404 }
00405 
00406 void DataEngine::forceImmediateUpdateOfAllVisualizations()
00407 {
00408     foreach (DataContainer *source, d->sources) {
00409         source->forceImmediateUpdate();
00410     }
00411 }
00412 
00413 void DataEngine::setIcon(const QString &icon)
00414 {
00415     d->icon = icon;
00416 }
00417 
00418 QString DataEngine::icon() const
00419 {
00420     return d->icon;
00421 }
00422 
00423 QString DataEngine::pluginName() const
00424 {
00425     if (!d->dataEngineDescription.isValid()) {
00426         return QString();
00427     }
00428 
00429     return d->dataEngineDescription.pluginName();
00430 }
00431 
00432 void DataEngine::setDefaultService(const QString &serviceName)
00433 {
00434     d->serviceName = serviceName;
00435 }
00436 
00437 Service* DataEngine::createDefaultService(QObject *parent)
00438 {
00439     QVariantList args;
00440     args << QVariant::fromValue<DataEngine*>(this);
00441     return Service::load(d->serviceName, args, parent);
00442 }
00443 
00444 void DataEnginePrivate::publish(AnnouncementMethods methods, const QString &name)
00445 {
00446     if (!publishedService) {
00447         publishedService = new DataEngineService(q);
00448     }
00449 
00450     //QString resourceName =
00451     //i18nc("%1 is the name of a dataengine, %2 the name of the machine that engine is published
00452 //on",
00453           //"%1 dataengine on %2", name(), AuthorizationManager::self()->d->myCredentials.name());
00454     kDebug() << "name: " << name;
00455     publishedService->d->publish(methods, name);
00456 }
00457 
00458 void DataEnginePrivate::unpublish(const QString &name)
00459 {
00460     Q_UNUSED(name)
00461 
00462     if (publishedService) {
00463         publishedService->d->unpublish();
00464     }
00465 }
00466 
00467 bool DataEnginePrivate::isPublished() const
00468 {
00469     if (publishedService) {
00470         return publishedService->d->isPublished();
00471     } else {
00472         return false;
00473     }
00474 }
00475 
00476 const Package *DataEngine::package() const
00477 {
00478     return d->package;
00479 }
00480 
00481 void DataEngine::scheduleSourcesUpdated()
00482 {
00483     if (d->checkSourcesTimerId) {
00484         return;
00485     }
00486 
00487     d->checkSourcesTimerId = startTimer(0);
00488 }
00489 
00490 QString DataEngine::name() const
00491 {
00492     return d->engineName;
00493 }
00494 
00495 void DataEngine::setName(const QString &name)
00496 {
00497     d->engineName = name;
00498     setObjectName(name);
00499 }
00500 
00501 void DataEngine::setStorageEnabled(const QString &source, bool store)
00502 {
00503     DataContainer *s = d->source(source, false);
00504     if (s) {
00505         s->setStorageEnabled(store);
00506     }
00507 }
00508 
00509 // Private class implementations
00510 DataEnginePrivate::DataEnginePrivate(DataEngine *e, const KPluginInfo &info)
00511     : q(e),
00512       dataEngineDescription(info),
00513       refCount(-1), // first ref
00514       checkSourcesTimerId(0),
00515       updateTimerId(0),
00516       minPollingInterval(-1),
00517       limit(0),
00518       valid(true),
00519       script(0),
00520       package(0),
00521       publishedService(0)
00522 {
00523     updateTimestamp.start();
00524 
00525     if (!info.isValid()) {
00526         engineName = i18n("Unnamed");
00527         return;
00528     }
00529 
00530     engineName = info.name();
00531     if (engineName.isEmpty()) {
00532         engineName = i18n("Unnamed");
00533     }
00534     e->setObjectName(engineName);
00535     icon = info.icon();
00536 
00537     if (dataEngineDescription.isValid()) {
00538         QString api = dataEngineDescription.property("X-Plasma-API").toString();
00539 
00540         if (!api.isEmpty()) {
00541             const QString path =
00542                 KStandardDirs::locate("data",
00543                                       "plasma/dataengines/" + dataEngineDescription.pluginName() + '/');
00544             PackageStructure::Ptr structure = Plasma::packageStructure(api, Plasma::DataEngineComponent);
00545             structure->setPath(path);
00546             package = new Package(path, structure);
00547 
00548             script = Plasma::loadScriptEngine(api, q);
00549             if (!script) {
00550                 kDebug() << "Could not create a" << api << "ScriptEngine for the"
00551                         << dataEngineDescription.name() << "DataEngine.";
00552                 delete package;
00553                 package = 0;
00554             }
00555         }
00556     }
00557 }
00558 
00559 DataEnginePrivate::~DataEnginePrivate()
00560 {
00561     delete script;
00562     script = 0;
00563     delete package;
00564     package = 0;
00565 }
00566 
00567 void DataEnginePrivate::internalUpdateSource(DataContainer *source)
00568 {
00569     if (minPollingInterval > 0 &&
00570         source->timeSinceLastUpdate() < (uint)minPollingInterval) {
00571         // skip updating this source; it's been too soon
00572         //kDebug() << "internal update source is delaying" << source->timeSinceLastUpdate() << minPollingInterval;
00573         //but fake an update so that the signalrelay that triggered this gets the data from the
00574         //recent update. this way we don't have to worry about queuing - the relay will send a
00575         //signal immediately and everyone else is undisturbed.
00576         source->setNeedsUpdate();
00577         return;
00578     }
00579 
00580     if (q->updateSourceEvent(source->objectName())) {
00581         //kDebug() << "queuing an update";
00582         q->scheduleSourcesUpdated();
00583     }/* else {
00584         kDebug() << "no update";
00585     }*/
00586 }
00587 
00588 void DataEnginePrivate::ref()
00589 {
00590     --refCount;
00591 }
00592 
00593 void DataEnginePrivate::deref()
00594 {
00595     ++refCount;
00596 }
00597 
00598 bool DataEnginePrivate::isUsed() const
00599 {
00600     return refCount != 0;
00601 }
00602 
00603 DataContainer *DataEnginePrivate::source(const QString &sourceName, bool createWhenMissing)
00604 {
00605     DataEngine::SourceDict::const_iterator it = sources.constFind(sourceName);
00606     if (it != sources.constEnd()) {
00607         DataContainer *s = it.value();
00608         if (limit > 0) {
00609             QQueue<DataContainer*>::iterator it = sourceQueue.begin();
00610             while (it != sourceQueue.end()) {
00611                 if (*it == s) {
00612                     sourceQueue.erase(it);
00613                     break;
00614                 }
00615                 ++it;
00616             }
00617             sourceQueue.enqueue(s);
00618         }
00619         return s;
00620     }
00621 
00622     if (!createWhenMissing) {
00623         return 0;
00624     }
00625 
00626     //kDebug() << "DataEngine " << q->objectName() << ": could not find DataContainer " << sourceName << ", creating";
00627     DataContainer *s = new DataContainer(q);
00628     s->setObjectName(sourceName);
00629     sources.insert(sourceName, s);
00630     QObject::connect(s, SIGNAL(destroyed(QObject*)), q, SLOT(sourceDestroyed(QObject*)));
00631     QObject::connect(s, SIGNAL(updateRequested(DataContainer*)),
00632                      q, SLOT(internalUpdateSource(DataContainer*)));
00633 
00634     if (limit > 0) {
00635         trimQueue();
00636         sourceQueue.enqueue(s);
00637     }
00638     return s;
00639 }
00640 
00641 void DataEnginePrivate::connectSource(DataContainer *s, QObject *visualization,
00642                                       uint pollingInterval,
00643                                       Plasma::IntervalAlignment align,
00644                                       bool immediateCall)
00645 {
00646     //kDebug() << "connect source called" << s->objectName() << "with interval" << pollingInterval;
00647 
00648     //FIXME: at the moment a remote dataengine can only poll, a push mechanism will be needed instead
00649     if (pollingInterval == 0 && qobject_cast<RemoteDataEngine *>(q)) {
00650         pollingInterval = 5000;
00651     }
00652     if (pollingInterval > 0) {
00653         // never more frequently than allowed, never more than 20 times per second
00654         uint min = qMax(50, minPollingInterval); // for qMax below
00655         pollingInterval = qMax(min, pollingInterval);
00656 
00657         // align on the 50ms
00658         pollingInterval = pollingInterval - (pollingInterval % 50);
00659     }
00660 
00661     if (immediateCall) {
00662         // we don't want to do an immediate call if we are simply
00663         // reconnecting
00664         //kDebug() << "immediate call requested, we have:" << s->visualizationIsConnected(visualization);
00665         immediateCall = !s->data().isEmpty() &&
00666                         !s->visualizationIsConnected(visualization);
00667     }
00668 
00669     s->connectVisualization(visualization, pollingInterval, align);
00670 
00671     if (immediateCall) {
00672         QMetaObject::invokeMethod(visualization, "dataUpdated",
00673                                   Q_ARG(QString, s->objectName()),
00674                                   Q_ARG(Plasma::DataEngine::Data, s->data()));
00675         s->d->dirty = false;
00676     }
00677 }
00678 
00679 void DataEnginePrivate::sourceDestroyed(QObject *object)
00680 {
00681     DataEngine::SourceDict::iterator it = sources.begin();
00682     while (it != sources.end()) {
00683         if (it.value() == object) {
00684             sources.erase(it);
00685             emit q->sourceRemoved(object->objectName());
00686             break;
00687         }
00688         ++it;
00689     }
00690 }
00691 
00692 DataContainer *DataEnginePrivate::requestSource(const QString &sourceName, bool *newSource)
00693 {
00694     if (newSource) {
00695         *newSource = false;
00696     }
00697 
00698     //kDebug() << "requesting source " << sourceName;
00699     DataContainer *s = source(sourceName, false);
00700 
00701     if (!s) {
00702         // we didn't find a data source, so give the engine an opportunity to make one
00703         /*kDebug() << "DataEngine " << q->objectName()
00704             << ": could not find DataContainer " << sourceName
00705             << " will create on request" << endl;*/
00706         waitingSourceRequest = sourceName;
00707         if (q->sourceRequestEvent(sourceName)) {
00708             s = source(sourceName, false);
00709             if (s) {
00710                 // now we have a source; since it was created on demand, assume
00711                 // it should be removed when not used
00712                 if (newSource) {
00713                     *newSource = true;
00714                 }
00715                 QObject::connect(s, SIGNAL(becameUnused(QString)), q, SLOT(removeSource(QString)));
00716                 emit q->sourceAdded(sourceName);
00717             }
00718         }
00719         waitingSourceRequest.clear();
00720     }
00721 
00722     return s;
00723 }
00724 
00725 void DataEnginePrivate::trimQueue()
00726 {
00727     uint queueCount = sourceQueue.count();
00728     while (queueCount >= limit && !sourceQueue.isEmpty()) {
00729         DataContainer *punted = sourceQueue.dequeue();
00730         q->removeSource(punted->objectName());
00731         queueCount = sourceQueue.count();
00732     }
00733 }
00734 
00735 // put all setup routines for script here. at this point we can assume that
00736 // package exists and that we have a script engine
00737 void DataEnginePrivate::setupScriptSupport()
00738 {
00739     if (!package) {
00740         return;
00741     }
00742 
00743     /*
00744     kDebug() << "sletting up script support, package is in" << package->path()
00745              << "which is a" << package->structure()->type() << "package"
00746              << ", main script is" << package->filePath("mainscript");
00747     */
00748 
00749     QString translationsPath = package->filePath("translations");
00750     if (!translationsPath.isEmpty()) {
00751         //FIXME: we should _probably_ use a KComponentData to segregate the applets
00752         //       from each other; but I want to get the basics working first :)
00753         KGlobal::dirs()->addResourceDir("locale", translationsPath);
00754         KGlobal::locale()->insertCatalog(package->metadata().pluginName());
00755     }
00756 }
00757 
00758 }
00759 
00760 #include "dataengine.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:36:03 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