diff --git a/package.cpp b/package.cpp index a7f3a06cf..2bf844592 100644 --- a/package.cpp +++ b/package.cpp @@ -36,7 +36,6 @@ #include #include "packagemetadata.h" -#include "packagestructure.h" namespace Plasma { @@ -44,7 +43,7 @@ namespace Plasma class Package::Private { public: - Private(const PackageStructure& st, const QString& p) + Private(const PackageStructure::Ptr st, const QString& p) : structure(st), basePath(p), valid(QFile::exists(basePath)), @@ -54,26 +53,25 @@ public: basePath.append('/'); } } - + ~Private() { delete metadata; } - PackageStructure structure; + const PackageStructure::Ptr structure; QString basePath; bool valid; PackageMetadata *metadata; - }; Package::Package(const QString& packageRoot, const QString& package, - const PackageStructure& structure) + const PackageStructure::Ptr structure) : d(new Private(structure, packageRoot + '/' + package)) { } -Package::Package(const QString &packagePath, const PackageStructure &structure) +Package::Package(const QString &packagePath, const PackageStructure::Ptr structure) : d(new Private(structure, packagePath)) { } @@ -89,18 +87,18 @@ bool Package::isValid() const return false; } - foreach (const char *dir, d->structure.requiredDirectories()) { - if (!QFile::exists(d->basePath + "contents/" + d->structure.path(dir))) { + foreach (const char *dir, d->structure->requiredDirectories()) { + if (!QFile::exists(d->basePath + "contents/" + d->structure->path(dir))) { kWarning(505) << "Could not find required directory" << dir; d->valid = false; return false; } } - foreach (const char *file, d->structure.requiredFiles()) { - if (!QFile::exists(d->basePath + "contents/" + d->structure.path(file))) { + foreach (const char *file, d->structure->requiredFiles()) { + if (!QFile::exists(d->basePath + "contents/" + d->structure->path(file))) { kWarning(505) << "Could not find required file" << file << ", look in" - << d->basePath + "contents/" + d->structure.path(file) << endl; + << d->basePath + "contents/" + d->structure->path(file) << endl; d->valid = false; return false; } @@ -115,7 +113,7 @@ QString Package::filePath(const char* fileType, const QString& filename) const return QString(); } - QString path = d->structure.path(fileType); + QString path = d->structure->path(fileType); if (path.isEmpty()) { return QString(); @@ -145,7 +143,7 @@ QStringList Package::entryList(const char* fileType) const return QStringList(); } - QString path = d->structure.path(fileType); + QString path = d->structure->path(fileType); if (path.isEmpty()) { return QStringList(); } @@ -159,7 +157,7 @@ QStringList Package::entryList(const char* fileType) const return dir.entryList(QDir::Files | QDir::Readable); } -const PackageMetadata *Package::metadata() const +const PackageMetadata* Package::metadata() const { if (!d->metadata) { d->metadata = new PackageMetadata(d->basePath + "metadata.desktop"); diff --git a/package.h b/package.h index 974313fa1..a36474ac1 100644 --- a/package.h +++ b/package.h @@ -24,6 +24,7 @@ #include #include +#include namespace Plasma { @@ -33,7 +34,6 @@ namespace Plasma **/ class PackageMetadata; -class PackageStructure; class PLASMA_EXPORT Package { @@ -46,15 +46,15 @@ class PLASMA_EXPORT Package * @arg structure the package structure describing this package **/ Package(const QString& packageRoot, const QString& package, - const PackageStructure& structure); - + const PackageStructure::Ptr structure); + /** * Construct a Package object. * * @arg packagePath full path to the package directory * @arg structure the package structure describing this package */ - Package(const QString &packagePath, const PackageStructure &structure); + Package(const QString &packagePath, const PackageStructure::Ptr structure); //TODO for 4.1: be able to load an uninstalled/uncompressed file. diff --git a/packages.cpp b/packages.cpp index b35ff9131..fff23b246 100644 --- a/packages.cpp +++ b/packages.cpp @@ -24,8 +24,8 @@ namespace Plasma { -PlasmoidPackage::PlasmoidPackage() - : Plasma::PackageStructure(QString("Plasmoid")) +PlasmoidPackage::PlasmoidPackage(QObject *parent) + : Plasma::PackageStructure(parent, QString("Plasmoid")) { addDirectoryDefinition("images", "images", i18n("Images")); QStringList mimetypes; @@ -52,8 +52,8 @@ PlasmoidPackage::PlasmoidPackage() setRequired("mainscript", true); } -ThemePackage::ThemePackage() - : Plasma::PackageStructure(QString("Plasma Theme")) +ThemePackage::ThemePackage(QObject *parent) + : Plasma::PackageStructure(parent, QString("Plasma Theme")) { addDirectoryDefinition("dialogs", "dialogs/", i18n("Images for dialogs")); addFileDefinition("dialogs/background", "dialogs/background.svg", @@ -112,4 +112,5 @@ ThemePackage::ThemePackage() } // namespace Plasma +#include "packages_p.moc" diff --git a/packages_p.h b/packages_p.h index 09b8c1811..b3d78d5d1 100644 --- a/packages_p.h +++ b/packages_p.h @@ -27,14 +27,16 @@ namespace Plasma class PlasmoidPackage : public PackageStructure { + Q_OBJECT public: - explicit PlasmoidPackage(); + explicit PlasmoidPackage(QObject *parent = 0); }; class ThemePackage : public PackageStructure { + Q_OBJECT public: - explicit ThemePackage(); + explicit ThemePackage(QObject *parent = 0); }; } // namespace Plasma diff --git a/packagestructure.cpp b/packagestructure.cpp index 4597f705a..9a8fbe0be 100644 --- a/packagestructure.cpp +++ b/packagestructure.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "packages_p.h" @@ -54,48 +55,71 @@ class ContentStructure bool required; }; + class PackageStructure::Private { - public: - QString type; - QMap contents; - QStringList mimetypes; +public: + QString type; + QMap contents; + QStringList mimetypes; + static QHash structures; }; -PackageStructure::PackageStructure(const QString &type) - : d(new Private) +QHash PackageStructure::Private::structures; + +PackageStructure::PackageStructure(QObject *parent, const QString &type) + : QObject(parent), + d(new Private) { d->type = type; } -PackageStructure::PackageStructure(const PackageStructure& rhs) - : d(new Private) -{ - *d = *rhs.d; -} - PackageStructure::~PackageStructure() { delete d; } -PackageStructure PackageStructure::load(const QString &packageFormat) +PackageStructure::Ptr PackageStructure::load(const QString &packageFormat) { - PackageStructure ps; - if (packageFormat.isEmpty()) { - return ps; + return Ptr(new PackageStructure()); } + PackageStructure::Ptr structure = Private::structures[packageFormat]; + + if (structure) { + return structure; + } + + // first we check for plugins in sycoca + QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat); + KService::List offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure", constraint); + + QVariantList args; + QString error; + foreach (const KService::Ptr &offer, offers) { + PackageStructure::Ptr structure(offer->createInstance(0, args, &error)); + + if (structure) { + Private::structures[packageFormat] = structure; + return structure; + } + + kDebug() << "Couldn't load PackageStructure for" << packageFormat << "! reason given: " << error; + } + + // if that didn't give us any love, then we try to load from a config file + structure = new PackageStructure(); QString configPath("plasma/packageformats/%1rc"); configPath = KStandardDirs::locate("data", configPath.arg(packageFormat)); if (!configPath.isEmpty()) { KConfig config(configPath); - ps.read(&config); + structure->read(&config); } - return ps; + Private::structures[packageFormat] = structure; + return structure; } PackageStructure& PackageStructure::operator=(const PackageStructure& rhs) @@ -308,3 +332,5 @@ void PackageStructure::write(KConfigBase *config) const } // Plasma namespace +#include "packagestructure.moc" + diff --git a/packagestructure.h b/packagestructure.h index fcfa01a2d..4ba1f5564 100644 --- a/packagestructure.h +++ b/packagestructure.h @@ -21,8 +21,11 @@ #define PACKAGESTRUCTURE_H #include +#include +#include #include +#include #include @@ -61,15 +64,19 @@ namespace Plasma * Either way, PackageStructure creates a sort of "contract" between the packager and * the application which is also self-documenting. **/ -class PLASMA_EXPORT PackageStructure +class PLASMA_EXPORT PackageStructure : public QObject, public QSharedData { + Q_OBJECT + public: + typedef KSharedPtr Ptr; + /** * Default constructor for a package structure definition * * @arg type the type of package. This is often application specific. **/ - explicit PackageStructure(const QString &type = i18n("Invalid")); + explicit PackageStructure(QObject *parent = 0, const QString &type = i18n("Invalid")); /** * Copy constructor @@ -94,7 +101,7 @@ public: * @return a package that matches the format, if available. The caller * is responsible for deleting the object. */ - static PackageStructure load(const QString &package); + static PackageStructure::Ptr load(const QString &package); /** * Type of package this structure describes @@ -205,5 +212,12 @@ private: Private * const d; }; +/** + * Register an applet when it is contained in a loadable module + */ +#define K_EXPORT_PLASMA_PACKAGESTRUCTURE(libname, classname) \ +K_PLUGIN_FACTORY(factory, registerPlugin();) \ +K_EXPORT_PLUGIN(factory("plasma_packagestructure_" #libname)) + } // Plasma namespace #endif