Show notifications about launcher errors

This commit is contained in:
Martchus 2019-07-12 20:24:19 +02:00
parent 59d71aa6a5
commit 31bb92da89
9 changed files with 75 additions and 6 deletions

View File

@ -41,6 +41,9 @@ SyncthingNotifier::SyncthingNotifier(const SyncthingConnection &connection, QObj
connect(&connection, &SyncthingConnection::dirCompleted, this, &SyncthingNotifier::emitSyncComplete);
connect(&connection, &SyncthingConnection::newDevAvailable, this, &SyncthingNotifier::handleNewDevEvent);
connect(&connection, &SyncthingConnection::newDirAvailable, this, &SyncthingNotifier::handleNewDirEvent);
if (m_process) {
connect(m_process, &QProcess::errorOccurred, this, &SyncthingNotifier::handleSyncthingProcessError);
}
}
void SyncthingNotifier::handleStatusChangedEvent(SyncthingStatus newStatus)
@ -92,6 +95,24 @@ void SyncthingNotifier::handleNewDirEvent(DateTime when, const QString &devId, c
emit newDir(devId, dirId, message);
}
void SyncthingNotifier::handleSyncthingProcessError(QProcess::ProcessError processError)
{
if (!(m_enabledNotifications & SyncthingHighLevelNotification::SyncthingProcessError)) {
return;
}
switch(processError) {
case QProcess::FailedToStart:
emit syncthingProcessError(tr("Failed to start Syncthing"), tr("Maybe the configured binary path is wrong or the binary is not marked as executable."));
break;
case QProcess::Crashed:
emit syncthingProcessError(tr("Syncthing crashed with exit code %1").arg(m_process->exitCode()), QString());
break;
default:
emit syncthingProcessError(tr("Syncthing launcher error occurred"), m_process->errorString());
}
}
/*!
* \brief Returns whether a "disconnected" notification should be shown.
* \todo Unify with InternalError::isRelevant().

View File

@ -4,6 +4,7 @@
#include "./global.h"
#include <QObject>
#include <QProcess>
namespace CppUtilities {
class DateTime;
@ -29,6 +30,7 @@ enum class SyncthingHighLevelNotification {
RemoteSyncComplete = 0x4,
NewDevice = 0x8,
NewDir = 0x10,
SyncthingProcessError = 0x20,
};
/// \cond
@ -90,11 +92,14 @@ Q_SIGNALS:
void newDevice(const QString &devId, const QString &message);
///! \brief Emitted when a new directory is shared with us.
void newDir(const QString &devId, const QString &dirId, const QString &message);
///! \brief Emitted when the Syncthing process fails to start or crashes.
void syncthingProcessError(const QString &message, const QString &additionalInfo);
private Q_SLOTS:
void handleStatusChangedEvent(SyncthingStatus newStatus);
void handleNewDevEvent(CppUtilities::DateTime when, const QString &devId, const QString &address);
void handleNewDirEvent(CppUtilities::DateTime when, const QString &devId, const SyncthingDev *dev, const QString &dirId, const QString &dirLabel);
void handleSyncthingProcessError(QProcess::ProcessError syncthingProcessError);
private:
bool isDisconnectRelevant() const;

View File

@ -86,6 +86,7 @@ TrayIcon::TrayIcon(const QString &connectionConfig, QObject *parent)
connect(this, &TrayIcon::messageClicked, this, &TrayIcon::handleMessageClicked);
connect(&connection, &SyncthingConnection::error, this, &TrayIcon::showInternalError);
connect(&connection, &SyncthingConnection::newNotification, this, &TrayIcon::showSyncthingNotification);
connect(&notifier, &SyncthingNotifier::syncthingProcessError, this, &TrayIcon::showLauncherError);
connect(&notifier, &SyncthingNotifier::disconnected, this, &TrayIcon::showDisconnected);
connect(&notifier, &SyncthingNotifier::syncComplete, this, &TrayIcon::showSyncComplete);
connect(&notifier, &SyncthingNotifier::newDevice, this, &TrayIcon::showNewDev);
@ -191,13 +192,12 @@ void TrayIcon::handleErrorsCleared()
m_errorsAction->setVisible(false);
}
void TrayIcon::showInternalError(
const QString &errorMsg, SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response)
void TrayIcon::showInternalError(const QString &errorMessage, SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response)
{
if (!InternalError::isRelevant(m_trayMenu.widget().connection(), category, networkError)) {
return;
}
InternalError error(errorMsg, request.url(), response);
InternalError error(errorMessage, request.url(), response);
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if (m_dbusNotificationsEnabled) {
m_dbusNotifier.showInternalError(error);
@ -205,12 +205,25 @@ void TrayIcon::showInternalError(
#endif
{
m_messageClickedAction = TrayIconMessageClickedAction::ShowInternalErrors;
showMessage(tr("Error"), errorMsg, QSystemTrayIcon::Critical);
showMessage(tr("Error"), errorMessage, QSystemTrayIcon::Critical);
}
InternalErrorsDialog::addError(move(error));
m_errorsAction->setVisible(true);
}
void TrayIcon::showLauncherError(const QString &errorMessage, const QString &additionalInfo)
{
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
if (m_dbusNotificationsEnabled) {
m_dbusNotifier.showLauncherError(errorMessage, additionalInfo);
} else
#endif
{
m_messageClickedAction = TrayIconMessageClickedAction::None;
showMessage(tr("Launcher error"), QStringList({errorMessage, additionalInfo}).join(QChar('\n')), QSystemTrayIcon::Critical);
}
}
void TrayIcon::showSyncthingNotification(CppUtilities::DateTime when, const QString &message)
{
if (m_notifyOnSyncthingErrors) {

View File

@ -33,7 +33,8 @@ public:
public slots:
void showInternalError(
const QString &errorMsg, Data::SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response);
const QString &errorMessage, Data::SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response);
void showLauncherError(const QString &errorMessage, const QString &additionalInfo);
void showSyncthingNotification(CppUtilities::DateTime when, const QString &message);
void showInternalErrorsDialog();
void updateStatusIconAndText();

View File

@ -23,6 +23,7 @@ DBusStatusNotifier::DBusStatusNotifier(QObject *parent)
: QObject(parent)
, m_disconnectedNotification(QStringLiteral(APP_NAME), QStringLiteral("network-disconnect"), 5000)
, m_internalErrorNotification(QStringLiteral(APP_NAME) + tr(" - internal error"), NotificationIcon::Critical, 5000)
, m_launcherErrorNotification(QStringLiteral(APP_NAME) + tr(" - launcher error"), NotificationIcon::Critical, 5000)
, m_syncthingNotification(tr("Syncthing notification"), NotificationIcon::Warning, 10000)
, m_syncCompleteNotification(QStringLiteral(APP_NAME), NotificationIcon::Information, 5000)
, m_newDevNotification(QStringLiteral(APP_NAME) + tr(" - new device"), NotificationIcon::Information, 5000)
@ -37,6 +38,10 @@ DBusStatusNotifier::DBusStatusNotifier(QObject *parent)
m_internalErrorNotification.setActions(QStringList({ QStringLiteral("details"), tr("View details") }));
connect(&m_internalErrorNotification, &DBusNotification::actionInvoked, this, &DBusStatusNotifier::errorDetailsRequested);
m_internalErrorNotification.setApplicationName(QStringLiteral(APP_NAME));
m_internalErrorNotification.setActions(QStringList({ QStringLiteral("details"), tr("View details") }));
connect(&m_internalErrorNotification, &DBusNotification::actionInvoked, this, &DBusStatusNotifier::errorDetailsRequested);
m_syncthingNotification.setApplicationName(QStringLiteral(APP_NAME));
m_syncthingNotification.setActions(QStringList({ QStringLiteral("show"), tr("Show"), QStringLiteral("dismiss"), tr("Dismiss") }));
connect(&m_syncthingNotification, &DBusNotification::actionInvoked, this, &DBusStatusNotifier::handleSyncthingNotificationAction);
@ -61,7 +66,8 @@ void DBusStatusNotifier::setIcons(const StatusIcons &icons)
if (!icons.isValid) {
return;
}
m_syncthingNotification.setImage(makeImage(icons.error));
m_launcherErrorNotification.setImage(makeImage(icons.error));
m_syncthingNotification.setImage(m_launcherErrorNotification.image());
m_syncthingNotification.setImage(makeImage(icons.notify));
m_syncCompleteNotification.setImage(makeImage(icons.syncComplete));
m_newDevNotification.setImage(makeImage(icons.newItem));
@ -76,6 +82,7 @@ void DBusStatusNotifier::handleSyncthingNotificationAction(const QString &action
emit showNotificationsRequested();
}
}
} // namespace QtGui
#endif

View File

@ -8,6 +8,7 @@
#include <c++utilities/chrono/datetime.h>
#include <QObject>
#include <QStringList>
namespace Data {
enum class SyncthingErrorCategory;
@ -26,6 +27,7 @@ public Q_SLOTS:
void showDisconnect();
void hideDisconnect();
void showInternalError(const InternalError &error);
void showLauncherError(const QString &errorMessage, const QString &additionalInfo);
void showSyncthingNotification(CppUtilities::DateTime when, const QString &message);
void showSyncComplete(const QString &message);
void showNewDev(const QString &devId, const QString &message);
@ -45,6 +47,7 @@ private Q_SLOTS:
private:
QtUtilities::DBusNotification m_disconnectedNotification;
QtUtilities::DBusNotification m_internalErrorNotification;
QtUtilities::DBusNotification m_launcherErrorNotification;
QtUtilities::DBusNotification m_syncthingNotification;
QtUtilities::DBusNotification m_syncCompleteNotification;
QtUtilities::DBusNotification m_newDevNotification;
@ -66,6 +69,11 @@ inline void DBusStatusNotifier::showInternalError(const InternalError &error)
m_internalErrorNotification.update(error.message);
}
inline void QtGui::DBusStatusNotifier::showLauncherError(const QString &errorMessage, const QString &additionalInfo)
{
m_launcherErrorNotification.update(QStringList({errorMessage, additionalInfo}).join(QStringLiteral("\n ")));
}
inline void DBusStatusNotifier::showSyncthingNotification(CppUtilities::DateTime when, const QString &message)
{
Q_UNUSED(when)

View File

@ -65,6 +65,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="notifyOnLauncherErrorsCheckBox">
<property name="text">
<string>errors of Syncthing launcher</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -160,6 +160,7 @@ void restore()
auto &notifyOn = v.notifyOn;
notifyOn.disconnect = settings.value(QStringLiteral("notifyOnDisconnect"), notifyOn.disconnect).toBool();
notifyOn.internalErrors = settings.value(QStringLiteral("notifyOnErrors"), notifyOn.internalErrors).toBool();
notifyOn.launcherErrors = settings.value(QStringLiteral("notifyOnLauncherErrors"), notifyOn.launcherErrors).toBool();
notifyOn.localSyncComplete = settings.value(QStringLiteral("notifyOnLocalSyncComplete"), notifyOn.localSyncComplete).toBool();
notifyOn.remoteSyncComplete = settings.value(QStringLiteral("notifyOnRemoteSyncComplete"), notifyOn.remoteSyncComplete).toBool();
notifyOn.syncthingErrors = settings.value(QStringLiteral("showSyncthingNotifications"), notifyOn.syncthingErrors).toBool();
@ -248,6 +249,7 @@ void save()
const auto &notifyOn = v.notifyOn;
settings.setValue(QStringLiteral("notifyOnDisconnect"), notifyOn.disconnect);
settings.setValue(QStringLiteral("notifyOnErrors"), notifyOn.internalErrors);
settings.setValue(QStringLiteral("notifyOnLauncherErrors"), notifyOn.launcherErrors);
settings.setValue(QStringLiteral("notifyOnLocalSyncComplete"), notifyOn.localSyncComplete);
settings.setValue(QStringLiteral("notifyOnRemoteSyncComplete"), notifyOn.remoteSyncComplete);
settings.setValue(QStringLiteral("showSyncthingNotifications"), notifyOn.syncthingErrors);
@ -325,6 +327,9 @@ void Settings::apply(SyncthingNotifier &notifier) const
if (notifyOn.newDirectoryShared) {
notifications |= SyncthingHighLevelNotification::NewDir;
}
if (notifyOn.launcherErrors) {
notifications |= SyncthingHighLevelNotification::SyncthingProcessError;
}
notifier.setEnabledNotifications(notifications);
notifier.setIgnoreInavailabilityAfterStart(ignoreInavailabilityAfterStart);
}

View File

@ -374,6 +374,7 @@ bool NotificationsOptionPage::apply()
auto &notifyOn(settings.notifyOn);
notifyOn.disconnect = ui()->notifyOnDisconnectCheckBox->isChecked();
notifyOn.internalErrors = ui()->notifyOnErrorsCheckBox->isChecked();
notifyOn.launcherErrors = ui()->notifyOnLauncherErrorsCheckBox->isChecked();
notifyOn.localSyncComplete = ui()->notifyOnLocalSyncCompleteCheckBox->isChecked();
notifyOn.remoteSyncComplete = ui()->notifyOnRemoteSyncCompleteCheckBox->isChecked();
notifyOn.syncthingErrors = ui()->showSyncthingNotificationsCheckBox->isChecked();
@ -395,6 +396,7 @@ void NotificationsOptionPage::reset()
const auto &notifyOn = values().notifyOn;
ui()->notifyOnDisconnectCheckBox->setChecked(notifyOn.disconnect);
ui()->notifyOnErrorsCheckBox->setChecked(notifyOn.internalErrors);
ui()->notifyOnLauncherErrorsCheckBox->setChecked(notifyOn.launcherErrors);
ui()->notifyOnLocalSyncCompleteCheckBox->setChecked(notifyOn.localSyncComplete);
ui()->notifyOnRemoteSyncCompleteCheckBox->setChecked(notifyOn.remoteSyncComplete);
ui()->showSyncthingNotificationsCheckBox->setChecked(notifyOn.syncthingErrors);