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

Plasma

service.cpp
Go to the documentation of this file.
00001 /*
00002  *   Copyright 2008 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 "service.h"
00021 #include "servicejob.h"
00022 #include "private/authorizationmanager_p.h"
00023 #include "private/service_p.h"
00024 #include "private/serviceprovider_p.h"
00025 
00026 #include "config-plasma.h"
00027 
00028 #include <QFile>
00029 #include <QGraphicsWidget>
00030 #include <QTimer>
00031 
00032 #include <kdebug.h>
00033 #include <kservice.h>
00034 #include <kservicetypetrader.h>
00035 #include <ksharedconfig.h>
00036 #include <kstandarddirs.h>
00037 #include <dnssd/publicservice.h>
00038 #include <dnssd/servicebrowser.h>
00039 
00040 #include "configloader.h"
00041 #include "version.h"
00042 #include "private/configloader_p.h"
00043 #include "private/remoteservice_p.h"
00044 #include "private/remoteservicejob_p.h"
00045 #include "pluginloader.h"
00046 
00047 namespace Plasma
00048 {
00049 
00050 Service::Service(QObject *parent)
00051     : QObject(parent),
00052       d(new ServicePrivate(this))
00053 {
00054 }
00055 
00056 Service::Service(QObject *parent, const QVariantList &args)
00057     : QObject(parent),
00058       d(new ServicePrivate(this))
00059 {
00060     Q_UNUSED(args)
00061 }
00062 
00063 Service::~Service()
00064 {
00065     d->unpublish();
00066     delete d;
00067 }
00068 
00069 Service *Service::load(const QString &name, QObject *parent)
00070 {
00071     QVariantList args;
00072     return load(name, args, parent);
00073 }
00074 
00075 Service *Service::load(const QString &name, const QVariantList &args, QObject *parent)
00076 {
00077     return PluginLoader::pluginLoader()->loadService(name, args, parent);
00078 }
00079 
00080 Service *Service::access(const KUrl &url, QObject *parent)
00081 {
00082     return new RemoteService(parent, url);
00083 }
00084 
00085 void ServicePrivate::jobFinished(KJob *job)
00086 {
00087     emit q->finished(static_cast<ServiceJob*>(job));
00088 }
00089 
00090 void ServicePrivate::associatedWidgetDestroyed(QObject *obj)
00091 {
00092     associatedWidgets.remove(static_cast<QWidget*>(obj));
00093 }
00094 
00095 void ServicePrivate::associatedGraphicsWidgetDestroyed(QObject *obj)
00096 {
00097     associatedGraphicsWidgets.remove(static_cast<QGraphicsObject*>(obj));
00098 }
00099 
00100 void ServicePrivate::publish(AnnouncementMethods methods, const QString &name, const PackageMetadata &metadata)
00101 {
00102 #ifdef ENABLE_REMOTE_WIDGETS
00103     if (!serviceProvider) {
00104         AuthorizationManager::self()->d->prepareForServicePublication();
00105 
00106         serviceProvider = new ServiceProvider(name, q);
00107 
00108         if (methods.testFlag(ZeroconfAnnouncement) &&
00109             (DNSSD::ServiceBrowser::isAvailable() == DNSSD::ServiceBrowser::Working)) {
00110             //TODO: dynamically pick a free port number.
00111             publicService = new DNSSD::PublicService(name, "_plasma._tcp", 4000);
00112 
00113             QMap<QString, QByteArray> textData;
00114             textData["name"] = name.toUtf8();
00115             textData["plasmoidname"] = metadata.name().toUtf8();
00116             textData["description"] = metadata.description().toUtf8();
00117             textData["icon"] = metadata.icon().toUtf8();
00118             publicService->setTextData(textData);
00119             kDebug() << "about to publish";
00120 
00121             publicService->publishAsync();
00122         } else if (methods.testFlag(ZeroconfAnnouncement) &&
00123                 (DNSSD::ServiceBrowser::isAvailable() != DNSSD::ServiceBrowser::Working)) {
00124             kDebug() << "sorry, but your zeroconf daemon doesn't seem to be running.";
00125         }
00126     } else {
00127         kDebug() << "already published!";
00128     }
00129 #else
00130     kWarning() << "libplasma is compiled without support for remote widgets. not publishing.";
00131 #endif
00132 }
00133 
00134 void ServicePrivate::unpublish()
00135 {
00136         delete serviceProvider;
00137         serviceProvider = 0;
00138 
00139         delete publicService;
00140         publicService = 0;
00141 }
00142 
00143 bool ServicePrivate::isPublished() const
00144 {
00145     if (serviceProvider) {
00146         return true;
00147     } else {
00148         return false;
00149     }
00150 }
00151 
00152 KConfigGroup ServicePrivate::dummyGroup()
00153 {
00154     if (!dummyConfig) {
00155         dummyConfig = new KConfig(QString(), KConfig::SimpleConfig);
00156     }
00157 
00158     return KConfigGroup(dummyConfig, "DummyGroup");
00159 }
00160 
00161 void Service::setDestination(const QString &destination)
00162 {
00163     d->destination = destination;
00164 }
00165 
00166 QString Service::destination() const
00167 {
00168     return d->destination;
00169 }
00170 
00171 QStringList Service::operationNames() const
00172 {
00173     if (!d->config) {
00174         kDebug() << "No valid operations scheme has been registered";
00175         return QStringList();
00176     }
00177 
00178     return d->config->groupList();
00179 }
00180 
00181 KConfigGroup Service::operationDescription(const QString &operationName)
00182 {
00183     if (!d->config) {
00184         kDebug() << "No valid operations scheme has been registered";
00185         return d->dummyGroup();
00186     }
00187 
00188     d->config->writeConfig();
00189     KConfigGroup params(d->config->config(), operationName);
00190     //kDebug() << "operation" << operationName
00191     //         << "requested, has keys" << params.keyList() << "from"
00192     //         << d->config->config()->name();
00193     return params;
00194 }
00195 
00196 QMap<QString, QVariant> Service::parametersFromDescription(const KConfigGroup &description)
00197 {
00198     QMap<QString, QVariant> params;
00199 
00200     if (!d->config || !description.isValid()) {
00201         return params;
00202     }
00203 
00204     const QString op = description.name();
00205     foreach (const QString &key, description.keyList()) {
00206         KConfigSkeletonItem *item = d->config->findItem(op, key);
00207         if (item) {
00208             params.insert(key, description.readEntry(key, item->property()));
00209         }
00210     }
00211 
00212     return params;
00213 }
00214 
00215 ServiceJob *Service::startOperationCall(const KConfigGroup &description, QObject *parent)
00216 {
00217     // TODO: nested groups?
00218     ServiceJob *job = 0;
00219     const QString op = description.isValid() ? description.name() : QString();
00220 
00221     RemoteService *rs = qobject_cast<RemoteService *>(this);
00222     if (!op.isEmpty() && rs && !rs->isReady()) {
00223         // if we have an operation, but a non-ready remote service, just let it through
00224         kDebug() << "Remote service is not ready; queueing operation";
00225         QMap<QString, QVariant> params;
00226         job = createJob(op, params);
00227         RemoteServiceJob *rsj = qobject_cast<RemoteServiceJob *>(job);
00228         if (rsj) {
00229             rsj->setDelayedDescription(description);
00230         }
00231     } else if (!d->config) {
00232         kDebug() << "No valid operations scheme has been registered";
00233     } else if (!op.isEmpty() && d->config->hasGroup(op)) {
00234         if (d->disabledOperations.contains(op)) {
00235             kDebug() << "Operation" << op << "is disabled";
00236         } else {
00237             QMap<QString, QVariant> params = parametersFromDescription(description);
00238             job = createJob(op, params);
00239         }
00240     } else {
00241         kDebug() << op << "is not a valid group; valid groups are:" << d->config->groupList();
00242     }
00243 
00244     if (!job) {
00245         job = new NullServiceJob(destination(), op, this);
00246     }
00247 
00248     job->setParent(parent ? parent : this);
00249     connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*)));
00250     QTimer::singleShot(0, job, SLOT(autoStart()));
00251     return job;
00252 }
00253 
00254 void Service::associateWidget(QWidget *widget, const QString &operation)
00255 {
00256     if (!widget) {
00257         return;
00258     }
00259 
00260     disassociateWidget(widget);
00261     d->associatedWidgets.insert(widget, operation);
00262     connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(associatedWidgetDestroyed(QObject*)));
00263 
00264     widget->setEnabled(!d->disabledOperations.contains(operation));
00265 }
00266 
00267 void Service::disassociateWidget(QWidget *widget)
00268 {
00269     if (!widget) {
00270         return;
00271     }
00272 
00273     disconnect(widget, SIGNAL(destroyed(QObject*)),
00274                this, SLOT(associatedWidgetDestroyed(QObject*)));
00275     d->associatedWidgets.remove(widget);
00276 }
00277 
00278 void Service::associateWidget(QGraphicsWidget *widget, const QString &operation)
00279 {
00280     associateItem(widget, operation);
00281 }
00282 
00283 void Service::disassociateWidget(QGraphicsWidget *widget)
00284 {
00285     disassociateItem(widget);
00286 }
00287 
00288 void Service::associateItem(QGraphicsObject *widget, const QString &operation)
00289 {
00290     if (!widget) {
00291         return;
00292     }
00293 
00294     disassociateItem(widget);
00295     d->associatedGraphicsWidgets.insert(widget, operation);
00296     connect(widget, SIGNAL(destroyed(QObject*)),
00297             this, SLOT(associatedGraphicsWidgetDestroyed(QObject*)));
00298 
00299     widget->setEnabled(!d->disabledOperations.contains(operation));
00300 }
00301 
00302 void Service::disassociateItem(QGraphicsObject *widget)
00303 {
00304     if (!widget) {
00305         return;
00306     }
00307 
00308     disconnect(widget, SIGNAL(destroyed(QObject*)),
00309                this, SLOT(associatedGraphicsWidgetDestroyed(QObject*)));
00310     d->associatedGraphicsWidgets.remove(widget);
00311 }
00312 
00313 QString Service::name() const
00314 {
00315     return d->name;
00316 }
00317 
00318 void Service::setName(const QString &name)
00319 {
00320     d->name = name;
00321 
00322     // now reset the config, which may be based on our name
00323     delete d->config;
00324     d->config = 0;
00325 
00326     delete d->dummyConfig;
00327     d->dummyConfig = 0;
00328 
00329     registerOperationsScheme();
00330 
00331     emit serviceReady(this);
00332 }
00333 
00334 void Service::setOperationEnabled(const QString &operation, bool enable)
00335 {
00336     if (!d->config || !d->config->hasGroup(operation)) {
00337         return;
00338     }
00339 
00340     if (enable) {
00341         d->disabledOperations.remove(operation);
00342     } else {
00343         d->disabledOperations.insert(operation);
00344     }
00345 
00346     {
00347         QHashIterator<QWidget *, QString> it(d->associatedWidgets);
00348         while (it.hasNext()) {
00349             it.next();
00350             if (it.value() == operation) {
00351                 it.key()->setEnabled(enable);
00352             }
00353         }
00354     }
00355 
00356     {
00357         QHashIterator<QGraphicsObject *, QString> it(d->associatedGraphicsWidgets);
00358         while (it.hasNext()) {
00359             it.next();
00360             if (it.value() == operation) {
00361                 it.key()->setEnabled(enable);
00362             }
00363         }
00364     }
00365 }
00366 
00367 bool Service::isOperationEnabled(const QString &operation) const
00368 {
00369     return d->config && d->config->hasGroup(operation) && !d->disabledOperations.contains(operation);
00370 }
00371 
00372 void Service::setOperationsScheme(QIODevice *xml)
00373 {
00374     delete d->config;
00375 
00376     delete d->dummyConfig;
00377     d->dummyConfig = 0;
00378 
00379     KSharedConfigPtr c = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
00380     d->config = new ConfigLoader(c, xml, this);
00381     d->config->d->setWriteDefaults(true);
00382 
00383     emit operationsChanged();
00384 
00385     {
00386         QHashIterator<QWidget *, QString> it(d->associatedWidgets);
00387         while (it.hasNext()) {
00388             it.next();
00389             it.key()->setEnabled(d->config->hasGroup(it.value()));
00390         }
00391     }
00392 
00393     {
00394         QHashIterator<QGraphicsObject *, QString> it(d->associatedGraphicsWidgets);
00395         while (it.hasNext()) {
00396             it.next();
00397             it.key()->setEnabled(d->config->hasGroup(it.value()));
00398         }
00399     }
00400 }
00401 
00402 void Service::registerOperationsScheme()
00403 {
00404     if (d->config) {
00405         // we've already done our job. let's go home.
00406         return;
00407     }
00408 
00409     if (d->name.isEmpty()) {
00410         kDebug() << "No name found";
00411         return;
00412     }
00413 
00414     const QString path = KStandardDirs::locate("data", "plasma/services/" + d->name + ".operations");
00415 
00416     if (path.isEmpty()) {
00417         kDebug() << "Cannot find operations description:" << d->name << ".operations";
00418         return;
00419     }
00420 
00421     QFile file(path);
00422     setOperationsScheme(&file);
00423 }
00424 
00425 } // namespace Plasma
00426 
00427 #include "service.moc"
00428 
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:30:45 by doxygen 1.7.5.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.9.5 API Reference

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