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

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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