From 3cadd8cbcb058bd649b26db65296452eedf09cbe Mon Sep 17 00:00:00 2001 From: Martchus Date: Tue, 27 Dec 2016 16:16:12 +0100 Subject: [PATCH] Improve systemd integration * Allow using systemd unit status to better handle reconnect attempts to local instance * Misc adjustments --- connector/syncthingservice.cpp | 17 +++++++--- connector/syncthingservice.h | 1 + tray/application/main.cpp | 2 +- tray/application/settings.cpp | 2 ++ tray/application/settings.h | 3 +- tray/gui/settingsdialog.cpp | 8 +++-- tray/gui/systemdoptionpage.ui | 43 ++++++++++++------------ tray/gui/traywidget.cpp | 60 +++++++++++++++++++++++++--------- tray/gui/traywidget.h | 3 +- 9 files changed, 94 insertions(+), 45 deletions(-) diff --git a/connector/syncthingservice.cpp b/connector/syncthingservice.cpp index 23a9ef5..a73e3e0 100644 --- a/connector/syncthingservice.cpp +++ b/connector/syncthingservice.cpp @@ -61,6 +61,8 @@ SyncthingService::SyncthingService(QObject *parent) : connect(s_manager, &OrgFreedesktopSystemd1ManagerInterface::UnitNew, this, &SyncthingService::handleUnitAdded); connect(s_manager, &OrgFreedesktopSystemd1ManagerInterface::UnitRemoved, this, &SyncthingService::handleUnitRemoved); m_serviceWatcher = new QDBusServiceWatcher(s_manager->service(), s_manager->connection()); + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &SyncthingService::handleServiceRegisteredChanged); + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &SyncthingService::handleServiceRegisteredChanged); } void SyncthingService::setUnitName(const QString &unitName) @@ -91,18 +93,18 @@ bool SyncthingService::isUnitAvailable() const void SyncthingService::setRunning(bool running) { if(running) { - registerErrorHandler(s_manager->StartUnit(m_unitName, QStringLiteral("replace")), QT_TR_NOOP_UTF8("starting unit")); + registerErrorHandler(s_manager->StartUnit(m_unitName, QStringLiteral("replace")), QT_TR_NOOP_UTF8("start unit")); } else { - registerErrorHandler(s_manager->StopUnit(m_unitName, QStringLiteral("replace")), QT_TR_NOOP_UTF8("stopping unit")); + registerErrorHandler(s_manager->StopUnit(m_unitName, QStringLiteral("replace")), QT_TR_NOOP_UTF8("stop unit")); } } void SyncthingService::setEnabled(bool enabled) { if(enabled) { - registerErrorHandler(s_manager->EnableUnitFiles(QStringList(m_unitName), false, true), QT_TR_NOOP_UTF8("enabling unit")); + registerErrorHandler(s_manager->EnableUnitFiles(QStringList(m_unitName), false, true), QT_TR_NOOP_UTF8("enable unit")); } else { - registerErrorHandler(s_manager->DisableUnitFiles(QStringList(m_unitName), false), QT_TR_NOOP_UTF8("disabling unit")); + registerErrorHandler(s_manager->DisableUnitFiles(QStringList(m_unitName), false), QT_TR_NOOP_UTF8("disable unit")); } } @@ -164,6 +166,13 @@ void SyncthingService::handleError(const char *context, QDBusPendingCallWatcher } } +void SyncthingService::handleServiceRegisteredChanged(const QString &service) +{ + if(service == s_manager->service()) { + emit systemdAvailableChanged(s_manager->isValid()); + } +} + bool SyncthingService::handlePropertyChanged(QString &variable, void (SyncthingService::*signal)(const QString &), const QString &propertyName, const QVariantMap &changedProperties, const QStringList &invalidatedProperties) { const QVariant valueVariant(changedProperties[propertyName]); diff --git a/connector/syncthingservice.h b/connector/syncthingservice.h index bc42fed..0657376 100644 --- a/connector/syncthingservice.h +++ b/connector/syncthingservice.h @@ -81,6 +81,7 @@ private Q_SLOTS: void handleUnitGet(QDBusPendingCallWatcher *watcher); void handlePropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); void handleError(const char *error, QDBusPendingCallWatcher *watcher); + void handleServiceRegisteredChanged(const QString &service); void setUnit(const QDBusObjectPath &objectPath); void setProperties(const QString &activeState, const QString &subState, const QString &unitFileState, const QString &description); diff --git a/tray/application/main.cpp b/tray/application/main.cpp index f952570..4c8cb9f 100644 --- a/tray/application/main.cpp +++ b/tray/application/main.cpp @@ -38,7 +38,7 @@ void handleSystemdServiceError(const QString &context, const QString &name, cons QMessageBox msgBox; msgBox.setIcon(QMessageBox::Critical); msgBox.setText(QCoreApplication::translate("main", "Unable to ") + context); - msgBox.setInformativeText(name % QStringLiteral(": ") % message); + msgBox.setInformativeText(name % QStringLiteral(":\n") % message); msgBox.exec(); } #endif diff --git a/tray/application/settings.cpp b/tray/application/settings.cpp index b932833..77dcc44 100644 --- a/tray/application/settings.cpp +++ b/tray/application/settings.cpp @@ -100,6 +100,7 @@ void restore() auto &systemd = v.systemd; systemd.syncthingUnit = settings.value(QStringLiteral("syncthingUnit"), systemd.syncthingUnit).toString(); systemd.showButton = settings.value(QStringLiteral("showButton"), systemd.showButton).toBool(); + systemd.considerForReconnect = settings.value(QStringLiteral("considerForReconnect"), systemd.considerForReconnect).toBool(); #endif settings.endGroup(); @@ -167,6 +168,7 @@ void save() const auto &systemd = v.systemd; settings.setValue(QStringLiteral("syncthingUnit"), systemd.syncthingUnit); settings.setValue(QStringLiteral("showButton"), systemd.showButton); + settings.setValue(QStringLiteral("considerForReconnect"), systemd.considerForReconnect); #endif settings.endGroup(); diff --git a/tray/application/settings.h b/tray/application/settings.h index 819a395..7aeb6ff 100644 --- a/tray/application/settings.h +++ b/tray/application/settings.h @@ -66,7 +66,8 @@ struct Launcher struct Systemd { QString syncthingUnit = QStringLiteral("syncthing.service"); - bool showButton = true; + bool showButton = false; + bool considerForReconnect = false; }; #endif diff --git a/tray/gui/settingsdialog.cpp b/tray/gui/settingsdialog.cpp index 20b593b..c308156 100644 --- a/tray/gui/settingsdialog.cpp +++ b/tray/gui/settingsdialog.cpp @@ -596,6 +596,7 @@ bool SystemdOptionPage::apply() auto &settings = values().systemd; settings.syncthingUnit = ui()->syncthingUnitLineEdit->text(); settings.showButton = ui()->showButtonCheckBox->isChecked(); + settings.considerForReconnect = ui()->considerForReconnectCheckBox->isChecked(); } return true; } @@ -606,6 +607,7 @@ void SystemdOptionPage::reset() const auto &settings = values().systemd; ui()->syncthingUnitLineEdit->setText(settings.syncthingUnit); ui()->showButtonCheckBox->setChecked(settings.showButton); + ui()->considerForReconnectCheckBox->setChecked(settings.considerForReconnect); handleDescriptionChanged(m_service.description()); handleStatusChanged(m_service.activeState(), m_service.subState()); handleEnabledChanged(m_service.unitFileState()); @@ -614,7 +616,7 @@ void SystemdOptionPage::reset() void SystemdOptionPage::handleDescriptionChanged(const QString &description) { - ui()->descriptionValueLabel->setText(description.isEmpty() ? QCoreApplication::translate("QtGui::SystemdOptionPage", "specified unit is unknown") : description); + ui()->descriptionValueLabel->setText(description.isEmpty() ? QCoreApplication::translate("QtGui::SystemdOptionPage", "specified unit is either inactive or doesn't exist") : description); } void setIndicatorColor(QWidget *indicator, const QColor &color) @@ -642,7 +644,7 @@ void SystemdOptionPage::handleStatusChanged(const QString &activeState, const QS ? Colors::green(values().appearance.brightTextColors) : Colors::red(values().appearance.brightTextColors)) ); - ui()->startPushButton->setVisible(!status.isEmpty() && !isRunning); + ui()->startPushButton->setVisible(!isRunning); ui()->stopPushButton->setVisible(!status.isEmpty() && isRunning); } @@ -653,7 +655,7 @@ void SystemdOptionPage::handleEnabledChanged(const QString &unitFileState) setIndicatorColor(ui()->enabledIndicator, isEnabled ? Colors::green(values().appearance.brightTextColors) : Colors::gray(values().appearance.brightTextColors)); - ui()->enablePushButton->setVisible(!unitFileState.isEmpty() && !isEnabled); + ui()->enablePushButton->setVisible(!isEnabled); ui()->disablePushButton->setVisible(!unitFileState.isEmpty() && isEnabled); } #endif diff --git a/tray/gui/systemdoptionpage.ui b/tray/gui/systemdoptionpage.ui index 6ac091e..0d5f419 100644 --- a/tray/gui/systemdoptionpage.ui +++ b/tray/gui/systemdoptionpage.ui @@ -15,7 +15,23 @@ - Show start/stop button on tray for local instance when specified unit available + Show start/stop button on tray for local instance when systemd is available + + + + + + + Consider systemd unit status for reconnect attempts to local instance + • Don't reconnect when unit not active/running + • Try to reconnect when unit becomes active/running + + + + + + + Qt::Horizontal @@ -50,20 +66,7 @@ - - - - - 0 - 0 - - - - Qt::Horizontal - - - - + @@ -76,7 +79,7 @@ - + @@ -99,7 +102,7 @@ - + @@ -112,7 +115,7 @@ - + @@ -176,7 +179,7 @@ - + @@ -189,7 +192,7 @@ - + diff --git a/tray/gui/traywidget.cpp b/tray/gui/traywidget.cpp index efed67a..4ba9edf 100644 --- a/tray/gui/traywidget.cpp +++ b/tray/gui/traywidget.cpp @@ -146,7 +146,8 @@ TrayWidget::TrayWidget(TrayMenu *parent) : #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD const SyncthingService &service = syncthingService(); connect(m_ui->startStopPushButton, &QPushButton::clicked, &service, &SyncthingService::toggleRunning); - connect(&service, &SyncthingService::stateChanged, this, &TrayWidget::updateStartStopButton); + connect(&service, &SyncthingService::systemdAvailableChanged, this, &TrayWidget::handleSystemdStatusChanged); + connect(&service, &SyncthingService::stateChanged, this, &TrayWidget::handleSystemdStatusChanged); #endif } @@ -385,7 +386,7 @@ void TrayWidget::applySettings() // systemd #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD - instance->updateStartStopButton(); + instance->handleSystemdStatusChanged(); #endif // update visual appearance @@ -493,25 +494,54 @@ void TrayWidget::updateTraffic() } #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD -void TrayWidget::updateStartStopButton() +void TrayWidget::handleSystemdStatusChanged() { const SyncthingService &service = syncthingService(); const Settings::Systemd &settings = Settings::values().systemd; + const bool serviceRelevant = service.isSystemdAvailable() && isLocal(QUrl(m_connection.syncthingUrl())); - if(settings.showButton && service.isUnitAvailable() && m_selectedConnection && isLocal(QUrl(m_selectedConnection->syncthingUrl))) { - m_ui->startStopPushButton->setVisible(true); - if(service.isRunning()) { - m_ui->startStopPushButton->setText(tr("Stop")); - m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user stop ") + service.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->setIcon(QIcon::fromTheme(QStringLiteral("system-run"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/system-run.svg")))); + if(serviceRelevant) { + const bool isRunning = service.isRunning(); + if(settings.showButton) { + m_ui->startStopPushButton->setVisible(true); + if(isRunning) { + m_ui->startStopPushButton->setText(tr("Stop")); + m_ui->startStopPushButton->setToolTip(QStringLiteral("systemctl --user stop ") + service.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->setIcon(QIcon::fromTheme(QStringLiteral("system-run"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/system-run.svg")))); + } } - } else { + 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); + // and reconnect in 5 seconds (Syncthing needs a few seconds till the API becomes available) + QTimer::singleShot(5000, Qt::VeryCoarseTimer, this, &TrayWidget::connectIfServiceRunning); + } else { + // disable auto-reconnect if unit isn't running + m_connection.setAutoReconnectInterval(0); + } + } + } + + if(!settings.showButton || !serviceRelevant) { m_ui->startStopPushButton->setVisible(false); } + if((!settings.considerForReconnect || !serviceRelevant) && m_selectedConnection) { + m_connection.setAutoReconnectInterval(m_selectedConnection->reconnectInterval); + } +} + +void TrayWidget::connectIfServiceRunning() +{ + if(Settings::values().systemd.considerForReconnect + && isLocal(QUrl(m_connection.syncthingUrl())) + && syncthingService().isRunning()) { + m_connection.connect(); + } } #endif @@ -538,7 +568,7 @@ void TrayWidget::handleConnectionSelected(QAction *connectionAction) m_ui->connectionsPushButton->setText(m_selectedConnection->label); m_connection.reconnect(*m_selectedConnection); #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD - updateStartStopButton(); + handleSystemdStatusChanged(); #endif #ifndef SYNCTHINGTRAY_NO_WEBVIEW if(m_webViewDlg) { diff --git a/tray/gui/traywidget.h b/tray/gui/traywidget.h index 5cdea8c..4427a9d 100644 --- a/tray/gui/traywidget.h +++ b/tray/gui/traywidget.h @@ -72,7 +72,8 @@ private slots: void changeStatus(); void updateTraffic(); #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD - void updateStartStopButton(); + void handleSystemdStatusChanged(); + void connectIfServiceRunning(); #endif #ifndef SYNCTHINGTRAY_NO_WEBVIEW void handleWebViewDeleted();