2017-11-26 03:17:30 +01:00
|
|
|
#include "./syncthingnotifier.h"
|
|
|
|
#include "./syncthingconnection.h"
|
2018-04-02 20:26:00 +02:00
|
|
|
#include "./syncthingprocess.h"
|
2018-01-27 23:27:50 +01:00
|
|
|
#include "./utils.h"
|
2017-11-26 03:17:30 +01:00
|
|
|
|
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
|
|
|
#include "./syncthingservice.h"
|
|
|
|
#endif
|
|
|
|
|
2018-01-28 18:07:39 +01:00
|
|
|
#include <c++utilities/chrono/datetime.h>
|
|
|
|
|
|
|
|
using namespace ChronoUtilities;
|
|
|
|
|
2017-11-26 03:17:30 +01:00
|
|
|
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, ...).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \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
|
2018-04-11 23:15:15 +02:00
|
|
|
, m_service(SyncthingService::mainInstance())
|
2017-11-26 03:17:30 +01:00
|
|
|
#endif
|
2018-04-11 23:15:15 +02:00
|
|
|
, m_process(SyncthingProcess::mainInstance())
|
2017-11-26 03:17:30 +01:00
|
|
|
, m_enabledNotifications(SyncthingHighLevelNotification::None)
|
|
|
|
, m_previousStatus(SyncthingStatus::Disconnected)
|
2018-04-02 20:26:00 +02:00
|
|
|
, m_ignoreInavailabilityAfterStart(15)
|
2017-11-26 03:17:30 +01:00
|
|
|
, m_initialized(false)
|
|
|
|
{
|
2018-01-27 23:27:50 +01:00
|
|
|
connect(&connection, &SyncthingConnection::statusChanged, this, &SyncthingNotifier::handleStatusChangedEvent);
|
|
|
|
connect(&connection, &SyncthingConnection::dirCompleted, this, &SyncthingNotifier::emitSyncComplete);
|
2017-11-26 03:17:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
// update status variables
|
|
|
|
m_initialized = true;
|
|
|
|
m_previousStatus = newStatus;
|
|
|
|
}
|
|
|
|
|
2018-04-02 20:50:59 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns whether a "disconnected" notification should be shown.
|
|
|
|
* \todo Unify with InternalError::isRelevant().
|
|
|
|
*/
|
2018-04-02 20:26:00 +02:00
|
|
|
bool SyncthingNotifier::isDisconnectRelevant() const
|
|
|
|
{
|
|
|
|
// skip disconnect if not initialized
|
|
|
|
if (!m_initialized) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip further considerations if connection is remote
|
|
|
|
if (!m_connection.isLocal()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// consider process/launcher or systemd unit status
|
2018-04-11 23:15:15 +02:00
|
|
|
if (m_process && m_process->isManuallyStopped()) {
|
2018-04-02 20:26:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2018-04-11 23:15:15 +02:00
|
|
|
if (m_service && m_service->isManuallyStopped()) {
|
2018-04-02 20:26:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-04-02 20:50:59 +02:00
|
|
|
#endif
|
2018-04-02 20:26:00 +02:00
|
|
|
|
|
|
|
// ignore inavailability after start or standby-wakeup
|
|
|
|
if (m_ignoreInavailabilityAfterStart) {
|
2018-04-11 23:15:15 +02:00
|
|
|
if ((m_process && m_process->isRunning())
|
2018-04-02 20:50:59 +02:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2018-04-11 23:15:15 +02:00
|
|
|
&& ((m_service && m_service->isSystemdAvailable()
|
|
|
|
&& !m_service->isActiveWithoutSleepFor(m_process->activeSince(), m_ignoreInavailabilityAfterStart))
|
|
|
|
|| !m_process->isActiveFor(m_ignoreInavailabilityAfterStart))
|
2018-04-02 20:50:59 +02:00
|
|
|
#else
|
|
|
|
&& !m_process.isActiveFor(m_ignoreInavailabilityAfterStart)
|
|
|
|
#endif
|
|
|
|
) {
|
2018-04-02 20:26:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-04-10 21:05:40 +02:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2018-04-11 23:15:15 +02:00
|
|
|
if (m_service->isRunning() && !m_service->isActiveWithoutSleepFor(m_ignoreInavailabilityAfterStart)) {
|
2018-04-02 20:26:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-04-10 21:05:40 +02:00
|
|
|
#endif
|
2018-04-02 20:26:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-26 03:17:30 +01:00
|
|
|
/*!
|
|
|
|
* \brief Emits the connected() or disconnected() signal.
|
|
|
|
*/
|
|
|
|
void SyncthingNotifier::emitConnectedAndDisconnected(SyncthingStatus newStatus)
|
|
|
|
{
|
2018-01-28 18:07:39 +01:00
|
|
|
// discard event if not enabled
|
2017-11-26 03:17:30 +01:00
|
|
|
if (!(m_enabledNotifications & SyncthingHighLevelNotification::ConnectedDisconnected)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (newStatus) {
|
|
|
|
case SyncthingStatus::Disconnected:
|
2018-04-02 20:26:00 +02:00
|
|
|
if (isDisconnectRelevant()) {
|
2017-11-26 03:17:30 +01:00
|
|
|
emit disconnected();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
switch (m_previousStatus) {
|
|
|
|
case SyncthingStatus::Disconnected:
|
|
|
|
case SyncthingStatus::Reconnecting:
|
|
|
|
emit connected();
|
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Emits the syncComplete() signal.
|
|
|
|
*/
|
2018-01-28 18:07:39 +01:00
|
|
|
void SyncthingNotifier::emitSyncComplete(ChronoUtilities::DateTime when, const SyncthingDir &dir, int index, const SyncthingDev *remoteDev)
|
2017-11-26 03:17:30 +01:00
|
|
|
{
|
2018-03-29 00:38:21 +02:00
|
|
|
VAR_UNUSED(when)
|
2018-01-27 23:27:50 +01:00
|
|
|
VAR_UNUSED(index)
|
|
|
|
|
2018-01-28 18:07:39 +01:00
|
|
|
// discard event if not enabled
|
2018-03-31 22:31:28 +02:00
|
|
|
if (!m_initialized || (!remoteDev && (m_enabledNotifications & SyncthingHighLevelNotification::LocalSyncComplete) == 0)
|
|
|
|
|| (remoteDev && (m_enabledNotifications & SyncthingHighLevelNotification::LocalSyncComplete) == 0)) {
|
2017-11-26 03:17:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-28 18:07:39 +01:00
|
|
|
// format the notification message
|
2018-03-29 00:38:21 +02:00
|
|
|
const auto message(syncCompleteString(std::vector<const SyncthingDir *>{ &dir }, remoteDev));
|
2018-01-27 23:27:50 +01:00
|
|
|
if (!message.isEmpty()) {
|
|
|
|
emit syncComplete(message);
|
2017-11-26 03:17:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Data
|