From 92b178b7404b002778d8288353f65e27ee5de5dd Mon Sep 17 00:00:00 2001 From: Felix Ernst Date: Mon, 1 Jul 2024 12:03:22 +0000 Subject: 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. --- src/dolphinpackageinstaller.cpp | 115 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/dolphinpackageinstaller.cpp (limited to 'src/dolphinpackageinstaller.cpp') 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 + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ + +#include "dolphinpackageinstaller.h" + +#include + +#if HAVE_PACKAGEKIT +#include +#else +#include +#endif + +#include +#include + +DolphinPackageInstaller::DolphinPackageInstaller(const QString &packageName, + const QUrl &fallBackInstallationPageUrl, + std::function 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().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 %1 failed: %2 (%3)Please try installing %1 manually instead.", + m_packageName, + details, + QMetaEnum::fromType().valueToKey(error))); + setError(error); + emitResult(); +} +#endif -- cgit v1.3