Improve systemd integration

* Allow using systemd unit status to better handle
  reconnect attempts to local instance
* Misc adjustments
This commit is contained in:
Martchus 2016-12-27 16:16:12 +01:00
parent 1c2c77b4ec
commit 3cadd8cbcb
9 changed files with 94 additions and 45 deletions

View File

@ -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]);

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -66,7 +66,8 @@ struct Launcher
struct Systemd
{
QString syncthingUnit = QStringLiteral("syncthing.service");
bool showButton = true;
bool showButton = false;
bool considerForReconnect = false;
};
#endif

View File

@ -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

View File

@ -15,7 +15,23 @@
</font>
</property>
<property name="text">
<string>Show start/stop button on tray for local instance when specified unit available</string>
<string>Show start/stop button on tray for local instance when systemd is available</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="considerForReconnectCheckBox">
<property name="text">
<string>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</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@ -50,20 +66,7 @@
<item row="0" column="1">
<widget class="Widgets::ClearLineEdit" name="syncthingUnitLineEdit"/>
</item>
<item row="1" column="1">
<widget class="Line" name="line1">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="0">
<widget class="QLabel" name="descriptionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@ -76,7 +79,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="1" column="1">
<layout class="QHBoxLayout" name="descriptionHorizontalLayout">
<item>
<widget class="QLabel" name="descriptionValueLabel">
@ -99,7 +102,7 @@
</item>
</layout>
</item>
<item row="3" column="0">
<item row="2" column="0">
<widget class="QLabel" name="statusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@ -112,7 +115,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<layout class="QHBoxLayout" name="statusHorizontalLayout">
<item>
<widget class="QWidget" name="statusIndicator" native="true">
@ -176,7 +179,7 @@
</item>
</layout>
</item>
<item row="4" column="0">
<item row="3" column="0">
<widget class="QLabel" name="unitFileStateLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@ -189,7 +192,7 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="3" column="1">
<layout class="QHBoxLayout" name="unitFileStateHorizontalLayout">
<item>
<widget class="QWidget" name="enabledIndicator" native="true">

View File

@ -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) {

View File

@ -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();