]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Dolphin: Implement package kit for deb/rpm/pacman service packages
authorAlexander Lohnau <alexander.lohnau@gmx.de>
Sun, 3 May 2020 18:23:08 +0000 (20:23 +0200)
committerAlexander Lohnau <alexander.lohnau@gmx.de>
Tue, 5 May 2020 15:26:13 +0000 (17:26 +0200)
Summary: The deb/rpm/pacman packages are now installed/uninstalled using packagekit.

Test Plan: Try to install deb package from kde store (search for `jetbrains`). Then uninstall it.

Reviewers: #dolphin, ngraham, elvisangelaccio, meven

Reviewed By: #dolphin, ngraham, elvisangelaccio, meven

Subscribers: cblack, anthonyfieroni, asturmlechner, meven, kfm-devel

Tags: #dolphin

Differential Revision: https://phabricator.kde.org/D29119

CMakeLists.txt
src/CMakeLists.txt
src/config-packagekit.h.cmake [new file with mode: 0644]
src/settings/services/servicemenuinstaller/CMakeLists.txt
src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp

index 3a30b69836ecea5199bc78e9ab62332ad807bf90..ee0082a8797e4e5626bced2353310654b0087eff 100644 (file)
@@ -77,6 +77,16 @@ set_package_properties(KF5Activities PROPERTIES DESCRIPTION "KActivities librari
 
 find_package(Phonon4Qt5 CONFIG REQUIRED)
 
+find_package(PackageKitQt5)
+set_package_properties(PackageKitQt5
+        PROPERTIES DESCRIPTION "Software Manager integration"
+        TYPE OPTIONAL
+        PURPOSE "Used in the service menu installer"
+        )
+if(PackageKitQt5_FOUND)
+    set(HAVE_PACKAGEKIT TRUE)
+endif()
+
 find_package(KF5Baloo ${KF5_MIN_VERSION})
 set_package_properties(KF5Baloo PROPERTIES DESCRIPTION "Baloo Core libraries"
                        URL "https://www.kde.org"
index fc7b33cbd4a78bd4881e213341c5cea4ff92c724..eabe80f61187e3c7b696fd507920ee48a53df6fc 100644 (file)
@@ -4,6 +4,8 @@ configure_file(config-baloo.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-baloo.h)
 
 configure_file(config-kactivities.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kactivities.h)
 
+configure_file(config-packagekit.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-packagekit.h)
+
 configure_file(config-terminal.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-terminal.h)
 
 add_definitions(
diff --git a/src/config-packagekit.h.cmake b/src/config-packagekit.h.cmake
new file mode 100644 (file)
index 0000000..780fff5
--- /dev/null
@@ -0,0 +1 @@
+#cmakedefine HAVE_PACKAGEKIT
index deb08421bf8cb636b5fb10eb14c7fc2e88f6bcdc..46b1590794f6be249d49442f58576429c2531423 100644 (file)
@@ -8,4 +8,8 @@ target_link_libraries(servicemenuinstaller PRIVATE
     KF5::I18n
     KF5::CoreAddons
 )
+
+if(HAVE_PACKAGEKIT)
+    target_link_libraries(servicemenuinstaller PRIVATE PK::packagekitqt5)
+endif()
 install(TARGETS servicemenuinstaller ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
index 60621921affdd80a44264cfbbf2425a32a21a32e..89f2545f80b9de6982a97685fda1abbfdf0bd652 100644 (file)
 
 #include <QDebug>
 #include <QProcess>
+#include <QTimer>
 #include <QStandardPaths>
 #include <QDir>
 #include <QDirIterator>
 #include <QCommandLineParser>
 #include <QMimeDatabase>
 #include <QUrl>
-#include <QDesktopServices>
 #include <QGuiApplication>
-
 #include <KLocalizedString>
 #include <KShell>
 
+#include "../../../config-packagekit.h"
+
+const static QStringList binaryPackages = {QStringLiteral("application/vnd.debian.binary-package"),
+                                     QStringLiteral("application/x-rpm"),
+                                     QStringLiteral("application/x-xz"),
+                                     QStringLiteral("application/zstd")};
+enum PackageOperation {
+    Install,
+    Uninstall
+};
+
+#ifdef HAVE_PACKAGEKIT
+#include <PackageKit/Daemon>
+#include <PackageKit/Details>
+#include <PackageKit/Transaction>
+#else
+#include <QDesktopServices>
+#endif
+
 // @param msg Error that gets logged to CLI
 Q_NORETURN void fail(const QString &str)
 {
     qCritical() << str;
-
-    QProcess process;
-    const QStringList args = {"--passivepopup", i18n("Dolphin service menu installation failed"), "15"};
-    process.start("kdialog", args, QIODevice::ReadOnly);
-    if (!process.waitForStarted()) {
-        qFatal("Failed to run kdialog");
-    }
+    const QStringList args = {"--detailederror" ,i18n("Dolphin service menu installation failed"),  str};
+    QProcess::startDetached("kdialog", args);
 
     exit(1);
 }
@@ -53,6 +66,84 @@ QString getServiceMenusDir()
     return QDir(dataLocation).absoluteFilePath("kservices5/ServiceMenus");
 }
 
+#ifdef HAVE_PACKAGEKIT
+void packageKitInstall(const QString &fileName)
+{
+    PackageKit::Transaction *transaction = PackageKit::Daemon::installFile(fileName);
+
+    const auto exitWithError = [=](PackageKit::Transaction::Error, const QString &details) {
+       fail(details);
+    };
+
+    QObject::connect(transaction, &PackageKit::Transaction::finished,
+                     [=](PackageKit::Transaction::Exit status, uint) {
+                        if (status == PackageKit::Transaction::ExitSuccess) {
+                            exit(0);
+                        }
+                        // Fallback error handling
+                        QTimer::singleShot(500, [=](){
+                            fail(i18n("Failed to install \"%1\", exited with status \"%2\"",
+                                      fileName, QVariant::fromValue(status).toString()));
+                        });
+                    });
+    QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+}
+
+void packageKitUninstall(const QString &fileName)
+{
+    const auto exitWithError = [=](PackageKit::Transaction::Error, const QString &details) {
+        fail(details);
+    };
+    const auto uninstallLambda = [=](PackageKit::Transaction::Exit status, uint) {
+        if (status == PackageKit::Transaction::ExitSuccess) {
+            exit(0);
+        }
+    };
+
+    PackageKit::Transaction *transaction = PackageKit::Daemon::getDetailsLocal(fileName);
+    QObject::connect(transaction, &PackageKit::Transaction::details,
+                     [=](const PackageKit::Details &details) {
+                         PackageKit::Transaction *transaction = PackageKit::Daemon::removePackage(details.packageId());
+                         QObject::connect(transaction, &PackageKit::Transaction::finished, uninstallLambda);
+                         QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+                     });
+
+    QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+    // Fallback error handling
+    QObject::connect(transaction, &PackageKit::Transaction::finished,
+        [=](PackageKit::Transaction::Exit status, uint) {
+            if (status != PackageKit::Transaction::ExitSuccess) {
+                QTimer::singleShot(500, [=]() {
+                    fail(i18n("Failed to uninstall \"%1\", exited with status \"%2\"",
+                              fileName, QVariant::fromValue(status).toString()));
+                });
+            }
+        });
+    }
+#endif
+
+Q_NORETURN void packageKit(PackageOperation operation, const QString &fileName)
+{
+#ifdef HAVE_PACKAGEKIT
+    QFileInfo fileInfo(fileName);
+    if (!fileInfo.exists()) {
+        fail(i18n("The file does not exist!"));
+    }
+    const QString absPath = fileInfo.absoluteFilePath();
+    if (operation == PackageOperation::Install) {
+        packageKitInstall(absPath);
+    } else {
+        packageKitUninstall(absPath);
+    }
+    QGuiApplication::exec(); // For event handling, no return after signals finish
+    fail(i18n("Unknown error when installing package"));
+#else
+    Q_UNUSED(operation)
+    QDesktopServices::openUrl(QUrl(fileName));
+    exit(0);
+#endif
+}
+
 struct UncompressCommand
 {
     QString command;
@@ -220,9 +311,8 @@ bool cmdInstall(const QString &archive, QString &errorText)
             return false;
         }
     } else {
-        const QStringList binaryPackages = {"application/vnd.debian.binary-package", "application/x-rpm"};
         if (binaryPackages.contains(QMimeDatabase().mimeTypeForFile(archive).name())) {
-            return QDesktopServices::openUrl(QUrl(archive));
+            packageKit(PackageOperation::Install, archive);
         }
         const QString dir = generateDirPath(archive);
         if (QFile::exists(dir)) {
@@ -290,6 +380,9 @@ bool cmdUninstall(const QString &archive, QString &errorText)
             return false;
         }
     } else {
+        if (binaryPackages.contains(QMimeDatabase().mimeTypeForFile(archive).name())) {
+            packageKit(PackageOperation::Uninstall, archive);
+        }
         const QString dir = generateDirPath(archive);
 
         // Try "deinstall" first