first draft of Service; still evaluating the use of KConfigSkeleton

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=809020
This commit is contained in:
Aaron J. Seigo 2008-05-18 04:27:54 +00:00
parent f561b7f861
commit 5f3493654f
9 changed files with 629 additions and 1 deletions

View File

@ -33,6 +33,8 @@
#include "datacontainer.h"
#include "package.h"
#include "service.h"
#include "service_p.h"
#include "scripting/dataenginescript.h"
namespace Plasma
@ -64,6 +66,11 @@ QStringList DataEngine::sources() const
return d->sources.keys();
}
Service* DataEngine::serviceForSource(const QString &source)
{
return new NullService(this);
}
void DataEngine::connectSource(const QString& source, QObject* visualization,
uint pollingInterval, Plasma::IntervalAlignment intervalAlignment) const
{

View File

@ -36,6 +36,7 @@ namespace Plasma
class DataContainer;
class DataEngineScript;
class Package;
class Service;
/**
* @class DataEngine
@ -76,7 +77,7 @@ class PLASMA_EXPORT DataEngine : public QObject
**/
explicit DataEngine(QObject* parent = 0, KService::Ptr service = KService::Ptr(0));
DataEngine(QObject* parent, const QVariantList& args);
virtual ~DataEngine();
~DataEngine();
/**
* This method is called when the DataEngine is started. When this
@ -94,6 +95,14 @@ class PLASMA_EXPORT DataEngine : public QObject
**/
virtual QStringList sources() const;
/**
* @param source the source to targe the Service at
* @return a Service that has the source as a destination. The service
* is parented to the DataEngine, but may be deleted by the
* caller when finished with it
*/
virtual Service* serviceForSource(const QString &source);
/**
* Returns the engine name for the DataEngine
*/

1
includes/Service Normal file
View File

@ -0,0 +1 @@
#include "../../plasma/service.h"

1
includes/ServiceJob Normal file
View File

@ -0,0 +1 @@
#include "../../plasma/servicejob.h"

174
service.cpp Normal file
View File

@ -0,0 +1,174 @@
/*
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "service.h"
#include "service_p.h"
#include <QFile>
#include <KDebug>
#include <KService>
#include <KServiceTypeTrader>
#include <KSharedConfig>
#include <KStandardDirs>
#include <KTemporaryFile>
#include "configxml.h"
namespace Plasma
{
Service::Service(QObject *parent)
: QObject(parent),
d(new Private(this))
{
}
Service::Service(QObject *parent, const QVariantList &args)
: QObject(parent),
d(new Private(this))
{
Q_UNUSED(args);
}
Service::~Service()
{
delete d;
}
Service* Service::load(const QString &name, QObject *parent)
{
//TODO: scripting API support
if (name.isEmpty()) {
return new NullService(parent);
}
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint);
if (offers.isEmpty()) {
kDebug() << "offers is empty for " << name;
return new NullService(parent);
}
KService::Ptr offer = offers.first();
QString error;
QVariantList args;
Service* service = offer->createInstance<Plasma::Service>(parent, args, &error);
if (!service) {
kDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error;
return new NullService(parent);
}
return service;
}
void Service::setDestination(const QString &destination)
{
d->destination = destination;
}
QString Service::destination() const
{
return d->destination;
}
QStringList Service::operationList() const
{
if (!d->config) {
return QStringList();
}
return d->config->config()->groupList();
}
KConfigGroup Service::operationParameters(const QString &operation)
{
if (!d->config) {
return KConfigGroup();
}
KConfigGroup params(d->config->config(), operation);
return params;
}
ServiceJob* Service::startOperation(const KConfigGroup &parameters)
{
// TODO: nested groups?
if (!d->config) {
return new NullServiceJob(parent());
}
d->config->writeConfig();
QMap<QString, QVariant> params;
QString op = parameters.name();
foreach (const QString &key, parameters.keyList()) {
KConfigSkeletonItem *item = d->config->findItem(op, key);
if (item) {
params.insert(key, item->property());
}
}
ServiceJob *job = createJob(parameters.name(), params);
connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*)));
return job;
}
QString Service::name() const
{
return d->name;
}
void Service::setName(const QString &name)
{
d->name = name;
}
void Service::setOperationsScheme(QIODevice *xml)
{
delete d->config;
delete d->tempFile;
//FIXME: make KSharedConfig and KConfigSkeleton not braindamaged in 4.2 and then get rid of the
// temp file object here
d->tempFile = new KTemporaryFile;
d->config = new ConfigXml(KSharedConfig::openConfig(d->tempFile->fileName()), xml, this);
}
void Service::registerOperationsScheme()
{
if (d->name.isEmpty()) {
return;
}
QString path = KStandardDirs::locate("data", "plasma/services/" + d->name + ".operations");
if (path.isEmpty()) {
return;
}
QFile file(path);
setOperationsScheme(&file);
}
} // namespace Plasma
#include "service.moc"

187
service.h Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PLASMA_SERVICE_H
#define PLASMA_SERVICE_H
#include <QMap>
#include <QObject>
#include <QVariant>
#include <KConfigGroup>
class QIODevice;
namespace Plasma
{
class ServiceJob;
/**
* @brief This class provides a generic API for write access to settings or services.
*
* Plasma::Service allows interaction with a "destination", the definition of which
* depends on the Service itself. For a network settings Service this might be a
* profile name ("Home", "Office", "Road Warrior") while a web based Service this
* might be a username ("aseigo", "stranger65").
*
* A Service provides one or more operations, each of which provides some sort
* of interaction with the destination. Operations are described using config
* XML which is used to create a KConfig object with one group per operation.
* The group names are used as the operation names, and the defined items in
* the group are the parameters available to be set when using that operation.
*
* A service is started with a KConfigGroup (representing a ready to be serviced
* operation) and automatically deletes itself after completion and signaling
* success or failure. See KJob for more information on this part of the process.
*
* Services may either be loaded "stand alone" from plugins, or from a DataEngine
* by passing in a source name to be used as the destination.
*
* Sample use might look like:
*
* Plasma::DataEngine *twitter = dataEngine("twitter");
* Plasma::Service *service = twitter.serviceForSource("aseigo");
* KConfigGroup op = service->operationParameters("update");
* op.writeEntry("tweet", "Hacking on plasma!");
* Plasma::ServiceJob *job = service->startOperation(op);
* connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobCompeted()));
*/
class Service : public QObject
{
Q_OBJECT
public:
/**
* Destructor
*/
~Service();
/**
* Used to load a given service from a plugin.
*
* @param name the plugin name of the service to load
* @param parent the parent object, if any, for the service
*
* @return a Service object, guaranteed to be not null.
*/
static Service* load(const QString &name, QObject *parent = 0);
/**
* Sets the destination for this Service to operate on
*
* @arg destination specific to each Service, this sets which
* target or address for ServiceJobs to operate on
*/
void setDestination(const QString &destination);
/**
* @return the target destination, if any, that this service is associated with
*/
QString destination() const;
/**
* @return the possible operations for this profile
*/
QStringList operationList() const;
/**
* Retrieves the parameters for a given operation
*
* @param operation the operation to retrieve parameters for
* @return KConfigGroup containing the parameters
*/
KConfigGroup operationParameters(const QString &operation);
/**
* Called to create a ServiceJob which is associated with a given
* operation and parameter set.
*
* @return a started ServiceJob; the consumer may connect to relevant
* signals before returning to the event loop
*/
ServiceJob* startOperation(const KConfigGroup &parameters);
/**
* The name of this service
*/
QString name() const;
Q_SIGNALS:
void finished(ServiceJob* job);
protected:
/**
* Default constructor
*
* @arg parent the parent object for this service
*/
explicit Service(QObject *parent = 0);
/**
* Constructor for plugin loading
*/
Service(QObject *parent, const QVariantList &args);
/**
* Called when a job should be created by the Service.
*
* @param operation which operation to work on
* @param parameters the parameters set by the user for the operation
* @return a ServiceJob that can be started and monitored by the consumer
*/
virtual ServiceJob* createJob(const QString &operation,
QMap<QString, QVariant> &parameters) = 0;
/**
* By default this is based on the file in plasma/services/name.operations, but can be
* reimplented to use a different mechanism.
*
* It should result in a call to setOperationsScheme(QIODevice *);
*/
virtual void registerOperationsScheme();
/**
* Sets the XML used to define the operation schema for
* this Service.
*/
void setOperationsScheme(QIODevice *xml);
/**
* Sets the name of the Service; useful for Services not loaded from plugins,
* which use the plugin name for this.
*
* @arg name the name to use for this service
*/
void setName(const QString &name);
private:
Q_PRIVATE_SLOT(d, void jobFinished(KJob*))
class Private;
Private * const d;
};
} // namespace Plasma
#define K_EXPORT_PLASMA_SERVICE(libname, classname) \
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
K_EXPORT_PLUGIN(factory("plasma_service_" #libname))
#endif // multiple inclusion guard

83
service_p.h Normal file
View File

@ -0,0 +1,83 @@
/*
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
class KTemporaryFile;
#include "servicejob.h"
namespace Plasma
{
class ConfigXml;
class NullServiceJob : public ServiceJob
{
public:
NullServiceJob(QObject *parent)
: ServiceJob(QString(), QString(), QMap<QString, QVariant>(), parent)
{
}
void start()
{
setErrorText(i18n("Invalid (null) service, can not perform any operations."));
emitResult();
}
};
class NullService : public Service
{
public:
NullService(QObject *parent)
: Service(parent)
{
setName("NullService");
}
ServiceJob *createJob(const QString &, QMap<QString, QVariant> &)
{
return new NullServiceJob(parent());
}
};
class Service::Private
{
public:
Private(Service *service)
: q(service),
config(0),
tempFile(0)
{
}
Service *q;
QString destination;
QString name;
ConfigXml *config;
KTemporaryFile *tempFile;
void jobFinished(KJob* job)
{
emit q->finished(static_cast<ServiceJob*>(job));
}
};
} // namespace Plasma

80
servicejob.cpp Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "servicejob.h"
namespace Plasma
{
class ServiceJob::Private
{
public:
Private(const QString &dest, const QString &op, const QMap<QString, QVariant> &params)
: destination(dest),
operation(op),
parameters(params)
{
}
QString destination;
QString operation;
QMap<QString, QVariant> parameters;
QVariant result;
};
ServiceJob::ServiceJob(const QString &destination, const QString &operation,
const QMap<QString, QVariant> &parameters, QObject *parent)
: KJob(parent),
d(new Private(destination, operation, parameters))
{
}
ServiceJob::~ServiceJob()
{
delete d;
}
QString ServiceJob::destination() const
{
return d->destination;
}
QString ServiceJob::operationName() const
{
return d->operation;
}
QMap<QString, QVariant> ServiceJob::parameters() const
{
return d->parameters;
}
QVariant ServiceJob::result() const
{
return d->result;
}
void ServiceJob::setResult(const QVariant &result)
{
d->result = result;
}
} // namespace Plasma
#include "servicejob.moc"

86
servicejob.h Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright 2008 Aaron Seigo <aseigo@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PLASMA_SERVICEJOB_H
#define PLASMA_SERVICEJOB_H
#include <QVariant>
#include <KJob>
#include <KService>
namespace Plasma
{
/**
* @brief This class provides jobs for use with Plasma::Service
*/
class ServiceJob : public KJob
{
Q_OBJECT
public:
/**
* Default constructor
*
* @arg parent the parent object for this service
*/
ServiceJob(const QString &destination, const QString &operation,
const QMap<QString, QVariant> &parameters, QObject *parent = 0);
/**
* Destructor
*/
~ServiceJob();
/**
* @return the destination, if any, that this service is associated with
*/
QString destination() const;
/**
* @return the operation this job should perform
*/
QString operationName() const;
/**
* @return the parameters for the job
*/
QMap<QString, QVariant> parameters() const;
/**
* @return the resulting value from the operation
*/
QVariant result() const;
protected:
/**
* Sets the result for an operation.
*/
void setResult(const QVariant &result);
private:
class Private;
Private * const d;
};
} // namespace Plasma
#endif // multiple inclusion guard