From d4ae9faad054db7b8dd3043248af7e76024522d6 Mon Sep 17 00:00:00 2001 From: jnewbon Date: Tue, 25 Feb 2020 17:00:30 +0000 Subject: [PATCH] #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)