Move status info/notification to widgets

* Allow reusing code in other components such
  as Plasmoid
* Separate determining status text and icon
  from displaying notifications
This commit is contained in:
Martchus 2017-04-25 00:50:30 +02:00
parent 49ff5a7b65
commit 1abb8b8a87
8 changed files with 275 additions and 92 deletions

View File

@ -2,6 +2,7 @@
#include "./traywidget.h"
#include "../../widgets/settings/settings.h"
#include "../../widgets/misc/statusinfo.h"
#include "../../model/syncthingicons.h"
@ -37,13 +38,6 @@ TrayIcon::TrayIcon(QObject *parent) :
m_initialized(false),
m_trayMenu(this),
m_status(SyncthingStatus::Disconnected)
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
,
m_disconnectedNotification(QCoreApplication::applicationName(), QStringLiteral("network-disconnect"), 5000),
m_internalErrorNotification(QCoreApplication::applicationName() + tr(" - internal error"), NotificationIcon::Critical, 5000),
m_syncthingNotification(tr("Syncthing notification"), NotificationIcon::Warning, 10000),
m_syncCompleteNotification(QCoreApplication::applicationName(), NotificationIcon::Information, 5000)
#endif
{
// set context menu
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("internet-web-browser"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/internet-web-browser.svg"))), tr("Web UI")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showWebUi);
@ -56,17 +50,8 @@ TrayIcon::TrayIcon(QObject *parent) :
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("window-close"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/window-close.svg"))), tr("Close")), &QAction::triggered, this, &TrayIcon::deleteLater);
setContextMenu(&m_contextMenu);
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
// setup notifications
m_disconnectedNotification.setMessage(tr("Disconnected from Syncthing"));
m_disconnectedNotification.setActions(QStringList(tr("Try to reconnect")));
connect(&m_disconnectedNotification, &DBusNotification::actionInvoked, &(m_trayMenu.widget()->connection()), static_cast<void(SyncthingConnection::*)(void)>(&SyncthingConnection::connect));
m_syncthingNotification.setActions(QStringList({QStringLiteral("show"), tr("Show"), QStringLiteral("dismiss"), tr("Dismiss")}));
connect(&m_syncthingNotification, &DBusNotification::actionInvoked, this, &TrayIcon::handleSyncthingNotificationAction);
#endif
// set initial status
updateStatusIconAndText(SyncthingStatus::Disconnected);
handleConnectionStatusChanged(SyncthingStatus::Disconnected);
// connect signals and slots
SyncthingConnection *connection = &(m_trayMenu.widget()->connection());
@ -74,7 +59,10 @@ TrayIcon::TrayIcon(QObject *parent) :
connect(this, &TrayIcon::messageClicked, m_trayMenu.widget(), &TrayWidget::dismissNotifications);
connect(connection, &SyncthingConnection::error, this, &TrayIcon::showInternalError);
connect(connection, &SyncthingConnection::newNotification, this, &TrayIcon::showSyncthingNotification);
connect(connection, &SyncthingConnection::statusChanged, this, &TrayIcon::updateStatusIconAndText);
connect(connection, &SyncthingConnection::statusChanged, this, &TrayIcon::handleConnectionStatusChanged);
connect(&m_dbusNotifier, &DBusStatusNotifier::connectRequested, connection, static_cast<void(SyncthingConnection::*)(void)>(&SyncthingConnection::connect));
connect(&m_dbusNotifier, &DBusStatusNotifier::dismissNotificationsRequested, m_trayMenu.widget(), &TrayWidget::dismissNotifications);
connect(&m_dbusNotifier, &DBusStatusNotifier::showNotificationsRequested, m_trayMenu.widget(), &TrayWidget::showNotifications);
m_initialized = true;
}
@ -114,14 +102,14 @@ void TrayIcon::handleActivated(QSystemTrayIcon::ActivationReason reason)
}
}
void TrayIcon::handleSyncthingNotificationAction(const QString &action)
void TrayIcon::handleConnectionStatusChanged(SyncthingStatus status)
{
if(action == QLatin1String("dismiss")) {
m_trayMenu.widget()->dismissNotifications();
} else if(action == QLatin1String("show")) {
m_trayMenu.widget()->showNotifications();
if(m_initialized && m_status == status) {
return;
}
updateStatusIconAndText();
showStatusNotification(status);
m_status = status;
}
void TrayIcon::showInternalError(const QString &errorMsg, SyncthingErrorCategory category, int networkError)
@ -141,7 +129,7 @@ void TrayIcon::showInternalError(const QString &errorMsg, SyncthingErrorCategory
) {
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if(settings.dbusNotifications) {
m_internalErrorNotification.update(errorMsg);
m_dbusNotifier.showInternalError(errorMsg, category, networkError);
} else
#endif
{
@ -152,38 +140,36 @@ void TrayIcon::showInternalError(const QString &errorMsg, SyncthingErrorCategory
void TrayIcon::showSyncthingNotification(ChronoUtilities::DateTime when, const QString &message)
{
Q_UNUSED(when)
const auto &settings = Settings::values();
if(settings.notifyOn.syncthingErrors) {
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if(settings.dbusNotifications) {
m_syncthingNotification.update(message);
m_dbusNotifier.showSyncthingNotification(when, message);
} else
#else
Q_UNUSED(when)
#endif
{
showMessage(tr("Syncthing notification - click to dismiss"), message, QSystemTrayIcon::Warning);
}
}
updateStatusIconAndText(m_status);
updateStatusIconAndText();
}
void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
void TrayIcon::updateStatusIconAndText()
{
if(m_initialized && m_status == status) {
return;
}
const StatusInfo statusInfo(trayMenu().widget()->connection());
setToolTip(statusInfo.statusText());
setIcon(statusInfo.statusIcon());
}
void TrayIcon::showStatusNotification(SyncthingStatus status)
{
const SyncthingConnection &connection = trayMenu().widget()->connection();
const auto &settings = Settings::values();
switch(status) {
case SyncthingStatus::Disconnected:
setIcon(statusIcons().disconnected);
if(connection.autoReconnectInterval() > 0) {
setToolTip(tr("Not connected to Syncthing - trying to reconnect every %1 ms")
.arg(connection.autoReconnectInterval()));
} else {
setToolTip(tr("Not connected to Syncthing"));
}
if(m_initialized && settings.notifyOn.disconnect
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
&& !syncthingService().isManuallyStopped()
@ -191,55 +177,18 @@ void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
) {
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if(settings.dbusNotifications) {
m_disconnectedNotification.show();
m_dbusNotifier.showDisconnect();
} else
#endif
{
showMessage(QCoreApplication::applicationName(), tr("Disconnected from Syncthing"), QSystemTrayIcon::Warning);
}
}
break;
case SyncthingStatus::Reconnecting:
setIcon(statusIcons().disconnected);
setToolTip(tr("Reconnecting ..."));
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
break;
default:
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
m_disconnectedNotification.hide();
m_dbusNotifier.hideDisconnect();
#endif
if(connection.hasOutOfSyncDirs()) {
if(status == SyncthingStatus::Synchronizing) {
setIcon(statusIcons().errorSync);
setToolTip(tr("Synchronization is ongoing but at least one directory is out of sync"));
} else {
setIcon(statusIcons().error);
setToolTip(tr("At least one directory is out of sync"));
}
} else if(connection.hasUnreadNotifications()) {
setIcon(statusIcons().notify);
setToolTip(tr("Notifications available"));
} else {
switch(status) {
case SyncthingStatus::Idle:
setIcon(statusIcons().idling);
setToolTip(tr("Syncthing is idling"));
break;
case SyncthingStatus::Scanning:
setIcon(statusIcons().scanninig);
setToolTip(tr("Syncthing is scanning"));
break;
case SyncthingStatus::Paused:
setIcon(statusIcons().pause);
setToolTip(tr("At least one device is paused"));
break;
case SyncthingStatus::Synchronizing:
setIcon(statusIcons().sync);
setToolTip(tr("Synchronization is ongoing"));
break;
default:
;
}
}
}
switch(status) {
case SyncthingStatus::Disconnected:
@ -263,7 +212,7 @@ void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
}
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if(settings.dbusNotifications) {
m_syncCompleteNotification.update(message);
m_dbusNotifier.showSyncComplete(message);
} else
#endif
{
@ -272,7 +221,6 @@ void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
}
}
}
m_status = status;
}
}

View File

@ -3,11 +3,9 @@
#include "./traymenu.h"
#include <c++utilities/chrono/datetime.h>
#include "../../widgets/misc/dbusstatusnotifier.h"
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
# include <qtutilities/misc/dbusnotification.h>
#endif
#include <c++utilities/chrono/datetime.h>
#include <QSystemTrayIcon>
#include <QIcon>
@ -32,11 +30,12 @@ public:
public slots:
void showInternalError(const QString &errorMsg, Data::SyncthingErrorCategory category, int networkError);
void showSyncthingNotification(ChronoUtilities::DateTime when, const QString &message);
void updateStatusIconAndText(Data::SyncthingStatus status);
void showStatusNotification(Data::SyncthingStatus status);
void updateStatusIconAndText();
private slots:
void handleActivated(QSystemTrayIcon::ActivationReason reason);
void handleSyncthingNotificationAction(const QString &action);
void handleConnectionStatusChanged(Data::SyncthingStatus status);
private:
bool m_initialized;
@ -44,10 +43,7 @@ private:
QMenu m_contextMenu;
Data::SyncthingStatus m_status;
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
MiscUtils::DBusNotification m_disconnectedNotification;
MiscUtils::DBusNotification m_internalErrorNotification;
MiscUtils::DBusNotification m_syncthingNotification;
MiscUtils::DBusNotification m_syncCompleteNotification;
DBusStatusNotifier m_dbusNotifier;
#endif
};

View File

@ -287,7 +287,7 @@ void TrayWidget::dismissNotifications()
m_connection.considerAllNotificationsRead();
m_ui->notificationsPushButton->setHidden(true);
if(m_menu && m_menu->icon()) {
m_menu->icon()->updateStatusIconAndText(m_connection.status());
m_menu->icon()->updateStatusIconAndText();
}
}

View File

@ -17,6 +17,8 @@ set(WIDGETS_HEADER_FILES
webview/webpage.h
webview/webviewdialog.h
misc/textviewdialog.h
misc/statusinfo.h
misc/dbusstatusnotifier.h
)
set(WIDGETS_SRC_FILES
settings/settings.cpp
@ -24,6 +26,8 @@ set(WIDGETS_SRC_FILES
webview/webpage.cpp
webview/webviewdialog.cpp
misc/textviewdialog.cpp
misc/statusinfo.cpp
misc/dbusstatusnotifier.cpp
)
set(RES_FILES
resources/${META_PROJECT_NAME}icons.qrc

View File

@ -0,0 +1,36 @@
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
#include "./dbusstatusnotifier.h"
#include <QCoreApplication>
using namespace Data;
using namespace MiscUtils;
namespace QtGui {
DBusStatusNotifier::DBusStatusNotifier(QObject *parent) :
QObject(parent),
m_disconnectedNotification(QCoreApplication::applicationName(), QStringLiteral("network-disconnect"), 5000),
m_internalErrorNotification(QCoreApplication::applicationName() + tr(" - internal error"), NotificationIcon::Critical, 5000),
m_syncthingNotification(tr("Syncthing notification"), NotificationIcon::Warning, 10000),
m_syncCompleteNotification(QCoreApplication::applicationName(), NotificationIcon::Information, 5000)
{
m_disconnectedNotification.setMessage(tr("Disconnected from Syncthing"));
m_disconnectedNotification.setActions(QStringList(tr("Try to reconnect")));
connect(&m_disconnectedNotification, &DBusNotification::actionInvoked, this, &DBusStatusNotifier::connectRequested);
m_syncthingNotification.setActions(QStringList({QStringLiteral("show"), tr("Show"), QStringLiteral("dismiss"), tr("Dismiss")}));
connect(&m_syncthingNotification, &DBusNotification::actionInvoked, this, &DBusStatusNotifier::handleSyncthingNotificationAction);
}
void DBusStatusNotifier::handleSyncthingNotificationAction(const QString &action)
{
if(action == QLatin1String("dismiss")) {
emit dismissNotificationsRequested();
} else if(action == QLatin1String("show")) {
emit showNotificationsRequested();
}
}
}
#endif

View File

@ -0,0 +1,77 @@
#if !defined(SYNCTHINGWIDGETS_DBUSSTATUSNOTIFIER_H) && defined(QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS)
#define SYNCTHINGWIDGETS_DBUSSTATUSNOTIFIER_H
#include "../global.h"
#include <qtutilities/misc/dbusnotification.h>
#include <c++utilities/chrono/datetime.h>
#include <QObject>
namespace Data {
enum class SyncthingErrorCategory;
}
namespace QtGui {
class SYNCTHINGWIDGETS_EXPORT DBusStatusNotifier : public QObject
{
Q_OBJECT
public:
explicit DBusStatusNotifier(QObject *parent = nullptr);
public Q_SLOTS:
void showDisconnect();
void hideDisconnect();
void showInternalError(const QString &errorMsg, Data::SyncthingErrorCategory category, int networkError);
void showSyncthingNotification(ChronoUtilities::DateTime when, const QString &message);
void showSyncComplete(const QString &message);
Q_SIGNALS:
void connectRequested();
void dismissNotificationsRequested();
void showNotificationsRequested();
private Q_SLOTS:
void handleSyncthingNotificationAction(const QString &action);
private:
MiscUtils::DBusNotification m_disconnectedNotification;
MiscUtils::DBusNotification m_internalErrorNotification;
MiscUtils::DBusNotification m_syncthingNotification;
MiscUtils::DBusNotification m_syncCompleteNotification;
};
inline void DBusStatusNotifier::showDisconnect()
{
m_disconnectedNotification.show();
}
inline void DBusStatusNotifier::hideDisconnect()
{
m_disconnectedNotification.hide();
}
inline void DBusStatusNotifier::showInternalError(const QString &errorMsg, Data::SyncthingErrorCategory category, int networkError)
{
Q_UNUSED(category)
Q_UNUSED(networkError)
m_internalErrorNotification.update(errorMsg);
}
inline void DBusStatusNotifier::showSyncthingNotification(ChronoUtilities::DateTime when, const QString &message)
{
Q_UNUSED(when)
m_syncthingNotification.update(message);
}
inline void DBusStatusNotifier::showSyncComplete(const QString &message)
{
m_syncCompleteNotification.update(message);
}
}
#endif // !defined(SYNCTHINGWIDGETS_DBUSSTATUSNOTIFIER_H) && defined(QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS)

View File

@ -0,0 +1,74 @@
#include "./statusinfo.h"
#include "../../connector/syncthingconnection.h"
#include "../../model/syncthingicons.h"
#include <QIcon>
#include <QCoreApplication>
using namespace Data;
namespace QtGui {
StatusInfo::StatusInfo() :
m_statusText(QCoreApplication::translate("QtGui::StatusInfo", "Initializing ...")),
m_statusIcon(&statusIcons().disconnected)
{}
void StatusInfo::update(const SyncthingConnection &connection)
{
switch(connection.status()) {
case SyncthingStatus::Disconnected:
if(connection.autoReconnectInterval() > 0) {
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Not connected to Syncthing - trying to reconnect every %1 ms")
.arg(connection.autoReconnectInterval());
} else {
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Not connected to Syncthing");
}
m_statusIcon = &statusIcons().disconnected;
break;
case SyncthingStatus::Reconnecting:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Reconnecting ...");
m_statusIcon = &statusIcons().disconnected;
break;
default:
if(connection.hasOutOfSyncDirs()) {
switch(connection.status()) {
case SyncthingStatus::Synchronizing:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Synchronization is ongoing but at least one directory is out of sync");
m_statusIcon = &statusIcons().errorSync;
break;
default:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "At least one directory is out of sync");
m_statusIcon = &statusIcons().error;
}
} else if(connection.hasUnreadNotifications()) {
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Notifications available");
m_statusIcon = &statusIcons().notify;
} else {
switch(connection.status()) {
case SyncthingStatus::Idle:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Syncthing is idling");
m_statusIcon = &statusIcons().idling;
break;
case SyncthingStatus::Scanning:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Syncthing is scanning");
m_statusIcon = &statusIcons().scanninig;
break;
case SyncthingStatus::Paused:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "At least one device is paused");
m_statusIcon = &statusIcons().pause;
break;
case SyncthingStatus::Synchronizing:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Synchronization is ongoing");
m_statusIcon = &statusIcons().sync;
break;
default:
m_statusText = QCoreApplication::translate("QtGui::StatusInfo", "Status is unknown");
m_statusIcon = &statusIcons().disconnected;
}
}
}
}
}

48
widgets/misc/statusinfo.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef SYNCTHINGWIDGETS_STATUSINFO_H
#define SYNCTHINGWIDGETS_STATUSINFO_H
#include "../global.h"
#include <QString>
QT_FORWARD_DECLARE_CLASS(QIcon)
namespace Data {
class SyncthingConnection;
}
namespace QtGui {
class SYNCTHINGWIDGETS_EXPORT StatusInfo
{
public:
explicit StatusInfo();
explicit StatusInfo(const Data::SyncthingConnection &connection);
QString statusText() const;
const QIcon &statusIcon() const;
void update(const Data::SyncthingConnection &connection);
private:
QString m_statusText;
const QIcon *m_statusIcon;
};
inline StatusInfo::StatusInfo(const Data::SyncthingConnection &connection)
{
update(connection);
}
inline QString StatusInfo::statusText() const
{
return m_statusText;
}
inline const QIcon &StatusInfo::statusIcon() const
{
return *m_statusIcon;
}
}
#endif // SYNCTHINGWIDGETS_STATUSINFO_H