diff --git a/libdiscover/backends/PackageKitBackend/CMakeLists.txt b/libdiscover/backends/PackageKitBackend/CMakeLists.txt index 7a162dec..f9d61885 100644 --- a/libdiscover/backends/PackageKitBackend/CMakeLists.txt +++ b/libdiscover/backends/PackageKitBackend/CMakeLists.txt @@ -1,37 +1,37 @@ find_package(KF5 REQUIRED Notifications) add_subdirectory(runservice) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-paths.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-paths.h) add_library(packagekit-backend MODULE PackageKitBackend.cpp PackageKitResource.cpp AppPackageKitResource.cpp PKTransaction.cpp PackageKitUpdater.cpp PackageKitMessages.cpp PackageKitSourcesBackend.cpp LocalFilePKResource.cpp TransactionSet.cpp ) target_link_libraries(packagekit-backend PRIVATE Discover::Common Qt5::Core PK::packagekitqt5 KF5::ConfigGui KF5::KIOCore KF5::Archive AppStreamQt) install(TARGETS packagekit-backend DESTINATION ${PLUGIN_INSTALL_DIR}/discover) #notifier add_library(DiscoverPackageKitNotifier MODULE PackageKitNotifier.cpp) target_link_libraries(DiscoverPackageKitNotifier PRIVATE PK::packagekitqt5 Discover::Notifiers KF5::I18n KF5::Notifications KF5::ConfigCore) set_target_properties(DiscoverPackageKitNotifier PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}/plasma-discover) install(TARGETS DiscoverPackageKitNotifier DESTINATION ${PLUGIN_INSTALL_DIR}/discover-notifier) install(FILES packagekit-backend-categories.xml DESTINATION ${DATA_INSTALL_DIR}/libdiscover/categories) add_subdirectory(categoryimages) -if(packagekitqt5_VERSION VERSION_GREATER 0.9.7) - target_compile_definitions(packagekit-backend PUBLIC -DPKQT_0_10) - target_compile_definitions(DiscoverPackageKitNotifier PUBLIC -DPKQT_0_10) +if(packagekitqt5_VERSION VERSION_GREATER 1.0.1) + target_compile_definitions(packagekit-backend PUBLIC -DPKQT_1_0) + target_compile_definitions(DiscoverPackageKitNotifier PUBLIC -DPKQT_1_0) endif() install( FILES org.kde.discover.packagekit.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR} ) diff --git a/libdiscover/backends/PackageKitBackend/PackageKitNotifier.cpp b/libdiscover/backends/PackageKitBackend/PackageKitNotifier.cpp index 3b30cb8e..a8ff468c 100644 --- a/libdiscover/backends/PackageKitBackend/PackageKitNotifier.cpp +++ b/libdiscover/backends/PackageKitBackend/PackageKitNotifier.cpp @@ -1,316 +1,316 @@ /*************************************************************************** * Copyright © 2013 Lukas Appelhans * * Copyright © 2015 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "PackageKitNotifier.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pk-offline-private.h" PackageKitNotifier::PackageKitNotifier(QObject* parent) : BackendNotifierModule(parent) , m_securityUpdates(0) , m_normalUpdates(0) { if (PackageKit::Daemon::global()->isRunning()) { recheckSystemUpdateNeeded(); } connect(PackageKit::Daemon::global(), &PackageKit::Daemon::networkStateChanged, this, &PackageKitNotifier::recheckSystemUpdateNeeded); connect(PackageKit::Daemon::global(), &PackageKit::Daemon::updatesChanged, this, &PackageKitNotifier::recheckSystemUpdateNeeded); connect(PackageKit::Daemon::global(), &PackageKit::Daemon::isRunningChanged, this, &PackageKitNotifier::recheckSystemUpdateNeeded); connect(PackageKit::Daemon::global(), &PackageKit::Daemon::transactionListChanged, this, &PackageKitNotifier::transactionListChanged); //Check if there's packages after 5' QTimer::singleShot(5 * 60 * 1000, this, &PackageKitNotifier::refreshDatabase); QTimer *regularCheck = new QTimer(this); regularCheck->setInterval(24 * 60 * 60 * 1000); //refresh at least once every day connect(regularCheck, &QTimer::timeout, this, &PackageKitNotifier::refreshDatabase); const QString aptconfig = QStandardPaths::findExecutable(QStringLiteral("apt-config")); if (!aptconfig.isEmpty()) { auto process = checkAptVariable(aptconfig, QLatin1String("Apt::Periodic::Update-Package-Lists"), [regularCheck](const QStringRef& value) { bool ok; int time = value.toInt(&ok); if (ok && time > 0) regularCheck->setInterval(time * 60 * 60 * 1000); else qWarning() << "couldn't understand value for timer:" << value; }); connect(process, static_cast(&QProcess::finished), regularCheck, static_cast(&QTimer::start)); } else regularCheck->start(); QTimer::singleShot(3000, this, &PackageKitNotifier::checkOfflineUpdates); m_recheckTimer = new QTimer(this); m_recheckTimer->setInterval(200); m_recheckTimer->setSingleShot(true); connect(m_recheckTimer, &QTimer::timeout, this, &PackageKitNotifier::recheckSystemUpdate); } PackageKitNotifier::~PackageKitNotifier() { } void PackageKitNotifier::checkOfflineUpdates() { if (!QFile::exists(QStringLiteral(PK_OFFLINE_RESULTS_FILENAME))) { return; } qDebug() << "found offline update results at " << PK_OFFLINE_RESULTS_FILENAME; KDesktopFile file(QStringLiteral(PK_OFFLINE_RESULTS_FILENAME)); KConfigGroup group(&file, PK_OFFLINE_RESULTS_GROUP); const bool success = group.readEntry("Success", false); const QString packagesJoined = group.readEntry("Packages"); const auto packages = packagesJoined.splitRef(QLatin1Char(',')); if (!success) { const QString errorDetails = group.readEntry("ErrorDetails"); KNotification *notification = new KNotification(QLatin1String("offlineupdate-failed"), KNotification::Persistent | KNotification::DefaultEvent); notification->setIconName(QStringLiteral("error")); notification->setText(i18n("Offline Updates")); notification->setText(i18n("Failed to update %1 packages\n%2", packages.count(), errorDetails)); notification->setActions(QStringList{QLatin1String("Open Discover")}); connect(notification, &KNotification::action1Activated, this, [] () { QProcess::startDetached(QStringLiteral("plasma-discover")); }); notification->sendEvent(); } else { KNotification *notification = new KNotification(QLatin1String("offlineupdate-successful")); notification->setIconName(QStringLiteral("system-software-update")); notification->setTitle(i18n("Offline Updates")); notification->setText(i18n("Successfully updated %1 packages", packages.count())); notification->setActions(QStringList{QLatin1String("Open Discover")}); connect(notification, &KNotification::action1Activated, this, [] () { QProcess::startDetached(QStringLiteral("plasma-discover")); }); notification->sendEvent(); } } void PackageKitNotifier::recheckSystemUpdateNeeded() { m_recheckTimer->start(); } void PackageKitNotifier::recheckSystemUpdate() { if (PackageKit::Daemon::global()->isRunning()) { PackageKit::Daemon::getUpdates(); } } void PackageKitNotifier::setupGetUpdatesTransaction(PackageKit::Transaction* trans) { qDebug() << "using..." << trans << trans->tid().path(); trans->setProperty("normalUpdates", 0); trans->setProperty("securityUpdates", 0); connect(trans, &PackageKit::Transaction::package, this, &PackageKitNotifier::package); connect(trans, &PackageKit::Transaction::finished, this, &PackageKitNotifier::finished); } void PackageKitNotifier::package(PackageKit::Transaction::Info info, const QString &/*packageID*/, const QString &/*summary*/) { PackageKit::Transaction * trans = qobject_cast(sender()); switch (info) { case PackageKit::Transaction::InfoBlocked: break; //skip, we ignore blocked updates case PackageKit::Transaction::InfoSecurity: trans->setProperty("securityUpdates", trans->property("securityUpdates").toInt()+1); break; default: trans->setProperty("normalUpdates", trans->property("normalUpdates").toInt()+1); break; } } void PackageKitNotifier::finished(PackageKit::Transaction::Exit /*exit*/, uint) { const PackageKit::Transaction * trans = qobject_cast(sender()); const uint normalUpdates = trans->property("normalUpdates").toInt(); const uint securityUpdates = trans->property("securityUpdates").toInt(); const bool changed = normalUpdates != m_normalUpdates || securityUpdates != m_securityUpdates; m_normalUpdates = normalUpdates; m_securityUpdates = securityUpdates; if (changed) { Q_EMIT foundUpdates(); } } uint PackageKitNotifier::securityUpdatesCount() { return m_securityUpdates; } uint PackageKitNotifier::updatesCount() { return m_normalUpdates; } void PackageKitNotifier::onDistroUpgrade(PackageKit::Transaction::DistroUpgrade type, const QString& name, const QString& description) { -#ifdef PKQT_0_10 +#ifdef PKQT_1_0 KNotification *notification = new KNotification(QLatin1String("distupgrade-notification"), KNotification::Persistent | KNotification::DefaultEvent); notification->setIconName(QStringLiteral("system-software-update")); notification->setActions(QStringList{QLatin1String("Upgrade")}); notification->setTitle(i18n("Upgrade available")); switch(type) { case PackageKit::Transaction::DistroUpgradeUnknown: case PackageKit::Transaction::DistroUpgradeUnstable: notification->setText(i18n("New unstable version: %1", description)); break; case PackageKit::Transaction::DistroUpgradeStable: notification->setText(i18n("New version: %1", description)); break; } connect(notification, &KNotification::action1Activated, this, [name] () { PackageKit::Daemon::upgradeSystem(name, PackageKit::Transaction::UpgradeKindDefault); }); notification->sendEvent(); #endif } void PackageKitNotifier::refreshDatabase() { if (!m_refresher) { m_refresher = PackageKit::Daemon::refreshCache(false); connect(m_refresher.data(), &PackageKit::Transaction::finished, this, [this]() { recheckSystemUpdateNeeded(); }); } -#ifdef PKQT_0_10 +#ifdef PKQT_1_0 if (!m_distUpgrades && (PackageKit::Daemon::roles() & PackageKit::Transaction::RoleUpgradeSystem)) { m_distUpgrades = PackageKit::Daemon::getDistroUpgrades(); connect(m_distUpgrades, &PackageKit::Transaction::distroUpgrade, this, &PackageKitNotifier::onDistroUpgrade); } #endif } QProcess* PackageKitNotifier::checkAptVariable(const QString &aptconfig, const QLatin1String& varname, std::function func) { QProcess* process = new QProcess; process->start(aptconfig, {QStringLiteral("dump")}); connect(process, static_cast(&QProcess::finished), this, [func, process, varname](int code) { if (code != 0) return; QRegularExpression rx(QLatin1Char('^') + varname + QStringLiteral(" \"(.*?)\"$")); QTextStream stream(process); QString line; while (stream.readLineInto(&line)) { const auto match = rx.match(line); if (match.hasMatch()) { func(match.capturedRef(1)); } } }); connect(process, static_cast(&QProcess::finished), process, &QObject::deleteLater); return process; } void PackageKitNotifier::transactionListChanged(const QStringList& tids) { for (const auto &tid: tids) { if (m_transactions.contains(tid)) continue; auto t = new PackageKit::Transaction(QDBusObjectPath(tid)); connect(t, &PackageKit::Transaction::roleChanged, this, [this, t]() { if (t->role() == PackageKit::Transaction::RoleGetUpdates) { setupGetUpdatesTransaction(t); } }); connect(t, &PackageKit::Transaction::requireRestart, this, &PackageKitNotifier::onRequireRestart); connect(t, &PackageKit::Transaction::finished, this, [this, t](){ auto restart = t->property("requireRestart"); if (!restart.isNull()) requireRestartNotification(PackageKit::Transaction::Restart(restart.toInt())); m_transactions.remove(t->tid().path()); t->deleteLater(); }); m_transactions.insert(tid, t); } } void PackageKitNotifier::onRequireRestart(PackageKit::Transaction::Restart type, const QString &packageID) { PackageKit::Transaction* t = qobject_cast(sender()); t->setProperty("requireRestart", qMax(t->property("requireRestart").toInt(), type)); qDebug() << "RESTART" << type << "is required for package" << packageID; } void PackageKitNotifier::requireRestartNotification(PackageKit::Transaction::Restart type) { if (type < PackageKit::Transaction::RestartSession) { return; } KNotification *notification = new KNotification(QLatin1String("notification"), KNotification::Persistent | KNotification::DefaultEvent); notification->setIconName(QStringLiteral("system-software-update")); if (type == PackageKit::Transaction::RestartSystem || type == PackageKit::Transaction::RestartSecuritySystem) { notification->setActions(QStringList{QLatin1String("Restart")}); notification->setTitle(i18n("Restart is required")); notification->setText(i18n("The system needs to be restarted for the updates to take effect.")); } else { notification->setActions(QStringList{QLatin1String("Logout")}); notification->setTitle(i18n("Session restart is required")); notification->setText(i18n("You will need to log out and back in for the update to take effect.")); } connect(notification, &KNotification::action1Activated, this, [type] () { QDBusInterface interface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QStringLiteral("org.kde.KSMServerInterface"), QDBusConnection::sessionBus()); if (type == PackageKit::Transaction::RestartSystem) { interface.asyncCall(QStringLiteral("logout"), 0, 1, 2); // Options: do not ask again | reboot | force } else { interface.asyncCall(QStringLiteral("logout"), 0, 0, 2); // Options: do not ask again | logout | force } }); notification->sendEvent(); } diff --git a/libdiscover/backends/PackageKitBackend/PackageKitUpdater.cpp b/libdiscover/backends/PackageKitBackend/PackageKitUpdater.cpp index a557267e..df360e15 100644 --- a/libdiscover/backends/PackageKitBackend/PackageKitUpdater.cpp +++ b/libdiscover/backends/PackageKitBackend/PackageKitUpdater.cpp @@ -1,389 +1,389 @@ /*************************************************************************** * Copyright © 2013 Lukas Appelhans * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "PackageKitUpdater.h" #include "PackageKitMessages.h" #include -#ifdef PKQT_0_10 +#ifdef PKQT_1_0 #include #endif #include #include #include #include static int percentageWithStatus(PackageKit::Transaction::Status status, uint percentage) { if (status != PackageKit::Transaction::StatusUnknown) { static const QMap statuses = { { PackageKit::Transaction::Status::StatusDownload, 0 }, { PackageKit::Transaction::Status::StatusInstall, 1}, { PackageKit::Transaction::Status::StatusUpdate, 1} }; const auto idx = statuses.value(status, -1); if (idx < 0) { qDebug() << "Status not present" << status << "among" << statuses .keys() << percentage; return -1; } percentage = (idx * 100 + percentage) / 2 /*the maximum in statuses*/; } qDebug() << "reporing progress with status:" << status << percentage; return percentage; } PackageKitUpdater::PackageKitUpdater(PackageKitBackend * parent) : AbstractBackendUpdater(parent), m_transaction(nullptr), m_backend(parent), m_isCancelable(false), m_isProgressing(false), m_percentage(0), m_lastUpdate() { fetchLastUpdateTime(); } PackageKitUpdater::~PackageKitUpdater() { } void PackageKitUpdater::prepare() { Q_ASSERT(!m_transaction); m_toUpgrade = m_backend->upgradeablePackages(); m_allUpgradeable = m_toUpgrade; } void PackageKitUpdater::setupTransaction(PackageKit::Transaction::TransactionFlags flags) { m_packagesRemoved.clear(); m_transaction = PackageKit::Daemon::updatePackages(involvedPackages(m_toUpgrade).toList(), flags); m_isCancelable = m_transaction->allowCancel(); connect(m_transaction.data(), &PackageKit::Transaction::finished, this, &PackageKitUpdater::finished); connect(m_transaction.data(), &PackageKit::Transaction::package, this, &PackageKitUpdater::packageResolved); connect(m_transaction.data(), &PackageKit::Transaction::errorCode, this, &PackageKitUpdater::errorFound); connect(m_transaction.data(), &PackageKit::Transaction::mediaChangeRequired, this, &PackageKitUpdater::mediaChange); connect(m_transaction.data(), &PackageKit::Transaction::requireRestart, this, &PackageKitUpdater::requireRestart); connect(m_transaction.data(), &PackageKit::Transaction::eulaRequired, this, &PackageKitUpdater::eulaRequired); connect(m_transaction.data(), &PackageKit::Transaction::repoSignatureRequired, this, &PackageKitUpdater::repoSignatureRequired); connect(m_transaction.data(), &PackageKit::Transaction::allowCancelChanged, this, &PackageKitUpdater::cancellableChanged); connect(m_transaction.data(), &PackageKit::Transaction::percentageChanged, this, &PackageKitUpdater::percentageChanged); connect(m_transaction.data(), &PackageKit::Transaction::itemProgress, this, &PackageKitUpdater::itemProgress); } QSet PackageKitUpdater::packagesForPackageId(const QSet& pkgids) const { QSet packages; packages.reserve(pkgids.size()); foreach(const QString& pkgid, pkgids) { packages += PackageKit::Daemon::packageName(pkgid); } QSet ret; foreach (AbstractResource * res, m_allUpgradeable) { PackageKitResource* pres = qobject_cast(res); if (packages.contains(pres->allPackageNames().toSet())) { ret.insert(res); } } return ret; } QSet PackageKitUpdater::involvedPackages(const QSet& packages) const { QSet packageIds; packageIds.reserve(packages.size()); foreach (AbstractResource * res, packages) { PackageKitResource * app = qobject_cast(res); QString pkgid = m_backend->upgradeablePackageId(app); packageIds.insert(pkgid); } return packageIds; } void PackageKitUpdater::processProceedFunction() { auto t = m_proceedFunctions.takeFirst()(); connect(t, &PackageKit::Transaction::finished, this, [this](PackageKit::Transaction::Exit status) { if (status != PackageKit::Transaction::Exit::ExitSuccess) { qWarning() << "transaction failed" << sender() << status; cancel(); return; } if (!m_proceedFunctions.isEmpty()) { processProceedFunction(); } else { start(); } }); } void PackageKitUpdater::proceed() { if (!m_proceedFunctions.isEmpty()) processProceedFunction(); -#ifdef PKQT_0_10 +#ifdef PKQT_1_0 else if (qEnvironmentVariableIsSet("PK_OFFLINE_UPDATE")) setupTransaction(PackageKit::Transaction::TransactionFlagOnlyTrusted | PackageKit::Transaction::TransactionFlagOnlyDownload); #endif else setupTransaction(PackageKit::Transaction::TransactionFlagOnlyTrusted); } void PackageKitUpdater::start() { Q_ASSERT(!isProgressing()); setupTransaction(PackageKit::Transaction::TransactionFlagSimulate); setProgressing(true); } void PackageKitUpdater::finished(PackageKit::Transaction::Exit exit, uint /*time*/) { // qDebug() << "update finished!" << exit << time; if (!m_proceedFunctions.isEmpty()) return; const bool cancel = exit == PackageKit::Transaction::ExitCancelled; const bool simulate = m_transaction->transactionFlags() & PackageKit::Transaction::TransactionFlagSimulate; disconnect(m_transaction, nullptr, this, nullptr); m_transaction = nullptr; if (!cancel && simulate) { if (!m_packagesRemoved.isEmpty()) Q_EMIT proceedRequest(i18n("Packages to remove"), i18n("The following packages will be removed by the update:\n
  • %1
", PackageKitResource::joinPackages(m_packagesRemoved, QStringLiteral("
  • ")))); else { proceed(); } return; } setProgressing(false); m_backend->refreshDatabase(); fetchLastUpdateTime(); if (qEnvironmentVariableIsSet("PK_OFFLINE_UPDATE")) -#ifdef PKQT_0_10 +#ifdef PKQT_1_0 PackageKit::Daemon::global()->offline()->trigger(PackageKit::Offline::ActionReboot); #else qWarning() << "PK_OFFLINE_UPDATE is set but discover was built against an old version of PackageKitQt that didn't support offline updates"; #endif } void PackageKitUpdater::cancellableChanged() { if (m_isCancelable != m_transaction->allowCancel()) { m_isCancelable = m_transaction->allowCancel(); emit cancelableChanged(m_isCancelable); } } void PackageKitUpdater::percentageChanged() { const auto actualPercentage = percentageWithStatus(m_transaction->status(), m_transaction->percentage()); if (actualPercentage >= 0 && m_percentage != actualPercentage) { m_percentage = actualPercentage; emit progressChanged(m_percentage); } } bool PackageKitUpdater::hasUpdates() const { return m_backend->updatesCount() > 0; } qreal PackageKitUpdater::progress() const { return m_percentage; } void PackageKitUpdater::removeResources(const QList& apps) { QSet pkgs = involvedPackages(apps.toSet()); m_toUpgrade.subtract(packagesForPackageId(pkgs)); } void PackageKitUpdater::addResources(const QList& apps) { QSet pkgs = involvedPackages(apps.toSet()); m_toUpgrade.unite(packagesForPackageId(pkgs)); } QList PackageKitUpdater::toUpdate() const { return m_toUpgrade.toList(); } bool PackageKitUpdater::isMarked(AbstractResource* res) const { return m_toUpgrade.contains(res); } QDateTime PackageKitUpdater::lastUpdate() const { return m_lastUpdate; } bool PackageKitUpdater::isCancelable() const { return m_isCancelable; } bool PackageKitUpdater::isProgressing() const { return m_isProgressing; } void PackageKitUpdater::cancel() { if (m_transaction) m_transaction->cancel(); else setProgressing(false); } void PackageKitUpdater::errorFound(PackageKit::Transaction::Error err, const QString& error) { if (err == PackageKit::Transaction::ErrorNoLicenseAgreement) return; Q_EMIT passiveMessage(QStringLiteral("%1\n%2").arg(PackageKitMessages::errorMessage(err), error)); qWarning() << "Error happened" << err << error; } void PackageKitUpdater::mediaChange(PackageKit::Transaction::MediaType media, const QString& type, const QString& text) { Q_UNUSED(media) Q_EMIT passiveMessage(i18n("Media Change of type '%1' is requested.\n%2", type, text)); } void PackageKitUpdater::requireRestart(PackageKit::Transaction::Restart restart, const QString& pkgid) { Q_EMIT passiveMessage(PackageKitMessages::restartMessage(restart, pkgid)); } void PackageKitUpdater::eulaRequired(const QString& eulaID, const QString& packageID, const QString& vendor, const QString& licenseAgreement) { m_proceedFunctions << [eulaID](){ return PackageKit::Daemon::acceptEula(eulaID); }; Q_EMIT proceedRequest(i18n("Accept EULA"), i18n("The package %1 and its vendor %2 require that you accept their license:\n %3", PackageKit::Daemon::packageName(packageID), vendor, licenseAgreement)); } void PackageKitUpdater::setProgressing(bool progressing) { if (m_isProgressing != progressing) { m_isProgressing = progressing; emit progressingChanged(m_isProgressing); } } void PackageKitUpdater::fetchLastUpdateTime() { QDBusPendingReply transaction = PackageKit::Daemon::global()->getTimeSinceAction(PackageKit::Transaction::RoleGetUpdates); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(transaction, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &PackageKitUpdater::lastUpdateTimeReceived); } void PackageKitUpdater::lastUpdateTimeReceived(QDBusPendingCallWatcher* w) { QDBusPendingReply reply = w->reply(); if (reply.isError()) { qWarning() << "Error when fetching the last update time" << reply.error(); } else { m_lastUpdate = QDateTime::currentDateTime().addSecs(-int(reply.value())); } w->deleteLater(); } void PackageKitUpdater::itemProgress(const QString& itemID, PackageKit::Transaction::Status status, uint percentage) { auto res = packagesForPackageId({itemID}); const auto actualPercentage = percentageWithStatus(status, percentage); if (actualPercentage<0) return; foreach(auto r, res) { Q_EMIT resourceProgressed(r, actualPercentage); } } void PackageKitUpdater::fetchChangelog() const { QStringList pkgids; foreach(AbstractResource* res, m_allUpgradeable) { pkgids += static_cast(res)->availablePackageId(); } Q_ASSERT(!pkgids.isEmpty()); PackageKit::Transaction* t = PackageKit::Daemon::getUpdatesDetails(pkgids); connect(t, &PackageKit::Transaction::updateDetail, this, &PackageKitUpdater::updateDetail); connect(t, &PackageKit::Transaction::errorCode, this, &PackageKitUpdater::errorFound); } void PackageKitUpdater::updateDetail(const QString& packageID, const QStringList& updates, const QStringList& obsoletes, const QStringList& vendorUrls, const QStringList& bugzillaUrls, const QStringList& cveUrls, PackageKit::Transaction::Restart restart, const QString& updateText, const QString& changelog, PackageKit::Transaction::UpdateState state, const QDateTime& issued, const QDateTime& updated) { auto res = packagesForPackageId({packageID}); foreach(auto r, res) { static_cast(r)->updateDetail(packageID, updates, obsoletes, vendorUrls, bugzillaUrls, cveUrls, restart, updateText, changelog, state, issued, updated); } } void PackageKitUpdater::packageResolved(PackageKit::Transaction::Info info, const QString& packageId) { if (info == PackageKit::Transaction::InfoRemoving) m_packagesRemoved << packageId; } void PackageKitUpdater::repoSignatureRequired(const QString& packageID, const QString& repoName, const QString& keyUrl, const QString& keyUserid, const QString& keyId, const QString& keyFingerprint, const QString& keyTimestamp, PackageKit::Transaction::SigType type) { Q_EMIT proceedRequest(i18n("Missing signature for %1 in %2", packageID, repoName), i18n("Do you trust the following key?\n\nUrl: %1\nUser: %2\nKey: %3\nFingerprint: %4\nTimestamp: %4\n", keyUrl, keyUserid, keyFingerprint, keyTimestamp)); m_proceedFunctions << [type, keyId, packageID](){ return PackageKit::Daemon::installSignature(type, keyId, packageID); }; } double PackageKitUpdater::updateSize() const { double ret = 0.; QSet donePkgs; for (AbstractResource * res : m_toUpgrade) { PackageKitResource * app = qobject_cast(res); QString pkgid = m_backend->upgradeablePackageId(app); if (!donePkgs.contains(pkgid)) { donePkgs.insert(pkgid); ret += app->size(); } } return ret; }