Change in plasma-framework[master]: migrate to KPackage

Marco Martin (Code Review) noreply at kde.org
Tue Dec 23 12:49:05 UTC 2014


Marco Martin has uploaded a new change for review.

  https://gerrit.vesnicky.cesnet.cz/r/260

Change subject: migrate to KPackage
......................................................................

migrate to KPackage

Plasma::Package internally uses KPackage, being a pure wrapper.
old client code and old packagestructures still work using the wrapper.
old workspace code that is not directly using kpackage continues to work correctly

Change-Id: I05f95e8d05e3b67759973c4009e3753c61b1dcce
---
M CMakeLists.txt
M src/plasma/CMakeLists.txt
M src/plasma/applet.cpp
M src/plasma/applet.h
M src/plasma/corona.cpp
M src/plasma/corona.h
M src/plasma/package.cpp
M src/plasma/package.h
M src/plasma/packagestructure.cpp
M src/plasma/packagestructure.h
M src/plasma/pluginloader.cpp
M src/plasma/private/applet_p.cpp
M src/plasma/private/applet_p.h
M src/plasma/private/corona_p.h
M src/plasma/private/package_p.h
D src/plasma/private/packagejob.cpp
D src/plasma/private/packagejob_p.h
D src/plasma/private/packagejobthread.cpp
D src/plasma/private/packagejobthread_p.h
M src/plasma/private/packages.cpp
M src/plasma/private/packages_p.h
A src/plasma/private/packagestructure_p.h
M src/plasmaquick/packageurlinterceptor.cpp
23 files changed, 345 insertions(+), 1,455 deletions(-)


  git pull ssh://gerrit.vesnicky.cesnet.cz:29418/plasma-framework refs/changes/60/260/1

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ccec0ed..891183c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,6 +59,7 @@
 find_package(KF5WindowSystem ${KF5_DEP_VERSION} REQUIRED)
 find_package(KF5XmlGui ${KF5_DEP_VERSION} REQUIRED)
 find_package(KF5Notifications ${KF5_DEP_VERSION} REQUIRED)
+find_package(KF5Package ${KF5_DEP_VERSION} REQUIRED)
 
 find_package(KF5DocTools ${KF5_DEP_VERSION})
 set_package_properties(KF5DocTools PROPERTIES DESCRIPTION "Tools to generate documentation"
diff --git a/src/plasma/CMakeLists.txt b/src/plasma/CMakeLists.txt
index f7aa38b..423b3e7 100644
--- a/src/plasma/CMakeLists.txt
+++ b/src/plasma/CMakeLists.txt
@@ -66,8 +66,6 @@
 #packages
     package.cpp
     packagestructure.cpp
-    private/packagejob.cpp
-    private/packagejobthread.cpp
     private/packages.cpp
 
 #graphics
@@ -112,6 +110,7 @@
 PUBLIC
     KF5::Service # For kplugininfo.h and kservice.h
     Qt5::Gui
+    KF5::Package
 PRIVATE
     Qt5::Sql
     Qt5::Svg
diff --git a/src/plasma/applet.cpp b/src/plasma/applet.cpp
index 5594bf8..1793a94 100644
--- a/src/plasma/applet.cpp
+++ b/src/plasma/applet.cpp
@@ -287,7 +287,12 @@
 
 Package Applet::package() const
 {
-    return d->package ? *d->package : Package();
+    return d->legacyPackage ? *d->legacyPackage : Package();
+}
+
+KPackage::Package Applet::kPackage() const
+{
+    return d->package ? *d->package : KPackage::Package();
 }
 
 void Applet::updateConstraints(Plasma::Types::Constraints constraints)
diff --git a/src/plasma/applet.h b/src/plasma/applet.h
index a30a7ac..daff8df 100644
--- a/src/plasma/applet.h
+++ b/src/plasma/applet.h
@@ -33,6 +33,8 @@
 #include <plasma/version.h>
 #include <plasma/framesvg.h>
 
+#include <KPackage/Package>
+
 class KActionCollection;
 class KConfigLoader;
 
@@ -224,13 +226,26 @@
     void setUserConfiguring(bool configuring);
 
 //UTILS
+#ifndef PLASMA_NO_DEPRECATED
+    /**
+     * Accessor for the associated Package object if any.
+     * Generally, only Plasmoids come in a Package.
+     * Deprecated: please use kPackage()
+     *
+     * @deprecated use kPackage() instead
+     * @return the Package object, or an invalid one if none
+     **/
+    PLASMA_DEPRECATED Package package() const;
+#endif
+
     /**
      * Accessor for the associated Package object if any.
      * Generally, only Plasmoids come in a Package.
      *
      * @return the Package object, or an invalid one if none
+     * @since 5.5
      **/
-    Package package() const;
+    KPackage::Package kPackage() const;
 
     /**
      * Called when any of the geometry constraints have been updated.
diff --git a/src/plasma/corona.cpp b/src/plasma/corona.cpp
index 038be7b..b04a510 100644
--- a/src/plasma/corona.cpp
+++ b/src/plasma/corona.cpp
@@ -38,8 +38,10 @@
 
 #include "containment.h"
 #include "pluginloader.h"
+#include "packagestructure.h"
 #include "private/applet_p.h"
 #include "private/containment_p.h"
+#include "private/package_p.h"
 #include "private/timetracker.h"
 
 using namespace Plasma;
@@ -71,15 +73,28 @@
 
 Plasma::Package Corona::package() const
 {
-    return d->package;
+    return d->legacyPackage;
 }
 
 void Corona::setPackage(const Plasma::Package &package)
 {
-    d->package = package;
+    d->legacyPackage = package;
     emit packageChanged(package);
 }
 
+KPackage::Package Corona::kPackage() const
+{
+    return d->package;
+}
+
+void Corona::setKPackage(const KPackage::Package &package)
+{
+    d->package = package;
+    d->legacyPackage = Package(new PackageStructure());
+    d->legacyPackage.d->internalPackage = new KPackage::Package(package);
+    emit kPackageChanged(package);
+}
+
 void Corona::saveLayout(const QString &configName) const
 {
     KSharedConfigPtr c;
diff --git a/src/plasma/corona.h b/src/plasma/corona.h
index 6e92502..42ba22e 100644
--- a/src/plasma/corona.h
+++ b/src/plasma/corona.h
@@ -43,10 +43,32 @@
     Q_OBJECT
     Q_PROPERTY(bool isStartupCompleted READ isStartupCompleted NOTIFY startupCompleted)
     Q_PROPERTY(Package package READ package NOTIFY packageChanged)
+    Q_PROPERTY(KPackage::Package package READ kPackage NOTIFY kPackageChanged)
 
 public:
     explicit Corona(QObject *parent = 0);
     ~Corona();
+
+#ifndef PLASMA_NO_DEPRECATED
+    /**
+     * Accessor for the associated Package object if any.
+     * A Corona package defines how Containments are laid out in a View,
+     * ToolBoxes, default layout, error messages
+     * and in genelal all the furniture specific of a particular
+     * device form factor.
+     *
+     * @deprecated use kPackage instead
+     * @return the Package object, or an invalid one if none
+     * @since 5.0
+     **/
+    PLASMA_DEPRECATED Plasma::Package package() const;
+
+    /**
+     * Setting the package name
+     * @deprecated use setKPackage instead
+     */
+    PLASMA_DEPRECATED void setPackage(const Plasma::Package &package);
+#endif
 
     /**
      * Accessor for the associated Package object if any.
@@ -56,14 +78,15 @@
      * device form factor.
      *
      * @return the Package object, or an invalid one if none
-     * @since 5.0
+     * @since 5.5
      **/
-    Plasma::Package package() const;
+    KPackage::Package kPackage() const;
 
     /**
-     * Setting the package name
+     * Setting the package for the corona
+     * @since 5.5
      */
-    void setPackage(const Plasma::Package &package);
+    void setKPackage(const KPackage::Package &package);
 
     /**
      * @return all containments on this Corona
@@ -278,13 +301,24 @@
      */
     void immutabilityChanged(Plasma::Types::ImmutabilityType immutability);
 
+#ifndef PLASMA_NO_DEPRECATED
+    /**
+     * Emitted when the package for this corona has been changed.
+     * Shells must support changing the shell package on the fly (for instance due to device form factor changing)
+     *
+     * @deprecated use kPackageChanged instead
+     * @param package the new package that defines the Corona furniture and behavior
+     */
+    PLASMA_DEPRECATED void packageChanged(const Plasma::Package &package);
+#endif
+
     /**
      * Emitted when the package for this corona has been changed.
      * Shells must support changing the shell package on the fly (for instance due to device form factor changing)
      *
      * @param package the new package that defines the Corona furniture and behavior
      */
-    void packageChanged(const Plasma::Package &package);
+    void kPackageChanged(const KPackage::Package &package);
 
     /**
      * Emitted when the startup phase has been completed
diff --git a/src/plasma/package.cpp b/src/plasma/package.cpp
index 07b3c90..fa40c04 100644
--- a/src/plasma/package.cpp
+++ b/src/plasma/package.cpp
@@ -39,35 +39,57 @@
 #include "packagestructure.h"
 #include "pluginloader.h"
 #include "private/package_p.h"
+#include "private/packagestructure_p.h"
 #include "private/packages_p.h"
-#include "private/packagejob_p.h"
 
 namespace Plasma
 {
 
+PackagePrivate::PackagePrivate()
+    : internalPackage(0),
+      fallbackPackage(0),
+      structure(0)
+{
+}
+
+PackagePrivate::~PackagePrivate()
+{
+}
+
+
 Package::Package(PackageStructure *structure)
-    : d(new PackagePrivate())
+    : d(new Plasma::PackagePrivate())
 {
     d->structure = structure;
 
-    if (d->structure) {
-        d->structure.data()->initPackage(this);
+    if (!structure) {
+        d->internalPackage = new KPackage::Package();
+        return;
     }
+
+    if (!structure->d->internalStructure) {
+        d->structure->d->internalStructure = new KPackage::PackageStructure;
+    }
+
+    d->internalPackage = new KPackage::Package(structure->d->internalStructure);
+    structure->initPackage(this);
 }
 
 Package::Package(const Package &other)
-    : d(other.d)
+    : d(new Plasma::PackagePrivate())
 {
+    d->internalPackage = new KPackage::Package(*other.d->internalPackage);
 }
 
 Package::~Package()
 {
+    delete d->internalPackage;
 }
 
 Package &Package::operator=(const Package &rhs)
 {
     if (&rhs != this) {
-        d = rhs.d;
+        d->internalPackage = new KPackage::Package(*rhs.d->internalPackage);
     }
 
     return *this;
@@ -75,130 +97,43 @@
 
 bool Package::hasValidStructure() const
 {
-    return d->structure;
+    return d->internalPackage->hasValidStructure();
 }
 
 bool Package::isValid() const
 {
-    if (!d->structure) {
-        return false;
-    }
-
-    //Minimal packages with no metadata *are* supposed to be possible
-    //so if !metadata().isValid() go ahead
-    if (metadata().isValid() && metadata().isHidden()) {
-        return false;
-    }
-
-    if (d->checkedValid) {
-        return d->valid;
-    }
-
-    d->valid = true;
-
-    //search for the file in all prefixes and in all possible paths for each prefix
-    //even if it's a big nested loop, usually there is one prefix and one location
-    //so shouldn't cause too much disk access
-    QHashIterator<QByteArray, ContentStructure> it(d->contents);
-    const QString rootPath = d->tempRoot.isEmpty() ? d->path : d->tempRoot;
-
-    while (it.hasNext()) {
-        it.next();
-        if (!it.value().required) {
-            continue;
-        }
-
-        bool failed = true;
-        foreach (const QString &path, it.value().paths) {
-            foreach (const QString &prefix, d->contentsPrefixPaths) {
-                if (QFile::exists(rootPath + prefix + path)) {
-                    failed = false;
-                    break;
-                }
-            }
-
-            if (!failed) {
-                break;
-            }
-        }
-
-        if (failed) {
-            //qWarning() << "Could not find required" << (it.value().directory ? "directory" : "file") << it.key() << "for package" << path();
-            d->valid = false;
-            break;
-        }
-    }
-
-    return d->valid;
+    return d->internalPackage->isValid();
 }
 
 QString Package::name(const char *key) const
 {
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
-    if (it == d->contents.constEnd()) {
-        return QString();
-    }
-
-    return it.value().name;
-#else
-    Q_UNUSED(key);
-    return QString();
-#endif
+    return d->internalPackage->name(key);
 }
 
 bool Package::isRequired(const char *key) const
 {
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
-    if (it == d->contents.constEnd()) {
-        return false;
-    }
-
-    return it.value().required;
+    return d->internalPackage->isRequired(key);
 }
 
 QStringList Package::mimeTypes(const char *key) const
 {
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
-    if (it == d->contents.constEnd()) {
-        return QStringList();
-    }
-
-    if (it.value().mimeTypes.isEmpty()) {
-        return d->mimeTypes;
-    }
-
-    return it.value().mimeTypes;
-#else
-    return QStringList();
-#endif
+    return d->internalPackage->mimeTypes(key);
 }
 
 QString Package::defaultPackageRoot() const
 {
-    return d->defaultPackageRoot;
+    return d->internalPackage->defaultPackageRoot();
 }
 
 void Package::setDefaultPackageRoot(const QString &packageRoot)
 {
-    d.detach();
-    d->defaultPackageRoot = packageRoot;
-    if (!d->defaultPackageRoot.isEmpty() && !d->defaultPackageRoot.endsWith('/')) {
-        d->defaultPackageRoot.append('/');
-    }
+    d->internalPackage->setDefaultPackageRoot(packageRoot);
 }
 
 void Package::setFallbackPackage(const Plasma::Package &package)
 {
-    if ((d->fallbackPackage && d->fallbackPackage->path() == package.path() && d->fallbackPackage->metadata() == package.metadata()) ||
-        //can't be fallback of itself
-        (package.path() == path() && package.metadata() == metadata()) ||
-        d->hasCycle(package)) {
-        return;
-    }
-
     d->fallbackPackage = new Package(package);
+    d->internalPackage->setFallbackPackage(*package.d->internalPackage);
 }
 
 Plasma::Package Package::fallbackPackage() const
@@ -217,553 +152,132 @@
 
 void Package::setServicePrefix(const QString &servicePrefix)
 {
-    d.detach();
     d->servicePrefix = servicePrefix;
 }
 
 bool Package::allowExternalPaths() const
 {
-    return d->externalPaths;
+    return d->internalPackage->allowExternalPaths();
 }
 
 void Package::setAllowExternalPaths(bool allow)
 {
-    d.detach();
-    d->externalPaths = allow;
+    d->internalPackage->setAllowExternalPaths(allow);
 }
 
 KPluginInfo Package::metadata() const
 {
-    //qDebug() << "metadata: " << d->path << filePath("metadata");
-    if (!d->metadata && !d->path.isEmpty()) {
-        const QString metadataPath = filePath("metadata");
-        if (!metadataPath.isEmpty()) {
-            d->createPackageMetadata(metadataPath);
-        } else {
-            // d->path might still be a file, if its path has a trailing /,
-            // the fileInfo lookup will fail, so remove it.
-            QString p = d->path;
-            if (p.endsWith("/")) {
-                p.chop(1);
-            }
-            QFileInfo fileInfo(p);
-
-            if (fileInfo.isDir()) {
-                d->createPackageMetadata(d->path);
-            } else if (fileInfo.exists()) {
-                d->path = p;
-                d->tempRoot = d->unpack(p);
-            }
-        }
-    }
-
-    if (!d->metadata) {
-        d->metadata = new KPluginInfo();
-    }
-
-    return *d->metadata;
-}
-
-QString PackagePrivate::unpack(const QString &filePath)
-{
-    KArchive *archive = 0;
-    QMimeDatabase db;
-    QMimeType mimeType = db.mimeTypeForFile(filePath);
-
-    if (mimeType.inherits("application/zip")) {
-        archive = new KZip(filePath);
-    } else if (mimeType.inherits("application/x-compressed-tar") || mimeType.inherits("application/x-gzip") ||
-               mimeType.inherits("application/x-tar") || mimeType.inherits("application/x-bzip-compressed-tar") ||
-               mimeType.inherits("application/x-xz") || mimeType.inherits("application/x-lzma")) {
-        archive = new KTar(filePath);
-    } else {
-        //qWarning() << "Could not open package file, unsupported archive format:" << filePath << mimeType.name();
-    }
-    QString tempRoot;
-    if (archive && archive->open(QIODevice::ReadOnly)) {
-        const KArchiveDirectory *source = archive->directory();
-        QTemporaryDir tempdir;
-        tempdir.setAutoRemove(false);
-        tempRoot = tempdir.path() + '/';
-        source->copyTo(tempRoot);
-
-        if (!QFile::exists(tempdir.path() + "/metadata.desktop")) {
-            // search metadata.desktop, the zip file might have the package contents in a subdirectory
-            QDir unpackedPath(tempdir.path());
-            const QStringList &entries = unpackedPath.entryList(QDir::Dirs);
-            foreach (const QString &pack, entries) {
-                if ((pack != "." && pack != "..") &&
-                        (QFile::exists(unpackedPath.absolutePath() + '/' + pack + "/metadata.desktop"))) {
-                    tempRoot = unpackedPath.absolutePath() + '/' + pack + '/';
-                }
-            }
-        }
-
-        createPackageMetadata(tempRoot);
-    } else {
-        //qWarning() << "Could not open package file:" << path;
-    }
-
-    delete archive;
-    return tempRoot;
+    return KPluginInfo::fromMetaData(d->internalPackage->metadata());
 }
 
 QString Package::filePath(const char *fileType, const QString &filename) const
 {
-    if (!d->valid) {
-        //qDebug() << "package is not valid";
-        return d->fallbackFilePath(fileType, filename);
-    }
-
-    const QString discoveryKey(fileType + filename);
-    if (d->discoveries.contains(discoveryKey)) {
-        //qDebug() << "looking for" << discoveryKey << d->discoveries.value(discoveryKey);
-        return d->discoveries[discoveryKey];
-    }
-
-    QStringList paths;
-
-    if (qstrlen(fileType) != 0) {
-        //qDebug()<<d->contents.keys();
-        if (!d->contents.contains(fileType)) {
-            //qDebug() << "package does not contain" << fileType << filename;
-            return d->fallbackFilePath(fileType, filename);
-        }
-
-        paths = d->contents[fileType].paths;
-
-        if (paths.isEmpty()) {
-            //qDebug() << "no matching path came of it, while looking for" << fileType << filename;
-            d->discoveries.insert(discoveryKey, QString());
-            return d->fallbackFilePath(fileType, filename);
-        }
-    } else {
-        //when filetype is empty paths is always empty, so try with an empty string
-        paths << QString();
-    }
-
-    //Nested loop, but in the medium case resolves to just one iteration
-    //qDebug() << "prefixes:" << prefixes.count() << prefixes;
-    foreach (const QString &contentsPrefix, d->contentsPrefixPaths) {
-        const QString prefix(d->path + contentsPrefix);
-
-        foreach (const QString &path, paths) {
-            QString file = prefix + path;
-
-            if (!filename.isEmpty()) {
-                file.append("/").append(filename);
-            }
-
-            //qDebug() << "testing" << file << QFile::exists("/bin/ls") << QFile::exists(file);
-            if (QFile::exists(file)) {
-                if (d->externalPaths) {
-                    //qDebug() << "found" << file;
-                    d->discoveries.insert(discoveryKey, file);
-                    return file;
-                }
-
-                // ensure that we don't return files outside of our base path
-                // due to symlink or ../ games
-                QDir dir(file);
-                QString canonicalized = dir.canonicalPath() + QDir::separator();
-
-                //qDebug() << "testing that" << canonicalized << "is in" << d->path;
-                if (canonicalized.startsWith(d->path)) {
-                    //qDebug() << "found" << file;
-                    d->discoveries.insert(discoveryKey, file);
-                    return file;
-                }
-            }
-        }
-    }
-
-    //qDebug() << fileType << filename << "does not exist in" << prefixes << "at root" << d->path;
-    return d->fallbackFilePath(fileType, filename);
+    return d->internalPackage->filePath(fileType, filename);
 }
 
 QStringList Package::entryList(const char *key) const
 {
-    if (!d->valid) {
-        return QStringList();
-    }
-
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
-    if (it == d->contents.constEnd()) {
-        //qDebug() << "couldn't find" << key;
-        return QStringList();
-    }
-
-    //qDebug() << "going to list" << key;
-    QStringList list;
-    foreach (const QString &prefix, d->contentsPrefixPaths) {
-        //qDebug() << "     looking in" << prefix;
-        foreach (const QString &path, it.value().paths) {
-            //qDebug() << "         looking in" << path;
-            if (it.value().directory) {
-                //qDebug() << "it's a directory, so trying out" << d->path + prefix + path;
-                QDir dir(d->path + prefix + path);
-
-                if (d->externalPaths) {
-                    list += dir.entryList(QDir::Files | QDir::Readable);
-                } else {
-                    // ensure that we don't return files outside of our base path
-                    // due to symlink or ../ games
-                    QString canonicalized = dir.canonicalPath();
-                    if (canonicalized.startsWith(d->path)) {
-                        list += dir.entryList(QDir::Files | QDir::Readable);
-                    }
-                }
-            } else {
-                const QString fullPath = d->path + prefix + path;
-                //qDebug() << "it's a file at" << fullPath << QFile::exists(fullPath);
-                if (!QFile::exists(fullPath)) {
-                    continue;
-                }
-
-                if (d->externalPaths) {
-                    list += fullPath;
-                } else {
-                    QDir dir(fullPath);
-                    QString canonicalized = dir.canonicalPath() + QDir::separator();
-
-                    //qDebug() << "testing that" << canonicalized << "is in" << d->path;
-                    if (canonicalized.startsWith(d->path)) {
-                        list += fullPath;
-                    }
-                }
-            }
-        }
-    }
-
-    return list;
+    return d->internalPackage->entryList(key);
 }
 
 void Package::setPath(const QString &path)
 {
-    // if the path is already what we have, don't bother
-    if (path == d->path) {
+    if (path == d->internalPackage->path()) {
         return;
     }
 
-    // our dptr is shared, and it is almost certainly going to change.
-    // hold onto the old pointer just in case it does not, however!
-    QExplicitlySharedDataPointer<PackagePrivate> oldD(d);
-    d.detach();
-
-    // without structure we're doomed
-    if (!d->structure) {
-        d->path.clear();
-        d->discoveries.clear();
-        d->valid = false;
-        d->checkedValid = true;
-        return;
+    if (d->structure && !d->structure->d->internalStructure) {
+        d->structure->pathChanged(this);
     }
-
-    // empty path => nothing to do
-    if (path.isEmpty()) {
-        d->path.clear();
-        d->discoveries.clear();
-        d->valid = false;
-        d->structure.data()->pathChanged(this);
-        return;
-    }
-
-    // now we look for all possible paths, including resolving
-    // relative paths against the system search paths
-    QStringList paths;
-    if (QDir::isRelativePath(path)) {
-        QString p;
-
-        if (d->defaultPackageRoot.isEmpty()) {
-            p = path % "/";
-        } else {
-            p = d->defaultPackageRoot % path % "/";
-        }
-
-        if (QDir::isRelativePath(p)) {
-            paths << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, p, QStandardPaths::LocateDirectory);
-        } else {
-            const QDir dir(p);
-            if (QFile::exists(dir.canonicalPath())) {
-                paths << p;
-            }
-        }
-
-        //qDebug() << "paths:" << p << paths << d->defaultPackageRoot;
-    } else {
-        const QDir dir(path);
-        if (QFile::exists(dir.canonicalPath())) {
-            paths << path;
-        }
-    }
-
-    QFileInfo fileInfo(path);
-    if (fileInfo.isFile() && d->tempRoot.isEmpty()) {
-        d->path = path;
-        d->tempRoot = d->unpack(path);
-    }
-
-    // now we search each path found, caching our previous path to know if
-    // anything actually really changed
-    const QString previousPath = d->path;
-    foreach (const QString &p, paths) {
-        d->checkedValid = false;
-        d->path = p;
-
-        if (!d->path.endsWith('/')) {
-            d->path.append('/');
-        }
-
-        // we need to tell the structure we're changing paths ...
-        d->structure.data()->pathChanged(this);
-        // ... and then testing the results for validity
-        if (isValid()) {
-            break;
-        }
-    }
-
-
-    // if nothing did change, then we go back to the old dptr
-    if (d->path == previousPath) {
-        d = oldD;
-        return;
-    }
-
-    // .. but something did change, so we get rid of our discovery cache
-    d->discoveries.clear();
-    delete d->metadata;
-    d->metadata = 0;
-
-    QString fallback;
-
-    // uh-oh, but we didn't end up with anything valid, so we sadly reset ourselves
-    // to futility.
-    if (!d->valid) {
-        d->path.clear();
-        d->structure.data()->pathChanged(this);
-    }
+    d->internalPackage->setPath(path);
 }
 
 const QString Package::path() const
 {
-    return d->path;
+    return d->internalPackage->path();
 }
 
 QStringList Package::contentsPrefixPaths() const
 {
-    return d->contentsPrefixPaths;
+    return d->internalPackage->contentsPrefixPaths();
 }
 
 void Package::setContentsPrefixPaths(const QStringList &prefixPaths)
 {
-    d.detach();
-    d->contentsPrefixPaths = prefixPaths;
-    if (d->contentsPrefixPaths.isEmpty()) {
-        d->contentsPrefixPaths << QString();
-    } else {
-        // the code assumes that the prefixes have a trailing slash
-        // so let's make that true here
-        QMutableStringListIterator it(d->contentsPrefixPaths);
-        while (it.hasNext()) {
-            it.next();
-
-            if (!it.value().endsWith('/')) {
-                it.setValue(it.value() % '/');
-            }
-        }
-    }
+    d->internalPackage->setContentsPrefixPaths(prefixPaths);
 }
 
 QString Package::contentsHash() const
 {
-    if (!d->valid) {
-        qWarning() << "can not create hash due to Package being invalid";
-        return QString();
-    }
-
-    QCryptographicHash hash(QCryptographicHash::Sha1);
-    QString metadataPath = d->path + "metadata.desktop";
-    if (QFile::exists(metadataPath)) {
-        QFile f(metadataPath);
-        if (f.open(QIODevice::ReadOnly)) {
-            while (!f.atEnd()) {
-                hash.addData(f.read(1024));
-            }
-        } else {
-            qWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading.";
-        }
-    } else {
-        qWarning() << "no metadata at" << metadataPath;
-    }
-
-    foreach (QString prefix, d->contentsPrefixPaths) {
-        const QString basePath = d->path + prefix;
-        QDir dir(basePath);
-
-        if (!dir.exists()) {
-            return QString();
-        }
-
-        d->updateHash(basePath, QString(), dir, hash);
-    }
-
-    return hash.result().toHex();
+    return d->internalPackage->contentsHash();
 }
 
 void Package::addDirectoryDefinition(const char *key, const QString &path, const QString &name)
 {
-    ContentStructure s;
-
-    if (d->contents.contains(key)) {
-        s = d->contents[key];
-        if (s.paths.contains(path) && s.directory == true
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-            && s.name == name
-#endif
-        ) {
-            return;
-        }
-    }
-
-    d.detach();
-
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    if (!name.isEmpty()) {
-        s.name = name;
-    }
-#else
-    Q_UNUSED(name)
-#endif
-
-    s.paths.append(path);
-    s.directory = true;
-
-    d->contents[key] = s;
+    d->internalPackage->addDirectoryDefinition(key, path, name);
 }
 
 void Package::addFileDefinition(const char *key, const QString &path, const QString &name)
 {
-    ContentStructure s;
-
-    if (d->contents.contains(key)) {
-        s = d->contents[key];
-        if (s.paths.contains(path) && s.directory == false
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-            && s.name == name
-#endif
-        ) {
-            return;
-        }
-    }
-
-    d.detach();
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    if (!name.isEmpty()) {
-        s.name = name;
-    }
-#else
-    Q_UNUSED(name)
-#endif
-
-    s.paths.append(path);
-    s.directory = false;
-
-    d->contents[key] = s;
+    d->internalPackage->addFileDefinition(key, path, name);
 }
 
 void Package::removeDefinition(const char *key)
 {
-    if (d->contents.contains(key)) {
-        d.detach();
-        d->contents.remove(key);
-    }
+    d->internalPackage->removeDefinition(key);
 }
 
 void Package::setRequired(const char *key, bool required)
 {
-    QHash<QByteArray, ContentStructure>::iterator it = d->contents.find(key);
-    if (it == d->contents.end()) {
-        return;
-    }
-
-    d.detach();
-    // have to find the item again after detaching: d->contents is a different object now
-    it = d->contents.find(key);
-    it.value().required = required;
+    d->internalPackage->setRequired(key, required);
 }
 
 void Package::setDefaultMimeTypes(QStringList mimeTypes)
 {
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    d.detach();
-    d->mimeTypes = mimeTypes;
-#endif
+    d->internalPackage->setDefaultMimeTypes(mimeTypes);
 }
 
 void Package::setMimeTypes(const char *key, QStringList mimeTypes)
 {
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    QHash<QByteArray, ContentStructure>::iterator it = d->contents.find(key);
-    if (it == d->contents.end()) {
-        return;
-    }
-
-    d.detach();
-    // have to find the item again after detaching: d->contents is a different object now
-    it = d->contents.find(key);
-    it.value().mimeTypes = mimeTypes;
-#endif
+    d->internalPackage->setMimeTypes(key, mimeTypes);
 }
 
 QList<const char *> Package::directories() const
 {
     QList<const char *> dirs;
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
-    while (it != d->contents.constEnd()) {
-        if (it.value().directory) {
-            dirs << it.key();
-        }
-        ++it;
+    for (auto data : d->internalPackage->directories()) {
+        dirs << data.constData();
     }
+
     return dirs;
 }
 
 QList<const char *> Package::requiredDirectories() const
 {
+   
     QList<const char *> dirs;
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
-    while (it != d->contents.constEnd()) {
-        if (it.value().directory &&
-                it.value().required) {
-            dirs << it.key();
-        }
-        ++it;
+    for (auto data : d->internalPackage->requiredDirectories()) {
+        dirs << data.constData();
     }
+
     return dirs;
 }
 
 QList<const char *> Package::files() const
 {
     QList<const char *> files;
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
-    while (it != d->contents.constEnd()) {
-        if (!it.value().directory) {
-            files << it.key();
-        }
-        ++it;
+    for (auto data : d->internalPackage->files()) {
+        files << data.constData();
     }
+
     return files;
 }
 
 QList<const char *> Package::requiredFiles() const
 {
     QList<const char *> files;
-    QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
-    while (it != d->contents.constEnd()) {
-        if (!it.value().directory && it.value().required) {
-            files << it.key();
-        }
-        ++it;
+    for (auto data : d->internalPackage->requiredFiles()) {
+        files << data.constData();
     }
 
     return files;
@@ -771,173 +285,12 @@
 
 KJob *Package::install(const QString &sourcePackage, const QString &packageRoot)
 {
-    const QString src = sourcePackage;
-    const QString dest = packageRoot.isEmpty() ? defaultPackageRoot() : packageRoot;
-    //qDebug() << "Source: " << src;
-    //qDebug() << "PackageRoot: " << dest;
-    KJob *j = d->structure.data()->install(this, src, dest);
-    //connect(j, SIGNAL(finished(bool)), SLOT(installFinished(bool)));
-    return j;
+    return d->internalPackage->install(sourcePackage, packageRoot);
 }
 
 KJob *Package::uninstall(const QString &packageName, const QString &packageRoot)
 {
-    d->createPackageMetadata(packageRoot + packageName);
-    return d->structure.data()->uninstall(this, packageRoot);
-}
-
-PackagePrivate::PackagePrivate()
-    : QSharedData(),
-      servicePrefix("plasma-applet-"),
-      fallbackPackage(0),
-      metadata(0),
-      externalPaths(false),
-      valid(false),
-      checkedValid(false)
-{
-    contentsPrefixPaths << "contents/";
-}
-
-PackagePrivate::PackagePrivate(const PackagePrivate &other)
-    : QSharedData()
-{
-    *this = other;
-    metadata = 0;
-}
-
-PackagePrivate::~PackagePrivate()
-{
-    if (!tempRoot.isEmpty()) {
-        QDir dir(tempRoot);
-        dir.removeRecursively();
-    }
-    delete metadata;
-    delete fallbackPackage;
-}
-
-PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
-{
-    if (&rhs == this) {
-        return *this;
-    }
-
-    structure = rhs.structure;
-    if (rhs.fallbackPackage) {
-        fallbackPackage = new Package(*rhs.fallbackPackage);
-    } else {
-        fallbackPackage = 0;
-    }
-    path = rhs.path;
-    contentsPrefixPaths = rhs.contentsPrefixPaths;
-    servicePrefix = rhs.servicePrefix;
-    contents = rhs.contents;
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    mimeTypes = rhs.mimeTypes;
-#endif
-    defaultPackageRoot = rhs.defaultPackageRoot;
-    servicePrefix = rhs.servicePrefix;
-    metadata = 0;
-    externalPaths = rhs.externalPaths;
-    valid = rhs.valid;
-    return *this;
-}
-
-void PackagePrivate::updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCryptographicHash &hash)
-{
-    // hash is calculated as a function of:
-    // * files ordered alphabetically by name, with each file's:
-    //      * path relative to the content root
-    //      * file data
-    // * directories ordered alphabetically by name, with each dir's:
-    //      * path relative to the content root
-    //      * file listing (recursing)
-    // symlinks (in both the file and dir case) are handled by adding
-    // the name of the symlink itself and the abs path of what it points to
-
-    const QDir::SortFlags sorting = QDir::Name | QDir::IgnoreCase;
-    const QDir::Filters filters = QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
-    foreach (const QString &file, dir.entryList(QDir::Files | filters, sorting)) {
-        if (!subPath.isEmpty()) {
-            hash.addData(subPath.toUtf8());
-        }
-
-        hash.addData(file.toUtf8());
-
-        QFileInfo info(dir.path() + '/' + file);
-        if (info.isSymLink()) {
-            hash.addData(info.symLinkTarget().toUtf8());
-        } else {
-            QFile f(info.filePath());
-            if (f.open(QIODevice::ReadOnly)) {
-                while (!f.atEnd()) {
-                    hash.addData(f.read(1024));
-                }
-            } else {
-                qWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading. "
-                           << "permissions fail?" << info.permissions() << info.isFile();
-            }
-        }
-    }
-
-    foreach (const QString &subDirPath, dir.entryList(QDir::Dirs | filters, sorting)) {
-        const QString relativePath = subPath + subDirPath + '/';
-        hash.addData(relativePath.toUtf8());
-
-        QDir subDir(dir.path());
-        subDir.cd(subDirPath);
-
-        if (subDir.path() != subDir.canonicalPath()) {
-            hash.addData(subDir.canonicalPath().toUtf8());
-        } else {
-            updateHash(basePath, relativePath, subDir, hash);
-        }
-    }
-}
-
-void PackagePrivate::createPackageMetadata(const QString &path)
-{
-    delete metadata;
-    QString metadataPath(path + "/metadata.desktop");
-    if (!QFile::exists(metadataPath)) {
-        qWarning() << "No metadata file in the package, expected it at:" << metadataPath;
-        metadataPath.clear();
-    }
-
-    metadata = new KPluginInfo(metadataPath);
-}
-
-QString PackagePrivate::fallbackFilePath(const char *key, const QString &filename) const
-{
-    //don't fallback if the package isn't valid and never fallback the metadata file
-    if (qstrcmp(key, "metadata") != 0 && fallbackPackage && fallbackPackage->isValid()) {
-        return fallbackPackage->filePath(key, filename);
-    } else {
-        return QString();
-    }
-}
-
-bool PackagePrivate::hasCycle(const Plasma::Package &package)
-{
-    if (!package.d->fallbackPackage) {
-        return false;
-    }
-
-    //This is the Floyd cycle detection algorithm
-    //http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
-    Plasma::Package *slowPackage = const_cast<Plasma::Package *>(&package);
-    Plasma::Package *fastPackage = const_cast<Plasma::Package *>(&package);
-
-    while (fastPackage && fastPackage->d->fallbackPackage) {
-        //consider two packages the same if they have the same metadata
-        if ((fastPackage->d->fallbackPackage->metadata().isValid() && fastPackage->d->fallbackPackage->metadata() == slowPackage->metadata()) ||
-            (fastPackage->d->fallbackPackage->d->fallbackPackage && fastPackage->d->fallbackPackage->d->fallbackPackage->metadata().isValid() && fastPackage->d->fallbackPackage->d->fallbackPackage->metadata() == slowPackage->metadata())) {
-            qWarning() << "Warning: the fallback chain of " << package.metadata().pluginName() << "contains a cyclical dependency.";
-            return true;
-        }
-        fastPackage = fastPackage->d->fallbackPackage->d->fallbackPackage;
-        slowPackage = slowPackage->d->fallbackPackage;
-    }
-    return false;
+    return d->internalPackage->uninstall(packageName, packageRoot);
 }
 
 } // Namespace
diff --git a/src/plasma/package.h b/src/plasma/package.h
index 28f8b08..7074655 100644
--- a/src/plasma/package.h
+++ b/src/plasma/package.h
@@ -29,6 +29,8 @@
 
 class KJob;
 
+#ifndef PLASMA_NO_DEPRECATED
+
 namespace Plasma
 {
 
@@ -37,6 +39,7 @@
  *
  * @short object representing an installed Plasma package
  *
+ * @deprecated USe KPAckage::PAckage instead
  * Package defines what is in a package and provides easy access to the contents.
  *
  * To define a package, one might write the following code:
@@ -85,13 +88,13 @@
      * otherwise the structure is allowed to set up the Package's initial layout
      * @since 4.6
      */
-    explicit Package(PackageStructure *structure = 0);
+    PLASMA_DEPRECATED explicit Package(PackageStructure *structure = 0);
 
     /**
      * Copy constructore
      * @since 4.6
      */
-    Package(const Package &other);
+    PLASMA_DEPRECATED Package(const Package &other);
 
     ~Package();
 
@@ -99,7 +102,7 @@
      * Assignment operator
      * @since 4.6
      */
-    Package &operator=(const Package &rhs);
+    PLASMA_DEPRECATED Package &operator=(const Package &rhs);
 
     /**
      * @return true if this package has a valid PackageStructure associatedw it with it.
@@ -107,24 +110,24 @@
      * Package objects in a semi-initialized state (e.g. before calling setPath())
      * @since 5.1
      */
-    bool hasValidStructure() const;
+    PLASMA_DEPRECATED bool hasValidStructure() const;
 
     /**
      * @return true if all the required components exist
      **/
-    bool isValid() const;
+    PLASMA_DEPRECATED bool isValid() const;
 
     /**
      * Sets the path to the root of this package
      * @param path an absolute path, or a relative path to the default package root
      * @since 4.3
      */
-    void setPath(const QString &path);
+    PLASMA_DEPRECATED void setPath(const QString &path);
 
     /**
      * @return the path to the root of this particular package
      */
-    const QString path() const;
+    PLASMA_DEPRECATED const QString path() const;
 
     /**
      * Get the path to a given file based on the key and an optional filename.
@@ -138,7 +141,7 @@
      * @param filename optional name of the file to locate within the package
      * @return path to the file on disk. QString() if not found.
      **/
-    QString filePath(const char *key, const QString &filename = QString()) const;
+    PLASMA_DEPRECATED QString filePath(const char *key, const QString &filename = QString()) const;
 
     /**
      * Get the list of files of a given type.
@@ -147,56 +150,56 @@
      *               package structure.
      * @return list of files by name, suitable for passing to filePath
      **/
-    QStringList entryList(const char *key) const;
+    PLASMA_DEPRECATED QStringList entryList(const char *key) const;
 
     /**
      * @return user visible name for the given entry
      **/
-    QString name(const char *key) const;
+    PLASMA_DEPRECATED QString name(const char *key) const;
 
     /**
      * @return true if the item at path exists and is required
      **/
-    bool isRequired(const char *key) const;
+    PLASMA_DEPRECATED bool isRequired(const char *key) const;
 
     /**
      * @return the mimeTypes associated with the path, if any
      **/
-    QStringList mimeTypes(const char *key) const;
+    PLASMA_DEPRECATED QStringList mimeTypes(const char *key) const;
 
     /**
      * @return the prefix paths inserted between the base path and content entries, in order of priority.
      *         When searching for a file, all paths will be tried in order.
      * @since 4.6
      */
-    QStringList contentsPrefixPaths() const;
+    PLASMA_DEPRECATED QStringList contentsPrefixPaths() const;
 
     /**
      * @return preferred package root. This defaults to plasma/plasmoids/
      */
-    QString defaultPackageRoot() const;
+    PLASMA_DEPRECATED QString defaultPackageRoot() const;
 
     /**
      * @return service prefix used in desktop files. This defaults to plasma-applet-
      */
-    QString servicePrefix() const;
+    PLASMA_DEPRECATED QString servicePrefix() const;
 
     /**
      * @return true if paths/symlinks outside the package itself should be followed.
      * By default this is set to false for security reasons.
      */
-    bool allowExternalPaths() const;
+    PLASMA_DEPRECATED bool allowExternalPaths() const;
 
     /**
       * @return the package metadata object.
       */
-    KPluginInfo metadata() const;
+    PLASMA_DEPRECATED KPluginInfo metadata() const;
 
     /**
      * @return a SHA1 hash digest of the contents of the package in hexadecimal form
      * @since 4.4
      */
-    QString contentsHash() const;
+    PLASMA_DEPRECATED QString contentsHash() const;
 
     /**
      * Adds a directory to the structure of the package. It is added as
@@ -209,7 +212,7 @@
      * @param path the path within the package for this directory
      * @param name the user visible (translated) name for the directory
      **/
-    void addDirectoryDefinition(const char *key, const QString &path, const QString &name);
+    PLASMA_DEPRECATED void addDirectoryDefinition(const char *key, const QString &path, const QString &name);
 
     /**
      * Adds a file to the structure of the package. It is added as
@@ -222,14 +225,14 @@
      * @param path the path within the package for this file
      * @param name the user visible (translated) name for the file
      **/
-    void addFileDefinition(const char *key, const QString &path, const QString &name);
+    PLASMA_DEPRECATED void addFileDefinition(const char *key, const QString &path, const QString &name);
 
     /**
      * Removes a definition from the structure of the package.
      * @since 4.6
      * @param key the internal label of the file or directory to remove
      */
-    void removeDefinition(const char *key);
+    PLASMA_DEPRECATED void removeDefinition(const char *key);
 
     /**
      * Sets whether or not a given part of the structure is required or not.
@@ -239,7 +242,7 @@
      * @param key the entry within the package
      * @param required true if this entry is required, false if not
      */
-    void setRequired(const char *key, bool required);
+    PLASMA_DEPRECATED void setRequired(const char *key, bool required);
 
     /**
      * Defines the default mimeTypes for any definitions that do not have
@@ -248,7 +251,7 @@
      *
      * @param mimeTypes a list of mimeTypes
      **/
-    void setDefaultMimeTypes(QStringList mimeTypes);
+    PLASMA_DEPRECATED void setDefaultMimeTypes(QStringList mimeTypes);
 
     /**
      * Define mimeTypes for a given part of the structure
@@ -258,7 +261,7 @@
      * @param key the entry within the package
      * @param mimeTypes a list of mimeTypes
      **/
-    void setMimeTypes(const char *key, QStringList mimeTypes);
+    PLASMA_DEPRECATED void setMimeTypes(const char *key, QStringList mimeTypes);
 
     /**
      * Sets the prefixes that all the contents in this package should
@@ -271,24 +274,24 @@
      * @param prefix paths the directory prefix to use
      * @since 4.6
      */
-    void setContentsPrefixPaths(const QStringList &prefixPaths);
+    PLASMA_DEPRECATED void setContentsPrefixPaths(const QStringList &prefixPaths);
 
     /**
      * Sets service prefix.
      */
-    void setServicePrefix(const QString &servicePrefix);
+    PLASMA_DEPRECATED void setServicePrefix(const QString &servicePrefix);
 
     /**
      * Sets whether or not external paths/symlinks can be followed by a package
      * @param allow true if paths/symlinks outside of the package should be followed,
      *             false if they should be rejected.
      */
-    void setAllowExternalPaths(bool allow);
+    PLASMA_DEPRECATED void setAllowExternalPaths(bool allow);
 
     /**
      * Sets preferred package root.
      */
-    void setDefaultPackageRoot(const QString &packageRoot);
+    PLASMA_DEPRECATED void setDefaultPackageRoot(const QString &packageRoot);
 
     /**
      * Sets the fallback package root path
@@ -297,33 +300,33 @@
      * It is intended to be used by the packageStructure
      * @param path package root path @see setPath
      */
-    void setFallbackPackage(const Plasma::Package &package);
+    PLASMA_DEPRECATED void setFallbackPackage(const Plasma::Package &package);
 
     /**
      * @return The fallback package root path
      */
-    Plasma::Package fallbackPackage() const;
+    PLASMA_DEPRECATED Plasma::Package fallbackPackage() const;
 
     // Content structure description methods
     /**
      * @return all directories registered as part of this Package's structure
      */
-    QList<const char *> directories() const;
+    PLASMA_DEPRECATED QList<const char *> directories() const;
 
     /**
      * @return all directories registered as part of this Package's required structure
      */
-    QList<const char *> requiredDirectories() const;
+    PLASMA_DEPRECATED QList<const char *> requiredDirectories() const;
 
     /**
      * @return all files registered as part of this Package's structure
      */
-    QList<const char *> files() const;
+    PLASMA_DEPRECATED QList<const char *> files() const;
 
     /**
      * @return all files registered as part of this Package's required structure
      */
-    QList<const char *> requiredFiles() const;
+    PLASMA_DEPRECATED QList<const char *> requiredFiles() const;
 
     /**
      * Installs a package matching this package structure. By default installs a
@@ -331,22 +334,25 @@
      *
      * @return KJob to track installation progress and result
      **/
-    KJob *install(const QString &sourcePackage, const QString &packageRoot = QString());
+    PLASMA_DEPRECATED KJob *install(const QString &sourcePackage, const QString &packageRoot = QString());
 
     /**
      * Uninstalls a package matching this package structure.
      *
      * @return KJob to track removal progress and result
      */
-    KJob *uninstall(const QString &packageName, const QString &packageRoot);
+    PLASMA_DEPRECATED KJob *uninstall(const QString &packageName, const QString &packageRoot);
 
 private:
     QExplicitlySharedDataPointer<PackagePrivate> d;
     friend class PackagePrivate;
+    friend class PackageStructure;
+    friend class AppletPrivate;
+    friend class Corona;
 };
 
 }
-
+#endif
 Q_DECLARE_METATYPE(Plasma::Package)
 #endif
 
diff --git a/src/plasma/packagestructure.cpp b/src/plasma/packagestructure.cpp
index a08269b..987ea49 100644
--- a/src/plasma/packagestructure.cpp
+++ b/src/plasma/packagestructure.cpp
@@ -19,45 +19,63 @@
 
 #include "packagestructure.h"
 #include <QDebug>
-#include <private/packagejob_p.h>
 #include "private/package_p.h"
+#include "private/packagestructure_p.h"
+
+#include <kpackage/packageloader.h>
+#include <kpackage/packagestructure.h>
+
+#include <QVariantMap>
 
 namespace Plasma
 {
 
 PackageStructure::PackageStructure(QObject *parent, const QVariantList &args)
     : QObject(parent),
-      d(0)
+      d(new PackageStructurePrivate)
 {
+    if (!args.isEmpty() && args.first().canConvert<QString>()) {
+        d->internalStructure = KPackage::PackageLoader::self()->loadPackageStructure(args.first().toString());
+    }
+
     Q_UNUSED(args)
 }
 
 PackageStructure::~PackageStructure()
 {
+    delete d;
 }
 
 void PackageStructure::initPackage(Package *package)
 {
-    Q_UNUSED(package)
+    if (d->internalStructure) {
+        d->internalStructure->initPackage(package->d->internalPackage);
+    }
 }
 
 void PackageStructure::pathChanged(Package *package)
 {
-    Q_UNUSED(package)
+   if (d->internalStructure) {
+       d->internalStructure->pathChanged(package->d->internalPackage);
+    }
 }
 
 KJob *PackageStructure::install(Package *package, const QString &archivePath, const QString &packageRoot)
 {
-    PackageJob *j = new PackageJob(package->servicePrefix(), this);
-    j->install(archivePath, packageRoot);
-    return j;
+    if (d->internalStructure) {
+        return d->internalStructure->install(package->d->internalPackage, archivePath, packageRoot);
+    }
+
+    return 0;
 }
 
 KJob *PackageStructure::uninstall(Package *package, const QString &packageRoot)
 {
-    PackageJob *j = new PackageJob(package->servicePrefix(), this);
-    j->uninstall(packageRoot + package->metadata().pluginName());
-    return j;
+    if (d->internalStructure) {
+        return d->internalStructure->uninstall(package->d->internalPackage, packageRoot);
+    }
+
+    return 0;
 }
 
 }
diff --git a/src/plasma/packagestructure.h b/src/plasma/packagestructure.h
index c746732..49c6fc4 100644
--- a/src/plasma/packagestructure.h
+++ b/src/plasma/packagestructure.h
@@ -29,6 +29,8 @@
 #include <plasma/package.h>
 #include <plasma/version.h>
 
+#ifndef PLASMA_NO_DEPRECATED
+
 namespace Plasma
 {
 
@@ -40,7 +42,7 @@
 
 public:
 
-    explicit PackageStructure(QObject *parent = 0, const QVariantList &args = QVariantList());
+    PLASMA_DEPRECATED explicit PackageStructure(QObject *parent = 0, const QVariantList &args = QVariantList());
 
     ~PackageStructure();
 
@@ -55,13 +57,13 @@
      * @arg package the Package to set up. The object is empty of all definition when
      *      first passed in.
      */
-    virtual void initPackage(Package *package);
+    PLASMA_DEPRECATED virtual void initPackage(Package *package);
 
     /**
      * Called whenever the path changes so that subclasses may take
      * package specific actions.
      */
-    virtual void pathChanged(Package *package);
+    PLASMA_DEPRECATED virtual void pathChanged(Package *package);
 
     /**
      * Installs a package matching this package structure. By default installs a
@@ -74,7 +76,7 @@
      *                    installed to
      * @return KJob* to track the installation status
      **/
-    virtual KJob *install(Package *package, const QString &archivePath, const QString &packageRoot);
+    PLASMA_DEPRECATED virtual KJob *install(Package *package, const QString &archivePath, const QString &packageRoot);
 
     /**
      * Uninstalls a package matching this package structure.
@@ -85,10 +87,12 @@
      * @param packageRoot path to the directory where the package should be installed to
      * @return KJob* to track the installation status
      */
-    virtual KJob *uninstall(Package *package, const QString &packageRoot);
+    PLASMA_DEPRECATED virtual KJob *uninstall(Package *package, const QString &packageRoot);
 
 private:
     PackageStructurePrivate *d;
+    friend class Package;
+    friend class PluginLoader;
 };
 
 } // Plasma namespace
@@ -105,3 +109,5 @@
     K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
 
 #endif
+
+#endif
diff --git a/src/plasma/pluginloader.cpp b/src/plasma/pluginloader.cpp
index e40567f..833f3f6 100644
--- a/src/plasma/pluginloader.cpp
+++ b/src/plasma/pluginloader.cpp
@@ -25,6 +25,7 @@
 #include <kservice.h>
 #include <kservicetypetrader.h>
 #include <kplugintrader.h>
+#include <kpackage/packageloader.h>
 
 #include "config-plasma.h"
 
@@ -41,6 +42,8 @@
 #include "private/packages_p.h"
 #include "private/service_p.h" // for NullService
 #include "private/storage_p.h"
+#include "private/package_p.h"
+#include "private/packagestructure_p.h"
 
 namespace Plasma
 {
@@ -401,50 +404,45 @@
 
     const QString hashkey = packageFormat + '%' + specialization;
     PackageStructure *structure = d->structures.value(hashkey).data();
+
+    KPackage::PackageStructure *internalStructure = 0;
     if (structure) {
         return Package(structure);
     }
 
-    if (!specialization.isEmpty()) {
-        // check that the provided strings are safe to use in a ServiceType query
-        if (d->packageRE.indexIn(specialization) == -1 && d->packageRE.indexIn(packageFormat) == -1) {
-            // FIXME: The query below is rather spepcific to script engines. generify if possible
-            const QString component = packageFormat.right(packageFormat.size() - packageFormat.lastIndexOf('/') - 1);
-            const QString constraint = QString("[X-Plasma-API] == '%1' and " "'%2' in [X-Plasma-ComponentTypes]").arg(specialization, component);
-            KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint);
-
-            if (!offers.isEmpty()) {
-                KService::Ptr offer = offers.first();
-                QString packageFormat = offer->property("X-Plasma-PackageFormat").toString();
-                if (!packageFormat.isEmpty()) {
-                    return loadPackage(packageFormat);
-                }
-            }
-        }
-    }
-
     if (packageFormat.startsWith("Plasma")) {
         if (packageFormat.endsWith("/Applet")) {
-            structure = new PlasmoidPackage();
+            internalStructure = new PlasmoidPackage();
         } else if (packageFormat.endsWith("/DataEngine")) {
-            structure = new DataEnginePackage();
+            internalStructure = new DataEnginePackage();
         } else if (packageFormat.endsWith("/Theme")) {
-            structure = new ThemePackage();
+            internalStructure = new ThemePackage();
         } else if (packageFormat.endsWith("/ContainmentActions")) {
-            structure = new ContainmentActionsPackage();
+            internalStructure = new ContainmentActionsPackage();
         } else if (packageFormat.endsWith("/Generic")) {
-            structure = new GenericPackage();
+            internalStructure = new GenericPackage();
         }
 
-        if (structure) {
+        if (internalStructure) {
+            structure = new PackageStructure();
+            structure->d->internalStructure = internalStructure;
             d->structures.insert(hashkey, structure);
             return Package(structure);
         }
     }
 
-    // first we check for plugins in sycoca
-    const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat);
-    structure = KPluginTrader::createInstanceFromQuery<Plasma::PackageStructure>(d->packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0);
+    internalStructure = KPackage::PackageLoader::self()->loadPackageStructure(packageFormat);
+
+    if (internalStructure) {
+        structure = new PackageStructure();
+        structure->d->internalStructure = internalStructure;
+    //fallback to old structures
+    } else {
+        const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat);
+        structure = KPluginTrader::createInstanceFromQuery<Plasma::PackageStructure>(d->packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0);
+    }
+
+
     if (structure) {
         d->structures.insert(hashkey, structure);
         return Package(structure);
diff --git a/src/plasma/private/applet_p.cpp b/src/plasma/private/applet_p.cpp
index 0c33b1c..781cdf4 100644
--- a/src/plasma/private/applet_p.cpp
+++ b/src/plasma/private/applet_p.cpp
@@ -43,6 +43,7 @@
 #include "scripting/scriptengine.h"
 #include "scripting/appletscript.h"
 #include "private/containment_p.h"
+#include "private/package_p.h"
 #include "timetracker.h"
 
 namespace Plasma
@@ -142,8 +143,9 @@
     if (path.isEmpty()) {
         path = packagePath.isEmpty() ? appletDescription.pluginName() : packagePath;
     }
-    package = new Package(PluginLoader::self()->loadPackage("Plasma/Applet", api));
-    package->setPath(path);
+    legacyPackage = new Package(PluginLoader::self()->loadPackage("Plasma/Applet", api));
+    legacyPackage->setPath(path);
+    package = legacyPackage->d->internalPackage;
 
     if (!package->isValid()) {
         delete package;
diff --git a/src/plasma/private/applet_p.h b/src/plasma/private/applet_p.h
index 863cac3..f38a368 100644
--- a/src/plasma/private/applet_p.h
+++ b/src/plasma/private/applet_p.h
@@ -31,6 +31,8 @@
 #include <kplugininfo.h>
 #include <KNotification>
 
+#include <KPackage/Package>
+
 #include "plasma/applet.h"
 
 class KKeySequenceWidget;
@@ -92,7 +94,8 @@
 
     // sripting and package stuff
     AppletScript *script;
-    Package *package;
+    KPackage::Package *package;
+    Package *legacyPackage;
     KConfigLoader *configLoader;
 
     // actions stuff; put activationAction into actions?
diff --git a/src/plasma/private/corona_p.h b/src/plasma/private/corona_p.h
index bf3280e..d7845d9 100644
--- a/src/plasma/private/corona_p.h
+++ b/src/plasma/private/corona_p.h
@@ -49,7 +49,8 @@
     QList<Plasma::Containment *> importLayout(const KConfigGroup &conf, bool mergeConfig);
 
     Corona *q;
-    Package package;
+    KPackage::Package package;
+    Package legacyPackage;
     KConfigGroup desktopDefaultsConfig;
     Types::ImmutabilityType immutability;
     QString configName;
diff --git a/src/plasma/private/package_p.h b/src/plasma/private/package_p.h
index ddf2bdb..0aaa442 100644
--- a/src/plasma/private/package_p.h
+++ b/src/plasma/private/package_p.h
@@ -1,5 +1,6 @@
 /*
  *   Copyright © 2009 Rob Scheepmaker <r.scheepmaker at student.utwente.nl>
+ *   Copyright 2014 Marco Martin <mart at 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 version 2 as
@@ -19,79 +20,25 @@
 #ifndef PLASMA_PACKAGE_P_H
 #define PLASMA_PACKAGE_P_H
 
-#include "../plasma.h"
 #include "../package.h"
-#include "../service.h"
 
-#include <QCryptographicHash>
-#include <QDir>
-#include <QString>
-#include <QSharedData>
+#include <QExplicitlySharedDataPointer>
+
+#include <kpackage/package.h>
 
 namespace Plasma
 {
-
-class ContentStructure
-{
-public:
-    ContentStructure()
-        : directory(false),
-          required(false)
-    {
-    }
-
-    ContentStructure(const ContentStructure &other)
-    {
-        paths = other.paths;
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-        name = other.name;
-        mimeTypes = other.mimeTypes;
-#endif
-        directory = other.directory;
-        required = other.required;
-    }
-
-    QString found;
-    QStringList paths;
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    QString name;
-    QStringList mimeTypes;
-#endif
-    bool directory : 1;
-    bool required : 1;
-};
 
 class PackagePrivate : public QSharedData
 {
 public:
     PackagePrivate();
-    PackagePrivate(const PackagePrivate &other);
     ~PackagePrivate();
 
-    PackagePrivate &operator=(const PackagePrivate &rhs);
-
-    void createPackageMetadata(const QString &path);
-    QString unpack(const QString &filePath);
-    void updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCryptographicHash &hash);
-    QString fallbackFilePath(const char *key, const QString &filename = QString()) const;
-    bool hasCycle(const Plasma::Package &package);
-
-    QWeakPointer<PackageStructure> structure;
-    QString path;
-    QString tempRoot;
-    QStringList contentsPrefixPaths;
-    QString defaultPackageRoot;
     QString servicePrefix;
-    QHash<QString, QString> discoveries;
-    QHash<QByteArray, ContentStructure> contents;
+    KPackage::Package *internalPackage;
     Package *fallbackPackage;
-#ifndef PLASMA_NO_PACKAGE_EXTRADATA
-    QStringList mimeTypes;
-#endif
-    KPluginInfo *metadata;
-    bool externalPaths : 1;
-    bool valid : 1;
-    bool checkedValid : 1;
+    PackageStructure *structure;
 };
 
 }
diff --git a/src/plasma/private/packagejob.cpp b/src/plasma/private/packagejob.cpp
deleted file mode 100644
index e0cf60f..0000000
--- a/src/plasma/private/packagejob.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/******************************************************************************
-*   Copyright 2012 Sebastian Kügler <sebas at kde.org>                           *
-*                                                                             *
-*   This library 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 of the License, or (at your option) any later version.          *
-*                                                                             *
-*   This library 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          *
-*   Library General Public License for more details.                          *
-*                                                                             *
-*   You should have received a copy of the GNU Library General Public License *
-*   along with this library; see the file COPYING.LIB.  If not, write to      *
-*   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
-*   Boston, MA 02110-1301, USA.                                               *
-*******************************************************************************/
-
-#include "packagejob_p.h"
-#include "packagejobthread_p.h"
-#include "config-plasma.h"
-
-#include <QDebug>
-
-namespace Plasma
-{
-class PackageJobPrivate
-{
-public:
-    PackageJobThread *thread;
-    QString installPath;
-};
-
-PackageJob::PackageJob(const QString &servicePrefix, QObject *parent) :
-    KJob(parent)
-{
-    d = new PackageJobPrivate;
-    d->thread = new PackageJobThread(servicePrefix, this);
-    connect(d->thread, SIGNAL(finished(bool,QString)),
-            SLOT(slotFinished(bool,QString)), Qt::QueuedConnection);
-    connect(d->thread, SIGNAL(installPathChanged(QString)),
-            SIGNAL(installPathChanged(QString)), Qt::QueuedConnection);
-}
-
-PackageJob::~PackageJob()
-{
-    delete d;
-}
-
-void PackageJob::slotFinished(bool ok, const QString &err)
-{
-    if (ok) {
-        setError(NoError);
-    } else {
-        setError(UserDefinedError);
-        setErrorText(err);
-    }
-    d->thread->exit(0);
-    emitResult();
-}
-
-void PackageJob::start()
-{
-    d->thread->start();
-}
-
-void PackageJob::install(const QString &src, const QString &dest)
-{
-    d->thread->install(src, dest);
-}
-
-void PackageJob::uninstall(const QString &installationPath)
-{
-    d->thread->uninstall(installationPath);
-}
-
-} // namespace Plasma
-
-#include "moc_packagejob_p.cpp"
diff --git a/src/plasma/private/packagejob_p.h b/src/plasma/private/packagejob_p.h
deleted file mode 100644
index 08c66dd..0000000
--- a/src/plasma/private/packagejob_p.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/******************************************************************************
-*   Copyright 2012 Sebastian Kügler <sebas at kde.org>                           *
-*                                                                             *
-*   This library 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 of the License, or (at your option) any later version.          *
-*                                                                             *
-*   This library 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          *
-*   Library General Public License for more details.                          *
-*                                                                             *
-*   You should have received a copy of the GNU Library General Public License *
-*   along with this library; see the file COPYING.LIB.  If not, write to      *
-*   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
-*   Boston, MA 02110-1301, USA.                                               *
-*******************************************************************************/
-
-#ifndef PLASMA_PACKAGEJOB_P_H
-#define PLASMA_PACKAGEJOB_P_H
-
-#include "kjob.h"
-
-namespace Plasma
-{
-
-class PackageJobPrivate;
-
-class PackageJob : public KJob
-{
-    Q_OBJECT
-
-public:
-    PackageJob(const QString &servicePrefix, QObject *parent = 0);
-    ~PackageJob();
-
-    virtual void start();
-
-    void install(const QString &src, const QString &dest);
-    void uninstall(const QString &installationPath);
-
-Q_SIGNALS:
-    void installPathChanged(const QString &path);
-
-//     Q_SIGNALS:
-//         void finished(bool success);
-
-private Q_SLOTS:
-    void slotFinished(bool ok, const QString &err);
-
-private:
-    PackageJobPrivate *d;
-};
-
-}
-
-#endif
diff --git a/src/plasma/private/packagejobthread.cpp b/src/plasma/private/packagejobthread.cpp
deleted file mode 100644
index 83d501b..0000000
--- a/src/plasma/private/packagejobthread.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/******************************************************************************
-*   Copyright 2007-2009 by Aaron Seigo <aseigo at kde.org>                       *
-*   Copyright 2012 Sebastian Kügler <sebas at kde.org>                           *
-*                                                                             *
-*   This library 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 of the License, or (at your option) any later version.          *
-*                                                                             *
-*   This library 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          *
-*   Library General Public License for more details.                          *
-*                                                                             *
-*   You should have received a copy of the GNU Library General Public License *
-*   along with this library; see the file COPYING.LIB.  If not, write to      *
-*   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
-*   Boston, MA 02110-1301, USA.                                               *
-*******************************************************************************/
-
-#include "private/packagejobthread_p.h"
-
-#include "package.h"
-#include "config-plasma.h"
-
-#include <karchive.h>
-#include <kdesktopfile.h>
-#include <klocalizedstring.h>
-#include <ktar.h>
-#include <kzip.h>
-
-#include <QDir>
-#include <QDBusInterface>
-#include <QDBusPendingCall>
-#include <QFile>
-#include <QIODevice>
-#include <QMimeType>
-#include <QMimeDatabase>
-#include <QRegExp>
-#include <QtNetwork/QHostInfo>
-#include <qtemporarydir.h>
-
-#include <QDebug>
-
-namespace Plasma
-{
-
-bool copyFolder(QString sourcePath, QString targetPath)
-{
-    QDir source(sourcePath);
-    if (!source.exists()) {
-        return false;
-    }
-
-    QDir target(targetPath);
-    if (!target.exists()) {
-        QString targetName = target.dirName();
-        target.cdUp();
-        target.mkdir(targetName);
-        target = QDir(targetPath);
-    }
-
-    foreach (const QString &fileName, source.entryList(QDir::Files)) {
-        QString sourceFilePath = sourcePath + QDir::separator() + fileName;
-        QString targetFilePath = targetPath + QDir::separator() + fileName;
-
-        if (!QFile::copy(sourceFilePath, targetFilePath)) {
-            return false;
-        }
-    }
-
-    foreach (const QString &subFolderName, source.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
-        QString sourceSubFolderPath = sourcePath + QDir::separator() + subFolderName;
-        QString targetSubFolderPath = targetPath + QDir::separator() + subFolderName;
-
-        if (!copyFolder(sourceSubFolderPath, targetSubFolderPath)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// Qt5 TODO: use QDir::removeRecursively() instead
-bool removeFolder(QString folderPath)
-{
-    QDir folder(folderPath);
-    if (!folder.exists()) {
-        return false;
-    }
-
-    foreach (const QString &fileName, folder.entryList(QDir::Files)) {
-        if (!QFile::remove(folderPath + QDir::separator() + fileName)) {
-            return false;
-        }
-    }
-
-    foreach (const QString &subFolderName, folder.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
-        if (!removeFolder(folderPath + QDir::separator() + subFolderName)) {
-            return false;
-        }
-    }
-
-    QString folderName = folder.dirName();
-    folder.cdUp();
-    return folder.rmdir(folderName);
-}
-
-class PackageJobThreadPrivate
-{
-public:
-    QString installPath;
-    QString errorMessage;
-    QString servicePrefix;
-};
-
-PackageJobThread::PackageJobThread(const QString &servicePrefix, QObject *parent) :
-    QThread(parent)
-{
-    d = new PackageJobThreadPrivate;
-    d->servicePrefix = servicePrefix;
-}
-
-PackageJobThread::~PackageJobThread()
-{
-    delete d;
-}
-
-bool PackageJobThread::install(const QString &src, const QString &dest)
-{
-    bool ok = installPackage(src, dest);
-    emit installPathChanged(d->installPath);
-    emit finished(ok, d->errorMessage);
-    return ok;
-}
-
-bool PackageJobThread::installPackage(const QString &src, const QString &dest)
-{
-    QString packageRoot = dest;
-    QDir root(dest);
-    if (!root.exists()) {
-        QDir().mkpath(dest);
-        if (!root.exists()) {
-            d->errorMessage = i18n("Could not create package root directory: %1", dest);
-            //qWarning() << "Could not create package root directory: " << dest;
-            return false;
-        }
-    }
-
-    QFileInfo fileInfo(src);
-    if (!fileInfo.exists()) {
-        d->errorMessage = i18n("No such file: %1", src);
-        return false;
-    }
-
-    QString path;
-    QTemporaryDir tempdir;
-    bool archivedPackage = false;
-
-    if (fileInfo.isDir()) {
-        // we have a directory, so let's just install what is in there
-        path = src;
-        // make sure we end in a slash!
-        if (path[path.size() - 1] != '/') {
-            path.append('/');
-        }
-    } else {
-        KArchive *archive = 0;
-        QMimeDatabase db;
-        QMimeType mimetype = db.mimeTypeForFile(src);
-        if (mimetype.inherits("application/zip")) {
-            archive = new KZip(src);
-        } else if (mimetype.inherits("application/x-compressed-tar") ||
-                   mimetype.inherits("application/x-tar") || mimetype.inherits("application/x-bzip-compressed-tar") ||
-                   mimetype.inherits("application/x-xz") || mimetype.inherits("application/x-lzma")) {
-            archive = new KTar(src);
-        } else {
-            //qWarning() << "Could not open package file, unsupported archive format:" << src << mimetype.name();
-            d->errorMessage = i18n("Could not open package file, unsupported archive format: %1 %2", src, mimetype.name());
-            return false;
-        }
-
-        if (!archive->open(QIODevice::ReadOnly)) {
-            //qWarning() << "Could not open package file:" << src;
-            delete archive;
-            d->errorMessage = i18n("Could not open package file: %1", src);
-            return false;
-        }
-
-        archivedPackage = true;
-        path = tempdir.path() + '/';
-
-        d->installPath = path;
-
-        const KArchiveDirectory *source = archive->directory();
-        source->copyTo(path);
-
-        QStringList entries = source->entries();
-        if (entries.count() == 1) {
-            const KArchiveEntry *entry = source->entry(entries[0]);
-            if (entry->isDirectory()) {
-                path.append(entry->name()).append("/");
-            }
-        }
-
-        delete archive;
-    }
-
-    QString metadataPath = path + "metadata.desktop";
-    if (!QFile::exists(metadataPath)) {
-        qDebug() << "No metadata file in package" << src << metadataPath;
-        d->errorMessage = i18n("No metadata file in package: %1", src);
-        return false;
-    }
-
-    KPluginInfo meta(metadataPath);
-    QString pluginName = meta.pluginName();
-    qDebug() << "pluginname: " << meta.pluginName();
-    if (pluginName.isEmpty()) {
-        //qWarning() << "Package plugin name not specified";
-        d->errorMessage = i18n("Package plugin name not specified: %1", src);
-        return false;
-    }
-
-    // Ensure that package names are safe so package uninstall can't inject
-    // bad characters into the paths used for removal.
-    QRegExp validatePluginName("^[\\w-\\.]+$"); // Only allow letters, numbers, underscore and period.
-    if (!validatePluginName.exactMatch(pluginName)) {
-        //qDebug() << "Package plugin name " << pluginName << "contains invalid characters";
-        d->errorMessage = i18n("Package plugin name %1 contains invalid characters", pluginName);
-        return false;
-    }
-
-    QString targetName = dest;
-    if (targetName[targetName.size() - 1] != '/') {
-        targetName.append('/');
-    }
-    targetName.append(pluginName);
-
-    if (QFile::exists(targetName)) {
-        d->errorMessage = i18n("%1 already exists", targetName);
-        return false;
-    }
-
-    if (archivedPackage) {
-        // it's in a temp dir, so just move it over.
-        const bool ok = copyFolder(path, targetName);
-        removeFolder(path);
-        if (!ok) {
-            //qWarning() << "Could not move package to destination:" << targetName;
-            d->errorMessage = i18n("Could not move package to destination: %1", targetName);
-            return false;
-        }
-    } else {
-        // it's a directory containing the stuff, so copy the contents rather
-        // than move them
-        const bool ok = copyFolder(path, targetName);
-        if (!ok) {
-            //qWarning() << "Could not copy package to destination:" << targetName;
-            d->errorMessage = i18n("Could not copy package to destination: %1", targetName);
-            return false;
-        }
-    }
-
-    if (archivedPackage) {
-        // no need to remove the temp dir (which has been successfully moved if it's an archive)
-        tempdir.setAutoRemove(false);
-    }
-
-    if (!d->servicePrefix.isEmpty()) {
-        // and now we register it as a service =)
-        QString metaPath = targetName + "/metadata.desktop";
-        KDesktopFile df(metaPath);
-        KConfigGroup cg = df.desktopGroup();
-
-        // Q: should not installing it as a service disqualify it?
-        // Q: 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
-
-        //TODO: reduce code duplication with registerPackage below
-
-        const QString serviceName = d->servicePrefix + meta.pluginName() + ".desktop";
-
-        QString localServiceDirectory = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/");
-        if (!QDir().mkpath(localServiceDirectory)) {
-            qDebug() << "Failed to create ... " << localServiceDirectory;
-            d->errorMessage = i18n("Could not create local service directory: %1", localServiceDirectory);
-            return false;
-        }
-        QString service = localServiceDirectory + serviceName;
-
-        qDebug() << "-- Copying " << metaPath << service;
-        const bool ok = QFile::copy(metaPath, service);
-        if (ok) {
-            qDebug() << "Copying metadata went ok.";
-            // the icon in the installed file needs to point to the icon in the
-            // installation dir!
-            QString iconPath = targetName + '/' + cg.readEntry("Icon");
-            QFile icon(iconPath);
-            if (icon.exists()) {
-                KDesktopFile df(service);
-                KConfigGroup cg = df.desktopGroup();
-                cg.writeEntry("Icon", iconPath);
-            }
-        } else {
-            qDebug() << "Could not register package as service (this is not necessarily fatal):" << serviceName;
-            d->errorMessage = i18n("Could not register package as service (this is not necessarily fatal): %1", serviceName);
-        }
-    }
-    QDBusInterface sycoca("org.kde.kded5", "/kbuildsycoca");
-    sycoca.asyncCall("recreate");
-    d->installPath = targetName;
-
-    //qWarning() << "Not updating kbuildsycoca4, since that will go away. Do it yourself for now if needed.";
-    return true;
-
-}
-
-bool PackageJobThread::uninstall(const QString &packagePath)
-{
-    bool ok = uninstallPackage(packagePath);
-    //qDebug() << "emit installPathChanged " << d->installPath;
-    emit installPathChanged(QString());
-    //qDebug() << "Thread: installFinished" << ok;
-    emit finished(ok, d->errorMessage);
-    return ok;
-}
-
-bool PackageJobThread::uninstallPackage(const QString &packagePath)
-{
-    if (!QFile::exists(packagePath)) {
-        d->errorMessage = i18n("%1 does not exist", packagePath);
-        return false;
-    }
-    QString pkg;
-    {
-        // FIXME: remove, pass in packageroot, type and pluginName separately?
-        QString _path = packagePath;
-        QStringList ps = packagePath.split('/');
-        int ix = ps.count() - 1;
-        if (packagePath.endsWith('/')) {
-            ix = ps.count() - 2;
-        }
-        pkg = ps[ix];
-    }
-    const QString &packageName = pkg;
-
-    const QString serviceName = d->servicePrefix + packageName + ".desktop";
-
-    QString service = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/") + serviceName;
-
-    bool ok = QFile::remove(service);
-    if (!ok) {
-        qWarning() << "Unable to remove " << service;
-    }
-
-    ok = removeFolder(packagePath);
-    if (!ok) {
-        d->errorMessage = i18n("Could not delete package from: %1", packagePath);
-        return false;
-    }
-
-    QDBusInterface sycoca("org.kde.kded5", "/kbuildsycoca");
-    sycoca.asyncCall("recreate");
-    return true;
-}
-
-} // namespace Plasma
-
-#include "moc_packagejobthread_p.cpp"
-
diff --git a/src/plasma/private/packagejobthread_p.h b/src/plasma/private/packagejobthread_p.h
deleted file mode 100644
index 4a990aa..0000000
--- a/src/plasma/private/packagejobthread_p.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/******************************************************************************
-*   Copyright 2007-2009 by Aaron Seigo <aseigo at kde.org>                       *
-*   Copyright 2012 Sebastian Kügler <sebas at kde.org>                           *
-*                                                                             *
-*   This library 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 of the License, or (at your option) any later version.          *
-*                                                                             *
-*   This library 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          *
-*   Library General Public License for more details.                          *
-*                                                                             *
-*   You should have received a copy of the GNU Library General Public License *
-*   along with this library; see the file COPYING.LIB.  If not, write to      *
-*   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,      *
-*   Boston, MA 02110-1301, USA.                                               *
-*******************************************************************************/
-
-#ifndef PLASMA_PACKAGEJOBTHREAD_P_H
-#define PLASMA_PACKAGEJOBTHREAD_P_H
-
-#include "kjob.h"
-#include <QThread>
-
-namespace Plasma
-{
-
-class PackageJobThreadPrivate;
-
-class PackageJobThread : public QThread
-{
-    Q_OBJECT
-
-public:
-    PackageJobThread(const QString &servicePrefix, QObject *parent = 0);
-    virtual ~PackageJobThread();
-
-    bool install(const QString &src, const QString &dest);
-    bool uninstall(const QString &packagePath);
-
-Q_SIGNALS:
-    void finished(bool success, const QString &errorMessage = QString());
-    void percentChanged(int percent);
-    void error(const QString &errorMessage);
-    void installPathChanged(const QString &installPath);
-
-private:
-    bool installPackage(const QString &src, const QString &dest);
-    bool uninstallPackage(const QString &packagePath);
-    PackageJobThreadPrivate *d;
-};
-
-}
-
-#endif
diff --git a/src/plasma/private/packages.cpp b/src/plasma/private/packages.cpp
index e1a4757..a125f1e 100644
--- a/src/plasma/private/packages.cpp
+++ b/src/plasma/private/packages.cpp
@@ -24,6 +24,7 @@
 
 #include <QCoreApplication>
 #include <QFileInfo>
+#include <QDebug>
 
 #include <kconfiggroup.h>
 #include <kdesktopfile.h>
@@ -34,10 +35,12 @@
 #include "package.h"
 #include "config-plasma.h"
 
+#include <kpackage/package.h>
+
 namespace Plasma
 {
 
-void ChangeableMainScriptPackage::initPackage(Package *package)
+void ChangeableMainScriptPackage::initPackage(KPackage::Package *package)
 {
     package->addFileDefinition("mainscript", "ui/main.qml", i18n("Main Script File"));
     package->setRequired("mainscript", true);
@@ -48,7 +51,7 @@
     return QLatin1String("X-Plasma-MainScript");
 }
 
-void ChangeableMainScriptPackage::pathChanged(Package *package)
+void ChangeableMainScriptPackage::pathChanged(KPackage::Package *package)
 {
     if (package->path().isEmpty()) {
         return;
@@ -63,7 +66,7 @@
     }
 }
 
-void GenericPackage::initPackage(Package *package)
+void GenericPackage::initPackage(KPackage::Package *package)
 {
     ChangeableMainScriptPackage::initPackage(package);
 
@@ -105,20 +108,18 @@
     package->addDirectoryDefinition("translations", "locale", i18n("Translations"));
 }
 
-void PlasmoidPackage::initPackage(Package *package)
+void PlasmoidPackage::initPackage(KPackage::Package *package)
 {
     GenericPackage::initPackage(package);
-    package->setServicePrefix("plasma-applet-");
     package->setDefaultPackageRoot(PLASMA_RELATIVE_DATA_INSTALL_DIR "/plasmoids/");
 
     package->addFileDefinition("configmodel", "config/config.qml", i18n("Configuration UI pages model"));
     package->addFileDefinition("mainconfigxml", "config/main.xml", i18n("Configuration XML file"));
 }
 
-void DataEnginePackage::initPackage(Package *package)
+void DataEnginePackage::initPackage(KPackage::Package *package)
 {
     ChangeableMainScriptPackage::initPackage(package);
-    package->setServicePrefix("plasma-dataengine-");
     package->setDefaultPackageRoot(PLASMA_RELATIVE_DATA_INSTALL_DIR "/dataengines/");
 
     package->addDirectoryDefinition("data", "data", i18n("Data Files"));
@@ -134,7 +135,7 @@
     package->addDirectoryDefinition("translations", "locale", i18n("Translations"));
 }
 
-void ThemePackage::initPackage(Package *package)
+void ThemePackage::initPackage(KPackage::Package *package)
 {
     // by default the packages have "contents/" as contentsPrefixPaths
     // but for the themes we don't want that, so unset it.
@@ -234,7 +235,7 @@
     package->setDefaultMimeTypes(mimetypes);
 }
 
-void ContainmentActionsPackage::initPackage(Package *package)
+void ContainmentActionsPackage::initPackage(KPackage::Package *package)
 {
     ChangeableMainScriptPackage::initPackage(package);
     package->setDefaultPackageRoot(PLASMA_RELATIVE_DATA_INSTALL_DIR "/containmentactions/");
diff --git a/src/plasma/private/packages_p.h b/src/plasma/private/packages_p.h
index 66d5765..0e0e803 100644
--- a/src/plasma/private/packages_p.h
+++ b/src/plasma/private/packages_p.h
@@ -20,50 +20,58 @@
 #ifndef LIBS_PLASMA_PACKAGES_P_H
 #define LIBS_PLASMA_PACKAGES_P_H
 
-#include "packagestructure.h"
 #include "plasma.h"
+
+#include <kpackage/package.h>
+#include <kpackage/packagestructure.h>
 
 namespace Plasma
 {
 
-class ChangeableMainScriptPackage : public PackageStructure
+class ChangeableMainScriptPackage : public KPackage::PackageStructure
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
+    void pathChanged(KPackage::Package *package);
 
 protected:
     virtual QString mainScriptConfigKey() const;
-    void pathChanged(Package *package);
 };
 
 class GenericPackage : public ChangeableMainScriptPackage
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
 };
 
 class PlasmoidPackage : public GenericPackage
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
 };
 
 class DataEnginePackage : public ChangeableMainScriptPackage
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
 };
 
-class ThemePackage : public PackageStructure
+class ThemePackage : public KPackage::PackageStructure
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
 };
 
 class ContainmentActionsPackage : public ChangeableMainScriptPackage
 {
+    Q_OBJECT
 public:
-    void initPackage(Package *package);
+    void initPackage(KPackage::Package *package);
 };
 
 } // namespace Plasma
diff --git a/src/plasma/private/packagestructure_p.h b/src/plasma/private/packagestructure_p.h
new file mode 100644
index 0000000..63d837c
--- /dev/null
+++ b/src/plasma/private/packagestructure_p.h
@@ -0,0 +1,44 @@
+/*
+ *   Copyright © 2009 Rob Scheepmaker <r.scheepmaker at student.utwente.nl>
+ *   Copyright 2014 Marco Martin <mart at 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 version 2 as
+ *   published by the Free Software Foundation
+ *
+ *   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_PACKAGESTRUCTURE_P_H
+#define PLASMA_PACKAGESTRUCTURE_P_H
+
+#include "../packagestructure.h"
+
+#include <kpackage/package.h>
+
+namespace Plasma
+{
+
+class PackageStructurePrivate
+{
+public:
+    PackageStructurePrivate()
+        : internalStructure(0)
+    {}
+    ~PackageStructurePrivate()
+    {}
+
+    KPackage::PackageStructure *internalStructure;
+};
+
+}
+
+#endif
diff --git a/src/plasmaquick/packageurlinterceptor.cpp b/src/plasmaquick/packageurlinterceptor.cpp
index 5534339..334ae42 100644
--- a/src/plasmaquick/packageurlinterceptor.cpp
+++ b/src/plasmaquick/packageurlinterceptor.cpp
@@ -91,6 +91,7 @@
                 break;
             }
         }
+
         //should never happen
         Q_ASSERT(!relativePath.isEmpty());
 

-- 
To view, visit https://gerrit.vesnicky.cesnet.cz/r/260
To unsubscribe, visit https://gerrit.vesnicky.cesnet.cz/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I05f95e8d05e3b67759973c4009e3753c61b1dcce
Gerrit-PatchSet: 1
Gerrit-Project: plasma-framework
Gerrit-Branch: master
Gerrit-Owner: Marco Martin <notmart at gmail.com>
Gerrit-Reviewer: Aaron J. Seigo <aseigo at kde.org>
Gerrit-Reviewer: Kevin Ottens <ervin at kde.org>
Gerrit-Reviewer: Sebastian Kügler <sebas at kde.org>


More information about the Plasma-devel mailing list