2016-08-25 00:45:32 +02:00
|
|
|
#include "./settings.h"
|
2018-04-11 23:15:15 +02:00
|
|
|
|
|
|
|
#include "../misc/syncthingkiller.h"
|
|
|
|
#include "../misc/syncthinglauncher.h"
|
|
|
|
|
2019-07-13 13:21:25 +02:00
|
|
|
#include "../../connector/syncthingconnection.h"
|
2018-03-31 22:31:28 +02:00
|
|
|
#include "../../connector/syncthingnotifier.h"
|
2017-03-17 00:38:42 +01:00
|
|
|
#include "../../connector/syncthingprocess.h"
|
2019-07-13 12:57:35 +02:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
2018-04-02 20:26:00 +02:00
|
|
|
#include "../../connector/syncthingservice.h"
|
|
|
|
#endif
|
2016-09-01 16:34:30 +02:00
|
|
|
|
2017-04-23 18:27:31 +02:00
|
|
|
// use meta-data of syncthingtray application here
|
|
|
|
#include "resources/../../tray/resources/config.h"
|
2017-02-20 19:41:34 +01:00
|
|
|
|
2016-08-25 00:45:32 +02:00
|
|
|
#include <qtutilities/settingsdialog/qtsettings.h>
|
2016-12-11 17:58:58 +01:00
|
|
|
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
|
2017-05-01 03:34:43 +02:00
|
|
|
#include <qtutilities/misc/dbusnotification.h>
|
2016-12-11 17:58:58 +01:00
|
|
|
#endif
|
2016-08-25 00:45:32 +02:00
|
|
|
|
|
|
|
#include <QApplication>
|
2019-06-22 17:28:09 +02:00
|
|
|
#include <QCursor>
|
2017-05-01 03:34:43 +02:00
|
|
|
#include <QFile>
|
|
|
|
#include <QMessageBox>
|
2016-08-25 00:45:32 +02:00
|
|
|
#include <QSettings>
|
2016-09-03 20:14:52 +02:00
|
|
|
#include <QSslCertificate>
|
|
|
|
#include <QSslError>
|
2017-05-01 03:34:43 +02:00
|
|
|
#include <QStringBuilder>
|
2016-08-25 00:45:32 +02:00
|
|
|
|
2017-03-17 00:38:42 +01:00
|
|
|
#include <unordered_map>
|
|
|
|
|
2016-09-03 20:14:52 +02:00
|
|
|
using namespace std;
|
2016-09-29 21:19:54 +02:00
|
|
|
using namespace Data;
|
2019-06-10 22:48:26 +02:00
|
|
|
using namespace QtUtilities;
|
2016-08-25 00:45:32 +02:00
|
|
|
|
2017-03-17 00:38:42 +01:00
|
|
|
namespace std {
|
|
|
|
|
2017-05-01 03:34:43 +02:00
|
|
|
template <> struct hash<QString> {
|
2017-03-17 00:38:42 +01:00
|
|
|
std::size_t operator()(const QString &str) const
|
|
|
|
{
|
|
|
|
return qHash(str);
|
|
|
|
}
|
|
|
|
};
|
2017-09-17 21:48:15 +02:00
|
|
|
} // namespace std
|
2017-03-17 00:38:42 +01:00
|
|
|
|
2016-08-25 00:45:32 +02:00
|
|
|
namespace Settings {
|
|
|
|
|
2019-07-13 17:59:48 +02:00
|
|
|
/*!
|
|
|
|
* \brief The minimum number of seconds the Syncthing service should be active before we try to connect.
|
|
|
|
*
|
|
|
|
* Because the REST-API is not instantly available after startup and we want to prevent connection errors.
|
|
|
|
*/
|
|
|
|
constexpr auto minActiveTimeInSeconds = 5;
|
|
|
|
|
2019-06-22 17:28:09 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the position to use.
|
|
|
|
*/
|
|
|
|
QPoint Appearance::Positioning::positionToUse() const
|
|
|
|
{
|
|
|
|
return useCursorPosition ? QCursor::pos() : assumedIconPosition;
|
|
|
|
}
|
|
|
|
|
2017-03-17 00:38:42 +01:00
|
|
|
/*!
|
|
|
|
* \brief Contains the processes for launching extra tools.
|
|
|
|
* \remarks Using std::unordered_map instead of QHash because SyncthingProcess can not be copied.
|
|
|
|
*/
|
|
|
|
static unordered_map<QString, SyncthingProcess> toolProcesses;
|
|
|
|
|
|
|
|
SyncthingProcess &Launcher::toolProcess(const QString &tool)
|
|
|
|
{
|
|
|
|
return toolProcesses[tool];
|
|
|
|
}
|
|
|
|
|
2018-04-02 23:29:39 +02:00
|
|
|
std::vector<SyncthingProcess *> Launcher::allProcesses()
|
|
|
|
{
|
|
|
|
vector<SyncthingProcess *> processes;
|
|
|
|
processes.reserve(1 + toolProcesses.size());
|
2018-04-11 23:15:15 +02:00
|
|
|
if (auto *const syncthingProcess = SyncthingProcess::mainInstance()) {
|
|
|
|
processes.push_back(syncthingProcess);
|
|
|
|
}
|
2018-04-02 23:29:39 +02:00
|
|
|
for (auto &process : toolProcesses) {
|
|
|
|
processes.push_back(&process.second);
|
|
|
|
}
|
|
|
|
return processes;
|
|
|
|
}
|
|
|
|
|
2017-03-17 00:38:42 +01:00
|
|
|
/*!
|
|
|
|
* \brief Starts all processes (Syncthing and tools) if autostart is enabled.
|
|
|
|
*/
|
|
|
|
void Launcher::autostart() const
|
|
|
|
{
|
2018-04-11 23:15:15 +02:00
|
|
|
auto *const launcher(SyncthingLauncher::mainInstance());
|
2019-07-12 20:26:56 +02:00
|
|
|
if (autostartEnabled && launcher) {
|
|
|
|
launcher->launch(*this);
|
2017-03-17 00:38:42 +01:00
|
|
|
}
|
2017-05-01 03:34:43 +02:00
|
|
|
for (auto i = tools.cbegin(), end = tools.cend(); i != end; ++i) {
|
2017-03-17 00:38:42 +01:00
|
|
|
const ToolParameter &toolParams = i.value();
|
2017-05-01 03:34:43 +02:00
|
|
|
if (toolParams.autostart && !toolParams.path.isEmpty()) {
|
2018-04-18 23:27:45 +02:00
|
|
|
toolProcesses[i.key()].startSyncthing(toolParams.path, SyncthingProcess::splitArguments(toolParams.args));
|
2017-03-17 00:38:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-02 23:29:39 +02:00
|
|
|
/*!
|
|
|
|
* \brief Terminates all launched processes.
|
|
|
|
* \remarks Waits until all processes have terminated. If a process hangs, the user is asked to kill.
|
|
|
|
*/
|
2017-03-17 00:38:42 +01:00
|
|
|
void Launcher::terminate()
|
|
|
|
{
|
2019-07-29 16:00:41 +02:00
|
|
|
auto *const launcher = SyncthingLauncher::mainInstance();
|
|
|
|
if (launcher) {
|
|
|
|
launcher->tearDownLibSyncthing();
|
|
|
|
}
|
2018-04-02 23:29:39 +02:00
|
|
|
QtGui::SyncthingKiller(allProcesses()).waitForFinished();
|
2017-03-17 00:38:42 +01:00
|
|
|
}
|
|
|
|
|
2019-07-12 20:26:56 +02:00
|
|
|
/*!
|
|
|
|
* \brief Applies the launcher settings to the specified \a connection considering the status of the main SyncthingLauncher instance.
|
|
|
|
* \remarks
|
|
|
|
* - Called by TrayWidget when the launcher settings have been changed.
|
|
|
|
* - \a currentConnectionSettings might be nullptr.
|
|
|
|
* - Currently this is only about the auto-reconnect interval and connecting instantly.
|
|
|
|
* \returns Returns the launcher status with respect to the specified \a connection.
|
|
|
|
*/
|
|
|
|
Launcher::LauncherStatus Launcher::apply(
|
|
|
|
Data::SyncthingConnection &connection, const SyncthingConnectionSettings *currentConnectionSettings, bool reconnectRequired) const
|
|
|
|
{
|
|
|
|
auto *const launcher(SyncthingLauncher::mainInstance());
|
|
|
|
if (!launcher) {
|
|
|
|
return LauncherStatus{};
|
|
|
|
}
|
|
|
|
const auto isRelevant = connection.isLocal();
|
|
|
|
const auto isRunning = launcher->isRunning();
|
|
|
|
const auto consideredForReconnect = considerForReconnect && isRelevant;
|
|
|
|
|
|
|
|
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 (consideredForReconnect) {
|
|
|
|
if (reconnectRequired) {
|
2019-07-13 17:59:48 +02:00
|
|
|
if (launcher->isActiveFor(minActiveTimeInSeconds)) {
|
|
|
|
connection.reconnect();
|
2019-07-26 16:36:48 +02:00
|
|
|
} else if (isRunning) {
|
2019-07-13 17:59:48 +02:00
|
|
|
// give the service (which has just started) a few seconds to initialize
|
|
|
|
connection.reconnectLater(minActiveTimeInSeconds * 1000);
|
|
|
|
}
|
2019-07-12 20:26:56 +02:00
|
|
|
} else if (isRunning && !connection.isConnected()) {
|
2019-07-13 17:59:48 +02:00
|
|
|
if (launcher->isActiveFor(minActiveTimeInSeconds)) {
|
|
|
|
connection.connect();
|
|
|
|
} else {
|
|
|
|
// give the service (which has just started) a few seconds to initialize
|
|
|
|
connection.connectLater(minActiveTimeInSeconds * 1000);
|
|
|
|
}
|
2019-07-12 20:26:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-13 13:21:25 +02:00
|
|
|
return LauncherStatus{ isRelevant, isRunning, consideredForReconnect, showButton && isRelevant };
|
2019-07-12 20:26:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the launcher status with respect to the specified \a connection.
|
|
|
|
*/
|
|
|
|
Launcher::LauncherStatus Launcher::status(SyncthingConnection &connection) const
|
|
|
|
{
|
|
|
|
auto *const launcher(SyncthingLauncher::mainInstance());
|
|
|
|
if (!launcher) {
|
|
|
|
return LauncherStatus{};
|
|
|
|
}
|
|
|
|
const auto isRelevant = connection.isLocal();
|
2019-07-13 13:21:25 +02:00
|
|
|
return LauncherStatus{ isRelevant, launcher->isRunning(), considerForReconnect && isRelevant, showButton && isRelevant };
|
2019-07-12 20:26:56 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
Settings &values()
|
2016-08-25 00:45:32 +02:00
|
|
|
{
|
2016-11-02 20:03:38 +01:00
|
|
|
static Settings settings;
|
|
|
|
return settings;
|
2016-08-25 00:45:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void restore()
|
|
|
|
{
|
2017-02-20 19:41:34 +01:00
|
|
|
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME));
|
|
|
|
// move old config to new location
|
2017-05-01 03:34:43 +02:00
|
|
|
const QString oldConfig
|
|
|
|
= QSettings(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName()).fileName();
|
2017-02-20 19:41:34 +01:00
|
|
|
QFile::rename(oldConfig, settings.fileName()) || QFile::remove(oldConfig);
|
|
|
|
settings.sync();
|
2016-11-02 20:03:38 +01:00
|
|
|
Settings &v = values();
|
2016-08-25 00:45:32 +02:00
|
|
|
|
|
|
|
settings.beginGroup(QStringLiteral("tray"));
|
2016-09-03 20:14:52 +02:00
|
|
|
const int connectionCount = settings.beginReadArray(QStringLiteral("connections"));
|
2016-11-02 20:03:38 +01:00
|
|
|
auto &primaryConnectionSettings = v.connection.primary;
|
2017-05-01 03:34:43 +02:00
|
|
|
if (connectionCount > 0) {
|
2016-11-02 20:03:38 +01:00
|
|
|
auto &secondaryConnectionSettings = v.connection.secondary;
|
|
|
|
secondaryConnectionSettings.clear();
|
|
|
|
secondaryConnectionSettings.reserve(static_cast<size_t>(connectionCount));
|
2017-05-01 03:34:43 +02:00
|
|
|
for (int i = 0; i < connectionCount; ++i) {
|
2016-09-29 21:19:54 +02:00
|
|
|
SyncthingConnectionSettings *connectionSettings;
|
2017-05-01 03:34:43 +02:00
|
|
|
if (i == 0) {
|
2016-11-02 20:03:38 +01:00
|
|
|
connectionSettings = &primaryConnectionSettings;
|
2016-09-03 20:14:52 +02:00
|
|
|
} else {
|
2016-11-02 20:03:38 +01:00
|
|
|
secondaryConnectionSettings.emplace_back();
|
|
|
|
connectionSettings = &secondaryConnectionSettings.back();
|
2016-09-03 20:14:52 +02:00
|
|
|
}
|
|
|
|
settings.setArrayIndex(i);
|
|
|
|
connectionSettings->label = settings.value(QStringLiteral("label")).toString();
|
2017-05-01 03:34:43 +02:00
|
|
|
if (connectionSettings->label.isEmpty()) {
|
2016-09-03 20:14:52 +02:00
|
|
|
connectionSettings->label = (i == 0 ? QStringLiteral("Primary instance") : QStringLiteral("Secondary instance %1").arg(i));
|
|
|
|
}
|
|
|
|
connectionSettings->syncthingUrl = settings.value(QStringLiteral("syncthingUrl"), connectionSettings->syncthingUrl).toString();
|
|
|
|
connectionSettings->authEnabled = settings.value(QStringLiteral("authEnabled"), connectionSettings->authEnabled).toBool();
|
|
|
|
connectionSettings->userName = settings.value(QStringLiteral("userName")).toString();
|
|
|
|
connectionSettings->password = settings.value(QStringLiteral("password")).toString();
|
|
|
|
connectionSettings->apiKey = settings.value(QStringLiteral("apiKey")).toByteArray();
|
2017-05-01 03:34:43 +02:00
|
|
|
connectionSettings->trafficPollInterval
|
|
|
|
= settings.value(QStringLiteral("trafficPollInterval"), connectionSettings->trafficPollInterval).toInt();
|
|
|
|
connectionSettings->devStatsPollInterval
|
|
|
|
= settings.value(QStringLiteral("devStatsPollInterval"), connectionSettings->devStatsPollInterval).toInt();
|
|
|
|
connectionSettings->errorsPollInterval
|
|
|
|
= settings.value(QStringLiteral("errorsPollInterval"), connectionSettings->errorsPollInterval).toInt();
|
|
|
|
connectionSettings->reconnectInterval
|
|
|
|
= settings.value(QStringLiteral("reconnectInterval"), connectionSettings->reconnectInterval).toInt();
|
2016-09-03 20:14:52 +02:00
|
|
|
connectionSettings->httpsCertPath = settings.value(QStringLiteral("httpsCertPath")).toString();
|
2017-05-01 03:34:43 +02:00
|
|
|
if (!connectionSettings->loadHttpsCert()) {
|
|
|
|
QMessageBox::critical(nullptr, QCoreApplication::applicationName(),
|
|
|
|
QCoreApplication::translate("Settings::restore", "Unable to load certificate \"%1\" when restoring settings.")
|
|
|
|
.arg(connectionSettings->httpsCertPath));
|
2016-09-03 20:14:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-11-02 20:03:38 +01:00
|
|
|
v.firstLaunch = true;
|
|
|
|
primaryConnectionSettings.label = QStringLiteral("Primary instance");
|
2016-09-03 20:14:52 +02:00
|
|
|
}
|
|
|
|
settings.endArray();
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
auto ¬ifyOn = v.notifyOn;
|
|
|
|
notifyOn.disconnect = settings.value(QStringLiteral("notifyOnDisconnect"), notifyOn.disconnect).toBool();
|
|
|
|
notifyOn.internalErrors = settings.value(QStringLiteral("notifyOnErrors"), notifyOn.internalErrors).toBool();
|
2019-07-12 20:24:19 +02:00
|
|
|
notifyOn.launcherErrors = settings.value(QStringLiteral("notifyOnLauncherErrors"), notifyOn.launcherErrors).toBool();
|
2018-03-31 22:31:28 +02:00
|
|
|
notifyOn.localSyncComplete = settings.value(QStringLiteral("notifyOnLocalSyncComplete"), notifyOn.localSyncComplete).toBool();
|
|
|
|
notifyOn.remoteSyncComplete = settings.value(QStringLiteral("notifyOnRemoteSyncComplete"), notifyOn.remoteSyncComplete).toBool();
|
2016-11-02 20:03:38 +01:00
|
|
|
notifyOn.syncthingErrors = settings.value(QStringLiteral("showSyncthingNotifications"), notifyOn.syncthingErrors).toBool();
|
2018-05-01 22:27:03 +02:00
|
|
|
notifyOn.newDeviceConnects = settings.value(QStringLiteral("notifyOnNewDeviceConnects"), notifyOn.newDeviceConnects).toBool();
|
|
|
|
notifyOn.newDirectoryShared = settings.value(QStringLiteral("notifyOnNewDirectoryShared"), notifyOn.newDirectoryShared).toBool();
|
2016-12-11 17:58:58 +01:00
|
|
|
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
|
|
|
|
v.dbusNotifications = settings.value(QStringLiteral("dbusNotifications"), DBusNotification::isAvailable()).toBool();
|
|
|
|
#endif
|
2017-01-14 02:12:38 +01:00
|
|
|
v.ignoreInavailabilityAfterStart = settings.value(QStringLiteral("ignoreInavailabilityAfterStart"), v.ignoreInavailabilityAfterStart).toUInt();
|
2016-11-02 20:03:38 +01:00
|
|
|
auto &appearance = v.appearance;
|
|
|
|
appearance.showTraffic = settings.value(QStringLiteral("showTraffic"), appearance.showTraffic).toBool();
|
|
|
|
appearance.trayMenuSize = settings.value(QStringLiteral("trayMenuSize"), appearance.trayMenuSize).toSize();
|
|
|
|
appearance.frameStyle = settings.value(QStringLiteral("frameStyle"), appearance.frameStyle).toInt();
|
|
|
|
appearance.tabPosition = settings.value(QStringLiteral("tabPos"), appearance.tabPosition).toInt();
|
2016-11-02 21:05:32 +01:00
|
|
|
appearance.brightTextColors = settings.value(QStringLiteral("brightTextColors"), appearance.brightTextColors).toBool();
|
2019-07-31 20:16:43 +02:00
|
|
|
v.icons.status = StatusIconSettings(settings.value(QStringLiteral("statusIcons")).toString());
|
|
|
|
v.icons.tray = StatusIconSettings(settings.value(QStringLiteral("trayIcons")).toString());
|
|
|
|
v.icons.distinguishTrayIcons = settings.value(QStringLiteral("distinguishTrayIcons")).toBool();
|
2019-06-22 17:28:09 +02:00
|
|
|
settings.beginGroup(QStringLiteral("positioning"));
|
|
|
|
auto &positioning = appearance.positioning;
|
|
|
|
positioning.useCursorPosition = settings.value(QStringLiteral("useCursorPos"), positioning.useCursorPosition).toBool();
|
|
|
|
positioning.assumedIconPosition = settings.value(QStringLiteral("assumedIconPos"), positioning.assumedIconPosition).toPoint();
|
|
|
|
settings.endGroup();
|
2016-09-03 19:39:43 +02:00
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
settings.beginGroup(QStringLiteral("startup"));
|
2016-11-02 20:03:38 +01:00
|
|
|
auto &launcher = v.launcher;
|
2019-07-12 20:26:56 +02:00
|
|
|
launcher.autostartEnabled = settings.value(QStringLiteral("syncthingAutostart"), launcher.autostartEnabled).toBool();
|
2018-04-18 23:27:45 +02:00
|
|
|
launcher.useLibSyncthing = settings.value(QStringLiteral("useLibSyncthing"), launcher.useLibSyncthing).toBool();
|
2019-07-17 17:53:36 +02:00
|
|
|
launcher.libSyncthing.configDir = settings.value(QStringLiteral("libSyncthingConfigDir"), launcher.libSyncthing.configDir).toString();
|
2016-11-02 20:03:38 +01:00
|
|
|
launcher.syncthingPath = settings.value(QStringLiteral("syncthingPath"), launcher.syncthingPath).toString();
|
|
|
|
launcher.syncthingArgs = settings.value(QStringLiteral("syncthingArgs"), launcher.syncthingArgs).toString();
|
2018-04-03 00:11:55 +02:00
|
|
|
launcher.considerForReconnect = settings.value(QStringLiteral("considerLauncherForReconnect"), launcher.considerForReconnect).toBool();
|
2019-07-12 20:26:56 +02:00
|
|
|
launcher.showButton = settings.value(QStringLiteral("showLauncherButton"), launcher.showButton).toBool();
|
2017-03-17 00:38:42 +01:00
|
|
|
settings.beginGroup(QStringLiteral("tools"));
|
2017-05-01 03:34:43 +02:00
|
|
|
for (const QString &tool : settings.childGroups()) {
|
2017-03-17 00:38:42 +01:00
|
|
|
settings.beginGroup(tool);
|
|
|
|
ToolParameter &toolParams = launcher.tools[tool];
|
|
|
|
toolParams.autostart = settings.value(QStringLiteral("autostart"), toolParams.autostart).toBool();
|
|
|
|
toolParams.path = settings.value(QStringLiteral("path"), toolParams.path).toString();
|
|
|
|
toolParams.args = settings.value(QStringLiteral("args"), toolParams.args).toString();
|
|
|
|
settings.endGroup();
|
|
|
|
}
|
|
|
|
settings.endGroup();
|
2016-12-18 16:50:35 +01:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
|
|
|
auto &systemd = v.systemd;
|
|
|
|
systemd.syncthingUnit = settings.value(QStringLiteral("syncthingUnit"), systemd.syncthingUnit).toString();
|
|
|
|
systemd.showButton = settings.value(QStringLiteral("showButton"), systemd.showButton).toBool();
|
2016-12-27 16:16:12 +01:00
|
|
|
systemd.considerForReconnect = settings.value(QStringLiteral("considerForReconnect"), systemd.considerForReconnect).toBool();
|
2016-12-18 16:50:35 +01:00
|
|
|
#endif
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.endGroup();
|
|
|
|
|
2017-04-23 18:27:31 +02:00
|
|
|
#if defined(SYNCTHINGWIDGETS_USE_WEBENGINE) || defined(SYNCTHINGWIDGETS_USE_WEBKIT)
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.beginGroup(QStringLiteral("webview"));
|
2016-11-02 20:03:38 +01:00
|
|
|
auto &webView = v.webView;
|
2017-01-07 16:15:13 +01:00
|
|
|
webView.disabled = settings.value(QStringLiteral("disabled"), webView.disabled).toBool();
|
2016-11-02 20:03:38 +01:00
|
|
|
webView.zoomFactor = settings.value(QStringLiteral("zoomFactor"), webView.zoomFactor).toDouble();
|
|
|
|
webView.geometry = settings.value(QStringLiteral("geometry")).toByteArray();
|
|
|
|
webView.keepRunning = settings.value(QStringLiteral("keepRunning"), webView.keepRunning).toBool();
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.endGroup();
|
|
|
|
#endif
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
v.qt.restore(settings);
|
2016-08-25 00:45:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void save()
|
|
|
|
{
|
2017-02-20 19:41:34 +01:00
|
|
|
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME));
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
const Settings &v = values();
|
2016-08-25 00:45:32 +02:00
|
|
|
|
|
|
|
settings.beginGroup(QStringLiteral("tray"));
|
2016-11-02 20:03:38 +01:00
|
|
|
const auto &primaryConnectionSettings = v.connection.primary;
|
|
|
|
const auto &secondaryConnectionSettings = v.connection.secondary;
|
|
|
|
const int connectionCount = static_cast<int>(1 + secondaryConnectionSettings.size());
|
2016-09-03 20:14:52 +02:00
|
|
|
settings.beginWriteArray(QStringLiteral("connections"), connectionCount);
|
2017-05-01 03:34:43 +02:00
|
|
|
for (int i = 0; i < connectionCount; ++i) {
|
|
|
|
const SyncthingConnectionSettings *connectionSettings
|
|
|
|
= (i == 0 ? &primaryConnectionSettings : &secondaryConnectionSettings[static_cast<size_t>(i - 1)]);
|
2016-09-03 20:14:52 +02:00
|
|
|
settings.setArrayIndex(i);
|
|
|
|
settings.setValue(QStringLiteral("label"), connectionSettings->label);
|
|
|
|
settings.setValue(QStringLiteral("syncthingUrl"), connectionSettings->syncthingUrl);
|
|
|
|
settings.setValue(QStringLiteral("authEnabled"), connectionSettings->authEnabled);
|
|
|
|
settings.setValue(QStringLiteral("userName"), connectionSettings->userName);
|
|
|
|
settings.setValue(QStringLiteral("password"), connectionSettings->password);
|
|
|
|
settings.setValue(QStringLiteral("apiKey"), connectionSettings->apiKey);
|
2016-09-25 20:54:09 +02:00
|
|
|
settings.setValue(QStringLiteral("trafficPollInterval"), connectionSettings->trafficPollInterval);
|
|
|
|
settings.setValue(QStringLiteral("devStatsPollInterval"), connectionSettings->devStatsPollInterval);
|
2017-01-12 22:38:36 +01:00
|
|
|
settings.setValue(QStringLiteral("errorsPollInterval"), connectionSettings->errorsPollInterval);
|
2016-10-07 15:11:25 +02:00
|
|
|
settings.setValue(QStringLiteral("reconnectInterval"), connectionSettings->reconnectInterval);
|
2016-09-03 20:14:52 +02:00
|
|
|
settings.setValue(QStringLiteral("httpsCertPath"), connectionSettings->httpsCertPath);
|
|
|
|
}
|
|
|
|
settings.endArray();
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
const auto ¬ifyOn = v.notifyOn;
|
|
|
|
settings.setValue(QStringLiteral("notifyOnDisconnect"), notifyOn.disconnect);
|
|
|
|
settings.setValue(QStringLiteral("notifyOnErrors"), notifyOn.internalErrors);
|
2019-07-12 20:24:19 +02:00
|
|
|
settings.setValue(QStringLiteral("notifyOnLauncherErrors"), notifyOn.launcherErrors);
|
2018-03-31 22:31:28 +02:00
|
|
|
settings.setValue(QStringLiteral("notifyOnLocalSyncComplete"), notifyOn.localSyncComplete);
|
|
|
|
settings.setValue(QStringLiteral("notifyOnRemoteSyncComplete"), notifyOn.remoteSyncComplete);
|
2016-11-02 20:03:38 +01:00
|
|
|
settings.setValue(QStringLiteral("showSyncthingNotifications"), notifyOn.syncthingErrors);
|
2018-05-01 22:27:03 +02:00
|
|
|
settings.setValue(QStringLiteral("notifyOnNewDeviceConnects"), notifyOn.newDeviceConnects);
|
|
|
|
settings.setValue(QStringLiteral("notifyOnNewDirectoryShared"), notifyOn.newDirectoryShared);
|
2016-12-11 17:58:58 +01:00
|
|
|
#ifdef QT_UTILITIES_SUPPORT_DBUS_NOTIFICATIONS
|
|
|
|
settings.setValue(QStringLiteral("dbusNotifications"), v.dbusNotifications);
|
|
|
|
#endif
|
2017-01-14 02:12:38 +01:00
|
|
|
settings.setValue(QStringLiteral("ignoreInavailabilityAfterStart"), v.ignoreInavailabilityAfterStart);
|
2016-11-02 20:03:38 +01:00
|
|
|
const auto &appearance = v.appearance;
|
|
|
|
settings.setValue(QStringLiteral("showTraffic"), appearance.showTraffic);
|
|
|
|
settings.setValue(QStringLiteral("trayMenuSize"), appearance.trayMenuSize);
|
|
|
|
settings.setValue(QStringLiteral("frameStyle"), appearance.frameStyle);
|
|
|
|
settings.setValue(QStringLiteral("tabPos"), appearance.tabPosition);
|
2016-11-02 21:05:32 +01:00
|
|
|
settings.setValue(QStringLiteral("brightTextColors"), appearance.brightTextColors);
|
2019-07-31 20:16:43 +02:00
|
|
|
settings.setValue(QStringLiteral("statusIcons"), v.icons.status.toString());
|
|
|
|
settings.setValue(QStringLiteral("trayIcons"), v.icons.tray.toString());
|
|
|
|
settings.setValue(QStringLiteral("distinguishTrayIcons"), v.icons.distinguishTrayIcons);
|
2019-06-22 17:28:09 +02:00
|
|
|
settings.beginGroup(QStringLiteral("positioning"));
|
|
|
|
settings.setValue(QStringLiteral("useCursorPos"), appearance.positioning.useCursorPosition);
|
|
|
|
settings.setValue(QStringLiteral("assumedIconPos"), appearance.positioning.assumedIconPosition);
|
|
|
|
settings.endGroup();
|
2016-09-03 19:39:43 +02:00
|
|
|
settings.endGroup();
|
|
|
|
|
|
|
|
settings.beginGroup(QStringLiteral("startup"));
|
2016-11-02 20:03:38 +01:00
|
|
|
const auto &launcher = v.launcher;
|
2019-07-12 20:26:56 +02:00
|
|
|
settings.setValue(QStringLiteral("syncthingAutostart"), launcher.autostartEnabled);
|
2018-04-18 23:27:45 +02:00
|
|
|
settings.setValue(QStringLiteral("useLibSyncthing"), launcher.useLibSyncthing);
|
2019-07-17 17:53:36 +02:00
|
|
|
settings.setValue(QStringLiteral("libSyncthingConfigDir"), launcher.libSyncthing.configDir);
|
2016-11-02 20:03:38 +01:00
|
|
|
settings.setValue(QStringLiteral("syncthingPath"), launcher.syncthingPath);
|
|
|
|
settings.setValue(QStringLiteral("syncthingArgs"), launcher.syncthingArgs);
|
2018-04-03 00:11:55 +02:00
|
|
|
settings.setValue(QStringLiteral("considerLauncherForReconnect"), launcher.considerForReconnect);
|
2019-07-12 20:26:56 +02:00
|
|
|
settings.setValue(QStringLiteral("showLauncherButton"), launcher.showButton);
|
2017-03-17 00:38:42 +01:00
|
|
|
settings.beginGroup(QStringLiteral("tools"));
|
2017-05-01 03:34:43 +02:00
|
|
|
for (auto i = launcher.tools.cbegin(), end = launcher.tools.cend(); i != end; ++i) {
|
2017-03-17 00:38:42 +01:00
|
|
|
const ToolParameter &toolParams = i.value();
|
|
|
|
settings.beginGroup(i.key());
|
|
|
|
settings.setValue(QStringLiteral("autostart"), toolParams.autostart);
|
|
|
|
settings.setValue(QStringLiteral("path"), toolParams.path);
|
|
|
|
settings.setValue(QStringLiteral("args"), toolParams.args);
|
|
|
|
settings.endGroup();
|
|
|
|
}
|
|
|
|
settings.endGroup();
|
2016-12-18 16:50:35 +01:00
|
|
|
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
|
|
|
|
const auto &systemd = v.systemd;
|
|
|
|
settings.setValue(QStringLiteral("syncthingUnit"), systemd.syncthingUnit);
|
|
|
|
settings.setValue(QStringLiteral("showButton"), systemd.showButton);
|
2016-12-27 16:16:12 +01:00
|
|
|
settings.setValue(QStringLiteral("considerForReconnect"), systemd.considerForReconnect);
|
2016-12-18 16:50:35 +01:00
|
|
|
#endif
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.endGroup();
|
|
|
|
|
2017-04-23 18:27:31 +02:00
|
|
|
#if defined(SYNCTHINGWIDGETS_USE_WEBENGINE) || defined(SYNCTHINGWIDGETS_USE_WEBKIT)
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.beginGroup(QStringLiteral("webview"));
|
2016-11-02 20:03:38 +01:00
|
|
|
const auto &webView = v.webView;
|
|
|
|
settings.setValue(QStringLiteral("disabled"), webView.disabled);
|
|
|
|
settings.setValue(QStringLiteral("zoomFactor"), webView.zoomFactor);
|
|
|
|
settings.setValue(QStringLiteral("geometry"), webView.geometry);
|
|
|
|
settings.setValue(QStringLiteral("keepRunning"), webView.keepRunning);
|
2016-08-25 00:45:32 +02:00
|
|
|
settings.endGroup();
|
|
|
|
#endif
|
|
|
|
|
2016-11-02 20:03:38 +01:00
|
|
|
v.qt.save(settings);
|
2016-08-25 00:45:32 +02:00
|
|
|
}
|
2018-03-31 22:31:28 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Applies the notification settings on the specified \a notifier.
|
|
|
|
*/
|
2018-04-02 20:26:00 +02:00
|
|
|
void Settings::apply(SyncthingNotifier ¬ifier) const
|
2018-03-31 22:31:28 +02:00
|
|
|
{
|
|
|
|
auto notifications(SyncthingHighLevelNotification::None);
|
2018-04-02 20:26:00 +02:00
|
|
|
if (notifyOn.disconnect) {
|
2018-03-31 22:31:28 +02:00
|
|
|
notifications |= SyncthingHighLevelNotification::ConnectedDisconnected;
|
|
|
|
}
|
2018-04-02 20:26:00 +02:00
|
|
|
if (notifyOn.localSyncComplete) {
|
2018-03-31 22:31:28 +02:00
|
|
|
notifications |= SyncthingHighLevelNotification::LocalSyncComplete;
|
|
|
|
}
|
2018-04-02 20:26:00 +02:00
|
|
|
if (notifyOn.remoteSyncComplete) {
|
2018-03-31 22:31:28 +02:00
|
|
|
notifications |= SyncthingHighLevelNotification::RemoteSyncComplete;
|
|
|
|
}
|
2018-05-01 22:27:03 +02:00
|
|
|
if (notifyOn.newDeviceConnects) {
|
|
|
|
notifications |= SyncthingHighLevelNotification::NewDevice;
|
|
|
|
}
|
|
|
|
if (notifyOn.newDirectoryShared) {
|
|
|
|
notifications |= SyncthingHighLevelNotification::NewDir;
|
|
|
|
}
|
2019-07-12 20:24:19 +02:00
|
|
|
if (notifyOn.launcherErrors) {
|
|
|
|
notifications |= SyncthingHighLevelNotification::SyncthingProcessError;
|
|
|
|
}
|
2018-03-31 22:31:28 +02:00
|
|
|
notifier.setEnabledNotifications(notifications);
|
2018-04-02 20:26:00 +02:00
|
|
|
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
|
2019-07-12 20:26:56 +02:00
|
|
|
* - Called by SyncthingApplet and TrayWidget when the status of the SyncthingService changes or the systemd settings have been changed.
|
2018-04-02 20:26:00 +02:00
|
|
|
* - \a currentConnectionSettings might be nullptr.
|
|
|
|
* - Currently this is only about the auto-reconnect interval and connecting instantly.
|
2019-07-12 20:26:56 +02:00
|
|
|
* \returns Returns the service status with respect to the specified \a connection.
|
2018-04-02 20:26:00 +02:00
|
|
|
*/
|
2019-07-12 20:26:56 +02:00
|
|
|
Systemd::ServiceStatus Systemd::apply(
|
2018-04-02 20:26:00 +02:00
|
|
|
Data::SyncthingConnection &connection, const SyncthingConnectionSettings *currentConnectionSettings, bool reconnectRequired) const
|
|
|
|
{
|
2018-04-11 23:15:15 +02:00
|
|
|
auto *const service(SyncthingService::mainInstance());
|
|
|
|
if (!service) {
|
2019-07-12 20:26:56 +02:00
|
|
|
return ServiceStatus{};
|
2018-04-11 23:15:15 +02:00
|
|
|
}
|
2019-07-26 16:36:48 +02:00
|
|
|
const auto isRelevant = service->isSystemdAvailable() && connection.isLocal();
|
|
|
|
const auto unitAvailable = service->isUnitAvailable();
|
|
|
|
const auto isRunning = unitAvailable && service->isRunning();
|
|
|
|
const auto consideredForReconnect = considerForReconnect && isRelevant && unitAvailable;
|
2018-04-02 20:26:00 +02:00
|
|
|
|
|
|
|
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
|
2019-07-12 20:26:56 +02:00
|
|
|
if (consideredForReconnect) {
|
2018-04-02 20:26:00 +02:00
|
|
|
if (reconnectRequired) {
|
2018-04-11 23:15:15 +02:00
|
|
|
if (service->isActiveWithoutSleepFor(minActiveTimeInSeconds)) {
|
2018-04-02 20:26:00 +02:00
|
|
|
connection.reconnect();
|
2019-07-26 16:36:48 +02:00
|
|
|
} else if (isRunning) {
|
2018-04-02 20:26:00 +02:00
|
|
|
// give the service (which has just started) a few seconds to initialize
|
|
|
|
connection.reconnectLater(minActiveTimeInSeconds * 1000);
|
|
|
|
}
|
|
|
|
} else if (isRunning && !connection.isConnected()) {
|
2018-04-11 23:15:15 +02:00
|
|
|
if (service->isActiveWithoutSleepFor(minActiveTimeInSeconds)) {
|
2018-04-02 20:26:00 +02:00
|
|
|
connection.connect();
|
|
|
|
} else {
|
|
|
|
// give the service (which has just started) a few seconds to initialize
|
|
|
|
connection.connectLater(minActiveTimeInSeconds * 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-13 13:21:25 +02:00
|
|
|
return ServiceStatus{ isRelevant, isRunning, consideredForReconnect, showButton && isRelevant };
|
2019-07-12 20:26:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the service status with respect to the specified \a connection.
|
|
|
|
*/
|
|
|
|
Systemd::ServiceStatus Systemd::status(SyncthingConnection &connection) const
|
|
|
|
{
|
|
|
|
auto *const service(SyncthingService::mainInstance());
|
|
|
|
if (!service) {
|
|
|
|
return ServiceStatus{};
|
|
|
|
}
|
|
|
|
const auto isRelevant = service->isSystemdAvailable() && connection.isLocal();
|
2019-07-13 13:21:25 +02:00
|
|
|
return ServiceStatus{ isRelevant, service->isRunning(), considerForReconnect && isRelevant, showButton && isRelevant };
|
2018-03-31 22:31:28 +02:00
|
|
|
}
|
2019-06-22 17:28:09 +02:00
|
|
|
|
2018-04-02 20:26:00 +02:00
|
|
|
#endif
|
2018-03-31 22:31:28 +02:00
|
|
|
|
2017-09-17 21:48:15 +02:00
|
|
|
} // namespace Settings
|