diff --git a/CMakeLists.txt b/CMakeLists.txt index ccec0edd3..891183c0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ find_package(KF5Service ${KF5_DEP_VERSION} REQUIRED) 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/KF5PlasmaConfig.cmake.in b/KF5PlasmaConfig.cmake.in index b85280867..13d10f298 100644 --- a/KF5PlasmaConfig.cmake.in +++ b/KF5PlasmaConfig.cmake.in @@ -4,6 +4,8 @@ include("${CMAKE_CURRENT_LIST_DIR}/KF5PlasmaTargets.cmake") +find_dependency(KF5Package "@KF5_DEP_VERSION@") + set(Plasma_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") set_and_check(Plasma_INCLUDE_DIR "@PACKAGE_KF5_INCLUDE_INSTALL_DIR@") diff --git a/src/plasma/CMakeLists.txt b/src/plasma/CMakeLists.txt index f7aa38b86..423b3e77f 100644 --- a/src/plasma/CMakeLists.txt +++ b/src/plasma/CMakeLists.txt @@ -66,8 +66,6 @@ set(Plasma_LIB_SRCS #packages package.cpp packagestructure.cpp - private/packagejob.cpp - private/packagejobthread.cpp private/packages.cpp #graphics @@ -112,6 +110,7 @@ target_link_libraries(KF5Plasma 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 5594bf8f6..3c0ffb12c 100644 --- a/src/plasma/applet.cpp +++ b/src/plasma/applet.cpp @@ -55,6 +55,7 @@ #include "private/associatedapplicationmanager_p.h" #include "private/containment_p.h" +#include "private/package_p.h" namespace Plasma { @@ -287,7 +288,16 @@ KConfigLoader *Applet::configScheme() const Package Applet::package() const { - return d->package ? *d->package : Package(); + Package p; + if (d->package) { + p.d->internalPackage = new KPackage::Package(*d->package); + } + return p; +} + +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 a30a7ac77..ea96bc8a5 100644 --- a/src/plasma/applet.h +++ b/src/plasma/applet.h @@ -33,6 +33,8 @@ #include #include +#include + class KActionCollection; class KConfigLoader; @@ -224,13 +226,26 @@ public: 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.6 **/ - 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 038be7b2e..f8d5c7dc5 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 @@ Corona::~Corona() Plasma::Package Corona::package() const { - return d->package; + Package p; + p.d->internalPackage = new KPackage::Package(d->package); + return p; } void Corona::setPackage(const Plasma::Package &package) { - d->package = package; + setKPackage(*package.d->internalPackage); emit packageChanged(package); } +KPackage::Package Corona::kPackage() const +{ + return d->package; +} + +void Corona::setKPackage(const KPackage::Package &package) +{ + d->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 6e925026d..b14f7ef08 100644 --- a/src/plasma/corona.h +++ b/src/plasma/corona.h @@ -43,11 +43,33 @@ class PLASMA_EXPORT Corona : public QObject Q_OBJECT Q_PROPERTY(bool isStartupCompleted READ isStartupCompleted NOTIFY startupCompleted) Q_PROPERTY(Package package READ package NOTIFY packageChanged) + Q_PROPERTY(KPackage::Package kPackage 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. * A Corona package defines how Containments are laid out in a View, @@ -56,14 +78,15 @@ public: * 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 @@ Q_SIGNALS: */ 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 07b3c90c5..4e0be88ba 100644 --- a/src/plasma/package.cpp +++ b/src/plasma/package.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "config-plasma.h" @@ -39,35 +40,64 @@ #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); + PackageStructureWrapper::s_packagesMap[d->internalPackage] = this; + structure->initPackage(this); } Package::Package(const Package &other) - : d(other.d) + : d(new Plasma::PackagePrivate()) { + d->internalPackage = new KPackage::Package(*other.d->internalPackage); + d->structure = other.d->structure; + PackageStructureWrapper::s_packagesMap[d->internalPackage] = this; } Package::~Package() { + PackageStructureWrapper::s_packagesMap.remove(d->internalPackage); + delete d->internalPackage; } Package &Package::operator=(const Package &rhs) { if (&rhs != this) { - d = rhs.d; + d->internalPackage = new KPackage::Package(*rhs.d->internalPackage); + d->structure = rhs.d->structure; + PackageStructureWrapper::s_packagesMap[d->internalPackage] = this; } return *this; @@ -75,130 +105,43 @@ Package &Package::operator=(const Package &rhs) 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 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::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::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::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 +160,128 @@ QString Package::servicePrefix() const 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()<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::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 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; - } - - // 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::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::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 Package::directories() const { QList dirs; - QHash::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 Package::requiredDirectories() const { QList dirs; - QHash::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 Package::files() const { QList files; - QHash::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 Package::requiredFiles() const { QList files; - QHash::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; @@ -775,169 +293,15 @@ KJob *Package::install(const QString &sourcePackage, const QString &packageRoot) 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))); + KJob *j = d->structure->install(this, src, dest); return j; } KJob *Package::uninstall(const QString &packageName, const QString &packageRoot) { - d->createPackageMetadata(packageRoot + packageName); - return d->structure.data()->uninstall(this, packageRoot); -} + setPath(packageRoot + packageName); -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(&package); - Plasma::Package *fastPackage = const_cast(&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->structure->uninstall(this, packageRoot); } } // Namespace diff --git a/src/plasma/package.h b/src/plasma/package.h index 28f8b08a1..6687ed0f2 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 @@ namespace Plasma * * @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 @@ public: * 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 @@ public: * 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 @@ public: * 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 @@ public: * @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 @@ public: * 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 @@ public: * @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 @@ public: * @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 @@ public: * @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 @@ public: * * @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 @@ public: * @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 @@ public: * @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 @@ public: * 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 directories() const; + PLASMA_DEPRECATED QList directories() const; /** * @return all directories registered as part of this Package's required structure */ - QList requiredDirectories() const; + PLASMA_DEPRECATED QList requiredDirectories() const; /** * @return all files registered as part of this Package's structure */ - QList files() const; + PLASMA_DEPRECATED QList files() const; /** * @return all files registered as part of this Package's required structure */ - QList requiredFiles() const; + PLASMA_DEPRECATED QList requiredFiles() const; /** * Installs a package matching this package structure. By default installs a @@ -331,22 +334,26 @@ public: * * @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 d; friend class PackagePrivate; + friend class PackageStructure; + friend class AppletPrivate; + friend class Applet; + friend class Corona; }; } - +#endif Q_DECLARE_METATYPE(Plasma::Package) #endif diff --git a/src/plasma/packagestructure.cpp b/src/plasma/packagestructure.cpp index a08269bd9..b2686b6fb 100644 --- a/src/plasma/packagestructure.cpp +++ b/src/plasma/packagestructure.cpp @@ -19,47 +19,226 @@ #include "packagestructure.h" #include -#include #include "private/package_p.h" +#include "private/packagestructure_p.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include namespace Plasma { +QHash PackageStructureWrapper::s_packagesMap; + +PackageStructureWrapper::PackageStructureWrapper(Plasma::PackageStructure *structure, QObject *parent, const QVariantList &args) + : KPackage::PackageStructure(parent, args), + m_struct(structure) +{ +} + +PackageStructureWrapper::~PackageStructureWrapper() +{ +} + +void PackageStructureWrapper::initPackage(KPackage::Package *package) +{ + + if (!m_struct || !s_packagesMap.contains(package)) { + return; + } + + m_struct->initPackage(s_packagesMap.value(package)); +} + +void PackageStructureWrapper::pathChanged(KPackage::Package *package) +{ + if (!m_struct || !s_packagesMap.contains(package)) { + return; + } + + m_struct->pathChanged(s_packagesMap.value(package)); +} + +KJob *PackageStructureWrapper::install(KPackage::Package *package, const QString &archivePath, const QString &packageRoot) +{ + if (!m_struct || !s_packagesMap.contains(package)) { + return 0; + } + + return m_struct->install(s_packagesMap.value(package), archivePath, packageRoot); +} + +KJob *PackageStructureWrapper::uninstall(KPackage::Package *package, const QString &packageRoot) +{ + if (!m_struct || !s_packagesMap.contains(package)) { + return 0; + } + + return m_struct->uninstall(s_packagesMap.value(package), packageRoot); +} + + + +void PackageStructurePrivate::installPathChanged(const QString &path) +{ + KJob *job = qobject_cast(q->sender()); + if (!job && job->error()) { + return; + } + + const QString servicePrefix = job->property("servicePrefix").toString(); + const QString serviceName = job->property("serviceName").toString(); + + //uninstall + if (path.isEmpty()) { + if (serviceName.isEmpty()) { + return; + } + + QString service = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/") + serviceName; + + bool ok = QFile::remove(service); + if (!ok) { + qWarning() << "Unable to remove " << service; + } + + //install + } else { + if (!servicePrefix.isEmpty()) { + // and now we register it as a service =) + QString metaPath = path + "/metadata.desktop"; + KDesktopFile df(metaPath); + KConfigGroup cg = df.desktopGroup(); + const QString pluginName = cg.readEntry("X-KDE-PluginInfo-Name", QString()); + + if (pluginName.isEmpty()) { + return; + } + + // 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 = servicePrefix + pluginName + ".desktop"; + + QString localServiceDirectory = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/"); + if (!QDir().mkpath(localServiceDirectory)) { + qDebug() << "Failed to create ... " << localServiceDirectory; + qWarning() << "Could not create local service directory:" << localServiceDirectory; + return; + } + 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 = path + '/' + cg.readEntry("Icon"); + QFile icon(iconPath); + if (icon.exists()) { + KDesktopFile df(service); + KConfigGroup cg = df.desktopGroup(); + cg.writeEntry("Icon", iconPath); + } + } else { + qWarning() << "Could not register package as service (this is not necessarily fatal):" << serviceName; + } + } + } + QDBusInterface sycoca("org.kde.kded5", "/kbuildsycoca"); + sycoca.asyncCall("recreate"); +} + + + PackageStructure::PackageStructure(QObject *parent, const QVariantList &args) : QObject(parent), - d(0) + d(new PackageStructurePrivate(this)) { + if (!args.isEmpty() && args.first().canConvert()) { + 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 && !qobject_cast(d->internalStructure)) { + d->internalStructure->initPackage(package->d->internalPackage); + } } void PackageStructure::pathChanged(Package *package) { - Q_UNUSED(package) + if (d->internalStructure && !qobject_cast(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 && !qobject_cast(d->internalStructure)) { + KJob *job = d->internalStructure->install(package->d->internalPackage, archivePath, packageRoot); + if (job) { + job->setProperty("servicePrefix", package->servicePrefix()); + connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); + } + return job; + } else if (d->internalStructure) { + KJob *job = d->internalStructure->KPackage::PackageStructure::install(package->d->internalPackage, archivePath, packageRoot); + connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); + return job; + } + + 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 && !qobject_cast(d->internalStructure)) { + QString metaPath = package->path() + "/metadata.desktop"; + KDesktopFile df(metaPath); + KConfigGroup cg = df.desktopGroup(); + const QString pluginName = cg.readEntry("X-KDE-PluginInfo-Name", QString()); + const QString serviceName = package->servicePrefix() + pluginName + ".desktop"; + + KJob *job = d->internalStructure->uninstall(package->d->internalPackage, packageRoot); + if (job) { + job->setProperty("serviceName", serviceName); + + connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); + } + return job; + } else if (d->internalStructure) { + KJob *job = d->internalStructure->KPackage::PackageStructure::uninstall(package->d->internalPackage, packageRoot); + connect(job, SIGNAL(installPathChanged(QString)), this, SLOT(installPathChanged(QString))); + return job; + } + + return 0; } } #include "moc_packagestructure.cpp" +#include "private/moc_packagestructure_p.cpp" diff --git a/src/plasma/packagestructure.h b/src/plasma/packagestructure.h index c746732ba..294cca3f2 100644 --- a/src/plasma/packagestructure.h +++ b/src/plasma/packagestructure.h @@ -29,6 +29,8 @@ #include #include +#ifndef PLASMA_NO_DEPRECATED + namespace Plasma { @@ -40,7 +42,7 @@ class PLASMA_EXPORT PackageStructure : public QObject 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 @@ public: * @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 @@ public: * 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,15 @@ public: * @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; + friend class PackageStructurePrivate; + + Q_PRIVATE_SLOT(d, void installPathChanged(const QString &path)) }; } // Plasma namespace @@ -105,3 +112,5 @@ private: K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION) #endif + +#endif diff --git a/src/plasma/pluginloader.cpp b/src/plasma/pluginloader.cpp index e40567ff1..48cd46cd5 100644 --- a/src/plasma/pluginloader.cpp +++ b/src/plasma/pluginloader.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #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,48 @@ Package PluginLoader::loadPackage(const QString &packageFormat, const QString &s 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(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(d->packageStructurePluginDir, "Plasma/PackageStructure", constraint, 0); + if (structure) { + structure->d->internalStructure = new PackageStructureWrapper(structure); + } + } + + 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 0c33b1c95..f4eb2c699 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,10 @@ void AppletPrivate::init(const QString &packagePath, const QVariantList &args) if (path.isEmpty()) { path = packagePath.isEmpty() ? appletDescription.pluginName() : packagePath; } - package = new Package(PluginLoader::self()->loadPackage("Plasma/Applet", api)); - package->setPath(path); + Plasma::Package p = PluginLoader::self()->loadPackage("Plasma/Applet", api); + p.setPath(path); + + package = new KPackage::Package(*p.d->internalPackage); if (!package->isValid()) { delete package; diff --git a/src/plasma/private/applet_p.h b/src/plasma/private/applet_p.h index 863cac3f9..13aae16b0 100644 --- a/src/plasma/private/applet_p.h +++ b/src/plasma/private/applet_p.h @@ -31,6 +31,8 @@ #include #include +#include + #include "plasma/applet.h" class KKeySequenceWidget; @@ -92,7 +94,7 @@ public: // sripting and package stuff AppletScript *script; - Package *package; + KPackage::Package *package; 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 bf3280e08..2ee13a57f 100644 --- a/src/plasma/private/corona_p.h +++ b/src/plasma/private/corona_p.h @@ -49,7 +49,7 @@ public: QList importLayout(const KConfigGroup &conf, bool mergeConfig); Corona *q; - Package package; + KPackage::Package package; KConfigGroup desktopDefaultsConfig; Types::ImmutabilityType immutability; QString configName; diff --git a/src/plasma/private/package_p.h b/src/plasma/private/package_p.h index ddf2bdb84..9714f815a 100644 --- a/src/plasma/private/package_p.h +++ b/src/plasma/private/package_p.h @@ -1,5 +1,6 @@ /* * Copyright © 2009 Rob Scheepmaker + * Copyright 2014 Marco Martin * * 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,28 @@ #ifndef PLASMA_PACKAGE_P_H #define PLASMA_PACKAGE_P_H -#include "../plasma.h" #include "../package.h" -#include "../service.h" -#include -#include -#include -#include +#include + +#include 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 installFinished(KJob *job); + void uninstallFinished(KJob *job); - 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 structure; - QString path; - QString tempRoot; - QStringList contentsPrefixPaths; - QString defaultPackageRoot; QString servicePrefix; - QHash discoveries; - QHash 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 e0cf60f79..000000000 --- a/src/plasma/private/packagejob.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** -* Copyright 2012 Sebastian Kügler * -* * -* 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 - -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 08c66dd1c..000000000 --- a/src/plasma/private/packagejob_p.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** -* Copyright 2012 Sebastian Kügler * -* * -* 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 83d501b91..000000000 --- a/src/plasma/private/packagejobthread.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/****************************************************************************** -* Copyright 2007-2009 by Aaron Seigo * -* Copyright 2012 Sebastian Kügler * -* * -* 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -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 4a990aa36..000000000 --- a/src/plasma/private/packagejobthread_p.h +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** -* Copyright 2007-2009 by Aaron Seigo * -* Copyright 2012 Sebastian Kügler * -* * -* 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 - -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 e1a4757c6..a125f1e16 100644 --- a/src/plasma/private/packages.cpp +++ b/src/plasma/private/packages.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -34,10 +35,12 @@ #include "package.h" #include "config-plasma.h" +#include + 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 @@ QString ChangeableMainScriptPackage::mainScriptConfigKey() const 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 ChangeableMainScriptPackage::pathChanged(Package *package) } } -void GenericPackage::initPackage(Package *package) +void GenericPackage::initPackage(KPackage::Package *package) { ChangeableMainScriptPackage::initPackage(package); @@ -105,20 +108,18 @@ void GenericPackage::initPackage(Package *package) 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 @@ void DataEnginePackage::initPackage(Package *package) 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 @@ void ThemePackage::initPackage(Package *package) 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 66d5765d9..0e0e80329 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 +#include + 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 000000000..24124e9fb --- /dev/null +++ b/src/plasma/private/packagestructure_p.h @@ -0,0 +1,71 @@ +/* + * Copyright © 2009 Rob Scheepmaker + * Copyright 2014 Marco Martin + * + * 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 +#include +#include + +namespace Plasma +{ + +class PackageStructureWrapper : public KPackage::PackageStructure { + Q_OBJECT + +public: + PackageStructureWrapper(Plasma::PackageStructure *structure, QObject *parent = 0, const QVariantList &args = QVariantList()); + + ~PackageStructureWrapper(); + + virtual void initPackage(KPackage::Package *package); + + virtual void pathChanged(KPackage::Package *package); + + virtual KJob *install(KPackage::Package *package, const QString &archivePath, const QString &packageRoot); + virtual KJob *uninstall(KPackage::Package *package, const QString &packageRoot); + +private: + QPointer m_struct; + static QHash s_packagesMap; + friend class Package; +}; + +class PackageStructurePrivate +{ +public: + PackageStructurePrivate(PackageStructure *str) + : internalStructure(0), + q(str) + {} + ~PackageStructurePrivate() + {} + + void installPathChanged(const QString &path); + + PackageStructure *q; + KPackage::PackageStructure *internalStructure; +}; + +} + +#endif diff --git a/src/plasmaquick/packageurlinterceptor.cpp b/src/plasmaquick/packageurlinterceptor.cpp index 553433941..334ae4220 100644 --- a/src/plasmaquick/packageurlinterceptor.cpp +++ b/src/plasmaquick/packageurlinterceptor.cpp @@ -91,6 +91,7 @@ QUrl PackageUrlInterceptor::intercept(const QUrl &path, QQmlAbstractUrlIntercept break; } } + //should never happen Q_ASSERT(!relativePath.isEmpty());