┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Lohnau <[email protected]>2020-05-03 20:23:08 +0200
committerAlexander Lohnau <[email protected]>2020-05-05 17:26:13 +0200
commit3e1cb2c7fb41d20f19bb039c77714e8128bf5e00 (patch)
tree570b95774a0509865b403c2eaf40086463b8f1c4
parentecede34048472432c140ed30981f86be2e9f1199 (diff)
Dolphin: Implement package kit for deb/rpm/pacman service packages
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
-rw-r--r--CMakeLists.txt10
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/config-packagekit.h.cmake1
-rw-r--r--src/settings/services/servicemenuinstaller/CMakeLists.txt4
-rw-r--r--src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp115
5 files changed, 121 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3a30b6983..ee0082a87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc7b33cbd..eabe80f61 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
index 000000000..780fff56e
--- /dev/null
+++ b/src/config-packagekit.h.cmake
@@ -0,0 +1 @@
+#cmakedefine HAVE_PACKAGEKIT
diff --git a/src/settings/services/servicemenuinstaller/CMakeLists.txt b/src/settings/services/servicemenuinstaller/CMakeLists.txt
index deb08421b..46b159079 100644
--- a/src/settings/services/servicemenuinstaller/CMakeLists.txt
+++ b/src/settings/services/servicemenuinstaller/CMakeLists.txt
@@ -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})
diff --git a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
index 60621921a..89f2545f8 100644
--- a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
+++ b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
@@ -20,29 +20,42 @@
#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