[kdelibs] * Sun Aug 21 2011 Kevin Kofler <Kevin at tigcc.ticalc.org> 4.7.0-3 - backport my GSoC 2011 patches for
Kevin Kofler
kkofler at fedoraproject.org
Sun Aug 21 02:10:47 UTC 2011
commit 516b628b71a8d0521d67ad5b454cfbacd6b886b2
Author: Kevin Kofler <Kevin at tigcc.ticalc.org>
Date: Sun Aug 21 04:10:16 2011 +0200
* Sun Aug 21 2011 Kevin Kofler <Kevin at tigcc.ticalc.org> 4.7.0-3
- backport my GSoC 2011 patches for libplasma PackageKit integration (F17+)
(The main reason this is F17+ only is because F16 and F15 don't have the
required Provides at this time.)
...currently-private-for-installing-missing-.patch | 312 ++++++++++++++++++
...tallation-of-missing-components-when-inst.patch | 166 ++++++++++
...utomatic-scanning-of-source-code-for-requ.patch | 333 ++++++++++++++++++++
kdelibs.spec | 23 ++-
4 files changed, 833 insertions(+), 1 deletions(-)
---
diff --git a/0001-Add-an-API-currently-private-for-installing-missing-.patch b/0001-Add-an-API-currently-private-for-installing-missing-.patch
new file mode 100644
index 0000000..29aa786
--- /dev/null
+++ b/0001-Add-an-API-currently-private-for-installing-missing-.patch
@@ -0,0 +1,312 @@
+From 5bf9e0aa14f849726f3573b04eb51acfff635fc6 Mon Sep 17 00:00:00 2001
+Message-Id: <5bf9e0aa14f849726f3573b04eb51acfff635fc6.1312359834.git.kevin.kofler at chello.at>
+From: Kevin Kofler <kevin.kofler at chello.at>
+Date: Mon, 1 Aug 2011 21:53:32 +0200
+Subject: [PATCH] Add an API (currently private) for installing missing Plasma
+ engines.
+
+Use it when a requested data or script engine is not found.
+
+REVIEW: 102175
+---
+ plasma/CMakeLists.txt | 11 ++++
+ plasma/dataenginemanager.cpp | 4 +
+ plasma/private/componentinstaller.cpp | 103 +++++++++++++++++++++++++++++++++
+ plasma/private/componentinstaller_p.h | 94 ++++++++++++++++++++++++++++++
+ plasma/scripting/scriptengine.cpp | 4 +
+ 5 files changed, 216 insertions(+), 0 deletions(-)
+
+diff --git a/plasma/CMakeLists.txt b/plasma/CMakeLists.txt
+index ef411df..f929967 100644
+--- a/plasma/CMakeLists.txt
++++ b/plasma/CMakeLists.txt
+@@ -6,8 +6,13 @@ if(KDE_PLATFORM_FEATURE_BINARY_COMPATIBLE_FEATURE_REDUCTION)
+ set(PLASMA_NO_KNEWSTUFF TRUE)
+ set(PLASMA_NO_SOLID TRUE)
+ set(PLASMA_NO_KIO TRUE)
++ set(PLASMA_NO_PACKAGEKIT TRUE)
+ endif(KDE_PLATFORM_FEATURE_BINARY_COMPATIBLE_FEATURE_REDUCTION)
+
++if(NOT Q_WS_X11)
++ set(PLASMA_NO_PACKAGEKIT TRUE)
++endif(NOT Q_WS_X11)
++
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${KDE4_KDECORE_INCLUDES}
+ ${KDE4_KDEUI_INCLUDES}
+@@ -42,6 +47,11 @@ if(NOT PLASMA_NO_SOLID)
+ set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${KDE4_SOLID_LIBS})
+ endif(NOT PLASMA_NO_SOLID)
+
++if(NOT PLASMA_NO_PACKAGEKIT)
++ add_definitions(-DPLASMA_ENABLE_PACKAGEKIT_SUPPORT=1)
++ set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${QT_QTDBUS_LIBRARY})
++endif(NOT PLASMA_NO_PACKAGEKIT)
++
+ if(QCA2_FOUND)
+ include_directories(${QCA2_INCLUDE_DIR})
+ set(ENABLE_REMOTE_WIDGETS TRUE)
+@@ -110,6 +120,7 @@ set(plasma_LIB_SRCS
+ private/animablegraphicswebview.cpp
+ private/applethandle.cpp
+ private/associatedapplicationmanager.cpp
++ private/componentinstaller.cpp
+ private/datacontainer_p.cpp
+ private/dataenginebindings.cpp
+ private/dataengineconsumer.cpp
+diff --git a/plasma/dataenginemanager.cpp b/plasma/dataenginemanager.cpp
+index 988fe76..c98ac40 100644
+--- a/plasma/dataenginemanager.cpp
++++ b/plasma/dataenginemanager.cpp
+@@ -29,6 +29,7 @@
+
+ #include "datacontainer.h"
+ #include "pluginloader.h"
++#include "private/componentinstaller_p.h"
+ #include "private/dataengine_p.h"
+ #include "private/datacontainer_p.h"
+ #include "scripting/scriptengine.h"
+@@ -130,6 +131,9 @@ Plasma::DataEngine *DataEngineManager::loadEngine(const QString &name)
+
+ DataEngine *engine = PluginLoader::pluginLoader()->loadDataEngine(name);
+ if (!engine) {
++ // Try installing the engine. However, it's too late for this request.
++ ComponentInstaller::self()->installMissingComponent("dataengine", name);
++
+ return d->nullEngine();
+ }
+
+diff --git a/plasma/private/componentinstaller.cpp b/plasma/private/componentinstaller.cpp
+new file mode 100644
+index 0000000..870667f
+--- /dev/null
++++ b/plasma/private/componentinstaller.cpp
+@@ -0,0 +1,103 @@
++/*
++ * Copyright 2011 Kevin Kofler <kevin.kofler at chello.at>
++ *
++ * This program 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, or
++ * (at your option) any later version.
++ *
++ * 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.
++ */
++
++#include "private/componentinstaller_p.h"
++
++#include <kglobal.h>
++
++#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
++#include <QSet>
++#include <QDBusInterface>
++#include <QDBusPendingCall>
++#include <QWidget>
++#include <QLatin1String>
++#include <QStringList>
++#endif
++
++namespace Plasma
++{
++
++class ComponentInstallerPrivate
++{
++ public:
++#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
++ QSet<QString> alreadyPrompted;
++#endif
++};
++
++class ComponentInstallerSingleton
++{
++ public:
++ ComponentInstaller self;
++};
++
++K_GLOBAL_STATIC(ComponentInstallerSingleton, privateComponentInstallerSelf)
++
++ComponentInstaller *ComponentInstaller::self()
++{
++ return &privateComponentInstallerSelf->self;
++}
++
++ComponentInstaller::ComponentInstaller()
++ : d(new ComponentInstallerPrivate)
++{
++}
++
++ComponentInstaller::~ComponentInstaller()
++{
++ delete d;
++}
++
++void ComponentInstaller::installMissingComponent(const QString &type,
++ const QString &name,
++ QWidget *parent, bool force)
++{
++#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
++ QString searchString = type + '-' + name;
++
++ if (!force) {
++ if (d->alreadyPrompted.contains(searchString)) {
++ return;
++ }
++ }
++
++ d->alreadyPrompted.insert(searchString);
++
++ QDBusInterface packageKit(QLatin1String("org.freedesktop.PackageKit"),
++ QLatin1String("/org/freedesktop/PackageKit"),
++ QLatin1String("org.freedesktop.PackageKit.Modify"));
++ // We don't check packageKit.isValid() because the service is activated on
++ // demand, so it will show up as "not valid".
++ WId wid = 0;
++ if (parent) {
++ wid = parent->winId();
++ }
++ QStringList resources;
++ resources.append(searchString);
++ packageKit.asyncCall(QLatin1String("InstallResources"), (unsigned int) wid,
++ QLatin1String("plasma-service"), resources, QString());
++#else
++ Q_UNUSED(type);
++ Q_UNUSED(name);
++ Q_UNUSED(parent);
++ Q_UNUSED(force);
++#endif
++}
++
++} // namespace Plasma
+diff --git a/plasma/private/componentinstaller_p.h b/plasma/private/componentinstaller_p.h
+new file mode 100644
+index 0000000..f85cbb6
+--- /dev/null
++++ b/plasma/private/componentinstaller_p.h
+@@ -0,0 +1,94 @@
++/*
++ * Copyright 2011 Kevin Kofler <kevin.kofler at chello.at>
++ *
++ * This program 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, or
++ * (at your option) any later version.
++ *
++ * 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_COMPONENTINSTALLER_H
++#define PLASMA_COMPONENTINSTALLER_H
++
++class QString;
++class QWidget;
++
++namespace Plasma
++{
++
++class ComponentInstallerPrivate;
++
++/**
++ * @class ComponentInstaller plasma/private/componentinstaller_p.h
++ *
++ * @short This class provides a generic API for installation of components.
++ *
++ * @internal
++ *
++ * Plasma::ComponentInstaller allows searching for a missing data or script
++ * engine by name, and allowing the user to install the missing service.
++ * Currently, PackageKit is supported as the mechanism to install components,
++ * but more mechanisms could be supported in the future through the same API.
++ *
++ * @since 4.8
++ */
++class ComponentInstaller
++{
++ public:
++ /**
++ * Singleton pattern accessor.
++ */
++ static ComponentInstaller *self();
++
++ /**
++ * Installs a missing component asynchronously.
++ *
++ * By default, this method will cache requested components and not
++ * prompt again for the same engine in the same session. The force
++ * parameter can be used to disable this mechanism, e.g. when the user
++ * just installed a new widget written in a scripting language, and so
++ * is likely to want the script engine installed after all.
++ *
++ * In the case of on-demand installation, this will unfortunately not
++ * allow the call which triggered the missing component lookup to
++ * succeed, but we cannot afford to block all of Plasma until the
++ * mechanism is done installing the service.
++ *
++ * This function does nothing if PackageKit integration was disabled at
++ * compile time.
++ *
++ * @param type the type of the component, should be "scriptengine" or
++ * "dataengine"
++ * @param name the name of the component
++ * @param parent a parent widget, used to set the wid for PackageKit
++ * @param force whether to always prompt, even if recently prompted
++ */
++ void installMissingComponent(const QString &type, const QString &name,
++ QWidget *parent = 0, bool force = false);
++
++ private:
++ /**
++ * Default constructor. The singleton method self() is the
++ * preferred access mechanism.
++ */
++ ComponentInstaller();
++ ~ComponentInstaller();
++
++ ComponentInstallerPrivate *const d;
++
++ friend class ComponentInstallerSingleton;
++};
++
++} // namespace Plasma
++
++#endif // multiple inclusion guard
+diff --git a/plasma/scripting/scriptengine.cpp b/plasma/scripting/scriptengine.cpp
+index fb8cd1a..21f8a9a 100644
+--- a/plasma/scripting/scriptengine.cpp
++++ b/plasma/scripting/scriptengine.cpp
+@@ -27,6 +27,7 @@
+ #include "applet.h"
+ #include "dataengine.h"
+ #include "package.h"
++#include "private/componentinstaller_p.h"
+ #include "scripting/appletscript.h"
+ #include "scripting/dataenginescript.h"
+ #include "scripting/runnerscript.h"
+@@ -196,6 +197,9 @@ ScriptEngine *loadEngine(const QString &language, ComponentType type, QObject *p
+ << "! error reported: " << error;
+ }
+
++ // Try installing the engine. However, it's too late for this request.
++ ComponentInstaller::self()->installMissingComponent("scriptengine", language);
++
+ return 0;
+ }
+
+--
+1.7.4.4
+
diff --git a/0002-Trigger-installation-of-missing-components-when-inst.patch b/0002-Trigger-installation-of-missing-components-when-inst.patch
new file mode 100644
index 0000000..b786bbf
--- /dev/null
+++ b/0002-Trigger-installation-of-missing-components-when-inst.patch
@@ -0,0 +1,166 @@
+From 00a8b22ad6dbb03eea18090f6d9f578101632752 Mon Sep 17 00:00:00 2001
+Message-Id: <00a8b22ad6dbb03eea18090f6d9f578101632752.1313007841.git.kevin.kofler at chello.at>
+From: Kevin Kofler <kevin.kofler at chello.at>
+Date: Wed, 10 Aug 2011 21:48:19 +0200
+Subject: [PATCH] Trigger installation of missing components when installing a
+ package.
+
+For script engines, the existing metadata (X-Plasma-API) is sufficient.
+
+For data engines, we introduce a new metadata entry:
+X-Plasma-RequiredDataEngines. Third-party packages will have to add this entry
+to benefit from this feature at this time. Automatic support for scanning
+package source code on installation (at least for some languages) is planned,
+but the metadata entry is definitely the most efficient method.
+---
+ plasma/package.cpp | 39 +++++++++++++++++++++++++++++++++++++++
+ plasma/packagemetadata.cpp | 13 +++++++++++++
+ plasma/packagemetadata.h | 7 +++++++
+ 3 files changed, 59 insertions(+), 0 deletions(-)
+
+diff --git a/plasma/package.cpp b/plasma/package.cpp
+index 4c00d36..0a45c87 100644
+--- a/plasma/package.cpp
++++ b/plasma/package.cpp
+@@ -49,8 +49,11 @@
+ #include <kdebug.h>
+
+ #include "authorizationmanager.h"
++#include "dataenginemanager.h"
+ #include "packagemetadata.h"
++#include "scripting/scriptengine.h"
+ #include "private/authorizationmanager_p.h"
++#include "private/componentinstaller_p.h"
+ #include "private/package_p.h"
+ #include "private/plasmoidservice_p.h"
+ #include "private/service_p.h"
+@@ -603,6 +606,42 @@ bool Package::installPackage(const QString &package,
+ tempdir.setAutoRemove(false);
+ }
+
++ // check for missing dependencies
++ QString requiredScriptEngine = meta.implementationApi();
++ if (!requiredScriptEngine.isEmpty()) {
++ // figure out the component type to query for
++ ComponentTypes componentTypes = static_cast<ComponentTypes>(0);
++ QStringList serviceTypes = meta.serviceType().split(',');
++ if (serviceTypes.contains("Plasma/Applet")) {
++ componentTypes |= AppletComponent;
++ }
++ if (serviceTypes.contains("Plasma/DataEngine")) {
++ componentTypes |= DataEngineComponent;
++ }
++ if (serviceTypes.contains("Plasma/Runner")) {
++ componentTypes |= RunnerComponent;
++ }
++ if (serviceTypes.contains("Plasma/Wallpaper")) {
++ componentTypes |= WallpaperComponent;
++ }
++ if (!knownLanguages(componentTypes).contains(requiredScriptEngine)) {
++ // install the missing script engine
++ // force prompting because the user has just explicitly installed a widget
++ ComponentInstaller::self()->installMissingComponent("scriptengine", requiredScriptEngine, 0, true);
++ }
++ }
++ QStringList requiredDataEngines = meta.requiredDataEngines();
++ if (!requiredDataEngines.isEmpty()) {
++ QStringList knownDataEngines = DataEngineManager::self()->listAllEngines(meta.application());
++ foreach (const QString &requiredDataEngine, requiredDataEngines) {
++ if (!knownDataEngines.contains(requiredDataEngine)) {
++ // install the missing data engine
++ // force prompting because the user has just explicitly installed a widget
++ ComponentInstaller::self()->installMissingComponent("dataengine", requiredDataEngine, 0, true);
++ }
++ }
++ }
++
+ if (!servicePrefix.isEmpty()) {
+ // and now we register it as a service =)
+ QString metaPath = targetName + "/metadata.desktop";
+diff --git a/plasma/packagemetadata.cpp b/plasma/packagemetadata.cpp
+index 59163b2..8cfaf64 100644
+--- a/plasma/packagemetadata.cpp
++++ b/plasma/packagemetadata.cpp
+@@ -52,6 +52,7 @@ class PackageMetadataPrivate
+ QString serviceType;
+ QString api;
+ KUrl location;
++ QStringList requiredDataEngines;
+ };
+
+ PackageMetadata::PackageMetadata(const PackageMetadata &other)
+@@ -106,6 +107,7 @@ void PackageMetadata::write(const QString &filename) const
+ config.writeEntry("X-KDE-ParentApp", d->app);
+ config.writeEntry("Type", d->type);
+ config.writeEntry("X-Plasma-RemoteLocation", d->location);
++ config.writeEntry("X-Plasma-RequiredDataEngines", d->requiredDataEngines);
+ }
+
+ void PackageMetadata::read(const QString &filename)
+@@ -133,6 +135,7 @@ void PackageMetadata::read(const QString &filename)
+ d->app = config.readEntry("X-KDE-ParentApp", d->app);
+ d->type = config.readEntry("Type", d->type);
+ d->location = config.readEntry("X-Plasma-RemoteLocation", d->location);
++ d->requiredDataEngines = config.readEntry("X-Plasma-RequiredDataEngines", d->requiredDataEngines);
+ }
+
+ QString PackageMetadata::name() const
+@@ -225,6 +228,11 @@ QString PackageMetadata::implementationApi() const
+ return d->api;
+ }
+
++QStringList PackageMetadata::requiredDataEngines() const
++{
++ return d->requiredDataEngines;
++}
++
+ void PackageMetadata::setImplementationApi(const QString &api)
+ {
+ d->api = api;
+@@ -300,6 +308,11 @@ void PackageMetadata::setRemoteLocation(const KUrl &location)
+ d->location = location;
+ }
+
++void PackageMetadata::setRequiredDataEngines(const QStringList &requiredDataEngines)
++{
++ d->requiredDataEngines = requiredDataEngines;
++}
++
+ void PackageMetadata::setType(const QString &type)
+ {
+ d->type = type;
+diff --git a/plasma/packagemetadata.h b/plasma/packagemetadata.h
+index b10f0e4..ec396a6 100644
+--- a/plasma/packagemetadata.h
++++ b/plasma/packagemetadata.h
+@@ -21,6 +21,7 @@
+ #define PLASMA_PACKAGEMETADATA_H
+
+ #include <QtCore/QString>
++#include <QtCore/QStringList>
+
+ #include <plasma/plasma_export.h>
+
+@@ -92,6 +93,7 @@ public:
+ QString pluginName() const;
+ QString implementationApi() const;
+ KUrl remoteLocation() const;
++ QStringList requiredDataEngines() const;
+
+ QString type() const;
+
+@@ -205,6 +207,11 @@ public:
+ */
+ void setImplementationApi(const QString &api);
+
++ /**
++ * Set the required data engines for this package.
++ */
++ void setRequiredDataEngines(const QStringList &);
++
+ private:
+ PackageMetadataPrivate * const d;
+ };
+--
+1.7.4.4
+
diff --git a/0003-Implement-automatic-scanning-of-source-code-for-requ.patch b/0003-Implement-automatic-scanning-of-source-code-for-requ.patch
new file mode 100644
index 0000000..250e5ea
--- /dev/null
+++ b/0003-Implement-automatic-scanning-of-source-code-for-requ.patch
@@ -0,0 +1,333 @@
+From 1ce984bda1bb6a06f237240069a9f3a554cbbf37 Mon Sep 17 00:00:00 2001
+Message-Id: <1ce984bda1bb6a06f237240069a9f3a554cbbf37.1313890335.git.kevin.kofler at chello.at>
+From: Kevin Kofler <kevin.kofler at chello.at>
+Date: Wed, 17 Aug 2011 04:54:37 +0200
+Subject: [PATCH] Implement automatic scanning of source code for required
+ data engines.
+
+For packages in scripting languages and distributed through OCS, this is fully
+automatic and triggered from Package::installPackage. If an
+X-Plasma-RequiredDataEngines entry is present in the .desktop file (even if
+empty), the dependency extraction is not run and the explicitly provided
+information is trusted instead.
+
+For native distribution packages, we ship a tool called
+plasma-dataengine-depextractor which can be run at any time during the build
+process and which adds the dependency information to the relevant .desktop file.
+
+Authors of plasmoids are encouraged to run plasma-dataengine-depextractor and/or
+fill in X-Plasma-RequiredDataEngines manually. (Please note that the list is
+expected to be comma-separated.)
+---
+ plasma/CMakeLists.txt | 15 ++++
+ plasma/depextractor/depextractor.cpp | 115 +++++++++++++++++++++++++++++++++
+ plasma/package.cpp | 11 +++
+ plasma/private/componentinstaller.cpp | 68 +++++++++++++++++++
+ plasma/private/componentinstaller_p.h | 17 +++++-
+ 5 files changed, 225 insertions(+), 1 deletions(-)
+
+diff --git a/plasma/CMakeLists.txt b/plasma/CMakeLists.txt
+index f929967..9a760ef 100644
+--- a/plasma/CMakeLists.txt
++++ b/plasma/CMakeLists.txt
+@@ -304,6 +304,18 @@ set_target_properties(plasma PROPERTIES
+
+ install(TARGETS plasma EXPORT kdelibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
+
++if(NOT PLASMA_NO_PACKAGEKIT)
++ # we need a copy of the component installer because libplasma does not export it
++ # plus, this avoids depending on GUI stuff in this command-line utility
++ set(plasma_dataengine_depextractor_SRCS depextractor/depextractor.cpp
++ private/componentinstaller.cpp)
++ kde4_add_executable(plasma-dataengine-depextractor
++ ${plasma_dataengine_depextractor_SRCS})
++ set_target_properties(plasma-dataengine-depextractor PROPERTIES
++ COMPILE_FLAGS -DPLASMA_COMPONENTINSTALLER_NO_QWIDGET=1)
++ target_link_libraries(plasma-dataengine-depextractor ${KDE4_KDECORE_LIBS})
++endif(NOT PLASMA_NO_PACKAGEKIT)
++
+
+ ########### install files ###############
+
+@@ -460,3 +472,6 @@ install(FILES data/operations/dataengineservice.operations DESTINATION ${DATA_IN
+ install(FILES data/operations/plasmoidservice.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
+ install(FILES data/operations/storage.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
+
++if(NOT PLASMA_NO_PACKAGEKIT)
++ install(TARGETS plasma-dataengine-depextractor DESTINATION ${BIN_INSTALL_DIR})
++endif(NOT PLASMA_NO_PACKAGEKIT)
+diff --git a/plasma/depextractor/depextractor.cpp b/plasma/depextractor/depextractor.cpp
+new file mode 100644
+index 0000000..221b88b
+--- /dev/null
++++ b/plasma/depextractor/depextractor.cpp
+@@ -0,0 +1,115 @@
++/* Plasma Data Engine dependency extractor
++ Copyright (C) 2011 Kevin Kofler <kevin.kofler at chello.at>
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 2 of the License, or
++ (at your option) any later version.
++
++ 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 General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++#include <QCoreApplication>
++#include <QTextStream>
++#include <QFileInfo>
++#include <QDir>
++
++#include <cstdio>
++
++#include <kaboutdata.h>
++#include <kcmdlineargs.h>
++#include <kdesktopfile.h>
++#include <kconfiggroup.h>
++
++#include "private/componentinstaller_p.h"
++
++static void writeDataEngineDependencies(const QStringList &deps,
++ const QString &desktopFile)
++{
++ if (!deps.isEmpty()) {
++ KDesktopFile desktop(desktopFile);
++ desktop.desktopGroup().writeEntry("X-Plasma-RequiredDataEngines", deps);
++ }
++}
++
++int main(int argc, char **argv)
++{
++ KAboutData aboutData("plasma-dataengine-depextractor", QByteArray(),
++ ki18n("Plasma Data Engine dependency extractor"),
++ "1",
++ ki18n("Plasma Data Engine dependency extractor"));
++ aboutData.addAuthor(ki18n("Kevin Kofler"), ki18n("Author"),
++ "kevin.kofler at chello.at");
++
++ KCmdLineArgs::init(argc, argv, &aboutData);
++ KCmdLineOptions options;
++ options.add("a")
++ .add("api <name>",
++ ki18n("Sets the name of the scripting API/language"));
++ options.add("+[path]",
++ ki18n("Source path (default: .)"));
++ options.add("+[file]",
++ ki18n(".desktop rel. to path (default: metadata.desktop)")
++ );
++ KCmdLineArgs::addCmdLineOptions(options);
++
++ QCoreApplication *app = new QCoreApplication(KCmdLineArgs::qtArgc(),
++ KCmdLineArgs::qtArgv());
++
++ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
++
++ int exitCode = 0;
++
++ QString api, path, desktopFile;
++ if (args->isSet("api")) {
++ api = args->getOption("api");
++ }
++ int argCount = args->count();
++ switch (argCount) {
++ case 0:
++ path = ".";
++ desktopFile = "metadata.desktop";
++ break;
++ case 1:
++ path = args->arg(0);
++ desktopFile = "metadata.desktop";
++ break;
++ case 2:
++ path = args->arg(0);
++ desktopFile = args->arg(1);
++ break;
++ default:
++ {
++ QTextStream err(stderr, QIODevice::WriteOnly | QIODevice::Text);
++ err << i18n("Expected at most 2 arguments, but %1 given", argCount)
++ << endl;
++ exitCode = 1;
++ break;
++ }
++ }
++
++ if (!exitCode) {
++ if (QFileInfo(desktopFile).isRelative())
++ desktopFile = QDir(path).filePath(desktopFile);
++
++ if (QFileInfo(desktopFile).exists()) {
++ writeDataEngineDependencies(Plasma::ComponentInstaller::self()
++ ->extractDataEngineDependencies(path,
++ api),
++ desktopFile);
++ } else {
++ QTextStream err(stderr, QIODevice::WriteOnly | QIODevice::Text);
++ err << i18n("Desktop file \"%1\" not found", desktopFile) << endl;
++ exitCode = 1;
++ }
++ }
++
++ args->clear();
++ delete app;
++ return exitCode;
++}
+diff --git a/plasma/package.cpp b/plasma/package.cpp
+index 0a45c87..131f204 100644
+--- a/plasma/package.cpp
++++ b/plasma/package.cpp
+@@ -631,6 +631,17 @@ bool Package::installPackage(const QString &package,
+ }
+ }
+ QStringList requiredDataEngines = meta.requiredDataEngines();
++ if (requiredDataEngines.isEmpty()) {
++ // check whether this was explicitly specified as empty
++ QString metaPath = targetName + "/metadata.desktop";
++ KDesktopFile df(metaPath);
++ KConfigGroup cg = df.desktopGroup();
++ if (!cg.hasKey("X-Plasma-RequiredDataEngines")) {
++ // not specified at all, try running the dependency extraction
++ requiredDataEngines = ComponentInstaller::self()->extractDataEngineDependencies(targetName,
++ requiredScriptEngine);
++ }
++ }
+ if (!requiredDataEngines.isEmpty()) {
+ QStringList knownDataEngines = DataEngineManager::self()->listAllEngines(meta.application());
+ foreach (const QString &requiredDataEngine, requiredDataEngines) {
+diff --git a/plasma/private/componentinstaller.cpp b/plasma/private/componentinstaller.cpp
+index 870667f..2c8c2dd 100644
+--- a/plasma/private/componentinstaller.cpp
++++ b/plasma/private/componentinstaller.cpp
+@@ -28,6 +28,10 @@
+ #include <QWidget>
+ #include <QLatin1String>
+ #include <QStringList>
++#include <QTextStream>
++#include <QFile>
++#include <QDirIterator>
++#include <QRegExp>
+ #endif
+
+ namespace Plasma
+@@ -85,9 +89,13 @@ void ComponentInstaller::installMissingComponent(const QString &type,
+ // We don't check packageKit.isValid() because the service is activated on
+ // demand, so it will show up as "not valid".
+ WId wid = 0;
++#ifndef PLASMA_COMPONENTINSTALLER_NO_QWIDGET
+ if (parent) {
+ wid = parent->winId();
+ }
++#else
++ Q_UNUSED(parent);
++#endif
+ QStringList resources;
+ resources.append(searchString);
+ packageKit.asyncCall(QLatin1String("InstallResources"), (unsigned int) wid,
+@@ -100,4 +108,64 @@ void ComponentInstaller::installMissingComponent(const QString &type,
+ #endif
+ }
+
++QStringList ComponentInstaller::extractDataEngineDependencies(const QString &path,
++ const QString &api)
++{
++ QStringList deps;
++
++#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
++ QStringList nameFilters;
++ QRegExp searchRegExp("dataEngine *\\( *\"([^\"]+)\" *\\)");
++ if (api.isEmpty()) {
++ // no script engine API, this is native C++ code
++ nameFilters.append("*.cpp");
++ nameFilters.append("*.cxx");
++ nameFilters.append("*.cc");
++ nameFilters.append("*.C");
++ nameFilters.append("*.h");
++ nameFilters.append("*.hpp");
++ nameFilters.append("*.hxx");
++ nameFilters.append("*.hh");
++ nameFilters.append("*.H");
++ } else if (api == "javascript") {
++ nameFilters.append("*.js");
++ } else if (api == "python") {
++ nameFilters.append("*.py");
++ searchRegExp = QRegExp("dataEngine *\\( *[\'\"]([^\'\"]+)[\'\"] *\\)");
++ } else if (api == "ruby-script") {
++ nameFilters.append("*.rb");
++ searchRegExp = QRegExp("dataEngine *\\( *[\'\"]([^\'\"]+)[\'\"] *\\)");
++ } else {
++ // dependency extraction not supported for this API
++ return deps;
++ }
++
++ QDirIterator it(path, nameFilters, QDir::Files | QDir::CaseSensitive,
++ QDirIterator::Subdirectories
++ | QDirIterator::FollowSymlinks);
++ while (it.hasNext()) {
++ QFile file(it.next());
++ file.open(QIODevice::ReadOnly | QIODevice::Text);
++ QTextStream stream(&file);
++ QString line;
++ while (!(line = stream.readLine()).isNull()) {
++ int column = 0;
++ while ((column = searchRegExp.indexIn(line, column)) != -1) {
++ QString dep = searchRegExp.cap(1);
++ if (!deps.contains(dep)) {
++ deps.append(dep);
++ }
++ column += searchRegExp.matchedLength();
++ }
++ }
++ file.close();
++ }
++#else
++ Q_UNUSED(path);
++ Q_UNUSED(api);
++#endif
++
++ return deps;
++}
++
+ } // namespace Plasma
+diff --git a/plasma/private/componentinstaller_p.h b/plasma/private/componentinstaller_p.h
+index f85cbb6..d0d9c75 100644
+--- a/plasma/private/componentinstaller_p.h
++++ b/plasma/private/componentinstaller_p.h
+@@ -20,7 +20,7 @@
+ #ifndef PLASMA_COMPONENTINSTALLER_H
+ #define PLASMA_COMPONENTINSTALLER_H
+
+-class QString;
++#include <QStringList>
+ class QWidget;
+
+ namespace Plasma
+@@ -76,6 +76,21 @@ class ComponentInstaller
+ void installMissingComponent(const QString &type, const QString &name,
+ QWidget *parent = 0, bool force = false);
+
++ /**
++ * Extracts the list of required data engines from source code.
++ *
++ * If the scripting API is not supported for dependency extraction or
++ * if Plasma was compiled without support for missing component
++ * installation, an empty list of dependencies is returned.
++ *
++ * @param path the path containing the source code
++ * @param api the scripting API used;
++ * if empty (the default), assumes the native C++ API
++ */
++ QStringList extractDataEngineDependencies(const QString &path,
++ const QString &api
++ = QString());
++
+ private:
+ /**
+ * Default constructor. The singleton method self() is the
+--
+1.7.4.4
+
diff --git a/kdelibs.spec b/kdelibs.spec
index 0e89883..9f76991 100644
--- a/kdelibs.spec
+++ b/kdelibs.spec
@@ -13,7 +13,7 @@
Summary: KDE Libraries
Version: 4.7.0
-Release: 2%{?dist}
+Release: 3%{?dist}
Name: kdelibs
Epoch: 6
@@ -96,6 +96,17 @@ Patch24: kdelibs-4.3.1-drkonq.patch
# -DCMAKE_SKIP_RPATH:BOOL=ON (finally)
Patch27: kdelibs-4.5.80-no_rpath.patch
+## libplasma PackageKit integration
+# Add an API (currently private) for installing missing Plasma engines.
+# https://git.reviewboard.kde.org/r/102175/
+Patch40: 0001-Add-an-API-currently-private-for-installing-missing-.patch
+# Trigger installation of missing components when installing a package.
+# https://git.reviewboard.kde.org/r/102291/
+Patch41: 0002-Trigger-installation-of-missing-components-when-inst.patch
+# Implement automatic scanning of source code for required data engines.
+# https://git.reviewboard.kde.org/r/102350/
+Patch42: 0003-Implement-automatic-scanning-of-source-code-for-requ.patch
+
## upstreamable
# add gpg2 support to knewstuff, rough first try s/gpg/gpg2/
# reverting to our past gnupg2-only setup.
@@ -290,6 +301,13 @@ sed -i -e "s|@@VERSION_RELEASE@@|%{version}-%{release}|" kio/kio/kprotocolmanage
%endif
%patch27 -p1 -b .no_rpath
+# libplasma PackageKit integration
+%if 0%{?fedora} > 16
+%patch40 -p1 -b .libplasma-pk-0001
+%patch41 -p1 -b .libplasma-pk-0002
+%patch42 -p1 -b .libplasma-pk-0003
+%endif
+
# upstreamable patches
%patch50 -p1 -b .knewstuff_gpg2
%patch51 -p1 -b .uri_mimetypes
@@ -542,6 +560,9 @@ rm -rf %{buildroot}
%changelog
+* Sun Aug 21 2011 Kevin Kofler <Kevin at tigcc.ticalc.org> 4.7.0-3
+- backport my GSoC 2011 patches for libplasma PackageKit integration (F17+)
+
* Sun Aug 21 2011 Kevin Kofler <Kevin at tigcc.ticalc.org> 4.7.0-2
- rebuild for the RPM dependency generators for Plasma (GSoC 2011)
- add BuildRequires: kde-settings to pick up the above
More information about the scm-commits
mailing list