SYNERGY-677 Application loses settings (#6933)

* SYNERGY-677 Application loses settings

* SYNERGY-677 Update ChangeLog

* SYNERGY-677 Code smells fix.
This commit is contained in:
SerhiiGadzhilov 2021-02-04 20:10:27 +03:00 committed by GitHub
parent d3cd28e051
commit b3034859ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 355 additions and 270 deletions

View file

@ -10,6 +10,7 @@ Bug fixes:
- #6921 Handling pre-main window creation status notifications
- #6922 macOS CI build
- #6927 Text copied and pasted between Windows and Mac OS converts to japanese
- #6933 Application loses settings
Enhancements:
- #6912 Removes UI for Screen Saver Sync and Files Drag and Drop

View file

@ -28,6 +28,7 @@
#include "ConfigWriter.h"
#include "SslCertificate.h"
using GUI::Config::ConfigWriter;
#if defined(Q_OS_WIN)
const char AppConfig::m_SynergysName[] = "synergys.exe";
const char AppConfig::m_SynergycName[] = "synergyc.exe";
@ -111,30 +112,20 @@ AppConfig::AppConfig() :
m_LoadFromSystemScope()
{
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(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(kScreenName), ConfigWriter::kUser) &&
writer->hasSetting(settingName(kScreenName), ConfigWriter::kSystem))
{
writer->setScope(ConfigWriter::kSystem);
} else { // Otherwise just load to user scope
writer->setScope(ConfigWriter::kUser);
}
//Notify registered classes to reload
writer->globalLoad();
//User settings exist and the load from system scope variable is true
if (writer->hasSetting(settingName(kLoadSystemSettings), ConfigWriter::kUser)) {
setLoadFromSystemScope(m_LoadFromSystemScope);
}
//If user setting don't exist but system ones do, load the system settings
else if (writer->hasSetting(settingName(kScreenName), ConfigWriter::kSystem)) {
setLoadFromSystemScope(true);
}
}
const QString &AppConfig::screenName() const { return m_ScreenName; }
@ -214,7 +205,7 @@ void AppConfig::loadSettings()
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_WizardLastRun = loadCommonSetting(kWizardLastRun, 0).toInt();
m_Language = loadSetting(kLanguage, QLocale::system().name()).toString();
m_StartedBefore = loadSetting(kStartedBefore, false).toBool();
m_AutoConfig = loadSetting(kAutoConfig, false).toBool();
@ -237,7 +228,7 @@ void AppConfig::loadSettings()
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_LoadFromSystemScope = loadCommonSetting(kLoadSystemSettings, false).toBool();
m_ServerGroupChecked = loadSetting(kGroupServerCheck, false).toBool();
m_UseExternalConfig = loadSetting(kUseExternalConfig, false).toBool();
m_ConfigFile = loadSetting(kConfigFile, QDir::homePath() + "/" + synergyConfigName).toString();
@ -246,8 +237,8 @@ void AppConfig::loadSettings()
m_ServerHostname = loadSetting(kServerHostname).toString();
//only change the serial key if the settings being loaded contains a key
bool updateSerial = GUI::Config::ConfigWriter::make()
->hasSetting(settingName(kLoadSystemSettings),GUI::Config::ConfigWriter::kCurrent);
bool updateSerial = ConfigWriter::make()
->hasSetting(settingName(kLoadSystemSettings),ConfigWriter::kCurrent);
//if the setting exists and is not empty
updateSerial = updateSerial && !loadSetting(kSerialKey, "").toString().trimmed().isEmpty();
@ -272,13 +263,14 @@ void AppConfig::loadSettings()
void AppConfig::saveSettings()
{
setCommonSetting(kWizardLastRun, kWizardVersion);
setCommonSetting(kLoadSystemSettings, m_LoadFromSystemScope);
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);
@ -295,7 +287,6 @@ void AppConfig::saveSettings()
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);
@ -383,12 +374,14 @@ void AppConfig::setAutoConfigServer(const QString& autoConfigServer)
#ifndef SYNERGY_ENTERPRISE
void AppConfig::setEdition(Edition e) {
setSettingModified(m_Edition, e);
setCommonSetting(kEditionSetting, m_Edition);
}
Edition AppConfig::edition() const { return m_Edition; }
void AppConfig::setSerialKey(const QString& serial) {
setSettingModified(m_Serialkey, serial);
setCommonSetting(kSerialKey, m_Serialkey);
}
void AppConfig::clearSerialKey()
@ -456,17 +449,41 @@ QString AppConfig::settingName(AppConfig::Setting name) {
template<typename T>
void AppConfig::setSetting(AppConfig::Setting name, T value) {
using GUI::Config::ConfigWriter;
ConfigWriter::make()->setSetting(settingName(name), value);
}
template<typename T>
void AppConfig::setCommonSetting(AppConfig::Setting name, T value) {
ConfigWriter::make()->setSetting(settingName(name), value, ConfigWriter::kUser);
ConfigWriter::make()->setSetting(settingName(name), value, ConfigWriter::kSystem);
}
QVariant AppConfig::loadSetting(AppConfig::Setting name, const QVariant& defaultValue) {
using GUI::Config::ConfigWriter;
return ConfigWriter::make()->loadSetting(settingName(name), defaultValue);
}
void AppConfig::loadScope(GUI::Config::ConfigWriter::Scope scope) const {
auto writer = GUI::Config::ConfigWriter::make();
QVariant AppConfig::loadCommonSetting(AppConfig::Setting name, const QVariant& defaultValue) const {
QVariant result(defaultValue);
QString setting(settingName(name));
auto& writer = *ConfigWriter::make();
if (writer.hasSetting(setting)) {
result = writer.loadSetting(setting, defaultValue);
}
else if (writer.getScope() == ConfigWriter::kSystem ) {
if (writer.hasSetting(setting, ConfigWriter::kUser)) {
result = writer.loadSetting(setting, defaultValue, ConfigWriter::kUser);
}
}
else if (writer.hasSetting(setting, ConfigWriter::kSystem)){
result = writer.loadSetting(setting, defaultValue, ConfigWriter::kSystem);
}
return result;
}
void AppConfig::loadScope(ConfigWriter::Scope scope) const {
auto writer = ConfigWriter::make();
if (writer->getScope() != scope) {
writer->setScope(scope);
@ -480,18 +497,10 @@ void AppConfig::loadScope(GUI::Config::ConfigWriter::Scope scope) const {
void AppConfig::setLoadFromSystemScope(bool value) {
if (value) {
/* Before switching to system scope we should store
* m_LoadFromSystemScope with the new value into user scope.
* It's neccessary because constructor of ConfigWriter
* loads user scope by default and we should know in this
* scope if we should switch to system scope.
*/
m_LoadFromSystemScope = value;
saveSettings();
loadScope(GUI::Config::ConfigWriter::kSystem);
loadScope(ConfigWriter::kSystem);
}
else {
loadScope(GUI::Config::ConfigWriter::kUser);
loadScope(ConfigWriter::kUser);
}
/*
@ -501,8 +510,12 @@ void AppConfig::setLoadFromSystemScope(bool value) {
m_LoadFromSystemScope = value;
}
bool AppConfig::isWritable() const {
return ConfigWriter::make()->isWritable();
}
bool AppConfig::isSystemScoped() const {
return GUI::Config::ConfigWriter::make()->getScope() == GUI::Config::ConfigWriter::kSystem;
return ConfigWriter::make()->getScope() == ConfigWriter::kSystem;
}
bool AppConfig::getServerGroupChecked() const {

View file

@ -67,7 +67,7 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase
AppConfig();
public:
bool isWritable() const;
bool isSystemScoped() const;
const QString& screenName() const;
@ -273,11 +273,23 @@ protected:
template <typename T>
void setSetting(AppConfig::Setting name, T value);
/// @brief Sets the value of a common setting
/// which should have the same value for all scopes
/// @param [in] name The Setting to be saved
/// @param [in] value The Value to be saved
template <typename T>
void setCommonSetting(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());
/// @brief Loads a common setting
/// @param [in] name The setting to be loaded
/// @param [in] defaultValue The default value of the setting
QVariant loadCommonSetting(AppConfig::Setting name, const QVariant& defaultValue = QVariant()) const;
/// @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.

View file

@ -18,8 +18,7 @@
#include <cassert>
#include <QCoreApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QFile>
#include "ConfigWriter.h"
#include "ConfigBase.h"
@ -38,6 +37,18 @@ namespace GUI {
return s_pConfiguration;
}
void loadOldSystemSettings(QSettings& settings)
{
if (!QFile(settings.fileName()).exists()) {
QFile oldSystemSettings("SystemConfig.ini");
if (oldSystemSettings.exists()) {
QSettings oldSettings(oldSystemSettings.fileName(), QSettings::Format::IniFormat);
for (const auto& key : oldSettings.allKeys()) {
settings.setValue(key, oldSettings.value(key));
}
}
}
}
ConfigWriter::ConfigWriter() {
QSettings::setPath(QSettings::Format::IniFormat,
@ -51,6 +62,9 @@ namespace GUI {
QCoreApplication::organizationName(),
QCoreApplication::applicationName());
//This call is needed for backwardcapability with old settings.
loadOldSystemSettings(*m_pSettingsSystem);
//defaults to user scope, if we set the scope specifically then we also have to set
// the application name and the organisation name which breaks backwards compatibility
// See #6730
@ -86,7 +100,9 @@ namespace GUI {
}
}
bool ConfigWriter::isWritable() const {
return m_pSettingsCurrent->isWritable();
}
QVariant ConfigWriter::loadSetting(const QString& name, const QVariant &defaultValue, Scope scope) {
switch (scope){
@ -151,7 +167,7 @@ namespace GUI {
QString path;
#if defined(Q_OS_WIN)
// Program file
path = "";
path = QCoreApplication::applicationDirPath() + "\\";
#elif defined(Q_OS_DARWIN)
//Global preferances dir
// Would be nice to use /library, but QT has no elevate system in place

View file

@ -51,6 +51,10 @@ namespace GUI {
/// @return bool True if the current scope has the named setting
bool hasSetting(const QString& name, Scope scope = kCurrent) const;
/// @brief Checks if the current scope settings writable
/// @return bool True if the current scope writable
bool isWritable() const;
/// @brief Sets the value of a setting
/// @param [in] name The Setting to be saved
/// @param [in] value The Value to be saved (Templated)

View file

@ -120,7 +120,6 @@ MainWindow::MainWindow (AppConfig& appConfig,
m_pMenuHelp(NULL),
m_pCancelButton(NULL),
m_ExpectedRunningState(kStopped),
m_pSslCertificate(NULL),
m_SecureSocket(false)
{
#ifndef SYNERGY_ENTERPRISE
@ -222,8 +221,6 @@ MainWindow::~MainWindow()
#ifndef SYNERGY_ENTERPRISE
delete m_pZeroconf;
#endif
delete m_pSslCertificate;
}
void MainWindow::open()
@ -1412,4 +1409,4 @@ void MainWindow::windowStateChanged()
void MainWindow::updateScreenName()
{
m_pLabelScreenName->setText(getScreenName());
}
}

View file

@ -236,7 +236,6 @@ public slots:
TrayIcon m_trayIcon;
qRuningState m_ExpectedRunningState;
QMutex m_StopDesktopMutex;
SslCertificate* m_pSslCertificate;
bool m_SecureSocket; // brief Is the program running a secure socket protocol (SSL/TLS)
QString m_SecureSocketVersion; // brief Contains the version of the Secure Socket currently active

View file

@ -45,10 +45,11 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
m_pMainWindow = dynamic_cast<MainWindow*>(parent);
m_Locale.fillLanguageComboBox(m_pComboLanguage);
m_isSystemAtStart = appConfig().isSystemScoped();
buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
loadFromConfig();
m_isSystemAtStart = appConfig().isSystemScoped();
buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
enableControls(appConfig().isWritable());
connect(m_pLineEditLogFilename, SIGNAL(textChanged(const QString&)), this, SLOT(onChange()));
connect(m_pComboLogLevel, SIGNAL(currentIndexChanged(int)), this, SLOT(onChange()));
@ -250,6 +251,7 @@ void SettingsDialog::on_m_pRadioSystemScope_toggled(bool checked)
appConfig().setLoadFromSystemScope(checked);
loadFromConfig();
buttonBox->button(QDialogButtonBox::Save)->setEnabled(m_isSystemAtStart != checked);
enableControls(appConfig().isWritable());
}
void SettingsDialog::on_m_pPushButtonBrowseCert_clicked() {
@ -318,6 +320,37 @@ bool SettingsDialog::isModified()
);
}
void SettingsDialog::enableControls(bool enable) {
m_pLineEditScreenName->setEnabled(enable);
m_pSpinBoxPort->setEnabled(enable);
m_pLineEditInterface->setEnabled(enable);
m_pComboLogLevel->setEnabled(enable);
m_pCheckBoxLogToFile->setEnabled(enable);
m_pComboLanguage->setEnabled(enable);
m_pComboElevate->setEnabled(enable);
m_pCheckBoxAutoHide->setEnabled(enable);
m_pCheckBoxAutoConfig->setEnabled(enable);
m_pCheckBoxMinimizeToTray->setEnabled(enable);
m_pLineEditCertificatePath->setEnabled(enable);
m_pComboBoxKeyLength->setEnabled(enable);
m_pPushButtonBrowseCert->setEnabled(enable);
m_labelAdminRightsMessage->setVisible(!enable);
if (enable) {
m_pLineEditLogFilename->setEnabled(m_pCheckBoxLogToFile->isChecked());
m_pButtonBrowseLog->setEnabled(m_pCheckBoxLogToFile->isChecked());
m_pCheckBoxEnableCrypto->setEnabled(m_appConfig.isCryptoAvailable());
updateRegenButton();
}
else {
m_pLineEditLogFilename->setEnabled(enable);
m_pButtonBrowseLog->setEnabled(enable);
m_pCheckBoxEnableCrypto->setEnabled(enable);
m_pPushButtonRegenCert->setEnabled(enable);
}
}
void SettingsDialog::onChange()
{
buttonBox->button(QDialogButtonBox::Save)->setEnabled(isModified());

View file

@ -59,6 +59,9 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
/// @return true if there are modifications.
bool isModified();
/// @brief Enables\disables all controls.
void enableControls(bool enabled);
private:
MainWindow* m_pMainWindow;
AppConfig& m_appConfig;

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>378</width>
<height>756</height>
<height>770</height>
</rect>
</property>
<property name="windowTitle">
@ -40,7 +40,226 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<item row="10" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QGroupBox" name="m_pGroupBoxTLS">
<property name="title">
<string>TLS/SSL Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditCertificatePath"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="m_pLabel_29">
<property name="text">
<string>Key length</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_30">
<property name="text">
<string>Certificate Path</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="m_pPushButtonBrowseCert">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="m_pComboBoxKeyLength">
<property name="currentText">
<string>1024</string>
</property>
<item>
<property name="text">
<string>1024</string>
</property>
</item>
<item>
<property name="text">
<string>2048</string>
</property>
</item>
<item>
<property name="text">
<string>4096</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="m_pPushButtonRegenCert">
<property name="text">
<string>Regenerate Cert</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="m_pGroupNetwork">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>&amp;Network</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="m_pGridLayoutNetwork">
<property name="leftMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>12</number>
</property>
<item row="1" column="1">
<widget class="QLabel" name="m_pLabelProUpgrade">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://symless.com/account?source=gui&amp;amp;intent=upgrade&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Upgrade to Pro&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="m_pLabelInstallBonjour">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Install Bonjour&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="m_pCheckBoxAutoConfig">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable Auto Config</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable &amp;TLS Encryption</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="m_pGroupAdvanced">
<property name="title">
<string>&amp;Miscellaneous</string>
@ -189,200 +408,7 @@
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="m_pGroupNetwork">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>&amp;Network</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="m_pGridLayoutNetwork">
<property name="leftMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>12</number>
</property>
<item row="1" column="1">
<widget class="QLabel" name="m_pLabelProUpgrade">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://symless.com/account?source=gui&amp;amp;intent=upgrade&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Upgrade to Pro&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="m_pLabelInstallBonjour">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;#&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Install Bonjour&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="m_pCheckBoxAutoConfig">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable Auto Config</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enable &amp;TLS Encryption</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="m_pGroupBoxTLS">
<property name="title">
<string>TLS/SSL Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditCertificatePath"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="m_pLabel_29">
<property name="text">
<string>Key length</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_30">
<property name="text">
<string>Certificate Path</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="m_pPushButtonBrowseCert">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="m_pComboBoxKeyLength">
<property name="currentText">
<string>2048</string>
</property>
<item>
<property name="text">
<string>1024</string>
</property>
</item>
<item>
<property name="text">
<string>2048</string>
</property>
</item>
<item>
<property name="text">
<string>4096</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="m_pPushButtonRegenCert">
<property name="text">
<string>Regenerate Cert</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QGroupBox" name="m_pGroupLog">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -467,29 +493,10 @@
</layout>
</widget>
</item>
<item row="8" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
<item row="1" column="0">
<widget class="QLabel" name="m_labelAdminRightsMessage">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:7pt; font-weight:600;&quot;&gt;To edit settings for all users, Admin privileges are required.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>