* use PackageMetadata when installing a package

* provide a Package::registerPackage convenience method
* make the contentsPrefix optional / changeable; required for packages we don't control the structure of
* PackageMetadata -> file fixes
* provide a way to set the implementation languae in PackageMetadata (e.g. "dashboard" or "webkit")

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=780464
This commit is contained in:
Aaron J. Seigo 2008-02-29 08:14:32 +00:00
parent cbffa9ae29
commit a3ed531670
8 changed files with 116 additions and 40 deletions

View File

@ -26,6 +26,7 @@
#include <KArchiveDirectory> #include <KArchiveDirectory>
#include <KArchiveEntry> #include <KArchiveEntry>
#include <KComponentData> #include <KComponentData>
#include <KDesktopFile>
#include <KIO/FileCopyJob> #include <KIO/FileCopyJob>
#include <KIO/Job> #include <KIO/Job>
#include <KPluginInfo> #include <KPluginInfo>
@ -89,7 +90,7 @@ bool Package::isValid() const
} }
foreach (const char *dir, d->structure->requiredDirectories()) { foreach (const char *dir, d->structure->requiredDirectories()) {
if (!QFile::exists(d->basePath + "contents/" + d->structure->path(dir))) { if (!QFile::exists(d->basePath + d->structure->contentsPrefix() + d->structure->path(dir))) {
kWarning(505) << "Could not find required directory" << dir; kWarning(505) << "Could not find required directory" << dir;
d->valid = false; d->valid = false;
return false; return false;
@ -97,9 +98,9 @@ bool Package::isValid() const
} }
foreach (const char *file, d->structure->requiredFiles()) { foreach (const char *file, d->structure->requiredFiles()) {
if (!QFile::exists(d->basePath + "contents/" + d->structure->path(file))) { if (!QFile::exists(d->basePath + d->structure->contentsPrefix() + d->structure->path(file))) {
kWarning(505) << "Could not find required file" << file << ", look in" kWarning(505) << "Could not find required file" << file << ", look in"
<< d->basePath + "contents/" + d->structure->path(file) << endl; << d->basePath + d->structure->contentsPrefix() + d->structure->path(file) << endl;
d->valid = false; d->valid = false;
return false; return false;
} }
@ -111,16 +112,18 @@ bool Package::isValid() const
QString Package::filePath(const char* fileType, const QString& filename) const QString Package::filePath(const char* fileType, const QString& filename) const
{ {
if (!d->valid) { if (!d->valid) {
kDebug() << "package is not valid";
return QString(); return QString();
} }
QString path = d->structure->path(fileType); QString path = d->structure->path(fileType);
if (path.isEmpty()) { if (path.isEmpty()) {
kDebug() << "no matching path came of it";
return QString(); return QString();
} }
path.prepend(d->basePath + "contents/"); path.prepend(d->basePath + d->structure->contentsPrefix());
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
path.append("/").append(filename); path.append("/").append(filename);
@ -130,6 +133,7 @@ QString Package::filePath(const char* fileType, const QString& filename) const
return path; return path;
} }
kDebug() << path << "does not exist";
return QString(); return QString();
} }
@ -149,7 +153,7 @@ QStringList Package::entryList(const char* fileType) const
return QStringList(); return QStringList();
} }
QDir dir(d->basePath + "contents/" + path); QDir dir(d->basePath + d->structure->contentsPrefix() + path);
if (!dir.exists()) { if (!dir.exists()) {
return QStringList(); return QStringList();
@ -268,27 +272,61 @@ bool Package::installPackage(const QString& package,
// and now we register it as a service =) // and now we register it as a service =)
targetName.append("/metadata.desktop"); targetName.append("/metadata.desktop");
KConfigGroup cg = KDesktopFile(targetName).desktopGroup();
// should not installing it as a service disqualify it? // should not installing it as a service disqualify it?
// i don't think so since KServiceTypeTrader may not be // i don't think so since KServiceTypeTrader may not be
// used by the installing app in any case, and the // used by the installing app in any case, and the
// package is properly installed - aseigo // package is properly installed - aseigo
registerPackage(targetName);
//TODO: reduce code duplication with registerPackage below
QFile icon(packageRoot + cg.readEntry("Icon"));
if (icon.exists()) {
QString installedIcon("plasma_applet_" + meta.pluginName() + cg.readEntry("Icon"));
meta.write(targetName, installedIcon);
installedIcon = KStandardDirs::locateLocal("icon", installedIcon);
job = KIO::file_copy(icon.fileName(), installedIcon, -1, KIO::HideProgressInfo);
job->exec();
}
QString serviceName(KGlobal::mainComponent().componentName() + "_plasma_applet_" + meta.pluginName());
QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
job = KIO::file_copy(targetName, service, -1, KIO::HideProgressInfo);
job->exec();
return true; return true;
} }
bool Package::registerPackage(const QString &desktopFilePath) bool Package::registerPackage(const PackageMetadata &data, const QString &iconPath)
{ {
QString service = KStandardDirs::locateLocal("services", KGlobal::mainComponent().componentName()); QString serviceName("plasma-applet-" + data.pluginName());
KPluginInfo pluginInfo(desktopFilePath); QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
if (pluginInfo.pluginName().isEmpty()) { if (data.pluginName().isEmpty()) {
return false; return false;
} }
service.append(pluginInfo.pluginName()).append(".desktop"); data.write(service);
KIO::FileCopyJob *job = KIO::file_copy(desktopFilePath, service, -1, KIO::HideProgressInfo);
return job->exec(); KDesktopFile config(service);
KConfigGroup cg = config.desktopGroup();
cg.writeEntry("Type", "Service");
cg.writeEntry("X-KDE-ServiceTypes", "Plasma/Applet");
cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", true);
QFile icon(iconPath);
if (icon.exists()) {
//FIXME: the '/' search will break on non-UNIX. do we care?
QString installedIcon("plasma_applet_" + data.pluginName() +
iconPath.right(iconPath.length() - iconPath.lastIndexOf("/")));
cg.writeEntry("Icon", installedIcon);
installedIcon = KStandardDirs::locateLocal("icon", installedIcon);
KIO::FileCopyJob *job = KIO::file_copy(iconPath, installedIcon, -1, KIO::HideProgressInfo);
job->exec();
}
return true;
} }
bool Package::createPackage(const PackageMetadata &metadata, bool Package::createPackage(const PackageMetadata &metadata,

View File

@ -136,7 +136,7 @@ class PLASMA_EXPORT Package
* @arg the full path to the desktop file (must be KPluginInfo compatible) * @arg the full path to the desktop file (must be KPluginInfo compatible)
* @return true on success, false on failure * @return true on success, false on failure
*/ */
static bool registerPackage(const QString &desktopFilePath); static bool registerPackage(const PackageMetadata &data, const QString &iconPath);
//TODO implement uninstall //TODO implement uninstall
//static bool uninstallPackage(const QString& package, const QString& packageRoot); //static bool uninstallPackage(const QString& package, const QString& packageRoot);

View File

@ -21,8 +21,8 @@
#include <QDir> #include <QDir>
#include <KConfig>
#include <KConfigGroup> #include <KConfigGroup>
#include <KDesktopFile>
namespace Plasma namespace Plasma
{ {
@ -37,11 +37,12 @@ class PackageMetadata::Private
QString version; QString version;
QString website; QString website;
QString license; QString license;
QString mainFile;
QString app; QString app;
QString requiredVersion; QString requiredVersion;
QString pluginName;
QString type; QString type;
QString serviceType; QString serviceType;
QString language;
}; };
PackageMetadata::PackageMetadata() PackageMetadata::PackageMetadata()
@ -72,25 +73,25 @@ bool PackageMetadata::isComplete() const
void PackageMetadata::write(const QString &filename, const QString &icon) const void PackageMetadata::write(const QString &filename, const QString &icon) const
{ {
KConfig cfg(filename); KDesktopFile cfg(filename);
KConfigGroup config(&cfg, "Desktop Entry"); KConfigGroup config = cfg.desktopGroup();
config.writeEntry("Encoding", "UTF-8"); config.writeEntry("Encoding", "UTF-8");
//TODO: this will be a problem for localized names? //TODO: this will be a problem for localized names?
config.writeEntry("Name", d->name); config.writeEntry("Name", d->name);
config.writeEntry("Description", d->description); config.writeEntry("Comment", d->description);
if (!icon.isNull()) { if (!icon.isNull()) {
config.writeEntry("Icon", icon); config.writeEntry("Icon", icon);
} }
config.writeEntry("X-KDE-ServiceTypes", d->serviceType); config.writeEntry("X-KDE-ServiceTypes", d->serviceType);
config.writeEntry("X-KDE-PluginInfo-Name", d->name); config.writeEntry("X-KDE-PluginInfo-Name", d->pluginName);
config.writeEntry("X-KDE-PluginInfo-Author", d->author); config.writeEntry("X-KDE-PluginInfo-Author", d->author);
config.writeEntry("X-KDE-PluginInfo-Email", d->email); config.writeEntry("X-KDE-PluginInfo-Email", d->email);
config.writeEntry("X-KDE-PluginInfo-Version", d->version); config.writeEntry("X-KDE-PluginInfo-Version", d->version);
config.writeEntry("X-KDE-PluginInfo-Website", d->website); config.writeEntry("X-KDE-PluginInfo-Website", d->website);
config.writeEntry("X-KDE-PluginInfo-License", d->license); config.writeEntry("X-KDE-PluginInfo-License", d->license);
config.writeEntry("X-KDE-PluginInfo-Category", d->type); config.writeEntry("X-KDE-PluginInfo-Category", d->type);
config.writeEntry("X-KDE-Plasmagik-MainFile", d->mainFile); config.writeEntry("X-Plasma-Language", d->language);
config.writeEntry("X-KDE-Plasmagik-ApplicationName", d->app); config.writeEntry("X-KDE-Plasmagik-ApplicationName", d->app);
config.writeEntry("X-KDE-Plasmagik-RequiredVersion", d->requiredVersion); config.writeEntry("X-KDE-Plasmagik-RequiredVersion", d->requiredVersion);
} }
@ -110,7 +111,6 @@ void PackageMetadata::read(const QString& filename)
d->website = config.readEntry("X-KDE-PluginInfo-Website", d->website); d->website = config.readEntry("X-KDE-PluginInfo-Website", d->website);
d->license = config.readEntry("X-KDE-PluginInfo-License", d->license); d->license = config.readEntry("X-KDE-PluginInfo-License", d->license);
d->type = config.readEntry("X-KDE-PluginInfo-Category", d->type); d->type = config.readEntry("X-KDE-PluginInfo-Category", d->type);
d->mainFile = config.readEntry("X-KDE-Plasmagik-MainFile", d->mainFile);
d->app = config.readEntry("X-KDE-Plasmagik-ApplicationName", d->app); d->app = config.readEntry("X-KDE-Plasmagik-ApplicationName", d->app);
d->requiredVersion = config.readEntry("X-KDE-Plasmagik-RequiredVersion", d->requiredVersion); d->requiredVersion = config.readEntry("X-KDE-Plasmagik-RequiredVersion", d->requiredVersion);
} }
@ -155,11 +155,6 @@ QString PackageMetadata::license() const
return d->license; return d->license;
} }
QString PackageMetadata::mainFile() const
{
return d->mainFile;
}
QString PackageMetadata::application() const QString PackageMetadata::application() const
{ {
return d->app; return d->app;
@ -175,6 +170,26 @@ QString PackageMetadata::type() const
return d->type; return d->type;
} }
QString PackageMetadata::implementationLanguage() const
{
return d->language;
}
void PackageMetadata::setImplementationLanguage(const QString& language)
{
d->language = language;
}
QString PackageMetadata::pluginName() const
{
return d->pluginName;
}
void PackageMetadata::setPluginName(const QString &pluginName)
{
d->pluginName = pluginName;
}
void PackageMetadata::setName(const QString &name) void PackageMetadata::setName(const QString &name)
{ {
d->name = name; d->name = name;
@ -215,11 +230,6 @@ void PackageMetadata::setLicense(const QString &license)
d->license = license; d->license = license;
} }
void PackageMetadata::setMainFile(const QString &mainFile)
{
d->mainFile = mainFile;
}
void PackageMetadata::setApplication(const QString &application) void PackageMetadata::setApplication(const QString &application)
{ {
d->app = application; d->app = application;

View File

@ -74,9 +74,10 @@ public:
QString version() const; QString version() const;
QString website() const; QString website() const;
QString license() const; QString license() const;
QString mainFile() const;
QString application() const; QString application() const;
QString requiredVersion() const; QString requiredVersion() const;
QString pluginName() const;
QString implementationLanguage() const;
QString type() const; QString type() const;
@ -88,10 +89,11 @@ public:
void setVersion(const QString &); void setVersion(const QString &);
void setWebsite(const QString &); void setWebsite(const QString &);
void setLicense(const QString &); void setLicense(const QString &);
void setMainFile(const QString &);
void setApplication(const QString &); void setApplication(const QString &);
void setRequiredVersion(const QString &); void setRequiredVersion(const QString &);
void setType(const QString& type); void setType(const QString& type);
void setPluginName(const QString& name);
void setImplementationLanguage(const QString& language);
private: private:
class Private; class Private;

View File

@ -61,6 +61,7 @@ class PackageStructure::Private
public: public:
QString type; QString type;
QString path; QString path;
QString contentsPrefix;
QMap<QByteArray, ContentStructure> contents; QMap<QByteArray, ContentStructure> contents;
QStringList mimetypes; QStringList mimetypes;
static QHash<QString, PackageStructure::Ptr> structures; static QHash<QString, PackageStructure::Ptr> structures;
@ -73,6 +74,7 @@ PackageStructure::PackageStructure(QObject *parent, const QString &type)
d(new Private) d(new Private)
{ {
d->type = type; d->type = type;
d->contentsPrefix = "contents/";
} }
PackageStructure::~PackageStructure() PackageStructure::~PackageStructure()
@ -143,7 +145,7 @@ QList<const char*> PackageStructure::directories() const
QMap<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin(); QMap<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
while (it != d->contents.constEnd()) { while (it != d->contents.constEnd()) {
if (it.value().directory) { if (it.value().directory) {
dirs << it.key().constData(); dirs << it.key();
} }
++it; ++it;
} }
@ -212,11 +214,13 @@ void PackageStructure::addFileDefinition(const char* key, const QString& path, c
QString PackageStructure::path(const char* key) const QString PackageStructure::path(const char* key) const
{ {
kDebug() << "looking for" << key;
QMap<QByteArray, ContentStructure>::const_iterator it = d->contents.find(key); QMap<QByteArray, ContentStructure>::const_iterator it = d->contents.find(key);
if (it == d->contents.constEnd()) { if (it == d->contents.constEnd()) {
return QString(); return QString();
} }
kDebug() << "found" << key << "and the value is" << it.value().path;
return it.value().path; return it.value().path;
} }
@ -346,6 +350,16 @@ void PackageStructure::write(KConfigBase *config) const
} }
} }
QString PackageStructure::contentsPrefix() const
{
return d->contentsPrefix;
}
void PackageStructure::setContentsPrefix(const QString &prefix)
{
d->contentsPrefix = prefix;
}
bool PackageStructure::installPackage(const QString &package, const QString &packageRoot) bool PackageStructure::installPackage(const QString &package, const QString &packageRoot)
{ {
return Package::installPackage(package, packageRoot); return Package::installPackage(package, packageRoot);

View File

@ -224,7 +224,22 @@ public:
**/ **/
virtual bool installPackage(const QString &archivePath, const QString &packageRoot); virtual bool installPackage(const QString &archivePath, const QString &packageRoot);
/**
* @return the prefix inserted between the base path and content entries
*/
QString contentsPrefix() const;
protected: protected:
/**
* Sets the prefix that all the contents in this package should
* appear under. This defaults to "contents/" and is added automatically
* between the base path and the entries as defined by the package
* structure
*
* @arg prefix the directory prefix to use
*/
void setContentsPrefix(const QString &prefix);
virtual void pathChanged(); virtual void pathChanged();
private: private:

View File

@ -34,7 +34,7 @@ static const char version[] = "1.0";
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
KAboutData aboutData("plasamappletbrowser", 0, ki18n("Plasma Applet Browser"), KAboutData aboutData("plasmappletbrowser", 0, ki18n("Plasma Applet Browser"),
version, ki18n( description ), KAboutData::License_GPL, version, ki18n( description ), KAboutData::License_GPL,
ki18n("(C) 2008, Aaron Seigo")); ki18n("(C) 2008, Aaron Seigo"));
aboutData.addAuthor(ki18n("Aaron Seigo"), ki18n("Original author"), "aseigo@kde.org"); aboutData.addAuthor(ki18n("Aaron Seigo"), ki18n("Original author"), "aseigo@kde.org");

View File

@ -73,7 +73,6 @@ void PackageMetadataTest::read()
QCOMPARE(pm->version(), QString("pre0.1")); QCOMPARE(pm->version(), QString("pre0.1"));
QCOMPARE(pm->website(), QString("http://plasma.kde.org/")); QCOMPARE(pm->website(), QString("http://plasma.kde.org/"));
QCOMPARE(pm->license(), QString("GPL")); QCOMPARE(pm->license(), QString("GPL"));
QCOMPARE(pm->mainFile(), QString("Main file"));
QCOMPARE(pm->application(), QString("A Test name")); QCOMPARE(pm->application(), QString("A Test name"));
QCOMPARE(pm->requiredVersion(), QString("1.2.3")); QCOMPARE(pm->requiredVersion(), QString("1.2.3"));
QCOMPARE(pm->type(), QString("System test")); QCOMPARE(pm->type(), QString("System test"));
@ -89,7 +88,6 @@ void PackageMetadataTest::write()
pm->setVersion(QString("pre0.1")); pm->setVersion(QString("pre0.1"));
pm->setWebsite(QString("http://plasma.kde.org/")); pm->setWebsite(QString("http://plasma.kde.org/"));
pm->setLicense(QString("GPL")); pm->setLicense(QString("GPL"));
pm->setMainFile(QString("Main file"));
pm->setApplication(QString("A Test name")); pm->setApplication(QString("A Test name"));
pm->setRequiredVersion(QString("1.2.3")); pm->setRequiredVersion(QString("1.2.3"));
@ -106,7 +104,6 @@ void PackageMetadataTest::write()
QCOMPARE(pm->version(), QString("pre0.1")); QCOMPARE(pm->version(), QString("pre0.1"));
QCOMPARE(pm->website(), QString("http://plasma.kde.org/")); QCOMPARE(pm->website(), QString("http://plasma.kde.org/"));
QCOMPARE(pm->license(), QString("GPL")); QCOMPARE(pm->license(), QString("GPL"));
QCOMPARE(pm->mainFile(), QString("Main file"));
QCOMPARE(pm->application(), QString("A Test name")); QCOMPARE(pm->application(), QString("A Test name"));
QCOMPARE(pm->requiredVersion(), QString("1.2.3")); QCOMPARE(pm->requiredVersion(), QString("1.2.3"));
} }