diff --git a/libdiscover/resources/discoverabstractnotifier.notifyrc b/libdiscover/resources/discoverabstractnotifier.notifyrc index da44a655..940dc437 100644 --- a/libdiscover/resources/discoverabstractnotifier.notifyrc +++ b/libdiscover/resources/discoverabstractnotifier.notifyrc @@ -1,133 +1,134 @@ [Global] IconName=plasmadiscover DesktopEntry=org.kde.discover Comment=Discover Comment[ar]=استكشف Comment[ca]=Discover Comment[ca@valencia]=Discover Comment[da]=Discover Comment[de]=Discover Comment[el]=Discover Comment[en_GB]=Discover Comment[es]=Discover Comment[et]=Avastusretk Comment[eu]=Aurkitu Comment[fi]=Discover Comment[fr]=Discover Comment[gl]=Descubrir Comment[hu]=Discover Comment[ia]=Discoperi Comment[id]=Discover Comment[it]=Discover Comment[ko]=소프트웨어 둘러보기 Comment[lt]=Discover Comment[ml]=കണ്ടെത്തുക Comment[nl]=Ontdekken Comment[nn]=Discover Comment[pa]=ਖੋਜ Comment[pl]=Odkryj Comment[pt]=Discover Comment[pt_BR]=Discover Comment[ru]=Центр программ Discover Comment[sk]=Objaviť Comment[sl]=Programsko središče Comment[sr]=Oткривач Comment[sr@ijekavian]=Oткривач Comment[sr@ijekavianlatin]=Otkrivač Comment[sr@latin]=Otkrivač Comment[sv]=Upptäck Comment[tr]=Keşfet Comment[uk]=Discover Comment[x-test]=xxDiscoverxx Comment[zh_CN]=Discover Comment[zh_TW]=探詢 [Event/Update] Name=Updates Are Available Name[ar]=تتوفّر تحديثات Name[ca]=Hi ha actualitzacions disponibles Name[ca@valencia]=Hi ha actualitzacions disponibles Name[cs]=Jsou dostupné aktualizace Name[da]=Opdateringer tilgængelige Name[de]=Es sind Aktualisierungen verfügbar Name[el]=Υπάρχουν διαθέσιμες ενημερώσεις Name[en_GB]=Updates Are Available Name[es]=Existen actualizaciones disponibles Name[et]=Saadaval on uuendused Name[eu]=Eguneraketak erabilgarri daude Name[fi]=Päivityksiä on saatavilla Name[fr]=Des mises à jour sont disponibles Name[gl]=Hai actualizacións dispoñíbeis Name[he]=יש עדכונים זמינים Name[hu]=Frissítések érhetőek el Name[ia]=Actualisationes es disponibile Name[id]=Update Telah Tersedia Name[it]=Sono disponibili aggiornamenti Name[ko]=업데이트 사용 가능 Name[lt]=Yra prieinami atnaujinimai Name[ml]=അപ്ഡേറ്റുകൾ ലഭ്യമാണ് Name[nb]=Oppgraderinger er tilgjengelige Name[nl]=Bijwerken is beschikbaar Name[nn]=Oppdateringar er tilgjengelege Name[pa]=ਅੱਪਡੇਟ ਮੌਜੂਦ ਹਨ Name[pl]=Uaktualnienia są dostępne Name[pt]=Estão Disponíveis Actualizações Name[pt_BR]=Atualizações estão disponíveis Name[ru]=Доступны обновления Name[sk]=Sú dostupné aktualizácie Name[sl]=Na voljo so posodobitve Name[sr]=Доступне допуне Name[sr@ijekavian]=Доступне допуне Name[sr@ijekavianlatin]=Dostupne dopune Name[sr@latin]=Dostupne dopune Name[sv]=Uppdateringar är tillgängliga Name[tr]=Güncellemeler Mevcut Name[uk]=Доступні оновлення Name[x-test]=xxUpdates Are Availablexx Name[zh_CN]=有可用更新 Name[zh_TW]=有可用的更新 Comment=Updates Available Comment[ar]=تتوفّر تحديثات Comment[ca]=Actualitzacions disponibles Comment[ca@valencia]=Actualitzacions disponibles Comment[cs]=Jsou dostupné aktualizace Comment[da]=Opdateringer tilgængelige Comment[de]=Aktualisierungen verfügbar Comment[el]=Διαθέσιμες ενημερώσεις Comment[en_GB]=Updates Available Comment[es]=Actualizaciones disponibles Comment[et]=Saadaval on uuendused Comment[eu]=Eguneraketak erabilgarri Comment[fi]=Päivityksiä saatavilla Comment[fr]=Mises à jour disponibles Comment[gl]=Actualizacións dispoñíbeis Comment[he]=עדכונים זמינים Comment[hu]=Frissítések érhetőek el Comment[ia]=Actualisationes disponibile Comment[id]=Update Tersedia Comment[it]=Aggiornamenti disponibili Comment[ko]=업데이트 사용 가능 Comment[lt]=Prieinami atnaujinimai Comment[ml]=അപ്ഡേറ്റുകൾ ലഭ്യമാണ് Comment[nb]=Oppgraderinger tilgjengelige Comment[nl]=Bijwerken is beschikbaar Comment[nn]=Oppdateringar tilgjengelege Comment[pa]=ਅੱਪਡੇਟ ਮੌਜੂਦ Comment[pl]=Dostępne uaktualnienia Comment[pt]=Actualizações Disponíveis Comment[pt_BR]=Atualizações disponíveis Comment[ru]=Доступны обновления Comment[sk]=Dostupné aktualizácie Comment[sl]=Na voljo so posodobitve Comment[sr]=Доступне су нове допуне Comment[sr@ijekavian]=Доступне су нове допуне Comment[sr@ijekavianlatin]=Dostupne su nove dopune Comment[sr@latin]=Dostupne su nove dopune Comment[sv]=Uppdateringar tillgängliga Comment[tr]=Güncellemeler Mevcut Comment[uk]=Доступні оновлення Comment[x-test]=xxUpdates Availablexx Comment[zh_CN]=可用更新 Comment[zh_TW]=有可用的更新 +Urgency=Low Action=Popup diff --git a/notifier/DiscoverNotifier.cpp b/notifier/DiscoverNotifier.cpp index 1e64f1e4..5ec0a324 100644 --- a/notifier/DiscoverNotifier.cpp +++ b/notifier/DiscoverNotifier.cpp @@ -1,218 +1,220 @@ /*************************************************************************** * Copyright © 2014 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 "DiscoverNotifier.h" #include "BackendNotifierFactory.h" #include #include #include #include #include #include #include #include #include #include #include "../libdiscover/utils.h" DiscoverNotifier::DiscoverNotifier(QObject * parent) : QObject(parent) { configurationChanged(); m_backends = BackendNotifierFactory().allBackends(); foreach(BackendNotifierModule* module, m_backends) { connect(module, &BackendNotifierModule::foundUpdates, this, &DiscoverNotifier::updateStatusNotifier); connect(module, &BackendNotifierModule::needsRebootChanged, this, [this]() { if (!m_needsReboot) { m_needsReboot = true; showRebootNotification(); Q_EMIT stateChanged(); Q_EMIT needsRebootChanged(true); } }); connect(module, &BackendNotifierModule::foundUpgradeAction, this, &DiscoverNotifier::foundUpgradeAction); } connect(&m_timer, &QTimer::timeout, this, &DiscoverNotifier::showUpdatesNotification); m_timer.setSingleShot(true); m_timer.setInterval(1000); updateStatusNotifier(); //Only fetch updates after the system is comfortably booted QTimer::singleShot(10000, this, &DiscoverNotifier::recheckSystemUpdateNeeded); } DiscoverNotifier::~DiscoverNotifier() = default; void DiscoverNotifier::configurationChanged() { KConfig notifierConfig(QStringLiteral("plasma-discover-notifierrc"), KConfig::NoGlobals); KConfigGroup notifyTypeGroup(¬ifierConfig, "NotificationType"); m_verbose = notifyTypeGroup.readEntry("Verbose", false); } void DiscoverNotifier::showDiscover() { KRun::runCommand(QStringLiteral("plasma-discover"), nullptr); + if (m_updatesAvailableNotification) { m_updatesAvailableNotification->close(); } } void DiscoverNotifier::showDiscoverUpdates() { KRun::runCommand(QStringLiteral("plasma-discover --mode update"), nullptr); + if (m_updatesAvailableNotification) { m_updatesAvailableNotification->close(); } } void DiscoverNotifier::showUpdatesNotification() { if (state() != NormalUpdates && state() != SecurityUpdates) { //it's not very helpful to notify that everything is in order return; } - auto e = KNotification::event(QStringLiteral("Update"), message(), {}, iconName(), nullptr, KNotification::CloseOnTimeout, QStringLiteral("discoverabstractnotifier")); + m_updatesAvailableNotification = KNotification::event(QStringLiteral("Update"), message(), {}, iconName(), nullptr, KNotification::Persistent, QStringLiteral("discoverabstractnotifier")); const QString name = i18n("Update"); - e->setDefaultAction(name); - e->setActions({name}); - connect(e, QOverload::of(&KNotification::activated), this, &DiscoverNotifier::showDiscoverUpdates); + m_updatesAvailableNotification->setDefaultAction(name); + m_updatesAvailableNotification->setActions({name}); + connect(m_updatesAvailableNotification, QOverload::of(&KNotification::activated), this, &DiscoverNotifier::showDiscoverUpdates); } void DiscoverNotifier::updateStatusNotifier() { const bool hasSecurityUpdates = kContains(m_backends, [](BackendNotifierModule* module) { return module->hasSecurityUpdates(); }); const bool hasUpdates = hasSecurityUpdates || kContains(m_backends, [](BackendNotifierModule* module) { return module->hasUpdates(); }); if (m_hasUpdates == hasUpdates && m_hasSecurityUpdates == hasSecurityUpdates ) return; m_hasSecurityUpdates = hasSecurityUpdates; m_hasUpdates = hasUpdates; if (state() != NoUpdates) { m_timer.start(); } emit stateChanged(); } DiscoverNotifier::State DiscoverNotifier::state() const { if (m_needsReboot) return RebootRequired; else if (m_manager && !m_manager->isOnline()) return Offline; else if (m_hasSecurityUpdates) return SecurityUpdates; else if (m_hasUpdates) return NormalUpdates; else return NoUpdates; } QString DiscoverNotifier::iconName() const { switch(state()) { case SecurityUpdates: return QStringLiteral("update-high"); case NormalUpdates: return QStringLiteral("update-low"); case NoUpdates: return QStringLiteral("update-none"); case RebootRequired: return QStringLiteral("system-reboot"); case Offline: return QStringLiteral("offline"); } return QString(); } QString DiscoverNotifier::message() const { switch(state()) { case SecurityUpdates: return i18n("Security updates available"); case NormalUpdates: return i18n("Updates available"); case NoUpdates: return i18n("System up to date"); case RebootRequired: return i18n("Computer needs to restart"); case Offline: return i18n("Offline"); } return QString(); } void DiscoverNotifier::recheckSystemUpdateNeeded() { if (!m_manager) { m_manager = new QNetworkConfigurationManager(this); connect(m_manager, &QNetworkConfigurationManager::onlineStateChanged, this, &DiscoverNotifier::stateChanged); if (!m_manager->isOnline()) { emit stateChanged(); } } foreach(BackendNotifierModule* module, m_backends) module->recheckSystemUpdateNeeded(); } QStringList DiscoverNotifier::loadedModules() const { QStringList ret; for(BackendNotifierModule* module : m_backends) ret += QString::fromLatin1(module->metaObject()->className()); return ret; } void DiscoverNotifier::showRebootNotification() { KNotification *notification = new KNotification(QStringLiteral("notification"), KNotification::Persistent | KNotification::DefaultEvent); notification->setIconName(QStringLiteral("system-software-update")); 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.")); connect(notification, &KNotification::action1Activated, this, &DiscoverNotifier::reboot); notification->sendEvent(); } void DiscoverNotifier::reboot() { QDBusInterface interface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QStringLiteral("org.kde.KSMServerInterface"), QDBusConnection::sessionBus()); interface.asyncCall(QStringLiteral("logout"), 0, 1, 2); // Options: do not ask again | reboot | force } void DiscoverNotifier::foundUpgradeAction(UpgradeAction* action) { KNotification *notification = new KNotification(QStringLiteral("distupgrade-notification"), KNotification::Persistent | KNotification::DefaultEvent); notification->setIconName(QStringLiteral("system-software-update")); notification->setActions(QStringList{QLatin1String("Upgrade")}); notification->setTitle(i18n("Upgrade available")); notification->setText(i18n("New version: %1", action->description())); connect(notification, &KNotification::action1Activated, this, [action] () { action->trigger(); }); notification->sendEvent(); } diff --git a/notifier/DiscoverNotifier.h b/notifier/DiscoverNotifier.h index a02231e1..2d416abe 100644 --- a/notifier/DiscoverNotifier.h +++ b/notifier/DiscoverNotifier.h @@ -1,87 +1,90 @@ /*************************************************************************** * Copyright © 2014 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 . * ***************************************************************************/ #ifndef DISCOVERNOTIFIERMODULE_H #define DISCOVERNOTIFIERMODULE_H #include #include #include +#include + class QNetworkConfigurationManager; class DiscoverNotifier : public QObject { Q_OBJECT Q_PROPERTY(QStringList modules READ loadedModules CONSTANT) Q_PROPERTY(QString iconName READ iconName NOTIFY stateChanged) Q_PROPERTY(QString message READ message NOTIFY stateChanged) Q_PROPERTY(State state READ state NOTIFY stateChanged) Q_PROPERTY(bool needsReboot READ needsReboot NOTIFY needsRebootChanged) public: enum State { NoUpdates, NormalUpdates, SecurityUpdates, RebootRequired, Offline, }; Q_ENUM(State) explicit DiscoverNotifier(QObject* parent = nullptr); ~DiscoverNotifier() override; State state() const; QString iconName() const; QString message() const; bool hasUpdates() const { return m_hasUpdates; } bool hasSecurityUpdates() const { return m_hasSecurityUpdates; } QStringList loadedModules() const; bool needsReboot() const { return m_needsReboot; } public Q_SLOTS: void configurationChanged(); void recheckSystemUpdateNeeded(); void showDiscover(); void showDiscoverUpdates(); void showUpdatesNotification(); void reboot(); void foundUpgradeAction(UpgradeAction* action); Q_SIGNALS: void stateChanged(); bool needsRebootChanged(bool needsReboot); void newUpgradeAction(UpgradeAction* action); private: void showRebootNotification(); void updateStatusNotifier(); QList m_backends; bool m_verbose = false; QTimer m_timer; bool m_hasSecurityUpdates = false; bool m_hasUpdates = false; bool m_needsReboot = false; QNetworkConfigurationManager* m_manager = nullptr; + KNotification* m_updatesAvailableNotification = nullptr; }; #endif //ABSTRACTKDEDMODULE_H