diff options
| author | Felix Ernst <[email protected]> | 2024-07-01 12:03:22 +0000 |
|---|---|---|
| committer | Felix Ernst <[email protected]> | 2024-07-01 12:03:22 +0000 |
| commit | 92b178b7404b002778d8288353f65e27ee5de5dd (patch) | |
| tree | ae38ce183e67098f7d0beb43b7de9dc9ca1e0c52 /src/dolphinpackageinstaller.cpp | |
| parent | 887f3a6e83832d645ddf55d38e3a098b64e12dd5 (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.cpp | 115 |
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 |
