* 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 <KArchiveEntry>
#include <KComponentData>
#include <KDesktopFile>
#include <KIO/FileCopyJob>
#include <KIO/Job>
#include <KPluginInfo>
@ -89,7 +90,7 @@ bool Package::isValid() const
}
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;
d->valid = false;
return false;
@ -97,9 +98,9 @@ bool Package::isValid() const
}
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"
<< d->basePath + "contents/" + d->structure->path(file) << endl;
<< d->basePath + d->structure->contentsPrefix() + d->structure->path(file) << endl;
d->valid = false;
return false;
}
@ -111,16 +112,18 @@ bool Package::isValid() const
QString Package::filePath(const char* fileType, const QString& filename) const
{
if (!d->valid) {
kDebug() << "package is not valid";
return QString();
}
QString path = d->structure->path(fileType);
if (path.isEmpty()) {
kDebug() << "no matching path came of it";
return QString();
}
path.prepend(d->basePath + "contents/");
path.prepend(d->basePath + d->structure->contentsPrefix());
if (!filename.isEmpty()) {
path.append("/").append(filename);
@ -130,6 +133,7 @@ QString Package::filePath(const char* fileType, const QString& filename) const
return path;
}
kDebug() << path << "does not exist";
return QString();
}
@ -149,7 +153,7 @@ QStringList Package::entryList(const char* fileType) const
return QStringList();
}
QDir dir(d->basePath + "contents/" + path);
QDir dir(d->basePath + d->structure->contentsPrefix() + path);
if (!dir.exists()) {
return QStringList();
@ -268,27 +272,61 @@ bool Package::installPackage(const QString& package,
// and now we register it as a service =)
targetName.append("/metadata.desktop");
KConfigGroup cg = KDesktopFile(targetName).desktopGroup();
// should not installing it as a service disqualify it?
// i don't think so since KServiceTypeTrader may not be
// used by the installing app in any case, and the
// 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;
}
bool Package::registerPackage(const QString &desktopFilePath)
bool Package::registerPackage(const PackageMetadata &data, const QString &iconPath)
{
QString service = KStandardDirs::locateLocal("services", KGlobal::mainComponent().componentName());
KPluginInfo pluginInfo(desktopFilePath);
QString serviceName("plasma-applet-" + data.pluginName());
QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
if (pluginInfo.pluginName().isEmpty()) {
if (data.pluginName().isEmpty()) {
return false;
}
service.append(pluginInfo.pluginName()).append(".desktop");
KIO::FileCopyJob *job = KIO::file_copy(desktopFilePath, service, -1, KIO::HideProgressInfo);
return job->exec();
data.write(service);
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,
@ -314,7 +352,7 @@ bool Package::createPackage(const PackageMetadata &metadata,
if (!creation.open(QIODevice::WriteOnly)) {
return false;
}
creation.addLocalFile(metadataFile.fileName(), "metadata.desktop");
creation.addLocalDirectory(source, "contents");
creation.close();

View File

@ -136,7 +136,7 @@ class PLASMA_EXPORT Package
* @arg the full path to the desktop file (must be KPluginInfo compatible)
* @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
//static bool uninstallPackage(const QString& package, const QString& packageRoot);

View File

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

View File

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

View File

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

View File

@ -224,7 +224,22 @@ public:
**/
virtual bool installPackage(const QString &archivePath, const QString &packageRoot);
/**
* @return the prefix inserted between the base path and content entries
*/
QString contentsPrefix() const;
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();
private:

View File

@ -34,7 +34,7 @@ static const char version[] = "1.0";
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,
ki18n("(C) 2008, Aaron Seigo"));
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->website(), QString("http://plasma.kde.org/"));
QCOMPARE(pm->license(), QString("GPL"));
QCOMPARE(pm->mainFile(), QString("Main file"));
QCOMPARE(pm->application(), QString("A Test name"));
QCOMPARE(pm->requiredVersion(), QString("1.2.3"));
QCOMPARE(pm->type(), QString("System test"));
@ -89,7 +88,6 @@ void PackageMetadataTest::write()
pm->setVersion(QString("pre0.1"));
pm->setWebsite(QString("http://plasma.kde.org/"));
pm->setLicense(QString("GPL"));
pm->setMainFile(QString("Main file"));
pm->setApplication(QString("A Test name"));
pm->setRequiredVersion(QString("1.2.3"));
@ -106,7 +104,6 @@ void PackageMetadataTest::write()
QCOMPARE(pm->version(), QString("pre0.1"));
QCOMPARE(pm->website(), QString("http://plasma.kde.org/"));
QCOMPARE(pm->license(), QString("GPL"));
QCOMPARE(pm->mainFile(), QString("Main file"));
QCOMPARE(pm->application(), QString("A Test name"));
QCOMPARE(pm->requiredVersion(), QString("1.2.3"));
}