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

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