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
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.