diff --git a/notifier/CMakeLists.txt b/notifier/CMakeLists.txt index e1392063..6f868ea4 100644 --- a/notifier/CMakeLists.txt +++ b/notifier/CMakeLists.txt @@ -1,22 +1,23 @@ add_definitions(-DTRANSLATION_DOMAIN=\"plasma-discover-notifier\") add_library(DiscoverNotifierDeclarativePlugin BackendNotifierFactory.cpp DiscoverNotifier.cpp DiscoverNotifierDeclarativePlugin.cpp) target_link_libraries(DiscoverNotifierDeclarativePlugin KF5::Notifications KF5::ConfigCore KF5::I18n KF5::KIOWidgets Qt5::Qml Qt5::DBus + Qt5::Network Discover::Notifiers ) set_target_properties(DiscoverNotifierDeclarativePlugin PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}/plasma-discover) install(TARGETS DiscoverNotifierDeclarativePlugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/discovernotifier) install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/discovernotifier) find_package(KF5Plasma) if(KF5Plasma_FOUND) plasma_install_package(plasmoid org.kde.discovernotifier) endif() diff --git a/notifier/DiscoverNotifier.cpp b/notifier/DiscoverNotifier.cpp index cc3ec60b..648cf4a6 100644 --- a/notifier/DiscoverNotifier.cpp +++ b/notifier/DiscoverNotifier.cpp @@ -1,201 +1,210 @@ /*************************************************************************** * 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) + , m_manager(new QNetworkConfigurationManager(this)) { 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 updatesChanged(); + 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(); + + connect(m_manager, &QNetworkConfigurationManager::onlineStateChanged, this, &DiscoverNotifier::stateChanged); } 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); } void DiscoverNotifier::showDiscoverUpdates() { KRun::runCommand(QStringLiteral("plasma-discover --mode update"), nullptr); } void DiscoverNotifier::showUpdatesNotification() { - if (state()==NoUpdates) { + 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")); const QString name = i18n("Update"); e->setDefaultAction(name); e->setActions({name}); connect(e, 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 updatesChanged(); + emit stateChanged(); } DiscoverNotifier::State DiscoverNotifier::state() const { if (m_needsReboot) return RebootRequired; + else if (!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() { 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 788d3de2..64d52db6 100644 --- a/notifier/DiscoverNotifier.h +++ b/notifier/DiscoverNotifier.h @@ -1,85 +1,88 @@ /*************************************************************************** * 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 +class QNetworkConfigurationManager; class KStatusNotifierItem; class DiscoverNotifier : public QObject { Q_OBJECT Q_PROPERTY(QStringList modules READ loadedModules CONSTANT) -Q_PROPERTY(QString iconName READ iconName NOTIFY updatesChanged) -Q_PROPERTY(QString message READ message NOTIFY updatesChanged) -Q_PROPERTY(State state READ state NOTIFY updatesChanged) +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 + 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 updatesChanged(); + 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* const m_manager; }; #endif //ABSTRACTKDEDMODULE_H diff --git a/notifier/plasmoid/contents/ui/main.qml b/notifier/plasmoid/contents/ui/main.qml index 5060ac20..296db530 100644 --- a/notifier/plasmoid/contents/ui/main.qml +++ b/notifier/plasmoid/contents/ui/main.qml @@ -1,104 +1,106 @@ /*************************************************************************** * Copyright (C) 2014 by 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.2 import QtQml.Models 2.3 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.discovernotifier 1.0 Item { id: root Plasmoid.icon: DiscoverNotifier.iconName Plasmoid.toolTipSubText: DiscoverNotifier.message Plasmoid.status: { + switch (DiscoverNotifier.state) { + case DiscoverNotifier.Offline: case DiscoverNotifier.NoUpdates: return PlasmaCore.Types.PassiveStatus; case DiscoverNotifier.NormalUpdates: case DiscoverNotifier.SecurityUpdates: case DiscoverNotifier.RebootRequired: return PlasmaCore.Types.ActiveStatus; } } Plasmoid.onActivated: action_discover() Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation Plasmoid.compactRepresentation: PlasmaCore.IconItem { source: plasmoid.icon MouseArea { anchors.fill: parent onClicked: action_update() } } Component.onCompleted: { plasmoid.setAction("discover", i18n("Open Software Center..."), "plasma-discover"); plasmoid.setAction("update", i18n("See Updates..."), "system-software-update"); plasmoid.setAction("refresh", i18n("Refresh..."), "view-refresh"); if (DiscoverNotifier.needsReboot) plasmoid.setAction("reboot", i18n("Restart..."), "system-reboot"); } Connections { target: DiscoverNotifier onNeedsRebootChanged: plasmoid.setAction("reboot", i18n("Restart..."), "system-reboot"); } Instantiator { Connections { target: DiscoverNotifier onNewUpgradeAction: { upgrades.append(action) } } model: ObjectModel { id: upgrades } onObjectAdded: { plasmoid.setAction(index, object.description, "system-upgrade") } } function actionTriggered(actionName) { var index = parseInt(actionName); if (index) upgrades.get(index).trigger() } function action_discover() { DiscoverNotifier.showDiscover(); } function action_update() { DiscoverNotifier.showDiscoverUpdates(); plasmoid.activated() } function action_refresh() { DiscoverNotifier.recheckSystemUpdateNeeded(); } function action_reboot() { DiscoverNotifier.reboot() } }