/* 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