Add SyncthingNotifier class

First step of refactoring compution of high-level
notifications to prevent code duplication for compution
of "disconnected" and "sync complete" events.
This commit is contained in:
Martchus 2017-11-26 03:17:30 +01:00
parent 712708822a
commit 841b250680
3 changed files with 204 additions and 0 deletions

View File

@ -14,6 +14,7 @@ set(HEADER_FILES
syncthingdev.h
syncthingconnection.h
syncthingconnectionsettings.h
syncthingnotifier.h
syncthingconfig.h
syncthingprocess.h
syncthingservice.h
@ -24,6 +25,7 @@ set(SRC_FILES
syncthingdev.cpp
syncthingconnection.cpp
syncthingconnectionsettings.cpp
syncthingnotifier.cpp
syncthingconfig.cpp
syncthingprocess.cpp
syncthingservice.cpp

View File

@ -0,0 +1,109 @@
#include "./syncthingnotifier.h"
#include "./syncthingconnection.h"
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
#include "./syncthingservice.h"
#endif
namespace Data {
/*!
* \class SyncthingNotifier
* \brief The SyncthingNotifier class emits high-level notification for a given SyncthingConnection.
*
* In contrast to the signals provided by the SyncthingConnection class, these signals take further apply
* further logic and take additional information into account (previous status, service status if known, ...).
*
* \remarks Not tested yet. Supposed to simplify
* - SyncthingApplet::handleConnectionStatusChanged(SyncthingStatus status)
* - and TrayIcon::showStatusNotification(SyncthingStatus status).
*/
/*!
* \brief Constructs a new SyncthingNotifier instance for the specified \a connection.
* \remarks Use setEnabledNotifications() to enable notifications (only statusChanged() is always emitted).
*/
SyncthingNotifier::SyncthingNotifier(const SyncthingConnection &connection, QObject *parent)
: QObject(parent)
, m_connection(connection)
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
, m_service(syncthingService())
#endif
, m_enabledNotifications(SyncthingHighLevelNotification::None)
, m_previousStatus(SyncthingStatus::Disconnected)
, m_initialized(false)
{
}
void SyncthingNotifier::handleStatusChangedEvent(SyncthingStatus newStatus)
{
// skip redundant status updates
if (m_initialized && m_previousStatus == newStatus) {
return;
}
// emit signals
emit statusChanged(m_previousStatus, newStatus);
emitConnectedAndDisconnected(newStatus);
emitSyncComplete(newStatus);
// update status variables
m_initialized = true;
m_previousStatus = newStatus;
}
/*!
* \brief Emits the connected() or disconnected() signal.
*/
void SyncthingNotifier::emitConnectedAndDisconnected(SyncthingStatus newStatus)
{
if (!(m_enabledNotifications & SyncthingHighLevelNotification::ConnectedDisconnected)) {
return;
}
switch (newStatus) {
case SyncthingStatus::Disconnected:
if (m_initialized
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
&& m_service.isManuallyStopped()
#endif
) {
emit disconnected();
}
break;
default:
switch (m_previousStatus) {
case SyncthingStatus::Disconnected:
case SyncthingStatus::Reconnecting:
emit connected();
break;
default:;
}
}
}
/*!
* \brief Emits the syncComplete() signal.
*/
void SyncthingNotifier::emitSyncComplete(SyncthingStatus newStatus)
{
if (!(m_enabledNotifications & SyncthingHighLevelNotification::SyncComplete)) {
return;
}
switch (newStatus) {
case SyncthingStatus::Disconnected:
case SyncthingStatus::Reconnecting:
case SyncthingStatus::Synchronizing:
break;
default:
if (m_previousStatus == SyncthingStatus::Synchronizing) {
const auto &completedDirs = m_connection.completedDirs();
if (!completedDirs.empty()) {
emit syncComplete(completedDirs);
}
}
}
}
} // namespace Data

View File

@ -0,0 +1,93 @@
#ifndef DATA_SYNCTHINGNOTIFIER_H
#define DATA_SYNCTHINGNOTIFIER_H
#include "./global.h"
#include <QObject>
namespace Data {
enum class SyncthingStatus;
class SyncthingConnection;
class SyncthingService;
struct SyncthingDir;
/*!
* \brief The SyncthingHighLevelNotification enum specifies the high-level notifications provided by the SyncthingNotifier class.
* \remarks The enum is supposed to be used as flag-enum.
*/
enum class SyncthingHighLevelNotification {
None = 0x0,
ConnectedDisconnected = 0x1,
SyncComplete = 0x2,
};
/// \cond
constexpr SyncthingHighLevelNotification operator|(SyncthingHighLevelNotification lhs, SyncthingHighLevelNotification rhs)
{
return static_cast<SyncthingHighLevelNotification>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
}
constexpr bool operator&(SyncthingHighLevelNotification lhs, SyncthingHighLevelNotification rhs)
{
return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
}
/// \endcond
class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingNotifier : public QObject {
Q_OBJECT
Q_PROPERTY(SyncthingHighLevelNotification enabledNotifications READ enabledNotifications WRITE setEnabledNotifications)
public:
SyncthingNotifier(const SyncthingConnection &connection, QObject *parent = nullptr);
SyncthingHighLevelNotification enabledNotifications() const;
public Q_SLOTS:
void setEnabledNotifications(SyncthingHighLevelNotification enabledNotifications);
Q_SIGNALS:
///! \brief Emitted when the connection status changes. Also provided the previous status.
void statusChanged(SyncthingStatus previousStatus, SyncthingStatus newStatus);
///! \brief Emitted when the connection to Syncthing has been established.
void connected();
///! \brief Emitted when the connection to Syncthing has been interrupted.
void disconnected();
///! \brief Emitted when the specified \a dirs have been completed synchronization.
void syncComplete(const std::vector<SyncthingDir *> &dirs);
private Q_SLOTS:
void handleStatusChangedEvent(SyncthingStatus newStatus);
private:
void emitConnectedAndDisconnected(SyncthingStatus newStatus);
void emitSyncComplete(SyncthingStatus newStatus);
const SyncthingConnection &m_connection;
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
const SyncthingService &m_service;
#endif
SyncthingHighLevelNotification m_enabledNotifications;
SyncthingStatus m_previousStatus;
bool m_initialized;
};
/*!
* \brief Returns which notifications are enabled (by default none).
*/
inline SyncthingHighLevelNotification SyncthingNotifier::enabledNotifications() const
{
return m_enabledNotifications;
}
/*!
* \brief Sets which notifications are enabled.
*/
inline void SyncthingNotifier::setEnabledNotifications(SyncthingHighLevelNotification enabledNotifications)
{
m_enabledNotifications = enabledNotifications;
}
} // namespace Data
#endif // DATA_SYNCTHINGNOTIFIER_H