Refactor preventing unwanted error messages
* See https://github.com/Martchus/syncthingtray/issues/15 * Not tested yet
This commit is contained in:
parent
b81c316d4a
commit
146d4870e4
|
@ -184,6 +184,15 @@ void SyncthingConnection::connect(SyncthingConnectionSettings &connectionSetting
|
|||
}
|
||||
}
|
||||
|
||||
void SyncthingConnection::connectLater(int milliSeconds)
|
||||
{
|
||||
// skip if conneting via auto-reconnect anyways
|
||||
if (autoReconnectInterval() > 0 && milliSeconds < autoReconnectInterval()) {
|
||||
return;
|
||||
}
|
||||
QTimer::singleShot(milliSeconds, this, static_cast<void (SyncthingConnection::*)(void)>(&SyncthingConnection::connect));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Disconnects. Does nothing if not connected.
|
||||
*/
|
||||
|
@ -223,6 +232,11 @@ void SyncthingConnection::reconnect(SyncthingConnectionSettings &connectionSetti
|
|||
reconnect();
|
||||
}
|
||||
|
||||
void SyncthingConnection::reconnectLater(int milliSeconds)
|
||||
{
|
||||
QTimer::singleShot(milliSeconds, this, static_cast<void (SyncthingConnection::*)(void)>(&SyncthingConnection::reconnect));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Internally called to reconnect; ensures currently cached config is cleared.
|
||||
*/
|
||||
|
|
|
@ -137,9 +137,11 @@ public Q_SLOTS:
|
|||
bool applySettings(SyncthingConnectionSettings &connectionSettings);
|
||||
void connect();
|
||||
void connect(SyncthingConnectionSettings &connectionSettings);
|
||||
void connectLater(int milliSeconds);
|
||||
void disconnect();
|
||||
void reconnect();
|
||||
void reconnect(SyncthingConnectionSettings &connectionSettings);
|
||||
void reconnectLater(int milliSeconds);
|
||||
bool pauseDevice(const QStringList &devIds);
|
||||
bool pauseAllDevs();
|
||||
bool resumeDevice(const QStringList &devIds);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "./syncthingnotifier.h"
|
||||
#include "./syncthingconnection.h"
|
||||
#include "./syncthingprocess.h"
|
||||
#include "./utils.h"
|
||||
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
|
@ -30,8 +31,10 @@ SyncthingNotifier::SyncthingNotifier(const SyncthingConnection &connection, QObj
|
|||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
, m_service(syncthingService())
|
||||
#endif
|
||||
, m_process(syncthingProcess())
|
||||
, m_enabledNotifications(SyncthingHighLevelNotification::None)
|
||||
, m_previousStatus(SyncthingStatus::Disconnected)
|
||||
, m_ignoreInavailabilityAfterStart(15)
|
||||
, m_initialized(false)
|
||||
{
|
||||
connect(&connection, &SyncthingConnection::statusChanged, this, &SyncthingNotifier::handleStatusChangedEvent);
|
||||
|
@ -54,6 +57,41 @@ void SyncthingNotifier::handleStatusChangedEvent(SyncthingStatus newStatus)
|
|||
m_previousStatus = newStatus;
|
||||
}
|
||||
|
||||
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
|
||||
if (m_process.isManuallyStopped()) {
|
||||
return false;
|
||||
}
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
if (m_service.isManuallyStopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ignore inavailability after start or standby-wakeup
|
||||
if (m_ignoreInavailabilityAfterStart) {
|
||||
if (m_process.isRunning() && !m_service.isActiveWithoutSleepFor(m_process.activeSince(), m_ignoreInavailabilityAfterStart)) {
|
||||
return false;
|
||||
}
|
||||
if (m_service.isRunning() && !m_service.isActiveWithoutSleepFor(m_ignoreInavailabilityAfterStart)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Emits the connected() or disconnected() signal.
|
||||
*/
|
||||
|
@ -66,11 +104,7 @@ void SyncthingNotifier::emitConnectedAndDisconnected(SyncthingStatus newStatus)
|
|||
|
||||
switch (newStatus) {
|
||||
case SyncthingStatus::Disconnected:
|
||||
if (m_initialized
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
&& m_service.isManuallyStopped()
|
||||
#endif
|
||||
) {
|
||||
if (isDisconnectRelevant()) {
|
||||
emit disconnected();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Data {
|
|||
enum class SyncthingStatus;
|
||||
class SyncthingConnection;
|
||||
class SyncthingService;
|
||||
class SyncthingProcess;
|
||||
struct SyncthingDir;
|
||||
struct SyncthingDev;
|
||||
|
||||
|
@ -48,14 +49,17 @@ constexpr bool operator&(SyncthingHighLevelNotification lhs, SyncthingHighLevelN
|
|||
class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingNotifier : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(SyncthingHighLevelNotification enabledNotifications READ enabledNotifications WRITE setEnabledNotifications)
|
||||
Q_PROPERTY(bool ignoreInavailabilityAfterStart READ ignoreInavailabilityAfterStart WRITE setIgnoreInavailabilityAfterStart)
|
||||
|
||||
public:
|
||||
SyncthingNotifier(const SyncthingConnection &connection, QObject *parent = nullptr);
|
||||
|
||||
SyncthingHighLevelNotification enabledNotifications() const;
|
||||
unsigned int ignoreInavailabilityAfterStart() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabledNotifications(SyncthingHighLevelNotification enabledNotifications);
|
||||
void setIgnoreInavailabilityAfterStart(unsigned int seconds);
|
||||
|
||||
Q_SIGNALS:
|
||||
///! \brief Emitted when the connection status changes. Also provides the previous status.
|
||||
|
@ -71,6 +75,7 @@ private Q_SLOTS:
|
|||
void handleStatusChangedEvent(SyncthingStatus newStatus);
|
||||
|
||||
private:
|
||||
bool isDisconnectRelevant() const;
|
||||
void emitConnectedAndDisconnected(SyncthingStatus newStatus);
|
||||
void emitSyncComplete(ChronoUtilities::DateTime when, const SyncthingDir &dir, int index, const SyncthingDev *remoteDev);
|
||||
|
||||
|
@ -78,8 +83,10 @@ private:
|
|||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
const SyncthingService &m_service;
|
||||
#endif
|
||||
const SyncthingProcess &m_process;
|
||||
SyncthingHighLevelNotification m_enabledNotifications;
|
||||
SyncthingStatus m_previousStatus;
|
||||
unsigned int m_ignoreInavailabilityAfterStart;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
|
@ -99,6 +106,22 @@ inline void SyncthingNotifier::setEnabledNotifications(SyncthingHighLevelNotific
|
|||
m_enabledNotifications = enabledNotifications;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the number of seconds after startup or standby-wakeup to supress disconnect notifications.
|
||||
*/
|
||||
inline unsigned int SyncthingNotifier::ignoreInavailabilityAfterStart() const
|
||||
{
|
||||
return m_ignoreInavailabilityAfterStart;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Prevents disconnect notifications in the first \a seconds after startup or standby-wakeup.
|
||||
*/
|
||||
inline void SyncthingNotifier::setIgnoreInavailabilityAfterStart(unsigned int seconds)
|
||||
{
|
||||
m_ignoreInavailabilityAfterStart = seconds;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
||||
#endif // DATA_SYNCTHINGNOTIFIER_H
|
||||
|
|
|
@ -2,52 +2,68 @@
|
|||
|
||||
#include <QTimer>
|
||||
|
||||
using namespace ChronoUtilities;
|
||||
|
||||
namespace Data {
|
||||
|
||||
SyncthingProcess::SyncthingProcess(QObject *parent)
|
||||
: QProcess(parent)
|
||||
, m_manuallyStopped(false)
|
||||
{
|
||||
setProcessChannelMode(QProcess::MergedChannels);
|
||||
connect(this, &SyncthingProcess::started, this, &SyncthingProcess::handleStarted);
|
||||
connect(this, static_cast<void (SyncthingProcess::*)(int exitCode, QProcess::ExitStatus exitStatus)>(&SyncthingProcess::finished), this,
|
||||
&SyncthingProcess::handleFinished);
|
||||
}
|
||||
|
||||
void SyncthingProcess::restartSyncthing(const QString &cmd)
|
||||
{
|
||||
if (state() == QProcess::Running) {
|
||||
if (!isRunning()) {
|
||||
startSyncthing(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
m_cmd = cmd;
|
||||
m_manuallyStopped = true;
|
||||
// give Syncthing 5 seconds to terminate, otherwise kill it
|
||||
QTimer::singleShot(5000, this, &SyncthingProcess::killToRestart);
|
||||
terminate();
|
||||
} else {
|
||||
startSyncthing(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void SyncthingProcess::startSyncthing(const QString &cmd)
|
||||
{
|
||||
if (state() == QProcess::NotRunning) {
|
||||
if (isRunning()) {
|
||||
return;
|
||||
}
|
||||
m_manuallyStopped = false;
|
||||
if (cmd.isEmpty()) {
|
||||
start(QProcess::ReadOnly);
|
||||
} else {
|
||||
start(cmd, QProcess::ReadOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SyncthingProcess::stopSyncthing()
|
||||
{
|
||||
if (state() == QProcess::Running) {
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
m_manuallyStopped = true;
|
||||
// give Syncthing 5 seconds to terminate, otherwise kill it
|
||||
QTimer::singleShot(5000, this, &SyncthingProcess::kill);
|
||||
terminate();
|
||||
}
|
||||
|
||||
void SyncthingProcess::handleStarted()
|
||||
{
|
||||
m_activeSince = DateTime::gmtNow();
|
||||
}
|
||||
|
||||
void SyncthingProcess::handleFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
Q_UNUSED(exitCode)
|
||||
Q_UNUSED(exitStatus)
|
||||
m_activeSince = DateTime();
|
||||
if (!m_cmd.isEmpty()) {
|
||||
startSyncthing(m_cmd);
|
||||
m_cmd.clear();
|
||||
|
|
|
@ -3,14 +3,24 @@
|
|||
|
||||
#include "./global.h"
|
||||
|
||||
#include <c++utilities/chrono/datetime.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
namespace Data {
|
||||
|
||||
class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingProcess : public QProcess {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool running READ isRunning)
|
||||
Q_PROPERTY(ChronoUtilities::DateTime activeSince READ activeSince)
|
||||
Q_PROPERTY(bool manuallyStopped READ isManuallyStopped)
|
||||
|
||||
public:
|
||||
explicit SyncthingProcess(QObject *parent = nullptr);
|
||||
bool isRunning() const;
|
||||
ChronoUtilities::DateTime activeSince() const;
|
||||
bool isActiveFor(unsigned int atLeastSeconds) const;
|
||||
bool isManuallyStopped() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void restartSyncthing(const QString &cmd);
|
||||
|
@ -18,13 +28,36 @@ public Q_SLOTS:
|
|||
void stopSyncthing();
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleStarted();
|
||||
void handleFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void killToRestart();
|
||||
|
||||
private:
|
||||
QString m_cmd;
|
||||
ChronoUtilities::DateTime m_activeSince;
|
||||
bool m_manuallyStopped;
|
||||
};
|
||||
|
||||
inline bool SyncthingProcess::isRunning() const
|
||||
{
|
||||
return state() != QProcess::NotRunning;
|
||||
}
|
||||
|
||||
inline ChronoUtilities::DateTime SyncthingProcess::activeSince() const
|
||||
{
|
||||
return m_activeSince;
|
||||
}
|
||||
|
||||
inline bool SyncthingProcess::isActiveFor(unsigned int atLeastSeconds) const
|
||||
{
|
||||
return !m_activeSince.isNull() && (ChronoUtilities::DateTime::gmtNow() - m_activeSince).totalSeconds() > atLeastSeconds;
|
||||
}
|
||||
|
||||
inline bool SyncthingProcess::isManuallyStopped() const
|
||||
{
|
||||
return m_manuallyStopped;
|
||||
}
|
||||
|
||||
SyncthingProcess LIB_SYNCTHING_CONNECTOR_EXPORT &syncthingProcess();
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -109,18 +109,17 @@ bool SyncthingService::isUnitAvailable() const
|
|||
return m_unit && m_unit->isValid();
|
||||
}
|
||||
|
||||
bool SyncthingService::isActiveWithoutSleepFor(unsigned int atLeastSeconds) const
|
||||
bool SyncthingService::isActiveWithoutSleepFor(DateTime activeSince, unsigned int atLeastSeconds)
|
||||
{
|
||||
if (!atLeastSeconds) {
|
||||
return true;
|
||||
}
|
||||
if (m_activeSince.isNull() || s_fallingAsleep) {
|
||||
if (activeSince.isNull() || s_fallingAsleep) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const DateTime now(DateTime::gmtNow());
|
||||
return ((now - m_activeSince).totalSeconds() > atLeastSeconds)
|
||||
&& (s_lastWakeUp.isNull() || ((now - s_lastWakeUp).totalSeconds() > atLeastSeconds));
|
||||
return ((now - activeSince).totalSeconds() > atLeastSeconds) && (s_lastWakeUp.isNull() || ((now - s_lastWakeUp).totalSeconds() > atLeastSeconds));
|
||||
}
|
||||
|
||||
void SyncthingService::setRunning(bool running)
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
ChronoUtilities::DateTime activeSince() const;
|
||||
bool isActiveFor(unsigned int atLeastSeconds) const;
|
||||
bool isActiveWithoutSleepFor(unsigned int atLeastSeconds) const;
|
||||
static bool isActiveWithoutSleepFor(ChronoUtilities::DateTime activeSince, unsigned int atLeastSeconds);
|
||||
static ChronoUtilities::DateTime lastWakeUp();
|
||||
const QString &unitFileState() const;
|
||||
const QString &description() const;
|
||||
|
@ -188,6 +189,11 @@ inline bool SyncthingService::isActiveFor(unsigned int atLeastSeconds) const
|
|||
return !m_activeSince.isNull() && (ChronoUtilities::DateTime::gmtNow() - m_activeSince).totalSeconds() > atLeastSeconds;
|
||||
}
|
||||
|
||||
inline bool SyncthingService::isActiveWithoutSleepFor(unsigned int atLeastSeconds) const
|
||||
{
|
||||
return isActiveWithoutSleepFor(m_activeSince, atLeastSeconds);
|
||||
}
|
||||
|
||||
inline ChronoUtilities::DateTime SyncthingService::lastWakeUp()
|
||||
{
|
||||
return s_lastWakeUp;
|
||||
|
|
|
@ -101,6 +101,7 @@ void SyncthingApplet::init()
|
|||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
SyncthingService &service = syncthingService();
|
||||
service.setUnitName(Settings::values().systemd.syncthingUnit);
|
||||
connect(&service, &SyncthingService::systemdAvailableChanged, this, &SyncthingApplet::handleSystemdStatusChanged);
|
||||
connect(&service, &SyncthingService::errorOccurred, this, &SyncthingApplet::handleSystemdServiceError);
|
||||
#endif
|
||||
|
||||
|
@ -156,10 +157,11 @@ Data::SyncthingConnectionSettings *SyncthingApplet::connectionConfig(int index)
|
|||
|
||||
void SyncthingApplet::setCurrentConnectionConfigIndex(int index)
|
||||
{
|
||||
auto &settings = Settings::values().connection;
|
||||
if (index != m_currentConnectionConfig && index >= 0 && static_cast<unsigned>(index) <= settings.secondary.size()) {
|
||||
auto &selectedConfig = index == 0 ? settings.primary : settings.secondary[static_cast<unsigned>(index) - 1];
|
||||
m_connection.connect(selectedConfig);
|
||||
auto &settings = Settings::values();
|
||||
bool reconnectRequired = false;
|
||||
if (index != m_currentConnectionConfig && index >= 0 && static_cast<unsigned>(index) <= settings.connection.secondary.size()) {
|
||||
auto &selectedConfig = index == 0 ? settings.connection.primary : settings.connection.secondary[static_cast<unsigned>(index) - 1];
|
||||
reconnectRequired = m_connection.applySettings(selectedConfig);
|
||||
#ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
|
||||
if (m_webViewDlg) {
|
||||
m_webViewDlg->applySettings(selectedConfig);
|
||||
|
@ -169,9 +171,18 @@ void SyncthingApplet::setCurrentConnectionConfigIndex(int index)
|
|||
emit currentConnectionConfigIndexChanged(m_currentConnectionConfig = index);
|
||||
emit localChanged();
|
||||
}
|
||||
|
||||
// apply systemd settings, reconnect if required and possible
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
settings.systemd.apply(m_connection, currentConnectionConfig(), reconnectRequired);
|
||||
#else
|
||||
if (reconnectRequired || !m_connection.isConnected()) {
|
||||
m_connection.reconnect();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SyncthingApplet::isStartStopForServiceEnabled() const
|
||||
bool SyncthingApplet::isStartStopEnabled() const
|
||||
{
|
||||
return Settings::values().systemd.showButton;
|
||||
}
|
||||
|
@ -311,7 +322,7 @@ void SyncthingApplet::handleSettingsChanged()
|
|||
const auto &settings(Settings::values());
|
||||
|
||||
// apply notifiction settings
|
||||
settings.notifyOn.apply(m_notifier);
|
||||
settings.apply(m_notifier);
|
||||
|
||||
// apply appearance settings
|
||||
setSize(config.readEntry<QSize>("size", QSize(25, 25)));
|
||||
|
@ -349,12 +360,13 @@ void SyncthingApplet::handleDevicesChanged()
|
|||
void SyncthingApplet::handleInternalError(
|
||||
const QString &errorMsg, SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response)
|
||||
{
|
||||
if (InternalError::isRelevant(m_connection, category, networkError)) {
|
||||
if (!InternalError::isRelevant(m_connection, category, networkError)) {
|
||||
return;
|
||||
}
|
||||
InternalError error(errorMsg, request.url(), response);
|
||||
m_dbusNotifier.showInternalError(error);
|
||||
ErrorViewDialog::addError(move(error));
|
||||
}
|
||||
}
|
||||
|
||||
void SyncthingApplet::handleErrorsCleared()
|
||||
{
|
||||
|
@ -388,6 +400,14 @@ void SyncthingApplet::handleSystemdServiceError(const QString &context, const QS
|
|||
handleInternalError(tr("D-Bus error - unable to ") % context % QChar('\n') % name % QChar(':') % message, SyncthingErrorCategory::SpecificRequest,
|
||||
QNetworkReply::NoError, QNetworkRequest(), QByteArray());
|
||||
}
|
||||
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
void SyncthingApplet::handleSystemdStatusChanged()
|
||||
{
|
||||
Settings::values().systemd.apply(m_connection, currentConnectionConfig());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Plasmoid
|
||||
|
||||
K_EXPORT_PLASMA_APPLET_WITH_JSON(syncthing, Plasmoid::SyncthingApplet, "metadata.json")
|
||||
|
|
|
@ -56,7 +56,7 @@ class SyncthingApplet : public Plasma::Applet {
|
|||
Q_PROPERTY(QString currentConnectionConfigName READ currentConnectionConfigName NOTIFY currentConnectionConfigIndexChanged)
|
||||
Q_PROPERTY(int currentConnectionConfigIndex READ currentConnectionConfigIndex WRITE setCurrentConnectionConfigIndex NOTIFY
|
||||
currentConnectionConfigIndexChanged)
|
||||
Q_PROPERTY(bool startStopForServiceEnabled READ isStartStopForServiceEnabled NOTIFY settingsChanged)
|
||||
Q_PROPERTY(bool startStopEnabled READ isStartStopEnabled NOTIFY settingsChanged)
|
||||
Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
|
||||
Q_PROPERTY(bool notificationsAvailable READ areNotificationsAvailable NOTIFY notificationsAvailableChanged)
|
||||
|
||||
|
@ -82,7 +82,7 @@ public:
|
|||
Data::SyncthingConnectionSettings *currentConnectionConfig();
|
||||
Data::SyncthingConnectionSettings *connectionConfig(int index);
|
||||
void setCurrentConnectionConfigIndex(int index);
|
||||
bool isStartStopForServiceEnabled() const;
|
||||
bool isStartStopEnabled() const;
|
||||
QSize size() const;
|
||||
void setSize(const QSize &size);
|
||||
bool areNotificationsAvailable() const;
|
||||
|
@ -133,6 +133,9 @@ private Q_SLOTS:
|
|||
#endif
|
||||
void handleNewNotification(ChronoUtilities::DateTime when, const QString &msg);
|
||||
void handleSystemdServiceError(const QString &context, const QString &name, const QString &message);
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
void handleSystemdStatusChanged();
|
||||
#endif
|
||||
|
||||
private:
|
||||
Dialogs::AboutDialog *m_aboutDlg;
|
||||
|
|
|
@ -280,7 +280,7 @@ ColumnLayout {
|
|||
var nativeInterface = plasmoid.nativeInterface
|
||||
// the systemd unit status is only relevant when connected to the local instance
|
||||
if (!nativeInterface.local
|
||||
|| !nativeInterface.startStopForServiceEnabled) {
|
||||
|| !nativeInterface.startStopEnabled) {
|
||||
return "irrelevant"
|
||||
}
|
||||
// show start/stop button only when the configured unit is available
|
||||
|
|
|
@ -48,41 +48,48 @@ void handleSystemdServiceError(const QString &context, const QString &name, cons
|
|||
|
||||
int initSyncthingTray(bool windowed, bool waitForTray, const char *connectionConfig)
|
||||
{
|
||||
auto &v = Settings::values();
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
SyncthingService &service = syncthingService();
|
||||
service.setUnitName(v.systemd.syncthingUnit);
|
||||
QObject::connect(&service, &SyncthingService::errorOccurred, &handleSystemdServiceError);
|
||||
#endif
|
||||
const QString connectionConfigQStr = connectionConfig ? QString::fromLocal8Bit(connectionConfig) : QString();
|
||||
// get settings
|
||||
auto &settings = Settings::values();
|
||||
const auto connectionConfigQStr(connectionConfig ? QString::fromLocal8Bit(connectionConfig) : QString());
|
||||
|
||||
// handle "windowed" case
|
||||
if (windowed) {
|
||||
v.launcher.autostart();
|
||||
auto *trayWidget = new TrayWidget(connectionConfigQStr);
|
||||
settings.launcher.autostart();
|
||||
auto *const trayWidget = new TrayWidget(connectionConfigQStr);
|
||||
trayWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
trayWidget->show();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SYSTEMTRAYICON
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable() || waitForTray) {
|
||||
v.launcher.autostart();
|
||||
auto *trayIcon = new TrayIcon(connectionConfigQStr);
|
||||
// check whether system tray is available
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable() && !waitForTray) {
|
||||
QMessageBox::critical(nullptr, QApplication::applicationName(),
|
||||
QApplication::translate(
|
||||
"main", "The system tray is (currently) not available. You could open the tray menu as a regular window using the -w flag, though."));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// show tray icon
|
||||
settings.launcher.autostart();
|
||||
auto *const trayIcon = new TrayIcon(connectionConfigQStr, QApplication::instance());
|
||||
trayIcon->show();
|
||||
if (v.firstLaunch) {
|
||||
if (!settings.firstLaunch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// show "first launch" message box
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Information);
|
||||
msgBox.setText(
|
||||
QCoreApplication::translate("main", "You must configure how to connect to Syncthing when using Syncthing Tray the first time."));
|
||||
msgBox.setText(QCoreApplication::translate("main", "You must configure how to connect to Syncthing when using Syncthing Tray the first time."));
|
||||
msgBox.setInformativeText(QCoreApplication::translate(
|
||||
"main", "Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration."));
|
||||
msgBox.exec();
|
||||
trayIcon->trayMenu().widget()->showSettingsDialog();
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(nullptr, QApplication::applicationName(),
|
||||
QApplication::translate("main",
|
||||
"The system tray is (currently) not available. You could open the tray menu as a regular window using the -w flag, though."));
|
||||
return -1;
|
||||
}
|
||||
trayIcon->trayMenu().widget().showSettingsDialog();
|
||||
return 0;
|
||||
|
||||
#else
|
||||
// show error if system tray is not supported by Qt
|
||||
QMessageBox::critical(nullptr, QApplication::applicationName(),
|
||||
QApplication::translate("main",
|
||||
"The Qt libraries have not been built with tray icon support. You could open the tray menu as a regular "
|
||||
|
@ -90,13 +97,13 @@ int initSyncthingTray(bool windowed, bool waitForTray, const char *connectionCon
|
|||
return -2;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void trigger(bool tray, bool webUi)
|
||||
{
|
||||
if (!TrayWidget::instances().empty() && (tray || webUi)) {
|
||||
TrayWidget *trayWidget = TrayWidget::instances().front();
|
||||
if (TrayWidget::instances().empty() || !(tray || webUi)) {
|
||||
return;
|
||||
}
|
||||
auto *const trayWidget = TrayWidget::instances().front();
|
||||
if (webUi) {
|
||||
trayWidget->showWebUi();
|
||||
}
|
||||
|
@ -104,12 +111,9 @@ void trigger(bool tray, bool webUi)
|
|||
trayWidget->showAtCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int runApplication(int argc, const char *const *argv)
|
||||
{
|
||||
static bool firstRun = true;
|
||||
|
||||
// setup argument parser
|
||||
SET_APPLICATION_INFO;
|
||||
CMD_UTILS_CONVERT_ARGS_TO_UTF8;
|
||||
|
@ -140,45 +144,55 @@ int runApplication(int argc, const char *const *argv)
|
|||
if (!qtConfigArgs.qtWidgetsGuiArg().isPresent()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check whether runApplication() has been called for the first time
|
||||
static auto firstRun = true;
|
||||
if (firstRun) {
|
||||
firstRun = false;
|
||||
|
||||
// do first-time initializations
|
||||
SET_QT_APPLICATION_INFO;
|
||||
QApplication application(argc, const_cast<char **>(argv));
|
||||
QGuiApplication::setQuitOnLastWindowClosed(false);
|
||||
SingleInstance singleInstance(argc, argv);
|
||||
networkAccessManager().setParent(&singleInstance);
|
||||
QObject::connect(&singleInstance, &SingleInstance::newInstance, &runApplication);
|
||||
|
||||
Settings::restore();
|
||||
Settings::values().qt.apply();
|
||||
qtConfigArgs.applySettings(true);
|
||||
LOAD_QT_TRANSLATIONS;
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
SyncthingService &service = syncthingService();
|
||||
service.setUnitName(Settings::values().systemd.syncthingUnit);
|
||||
QObject::connect(&service, &SyncthingService::errorOccurred, &handleSystemdServiceError);
|
||||
#endif
|
||||
|
||||
int res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
||||
// show (first) tray icon and enter main event loop
|
||||
auto res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
||||
if (!res) {
|
||||
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
||||
res = application.exec();
|
||||
}
|
||||
|
||||
// perform cleanup, then terminate
|
||||
Settings::Launcher::terminate();
|
||||
Settings::save();
|
||||
return res;
|
||||
} else {
|
||||
}
|
||||
|
||||
// trigger actions if --webui or --trigger is present but don't create a new tray icon
|
||||
if (!TrayWidget::instances().empty() && (showWebUiArg.isPresent() || triggerArg.isPresent())) {
|
||||
// if --webui or --trigger is present don't create a new tray icon, just trigger actions
|
||||
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
||||
} else {
|
||||
const int res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create new/additional tray icon
|
||||
const auto res = initSyncthingTray(windowedArg.isPresent(), waitForTrayArg.isPresent(), connectionArg.firstValue());
|
||||
if (!res) {
|
||||
trigger(triggerArg.isPresent(), showWebUiArg.isPresent());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
|
|
@ -45,28 +45,28 @@ TrayIcon::TrayIcon(const QString &connectionConfig, QObject *parent)
|
|||
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);
|
||||
&QAction::triggered, &m_trayMenu.widget(), &TrayWidget::showWebUi);
|
||||
connect(m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("preferences-other"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/preferences-other.svg"))),
|
||||
tr("Settings")),
|
||||
&QAction::triggered, m_trayMenu.widget(), &TrayWidget::showSettingsDialog);
|
||||
&QAction::triggered, &m_trayMenu.widget(), &TrayWidget::showSettingsDialog);
|
||||
connect(m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("folder-sync"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/folder-sync.svg"))),
|
||||
tr("Rescan all")),
|
||||
&QAction::triggered, &m_trayMenu.widget()->connection(), &SyncthingConnection::rescanAllDirs);
|
||||
&QAction::triggered, &m_trayMenu.widget().connection(), &SyncthingConnection::rescanAllDirs);
|
||||
connect(m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("text-x-generic"), QIcon(QStringLiteral(":/icons/hicolor/scalable/mimetypes/text-x-generic.svg"))),
|
||||
tr("Log")),
|
||||
&QAction::triggered, m_trayMenu.widget(), &TrayWidget::showLog);
|
||||
&QAction::triggered, &m_trayMenu.widget(), &TrayWidget::showLog);
|
||||
m_errorsAction = m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("emblem-error"), QIcon(QStringLiteral(":/icons/hicolor/scalable/emblems/8/emblem-error.svg"))),
|
||||
tr("Show internal errors"));
|
||||
m_errorsAction->setVisible(false);
|
||||
connect(m_errorsAction, &QAction::triggered, this, &TrayIcon::showInternalErrorsDialog);
|
||||
m_contextMenu.addMenu(m_trayMenu.widget()->connectionsMenu());
|
||||
m_contextMenu.addMenu(m_trayMenu.widget().connectionsMenu());
|
||||
connect(m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("help-about"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/help-about.svg"))), tr("About")),
|
||||
&QAction::triggered, m_trayMenu.widget(), &TrayWidget::showAboutDialog);
|
||||
&QAction::triggered, &m_trayMenu.widget(), &TrayWidget::showAboutDialog);
|
||||
m_contextMenu.addSeparator();
|
||||
connect(m_contextMenu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("window-close"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/window-close.svg"))),
|
||||
|
@ -75,8 +75,8 @@ TrayIcon::TrayIcon(const QString &connectionConfig, QObject *parent)
|
|||
setContextMenu(&m_contextMenu);
|
||||
|
||||
// connect signals and slots
|
||||
const SyncthingConnection &connection = m_trayMenu.widget()->connection();
|
||||
const SyncthingNotifier ¬ifier = m_trayMenu.widget()->notifier();
|
||||
const SyncthingConnection &connection = m_trayMenu.widget().connection();
|
||||
const SyncthingNotifier ¬ifier = m_trayMenu.widget().notifier();
|
||||
connect(this, &TrayIcon::activated, this, &TrayIcon::handleActivated);
|
||||
connect(this, &TrayIcon::messageClicked, this, &TrayIcon::handleMessageClicked);
|
||||
connect(&connection, &SyncthingConnection::error, this, &TrayIcon::showInternalError);
|
||||
|
@ -89,8 +89,8 @@ TrayIcon::TrayIcon(const QString &connectionConfig, QObject *parent)
|
|||
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
|
||||
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);
|
||||
connect(&m_dbusNotifier, &DBusStatusNotifier::dismissNotificationsRequested, &m_trayMenu.widget(), &TrayWidget::dismissNotifications);
|
||||
connect(&m_dbusNotifier, &DBusStatusNotifier::showNotificationsRequested, &m_trayMenu.widget(), &TrayWidget::showNotifications);
|
||||
connect(&m_dbusNotifier, &DBusStatusNotifier::errorDetailsRequested, this, &TrayIcon::showInternalErrorsDialog);
|
||||
connect(¬ifier, &SyncthingNotifier::connected, &m_dbusNotifier, &DBusStatusNotifier::hideDisconnect);
|
||||
#endif
|
||||
|
@ -120,7 +120,7 @@ void TrayIcon::handleActivated(QSystemTrayIcon::ActivationReason reason)
|
|||
// can't catch that event on Plasma 5 anyways
|
||||
break;
|
||||
case QSystemTrayIcon::MiddleClick:
|
||||
m_trayMenu.widget()->showWebUi();
|
||||
m_trayMenu.widget().showWebUi();
|
||||
break;
|
||||
case QSystemTrayIcon::Trigger: {
|
||||
m_trayMenu.showAtCursor();
|
||||
|
@ -136,7 +136,7 @@ void TrayIcon::handleMessageClicked()
|
|||
case TrayIconMessageClickedAction::None:
|
||||
return;
|
||||
case TrayIconMessageClickedAction::DismissNotification:
|
||||
m_trayMenu.widget()->dismissNotifications();
|
||||
m_trayMenu.widget().dismissNotifications();
|
||||
break;
|
||||
case TrayIconMessageClickedAction::ShowInternalErrors:
|
||||
showInternalErrorsDialog();
|
||||
|
@ -178,7 +178,9 @@ void TrayIcon::handleErrorsCleared()
|
|||
void TrayIcon::showInternalError(
|
||||
const QString &errorMsg, SyncthingErrorCategory category, int networkError, const QNetworkRequest &request, const QByteArray &response)
|
||||
{
|
||||
if (InternalError::isRelevant(m_trayMenu.widget()->connection(), category, networkError)) {
|
||||
if (!InternalError::isRelevant(m_trayMenu.widget().connection(), category, networkError)) {
|
||||
return;
|
||||
}
|
||||
InternalError error(errorMsg, request.url(), response);
|
||||
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
|
||||
if (Settings::values().dbusNotifications) {
|
||||
|
@ -192,7 +194,6 @@ void TrayIcon::showInternalError(
|
|||
ErrorViewDialog::addError(move(error));
|
||||
m_errorsAction->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TrayIcon::showSyncthingNotification(ChronoUtilities::DateTime when, const QString &message)
|
||||
{
|
||||
|
@ -215,7 +216,7 @@ void TrayIcon::showSyncthingNotification(ChronoUtilities::DateTime when, const Q
|
|||
|
||||
void TrayIcon::updateStatusIconAndText()
|
||||
{
|
||||
const StatusInfo statusInfo(trayMenu().widget()->connection());
|
||||
const StatusInfo statusInfo(trayMenu().widget().connection());
|
||||
if (statusInfo.additionalStatusText().isEmpty()) {
|
||||
setToolTip(statusInfo.statusText());
|
||||
} else {
|
||||
|
|
|
@ -15,8 +15,9 @@ TrayMenu::TrayMenu(const QString &connectionConfig, TrayIcon *trayIcon, QWidget
|
|||
: QMenu(parent)
|
||||
, m_trayIcon(trayIcon)
|
||||
{
|
||||
auto *menuLayout = new QHBoxLayout;
|
||||
menuLayout->setMargin(0), menuLayout->setSpacing(0);
|
||||
auto *const menuLayout = new QHBoxLayout;
|
||||
menuLayout->setMargin(0);
|
||||
menuLayout->setSpacing(0);
|
||||
menuLayout->addWidget(m_trayWidget = new TrayWidget(connectionConfig, this));
|
||||
setLayout(menuLayout);
|
||||
setPlatformMenu(nullptr);
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
TrayMenu(const QString &connectionConfig = QString(), TrayIcon *trayIcon = nullptr, QWidget *parent = nullptr);
|
||||
|
||||
QSize sizeHint() const;
|
||||
TrayWidget *widget();
|
||||
TrayWidget &widget();
|
||||
TrayIcon *icon();
|
||||
|
||||
public slots:
|
||||
|
@ -26,9 +26,9 @@ private:
|
|||
TrayIcon *m_trayIcon;
|
||||
};
|
||||
|
||||
inline TrayWidget *TrayMenu::widget()
|
||||
inline TrayWidget &TrayMenu::widget()
|
||||
{
|
||||
return m_trayWidget;
|
||||
return *m_trayWidget;
|
||||
}
|
||||
|
||||
inline TrayIcon *TrayMenu::icon()
|
||||
|
|
|
@ -365,15 +365,13 @@ void TrayWidget::applySettings(const QString &connectionConfig)
|
|||
const bool reconnectRequired = m_connection.applySettings(*m_selectedConnection);
|
||||
|
||||
// apply notifiction settings
|
||||
settings.notifyOn.apply(m_notifier);
|
||||
settings.apply(m_notifier);
|
||||
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
// reconnect to apply settings considering systemd
|
||||
const bool couldReconnect = handleSystemdStatusChanged();
|
||||
if (reconnectRequired && couldReconnect) {
|
||||
m_connection.reconnect();
|
||||
}
|
||||
// apply systemd settings, also enforce reconnect if required and possible
|
||||
applySystemdSettings(reconnectRequired);
|
||||
#else
|
||||
// reconnect if required, not checking whether possible
|
||||
if (reconnectRequired) {
|
||||
m_connection.reconnect();
|
||||
}
|
||||
|
@ -500,56 +498,43 @@ void TrayWidget::updateTraffic()
|
|||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
bool TrayWidget::handleSystemdStatusChanged()
|
||||
{
|
||||
const SyncthingService &service = syncthingService();
|
||||
const Settings::Systemd &settings = Settings::values().systemd;
|
||||
const bool serviceRelevant = service.isSystemdAvailable() && isLocal(QUrl(m_connection.syncthingUrl()));
|
||||
bool couldConnectNow = true;
|
||||
return applySystemdSettings();
|
||||
}
|
||||
|
||||
if (serviceRelevant) {
|
||||
const bool isRunning = service.isRunning();
|
||||
if (settings.showButton) {
|
||||
bool TrayWidget::applySystemdSettings(bool reconnectRequired)
|
||||
{
|
||||
// update connection
|
||||
const Settings::Systemd &systemdSettings(Settings::values().systemd);
|
||||
bool isServiceRelevant, isServiceRunning;
|
||||
tie(isServiceRelevant, isServiceRunning) = systemdSettings.apply(m_connection, m_selectedConnection, reconnectRequired);
|
||||
|
||||
if (isServiceRelevant) {
|
||||
// update start/stop button
|
||||
if (systemdSettings.showButton) {
|
||||
m_ui->startStopPushButton->setVisible(true);
|
||||
if (isRunning) {
|
||||
const auto &unitName(syncthingService().unitName());
|
||||
if (isServiceRunning) {
|
||||
m_ui->startStopPushButton->setText(tr("Stop"));
|
||||
m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user stop ") + service.unitName());
|
||||
m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user stop ") + unitName);
|
||||
m_ui->startStopPushButton->setIcon(
|
||||
QIcon::fromTheme(QStringLiteral("process-stop"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/process-stop.svg"))));
|
||||
} else {
|
||||
m_ui->startStopPushButton->setText(tr("Start"));
|
||||
m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user start ") + service.unitName());
|
||||
m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user start ") + unitName);
|
||||
m_ui->startStopPushButton->setIcon(
|
||||
QIcon::fromTheme(QStringLiteral("system-run"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/system-run.svg"))));
|
||||
}
|
||||
}
|
||||
if (settings.considerForReconnect) {
|
||||
if (isRunning && m_selectedConnection) {
|
||||
// auto-reconnect might have been disabled when unit was inactive before, so re-enable it according current connection settings
|
||||
m_connection.setAutoReconnectInterval(m_selectedConnection->reconnectInterval);
|
||||
if (!m_connection.isConnected()) {
|
||||
// FIXME: This will fail if Syncthing has just been started and isn't ready yet
|
||||
m_connection.connect();
|
||||
}
|
||||
} else {
|
||||
// disable auto-reconnect if unit isn't running
|
||||
m_connection.setAutoReconnectInterval(0);
|
||||
couldConnectNow = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings.showButton || !serviceRelevant) {
|
||||
if (!systemdSettings.showButton || !isServiceRelevant) {
|
||||
m_ui->startStopPushButton->setVisible(false);
|
||||
}
|
||||
if ((!settings.considerForReconnect || !serviceRelevant) && m_selectedConnection) {
|
||||
m_connection.setAutoReconnectInterval(m_selectedConnection->reconnectInterval);
|
||||
}
|
||||
|
||||
return couldConnectNow;
|
||||
return isServiceRelevant && isServiceRunning;
|
||||
}
|
||||
|
||||
void TrayWidget::connectIfServiceRunning()
|
||||
{
|
||||
if (Settings::values().systemd.considerForReconnect && isLocal(QUrl(m_connection.syncthingUrl())) && syncthingService().isRunning()) {
|
||||
if (Settings::values().systemd.considerForReconnect && m_connection.isLocal() && syncthingService().isRunning()) {
|
||||
m_connection.connect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ private slots:
|
|||
void updateTraffic();
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
bool handleSystemdStatusChanged();
|
||||
bool applySystemdSettings(bool reconnectRequired = false);
|
||||
void connectIfServiceRunning();
|
||||
#endif
|
||||
#ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "../settings/settings.h"
|
||||
|
||||
#include "../../connector/syncthingconnection.h"
|
||||
#include "../../connector/syncthingprocess.h"
|
||||
#include "../../connector/syncthingservice.h"
|
||||
#include "../../connector/utils.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
|
||||
|
@ -12,21 +12,51 @@ using namespace Data;
|
|||
|
||||
namespace QtGui {
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the error is relevant. Only in this case a notification for the error should be shown.
|
||||
*/
|
||||
bool InternalError::isRelevant(const SyncthingConnection &connection, SyncthingErrorCategory category, int networkError)
|
||||
{
|
||||
// ignore overall connection errors when auto reconnect tries >= 1
|
||||
if (category != SyncthingErrorCategory::OverallConnection && connection.autoReconnectTries() >= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ignore errors when disabled in settings
|
||||
const auto &settings = Settings::values();
|
||||
if (!settings.notifyOn.internalErrors) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip further considerations if connection is remote
|
||||
if (!connection.isLocal()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// consider process/launcher or systemd unit status
|
||||
const auto remoteHostClosed(networkError == QNetworkReply::RemoteHostClosedError);
|
||||
// ignore "remote host closed" error if we've just stopped Syncthing ourselves
|
||||
const SyncthingProcess &process(syncthingProcess());
|
||||
if (settings.launcher.considerForReconnect && remoteHostClosed && process.isManuallyStopped()) {
|
||||
return false;
|
||||
}
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
const SyncthingService &service = syncthingService();
|
||||
const bool serviceRelevant = service.isSystemdAvailable() && isLocal(QUrl(connection.syncthingUrl()));
|
||||
const SyncthingService &service(syncthingService());
|
||||
if (settings.systemd.considerForReconnect && remoteHostClosed && service.isManuallyStopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ignore inavailability after start or standby-wakeup
|
||||
if (settings.ignoreInavailabilityAfterStart && networkError == QNetworkReply::ConnectionRefusedError) {
|
||||
if (process.isRunning() && !service.isActiveWithoutSleepFor(process.activeSince(), settings.ignoreInavailabilityAfterStart)) {
|
||||
return false;
|
||||
}
|
||||
if (service.isRunning() && !service.isActiveWithoutSleepFor(settings.ignoreInavailabilityAfterStart)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return settings.notifyOn.internalErrors && (connection.autoReconnectTries() < 1 || category != SyncthingErrorCategory::OverallConnection)
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
&& (!settings.systemd.considerForReconnect || !serviceRelevant
|
||||
|| !(networkError == QNetworkReply::RemoteHostClosedError && service.isManuallyStopped()))
|
||||
&& (settings.ignoreInavailabilityAfterStart == 0
|
||||
|| !(networkError == QNetworkReply::ConnectionRefusedError && service.isRunning()
|
||||
&& !service.isActiveWithoutSleepFor(settings.ignoreInavailabilityAfterStart)))
|
||||
#endif
|
||||
;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "./settings.h"
|
||||
#include "../../connector/syncthingnotifier.h"
|
||||
#include "../../connector/syncthingprocess.h"
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
#include "../../connector/syncthingconnection.h"
|
||||
#include "../../connector/syncthingservice.h"
|
||||
#endif
|
||||
|
||||
// use meta-data of syncthingtray application here
|
||||
#include "resources/../../tray/resources/config.h"
|
||||
|
@ -295,19 +299,70 @@ void save()
|
|||
/*!
|
||||
* \brief Applies the notification settings on the specified \a notifier.
|
||||
*/
|
||||
void NotifyOn::apply(SyncthingNotifier ¬ifier) const
|
||||
void Settings::apply(SyncthingNotifier ¬ifier) const
|
||||
{
|
||||
auto notifications(SyncthingHighLevelNotification::None);
|
||||
if (disconnect) {
|
||||
if (notifyOn.disconnect) {
|
||||
notifications |= SyncthingHighLevelNotification::ConnectedDisconnected;
|
||||
}
|
||||
if (localSyncComplete) {
|
||||
if (notifyOn.localSyncComplete) {
|
||||
notifications |= SyncthingHighLevelNotification::LocalSyncComplete;
|
||||
}
|
||||
if (remoteSyncComplete) {
|
||||
if (notifyOn.remoteSyncComplete) {
|
||||
notifications |= SyncthingHighLevelNotification::RemoteSyncComplete;
|
||||
}
|
||||
notifier.setEnabledNotifications(notifications);
|
||||
notifier.setIgnoreInavailabilityAfterStart(ignoreInavailabilityAfterStart);
|
||||
}
|
||||
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
/*!
|
||||
* \brief Applies the systemd settings to the specified \a connection considering the status of the global SyncthingService instance.
|
||||
* \remarks
|
||||
* - Called by SyncthingApplet and TrayWidget when the status of the SyncthingService changes.
|
||||
* - \a currentConnectionSettings might be nullptr.
|
||||
* - Currently this is only about the auto-reconnect interval and connecting instantly.
|
||||
* \returns Returns whether the service is relevant and running.
|
||||
*/
|
||||
std::tuple<bool, bool> Systemd::apply(
|
||||
Data::SyncthingConnection &connection, const SyncthingConnectionSettings *currentConnectionSettings, bool reconnectRequired) const
|
||||
{
|
||||
const SyncthingService &service(syncthingService());
|
||||
const auto isRelevant = service.isSystemdAvailable() && connection.isLocal();
|
||||
const auto isRunning = service.isRunning();
|
||||
|
||||
if (currentConnectionSettings && (!considerForReconnect || !isRelevant || isRunning)) {
|
||||
// ensure auto-reconnect is configured according to settings
|
||||
connection.setAutoReconnectInterval(currentConnectionSettings->reconnectInterval);
|
||||
} else {
|
||||
// disable auto-reconnect regardless of the overall settings
|
||||
connection.setAutoReconnectInterval(0);
|
||||
}
|
||||
|
||||
// connect instantly if service is running
|
||||
if (considerForReconnect && isRelevant) {
|
||||
constexpr auto minActiveTimeInSeconds(5);
|
||||
if (reconnectRequired) {
|
||||
if (service.isActiveWithoutSleepFor(minActiveTimeInSeconds)) {
|
||||
connection.reconnect();
|
||||
} else {
|
||||
// give the service (which has just started) a few seconds to initialize
|
||||
connection.reconnectLater(minActiveTimeInSeconds * 1000);
|
||||
}
|
||||
} else if (isRunning && !connection.isConnected()) {
|
||||
if (service.isActiveWithoutSleepFor(minActiveTimeInSeconds)) {
|
||||
connection.connect();
|
||||
} else {
|
||||
// give the service (which has just started) a few seconds to initialize
|
||||
connection.connectLater(minActiveTimeInSeconds * 1000);
|
||||
}
|
||||
}
|
||||
} else if (reconnectRequired) {
|
||||
connection.reconnect();
|
||||
}
|
||||
|
||||
return make_tuple(isRelevant, isRunning);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Settings
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QString>
|
||||
#include <QTabWidget>
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace Dialogs {
|
||||
|
@ -24,6 +25,7 @@ class QtSettings;
|
|||
namespace Data {
|
||||
class SyncthingProcess;
|
||||
class SyncthingNotifier;
|
||||
class SyncthingConnection;
|
||||
} // namespace Data
|
||||
|
||||
namespace Settings {
|
||||
|
@ -39,8 +41,6 @@ struct SYNCTHINGWIDGETS_EXPORT NotifyOn {
|
|||
bool localSyncComplete = false;
|
||||
bool remoteSyncComplete = false;
|
||||
bool syncthingErrors = true;
|
||||
|
||||
void apply(Data::SyncthingNotifier ¬ifier) const;
|
||||
};
|
||||
|
||||
struct SYNCTHINGWIDGETS_EXPORT Appearance {
|
||||
|
@ -67,6 +67,7 @@ struct SYNCTHINGWIDGETS_EXPORT Launcher {
|
|||
#endif
|
||||
QString syncthingArgs;
|
||||
QHash<QString, ToolParameter> tools;
|
||||
bool considerForReconnect = false;
|
||||
QString syncthingCmd() const;
|
||||
QString toolCmd(const QString &tool) const;
|
||||
static Data::SyncthingProcess &toolProcess(const QString &tool);
|
||||
|
@ -79,6 +80,11 @@ struct SYNCTHINGWIDGETS_EXPORT Systemd {
|
|||
QString syncthingUnit = QStringLiteral("syncthing.service");
|
||||
bool showButton = false;
|
||||
bool considerForReconnect = false;
|
||||
|
||||
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
||||
std::tuple<bool, bool> apply(Data::SyncthingConnection &connection, const Data::SyncthingConnectionSettings *currentConnectionSettings,
|
||||
bool preventReconnect = false) const;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -108,6 +114,8 @@ struct SYNCTHINGWIDGETS_EXPORT Settings {
|
|||
WebView webView;
|
||||
#endif
|
||||
Dialogs::QtSettings qt;
|
||||
|
||||
void apply(Data::SyncthingNotifier ¬ifier) const;
|
||||
};
|
||||
|
||||
Settings SYNCTHINGWIDGETS_EXPORT &values();
|
||||
|
|
Loading…
Reference in New Issue