┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/dolphinpackageinstaller.cpp
diff options
context:
space:
mode:
authorFelix Ernst <[email protected]>2024-07-01 12:03:22 +0000
committerFelix Ernst <[email protected]>2024-07-01 12:03:22 +0000
commit92b178b7404b002778d8288353f65e27ee5de5dd (patch)
treeae38ce183e67098f7d0beb43b7de9dc9ca1e0c52 /src/dolphinpackageinstaller.cpp
parent887f3a6e83832d645ddf55d38e3a098b64e12dd5 (diff)
Guide users to using kio-admin instead of sudo
This commit adds a guided setup that leads users from a situation in which they try to "sudo dolphin" towards them successfully setting up and using kio-admin. 1. When users enter "sudo dolphin", they are told to start Dolphin by typing "dolphin --sudo" or "dolphin --admin" instead. 2. When Dolphin is started with "--sudo" or "--admin" it checks whether an "admin" protocol is installed. If not, a guided setup leads users towards installing it. 3. After that, Dolphin starts with an installed "admin" protocoll like kio-admin. Now a non-modal information dialog appears that explains how to activate and use kio-admin.
Diffstat (limited to 'src/dolphinpackageinstaller.cpp')
-rw-r--r--src/dolphinpackageinstaller.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/dolphinpackageinstaller.cpp b/src/dolphinpackageinstaller.cpp
new file mode 100644
index 000000000..b70159663
--- /dev/null
+++ b/src/dolphinpackageinstaller.cpp
@@ -0,0 +1,115 @@
+/*
+ This file is part of the KDE project
+ SPDX-FileCopyrightText: 2024 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "dolphinpackageinstaller.h"
+
+#include <KLocalizedString>
+
+#if HAVE_PACKAGEKIT
+#include <PackageKit/Daemon>
+#else
+#include <QDesktopServices>
+#endif
+
+#include <QTimer>
+#include <QtAssert>
+
+DolphinPackageInstaller::DolphinPackageInstaller(const QString &packageName,
+ const QUrl &fallBackInstallationPageUrl,
+ std::function<bool()> isPackageInstalledCheck,
+ QObject *parent)
+ : KJob(parent)
+ , m_packageName{packageName}
+ , m_fallBackInstallationPageUrl{fallBackInstallationPageUrl}
+ , m_isPackageInstalledCheck{isPackageInstalledCheck}
+{
+}
+
+void DolphinPackageInstaller::start()
+{
+ if (m_isPackageInstalledCheck()) {
+ emitResult();
+ return;
+ }
+
+#if HAVE_PACKAGEKIT
+ PackageKit::Daemon::setHints(PackageKit::Daemon::hints() + QStringList{QStringLiteral("interactive=true")});
+ const PackageKit::Transaction *resolveTransaction = PackageKit::Daemon::resolve(m_packageName);
+
+ connect(resolveTransaction, &PackageKit::Transaction::errorCode, this, &DolphinPackageInstaller::slotInstallationFailed);
+ connect(resolveTransaction, &PackageKit::Transaction::finished, this, [this]() { // Will be disconnected if we find a package.
+ slotInstallationFailed(PackageKit::Transaction::ErrorPackageNotFound,
+ i18nc("@info:shell about system packages", "Could not find package %1.", m_packageName));
+ });
+ connect(resolveTransaction,
+ &PackageKit::Transaction::package,
+ this,
+ [this, resolveTransaction](PackageKit::Transaction::Info /* info */, const QString &packageId) {
+ disconnect(resolveTransaction, nullptr, this, nullptr); // We only care about the first package.
+ install(packageId);
+ });
+#else
+ QDesktopServices::openUrl(m_fallBackInstallationPageUrl);
+ auto waitForSuccess = new QTimer(this);
+ connect(waitForSuccess, &QTimer::timeout, this, [this]() {
+ if (m_isPackageInstalledCheck()) {
+ emitResult();
+ }
+ });
+ waitForSuccess->start(3000);
+#endif
+}
+
+#if HAVE_PACKAGEKIT
+void DolphinPackageInstaller::install(const QString &packageId)
+{
+ const PackageKit::Transaction *installTransaction = PackageKit::Daemon::installPackage(packageId);
+ connectTransactionToJobProgress(*installTransaction);
+ connect(installTransaction,
+ &PackageKit::Transaction::errorCode,
+ this,
+ [installTransaction, this](PackageKit::Transaction::Error error, const QString &details) {
+ disconnect(installTransaction, nullptr, this, nullptr); // We only want to emit a result once.
+ slotInstallationFailed(error, details);
+ });
+ connect(installTransaction,
+ &PackageKit::Transaction::finished,
+ this,
+ [installTransaction, this](const PackageKit::Transaction::Exit status, uint /* runtime */) {
+ disconnect(installTransaction, nullptr, this, nullptr); // We only want to emit a result once.
+ if (status == PackageKit::Transaction::ExitSuccess) {
+ emitResult();
+ } else {
+ slotInstallationFailed(PackageKit::Transaction::ErrorUnknown,
+ i18nc("@info %1 is error code",
+ "Installation exited without reporting success. (%1)",
+ QMetaEnum::fromType<PackageKit::Transaction::Exit>().valueToKey(status)));
+ }
+ });
+}
+
+void DolphinPackageInstaller::connectTransactionToJobProgress(const PackageKit::Transaction &transaction)
+{
+ connect(&transaction, &PackageKit::Transaction::speedChanged, this, [this, &transaction]() {
+ emitSpeed(transaction.speed());
+ });
+ connect(&transaction, &PackageKit::Transaction::percentageChanged, this, [this, &transaction]() {
+ setPercent(transaction.percentage());
+ });
+}
+
+void DolphinPackageInstaller::slotInstallationFailed(PackageKit::Transaction::Error error, const QString &details)
+{
+ setErrorString(xi18nc("@info:shell %1 is package name, %2 is error message, %3 is error e.g. 'ErrorNoNetwork'",
+ "Installing <application>%1</application> failed: %2 (%3)<nl/>Please try installing <application>%1</application> manually instead.",
+ m_packageName,
+ details,
+ QMetaEnum::fromType<PackageKit::Transaction::Error>().valueToKey(error)));
+ setError(error);
+ emitResult();
+}
+#endif