From 59254c1c10d3261342304b87ac935da556bde7ba Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Wed, 12 Feb 2020 16:28:31 +0000 Subject: [PATCH 01/25] #6538 Made Loading and saving of settings more readable Signed-off-by: Jamie Newbon --- src/gui/src/AppConfig.cpp | 145 ++++++++++++++++++++++++++------------ src/gui/src/AppConfig.h | 46 ++++++++++++ 2 files changed, 145 insertions(+), 46 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 7613b3c60..62d1d8f60 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -36,6 +36,32 @@ const char AppConfig::m_SynergyLogDir[] = "/var/log/"; const ElevateMode defaultElevateMode = ElevateAsNeeded; +const char* AppConfig::m_SynergySettingsName[] = { + "screenName", + "port", + "interface", + "logLevel2", + "logToFile", + "logFilename", + "wizardLastRun", + "language", + "startedBefore", + "autoConfig", + "autoConfigServer", + "elevateMode", + "elevateModeEnum", + "edition", + "cryptoEnabled", + "autoHide", + "serialKey", + "lastVersion", + "lastExpiringWarningTime", + "activationHasRun", + "minimizeToTray" +}; + + + static const char* logLevelNames[] = { "INFO", @@ -141,59 +167,66 @@ QString AppConfig::autoConfigServer() const { return m_AutoConfigServer; } void AppConfig::loadSettings() { - m_ScreenName = settings().value("screenName", QHostInfo::localHostName()).toString(); - m_Port = settings().value("port", 24800).toInt(); - m_Interface = settings().value("interface").toString(); - m_LogLevel = settings().value("logLevel2", 0).toInt(); // level 0: INFO - m_LogToFile = settings().value("logToFile", false).toBool(); - m_LogFilename = settings().value("logFilename", synergyLogDir() + "synergy.log").toString(); - m_WizardLastRun = settings().value("wizardLastRun", 0).toInt(); - m_Language = settings().value("language", QLocale::system().name()).toString(); - m_StartedBefore = settings().value("startedBefore", false).toBool(); - m_AutoConfig = settings().value("autoConfig", false).toBool(); - m_AutoConfigServer = settings().value("autoConfigServer", "").toString(); - QVariant elevateMode = settings().value("elevateModeEnum"); - if (!elevateMode.isValid()) { - elevateMode = settings().value ("elevateMode", - QVariant(static_cast(defaultElevateMode))); + m_ScreenName = loadSetting(ScreenName, QHostInfo::localHostName()).toString(); + m_Port = loadSetting(Port, 24800).toInt(); + m_Interface = loadSetting(InterfaceSetting).toString(); + m_LogLevel = loadSetting(LogLevel, 0).toInt(); + m_LogToFile = loadSetting(LogToFile, false).toBool(); + m_LogFilename = loadSetting(LogFilename,synergyLogDir() + "synergy.log").toString(); + m_WizardLastRun = loadSetting(WizardLastRun,0).toInt(); + m_Language = loadSetting(Language, QLocale::system().name()).toString(); + m_StartedBefore = loadSetting(StartedBefore, false).toBool(); + m_AutoConfig = loadSetting(AutoConfig, false).toBool(); + m_AutoConfigServer = loadSetting(AutoConfigServer,"").toString(); + + { //Scope related code together + // TODO Investigate why ElevateModeEnum isn't loaded fully + QVariant elevateMode = loadSetting(ElevateModeEnum); + if (!elevateMode.isValid()) { + elevateMode = loadSetting(ElevateModeSetting, + QVariant(static_cast(defaultElevateMode))); + } + m_ElevateMode = static_cast(elevateMode.toInt()); } - m_ElevateMode = static_cast(elevateMode.toInt()); - m_Edition = static_cast(settings().value("edition", kUnregistered).toInt()); - m_ActivateEmail = settings().value("activateEmail", "").toString(); - m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool(); - m_AutoHide = settings().value("autoHide", false).toBool(); - m_Serialkey = settings().value("serialKey", "").toString().trimmed(); - m_lastVersion = settings().value("lastVersion", "Unknown").toString(); - m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt(); - m_ActivationHasRun = settings().value("activationHasRun", false).toBool(); - m_MinimizeToTray = settings().value("minimizeToTray", false).toBool(); + + m_Edition = static_cast(loadSetting(EditionSetting, kUnregistered).toInt()); + m_ActivateEmail = loadSetting(ActivateEmail, "").toString(); + m_CryptoEnabled = loadSetting(CryptoEnabled, true).toBool(); + m_AutoHide = loadSetting(AutoHide, false).toBool(); + m_Serialkey = loadSetting(SerialKey, "").toString().trimmed(); + m_lastVersion = loadSetting(LastVersion, "Unknown").toString(); + m_LastExpiringWarningTime = loadSetting(LastExpireWarningTime, 0).toInt(); + m_ActivationHasRun = loadSetting(ActivationHasRun, false).toBool(); + m_MinimizeToTray = loadSetting(MinimizeToTray, false).toBool(); + } void AppConfig::saveSettings() { - settings().setValue("screenName", m_ScreenName); - settings().setValue("port", m_Port); - settings().setValue("interface", m_Interface); - settings().setValue("logLevel2", m_LogLevel); - settings().setValue("logToFile", m_LogToFile); - settings().setValue("logFilename", m_LogFilename); - settings().setValue("wizardLastRun", kWizardVersion); - settings().setValue("language", m_Language); - settings().setValue("startedBefore", m_StartedBefore); - settings().setValue("autoConfig", m_AutoConfig); - settings().setValue("autoConfigServer", m_AutoConfigServer); + setSetting(ScreenName, m_ScreenName); + setSetting(Port, m_Port); + setSetting(InterfaceSetting, m_Interface); + setSetting(LogLevel, m_LogLevel); + setSetting(LogToFile, m_LogToFile); + setSetting(LogFilename, m_LogFilename); + setSetting(WizardLastRun, kWizardVersion); + setSetting(Language, m_Language); + setSetting(StartedBefore, m_StartedBefore); + setSetting(AutoConfig, m_AutoConfig); + setSetting(AutoConfigServer, m_AutoConfigServer); // Refer to enum ElevateMode declaration for insight in to why this // flag is mapped this way - settings().setValue("elevateMode", m_ElevateMode == ElevateAlways); - settings().setValue("elevateModeEnum", static_cast(m_ElevateMode)); - settings().setValue("edition", m_Edition); - settings().setValue("cryptoEnabled", m_CryptoEnabled); - settings().setValue("autoHide", m_AutoHide); - settings().setValue("serialKey", m_Serialkey); - settings().setValue("lastVersion", m_lastVersion); - settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime); - settings().setValue("activationHasRun", m_ActivationHasRun); - settings().setValue("minimizeToTray", m_MinimizeToTray); + setSetting(ElevateModeSetting, m_ElevateMode == ElevateAlways); + setSetting(ElevateModeEnum, static_cast(m_ElevateMode)); + setSetting(EditionSetting, m_Edition); + setSetting(CryptoEnabled, m_CryptoEnabled); + setSetting(AutoHide, m_AutoHide); + setSetting(SerialKey, m_Serialkey); + setSetting(LastVersion, m_lastVersion); + setSetting(LastExpireWarningTime, m_LastExpiringWarningTime); + setSetting(ActivationHasRun, m_ActivationHasRun); + setSetting(MinimizeToTray, m_MinimizeToTray); + settings().sync(); } @@ -305,3 +338,23 @@ bool AppConfig::getAutoHide() { return m_AutoHide; } void AppConfig::setMinimizeToTray(bool b) { m_MinimizeToTray = b; } bool AppConfig::getMinimizeToTray() { return m_MinimizeToTray; } + +bool AppConfig::settingsExist(QSettings* settings) { + //Use screen name as the test to see if the settings have been saved to this location + return settings->contains(settingName(ScreenName)); +} + +QString AppConfig::settingName(AppConfig::Setting name) { + return m_SynergySettingsName[name]; +} + +template +void AppConfig::setSetting(AppConfig::Setting name, T value) { + settings().setValue(settingName(name), value); +} + +QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& defaultValue) { + return settings().value(settingName(name), defaultValue); +} + + diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 7e075e62b..8b200aa8f 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -116,7 +116,38 @@ class AppConfig: public QObject void saveSettings(); void setLastVersion(QString version); + /// @brief settingsExist Checks ths settings to see if they exist in the QSettings location + /// @param [in] settings The QSettings object to check + /// @return True if the setting was found. + static bool settingsExist(QSettings* settings); + protected: + /// @brief The enumeration to easily access the names of the setting inside m_SynergySettingsName + enum Setting { + ScreenName, + Port, + InterfaceSetting, + LogLevel, + LogToFile, + LogFilename, + WizardLastRun, + Language, + StartedBefore, + AutoConfig, + AutoConfigServer, + ElevateModeSetting, + ElevateModeEnum, + EditionSetting, + CryptoEnabled, + AutoHide, + SerialKey, + LastVersion, + LastExpireWarningTime, + ActivationHasRun, + MinimizeToTray, + ActivateEmail, + }; + QSettings& settings(); void setScreenName(const QString& s); void setPort(int i); @@ -129,6 +160,7 @@ protected: void setStartedBefore(bool b); void setElevateMode(ElevateMode em); void loadSettings(); + static QString settingName(AppConfig::Setting name); private: QSettings* m_pSettings; @@ -159,6 +191,20 @@ protected: static const char m_SynergycName[]; static const char m_SynergyLogDir[]; + /// @brief Contains the string values of the settings names that will be saved + static const char* m_SynergySettingsName[]; + + /// @brief Sets the value of a setting + /// @param [in] name The Setting to be saved + /// @param [in] value The Value to be saved + template + void setSetting(AppConfig::Setting name, T value); + + /// @brief Loads a setting + /// @param [in] name The setting to be loaded + /// @param [in] defaultValue The default value of the setting + QVariant loadSetting(AppConfig::Setting name, const QVariant& defaultValue = QVariant()); + signals: void sslToggled(bool enabled); }; From 969595dfe03cfdbceb00a968e523a1087587d244 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 13 Feb 2020 09:21:02 +0000 Subject: [PATCH 02/25] #6538 Loading of global settings if user setting dont exist --- src/gui/src/AppConfig.cpp | 16 ++++++++++++---- src/gui/src/AppConfig.h | 6 +++++- src/gui/src/main.cpp | 15 ++++++++++++--- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 62d1d8f60..93924a3ca 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include "QSynergyApplication.h" #include "AppConfig.h" #include "QUtility.h" @@ -70,8 +71,8 @@ static const char* logLevelNames[] = "DEBUG2" }; -AppConfig::AppConfig(QSettings* settings) : - m_pSettings(settings), +AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : + m_pSettings(userSettings), m_ScreenName(), m_Port(24800), m_Interface(), @@ -88,6 +89,15 @@ AppConfig::AppConfig(QSettings* settings) : { Q_ASSERT(m_pSettings); + //If user setting dont exist but system ones do, load the system setting and save them to user settings + if (!settingsExist(userSettings) && settingsExist(systemSettings)) + { + m_pSettings = systemSettings; + loadSettings(); + m_pSettings = userSettings; + saveSettings(); + } + loadSettings(); } @@ -356,5 +366,3 @@ void AppConfig::setSetting(AppConfig::Setting name, T value) { QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& defaultValue) { return settings().value(settingName(name), defaultValue); } - - diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 8b200aa8f..10da8222e 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -22,6 +22,7 @@ #include #include +#include #include "ElevateMode.h" #include @@ -59,7 +60,7 @@ class AppConfig: public QObject friend class SetupWizard; public: - AppConfig(QSettings* settings); + AppConfig(QSettings* userSettings, QSettings* systemSettings); ~AppConfig(); public: @@ -205,6 +206,9 @@ protected: /// @param [in] defaultValue The default value of the setting QVariant loadSetting(AppConfig::Setting name, const QVariant& defaultValue = QVariant()); + /// @brief This will save the settings to globalScope instead of userScope + void saveToGlobalScope(); + signals: void sslToggled(bool enabled); }; diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 5d8a5e899..e05b7ba84 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -89,8 +89,17 @@ int main(int argc, char* argv[]) QApplication::setQuitOnLastWindowClosed(false); #endif - QSettings settings; - AppConfig appConfig (&settings); + //Config will default to User settings if they exist, + // otherwise it will load System setting and save them to User settings + QSettings systemSettings(QSettings::Scope::SystemScope, + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); + + QSettings userSettings(QSettings::Scope::UserScope, + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); + + AppConfig appConfig (&userSettings, &systemSettings); qRegisterMetaType("Edition"); #ifndef SYNERGY_ENTERPRISE LicenseManager licenseManager (&appConfig); @@ -101,7 +110,7 @@ int main(int argc, char* argv[]) #ifdef SYNERGY_ENTERPRISE MainWindow mainWindow(settings, appConfig); #else - MainWindow mainWindow(settings, appConfig, licenseManager); + MainWindow mainWindow(userSettings, appConfig, licenseManager); #endif QObject::connect(dynamic_cast(&app), SIGNAL(aboutToQuit()), From 87692ad0a5807e01ab03fb631821f60bafa77be3 Mon Sep 17 00:00:00 2001 From: jnewbon Date: Tue, 25 Feb 2020 14:41:11 +0000 Subject: [PATCH 03/25] #6538 Changed mainwindow to grab settings from appconfig instead of maintaining its own pointer Signed-off-by: jnewbon --- src/gui/src/AppConfig.h | 4 ++++ src/gui/src/MainWindow.cpp | 5 ++--- src/gui/src/MainWindow.h | 5 ++--- src/gui/src/main.cpp | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 10da8222e..c6bdd34b9 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -64,6 +64,10 @@ class AppConfig: public QObject ~AppConfig(); public: + /// @brief Gets the current settings. + /// @return The scoped setting currently selected + QSettings& settings(); + const QString& screenName() const; int port() const; const QString& networkInterface() const; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index d8337d998..d3e1ee8d5 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -97,7 +97,7 @@ static const char* synergyDefaultIconFiles[] = #ifdef SYNERGY_ENTERPRISE MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig) #else -MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig, +MainWindow::MainWindow (AppConfig& appConfig, LicenseManager& licenseManager) #endif : @@ -106,11 +106,10 @@ MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig, m_ActivationDialogRunning(false), #endif m_pZeroconf(nullptr), - m_Settings(settings), m_AppConfig(&appConfig), m_pSynergy(NULL), m_SynergyState(synergyDisconnected), - m_ServerConfig(&m_Settings, 5, 3, m_AppConfig->screenName(), this), + m_ServerConfig(&appConfig.settings(), 5, 3, m_AppConfig->screenName(), this), m_pTempConfigFile(NULL), m_pTrayIcon(NULL), m_pTrayIconMenu(NULL), diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 79b81081e..add5ade57 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -97,7 +97,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase #ifdef SYNERGY_ENTERPRISE MainWindow(QSettings& settings, AppConfig& appConfig); #else - MainWindow(QSettings& settings, AppConfig& appConfig, + MainWindow(AppConfig& appConfig, LicenseManager& licenseManager); #endif ~MainWindow(); @@ -160,7 +160,7 @@ public slots: void saveSettings(); protected: - QSettings& settings() { return m_Settings; } + QSettings& settings() { return appConfig().settings(); } AppConfig& appConfig() { return *m_AppConfig; } QProcess* synergyProcess() { return m_pSynergy; } void setSynergyProcess(QProcess* p) { m_pSynergy = p; } @@ -212,7 +212,6 @@ public slots: QStringList m_PendingClientNames; #endif Zeroconf* m_pZeroconf; - QSettings& m_Settings; AppConfig* m_AppConfig; QProcess* m_pSynergy; int m_SynergyState; diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index e05b7ba84..1c6d3761f 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -110,7 +110,7 @@ int main(int argc, char* argv[]) #ifdef SYNERGY_ENTERPRISE MainWindow mainWindow(settings, appConfig); #else - MainWindow mainWindow(userSettings, appConfig, licenseManager); + MainWindow mainWindow(appConfig, licenseManager); #endif QObject::connect(dynamic_cast(&app), SIGNAL(aboutToQuit()), From 0243ba91710590396196ca674e75111bb50089a2 Mon Sep 17 00:00:00 2001 From: jnewbon Date: Tue, 25 Feb 2020 16:32:46 +0000 Subject: [PATCH 04/25] #6583 Changed Server config to pull Settings directly from AppConfig instead of maintaining its own pointer Signed-off-by: jnewbon --- src/gui/src/ServerConfig.cpp | 30 +++++++++++++++++------------- src/gui/src/ServerConfig.h | 7 ++++--- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp index fd821e5ad..11797181c 100644 --- a/src/gui/src/ServerConfig.cpp +++ b/src/gui/src/ServerConfig.cpp @@ -42,21 +42,21 @@ static const struct const int serverDefaultIndex = 7; -ServerConfig::ServerConfig(QSettings* settings, int numColumns, int numRows , +ServerConfig::ServerConfig(AppConfig* appConfig, int numColumns, int numRows , QString serverName, MainWindow* mainWindow) : - m_pSettings(settings), - m_Screens(), - m_NumColumns(numColumns), - m_NumRows(numRows), - m_ServerName(serverName), - m_IgnoreAutoConfigClient(false), - m_EnableDragAndDrop(false), - m_DisableLockToScreen(false), - m_ClipboardSharing(true), - m_ClipboardSharingSize(defaultClipboardSharingSize()), - m_pMainWindow(mainWindow) + m_pAppConfig(appConfig), + m_Screens(), + m_NumColumns(numColumns), + m_NumRows(numRows), + m_ServerName(serverName), + m_IgnoreAutoConfigClient(false), + m_EnableDragAndDrop(false), + m_DisableLockToScreen(false), + m_ClipboardSharing(true), + m_ClipboardSharingSize(defaultClipboardSharingSize()), + m_pMainWindow(mainWindow) { - Q_ASSERT(m_pSettings); + Q_ASSERT(m_pAppConfig); loadSettings(); } @@ -430,3 +430,7 @@ size_t ServerConfig::setClipboardSharingSize(size_t size) { swap (size, m_ClipboardSharingSize); return size; } + +QSettings &ServerConfig::settings() { + return m_pAppConfig->settings(); +} diff --git a/src/gui/src/ServerConfig.h b/src/gui/src/ServerConfig.h index fb3284ce5..506e4edfd 100644 --- a/src/gui/src/ServerConfig.h +++ b/src/gui/src/ServerConfig.h @@ -32,6 +32,7 @@ class QString; class QFile; class ServerConfigDialog; class MainWindow; +class AppConfig; class ServerConfig : public BaseConfig { @@ -39,7 +40,7 @@ class ServerConfig : public BaseConfig friend QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config); public: - ServerConfig(QSettings* settings, int numColumns, int numRows, + ServerConfig(AppConfig* settings, int numColumns, int numRows, QString serverName, MainWindow* mainWindow); ~ServerConfig(); @@ -75,7 +76,7 @@ class ServerConfig : public BaseConfig int autoAddScreen(const QString name); protected: - QSettings& settings() { return *m_pSettings; } + QSettings& settings(); ScreenList& screens() { return m_Screens; } void setScreens(const ScreenList& screens) { m_Screens = screens; } void addScreen(const Screen& screen) { m_Screens.append(screen); } @@ -110,7 +111,7 @@ class ServerConfig : public BaseConfig void addToFirstEmptyGrid(const QString& clientName); private: - QSettings* m_pSettings; + AppConfig* m_pAppConfig; ScreenList m_Screens; int m_NumColumns; int m_NumRows; From d4ae9faad054db7b8dd3043248af7e76024522d6 Mon Sep 17 00:00:00 2001 From: jnewbon Date: Tue, 25 Feb 2020 17:00:30 +0000 Subject: [PATCH 05/25] #6538 Added settings scope switching to AppConfig Signed-off-by: jnewbon --- src/gui/src/AppConfig.cpp | 86 ++++++++++++++++++++++++++++++++++---- src/gui/src/AppConfig.h | 45 +++++++++++++++++--- src/gui/src/MainWindow.cpp | 17 +++++++- 3 files changed, 134 insertions(+), 14 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 93924a3ca..0203c8c56 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -22,6 +22,8 @@ #include #include +#include +#include #if defined(Q_OS_WIN) const char AppConfig::m_SynergysName[] = "synergys.exe"; @@ -58,7 +60,8 @@ const char* AppConfig::m_SynergySettingsName[] = { "lastVersion", "lastExpiringWarningTime", "activationHasRun", - "minimizeToTray" + "minimizeToTray", + "loadFromSystemScope" }; @@ -72,7 +75,9 @@ static const char* logLevelNames[] = }; AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : - m_pSettings(userSettings), + m_pSettings(nullptr), + m_pUserSettings(userSettings), + m_pSystemSettings(systemSettings), m_ScreenName(), m_Port(24800), m_Interface(), @@ -87,17 +92,17 @@ AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : m_AutoConfigServer(), m_MinimizeToTray(false) { - Q_ASSERT(m_pSettings); - //If user setting dont exist but system ones do, load the system setting and save them to user settings + //If user setting don't exist but system ones do, load the system settings if (!settingsExist(userSettings) && settingsExist(systemSettings)) { m_pSettings = systemSettings; - loadSettings(); + } else { // Otherwise just load to user scope m_pSettings = userSettings; - saveSettings(); } + Q_ASSERT(m_pSettings); + loadSettings(); } @@ -175,7 +180,7 @@ bool AppConfig::autoConfig() const { QString AppConfig::autoConfigServer() const { return m_AutoConfigServer; } -void AppConfig::loadSettings() +void AppConfig::loadSettings(bool ignoreSystem) { m_ScreenName = loadSetting(ScreenName, QHostInfo::localHostName()).toString(); m_Port = loadSetting(Port, 24800).toInt(); @@ -208,7 +213,17 @@ void AppConfig::loadSettings() m_LastExpiringWarningTime = loadSetting(LastExpireWarningTime, 0).toInt(); m_ActivationHasRun = loadSetting(ActivationHasRun, false).toBool(); m_MinimizeToTray = loadSetting(MinimizeToTray, false).toBool(); + m_LoadFromSystemScope = loadSetting(LoadSystemSettings, false).toBool(); + //If this is user scope and the user chose switch to global but ignoreSystem is not set. + if (settings().scope() == QSettings::UserScope && + m_LoadFromSystemScope && + !ignoreSystem) + { + //Switch to global scope and reload settings + switchToGlobal(); + loadSettings(); + } } void AppConfig::saveSettings() @@ -366,3 +381,60 @@ void AppConfig::setSetting(AppConfig::Setting name, T value) { QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& defaultValue) { return settings().value(settingName(name), defaultValue); } + +AppConfig::SaveChoice AppConfig::checkGlobalSave() { + if (settings().scope() == QSettings::Scope::SystemScope) { + + QMessageBox query; + query.setWindowTitle(tr("Save global settings.")); + query.setText(tr("This will overwrite the settings of anybody else that uses this computer.")); + + query.addButton(QMessageBox::Save); + const auto* pBtnCancel = query.addButton(QMessageBox::Cancel); + const auto* pBtnSaveLocal = query.addButton(tr("Save to user"), QMessageBox::ActionRole); + + query.setDefaultButton(QMessageBox::Cancel); + + query.exec(); + + if(query.clickedButton() == pBtnSaveLocal) + { + return SaveToUser; + } + else if(query.clickedButton() == pBtnCancel) + { + return Cancel; + } + } + return Save; +} + +void AppConfig::switchToGlobal(bool global) { + m_settings_lock.lock(); + if (global) + { + m_pSettings = m_pSystemSettings; + } + else + { + m_pSettings = m_pUserSettings; + } + m_settings_lock.unlock(); +} + +void AppConfig::setLoadFromSystemScope(bool value) { + if (value && settings().scope() == QSettings::UserScope) + { + m_LoadFromSystemScope = value; + saveSettings(); //Save user prefs + switchToGlobal(); //Switch the the System Scope + loadSettings(); //Load the settings. + } + else if (!value && settings().scope() == QSettings::SystemScope) + { + switchToGlobal(false); // Switch to UserScope + loadSettings(true); // Load user settings ignoring System scope setting + m_LoadFromSystemScope = value; // Set the user pref + saveSettings(); // Save user prefs + } +} diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index c6bdd34b9..3adf7169e 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -25,6 +25,7 @@ #include #include "ElevateMode.h" #include +#include // this should be incremented each time a new page is added. this is // saved to settings when the user finishes running the wizard. if @@ -64,6 +65,12 @@ class AppConfig: public QObject ~AppConfig(); public: + enum SaveChoice { + Save, + Cancel, + SaveToUser + }; + /// @brief Gets the current settings. /// @return The scoped setting currently selected QSettings& settings(); @@ -112,6 +119,14 @@ class AppConfig: public QObject bool activationHasRun() const; AppConfig& activationHasRun(bool value); #endif + /// @brief Sets the user preference to load from SystemScope. + /// @param [in] value + /// True - This will set the variable, and save the user settings before loading the global scope settings + /// False - This will load the UserScope then set the variable and save. + void setLoadFromSystemScope(bool value); + + /// @brief Returns true if the setting should be set to global scope. Only useful if current scope is UserScope + bool getLoadFromSystemScope() const; QString lastVersion() const; @@ -126,6 +141,16 @@ class AppConfig: public QObject /// @return True if the setting was found. static bool settingsExist(QSettings* settings); + /// @brief If the scope is set to system, this function will query the user + /// if they want to continue saving to global scope or switch to user scope + /// if the scope is set to User the function will just return Save + /// @return SaveChoice The choice that was selected, or Save if the scope is user already + SaveChoice checkGlobalSave(); + + /// @brief This will switch the scope to or from global + /// @param [in] global bool Defaults to true to switch to global scope, False to set to User scope + void switchToGlobal(bool global = true); + protected: /// @brief The enumeration to easily access the names of the setting inside m_SynergySettingsName enum Setting { @@ -151,9 +176,9 @@ protected: ActivationHasRun, MinimizeToTray, ActivateEmail, + LoadSystemSettings, }; - QSettings& settings(); void setScreenName(const QString& s); void setPort(int i); void setNetworkInterface(const QString& s); @@ -164,11 +189,16 @@ protected: void setLanguage(const QString language); void setStartedBefore(bool b); void setElevateMode(ElevateMode em); - void loadSettings(); + + /// @brief loads the setting from the current scope + /// @param ignoreSystem should the load feature ignore the globalScope setting that was saved + void loadSettings(bool ignoreSystem = false); static QString settingName(AppConfig::Setting name); private: - QSettings* m_pSettings; + QSettings* m_pSettings; /// @brief Contain the current settings scope + QSettings* m_pUserSettings; /// @brief Contains the setting in UserScope + QSettings* m_pSystemSettings; /// @brief Contains the setting in SystemScope QString m_ScreenName; int m_Port; QString m_Interface; @@ -191,6 +221,9 @@ protected: int m_LastExpiringWarningTime; bool m_ActivationHasRun; bool m_MinimizeToTray; + bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope + /// If the user has settings but this is true then + /// system settings will be loaded instead of the users static const char m_SynergysName[]; static const char m_SynergycName[]; @@ -210,8 +243,10 @@ protected: /// @param [in] defaultValue The default value of the setting QVariant loadSetting(AppConfig::Setting name, const QVariant& defaultValue = QVariant()); - /// @brief This will save the settings to globalScope instead of userScope - void saveToGlobalScope(); + /// @brief As the settings will be accessible by multiple objects this lock will ensure that + /// it cant be modified by more that one object at a time if the setting is being switched + /// from system to user. + std::mutex m_settings_lock; signals: void sslToggled(bool enabled); diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index d3e1ee8d5..99f8d30bf 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -35,6 +35,7 @@ #include "ProcessorArch.h" #include "SslCertificate.h" #include "Zeroconf.h" +#include #if defined(Q_OS_MAC) #include "OSXHelpers.h" @@ -109,7 +110,7 @@ MainWindow::MainWindow (AppConfig& appConfig, m_AppConfig(&appConfig), m_pSynergy(NULL), m_SynergyState(synergyDisconnected), - m_ServerConfig(&appConfig.settings(), 5, 3, m_AppConfig->screenName(), this), + m_ServerConfig(m_AppConfig, 5, 3, m_AppConfig->screenName(), this), m_pTempConfigFile(NULL), m_pTrayIcon(NULL), m_pTrayIconMenu(NULL), @@ -348,7 +349,19 @@ void MainWindow::saveSettings() settings().setValue("groupClientChecked", m_pGroupClient->isChecked()); settings().setValue("serverHostname", m_pLineEditHostname->text()); - settings().sync(); + auto choice = appConfig().checkGlobalSave(); + + switch (choice) + { + case AppConfig::SaveToUser: + //Switch to local and overrun into the save case + appConfig().switchToGlobal(false); + case AppConfig::Save: + settings().sync(); + break; + default: + break; + } } void MainWindow::setIcon(qSynergyState state) From 691019c6b5150a19bf4fdd20829c2e97f143b383 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 27 Feb 2020 00:40:58 +0000 Subject: [PATCH 06/25] #6538 Fixed missing setting and added function to remove repetitions --- src/gui/src/AppConfig.cpp | 14 +++++++++----- src/gui/src/AppConfig.h | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 0203c8c56..5aceca0f5 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -61,11 +61,10 @@ const char* AppConfig::m_SynergySettingsName[] = { "lastExpiringWarningTime", "activationHasRun", "minimizeToTray", + "ActivateEmail", "loadFromSystemScope" }; - - static const char* logLevelNames[] = { "INFO", @@ -251,6 +250,7 @@ void AppConfig::saveSettings() setSetting(LastExpireWarningTime, m_LastExpiringWarningTime); setSetting(ActivationHasRun, m_ActivationHasRun); setSetting(MinimizeToTray, m_MinimizeToTray); + setSetting(LoadSystemSettings, m_LoadFromSystemScope); settings().sync(); } @@ -383,7 +383,7 @@ QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& default } AppConfig::SaveChoice AppConfig::checkGlobalSave() { - if (settings().scope() == QSettings::Scope::SystemScope) { + if (isSystemScoped()) { QMessageBox query; query.setWindowTitle(tr("Save global settings.")); @@ -423,14 +423,14 @@ void AppConfig::switchToGlobal(bool global) { } void AppConfig::setLoadFromSystemScope(bool value) { - if (value && settings().scope() == QSettings::UserScope) + if (value && !isSystemScoped()) { m_LoadFromSystemScope = value; saveSettings(); //Save user prefs switchToGlobal(); //Switch the the System Scope loadSettings(); //Load the settings. } - else if (!value && settings().scope() == QSettings::SystemScope) + else if (!value && isSystemScoped()) { switchToGlobal(false); // Switch to UserScope loadSettings(true); // Load user settings ignoring System scope setting @@ -438,3 +438,7 @@ void AppConfig::setLoadFromSystemScope(bool value) { saveSettings(); // Save user prefs } } + +bool AppConfig::isSystemScoped() const { + return m_pSettings->scope() == QSettings::SystemScope; +} diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 3adf7169e..83e02fa97 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -75,6 +75,8 @@ class AppConfig: public QObject /// @return The scoped setting currently selected QSettings& settings(); + bool isSystemScoped() const; + const QString& screenName() const; int port() const; const QString& networkInterface() const; From d4ecffd1f0e2d1c256542b352f374986c013726f Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 27 Feb 2020 00:41:27 +0000 Subject: [PATCH 07/25] #6538 Added Scope selection to settings --- src/gui/src/SettingsDialog.cpp | 10 ++++++++++ src/gui/src/SettingsDialogBase.ui | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 8c512a414..b33bbdb01 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -60,6 +60,13 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + if (m_appConfig.isSystemScoped()) { + m_pRadioSystemScope->setChecked(true); + } + else { + m_pRadioUserScope->setChecked(true); + } + #if defined(Q_OS_WIN) m_pBonjourWindows = new BonjourWindows(this, m_pMainWindow, m_appConfig); if (m_pBonjourWindows->isRunning()) { @@ -111,6 +118,9 @@ void SettingsDialog::accept() appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked()); appConfig().setAutoConfig(m_pCheckBoxAutoConfig->isChecked()); appConfig().setMinimizeToTray(m_pCheckBoxMinimizeToTray->isChecked()); + + //We only need to test the System scoped Radio as they are connected + appConfig().setLoadFromSystemScope(m_pRadioSystemScope->isChecked()); appConfig().saveSettings(); QDialog::accept(); } diff --git a/src/gui/src/SettingsDialogBase.ui b/src/gui/src/SettingsDialogBase.ui index 10bcc5891..ef7fcc806 100644 --- a/src/gui/src/SettingsDialogBase.ui +++ b/src/gui/src/SettingsDialogBase.ui @@ -13,7 +13,34 @@ Settings + + + + + &Settings Scope + + + + + + System + + + true + + + + + + + User + + + + + + From 70f50a655ba5e2c2d4876c6f3535c0442923306c Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Fri, 28 Feb 2020 11:33:30 +0000 Subject: [PATCH 08/25] #6538 Moved System scope to ini format and saved to application folder --- src/gui/src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 1c6d3761f..5e036be81 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -88,10 +88,16 @@ int main(int argc, char* argv[]) #ifndef Q_OS_WIN QApplication::setQuitOnLastWindowClosed(false); #endif + //Set the path of the system settings to the programs local folder + //as the default system settings path has problems writing without Admin/root permission + QSettings::setPath(QSettings::Format::IniFormat, + QSettings::Scope::SystemScope, + QString("SystemSettings")); //Config will default to User settings if they exist, // otherwise it will load System setting and save them to User settings - QSettings systemSettings(QSettings::Scope::SystemScope, + QSettings systemSettings(QSettings::Format::IniFormat, + QSettings::Scope::SystemScope, QCoreApplication::organizationName(), QCoreApplication::applicationName()); From a2009d0aa022c6c0efb9da5d1b525f92e7d08e84 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Fri, 28 Feb 2020 11:34:28 +0000 Subject: [PATCH 09/25] #6538 Added event to live swap configs as soon as the scope is changed in settings --- src/gui/src/SettingsDialog.cpp | 120 ++++++++++++++++++--------------- src/gui/src/SettingsDialog.h | 7 ++ 2 files changed, 73 insertions(+), 54 deletions(-) diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index b33bbdb01..f1546687c 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -49,60 +49,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_Locale.fillLanguageComboBox(m_pComboLanguage); - m_pLineEditScreenName->setText(appConfig().screenName()); - m_pSpinBoxPort->setValue(appConfig().port()); - m_pLineEditInterface->setText(appConfig().networkInterface()); - m_pComboLogLevel->setCurrentIndex(appConfig().logLevel()); - m_pCheckBoxLogToFile->setChecked(appConfig().logToFile()); - m_pLineEditLogFilename->setText(appConfig().logFilename()); - setIndexFromItemData(m_pComboLanguage, appConfig().language()); - m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide()); - m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); - m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); - - if (m_appConfig.isSystemScoped()) { - m_pRadioSystemScope->setChecked(true); - } - else { - m_pRadioUserScope->setChecked(true); - } - -#if defined(Q_OS_WIN) - m_pBonjourWindows = new BonjourWindows(this, m_pMainWindow, m_appConfig); - if (m_pBonjourWindows->isRunning()) { - allowAutoConfig(); - } - - m_pComboElevate->setCurrentIndex(static_cast(appConfig().elevateMode())); - -#else - // elevate checkbox is only useful on ms windows. - m_pLabelElevate->hide(); - m_pComboElevate->hide(); - - // for linux and mac, allow auto config by default - allowAutoConfig(); -#endif - - m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); - -#ifdef SYNERGY_ENTERPRISE - - m_pCheckBoxEnableCrypto->setEnabled(true); - m_pLabelProUpgrade->hide(); - - m_pCheckBoxAutoConfig->hide(); - m_pLabelInstallBonjour->hide(); - -#else - - bool isPro = m_appConfig.edition() == kPro; - m_pCheckBoxEnableCrypto->setEnabled(isPro); - m_pLabelProUpgrade->setVisible(!isPro); - - m_pCheckBoxAutoConfig->setChecked(appConfig().autoConfig()); - -#endif + loadFromConfig(); } void SettingsDialog::accept() @@ -158,6 +105,65 @@ void SettingsDialog::changeEvent(QEvent* event) } } +void SettingsDialog::loadFromConfig() { + + m_pLineEditScreenName->setText(appConfig().screenName()); + m_pSpinBoxPort->setValue(appConfig().port()); + m_pLineEditInterface->setText(appConfig().networkInterface()); + m_pComboLogLevel->setCurrentIndex(appConfig().logLevel()); + m_pCheckBoxLogToFile->setChecked(appConfig().logToFile()); + m_pLineEditLogFilename->setText(appConfig().logFilename()); + setIndexFromItemData(m_pComboLanguage, appConfig().language()); + m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide()); + m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); + m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + + if (m_appConfig.isSystemScoped()) { + m_pRadioSystemScope->setChecked(true); + } + else { + m_pRadioUserScope->setChecked(true); + } + +#if defined(Q_OS_WIN) + m_pBonjourWindows = new BonjourWindows(this, m_pMainWindow, m_appConfig); + if (m_pBonjourWindows->isRunning()) { + allowAutoConfig(); + } + + m_pComboElevate->setCurrentIndex(static_cast(appConfig().elevateMode())); + +#else + // elevate checkbox is only useful on ms windows. + m_pLabelElevate->hide(); + m_pComboElevate->hide(); + + // for linux and mac, allow auto config by default + allowAutoConfig(); +#endif + + m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + +#ifdef SYNERGY_ENTERPRISE + + m_pCheckBoxEnableCrypto->setEnabled(true); + m_pLabelProUpgrade->hide(); + + m_pCheckBoxAutoConfig->hide(); + m_pLabelInstallBonjour->hide(); + +#else + + bool isPro = m_appConfig.edition() == kPro; + m_pCheckBoxEnableCrypto->setEnabled(isPro); + m_pLabelProUpgrade->setVisible(!isPro); + + m_pCheckBoxAutoConfig->setChecked(appConfig().autoConfig()); + +#endif +} + + void SettingsDialog::allowAutoConfig() { m_pLabelInstallBonjour->hide(); @@ -209,3 +215,9 @@ void SettingsDialog::on_m_pLabelInstallBonjour_linkActivated(const QString&) m_pBonjourWindows->downloadAndInstall(); #endif } + +void SettingsDialog::on_m_pRadioSystemScope_toggled(bool checked) +{ + appConfig().setLoadFromSystemScope(checked); + loadFromConfig(); +} diff --git a/src/gui/src/SettingsDialog.h b/src/gui/src/SettingsDialog.h index 738bb4578..64596dda5 100644 --- a/src/gui/src/SettingsDialog.h +++ b/src/gui/src/SettingsDialog.h @@ -45,6 +45,9 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase void changeEvent(QEvent* event); AppConfig& appConfig() { return m_appConfig; } + /// @brief Causes the dialog to load all the settings from m_appConfig + void loadFromConfig(); + private: MainWindow* m_pMainWindow; AppConfig& m_appConfig; @@ -58,6 +61,10 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase void on_m_pCheckBoxLogToFile_stateChanged(int ); void on_m_pButtonBrowseLog_clicked(); void on_m_pLabelInstallBonjour_linkActivated(const QString &link); + + /// @brief Handles the toggling of the system scoped radio button + /// As the user scope radio is connected this will fire for either radio button + void on_m_pRadioSystemScope_toggled(bool checked); }; #endif From 11eda2037877c5b186aa9a4a77501ae4b2519462 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 19 Mar 2020 15:35:29 +0000 Subject: [PATCH 10/25] #6538 Changed System scope path to be OS dependant --- src/gui/src/main.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 5e036be81..24d80b93a 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -48,6 +48,7 @@ public: }; int waitForTray(); +QString getSystemSettingPath(); #if defined(Q_OS_MAC) bool checkMacAssistiveDevices(); @@ -88,11 +89,10 @@ int main(int argc, char* argv[]) #ifndef Q_OS_WIN QApplication::setQuitOnLastWindowClosed(false); #endif - //Set the path of the system settings to the programs local folder - //as the default system settings path has problems writing without Admin/root permission + //S QSettings::setPath(QSettings::Format::IniFormat, - QSettings::Scope::SystemScope, - QString("SystemSettings")); + QSettings::Scope::SystemScope, + getSystemSettingPath()); //Config will default to User settings if they exist, // otherwise it will load System setting and save them to User settings @@ -160,6 +160,26 @@ int waitForTray() return true; } +QString getSystemSettingPath() +{ + const QString settingFilename("SystemConfig.ini"); + QString path; +#if defined(Q_OS_WIN) + // Program file + path = "" +#elif defined(Q_OS_DARWIN) + //Global preferances dir + // Would be nice to use /library, but QT has no elevate system in place + path = "/usr/local/etc/symless/synergy/"; +#elif defined(Q_OS_LINUX) + // /usr/local/etc/synergy + path = "/usr/local/etc/symless/synergy/"; +#else + assert("OS not supported") +#endif + return path + settingFilename; +} + #if defined(Q_OS_MAC) bool checkMacAssistiveDevices() { From 2bff3807f8feee2b221aadc8a849b1d1e595b027 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Tue, 31 Mar 2020 11:09:50 +0100 Subject: [PATCH 11/25] #6538 Moved settings from main window to appconfig --- src/gui/src/AppConfig.cpp | 74 +++++++++++++++++++++++++++++++++++++- src/gui/src/AppConfig.h | 32 +++++++++++++++++ src/gui/src/MainWindow.cpp | 49 +++++++++++++------------ 3 files changed, 131 insertions(+), 24 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 5aceca0f5..c2d7a100b 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -29,11 +29,13 @@ const char AppConfig::m_SynergysName[] = "synergys.exe"; const char AppConfig::m_SynergycName[] = "synergyc.exe"; const char AppConfig::m_SynergyLogDir[] = "log/"; +const char AppConfig::synergyConfigName[] = "synergy.sgc"; #define DEFAULT_PROCESS_MODE Service #else const char AppConfig::m_SynergysName[] = "synergys"; const char AppConfig::m_SynergycName[] = "synergyc"; const char AppConfig::m_SynergyLogDir[] = "/var/log/"; +const char AppConfig::synergyConfigName[] = "synergy.conf"; #define DEFAULT_PROCESS_MODE Desktop #endif @@ -62,7 +64,13 @@ const char* AppConfig::m_SynergySettingsName[] = { "activationHasRun", "minimizeToTray", "ActivateEmail", - "loadFromSystemScope" + "loadFromSystemScope", + "groupServerChecked", + "useExternalConfig", + "configFile", + "useInternalConfig", + "groupClientChecked", + "serverHostname", }; static const char* logLevelNames[] = @@ -213,6 +221,12 @@ void AppConfig::loadSettings(bool ignoreSystem) m_ActivationHasRun = loadSetting(ActivationHasRun, false).toBool(); m_MinimizeToTray = loadSetting(MinimizeToTray, false).toBool(); m_LoadFromSystemScope = loadSetting(LoadSystemSettings, false).toBool(); + m_ServerGroupChecked = loadSetting(GroupServerCheck, false).toBool(); + m_UseExternalConfig = loadSetting(UseExternalConfig, false).toBool(); + m_ConfigFile = loadSetting(ConfigFile, QDir::homePath() + "/" + synergyConfigName).toString(); + m_UseInternalConfig = loadSetting(UseInternalConfig, false).toBool(); + m_ClientGroupChecked = loadSetting(GroupClientCheck, true).toBool(); + m_ServerHostname = loadSetting(ServerHostname).toString(); //If this is user scope and the user chose switch to global but ignoreSystem is not set. if (settings().scope() == QSettings::UserScope && @@ -251,6 +265,12 @@ void AppConfig::saveSettings() setSetting(ActivationHasRun, m_ActivationHasRun); setSetting(MinimizeToTray, m_MinimizeToTray); setSetting(LoadSystemSettings, m_LoadFromSystemScope); + setSetting(GroupServerCheck, m_ServerGroupChecked); + setSetting(UseExternalConfig, m_UseExternalConfig); + setSetting(ConfigFile, m_ConfigFile); + setSetting(UseInternalConfig, m_UseInternalConfig); + setSetting(GroupClientCheck, m_ClientGroupChecked); + setSetting(ServerHostname, m_ServerHostname); settings().sync(); } @@ -442,3 +462,55 @@ void AppConfig::setLoadFromSystemScope(bool value) { bool AppConfig::isSystemScoped() const { return m_pSettings->scope() == QSettings::SystemScope; } + +bool AppConfig::unsavedChanges() { + return m_SettingModified; +} + +bool AppConfig::getServerGroupChecked() const { + return m_ServerGroupChecked; +} + +bool AppConfig::getUseExternalConfig() const { + return m_UseExternalConfig; +} + +QString AppConfig::getConfigFile() const { + return m_ConfigFile; +} + +bool AppConfig::getUseInternalConfig() const { + return m_UseInternalConfig; +} + +bool AppConfig::getClientGroupChecked() const { + return m_ClientGroupChecked; +} + +QString AppConfig::getServerHostname() const { + return m_ServerHostname; +} + +void AppConfig::setServerGroupChecked(bool newValue) { + m_ServerGroupChecked = newValue; +} + +void AppConfig::setUseExternalConfig(bool newValue) { + m_UseExternalConfig = newValue; +} + +void AppConfig::setConfigFile(const QString& newValue) { + m_ConfigFile = newValue; +} + +void AppConfig::setUseInternalConfig(bool newValue) { + m_UseInternalConfig = newValue; +} + +void AppConfig::setClientGroupChecked(bool newValue) { + m_ClientGroupChecked = newValue; +} + +void AppConfig::setServerHostname(const QString& newValue) { + m_ServerHostname = newValue; +} diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 83e02fa97..2f33ae012 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -130,6 +130,21 @@ class AppConfig: public QObject /// @brief Returns true if the setting should be set to global scope. Only useful if current scope is UserScope bool getLoadFromSystemScope() const; + + bool getServerGroupChecked() const; + bool getUseExternalConfig() const; + QString getConfigFile() const; + bool getUseInternalConfig() const; + bool getClientGroupChecked() const; + QString getServerHostname() const; + + void setServerGroupChecked(bool); + void setUseExternalConfig(bool) ; + void setConfigFile(const QString&); + void setUseInternalConfig(bool) ; + void setClientGroupChecked(bool) ; + void setServerHostname(const QString&); + QString lastVersion() const; void setMinimizeToTray(bool b); @@ -179,6 +194,12 @@ protected: MinimizeToTray, ActivateEmail, LoadSystemSettings, + GroupServerCheck, + UseExternalConfig, + ConfigFile, + UseInternalConfig, + GroupClientCheck, + ServerHostname, }; void setScreenName(const QString& s); @@ -223,6 +244,14 @@ protected: int m_LastExpiringWarningTime; bool m_ActivationHasRun; bool m_MinimizeToTray; + + bool m_ServerGroupChecked; + bool m_UseExternalConfig; + QString m_ConfigFile; + bool m_UseInternalConfig; + bool m_ClientGroupChecked; + QString m_ServerHostname; + bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope /// If the user has settings but this is true then /// system settings will be loaded instead of the users @@ -234,6 +263,9 @@ protected: /// @brief Contains the string values of the settings names that will be saved static const char* m_SynergySettingsName[]; + /// @brief Contains the name of the default configuration filename + static const char synergyConfigName[]; + /// @brief Sets the value of a setting /// @param [in] name The Setting to be saved /// @param [in] value The Value to be saved diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 5828a17f9..7c772f6a2 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -323,13 +323,13 @@ void MainWindow::loadSettings() { // the next two must come BEFORE loading groupServerChecked and groupClientChecked or // disabling and/or enabling the right widgets won't automatically work - m_pRadioExternalConfig->setChecked(settings().value("useExternalConfig", false).toBool()); - m_pRadioInternalConfig->setChecked(settings().value("useInternalConfig", true).toBool()); + m_pRadioExternalConfig->setChecked(appConfig().getUseExternalConfig()); + m_pRadioInternalConfig->setChecked(appConfig().getUseInternalConfig()); - m_pGroupServer->setChecked(settings().value("groupServerChecked", false).toBool()); - m_pLineEditConfigFile->setText(settings().value("configFile", QDir::homePath() + "/" + synergyConfigName).toString()); - m_pGroupClient->setChecked(settings().value("groupClientChecked", true).toBool()); - m_pLineEditHostname->setText(settings().value("serverHostname").toString()); + m_pGroupServer->setChecked(appConfig().getServerGroupChecked())); + m_pLineEditConfigFile->setText(appConfig().getConfigFile()); + m_pGroupClient->setChecked(appConfig().getClientGroupChecked()); + m_pLineEditHostname->setText(appConfig().getServerHostname()); } void MainWindow::initConnections() @@ -345,25 +345,28 @@ void MainWindow::initConnections() void MainWindow::saveSettings() { // program settings - settings().setValue("groupServerChecked", m_pGroupServer->isChecked()); - settings().setValue("useExternalConfig", m_pRadioExternalConfig->isChecked()); - settings().setValue("configFile", m_pLineEditConfigFile->text()); - settings().setValue("useInternalConfig", m_pRadioInternalConfig->isChecked()); - settings().setValue("groupClientChecked", m_pGroupClient->isChecked()); - settings().setValue("serverHostname", m_pLineEditHostname->text()); + appConfig().setServerGroupChecked(m_pGroupServer->isChecked()); + appConfig().setClientGroupChecked(m_pGroupClient->isChecked()); + appConfig().setUseExternalConfig(m_pRadioExternalConfig->isChecked()); + appConfig().setUseInternalConfig(m_pRadioInternalConfig->isChecked()); + appConfig().setConfigFile(m_pLineEditConfigFile->text()); + appConfig().setServerHostname(m_pLineEditHostname->text()); - auto choice = appConfig().checkGlobalSave(); - switch (choice) - { - case AppConfig::SaveToUser: - //Switch to local and overrun into the save case - appConfig().switchToGlobal(false); - case AppConfig::Save: - settings().sync(); - break; - default: - break; + //Save if there are any unsaved changes otherwise skip + if (appConfig().unsavedChanges()) { + auto choice = appConfig().checkGlobalSave(); + + switch (choice) { + case AppConfig::SaveToUser: + //Switch to local and overrun into the save case + appConfig().switchToGlobal(false); + case AppConfig::Save: + settings().sync(); + break; + default: + break; + } } } From c62d23ab06122f259a30f574a2a1d437449359f8 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Tue, 31 Mar 2020 15:18:57 +0100 Subject: [PATCH 12/25] #6538 started adding modified settings check to prevent saving changes multiple times --- src/gui/src/AppConfig.cpp | 102 +++++++++++++++++++++++++------------ src/gui/src/AppConfig.h | 20 ++++++-- src/gui/src/MainWindow.cpp | 4 +- 3 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index c2d7a100b..78951e094 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -97,7 +97,8 @@ AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : m_AutoHide(false), m_LastExpiringWarningTime(0), m_AutoConfigServer(), - m_MinimizeToTray(false) + m_MinimizeToTray(false), + m_SettingModified(false) { //If user setting don't exist but system ones do, load the system settings @@ -273,6 +274,7 @@ void AppConfig::saveSettings() setSetting(ServerHostname, m_ServerHostname); settings().sync(); + m_SettingModified = false; } #ifndef SYNERGY_ENTERPRISE @@ -293,53 +295,71 @@ QString AppConfig::lastVersion() const return m_lastVersion; } -void AppConfig::setLastVersion(QString version) { - m_lastVersion = version; +void AppConfig::setLastVersion(const QString& version) { + setSettingModified(m_lastVersion, version); } QSettings &AppConfig::settings() { return *m_pSettings; } -void AppConfig::setScreenName(const QString &s) { m_ScreenName = s; } +void AppConfig::setScreenName(const QString &s) { + setSettingModified(m_ScreenName, s); +} -void AppConfig::setPort(int i) { m_Port = i; } +void AppConfig::setPort(int i) { + setSettingModified(m_Port, i); +} -void AppConfig::setNetworkInterface(const QString &s) { m_Interface = s; } +void AppConfig::setNetworkInterface(const QString &s) { + setSettingModified(m_Interface, s); +} -void AppConfig::setLogLevel(int i) { m_LogLevel = i; } +void AppConfig::setLogLevel(int i) { + setSettingModified(m_LogLevel, i); +} -void AppConfig::setLogToFile(bool b) { m_LogToFile = b; } +void AppConfig::setLogToFile(bool b) { + setSettingModified(m_LogToFile, b); +} -void AppConfig::setLogFilename(const QString &s) { m_LogFilename = s; } +void AppConfig::setLogFilename(const QString &s) { + setSettingModified(m_LogFilename, s); +} -void AppConfig::setWizardHasRun() { m_WizardLastRun = kWizardVersion; } +void AppConfig::setWizardHasRun() { + setSettingModified(m_WizardLastRun, kWizardVersion); +} -void AppConfig::setLanguage(const QString language) { m_Language = language; } +void AppConfig::setLanguage(const QString& language) { + setSettingModified(m_Language, language); +} -void AppConfig::setStartedBefore(bool b) { m_StartedBefore = b; } +void AppConfig::setStartedBefore(bool b) { + setSettingModified(m_StartedBefore, b); +} -void AppConfig::setElevateMode(ElevateMode em) { m_ElevateMode = em; } +void AppConfig::setElevateMode(ElevateMode em) { + setSettingModified(m_ElevateMode, em); +} void AppConfig::setAutoConfig(bool autoConfig) { - m_AutoConfig = autoConfig; + setSettingModified(m_AutoConfig, autoConfig); } -void AppConfig::setAutoConfigServer(QString autoConfigServer) +void AppConfig::setAutoConfigServer(const QString& autoConfigServer) { - m_AutoConfigServer = autoConfigServer; + setSettingModified(m_AutoConfigServer, autoConfigServer); } #ifndef SYNERGY_ENTERPRISE void AppConfig::setEdition(Edition e) { - m_Edition = e; + setSettingModified(m_Edition, e); } Edition AppConfig::edition() const { return m_Edition; } -QString AppConfig::setSerialKey(QString serial) { - using std::swap; - swap (serial, m_Serialkey); - return serial; +void AppConfig::setSerialKey(const QString& serial) { + setSettingModified(m_Serialkey, serial); } void AppConfig::clearSerialKey() @@ -351,7 +371,9 @@ QString AppConfig::serialKey() { return m_Serialkey; } int AppConfig::lastExpiringWarningTime() const { return m_LastExpiringWarningTime; } -void AppConfig::setLastExpiringWarningTime(int t) { m_LastExpiringWarningTime = t; } +void AppConfig::setLastExpiringWarningTime(int newValue) { + setSettingModified(m_LastExpiringWarningTime, newValue); +} #endif QString AppConfig::synergysName() const { return m_SynergysName; } @@ -363,9 +385,9 @@ ElevateMode AppConfig::elevateMode() return m_ElevateMode; } -void AppConfig::setCryptoEnabled(bool e) { - m_CryptoEnabled = e; - emit sslToggled(e); +void AppConfig::setCryptoEnabled(bool newValue) { + setSettingModified(m_CryptoEnabled, newValue); + emit sslToggled(m_CryptoEnabled); } bool AppConfig::getCryptoEnabled() const { @@ -376,11 +398,15 @@ bool AppConfig::getCryptoEnabled() const { m_CryptoEnabled; } -void AppConfig::setAutoHide(bool b) { m_AutoHide = b; } +void AppConfig::setAutoHide(bool b) { + setSettingModified(m_MinimizeToTray, b); +} bool AppConfig::getAutoHide() { return m_AutoHide; } -void AppConfig::setMinimizeToTray(bool b) { m_MinimizeToTray = b; } +void AppConfig::setMinimizeToTray(bool newValue) { + setSettingModified(m_MinimizeToTray, newValue); +} bool AppConfig::getMinimizeToTray() { return m_MinimizeToTray; } @@ -492,25 +518,35 @@ QString AppConfig::getServerHostname() const { } void AppConfig::setServerGroupChecked(bool newValue) { - m_ServerGroupChecked = newValue; + setSettingModified(m_ServerGroupChecked, newValue); } void AppConfig::setUseExternalConfig(bool newValue) { - m_UseExternalConfig = newValue; + setSettingModified(m_UseExternalConfig, newValue); } void AppConfig::setConfigFile(const QString& newValue) { - m_ConfigFile = newValue; + setSettingModified(m_ConfigFile, newValue); } void AppConfig::setUseInternalConfig(bool newValue) { - m_UseInternalConfig = newValue; + setSettingModified(m_UseInternalConfig, newValue); } void AppConfig::setClientGroupChecked(bool newValue) { - m_ClientGroupChecked = newValue; + setSettingModified(m_ClientGroupChecked, newValue); } void AppConfig::setServerHostname(const QString& newValue) { - m_ServerHostname = newValue; + setSettingModified(m_ServerHostname, newValue); } + +template +void AppConfig::setSettingModified(T &variable, const T& newValue) { + if (variable != newValue) + { + variable = newValue; + m_SettingModified = true; + } +} + diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 2f33ae012..966966f62 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -92,11 +92,11 @@ class AppConfig: public QObject bool autoConfig() const; void setAutoConfig(bool autoConfig); QString autoConfigServer() const; - void setAutoConfigServer(QString autoConfigServer); + void setAutoConfigServer(const QString& autoConfigServer); #ifndef SYNERGY_ENTERPRISE void setEdition(Edition); Edition edition() const; - QString setSerialKey(QString serial); + void setSerialKey(const QString& serial); void clearSerialKey(); QString serialKey(); int lastExpiringWarningTime() const; @@ -151,7 +151,11 @@ class AppConfig: public QObject bool getMinimizeToTray(); void saveSettings(); - void setLastVersion(QString version); + void setLastVersion(const QString& version); + + /// @brief settingsExist Checks ths settings to see if they exist in the QSettings location + /// @return bool True if there are unsaved changes + bool unsavedChanges(); /// @brief settingsExist Checks ths settings to see if they exist in the QSettings location /// @param [in] settings The QSettings object to check @@ -209,7 +213,7 @@ protected: void setLogToFile(bool b); void setLogFilename(const QString& s); void setWizardHasRun(); - void setLanguage(const QString language); + void setLanguage(const QString& language); void setStartedBefore(bool b); void setElevateMode(ElevateMode em); @@ -255,6 +259,7 @@ protected: bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope /// If the user has settings but this is true then /// system settings will be loaded instead of the users + bool m_SettingModified; /// @brief Have the setting been changed since the last save static const char m_SynergysName[]; static const char m_SynergycName[]; @@ -282,6 +287,13 @@ protected: /// from system to user. std::mutex m_settings_lock; + /// @brief Sets the setting in the config checking if it has changed and flagging that settings + /// needs to be saved if the setting was different + /// @param [in] variable the setting that will be changed + /// @param [in] newValue The new value of the setting + template + void setSettingModified(T& variable,const T& newValue); + signals: void sslToggled(bool enabled); }; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 7c772f6a2..61966eba6 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -326,7 +326,7 @@ void MainWindow::loadSettings() m_pRadioExternalConfig->setChecked(appConfig().getUseExternalConfig()); m_pRadioInternalConfig->setChecked(appConfig().getUseInternalConfig()); - m_pGroupServer->setChecked(appConfig().getServerGroupChecked())); + m_pGroupServer->setChecked(appConfig().getServerGroupChecked()); m_pLineEditConfigFile->setText(appConfig().getConfigFile()); m_pGroupClient->setChecked(appConfig().getClientGroupChecked()); m_pLineEditHostname->setText(appConfig().getServerHostname()); @@ -362,7 +362,7 @@ void MainWindow::saveSettings() //Switch to local and overrun into the save case appConfig().switchToGlobal(false); case AppConfig::Save: - settings().sync(); + appConfig().saveSettings(); break; default: break; From d061eac117190bccdf9fe9e301d679b0c2a37719 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Wed, 1 Apr 2020 16:30:02 +0100 Subject: [PATCH 13/25] #6538 Fixed missing semicolon --- src/gui/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 24d80b93a..d993160cf 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -166,7 +166,7 @@ QString getSystemSettingPath() QString path; #if defined(Q_OS_WIN) // Program file - path = "" + path = ""; #elif defined(Q_OS_DARWIN) //Global preferances dir // Would be nice to use /library, but QT has no elevate system in place @@ -175,7 +175,7 @@ QString getSystemSettingPath() // /usr/local/etc/synergy path = "/usr/local/etc/symless/synergy/"; #else - assert("OS not supported") + assert("OS not supported"); #endif return path + settingFilename; } From 10f558d86395db2e4cef1ec220a6896630e9515e Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Tue, 21 Apr 2020 15:53:53 +0100 Subject: [PATCH 14/25] #6538 Added ConfigWriter to centralized config file interaction --- src/gui/CMakeLists.txt | 2 +- src/gui/src/ConfigWriter.cpp | 73 ++++++++++++++++++++++++ src/gui/src/ConfigWriter.h | 104 +++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/gui/src/ConfigWriter.cpp create mode 100644 src/gui/src/ConfigWriter.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index bdb4d1f9d..2ea13189f 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -30,7 +30,7 @@ if (SYNERGY_ENTERPRISE) endif () if (WIN32) - set (LEGACY_GUI_RC_FILES res/win/Synergy.rc) + set (LEGACY_GUI_RC_FILES res/win/Synergy.rc src/ConfigWriter.cpp src/ConfigWriter.h) endif() add_executable (synergy WIN32 diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/ConfigWriter.cpp new file mode 100644 index 000000000..165c0fc7f --- /dev/null +++ b/src/gui/src/ConfigWriter.cpp @@ -0,0 +1,73 @@ +// +// Created by jamie on 21/04/2020. +// + +#include "ConfigWriter.h" + +ConfigWriter* ConfigWriter::s_pConfiguration = nullptr; + + +ConfigWriter *ConfigWriter::make() { + // Only one ConfigWriter can exist at any one time (Singolton) + if (!s_pConfiguration) { + s_pConfiguration = new ConfigWriter(); + } + return s_pConfiguration; +} + +ConfigWriter::ConfigWriter() { + +} + +void ConfigWriter::destroy() { + destroy(s_pConfiguration); +} + +ConfigWriter::~ConfigWriter() { + destroy(m_pSettingsCurrent); + destroy(m_pSettingsSystem); + destroy(m_pSettingsUser); +} + +template +void ConfigWriter::setSetting(const char *name, T value) { + +} + +QVariant ConfigWriter::loadSetting(const char *name, const QVariant &defaultValue) { + return QVariant(); +} + + +void ConfigWriter::setScope(ConfigWriter::Scope scope) { + if (m_CurrentScope != scope) + { + m_CurrentScope = scope; + switch (scope) + { + case User: + m_pSettingsCurrent = m_pSettingsUser; + break; + case System: + m_pSettingsCurrent = m_pSettingsSystem; + break; + } + } +} + +ConfigWriter::Scope ConfigWriter::getScope() const { + return m_CurrentScope; +} + +void ConfigWriter::gloablLoad() { + for(auto & i : m_pCallerList) { + i->loadSettings(); + } +} + +void ConfigWriter::globalSave() { + for(auto & i : m_pCallerList) { + i->saveSettings(); + } +} + diff --git a/src/gui/src/ConfigWriter.h b/src/gui/src/ConfigWriter.h new file mode 100644 index 000000000..bcf659b6b --- /dev/null +++ b/src/gui/src/ConfigWriter.h @@ -0,0 +1,104 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2020 - 2020 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef SYNERGY_CORE_CONFIGWRITER_H +#define SYNERGY_CORE_CONFIGWRITER_H + + +#include +#include + +///@brief This abstract class will be used by all classes that use the ConfigWriter +/// to allow global saving and loading +class ConfigBase { +public : + ConfigBase() = default; + virtual ~ConfigBase() = default; + + /// @brief The function that is called when the settings need to be loaded from file + virtual void loadSettings() = 0; + + /// @brief The function that is called when the settings need to be saved to file + virtual void saveSettings() = 0; +}; + +class ConfigWriter { + +public: + + /// @brief the public way to construct the configuration calls + static ConfigWriter* make(); + + /// @brief the public way to destroy the configuration class + static void destroy(); + + ~ConfigWriter(); + + ///@brief An Enumeration of all the scopes available + enum Scope { System, User}; + + /// @brief Sets the value of a setting + /// @param [in] name The Setting to be saved + /// @param [in] value The Value to be saved + template + void setSetting(const char* name, T value); + + /// @brief Loads a setting + /// @param [in] name The setting to be loaded + /// @param [in] defaultValue The default value of the setting + QVariant loadSetting(const char* name, const QVariant& defaultValue = QVariant()); + + /// @brief Changes the setting save and load location between System and User scope + /// @param [in] scope The scope to set + void setScope(Scope scope = User); + + /// @brief Get the current scope the settings are loading and save from. + /// @return Scope An enum defining the current scope + Scope getScope() const; + + /// @brief trigger a config load across all registered classes + void gloablLoad(); + + /// @brief trigger a config save across all registered classes + void globalSave(); + +protected: + + Scope m_CurrentScope = User; /// @brief The current scope of the settings + + QSettings* m_pSettingsCurrent = nullptr; /// @brief The currently active settings + QSettings* m_pSettingsUser = nullptr; /// @brief The user specific settings + QSettings* m_pSettingsSystem = nullptr; /// @brief The system wide settings + +private: + + /// @brief Contains a list all all classes that hook into the writer. + /// This allows all classes that save settings to be called an updated + /// on a save and reload by any other class + std::list m_pCallerList; + + /// @brief The constructor, as this is a singolton we want to control who can call the constructor + ConfigWriter(); + + /// @brief the pointer of the + static ConfigWriter* s_pConfiguration; + + /// @brief deletes pointers and sets the value to null + template static inline void destroy(T*& p) { delete p; p = 0; } +}; + + +#endif //SYNERGY_CORE_CONFIGWRITER_H From df2d31ecf8b5ae910fba5e670bdbe46c086a9aec Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 23 Apr 2020 18:11:20 +0100 Subject: [PATCH 15/25] #6538 Implemented a most of the new config system --- src/gui/CMakeLists.txt | 2 +- src/gui/src/AppConfig.cpp | 134 +++++++----------- src/gui/src/AppConfig.h | 63 ++------- src/gui/src/ConfigBase.h | 48 +++++++ src/gui/src/ConfigWriter.cpp | 257 ++++++++++++++++++++++++++--------- src/gui/src/ConfigWriter.h | 161 ++++++++++++++-------- src/gui/src/MainWindow.cpp | 16 +-- src/gui/src/MainWindow.h | 4 +- src/gui/src/ServerConfig.cpp | 4 +- src/gui/src/main.cpp | 37 +---- 10 files changed, 423 insertions(+), 303 deletions(-) create mode 100644 src/gui/src/ConfigBase.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 2ea13189f..bdb4d1f9d 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -30,7 +30,7 @@ if (SYNERGY_ENTERPRISE) endif () if (WIN32) - set (LEGACY_GUI_RC_FILES res/win/Synergy.rc src/ConfigWriter.cpp src/ConfigWriter.h) + set (LEGACY_GUI_RC_FILES res/win/Synergy.rc) endif() add_executable (synergy WIN32 diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 28e365bb9..5bb33b93e 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -25,6 +25,8 @@ #include #include +#include "ConfigWriter.h" + #if defined(Q_OS_WIN) const char AppConfig::m_SynergysName[] = "synergys.exe"; const char AppConfig::m_SynergycName[] = "synergyc.exe"; @@ -81,10 +83,7 @@ static const char* logLevelNames[] = "DEBUG2" }; -AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : - m_pSettings(nullptr), - m_pUserSettings(userSettings), - m_pSystemSettings(systemSettings), +AppConfig::AppConfig() : m_ScreenName(), m_Port(24800), m_Interface(), @@ -98,20 +97,41 @@ AppConfig::AppConfig(QSettings* userSettings, QSettings* systemSettings) : m_LastExpiringWarningTime(0), m_AutoConfigServer(), m_MinimizeToTray(false), - m_SettingModified(false) + m_Edition(kUnregistered), + m_LogToFile(), + m_StartedBefore(), + m_ActivationHasRun(), + m_ServerGroupChecked(), + m_UseExternalConfig(), + m_UseInternalConfig(), + m_ClientGroupChecked(), + m_LoadFromSystemScope(), { - //If user setting don't exist but system ones do, load the system settings - if (!settingsExist(userSettings) && settingsExist(systemSettings)) + using GUI::Config::ConfigWriter; + + auto writer = ConfigWriter::make(); + + //Register this class to receive global load and saves + writer->registerClass(this); + + //User settings exist and the load from system scope variable is true + if (writer->hasSetting(settingName(LoadSystemSettings), ConfigWriter::kUser) && + writer->loadSetting(settingName(LoadSystemSettings), false,ConfigWriter::kUser).toBool()) { - m_pSettings = systemSettings; + writer->setScope(ConfigWriter::kSystem); + } + //If user setting don't exist but system ones do, load the system settings + else if (!writer->hasSetting(settingName(ScreenName), ConfigWriter::kUser) && + writer->hasSetting(settingName(ScreenName), ConfigWriter::kSystem)) + { + writer->setScope(ConfigWriter::kSystem); } else { // Otherwise just load to user scope - m_pSettings = userSettings; + writer->setScope(ConfigWriter::kUser); } - Q_ASSERT(m_pSettings); + //setScope triggers a global load so no need to call it again - loadSettings(); } AppConfig::~AppConfig() @@ -188,7 +208,7 @@ bool AppConfig::autoConfig() const { QString AppConfig::autoConfigServer() const { return m_AutoConfigServer; } -void AppConfig::loadSettings(bool ignoreSystem) +void AppConfig::loadSettings() { m_ScreenName = loadSetting(ScreenName, QHostInfo::localHostName()).toString(); m_Port = loadSetting(Port, 24800).toInt(); @@ -229,15 +249,7 @@ void AppConfig::loadSettings(bool ignoreSystem) m_ClientGroupChecked = loadSetting(GroupClientCheck, true).toBool(); m_ServerHostname = loadSetting(ServerHostname).toString(); - //If this is user scope and the user chose switch to global but ignoreSystem is not set. - if (settings().scope() == QSettings::UserScope && - m_LoadFromSystemScope && - !ignoreSystem) - { - //Switch to global scope and reload settings - switchToGlobal(); - loadSettings(); - } + } void AppConfig::saveSettings() @@ -273,8 +285,7 @@ void AppConfig::saveSettings() setSetting(GroupClientCheck, m_ClientGroupChecked); setSetting(ServerHostname, m_ServerHostname); - settings().sync(); - m_SettingModified = false; + m_unsavedChanges = false; } #ifndef SYNERGY_ENTERPRISE @@ -299,8 +310,6 @@ void AppConfig::setLastVersion(const QString& version) { setSettingModified(m_lastVersion, version); } -QSettings &AppConfig::settings() { return *m_pSettings; } - void AppConfig::setScreenName(const QString &s) { setSettingModified(m_ScreenName, s); } @@ -411,87 +420,44 @@ void AppConfig::setMinimizeToTray(bool newValue) { bool AppConfig::getMinimizeToTray() { return m_MinimizeToTray; } -bool AppConfig::settingsExist(QSettings* settings) { - //Use screen name as the test to see if the settings have been saved to this location - return settings->contains(settingName(ScreenName)); -} - QString AppConfig::settingName(AppConfig::Setting name) { return m_SynergySettingsName[name]; } template void AppConfig::setSetting(AppConfig::Setting name, T value) { - settings().setValue(settingName(name), value); + using GUI::Config::ConfigWriter; + ConfigWriter::make()->setSetting(settingName(name), value); } QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& defaultValue) { - return settings().value(settingName(name), defaultValue); + using GUI::Config::ConfigWriter; + return ConfigWriter::make()->loadSetting(settingName(name), defaultValue); } -AppConfig::SaveChoice AppConfig::checkGlobalSave() { - if (isSystemScoped()) { - - QMessageBox query; - query.setWindowTitle(tr("Save global settings.")); - query.setText(tr("This will overwrite the settings of anybody else that uses this computer.")); - - query.addButton(QMessageBox::Save); - const auto* pBtnCancel = query.addButton(QMessageBox::Cancel); - const auto* pBtnSaveLocal = query.addButton(tr("Save to user"), QMessageBox::ActionRole); - - query.setDefaultButton(QMessageBox::Cancel); - - query.exec(); - - if(query.clickedButton() == pBtnSaveLocal) - { - return SaveToUser; - } - else if(query.clickedButton() == pBtnCancel) - { - return Cancel; - } - } - return Save; -} - -void AppConfig::switchToGlobal(bool global) { - m_settings_lock.lock(); - if (global) - { - m_pSettings = m_pSystemSettings; - } - else - { - m_pSettings = m_pUserSettings; - } - m_settings_lock.unlock(); -} void AppConfig::setLoadFromSystemScope(bool value) { - if (value && !isSystemScoped()) + using GUI::Config::ConfigWriter; + + auto writer = ConfigWriter::make(); + + if (value && writer->getScope() != ConfigWriter::kSystem) { m_LoadFromSystemScope = value; - saveSettings(); //Save user prefs - switchToGlobal(); //Switch the the System Scope - loadSettings(); //Load the settings. + writer->globalSave(); //Save user prefs + writer->setScope(ConfigWriter::kSystem); //Switch the the System Scope and reload + } - else if (!value && isSystemScoped()) + else if (!value && writer->getScope() == ConfigWriter::kSystem) { - switchToGlobal(false); // Switch to UserScope - loadSettings(true); // Load user settings ignoring System scope setting + writer->setScope(ConfigWriter::kUser); // Switch to UserScope m_LoadFromSystemScope = value; // Set the user pref saveSettings(); // Save user prefs } } bool AppConfig::isSystemScoped() const { - return m_pSettings->scope() == QSettings::SystemScope; -} - -bool AppConfig::unsavedChanges() { - return m_SettingModified; + return GUI::Config::ConfigWriter::make()->getScope() == GUI::Config::ConfigWriter::kSystem; } bool AppConfig::getServerGroupChecked() const { @@ -547,7 +513,7 @@ void AppConfig::setSettingModified(T &variable, const T& newValue) { if (variable != newValue) { variable = newValue; - m_SettingModified = true; + m_unsavedChanges = true; } } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 9c7c37248..6635e4a9a 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -26,6 +26,7 @@ #include "ElevateMode.h" #include #include +#include "ConfigBase.h" // this should be incremented each time a new page is added. this is // saved to settings when the user finishes running the wizard. if @@ -52,7 +53,7 @@ enum ProcessMode { Desktop }; -class AppConfig: public QObject +class AppConfig: public QObject, public GUI::Config::ConfigBase { Q_OBJECT @@ -61,19 +62,10 @@ class AppConfig: public QObject friend class SetupWizard; public: - AppConfig(QSettings* userSettings, QSettings* systemSettings); - ~AppConfig(); + AppConfig(); + ~AppConfig() override; public: - enum SaveChoice { - Save, - Cancel, - SaveToUser - }; - - /// @brief Gets the current settings. - /// @return The scoped setting currently selected - QSettings& settings(); bool isSystemScoped() const; @@ -108,7 +100,6 @@ class AppConfig: public QObject QString synergyProgramDir() const; QString synergyLogDir() const; - bool detectPath(const QString& name, QString& path); void persistLogDir(); ElevateMode elevateMode(); @@ -127,9 +118,6 @@ class AppConfig: public QObject /// False - This will load the UserScope then set the variable and save. void setLoadFromSystemScope(bool value); - /// @brief Returns true if the setting should be set to global scope. Only useful if current scope is UserScope - bool getLoadFromSystemScope() const; - bool getServerGroupChecked() const; bool getUseExternalConfig() const; @@ -150,27 +138,9 @@ class AppConfig: public QObject void setMinimizeToTray(bool b); bool getMinimizeToTray(); - void saveSettings(); + void saveSettings() override; void setLastVersion(const QString& version); - /// @brief settingsExist Checks ths settings to see if they exist in the QSettings location - /// @return bool True if there are unsaved changes - bool unsavedChanges(); - - /// @brief settingsExist Checks ths settings to see if they exist in the QSettings location - /// @param [in] settings The QSettings object to check - /// @return True if the setting was found. - static bool settingsExist(QSettings* settings); - - /// @brief If the scope is set to system, this function will query the user - /// if they want to continue saving to global scope or switch to user scope - /// if the scope is set to User the function will just return Save - /// @return SaveChoice The choice that was selected, or Save if the scope is user already - SaveChoice checkGlobalSave(); - - /// @brief This will switch the scope to or from global - /// @param [in] global bool Defaults to true to switch to global scope, False to set to User scope - void switchToGlobal(bool global = true); protected: /// @brief The enumeration to easily access the names of the setting inside m_SynergySettingsName @@ -219,23 +189,21 @@ protected: /// @brief loads the setting from the current scope /// @param ignoreSystem should the load feature ignore the globalScope setting that was saved - void loadSettings(bool ignoreSystem = false); + void loadSettings() override; static QString settingName(AppConfig::Setting name); private: - QSettings* m_pSettings; /// @brief Contain the current settings scope - QSettings* m_pUserSettings; /// @brief Contains the setting in UserScope - QSettings* m_pSystemSettings; /// @brief Contains the setting in SystemScope + QString m_ScreenName; int m_Port; QString m_Interface; int m_LogLevel; - bool m_LogToFile; + bool m_LogToFile{}; QString m_LogFilename; int m_WizardLastRun; ProcessMode m_ProcessMode; QString m_Language; - bool m_StartedBefore; + bool m_StartedBefore{}; bool m_AutoConfig; QString m_AutoConfigServer; ElevateMode m_ElevateMode; @@ -246,20 +214,19 @@ protected: QString m_Serialkey; QString m_lastVersion; int m_LastExpiringWarningTime; - bool m_ActivationHasRun; + bool m_ActivationHasRun{}; bool m_MinimizeToTray; - bool m_ServerGroupChecked; - bool m_UseExternalConfig; + bool m_ServerGroupChecked{}; + bool m_UseExternalConfig{}; QString m_ConfigFile; - bool m_UseInternalConfig; - bool m_ClientGroupChecked; + bool m_UseInternalConfig{}; + bool m_ClientGroupChecked{}; QString m_ServerHostname; - bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope + bool m_LoadFromSystemScope{}; /// @brief should the setting be loaded from SystemScope /// If the user has settings but this is true then /// system settings will be loaded instead of the users - bool m_SettingModified; /// @brief Have the setting been changed since the last save static const char m_SynergysName[]; static const char m_SynergycName[]; diff --git a/src/gui/src/ConfigBase.h b/src/gui/src/ConfigBase.h new file mode 100644 index 000000000..5ea7389ec --- /dev/null +++ b/src/gui/src/ConfigBase.h @@ -0,0 +1,48 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2020 - 2020 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SYNERGY_CORE_CONFIGBASE_H +#define SYNERGY_CORE_CONFIGBASE_H + +namespace GUI { + namespace Config { + + ///@brief This abstract class will be used by all classes that use the ConfigWriter + /// to allow global saving and loading + class ConfigBase { + public : + ConfigBase() = default; + + virtual ~ConfigBase() = default; + + /// @brief The function that is called when the settings need to be loaded from file + virtual void loadSettings() = 0; + + /// @brief The function that is called when the settings need to be saved to file + virtual void saveSettings() = 0; + + /// @brief Returns true if the class has marked itself with having unsaved changes + bool modified() const { return m_unsavedChanges; } + + protected: + /// @brief Does the class have unsaved changes in it. + bool m_unsavedChanges = false; + + }; + } +} +#endif //SYNERGY_CORE_CONFIGBASE_H diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/ConfigWriter.cpp index 165c0fc7f..421ffc665 100644 --- a/src/gui/src/ConfigWriter.cpp +++ b/src/gui/src/ConfigWriter.cpp @@ -2,72 +2,203 @@ // Created by jamie on 21/04/2020. // +#include +#include +#include + #include "ConfigWriter.h" +#include "ConfigBase.h" -ConfigWriter* ConfigWriter::s_pConfiguration = nullptr; +namespace GUI { + namespace Config { + //Assignment of static variable + ConfigWriter *ConfigWriter::s_pConfiguration = nullptr; -ConfigWriter *ConfigWriter::make() { - // Only one ConfigWriter can exist at any one time (Singolton) - if (!s_pConfiguration) { - s_pConfiguration = new ConfigWriter(); - } - return s_pConfiguration; -} - -ConfigWriter::ConfigWriter() { - -} - -void ConfigWriter::destroy() { - destroy(s_pConfiguration); -} - -ConfigWriter::~ConfigWriter() { - destroy(m_pSettingsCurrent); - destroy(m_pSettingsSystem); - destroy(m_pSettingsUser); -} - -template -void ConfigWriter::setSetting(const char *name, T value) { - -} - -QVariant ConfigWriter::loadSetting(const char *name, const QVariant &defaultValue) { - return QVariant(); -} - - -void ConfigWriter::setScope(ConfigWriter::Scope scope) { - if (m_CurrentScope != scope) - { - m_CurrentScope = scope; - switch (scope) - { - case User: - m_pSettingsCurrent = m_pSettingsUser; - break; - case System: - m_pSettingsCurrent = m_pSettingsSystem; - break; + ConfigWriter *ConfigWriter::make() { + // Only one ConfigWriter can exist at any one time (Singolton) + if (!s_pConfiguration) { + s_pConfiguration = new ConfigWriter(); + } + return s_pConfiguration; } + + + ConfigWriter::ConfigWriter() { + QSettings::setPath(QSettings::Format::IniFormat, + QSettings::Scope::SystemScope, + getSystemSettingPath()); + + //Config will default to User settings if they exist, + // otherwise it will load System setting and save them to User settings + m_pSettingsSystem = new QSettings(QSettings::Format::IniFormat, + QSettings::Scope::SystemScope, + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); + + m_pSettingsUser = new QSettings(QSettings::Scope::UserScope, + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); + + } + + + void ConfigWriter::destroy() { + destroy(s_pConfiguration); + } + + ConfigWriter::~ConfigWriter() { + while(!m_pCallerList.empty()) { + m_pCallerList.pop_back(); + } + m_pSettingsCurrent = nullptr; //this only references other pointers + destroy(m_pSettingsSystem); + destroy(m_pSettingsUser); + } + + + bool ConfigWriter::hasSetting(const QString &name, Scope scope) const { + switch (scope){ + case kUser: + return m_pSettingsUser->contains(name); + case kSystem: + return m_pSettingsSystem->contains(name); + default: + return m_pSettingsCurrent->contains(name); + } + } + + + + QVariant ConfigWriter::loadSetting(const QString& name, const QVariant &defaultValue, Scope scope) { + switch (scope){ + case kUser: + return m_pSettingsUser->value(name, defaultValue); + case kSystem: + return m_pSettingsSystem->value(name, defaultValue); + default: + return m_pSettingsCurrent->value(name, defaultValue); + } + } + + + void ConfigWriter::setScope(ConfigWriter::Scope scope) { + if (m_CurrentScope != scope) { + m_CurrentScope = scope; + switch (scope) { + case kUser: + m_pSettingsCurrent = m_pSettingsUser; + break; + case kSystem: + m_pSettingsCurrent = m_pSettingsSystem; + break; + default: + //setScope should never be kCurrent + assert(scope); + } + + //Notify registered classes to reload + globalLoad(); + } + } + + ConfigWriter::Scope ConfigWriter::getScope() const { + return m_CurrentScope; + } + + void ConfigWriter::globalLoad() { + for (auto &i : m_pCallerList) { + i->loadSettings(); + } + } + + void ConfigWriter::globalSave() { + + //Save if there are any unsaved changes otherwise skip + if (unsavedChanges()) { + auto choice = checkSystemSave(); + + switch (choice) { + case kSaveToUser: + //Switch to local and overrun into the save case without reloading + m_CurrentScope = kUser; + m_pSettingsCurrent = m_pSettingsUser; + case kSave: + for (auto &i : m_pCallerList) { + i->saveSettings(); + } + break; + default: + break; + } + } + } + + QSettings &ConfigWriter::settings() { + return *m_pSettingsCurrent; + } + + void ConfigWriter::registerClass(ConfigBase * receiver) { + m_pCallerList.push_back(receiver); + } + + QString ConfigWriter::getSystemSettingPath() { + const QString settingFilename("SystemConfig.ini"); + QString path; +#if defined(Q_OS_WIN) + // Program file + path = ""; +#elif defined(Q_OS_DARWIN) + //Global preferances dir + // Would be nice to use /library, but QT has no elevate system in place + path = "/usr/local/etc/symless/synergy/"; +#elif defined(Q_OS_LINUX) + // /usr/local/etc/synergy + path = "/usr/local/etc/symless/synergy/"; +#else + assert("OS not supported"); +#endif + return path + settingFilename; + } + + bool ConfigWriter::unsavedChanges() const { + for (const auto &i : m_pCallerList) { + if (i->modified()){ + //If any class returns true there is no point checking more + return true; + } + } + // If this line is reached no class has unsaved changes + return false; + } + + ConfigWriter::SaveChoice ConfigWriter::checkSystemSave() const { + if (m_CurrentScope == kSystem) { + + QMessageBox query; + query.setWindowTitle(tr("Save global settings.")); + query.setText(tr("This will overwrite the settings of anybody else that uses this computer.")); + + query.addButton(QMessageBox::Save); + const auto* pBtnCancel = query.addButton(QMessageBox::Cancel); + const auto* pBtnSaveLocal = query.addButton(tr("Save to user"), QMessageBox::ActionRole); + + query.setDefaultButton(QMessageBox::Cancel); + + query.exec(); + + if(query.clickedButton() == pBtnSaveLocal) + { + return kSaveToUser; + } + else if(query.clickedButton() == pBtnCancel) + { + return kCancel; + } + } + return kSave; + } + + } -} - -ConfigWriter::Scope ConfigWriter::getScope() const { - return m_CurrentScope; -} - -void ConfigWriter::gloablLoad() { - for(auto & i : m_pCallerList) { - i->loadSettings(); - } -} - -void ConfigWriter::globalSave() { - for(auto & i : m_pCallerList) { - i->saveSettings(); - } -} - +} \ No newline at end of file diff --git a/src/gui/src/ConfigWriter.h b/src/gui/src/ConfigWriter.h index bcf659b6b..79ba87c02 100644 --- a/src/gui/src/ConfigWriter.h +++ b/src/gui/src/ConfigWriter.h @@ -17,88 +17,135 @@ #ifndef SYNERGY_CORE_CONFIGWRITER_H #define SYNERGY_CORE_CONFIGWRITER_H - #include #include -///@brief This abstract class will be used by all classes that use the ConfigWriter -/// to allow global saving and loading -class ConfigBase { -public : - ConfigBase() = default; - virtual ~ConfigBase() = default; +/// @brief Contains GUI code +namespace GUI { + /// @brief Contains Configuration code + namespace Config { - /// @brief The function that is called when the settings need to be loaded from file - virtual void loadSettings() = 0; + //Forward declare the class referenced by pointer + class ConfigBase; - /// @brief The function that is called when the settings need to be saved to file - virtual void saveSettings() = 0; -}; + class ConfigWriter: private QObject { -class ConfigWriter { + public: -public: + /// @brief the public way to construct the configuration calls + /// The pointer returned is owned by this class and should not be stored + /// by other classes. + static ConfigWriter* make(); - /// @brief the public way to construct the configuration calls - static ConfigWriter* make(); + /// @brief the public way to destroy the configuration class + static void destroy(); - /// @brief the public way to destroy the configuration class - static void destroy(); + ~ConfigWriter() override; - ~ConfigWriter(); + ///@brief An Enumeration of all the scopes available + enum Scope { kCurrent, kSystem, kUser}; - ///@brief An Enumeration of all the scopes available - enum Scope { System, User}; + /// @brief The choice selected when saving. + enum SaveChoice { kSave, kCancel, kSaveToUser}; - /// @brief Sets the value of a setting - /// @param [in] name The Setting to be saved - /// @param [in] value The Value to be saved - template - void setSetting(const char* name, T value); + /// @brief Checks if the setting exists + /// @param [in] name The name of the setting to check + /// @param [in] scope The scope to search in + /// @return bool True if the current scope has the named setting + bool hasSetting(const QString& name, Scope scope = kCurrent) const; - /// @brief Loads a setting - /// @param [in] name The setting to be loaded - /// @param [in] defaultValue The default value of the setting - QVariant loadSetting(const char* name, const QVariant& defaultValue = QVariant()); + /// @brief Sets the value of a setting + /// @param [in] name The Setting to be saved + /// @param [in] value The Value to be saved (Templated) + /// @param [in] scope The scope to get the value from, default is current scope + template + void setSetting(const QString& name, T value, Scope scope = kCurrent); - /// @brief Changes the setting save and load location between System and User scope - /// @param [in] scope The scope to set - void setScope(Scope scope = User); + /// @brief Loads a setting + /// @param [in] name The setting to be loaded + /// @param [in] defaultValue The default value of the setting + /// @param [in] scope The scope to get the value from, default is current scope + QVariant loadSetting(const QString& name, const QVariant& defaultValue = QVariant(), Scope scope = kCurrent); - /// @brief Get the current scope the settings are loading and save from. - /// @return Scope An enum defining the current scope - Scope getScope() const; + /// @brief Changes the setting save and load location between System and User scope + /// @param [in] scope The scope to set + void setScope(Scope scope = kUser); - /// @brief trigger a config load across all registered classes - void gloablLoad(); + /// @brief Get the current scope the settings are loading and save from. + /// @return Scope An enum defining the current scope + Scope getScope() const; - /// @brief trigger a config save across all registered classes - void globalSave(); + /// @brief trigger a config load across all registered classes + void globalLoad(); -protected: + /// @brief trigger a config save across all registered classes + void globalSave(); - Scope m_CurrentScope = User; /// @brief The current scope of the settings + /// @brief Returns the current scopes settings object + /// If more specialize control into the settings is needed this can provide + /// direct access to the settings file handler + /// @return QSettings The Settings object as a reference + QSettings& settings(); - QSettings* m_pSettingsCurrent = nullptr; /// @brief The currently active settings - QSettings* m_pSettingsUser = nullptr; /// @brief The user specific settings - QSettings* m_pSettingsSystem = nullptr; /// @brief The system wide settings + /// @brief Register a class to receives globalLoad and globalSave events + /// @param [in] ConfigBase The class that will receive the events + void registerClass(ConfigBase* receiver); -private: + /// @brief Checks if any registered class has any unsaved changes + /// @return bool True if any registered class has unsaved changes + bool unsavedChanges() const; - /// @brief Contains a list all all classes that hook into the writer. - /// This allows all classes that save settings to be called an updated - /// on a save and reload by any other class - std::list m_pCallerList; + /// @brief If the scope is set to system, this function will query the user + /// if they want to continue saving to global scope or switch to user scope + /// if the scope is set to User the function will just return Save + /// @return SaveChoice The choice that was selected, or Save if the scope is user already + SaveChoice checkSystemSave() const; - /// @brief The constructor, as this is a singolton we want to control who can call the constructor - ConfigWriter(); + protected: - /// @brief the pointer of the - static ConfigWriter* s_pConfiguration; + Scope m_CurrentScope = kUser; /// @brief The current scope of the settings - /// @brief deletes pointers and sets the value to null - template static inline void destroy(T*& p) { delete p; p = 0; } -}; + QSettings* m_pSettingsCurrent = nullptr; /// @brief The currently active settings + QSettings* m_pSettingsUser = nullptr; /// @brief The user specific settings + QSettings* m_pSettingsSystem = nullptr; /// @brief The system wide settings + + private: + + /// @brief Contains a list all all classes that hook into the writer. + /// This allows all classes that save settings to be called an updated + /// on a save and reload by any other class + std::list m_pCallerList; + + /// @brief The constructor, as this is a singolton we want to control who can call the constructor + ConfigWriter(); + + /// @brief the pointer of the ConfigWriter for singolton use + static ConfigWriter* s_pConfiguration; + + /// @brief Returns the OS specific settings ini file location + static QString getSystemSettingPath(); + /// @brief deletes pointers and sets the value to null + template static inline void destroy(T*& p) { delete p; p = 0; } + }; + + // Implementation of a template function needs to be visible to all calls thus is must be in the header + // Moved so its not bulking out the class definition + template + void ConfigWriter::setSetting(const QString& name, T value, Scope scope) { + switch (scope){ + case kUser: + m_pSettingsUser->setValue(name, value); + break; + case kSystem: + m_pSettingsSystem->setValue(name, value); + break; + default: + m_pSettingsCurrent->setValue(name, value); + break; + } + } + } +} #endif //SYNERGY_CORE_CONFIGWRITER_H diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 772378fd0..50b1ffcb2 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -356,21 +356,9 @@ void MainWindow::saveSettings() appConfig().setServerHostname(m_pLineEditHostname->text()); - //Save if there are any unsaved changes otherwise skip - if (appConfig().unsavedChanges()) { - auto choice = appConfig().checkGlobalSave(); + //Save everything + GUI::Config::ConfigWriter::make()->globalSave(); - switch (choice) { - case AppConfig::SaveToUser: - //Switch to local and overrun into the save case - appConfig().switchToGlobal(false); - case AppConfig::Save: - appConfig().saveSettings(); - break; - default: - break; - } - } } void MainWindow::zeroConfToggled() { diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index ce545902a..6b34253cb 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -32,6 +32,7 @@ #include "IpcClient.h" #include "Ipc.h" #include "ActivationDialog.h" +#include "ConfigWriter.h" #include @@ -164,7 +165,8 @@ public slots: void zeroConfToggled(); protected: - QSettings& settings() { return appConfig().settings(); } + // TODO This should be properly using the ConfigWriter system. + QSettings& settings() { return GUI::Config::ConfigWriter::make()->settings(); } AppConfig& appConfig() { return *m_AppConfig; } QProcess* synergyProcess() { return m_pSynergy; } void setSynergyProcess(QProcess* p) { m_pSynergy = p; } diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp index 11797181c..72519f4d1 100644 --- a/src/gui/src/ServerConfig.cpp +++ b/src/gui/src/ServerConfig.cpp @@ -432,5 +432,7 @@ size_t ServerConfig::setClipboardSharingSize(size_t size) { } QSettings &ServerConfig::settings() { - return m_pAppConfig->settings(); + using GUI::Config::ConfigWriter; + + return ConfigWriter::make()->settings(); } diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index d993160cf..9738c9697 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -#define TRAY_RETRY_COUNT 10 +#define TRAY_RETRY_COUNT 1 #define TRAY_RETRY_WAIT 2000 #include "QSynergyApplication.h" @@ -90,22 +90,9 @@ int main(int argc, char* argv[]) QApplication::setQuitOnLastWindowClosed(false); #endif //S - QSettings::setPath(QSettings::Format::IniFormat, - QSettings::Scope::SystemScope, - getSystemSettingPath()); - //Config will default to User settings if they exist, - // otherwise it will load System setting and save them to User settings - QSettings systemSettings(QSettings::Format::IniFormat, - QSettings::Scope::SystemScope, - QCoreApplication::organizationName(), - QCoreApplication::applicationName()); - QSettings userSettings(QSettings::Scope::UserScope, - QCoreApplication::organizationName(), - QCoreApplication::applicationName()); - - AppConfig appConfig (&userSettings, &systemSettings); + AppConfig appConfig; qRegisterMetaType("Edition"); #ifndef SYNERGY_ENTERPRISE LicenseManager licenseManager (&appConfig); @@ -160,25 +147,7 @@ int waitForTray() return true; } -QString getSystemSettingPath() -{ - const QString settingFilename("SystemConfig.ini"); - QString path; -#if defined(Q_OS_WIN) - // Program file - path = ""; -#elif defined(Q_OS_DARWIN) - //Global preferances dir - // Would be nice to use /library, but QT has no elevate system in place - path = "/usr/local/etc/symless/synergy/"; -#elif defined(Q_OS_LINUX) - // /usr/local/etc/synergy - path = "/usr/local/etc/symless/synergy/"; -#else - assert("OS not supported"); -#endif - return path + settingFilename; -} + #if defined(Q_OS_MAC) bool checkMacAssistiveDevices() From a5d18ebb0a0bdfd8d5680118e017e1bcee6a9729 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Thu, 23 Apr 2020 19:07:50 +0100 Subject: [PATCH 16/25] #6538 Removed extra , --- src/gui/src/AppConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 5bb33b93e..f006867c6 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -105,7 +105,7 @@ AppConfig::AppConfig() : m_UseExternalConfig(), m_UseInternalConfig(), m_ClientGroupChecked(), - m_LoadFromSystemScope(), + m_LoadFromSystemScope() { using GUI::Config::ConfigWriter; From fb5b46c02ec5a3f05c170fef7bc3b180ea8fc0cf Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Fri, 24 Apr 2020 10:22:40 +0100 Subject: [PATCH 17/25] #6538 Added assert declaration --- src/gui/src/ConfigWriter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/ConfigWriter.cpp index 421ffc665..e0c562aa1 100644 --- a/src/gui/src/ConfigWriter.cpp +++ b/src/gui/src/ConfigWriter.cpp @@ -2,6 +2,8 @@ // Created by jamie on 21/04/2020. // +#include + #include #include #include From b3892a1b82fe9e1297d53cadc78159744f11f62f Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 12:53:39 +0100 Subject: [PATCH 18/25] #6538 Changed Enum names to follow code standards --- src/gui/src/AppConfig.cpp | 142 ++++++++++++++++++++------------------ src/gui/src/AppConfig.h | 58 ++++++++-------- 2 files changed, 103 insertions(+), 97 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index f006867c6..5259a19ab 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -114,23 +114,23 @@ AppConfig::AppConfig() : //Register this class to receive global load and saves writer->registerClass(this); - //User settings exist and the load from system scope variable is true - if (writer->hasSetting(settingName(LoadSystemSettings), ConfigWriter::kUser) && - writer->loadSetting(settingName(LoadSystemSettings), false,ConfigWriter::kUser).toBool()) + if (writer->hasSetting(settingName(kLoadSystemSettings), ConfigWriter::kUser) && + writer->loadSetting(settingName(kLoadSystemSettings), false, ConfigWriter::kUser).toBool()) { writer->setScope(ConfigWriter::kSystem); } //If user setting don't exist but system ones do, load the system settings - else if (!writer->hasSetting(settingName(ScreenName), ConfigWriter::kUser) && - writer->hasSetting(settingName(ScreenName), ConfigWriter::kSystem)) + else if (!writer->hasSetting(settingName(kScreenName), ConfigWriter::kUser) && + writer->hasSetting(settingName(kScreenName), ConfigWriter::kSystem)) { writer->setScope(ConfigWriter::kSystem); } else { // Otherwise just load to user scope writer->setScope(ConfigWriter::kUser); } - //setScope triggers a global load so no need to call it again + //Notify registered classes to reload + writer->globalLoad(); } @@ -210,80 +210,80 @@ QString AppConfig::autoConfigServer() const { return m_AutoConfigServer; } void AppConfig::loadSettings() { - m_ScreenName = loadSetting(ScreenName, QHostInfo::localHostName()).toString(); - m_Port = loadSetting(Port, 24800).toInt(); - m_Interface = loadSetting(InterfaceSetting).toString(); - m_LogLevel = loadSetting(LogLevel, 0).toInt(); - m_LogToFile = loadSetting(LogToFile, false).toBool(); - m_LogFilename = loadSetting(LogFilename,synergyLogDir() + "synergy.log").toString(); - m_WizardLastRun = loadSetting(WizardLastRun,0).toInt(); - m_Language = loadSetting(Language, QLocale::system().name()).toString(); - m_StartedBefore = loadSetting(StartedBefore, false).toBool(); - m_AutoConfig = loadSetting(AutoConfig, false).toBool(); - m_AutoConfigServer = loadSetting(AutoConfigServer,"").toString(); + m_ScreenName = loadSetting(kScreenName, QHostInfo::localHostName()).toString(); + m_Port = loadSetting(kPort, 24800).toInt(); + m_Interface = loadSetting(kInterfaceSetting).toString(); + m_LogLevel = loadSetting(kLogLevel, 0).toInt(); + m_LogToFile = loadSetting(kLogToFile, false).toBool(); + m_LogFilename = loadSetting(kLogFilename, synergyLogDir() + "synergy.log").toString(); + m_WizardLastRun = loadSetting(kWizardLastRun, 0).toInt(); + m_Language = loadSetting(kLanguage, QLocale::system().name()).toString(); + m_StartedBefore = loadSetting(kStartedBefore, false).toBool(); + m_AutoConfig = loadSetting(kAutoConfig, false).toBool(); + m_AutoConfigServer = loadSetting(kAutoConfigServer, "").toString(); { //Scope related code together - // TODO Investigate why ElevateModeEnum isn't loaded fully - QVariant elevateMode = loadSetting(ElevateModeEnum); + // TODO Investigate why kElevateModeEnum isn't loaded fully + QVariant elevateMode = loadSetting(kElevateModeEnum); if (!elevateMode.isValid()) { - elevateMode = loadSetting(ElevateModeSetting, - QVariant(static_cast(defaultElevateMode))); + elevateMode = loadSetting(kElevateModeSetting, + QVariant(static_cast(defaultElevateMode))); } m_ElevateMode = static_cast(elevateMode.toInt()); } - m_Edition = static_cast(loadSetting(EditionSetting, kUnregistered).toInt()); - m_ActivateEmail = loadSetting(ActivateEmail, "").toString(); - m_CryptoEnabled = loadSetting(CryptoEnabled, true).toBool(); - m_AutoHide = loadSetting(AutoHide, false).toBool(); - m_Serialkey = loadSetting(SerialKey, "").toString().trimmed(); - m_lastVersion = loadSetting(LastVersion, "Unknown").toString(); - m_LastExpiringWarningTime = loadSetting(LastExpireWarningTime, 0).toInt(); - m_ActivationHasRun = loadSetting(ActivationHasRun, false).toBool(); - m_MinimizeToTray = loadSetting(MinimizeToTray, false).toBool(); - m_LoadFromSystemScope = loadSetting(LoadSystemSettings, false).toBool(); - m_ServerGroupChecked = loadSetting(GroupServerCheck, false).toBool(); - m_UseExternalConfig = loadSetting(UseExternalConfig, false).toBool(); - m_ConfigFile = loadSetting(ConfigFile, QDir::homePath() + "/" + synergyConfigName).toString(); - m_UseInternalConfig = loadSetting(UseInternalConfig, false).toBool(); - m_ClientGroupChecked = loadSetting(GroupClientCheck, true).toBool(); - m_ServerHostname = loadSetting(ServerHostname).toString(); + m_Edition = static_cast(loadSetting(kEditionSetting, kUnregistered).toInt()); + m_ActivateEmail = loadSetting(kActivateEmail, "").toString(); + m_CryptoEnabled = loadSetting(kCryptoEnabled, true).toBool(); + m_AutoHide = loadSetting(kAutoHide, false).toBool(); + m_Serialkey = loadSetting(kSerialKey, "").toString().trimmed(); + m_lastVersion = loadSetting(kLastVersion, "Unknown").toString(); + m_LastExpiringWarningTime = loadSetting(kLastExpireWarningTime, 0).toInt(); + m_ActivationHasRun = loadSetting(kActivationHasRun, false).toBool(); + m_MinimizeToTray = loadSetting(kMinimizeToTray, false).toBool(); + m_LoadFromSystemScope = loadSetting(kLoadSystemSettings, false).toBool(); + m_ServerGroupChecked = loadSetting(kGroupServerCheck, false).toBool(); + m_UseExternalConfig = loadSetting(kUseExternalConfig, false).toBool(); + m_ConfigFile = loadSetting(kConfigFile, QDir::homePath() + "/" + synergyConfigName).toString(); + m_UseInternalConfig = loadSetting(kUseInternalConfig, false).toBool(); + m_ClientGroupChecked = loadSetting(kGroupClientCheck, true).toBool(); + m_ServerHostname = loadSetting(kServerHostname).toString(); } void AppConfig::saveSettings() { - setSetting(ScreenName, m_ScreenName); - setSetting(Port, m_Port); - setSetting(InterfaceSetting, m_Interface); - setSetting(LogLevel, m_LogLevel); - setSetting(LogToFile, m_LogToFile); - setSetting(LogFilename, m_LogFilename); - setSetting(WizardLastRun, kWizardVersion); - setSetting(Language, m_Language); - setSetting(StartedBefore, m_StartedBefore); - setSetting(AutoConfig, m_AutoConfig); - setSetting(AutoConfigServer, m_AutoConfigServer); + setSetting(kScreenName, m_ScreenName); + setSetting(kPort, m_Port); + setSetting(kInterfaceSetting, m_Interface); + setSetting(kLogLevel, m_LogLevel); + setSetting(kLogToFile, m_LogToFile); + setSetting(kLogFilename, m_LogFilename); + setSetting(kWizardLastRun, kWizardVersion); + setSetting(kLanguage, m_Language); + setSetting(kStartedBefore, m_StartedBefore); + setSetting(kAutoConfig, m_AutoConfig); + setSetting(kAutoConfigServer, m_AutoConfigServer); // Refer to enum ElevateMode declaration for insight in to why this // flag is mapped this way - setSetting(ElevateModeSetting, m_ElevateMode == ElevateAlways); - setSetting(ElevateModeEnum, static_cast(m_ElevateMode)); - setSetting(EditionSetting, m_Edition); - setSetting(CryptoEnabled, m_CryptoEnabled); - setSetting(AutoHide, m_AutoHide); - setSetting(SerialKey, m_Serialkey); - setSetting(LastVersion, m_lastVersion); - setSetting(LastExpireWarningTime, m_LastExpiringWarningTime); - setSetting(ActivationHasRun, m_ActivationHasRun); - setSetting(MinimizeToTray, m_MinimizeToTray); - setSetting(LoadSystemSettings, m_LoadFromSystemScope); - setSetting(GroupServerCheck, m_ServerGroupChecked); - setSetting(UseExternalConfig, m_UseExternalConfig); - setSetting(ConfigFile, m_ConfigFile); - setSetting(UseInternalConfig, m_UseInternalConfig); - setSetting(GroupClientCheck, m_ClientGroupChecked); - setSetting(ServerHostname, m_ServerHostname); + setSetting(kElevateModeSetting, m_ElevateMode == ElevateAlways); + setSetting(kElevateModeEnum, static_cast(m_ElevateMode)); + setSetting(kEditionSetting, m_Edition); + setSetting(kCryptoEnabled, m_CryptoEnabled); + setSetting(kAutoHide, m_AutoHide); + setSetting(kSerialKey, m_Serialkey); + setSetting(kLastVersion, m_lastVersion); + setSetting(kLastExpireWarningTime, m_LastExpiringWarningTime); + setSetting(kActivationHasRun, m_ActivationHasRun); + setSetting(kMinimizeToTray, m_MinimizeToTray); + setSetting(kLoadSystemSettings, m_LoadFromSystemScope); + setSetting(kGroupServerCheck, m_ServerGroupChecked); + setSetting(kUseExternalConfig, m_UseExternalConfig); + setSetting(kConfigFile, m_ConfigFile); + setSetting(kUseInternalConfig, m_UseInternalConfig); + setSetting(kGroupClientCheck, m_ClientGroupChecked); + setSetting(kServerHostname, m_ServerHostname); m_unsavedChanges = false; } @@ -444,15 +444,21 @@ void AppConfig::setLoadFromSystemScope(bool value) { if (value && writer->getScope() != ConfigWriter::kSystem) { m_LoadFromSystemScope = value; + m_unsavedChanges = true; writer->globalSave(); //Save user prefs writer->setScope(ConfigWriter::kSystem); //Switch the the System Scope and reload - + writer->globalLoad(); } else if (!value && writer->getScope() == ConfigWriter::kSystem) { writer->setScope(ConfigWriter::kUser); // Switch to UserScope - m_LoadFromSystemScope = value; // Set the user pref - saveSettings(); // Save user prefs + if (writer->hasSetting(settingName(kScreenName), ConfigWriter::kUser)) { + // If the user already has settings, then load them up now. + writer->globalLoad(); + } + m_LoadFromSystemScope = value; + m_unsavedChanges = true; + writer->globalSave(); // Save user prefs } } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 6635e4a9a..a7571541d 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -145,35 +145,35 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase protected: /// @brief The enumeration to easily access the names of the setting inside m_SynergySettingsName enum Setting { - ScreenName, - Port, - InterfaceSetting, - LogLevel, - LogToFile, - LogFilename, - WizardLastRun, - Language, - StartedBefore, - AutoConfig, - AutoConfigServer, - ElevateModeSetting, - ElevateModeEnum, - EditionSetting, - CryptoEnabled, - AutoHide, - SerialKey, - LastVersion, - LastExpireWarningTime, - ActivationHasRun, - MinimizeToTray, - ActivateEmail, - LoadSystemSettings, - GroupServerCheck, - UseExternalConfig, - ConfigFile, - UseInternalConfig, - GroupClientCheck, - ServerHostname, + kScreenName, + kPort, + kInterfaceSetting, + kLogLevel, + kLogToFile, + kLogFilename, + kWizardLastRun, + kLanguage, + kStartedBefore, + kAutoConfig, + kAutoConfigServer, + kElevateModeSetting, + kElevateModeEnum, + kEditionSetting, + kCryptoEnabled, + kAutoHide, + kSerialKey, + kLastVersion, + kLastExpireWarningTime, + kActivationHasRun, + kMinimizeToTray, + kActivateEmail, + kLoadSystemSettings, + kGroupServerCheck, + kUseExternalConfig, + kConfigFile, + kUseInternalConfig, + kGroupClientCheck, + kServerHostname, }; void setScreenName(const QString& s); From 73b9f40a44728c9ce7822c0b1f8a0422bbb35c27 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 12:59:37 +0100 Subject: [PATCH 19/25] #6538 Added save to ConfigWriter, updated system config pathing and, set initial scope --- src/gui/src/ConfigWriter.cpp | 26 +++++++++++++++++++------- src/gui/src/ConfigWriter.h | 10 ++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/ConfigWriter.cpp index e0c562aa1..8e77dab4b 100644 --- a/src/gui/src/ConfigWriter.cpp +++ b/src/gui/src/ConfigWriter.cpp @@ -42,6 +42,8 @@ namespace GUI { QCoreApplication::organizationName(), QCoreApplication::applicationName()); + //Set scope to user for initially + m_pSettingsCurrent = m_pSettingsUser; } @@ -98,9 +100,6 @@ namespace GUI { //setScope should never be kCurrent assert(scope); } - - //Notify registered classes to reload - globalLoad(); } } @@ -129,6 +128,7 @@ namespace GUI { for (auto &i : m_pCallerList) { i->saveSettings(); } + save(); break; default: break; @@ -153,10 +153,11 @@ namespace GUI { #elif defined(Q_OS_DARWIN) //Global preferances dir // Would be nice to use /library, but QT has no elevate system in place - path = "/usr/local/etc/symless/synergy/"; + path = "/usr/local/etc/symless/"; #elif defined(Q_OS_LINUX) - // /usr/local/etc/synergy - path = "/usr/local/etc/symless/synergy/"; + // QT adds application and filename to the end of the path already on linux + path = "/usr/local/etc/symless/"; + return path; #else assert("OS not supported"); #endif @@ -164,6 +165,10 @@ namespace GUI { } bool ConfigWriter::unsavedChanges() const { + if (m_unsavedChanges) { + return true; + } + for (const auto &i : m_pCallerList) { if (i->modified()){ //If any class returns true there is no point checking more @@ -174,6 +179,10 @@ namespace GUI { return false; } + void ConfigWriter::markUnsaved() { + m_unsavedChanges = true; + } + ConfigWriter::SaveChoice ConfigWriter::checkSystemSave() const { if (m_CurrentScope == kSystem) { @@ -201,6 +210,9 @@ namespace GUI { return kSave; } - + void ConfigWriter::save() { + m_pSettingsCurrent->sync(); + m_unsavedChanges = false; + } } } \ No newline at end of file diff --git a/src/gui/src/ConfigWriter.h b/src/gui/src/ConfigWriter.h index 79ba87c02..f7817ef18 100644 --- a/src/gui/src/ConfigWriter.h +++ b/src/gui/src/ConfigWriter.h @@ -81,12 +81,18 @@ namespace GUI { /// @brief trigger a config save across all registered classes void globalSave(); + /// @brief Saves the settings to file + void save(); + /// @brief Returns the current scopes settings object /// If more specialize control into the settings is needed this can provide /// direct access to the settings file handler /// @return QSettings The Settings object as a reference QSettings& settings(); + /// @brief This marks the settings as unsaved if the settings() was used to directly affect the config file + void markUnsaved(); + /// @brief Register a class to receives globalLoad and globalSave events /// @param [in] ConfigBase The class that will receive the events void registerClass(ConfigBase* receiver); @@ -116,6 +122,9 @@ namespace GUI { /// on a save and reload by any other class std::list m_pCallerList; + /// @brief if this class modified settings then set the flag + bool m_unsavedChanges = false; + /// @brief The constructor, as this is a singolton we want to control who can call the constructor ConfigWriter(); @@ -145,6 +154,7 @@ namespace GUI { m_pSettingsCurrent->setValue(name, value); break; } + m_unsavedChanges = true; } } } From ad1429e9aaa9bdf312c601e35fdc69a132810790 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 13:02:26 +0100 Subject: [PATCH 20/25] #6538 Removed appconfig saveSettings calls from external classes, update serverconfig to derived class --- src/gui/src/ActivationDialog.cpp | 2 -- src/gui/src/LicenseManager.cpp | 3 --- src/gui/src/ServerConfig.cpp | 10 ++++++---- src/gui/src/ServerConfig.h | 10 +++++----- src/gui/src/SettingsDialog.cpp | 2 -- src/gui/src/main.cpp | 3 +-- 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index 88948958b..e8136107f 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -54,7 +54,6 @@ void ActivationDialog::reject() if (QDialog::Accepted == cancelActivationDialog.exec()) { m_LicenseManager->skipActivation(); m_appConfig->activationHasRun(true); - m_appConfig->saveSettings(); } else { return; } @@ -66,7 +65,6 @@ void ActivationDialog::accept() { QMessageBox message; m_appConfig->activationHasRun(true); - m_appConfig->saveSettings(); std::pair result; try { diff --git a/src/gui/src/LicenseManager.cpp b/src/gui/src/LicenseManager.cpp index b756bbf80..f0f09c2f3 100644 --- a/src/gui/src/LicenseManager.cpp +++ b/src/gui/src/LicenseManager.cpp @@ -62,8 +62,6 @@ LicenseManager::setSerialKey(SerialKey serialKey, bool acceptExpired) emit beginTrial(m_serialKey.isExpiring(currentTime)); } } - - m_AppConfig->saveSettings(); } return ret; @@ -118,7 +116,6 @@ void LicenseManager::refresh() setSerialKey(serialKey, true); } catch (...) { m_AppConfig->clearSerialKey(); - m_AppConfig->saveSettings(); } } if (m_serialKey.isExpired(::time(0))) { diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp index 72519f4d1..3220a5a10 100644 --- a/src/gui/src/ServerConfig.cpp +++ b/src/gui/src/ServerConfig.cpp @@ -42,9 +42,9 @@ static const struct const int serverDefaultIndex = 7; -ServerConfig::ServerConfig(AppConfig* appConfig, int numColumns, int numRows , +ServerConfig::ServerConfig(int numColumns, int numRows , QString serverName, MainWindow* mainWindow) : - m_pAppConfig(appConfig), + m_Screens(), m_NumColumns(numColumns), m_NumRows(numRows), @@ -56,8 +56,7 @@ ServerConfig::ServerConfig(AppConfig* appConfig, int numColumns, int numRows , m_ClipboardSharingSize(defaultClipboardSharingSize()), m_pMainWindow(mainWindow) { - Q_ASSERT(m_pAppConfig); - + GUI::Config::ConfigWriter::make()->registerClass(this); loadSettings(); } @@ -142,6 +141,9 @@ void ServerConfig::saveSettings() settings().endArray(); settings().endGroup(); + + //Tell the config writer there are changes + GUI::Config::ConfigWriter::make()->markUnsaved(); } void ServerConfig::loadSettings() diff --git a/src/gui/src/ServerConfig.h b/src/gui/src/ServerConfig.h index 506e4edfd..5b989e831 100644 --- a/src/gui/src/ServerConfig.h +++ b/src/gui/src/ServerConfig.h @@ -25,6 +25,7 @@ #include "Screen.h" #include "BaseConfig.h" #include "Hotkey.h" +#include "ConfigBase.h" class QTextStream; class QSettings; @@ -34,13 +35,13 @@ class ServerConfigDialog; class MainWindow; class AppConfig; -class ServerConfig : public BaseConfig +class ServerConfig : public BaseConfig, public GUI::Config::ConfigBase { friend class ServerConfigDialog; friend QTextStream& operator<<(QTextStream& outStream, const ServerConfig& config); public: - ServerConfig(AppConfig* settings, int numColumns, int numRows, + ServerConfig(int numColumns, int numRows, QString serverName, MainWindow* mainWindow); ~ServerConfig(); @@ -68,8 +69,8 @@ class ServerConfig : public BaseConfig size_t clipboardSharingSize() const { return m_ClipboardSharingSize; } static size_t defaultClipboardSharingSize(); - void saveSettings(); - void loadSettings(); + void saveSettings() override; + void loadSettings() override; bool save(const QString& fileName) const; void save(QFile& file) const; int numScreens() const; @@ -111,7 +112,6 @@ class ServerConfig : public BaseConfig void addToFirstEmptyGrid(const QString& clientName); private: - AppConfig* m_pAppConfig; ScreenList m_Screens; int m_NumColumns; int m_NumRows; diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index f1546687c..b8c720ec0 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -68,7 +68,6 @@ void SettingsDialog::accept() //We only need to test the System scoped Radio as they are connected appConfig().setLoadFromSystemScope(m_pRadioSystemScope->isChecked()); - appConfig().saveSettings(); QDialog::accept(); } @@ -201,7 +200,6 @@ void SettingsDialog::on_m_pComboLanguage_currentIndexChanged(int index) void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) { m_appConfig.setCryptoEnabled(checked); - m_appConfig.saveSettings(); if (checked) { SslCertificate sslCertificate; sslCertificate.generateCertificate(); diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 9738c9697..2d350f1cf 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -#define TRAY_RETRY_COUNT 1 +#define TRAY_RETRY_COUNT 10 #define TRAY_RETRY_WAIT 2000 #include "QSynergyApplication.h" @@ -27,7 +27,6 @@ #include #include -#include #include #if defined(Q_OS_MAC) From f50d2065e4e2a78d45dd1332770a50abf3744dc2 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 13:03:42 +0100 Subject: [PATCH 21/25] #6538 Updated AppConfig constructor, and removed some save settings calls --- src/gui/src/MainWindow.cpp | 7 ++----- src/gui/src/MainWindow.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 50b1ffcb2..d342c3850 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -97,7 +97,7 @@ static const char* synergyDefaultIconFiles[] = }; #ifdef SYNERGY_ENTERPRISE -MainWindow::MainWindow (QSettings& settings, AppConfig& appConfig) +MainWindow::MainWindow (AppConfig& appConfig) #else MainWindow::MainWindow (AppConfig& appConfig, LicenseManager& licenseManager) @@ -111,7 +111,7 @@ MainWindow::MainWindow (AppConfig& appConfig, m_AppConfig(&appConfig), m_pSynergy(NULL), m_SynergyState(synergyDisconnected), - m_ServerConfig(m_AppConfig, 5, 3, m_AppConfig->screenName(), this), + m_ServerConfig(5, 3, m_AppConfig->screenName(), this), m_pTempConfigFile(NULL), m_pTrayIcon(NULL), m_pTrayIconMenu(NULL), @@ -195,7 +195,6 @@ MainWindow::MainWindow (AppConfig& appConfig, QString currentVersion = m_VersionChecker.getVersion(); if (lastVersion != currentVersion) { m_AppConfig->setLastVersion (currentVersion); - m_AppConfig->saveSettings(); #ifndef SYNERGY_ENTERPRISE m_LicenseManager->notifyUpdate (lastVersion, currentVersion); #endif @@ -497,7 +496,6 @@ void MainWindow::checkConnected(const QString& line) "the background.")); appConfig().setStartedBefore(true); - appConfig().saveSettings(); } } else if (line.contains("started server")) @@ -1460,7 +1458,6 @@ void MainWindow::on_m_pLabelAutoConfig_linkActivated(const QString &) void MainWindow::on_m_pComboServerList_currentIndexChanged(const QString &server) { appConfig().setAutoConfigServer(server); - appConfig().saveSettings(); } void MainWindow::windowStateChanged() diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 6b34253cb..083d2219f 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -96,7 +96,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase public: #ifdef SYNERGY_ENTERPRISE - MainWindow(QSettings& settings, AppConfig& appConfig); + MainWindow(AppConfig& appConfig); #else MainWindow(AppConfig& appConfig, LicenseManager& licenseManager); From eaf99424c51cc92ff4febef8cf04cad345de57e1 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 13:04:30 +0100 Subject: [PATCH 22/25] #6538 Added Save call when main window is closed. --- src/gui/src/MainWindow.cpp | 6 ++++++ src/gui/src/MainWindow.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index d342c3850..ceec7179b 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -1465,3 +1465,9 @@ void MainWindow::windowStateChanged() if (windowState() == Qt::WindowMinimized && appConfig().getMinimizeToTray()) hide(); } + +void MainWindow::closeEvent(QCloseEvent *event) { + //If the main window is closing, trigger a save + GUI::Config::ConfigWriter::make()->globalSave(); + event->accept(); +} diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 083d2219f..0dd60c80e 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -188,6 +188,8 @@ public slots: void stopDesktop(); void changeEvent(QEvent* event); void retranslateMenuBar(); + void closeEvent(QCloseEvent *event) override; + #if defined(Q_OS_WIN) bool isServiceRunning(QString name); #else From f1f5079497cf7e6723a20ca4775f8bcb31e884d4 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 13:09:26 +0100 Subject: [PATCH 23/25] #6538 Removed braces that somehow got added to member variables --- src/gui/src/AppConfig.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index a7571541d..452899484 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -198,12 +198,12 @@ protected: int m_Port; QString m_Interface; int m_LogLevel; - bool m_LogToFile{}; + bool m_LogToFile; QString m_LogFilename; int m_WizardLastRun; ProcessMode m_ProcessMode; QString m_Language; - bool m_StartedBefore{}; + bool m_StartedBefore; bool m_AutoConfig; QString m_AutoConfigServer; ElevateMode m_ElevateMode; @@ -214,17 +214,17 @@ protected: QString m_Serialkey; QString m_lastVersion; int m_LastExpiringWarningTime; - bool m_ActivationHasRun{}; + bool m_ActivationHasRun; bool m_MinimizeToTray; - bool m_ServerGroupChecked{}; - bool m_UseExternalConfig{}; + bool m_ServerGroupChecked; + bool m_UseExternalConfig; QString m_ConfigFile; - bool m_UseInternalConfig{}; - bool m_ClientGroupChecked{}; + bool m_UseInternalConfig; + bool m_ClientGroupChecked; QString m_ServerHostname; - bool m_LoadFromSystemScope{}; /// @brief should the setting be loaded from SystemScope + bool m_LoadFromSystemScope; /// @brief should the setting be loaded from SystemScope /// If the user has settings but this is true then /// system settings will be loaded instead of the users From f77bc2acff1cffb0262ef7fc990d810e3a6a06d7 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 15:50:01 +0100 Subject: [PATCH 24/25] #6538 Fixed couple issues with comments --- src/gui/src/ConfigWriter.cpp | 21 +++++++++++++++++---- src/gui/src/main.cpp | 2 -- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/ConfigWriter.cpp index 8e77dab4b..0a98003da 100644 --- a/src/gui/src/ConfigWriter.cpp +++ b/src/gui/src/ConfigWriter.cpp @@ -1,6 +1,19 @@ -// -// Created by jamie on 21/04/2020. -// +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2020-2020 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include @@ -18,7 +31,7 @@ namespace GUI { ConfigWriter *ConfigWriter::make() { - // Only one ConfigWriter can exist at any one time (Singolton) + // Only one ConfigWriter can exist at any one time (Singleton) if (!s_pConfiguration) { s_pConfiguration = new ConfigWriter(); } diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp index 2d350f1cf..cff969fd0 100644 --- a/src/gui/src/main.cpp +++ b/src/gui/src/main.cpp @@ -88,8 +88,6 @@ int main(int argc, char* argv[]) #ifndef Q_OS_WIN QApplication::setQuitOnLastWindowClosed(false); #endif - //S - AppConfig appConfig; qRegisterMetaType("Edition"); From 62607ec39071cbe6c8e03eb336ce0497b5853bd0 Mon Sep 17 00:00:00 2001 From: Jamie Newbon Date: Mon, 27 Apr 2020 16:58:27 +0100 Subject: [PATCH 25/25] #6538 Added check if system config doesnt exist then copy from user settings --- src/gui/src/AppConfig.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 5259a19ab..990405078 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -446,8 +446,12 @@ void AppConfig::setLoadFromSystemScope(bool value) { m_LoadFromSystemScope = value; m_unsavedChanges = true; writer->globalSave(); //Save user prefs - writer->setScope(ConfigWriter::kSystem); //Switch the the System Scope and reload - writer->globalLoad(); + writer->setScope(ConfigWriter::kSystem); //Switch the the System Scope + //If the system scope has settings, trigger a global reload, otherwise keep the current users settings + if (writer->hasSetting(settingName(kScreenName), ConfigWriter::kUser)) { + // If the system already has settings, then load them up now. + writer->globalLoad(); + } } else if (!value && writer->getScope() == ConfigWriter::kSystem) {