Introduce 'Advanced' tab to Preferences window (#7419)

* Add QML and QtQuick deps

* Keep only Qt declarative

* Fixed delcarative package name

* Use `qt6-qtdeclarative` on OpenSUSE

* Fixed warnings

* Introduce tabs for settings and make some settings easier to understand

* Further reorganization of settings UI

* Revert config.yml

* Show Qt version in config

* Remove custom font

* Improve wording of elevate privs

* Fixed window sizes and default tabs

* Save main window size and position

* Fixed slot warning

* Fixed hacky use of validators

* Make activation cancel more intuitive

* Save window state in dtor and add try-catch to prevent exceptions propagating

* Fixed consistency of fatal messages

* Improve color conssitency and add tooltip

* Clean up styles and weird layout

* Move config files to new gui lib

* Core interface integ tests

* Rename `Config` to `ConfigScopes`

* Add 'Schoeneman' to cspell

* Fixed incorrect `Config` (should be `ConfigScopes`)

* Fixed typo

* Missed a spot

* Delete accidentally re-added file

* Fixed formatting

* Add short opt

* Coverage for `AppConfig`

* Update ChangeLog

* Remove redundant includes

* Fixed date

* Remove rogue include
This commit is contained in:
Nick Bolton 2024-08-01 01:13:01 +01:00 committed by GitHub
parent 6a6de24f59
commit 9eeb1cb7ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 2064 additions and 2004 deletions

View file

@ -64,6 +64,7 @@ Enhancements:
- #7415 Assert arg value `num > 0` for BSD socket poll unblock pipe
- #7416 Catch exception propagating to `Server` dtor
- #7421 Only load core after settings have fully loaded
- #7419 Introduce 'Advanced' tab to Preferences window
# 1.14.6

View file

@ -291,6 +291,8 @@ macro(config_qt)
COMPONENTS Core Widgets Network
REQUIRED)
message(STATUS "Qt version: ${Qt6_VERSION}")
endmacro()
macro(configure_openssl)

View file

@ -4,6 +4,7 @@
"dictionaryDefinitions": [],
"dictionaries": [],
"words": [
"Schoeneman",
"aqtinstall",
"codesign",
"codesigning",

View file

@ -25,6 +25,7 @@ def main():
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"-f",
"--format",
action="store_true",
help="In-place format all files",

View file

@ -23,6 +23,7 @@ def main():
"""
parser = argparse.ArgumentParser()
parser.add_argument(
"-f",
"--format",
action="store_true",
help="In-place format all files",

View file

@ -51,19 +51,11 @@ AboutDialog::AboutDialog(MainWindow *parent, const AppConfig &config)
int AboutDialog::exec() {
m_pDevelopersLabel->setText(getImportantDevelopers());
m_pCopyrightLabel->setText(getCopyright());
resizeWindow();
updateLogo();
return QDialog::exec();
}
void AboutDialog::resizeWindow() {
QSize size(600, 310);
setMaximumSize(size);
setMinimumSize(size);
resize(size);
}
void AboutDialog::updateLogo() const {
#if defined(Q_OS_MAC)
if (isOSXInterfaceStyleDark()) {

View file

@ -37,7 +37,6 @@ private:
VersionChecker m_versionChecker;
void updateLogo() const;
virtual void resizeWindow();
virtual QString getCopyright() const;
virtual QString getImportantDevelopers() const;
};

View file

@ -17,17 +17,15 @@
#include "ActivationDialog.h"
#include "gui/license_notices.h"
#include "ui_ActivationDialog.h"
#include "AppConfig.h"
#include "CancelActivationDialog.h"
#include "MainWindow.h"
#include "gui/AppConfig.h"
#include "gui/LicenseHandler.h"
#include "gui/constants.h"
#include "gui/license_notices.h"
#include "license/ProductEdition.h"
#include "license/parse_serial_key.h"
#include "ui_ActivationDialog.h"
#include <QApplication>
#include <QMessageBox>
@ -44,6 +42,9 @@ ActivationDialog::ActivationDialog(
m_licenseHandler(licenseHandler) {
m_ui->setupUi(this);
m_ui->m_pLabelNotice->setStyleSheet(kStyleNoticeLabel);
refreshSerialKey();
if (!m_licenseHandler.license().isExpired()) {
@ -64,7 +65,7 @@ void ActivationDialog::refreshSerialKey() {
const auto &license = m_licenseHandler.license();
if (license.isTimeLimited()) {
m_ui->m_labelNotice->setText(licenseNotice(license));
m_ui->m_pLabelNotice->setText(licenseNotice(license));
}
}
@ -78,9 +79,9 @@ void ActivationDialog::reject() {
return;
}
// the user is told that the 'No' button will exit the app.
// the accept button should be labeled "Exit" on the cancel dialoig.
CancelActivationDialog cancelActivationDialog(this);
if (cancelActivationDialog.exec() == QDialog::Rejected) {
if (cancelActivationDialog.exec() == QDialog::Accepted) {
QApplication::exit();
}
}
@ -126,19 +127,21 @@ void ActivationDialog::showResultDialog(
case kInvalid:
QMessageBox::critical(
this, title,
QString("Invalid serial key. "
R"(Please <a href="%1" style="%2">contact us</a> for help.)")
QString(
"Invalid serial key. "
R"(Please <a href="%1" style="color: %2">contact us</a> for help.)")
.arg(kUrlContact)
.arg(kLinkStyleSecondary));
.arg(kColorSecondary));
break;
case kExpired:
QMessageBox::warning(
this, title,
QString("Sorry, that serial key has expired. "
R"(Please <a href="%1" style="%1">renew</a> your license.)")
QString(
"Sorry, that serial key has expired. "
R"(Please <a href="%1" style="color: %1">renew</a> your license.)")
.arg(kUrlPurchase)
.arg(kLinkStyleSecondary));
.arg(kColorSecondary));
break;
default:
@ -180,11 +183,11 @@ void ActivationDialog::showSuccessDialog() {
void ActivationDialog::showErrorDialog(const QString &message) {
QString fullMessage =
QString("<p>There was a problem activating Synergy.</p>"
R"(<p>Please <a href="%1" style="%2">contact us</a> )"
R"(<p>Please <a href="%1" style="color: %2">contact us</a> )"
"and provide the following information:</p>"
"%3")
.arg(kUrlContact)
.arg(kLinkStyleSecondary)
.arg(kColorSecondary)
.arg(message);
QMessageBox::critical(this, "Activation failed", fullMessage);
}

View file

@ -75,16 +75,9 @@ li.checked::marker { content: &quot;\2612&quot;; }
<number>8</number>
</property>
<item>
<widget class="QLabel" name="m_labelNotice">
<property name="styleSheet">
<string notr="true">padding: 3px 5px;
border-radius: 3px;
background-color: #3B67D3;
color: #ffffff;
top: 3px;</string>
</property>
<widget class="QLabel" name="m_pLabelNotice">
<property name="text">
<string>m_labelNotice</string>
<string>m_pLabelNotice</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@ -94,7 +87,7 @@ top: 3px;</string>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -110,10 +103,10 @@ top: 3px;</string>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>

View file

@ -1,10 +1,33 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
#include "CancelActivationDialog.h"
#include "ui_CancelActivationDialog.h"
#include "QPushButton"
CancelActivationDialog::CancelActivationDialog(QWidget *parent)
: QDialog(parent),
ui(new Ui::CancelActivationDialog) {
ui->setupUi(this);
ui->m_pButtonBox->button(QDialogButtonBox::Cancel)->setText("&Back");
ui->m_pButtonBox->button(QDialogButtonBox::Ok)->setText("&Exit");
}
CancelActivationDialog::~CancelActivationDialog() { delete ui; }

View file

@ -1,5 +1,21 @@
#ifndef CANCELACTIVATIONDIALOG_H
#define CANCELACTIVATIONDIALOG_H
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QDialog>
@ -17,5 +33,3 @@ public:
private:
Ui::CancelActivationDialog *ui;
};
#endif // CANCELACTIVATIONDIALOG_H

View file

@ -6,18 +6,18 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>246</height>
<width>429</width>
<height>273</height>
</rect>
</property>
<property name="windowTitle">
<string>Cancel Activation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You'll need to purchase a license to use this build of Synergy.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://symless.com/synergy/purchase?source=gui&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Purchase Synergy&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If you'd prefer to use the community edition instead, visit us on GitHub.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/symless/synergy-core&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;GitHub project&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Would you like to go back and enter a serial key?&lt;/p&gt;&lt;p&gt;Choosing 'No' will quit Synergy.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You'll need to purchase a license to use this build of Synergy.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://symless.com/synergy/purchase?source=gui&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Purchase Synergy&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If you'd prefer to use the community edition instead, visit us on GitHub.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/symless/synergy-core&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;GitHub project&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -28,25 +28,12 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<widget class="QDialogButtonBox" name="m_pButtonBox">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::No|QDialogButtonBox::Yes</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
@ -55,7 +42,7 @@
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<sender>m_pButtonBox</sender>
<signal>accepted()</signal>
<receiver>CancelActivationDialog</receiver>
<slot>accept()</slot>
@ -71,7 +58,7 @@
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<sender>m_pButtonBox</sender>
<signal>rejected()</signal>
<receiver>CancelActivationDialog</receiver>
<slot>reject()</slot>

View file

@ -94,19 +94,89 @@ MainWindow::MainWindow(AppConfig &appConfig)
m_ServerConfig(5, 3, &m_AppConfig, this),
m_ServerConnection(*this),
m_ClientConnection(*this),
m_TlsUtility(appConfig, m_LicenseHandler.license()) {
m_TlsUtility(appConfig, m_LicenseHandler.license()),
m_WindowSaveTimer(this) {
setupUi(this);
setupControls();
connectSlots();
#if defined(Q_OS_WIN)
// TODO: only connect permenantly to ipc when switching to service mode.
// if switching from service to desktop, connect only to stop the service
// and don't retry.
m_IpcClient.connectToHost();
#endif
emit created();
}
MainWindow::~MainWindow() {
try {
if (appConfig().processMode() == ProcessMode::kDesktop) {
m_ExpectedRunningState = RuningState::Stopped;
stopDesktop();
}
} catch (const std::exception &e) {
qFatal("failed to stop core on main window close: %s", e.what());
}
try {
saveWindow();
} catch (const std::exception &e) {
qFatal("failed to save window on main window close: %s", e.what());
}
}
void MainWindow::restoreWindow() {
const auto &config = appConfig();
const auto &size = config.mainWindowSize();
if (size.has_value()) {
qDebug("restoring main window size");
resize(size.value());
}
const auto &position = config.mainWindowPosition();
if (position.has_value()) {
qDebug("restoring main window position");
move(position.value());
}
// give the window chance to restore its size and position before the window
// size and position are saved. this prevents the window from being saved
// with the wrong size and position.
m_SaveWindow = true;
}
void MainWindow::saveWindow() {
if (!m_SaveWindow) {
qDebug("not yet ready to save window size and position, skipping");
return;
}
qDebug("saving window size and position");
auto &config = appConfig();
config.setMainWindowSize(size());
config.setMainWindowPosition(pos());
config.saveSettings();
}
void MainWindow::setupControls() {
createMenuBar();
secureSocket(false);
m_pLabelUpdate->setStyleSheet(kStyleNoticeLabel);
m_pLabelUpdate->hide();
m_pLabelIpAddresses->setText(
tr("This computer's IP addresses: %1").arg(getIPAddresses()));
m_pLabelNotice->setStyleSheet(kStyleNoticeLabel);
m_pLabelNotice->hide();
m_labelNotice->hide();
m_pLabelIpAddresses->setText(
QString("This computer's IP addresses: %1").arg(getIPAddresses()));
if (m_AppConfig.lastVersion() != SYNERGY_VERSION) {
m_AppConfig.setLastVersion(SYNERGY_VERSION);
@ -118,34 +188,10 @@ MainWindow::MainWindow(AppConfig &appConfig)
#if defined(Q_OS_MAC)
resize(720, 550);
setMinimumSize(size());
m_pRadioGroupServer->setAttribute(Qt::WA_MacShowFocusRect, 0);
m_pRadioGroupClient->setAttribute(Qt::WA_MacShowFocusRect, 0);
#elif defined(Q_OS_LINUX)
resize(700, 530);
setMinimumSize(size());
#elif defined(Q_OS_WIN)
// TODO: only connect permenantly to ipc when switching to service mode.
// if switching from service to desktop, connect only to stop the service and
// don't retry.
m_IpcClient.connectToHost();
#endif
emit created();
}
MainWindow::~MainWindow() {
if (appConfig().processMode() == ProcessMode::kDesktop) {
m_ExpectedRunningState = RuningState::Stopped;
stopDesktop();
}
}
//////////////////////////////////////////////////////////////////////////////
@ -175,7 +221,7 @@ void MainWindow::connectSlots() const {
&MainWindow::onAppConfigScreenNameChanged);
connect(
&m_AppConfig, &AppConfig::invertConnection, this,
&m_AppConfig, &AppConfig::invertConnectionChanged, this,
&MainWindow::onAppConfigInvertConnection);
connect(
@ -215,6 +261,10 @@ void MainWindow::connectSlots() const {
connect(
&m_VersionChecker, &VersionChecker::updateFound, this,
&MainWindow::onVersionCheckerUpdateFound);
connect(
&m_WindowSaveTimer, &QTimer::timeout, this,
&MainWindow::onWindowSaveTimerTimeout);
}
void MainWindow::onAppAboutToQuit() { m_AppConfig.saveSettings(); }
@ -263,8 +313,10 @@ void MainWindow::onAppConfigLoaded() {
if (!m_AppConfig.serialKey().isEmpty()) {
m_LicenseHandler.changeSerialKey(m_AppConfig.serialKey());
}
updateScreenName();
applyConfig();
restoreWindow();
}
void MainWindow::onAppConfigTlsChanged() {
@ -315,7 +367,7 @@ void MainWindow::onCoreProcessReadyReadStandardError() {
}
void MainWindow::onVersionCheckerUpdateFound(const QString &version) {
const auto link = QString(kLinkDownload).arg(kUrlDownload, kLinkStyleWhite);
const auto link = QString(kLinkDownload).arg(kUrlDownload, kColorWhite);
const auto text =
QString("A new version is available (v%1). %2").arg(version, link);
@ -367,11 +419,12 @@ void MainWindow::onCoreProcessFinished(int exitCode, QProcess::ExitStatus) {
bool MainWindow::on_m_pActionSave_triggered() {
QString fileName =
QFileDialog::getSaveFileName(this, tr("Save configuration as..."));
QFileDialog::getSaveFileName(this, QString("Save configuration as..."));
if (!fileName.isEmpty() && !serverConfig().save(fileName)) {
QMessageBox::warning(
this, tr("Save failed"), tr("Could not save configuration to file."));
this, QString("Save failed"),
QString("Could not save configuration to file."));
return true;
}
@ -439,10 +492,28 @@ void MainWindow::on_m_pButtonConnectToClient_clicked() {
on_m_pButtonApply_clicked();
}
void MainWindow::onWindowSaveTimerTimeout() { saveWindow(); }
//////////////////////////////////////////////////////////////////////////////
// End slots
//////////////////////////////////////////////////////////////////////////////
void MainWindow::resizeEvent(QResizeEvent *event) {
QMainWindow::resizeEvent(event);
// postpone save so that settings are not written every delta change.
m_WindowSaveTimer.setSingleShot(true);
m_WindowSaveTimer.start(1000);
}
void MainWindow::moveEvent(QMoveEvent *event) {
QMainWindow::moveEvent(event);
// postpone save so that settings are not written every delta change.
m_WindowSaveTimer.setSingleShot(true);
m_WindowSaveTimer.start(1000);
}
void MainWindow::open() {
std::array<QAction *, 7> trayMenu = {
@ -522,7 +593,7 @@ void MainWindow::saveSettings() {
appConfig().setServerHostname(m_pLineEditHostname->text());
serverConfig().setClientAddress(m_pLineEditClientIp->text());
appConfig().config().saveAll();
appConfig().scopes().saveAll();
}
void MainWindow::setIcon(CoreState state) const {
@ -555,7 +626,7 @@ void MainWindow::appendLogInfo(const QString &text) {
}
void MainWindow::appendLogDebug(const QString &text) {
qDebug() << text;
qDebug("%s", text.toStdString().c_str());
if (appConfig().logLevel() >= kDebugLogLevel) {
processCoreLogLine(getTimeStamp() + " DEBUG: " + text);
@ -621,7 +692,7 @@ void MainWindow::checkConnected(const QString &line) {
if (!appConfig().startedBefore() && isVisible()) {
QMessageBox::information(
this, "Synergy",
tr("Synergy is now connected. You can close the "
QString("Synergy is now connected. You can close the "
"config window and Synergy will remain connected in "
"the background."));
@ -663,8 +734,9 @@ void MainWindow::checkFingerprint(const QString &line) {
messageBoxAlreadyShown = true;
QMessageBox::StandardButton fingerprintReply = QMessageBox::information(
this, tr("Security question"),
tr("You are connecting to a server. Here is it's fingerprint:\n\n"
this, QString("Security question"),
QString(
"You are connecting to a server. Here is it's fingerprint:\n\n"
"%1\n\n"
"Compare this fingerprint to the one on your server's screen."
"If the two don't match exactly, then it's probably not the server "
@ -806,7 +878,7 @@ void MainWindow::startCore() {
args << "--profile-dir" << getProfileRootForArg();
} catch (const std::exception &e) {
qDebug() << e.what();
qFatal("Failed to get profile dir, skipping arg");
qFatal("failed to get profile dir, skipping arg");
}
#else
@ -861,9 +933,10 @@ void MainWindow::startCore() {
if (!m_pCoreProcess->waitForStarted()) {
show();
QMessageBox::warning(
this, tr("Program can not be started"),
this, QString("Program can not be started"),
QString(
tr("The executable<br><br>%1<br><br>could not be successfully "
QString(
"The executable<br><br>%1<br><br>could not be successfully "
"started, although it does exist. Please check if you have "
"sufficient permissions to run this program.")
.arg(app)));
@ -881,8 +954,8 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
if (!QFile::exists(app)) {
show();
QMessageBox::warning(
this, tr("Synergy client not found"),
tr("The executable for the synergy client does not exist."));
this, QString("Synergy client not found"),
QString("The executable for the synergy client does not exist."));
return false;
}
@ -906,8 +979,8 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
if (m_pLineEditHostname->text().isEmpty()) {
show();
QMessageBox::warning(
this, tr("IP/hostname is empty"),
tr("Please enter a server hostname or IP address."));
this, QString("IP/hostname is empty"),
QString("Please enter a server hostname or IP address."));
return false;
}
@ -937,15 +1010,15 @@ QString MainWindow::configFilename() {
{QStandardPaths::AppDataLocation, QStandardPaths::AppConfigLocation}) {
auto configDirPath = QStandardPaths::writableLocation(path);
if (!QDir().mkpath(configDirPath)) {
errors.push_back(
tr("Failed to create config folder \"%1\"").arg(configDirPath));
errors.push_back(QString("Failed to create config folder \"%1\"")
.arg(configDirPath));
continue;
}
QFile configFile(configDirPath + "/LastConfig.cfg");
if (!configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
errors.push_back(
tr("File:\"%1\" Error:%2")
QString("File:\"%1\" Error:%2")
.arg(configFile.fileName(), configFile.errorString()));
continue;
}
@ -959,7 +1032,7 @@ QString MainWindow::configFilename() {
if (configFullPath.isEmpty()) {
QMessageBox::critical(
this, tr("Cannot write configuration file"), errors.join('\n'));
this, QString("Cannot write configuration file"), errors.join('\n'));
}
}
@ -990,15 +1063,15 @@ bool MainWindow::serverArgs(QStringList &args, QString &app) {
if (!QFile::exists(app)) {
QMessageBox::warning(
this, tr("Synergy server not found"),
tr("The executable for the synergy server does not exist."));
this, QString("Synergy server not found"),
QString("The executable for the synergy server does not exist."));
return false;
}
if (appConfig().invertConnection() && m_pLineEditClientIp->text().isEmpty()) {
QMessageBox::warning(
this, tr("Client IP address or name is empty"),
tr("Please fill in a client IP address or name."));
this, QString("Client IP address or name is empty"),
QString("Please fill in a client IP address or name."));
return false;
}
@ -1080,7 +1153,7 @@ void MainWindow::setCoreState(CoreState state) {
m_pButtonToggleStart, &QPushButton::clicked, m_pActionStopCore,
&QAction::trigger);
m_pButtonToggleStart->setText(tr("&Stop"));
m_pButtonToggleStart->setText(QString("&Stop"));
m_pButtonApply->setEnabled(true);
m_pActionStartCore->setEnabled(false);
@ -1094,7 +1167,7 @@ void MainWindow::setCoreState(CoreState state) {
m_pButtonToggleStart, &QPushButton::clicked, m_pActionStartCore,
&QAction::trigger);
m_pButtonToggleStart->setText(tr("&Start"));
m_pButtonToggleStart->setText(QString("&Start"));
m_pButtonApply->setEnabled(false);
m_pActionStartCore->setEnabled(true);
@ -1106,8 +1179,7 @@ void MainWindow::setCoreState(CoreState state) {
case Listening: {
if (coreMode() == CoreMode::Server) {
setStatus(
tr("Synergy is waiting for clients").arg(m_SecureSocketVersion));
setStatus("Synergy is waiting for clients");
}
break;
@ -1115,21 +1187,20 @@ void MainWindow::setCoreState(CoreState state) {
case Connected: {
if (m_SecureSocket) {
setStatus(
tr("Synergy is connected (with %1)").arg(m_SecureSocketVersion));
QString("Synergy is connected (with %1)").arg(m_SecureSocketVersion));
} else {
setStatus(tr("Synergy is running (without TLS encryption)")
.arg(m_SecureSocketVersion));
setStatus("Synergy is running (without TLS encryption)");
}
break;
}
case Connecting:
setStatus(tr("Synergy is starting..."));
setStatus("Synergy is starting...");
break;
case PendingRetry:
setStatus(tr("There was an error, retrying..."));
setStatus("There was an error, retrying...");
break;
case Disconnected:
setStatus(tr("Synergy is not running"));
setStatus("Synergy is not running");
break;
}
@ -1176,8 +1247,8 @@ QString MainWindow::getIPAddresses() const {
// usually 192.168.x.x is a useful ip for the user, so indicate
// this by making it bold.
if (!hinted && address.isInSubnet(localnet)) {
QString format = "<span style=\"color:#4285F4;\">%1</span>";
result.append(format.arg(address.toString()));
QString format = R"(<span style="color:%1;">%2</span>)";
result.append(format.arg(kColorTertiary, address.toString()));
hinted = true;
} else {
result.append(address.toString());
@ -1186,7 +1257,7 @@ QString MainWindow::getIPAddresses() const {
}
if (result.isEmpty()) {
result.append(tr("Unknown"));
result.append("Unknown");
}
return result.join(", ");
@ -1196,10 +1267,10 @@ void MainWindow::showLicenseNotice() {
const auto &license = m_LicenseHandler.license();
const bool timeLimited = license.isTimeLimited();
m_labelNotice->setVisible(timeLimited);
m_pLabelNotice->setVisible(timeLimited);
if (timeLimited) {
auto notice = licenseNotice(m_LicenseHandler.license());
this->m_labelNotice->setText(notice);
this->m_pLabelNotice->setText(notice);
}
}
@ -1209,7 +1280,7 @@ void MainWindow::updateLocalFingerprint() {
fingerprintExists = TlsFingerprint::local().fileExists();
} catch (const std::exception &e) {
qDebug() << e.what();
qFatal("Failed to check if fingerprint exists");
qFatal("failed to check if fingerprint exists");
}
if (m_AppConfig.tlsEnabled() && fingerprintExists &&
@ -1244,12 +1315,12 @@ void MainWindow::autoAddScreen(const QString name) {
if (r != kAutoAddScreenOk) {
switch (r) {
case kAutoAddScreenManualServer:
showConfigureServer(tr("Please add the server (%1) to the grid.")
showConfigureServer(QString("Please add the server (%1) to the grid.")
.arg(appConfig().screenName()));
break;
case kAutoAddScreenManualClient:
showConfigureServer(tr("Please drag the new client screen (%1) "
showConfigureServer(QString("Please drag the new client screen (%1) "
"to the desired position on the grid.")
.arg(name));
break;
@ -1316,17 +1387,12 @@ void MainWindow::secureSocket(bool secureSocket) {
}
}
void MainWindow::windowStateChanged() {
if (windowState() == Qt::WindowMinimized && appConfig().minimizeToTray())
hide();
}
void MainWindow::updateScreenName() {
m_pLabelComputerName->setText(
QString("This computer's name: %1 "
R"((<a href="#" style="%2;">change</a>))")
R"((<a href="#" style="color: %2">change</a>))")
.arg(appConfig().screenName())
.arg(kLinkStyleSecondary));
.arg(kColorSecondary));
serverConfig().updateServerName();
}

View file

@ -29,13 +29,13 @@
#include "ui_MainWindowBase.h"
#include "ActivationDialog.h"
#include "AppConfig.h"
#include "ClientConnection.h"
#include "Config.h"
#include "ServerConfig.h"
#include "ServerConnection.h"
#include "TrayIcon.h"
#include "global/Ipc.h"
#include "gui/AppConfig.h"
#include "gui/ConfigScopes.h"
#include "gui/QIpcClient.h"
#include "gui/TlsUtility.h"
#include "gui/VersionChecker.h"
@ -126,6 +126,9 @@ private slots:
void onActionStopCoreTriggered();
void onCoreProcessReadyReadStandardOutput();
void onCoreProcessReadyReadStandardError();
void onWindowSaveTimerTimeout();
// autoconnect slots
void on_m_pButtonApply_clicked();
void on_m_pLabelComputerName_linkActivated(const QString &link);
void on_m_pLabelFingerprint_linkActivated(const QString &link);
@ -141,7 +144,7 @@ private slots:
void on_m_pActivate_triggered();
private:
QSettings &settings() { return *appConfig().config().currentSettings(); }
QSettings &settings() { return *appConfig().scopes().currentSettings(); }
AppConfig &appConfig() { return m_AppConfig; }
AppConfig const &appConfig() const { return m_AppConfig; }
void createMenuBar();
@ -184,6 +187,11 @@ private:
void showConfigureServer() { showConfigureServer(""); }
void showLicenseNotice();
void stopCore();
void restoreWindow();
void saveWindow();
void setupControls();
void resizeEvent(QResizeEvent *event) override;
void moveEvent(QMoveEvent *event) override;
#ifdef Q_OS_MAC
void checkOSXNotification(const QString &line);
@ -207,6 +215,7 @@ private:
bool m_AlreadyHidden = false;
bool m_SecureSocket = false;
QString m_SecureSocketVersion = "";
bool m_SaveWindow = false;
AppConfig &m_AppConfig;
LicenseHandler m_LicenseHandler;
@ -214,4 +223,5 @@ private:
ServerConnection m_ServerConnection;
ClientConnection m_ClientConnection;
synergy::gui::TlsUtility m_TlsUtility;
QTimer m_WindowSaveTimer;
};

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>750</width>
<height>700</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
@ -57,13 +57,6 @@
</item>
<item>
<widget class="QLabel" name="m_pLabelUpdate">
<property name="styleSheet">
<string notr="true">padding: 3px 5px;
border-radius: 3px;
background-color: #3B67D3;
color: #ffffff;
top: 3px;</string>
</property>
<property name="text">
<string notr="true">m_pLabelUpdate</string>
</property>
@ -92,6 +85,9 @@ top: 3px;</string>
</item>
<item>
<widget class="QLabel" name="m_pLabelIpAddresses">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The highlighted IP is the one we think you should use. The server listens on all IPs, so the other IPs may work as well.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">This computer's IP addresses:</string>
</property>
@ -106,21 +102,6 @@ top: 3px;</string>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="spacing">
<number>16</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>15</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QFrame" name="m_pGroupServer">
<property name="sizePolicy">
@ -129,30 +110,31 @@ top: 3px;</string>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);;
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>15</number>
</property>
<item alignment="Qt::AlignTop">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QRadioButton" name="m_pRadioGroupServer">
<property name="styleSheet">
<string notr="true">QRadioButton::indicator{
top: -7px;
}</string>
</property>
<property name="text">
<string>Use this computer's keyboard and mouse
(make this computer the &amp;server)</string>
<string>Use this computer's keyboard and mouse</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>(make this computer the server)</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
</layout>
</item>
<item alignment="Qt::AlignTop">
<widget class="QWidget" name="m_pWidgetServer" native="true">
<layout class="QVBoxLayout" name="m_pLayoutServer">
@ -293,33 +275,31 @@ background-color: rgba(192,192,192, 0.1);
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>15</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<item alignment="Qt::AlignTop">
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QRadioButton" name="m_pRadioGroupClient">
<property name="styleSheet">
<string notr="true">QRadioButton::indicator{
top: -7px;
}</string>
</property>
<property name="text">
<string>Use another computer’s mouse and keyboard
(make this computer the &amp;client)</string>
<string>Use another computer’s mouse and keyboard</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>(make this computer the client)</string>
</property>
<property name="indent">
<number>20</number>
</property>
</widget>
</item>
</layout>
</item>
<item alignment="Qt::AlignTop">
<widget class="QWidget" name="m_pWidgetClient" native="true">
<layout class="QVBoxLayout" name="m_pLayoutClient">
@ -409,9 +389,6 @@ background-color: rgba(192,192,192, 0.1);
</item>
<item>
<widget class="QLabel" name="m_pLabelLogs">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Logs</string>
</property>
@ -441,13 +418,6 @@ background-color: rgba(192,192,192, 0.1);
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);;
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -481,9 +451,6 @@ background-color: rgba(192,192,192, 0.1);
<kerning>true</kerning>
</font>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
@ -546,19 +513,12 @@ background-color: rgba(192,192,192, 0.1);
</spacer>
</item>
<item>
<widget class="QLabel" name="m_labelNotice">
<widget class="QLabel" name="m_pLabelNotice">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">padding: 3px 5px;
border-radius: 3px;
background-color: #3B67D3;
color: #ffffff;
top: 3px;</string>
</property>
<property name="text">
<string notr="true">m_labelNotice</string>
<string notr="true">m_pLabelNotice</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@ -736,6 +696,18 @@ top: 3px;</string>
<header>widgets/ClientStateLabel.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_pRadioGroupServer</tabstop>
<tabstop>m_pRadioGroupClient</tabstop>
<tabstop>m_pLineEditClientIp</tabstop>
<tabstop>m_pButtonConnectToClient</tabstop>
<tabstop>m_pButtonConfigureServer</tabstop>
<tabstop>m_pLineEditHostname</tabstop>
<tabstop>m_pButtonConnect</tabstop>
<tabstop>m_pLogOutput</tabstop>
<tabstop>m_pButtonApply</tabstop>
<tabstop>m_pButtonToggleStart</tabstop>
</tabstops>
<resources>
<include location="../res/Synergy.qrc"/>
</resources>

View file

@ -26,12 +26,6 @@
QSynergyApplication::QSynergyApplication(int &argc, char **argv)
: QApplication(argc, argv) {
QFontDatabase::addApplicationFont(":/res/fonts/Arial.ttf");
QFont Arial("Arial");
Arial.setPixelSize(13);
Arial.setStyleHint(QFont::SansSerif);
setFont(Arial);
// Setting the style to 'Fusion' seems to fix issues such as text being
// rendered as black on black. This may not be the style we want long-term
// but it does fix the style issues for now.

View file

@ -18,8 +18,10 @@
#include "ScreenSettingsDialog.h"
#include "Screen.h"
#include "gui/constants.h"
#include "validators/AliasValidator.h"
#include "validators/ScreenNameValidator.h"
#include "validators/ValidationError.h"
#include <QMessageBox>
#include <QtCore>
@ -30,15 +32,21 @@ ScreenSettingsDialog::ScreenSettingsDialog(
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::ScreenSettingsDialogBase(),
m_pScreen(pScreen) {
setupUi(this);
m_pLabelAliasError->setStyleSheet(kStyleErrorActiveLabel);
m_pLabelNameError->setStyleSheet(kStyleErrorActiveLabel);
m_pLineEditName->setText(m_pScreen->name());
m_pLineEditName->setValidator(new validators::ScreenNameValidator(
m_pLineEditName, m_pLabelNameError, pScreens));
m_pLineEditName, new validators::ValidationError(this, m_pLabelNameError),
pScreens));
m_pLineEditName->selectAll();
m_pLineEditAlias->setValidator(
new validators::AliasValidator(m_pLineEditAlias, m_pLabelAliasError));
m_pLineEditAlias->setValidator(new validators::AliasValidator(
m_pLineEditAlias,
new validators::ValidationError(this, m_pLabelAliasError)));
for (int i = 0; i < m_pScreen->aliases().count(); i++)
new QListWidgetItem(m_pScreen->aliases()[i], m_pListAliases);

View file

@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2012 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
*
* This package is free software; you can redistribute it and/or
@ -16,10 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(SCREENSETTINGSDIALOG__H)
#define SCREENSETTINGSDIALOG__H
#include <memory>
#pragma once
#include <QDialog>
@ -52,5 +49,3 @@ private slots:
private:
Screen *m_pScreen;
};
#endif

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>675</height>
<width>440</width>
<height>739</height>
</rect>
</property>
<property name="sizePolicy">
@ -43,13 +43,6 @@
</property>
<item>
<widget class="QFrame" name="groupBox">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -106,14 +99,8 @@ background-color: rgba(192,192,192, 0.1);
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: #EC4C47;
font-size: 13px;
font-family: Arial;
font-weight: bold;</string>
</property>
<property name="text">
<string/>
<string>m_pLabelNameError</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@ -154,13 +141,6 @@ font-weight: bold;</string>
</item>
<item>
<widget class="QFrame" name="m_pGroupModifiers">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -477,13 +457,6 @@ background-color: rgba(192,192,192, 0.1);
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -648,13 +621,6 @@ background-color: rgba(192,192,192, 0.1);
</item>
<item>
<widget class="QFrame" name="m_pGroupFixes">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -760,19 +726,6 @@ background-color: rgba(192,192,192, 0.1);
</item>
<item>
<widget class="QFrame" name="m_pGroupAliases">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -809,26 +762,6 @@ background-color: rgba(192,192,192, 0.1);
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>43</width>
<height>20</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#m_pButtonAddAlias{
left: 30px;
}</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
@ -848,9 +781,6 @@ left: 30px;
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="maxLength">
<number>255</number>
</property>
@ -876,14 +806,8 @@ left: 30px;
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: #EC4C47;
font-size: 13px;
font-family: Arial;
font-weight: bold;</string>
</property>
<property name="text">
<string/>
<string>m_pLabelNameError</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -933,9 +857,6 @@ font-weight: bold;</string>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
@ -946,12 +867,6 @@ font-weight: bold;</string>
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&amp;Remove</string>
</property>

View file

@ -35,14 +35,14 @@ ScreenSetupModel::ScreenSetupModel(
// this is unlikely to happen, as the grid size is only 3x9.
if (m_NumColumns > 100 || m_NumRows > 100) {
qFatal(
"Grid size out of bounds: %d columns x %d rows", m_NumColumns,
"grid size out of bounds: %d columns x %d rows", m_NumColumns,
m_NumRows);
return;
}
if (m_NumColumns * m_NumRows > screens.size()) {
qFatal(
"Scrren list (%lld) too small for %d columns x %d rows", screens.size(),
"scrren list (%lld) too small for %d columns x %d rows", screens.size(),
m_NumColumns, m_NumRows);
}
}

View file

@ -91,8 +91,9 @@ void ScreenSetupView::dragMoveEvent(QDragMoveEvent *event) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
int col = columnAt(event->pos().x());
int row = rowAt(event->pos().y());
const auto &point = event->position().toPoint();
int col = columnAt(point.x());
int row = rowAt(point.y());
// a drop from outside is not allowed if there's a screen already there.
if (!model()->screen(col, row).isNull())

View file

@ -19,9 +19,9 @@
#include "ServerConfig.h"
#include "AddClientDialog.h"
#include "Config.h"
#include "Hotkey.h"
#include "MainWindow.h"
#include "gui/ConfigScopes.h"
#include "gui/constants.h"
#include <QAbstractButton>
@ -51,7 +51,7 @@ ServerConfig::ServerConfig(
m_NumColumns(numColumns),
m_NumRows(numRows),
m_ClipboardSharingSize(defaultClipboardSharingSize()) {
appConfig->config().registerReceiever(this);
appConfig->scopes().registerReceiver(this);
}
ServerConfig::~ServerConfig() {
@ -553,5 +553,5 @@ QString ServerConfig::getClientAddress() const {
}
QSettings &ServerConfig::settings() {
return *m_pAppConfig->config().currentSettings();
return *m_pAppConfig->scopes().currentSettings();
}

View file

@ -18,12 +18,12 @@
#pragma once
#include <QList>
#include "CommonConfig.h"
#include "Hotkey.h"
#include "ScreenConfig.h"
#include "ScreenList.h"
#include "gui/CommonConfig.h"
#include <QList>
class QTextStream;
class QSettings;

View file

@ -17,13 +17,11 @@
*/
#include "ServerConfigDialog.h"
#include "ActionDialog.h"
#include "HotkeyDialog.h"
#include "ScreenSettingsDialog.h"
#include "ServerConfig.h"
#include "UpgradeDialog.h"
#include "gui/constants.h"
#include "license/ProductEdition.h"
#include <QFileDialog>
#include <QMessageBox>
@ -43,8 +41,13 @@ ServerConfigDialog::ServerConfigDialog(
serverConfig().numRows()),
m_Message(""),
m_appConfig(appConfig) {
setupUi(this);
// force the first tab, since qt creator sets the active tab as the last one
// the developer was looking at, and it's easy to accidentally save that.
m_pTabWidget->setCurrentIndex(0);
m_pEditConfigFile->setText(serverConfig().configFile());
m_pCheckBoxUseExternalConfig->setChecked(serverConfig().useExternalConfig());
m_pCheckBoxHeartbeat->setChecked(serverConfig().hasHeartbeat());

View file

@ -20,10 +20,9 @@
#define SERVERCONFIGDIALOG__H
#include "AppConfig.h"
#include "ScreenSetupModel.h"
#include "ServerConfig.h"
#include "gui/AppConfig.h"
#include "ui_ServerConfigDialogBase.h"
#include <QDialog>

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>799</width>
<height>508</height>
<width>814</width>
<height>588</height>
</rect>
</property>
<property name="minimumSize">
@ -29,7 +29,7 @@
</size>
</property>
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="m_pTabScreens">
<attribute name="title">
@ -359,12 +359,6 @@
<kerning>true</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title{
left: -5px;
top: -2px;
}</string>
</property>
<property name="title">
<string>&amp;Switch computer</string>
</property>
@ -510,12 +504,6 @@
<kerning>true</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title{
left: -2px;
top: -2px;
}</string>
</property>
<property name="title">
<string>Clipboard sharing</string>
</property>
@ -617,12 +605,6 @@
<kerning>true</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title{
left: -5px;
top: -2px;
}</string>
</property>
<property name="title">
<string>&amp;Dead corners for this computer</string>
</property>
@ -707,12 +689,6 @@
<kerning>false</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title{
left: -5px;
top: -2px;
}</string>
</property>
<property name="title">
<string>&amp;Options</string>
</property>
@ -738,9 +714,6 @@
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">padding-left: 2px;</string>
</property>
<property name="text">
<string>Use &amp;relative mouse moves</string>
</property>
@ -759,9 +732,6 @@
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">left: -2px;</string>
</property>
<property name="text">
<string>&amp;Check clients every</string>
</property>
@ -816,9 +786,6 @@
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="m_pCheckBoxIgnoreAutoConfigClient">
<property name="styleSheet">
<string notr="true">padding-left: 2px;</string>
</property>
<property name="text">
<string>Ignore auto config clients</string>
</property>
@ -826,9 +793,6 @@
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="m_pCheckBoxDisableLockToScreen">
<property name="styleSheet">
<string notr="true">padding-left: 2px;</string>
</property>
<property name="text">
<string>Disable lock to screen</string>
</property>
@ -839,9 +803,6 @@
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">padding-left: 2px;</string>
</property>
<property name="text">
<string>Don't take &amp;foreground window on Windows servers</string>
</property>
@ -1110,9 +1071,6 @@
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">margin: 0px; padding: 0px;</string>
</property>
<property name="text">
<string/>
</property>
@ -1193,6 +1151,39 @@
<header>TrashScreenWidget.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_pButtonBrowseConfigFile</tabstop>
<tabstop>m_pButtonAddComputer</tabstop>
<tabstop>m_pScreenSetupView</tabstop>
<tabstop>m_pListHotkeys</tabstop>
<tabstop>m_pButtonNewHotkey</tabstop>
<tabstop>m_pButtonEditHotkey</tabstop>
<tabstop>m_pButtonRemoveHotkey</tabstop>
<tabstop>m_pListActions</tabstop>
<tabstop>m_pButtonNewAction</tabstop>
<tabstop>m_pButtonEditAction</tabstop>
<tabstop>m_pButtonRemoveAction</tabstop>
<tabstop>m_pCheckBoxSwitchDelay</tabstop>
<tabstop>m_pSpinBoxSwitchDelay</tabstop>
<tabstop>m_pCheckBoxSwitchDoubleTap</tabstop>
<tabstop>m_pSpinBoxSwitchDoubleTap</tabstop>
<tabstop>m_pCheckBoxEnableClipboard</tabstop>
<tabstop>m_pSpinBoxClipboardSizeLimit</tabstop>
<tabstop>m_pCheckBoxHeartbeat</tabstop>
<tabstop>m_pSpinBoxHeartbeat</tabstop>
<tabstop>m_pCheckBoxRelativeMouseMoves</tabstop>
<tabstop>m_pCheckBoxWin32KeepForeground</tabstop>
<tabstop>m_pCheckBoxIgnoreAutoConfigClient</tabstop>
<tabstop>m_pCheckBoxDisableLockToScreen</tabstop>
<tabstop>m_pCheckBoxCornerTopLeft</tabstop>
<tabstop>m_pCheckBoxCornerBottomLeft</tabstop>
<tabstop>m_pCheckBoxCornerTopRight</tabstop>
<tabstop>m_pCheckBoxCornerBottomRight</tabstop>
<tabstop>m_pSpinBoxSwitchCornerSize</tabstop>
<tabstop>m_pCheckBoxUseExternalConfig</tabstop>
<tabstop>m_pEditConfigFile</tabstop>
<tabstop>m_pTabWidget</tabstop>
</tabstops>
<resources>
<include location="../res/Synergy.qrc"/>
</resources>

View file

@ -18,10 +18,10 @@
#include "ServerConnection.h"
#include "AppConfig.h"
#include "MainWindow.h"
#include "ServerConfigDialog.h"
#include "ServerMessage.h"
#include "gui/AppConfig.h"
#include <QMessageBox>

View file

@ -18,18 +18,19 @@
#include "SettingsDialog.h"
#include "AppConfig.h"
#include "MainWindow.h"
#include "UpgradeDialog.h"
#include "gui/AppConfig.h"
#include "gui/TlsCertificate.h"
#include "gui/constants.h"
#include "validators/ScreenNameValidator.h"
#include "validators/ValidationError.h"
#include <QDir>
#include <QFileDialog>
#include <QMessageBox>
#include <QtCore>
#include <QtGui>
#include <memory>
using namespace synergy::license;
@ -45,6 +46,10 @@ SettingsDialog::SettingsDialog(
setupUi(this);
// force the first tab, since qt creator sets the active tab as the last one
// the developer was looking at, and it's easy to accidentally save that.
m_pTabWidget->setCurrentIndex(0);
m_pMainWindow = dynamic_cast<MainWindow *>(parent);
loadFromConfig();
@ -52,45 +57,16 @@ SettingsDialog::SettingsDialog(
updateControlsEnabled();
const auto &serveConfig = m_pMainWindow->serverConfig();
m_screenNameValidator = std::make_unique<validators::ScreenNameValidator>(
m_pLineEditScreenName, nullptr, (&serveConfig.screens()));
connect(
m_screenNameValidator.get(), SIGNAL(finished(QString)), this,
SLOT(on_m_pScreenNameValidator_finished(QString)));
m_pLineEditScreenName->setValidator(m_screenNameValidator.get());
connect(
m_pLineEditLogFilename, SIGNAL(textChanged(QString)), this,
SLOT(onChange()));
connect(
m_pComboLogLevel, SIGNAL(currentIndexChanged(int)), this,
SLOT(onChange()));
connect(
m_pLineEditCertificatePath, SIGNAL(textChanged(QString)), this,
SLOT(onChange()));
connect(m_pCheckBoxMinimizeToTray, SIGNAL(clicked()), this, SLOT(onChange()));
connect(m_pCheckBoxAutoHide, SIGNAL(clicked()), this, SLOT(onChange()));
connect(m_pCheckBoxPreventSleep, SIGNAL(clicked()), this, SLOT(onChange()));
connect(
m_pLineEditInterface, SIGNAL(textEdited(QString)), this,
SLOT(onChange()));
connect(m_pSpinBoxPort, SIGNAL(valueChanged(int)), this, SLOT(onChange()));
connect(
m_pLineEditScreenName, SIGNAL(textEdited(QString)), this,
SLOT(onChange()));
connect(
m_pComboElevate, SIGNAL(currentIndexChanged(int)), this,
SLOT(onChange()));
connect(m_pCheckBoxLanguageSync, SIGNAL(clicked()), this, SLOT(onChange()));
connect(
m_pCheckBoxScrollDirection, SIGNAL(clicked()), this, SLOT(onChange()));
adjustSize();
m_pScreenNameError = new validators::ValidationError(this);
m_pLineEditScreenName->setValidator(new validators::ScreenNameValidator(
m_pLineEditScreenName, m_pScreenNameError, &serveConfig.screens()));
}
void SettingsDialog::accept() {
if (!m_nameError.isEmpty()) {
QMessageBox::warning(this, tr("Invalid screen name"), m_nameError);
if (!m_pLineEditScreenName->hasAcceptableInput()) {
QMessageBox::warning(
this, tr("Invalid screen name"), m_pScreenNameError->message());
return;
}
@ -105,7 +81,6 @@ void SettingsDialog::accept() {
static_cast<ElevateMode>(m_pComboElevate->currentIndex()));
appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked());
appConfig().setPreventSleep(m_pCheckBoxPreventSleep->isChecked());
appConfig().setMinimizeToTray(m_pCheckBoxMinimizeToTray->isChecked());
appConfig().setTlsCertPath(m_pLineEditCertificatePath->text());
appConfig().setTlsKeyLength(m_pComboBoxKeyLength->currentText());
appConfig().setTlsEnabled(m_pCheckBoxEnableCrypto->isChecked());
@ -138,7 +113,6 @@ void SettingsDialog::loadFromConfig() {
m_pLineEditLogFilename->setText(appConfig().logFilename());
m_pCheckBoxAutoHide->setChecked(appConfig().autoHide());
m_pCheckBoxPreventSleep->setChecked(appConfig().preventSleep());
m_pCheckBoxMinimizeToTray->setChecked(appConfig().minimizeToTray());
m_pLineEditCertificatePath->setText(appConfig().tlsCertPath());
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.tlsEnabled());
m_pCheckBoxLanguageSync->setChecked(m_appConfig.languageSync());
@ -179,7 +153,7 @@ void SettingsDialog::updateTlsControlsEnabled() {
auto enabled = !clientMode && tlsAvailable && tlsChecked;
qDebug(
"TLS controls enabled=%d, client=%d, available=%d, checked=%d", enabled,
"tls enabled=%d, client=%d, available=%d, checked=%d", enabled,
clientMode, tlsAvailable, tlsChecked);
m_pLabelKeyLength->setEnabled(enabled);
@ -290,7 +264,6 @@ void SettingsDialog::updateControlsEnabled() {
m_pComboElevate->setEnabled(writable);
m_pCheckBoxAutoHide->setEnabled(writable);
m_pCheckBoxPreventSleep->setEnabled(writable);
m_pCheckBoxMinimizeToTray->setEnabled(writable);
m_pLineEditCertificatePath->setEnabled(writable);
m_pComboBoxKeyLength->setEnabled(writable);
m_pPushButtonBrowseCert->setEnabled(writable);
@ -326,7 +299,3 @@ void SettingsDialog::updateControlsEnabled() {
updateTlsControls();
}
void SettingsDialog::on_m_pScreenNameValidator_finished(const QString &error) {
m_nameError = error;
}

View file

@ -18,15 +18,14 @@
#pragma once
#include "gui/TlsUtility.h"
#include "ui_SettingsDialogBase.h"
#include "gui/CoreInterface.h"
#include "gui/TlsUtility.h"
#include "license/License.h"
#include "validators/ScreenNameValidator.h"
#include "validators/ValidationError.h"
#include <QDialog>
#include <memory>
class MainWindow;
class AppConfig;
@ -67,13 +66,12 @@ protected:
void updateTlsControlsEnabled();
private:
QString m_nameError = "";
MainWindow *m_pMainWindow;
AppConfig &m_appConfig;
CoreInterface m_coreInterface;
const synergy::license::License &m_license;
synergy::gui::TlsUtility m_tlsUtility;
std::unique_ptr<validators::ScreenNameValidator> m_screenNameValidator;
validators::ValidationError *m_pScreenNameError;
/// @brief Stores settings scope at start of settings dialog
/// This is neccessary to restore state if user changes
@ -84,23 +82,8 @@ private slots:
void on_m_pCheckBoxEnableCrypto_clicked(bool checked);
void on_m_pCheckBoxLogToFile_stateChanged(int);
void on_m_pButtonBrowseLog_clicked();
/// @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);
/// @brief Handles the click event of the Cert Path browse button
/// displaying a file browser
void on_m_pPushButtonBrowseCert_clicked();
/// @brief Handles the TLS cert key length changed event
void on_m_pComboBoxKeyLength_currentIndexChanged(int index);
/// @brief handels the regenerate cert button event
/// This will regenerate the TLS certificate as long as the settings
/// haven't changed
void on_m_pPushButtonRegenCert_clicked();
void on_m_pScreenNameValidator_finished(const QString &error);
};

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>830</height>
<width>550</width>
<height>582</height>
</rect>
</property>
<property name="sizePolicy">
@ -16,51 +16,38 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>620</height>
</size>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>11</number>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="spacing">
<number>15</number>
</property>
<property name="topMargin">
<number>11</number>
<item alignment="Qt::AlignTop">
<widget class="QTabWidget" name="m_pTabWidget">
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="verticalSpacing">
<number>5</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="m_pGroupBoxCommon">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}
</string>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="m_pTabRegular">
<attribute name="title">
<string>&amp;Regular</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>15</number>
</property>
<property name="topMargin">
<number>17</number>
<number>15</number>
</property>
<property name="bottomMargin">
<number>17</number>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupBasics">
<property name="title">
<string>Basics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -78,20 +65,17 @@ background-color: rgba(192,192,192, 0.1);
</size>
</property>
<property name="text">
<string>Computer &amp;name</string>
</property>
<property name="buddy">
<cstring>m_pLineEditScreenName</cstring>
<string>Computer name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Maximum</enum>
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -114,414 +98,56 @@ background-color: rgba(192,192,192, 0.1);
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_pLabel_20">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>P&amp;ort</string>
</property>
<property name="buddy">
<cstring>m_pSpinBoxPort</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="m_pSpinBoxPort">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>24800</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabel_21">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Network IP</string>
</property>
<property name="buddy">
<cstring>m_pLineEditInterface</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="m_pLineEditInterface">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="m_pCheckBoxCloseToTray">
<property name="text">
<string>Minimize to tray on close</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="m_pCheckBoxMinimizeToTray">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LayoutDirection::LeftToRight</enum>
</property>
<property name="text">
<string>Minimize to system &amp;tray</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="m_pCheckBoxAutoHide">
<property name="text">
<string>Hide window on start</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>3</height>
</size>
</property>
</spacer>
</item>
<item row="12" column="0">
<widget class="QLabel" name="m_pLabelGroupAdvanced">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item row="11" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>3</height>
</size>
</property>
</spacer>
</item>
<item row="15" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="m_pLabelGroupLog">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Logs</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QFrame" name="m_pGroupAdvanced">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}
</string>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QCheckBox" name="m_pCheckBoxPreventSleep">
<property name="text">
<string>Stop this computer from sleeping</string>
<string>Prevent this computer from going to sleep</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="m_pCheckBoxScrollDirection">
<property name="text">
<string>Invert scroll direction on this computer (client mode)</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="m_pInvertConnection">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Invert server/client TCP connection (business edition)</string>
</property>
</widget>
</item>
<item row="8" column="0">
<item>
<widget class="QCheckBox" name="m_pCheckBoxLanguageSync">
<property name="text">
<string>Use server's keyboard language on this computer (client mode)</string>
</property>
</widget>
</item>
<item row="4" column="0" rowspan="3" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="m_pLabelElevate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QCheckBox" name="m_pCheckBoxScrollDirection">
<property name="text">
<string>Elevate privileges (service required)</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="m_pComboElevate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Specify when the Synergy service should run at an elevated privilege level</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>As Needed</string>
</property>
</item>
<item>
<property name="text">
<string>Always</string>
</property>
</item>
<item>
<property name="text">
<string>Never</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="m_pCheckBoxServiceEnabled">
<property name="text">
<string>Use background service (daemon)</string>
<string>Invert scroll direction on this computer (client mode)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="m_pLabelGroupScope">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupApp">
<property name="title">
<string>App</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="m_pCheckBoxCloseToTray">
<property name="text">
<string>Use settings profile from</string>
<string>Leave app running in notification area when the window is closed</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>3</height>
</size>
</property>
</spacer>
</item>
<item row="10" column="0">
<widget class="QFrame" name="m_pGroupScope">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}
</string>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>15</number>
</property>
<property name="bottomMargin">
<number>15</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="1">
<widget class="QRadioButton" name="m_pRadioSystemScope">
<item>
<widget class="QCheckBox" name="m_pCheckBoxAutoHide">
<property name="text">
<string>All users</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="m_pRadioUserScope">
<property name="text">
<string>Current user</string>
<string>Hide the window when the app starts</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QFrame" name="m_pGroupSecurity">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}
</string>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupSecurity">
<property name="title">
<string>Security</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
@ -551,7 +177,7 @@ background-color: rgba(192,192,192, 0.1);
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -619,10 +245,10 @@ background-color: rgba(192,192,192, 0.1);
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Minimum</enum>
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -647,9 +273,6 @@ background-color: rgba(192,192,192, 0.1);
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">margin: 0px; padding: 0px;</string>
</property>
<property name="text">
<string/>
</property>
@ -678,7 +301,7 @@ background-color: rgba(192,192,192, 0.1);
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -700,31 +323,114 @@ background-color: rgba(192,192,192, 0.1);
</layout>
</widget>
</item>
<item row="19" column="0">
<widget class="QDialogButtonBox" name="m_pButtonBox">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="m_pTabAdvanced">
<attribute name="title">
<string>&amp;Advanced</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>15</number>
</property>
<property name="topMargin">
<number>15</number>
</property>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupNetworking">
<property name="title">
<string>Networking</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_pLabel_20">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QFrame" name="m_pGroupLog1">
<property name="styleSheet">
<string notr="true">.QFrame{
border: 1px solid rgba(192,192,192, 0.2);
border-radius: 4px;
background-color: rgba(192,192,192, 0.1);
}
</string>
<item>
<widget class="QSpinBox" name="m_pSpinBoxPort">
<property name="enabled">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>24800</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabel_21">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Network IP</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="m_pLineEditInterface">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="m_pInvertConnection">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Invert server/client TCP connection (business edition)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupLogs">
<property name="title">
<string>Logs</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="topMargin">
@ -739,7 +445,7 @@ background-color: rgba(192,192,192, 0.1);
<item row="0" column="1">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -797,9 +503,6 @@ background-color: rgba(192,192,192, 0.1);
<property name="text">
<string>Level</string>
</property>
<property name="buddy">
<cstring>m_pComboLogLevel</cstring>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
@ -826,10 +529,10 @@ background-color: rgba(192,192,192, 0.1);
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Minimum</enum>
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -860,9 +563,6 @@ background-color: rgba(192,192,192, 0.1);
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">margin: 0px; padding: 0px;</string>
</property>
<property name="text">
<string/>
</property>
@ -886,8 +586,22 @@ background-color: rgba(192,192,192, 0.1);
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="m_pLabelGroupNetwork">
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupService">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Service</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="m_pLabelElevate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -895,35 +609,137 @@ background-color: rgba(192,192,192, 0.1);
</sizepolicy>
</property>
<property name="text">
<string>Security</string>
<string>Launch with elevated privilages</string>
</property>
</widget>
</item>
<item row="8" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
<item>
<widget class="QComboBox" name="m_pComboElevate">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Specify when the Synergy service should run at an elevated privilege level</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>Automatic (as needed)</string>
</property>
</item>
<item>
<property name="text">
<string>Always elevate</string>
</property>
</item>
<item>
<property name="text">
<string>Never elevate</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="m_pCheckBoxServiceEnabled">
<property name="text">
<string>Use background service (daemon)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="m_pGroupScope">
<property name="title">
<string>Use settings profile from</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>5</number>
</property>
<item row="0" column="1">
<widget class="QRadioButton" name="m_pRadioSystemScope">
<property name="text">
<string>All users</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="m_pRadioUserScope">
<property name="text">
<string>Current user</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>3</height>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="m_pButtonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_pLineEditScreenName</tabstop>
<tabstop>m_pSpinBoxPort</tabstop>
<tabstop>m_pLineEditInterface</tabstop>
<tabstop>m_pCheckBoxCloseToTray</tabstop>
<tabstop>m_pCheckBoxMinimizeToTray</tabstop>
<tabstop>m_pCheckBoxAutoHide</tabstop>
<tabstop>m_pCheckBoxEnableCrypto</tabstop>
<tabstop>m_pComboBoxKeyLength</tabstop>
<tabstop>m_pLineEditCertificatePath</tabstop>
@ -935,8 +751,6 @@ background-color: rgba(192,192,192, 0.1);
<tabstop>m_pButtonBrowseLog</tabstop>
<tabstop>m_pRadioUserScope</tabstop>
<tabstop>m_pRadioSystemScope</tabstop>
<tabstop>m_pCheckBoxPreventSleep</tabstop>
<tabstop>m_pCheckBoxServiceEnabled</tabstop>
<tabstop>m_pComboElevate</tabstop>
</tabstops>
<resources>

View file

@ -16,35 +16,41 @@
*/
#include "SetupWizard.h"
#include "MainWindow.h"
#include "validators/ScreenNameValidator.h"
SetupWizard::SetupWizard(MainWindow &mainWindow) : m_MainWindow(mainWindow) {
#include "MainWindow.h"
#include "gui/constants.h"
#include "validators/ScreenNameValidator.h"
#include "validators/ValidationError.h"
SetupWizard::SetupWizard(MainWindow &mainWindow) : m_mainWindow(mainWindow) {
setupUi(this);
m_pLineEditName->setText(m_MainWindow.appConfig().screenName());
m_pLineEditName->setValidator(
new validators::ScreenNameValidator(m_pLineEditName, label_ErrorMessage));
m_pLabelError->setStyleSheet(kStyleErrorActiveLabel);
connect(m_pButtonApply, SIGNAL(clicked()), this, SLOT(accept()));
m_pLineEditName->setText(m_mainWindow.appConfig().screenName());
m_pLineEditName->setValidator(new validators::ScreenNameValidator(
m_pLineEditName, new validators::ValidationError(this, m_pLabelError)));
connect(m_pButtonApply, &QPushButton::clicked, this, &SetupWizard::accept);
connect(
m_pLineEditName, SIGNAL(textEdited(QString)), this,
SLOT(onNameChanged()));
m_pLineEditName, &QLineEdit::textChanged, this,
&SetupWizard::onLineEditNameChanged);
}
void SetupWizard::accept() {
AppConfig &appConfig = m_MainWindow.appConfig();
AppConfig &appConfig = m_mainWindow.appConfig();
appConfig.setWizardHasRun();
appConfig.setScreenName(m_pLineEditName->text());
appConfig.saveSettings();
m_MainWindow.open();
m_mainWindow.open();
QDialog::accept();
}
void SetupWizard::onNameChanged() {
m_pButtonApply->setEnabled(label_ErrorMessage->text().isEmpty());
void SetupWizard::onLineEditNameChanged(const QString &error) {
m_pButtonApply->setEnabled(m_pLineEditName->hasAcceptableInput());
}
void SetupWizard::reject() {

View file

@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2012 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -16,9 +16,11 @@
*/
#pragma once
#include "ui_SetupWizardBase.h"
#include <QDialog>
#include <memory>
#include <QObject>
class MainWindow;
@ -33,8 +35,8 @@ protected:
void reject();
private:
MainWindow &m_MainWindow;
MainWindow &m_mainWindow;
private slots:
void onNameChanged();
public slots:
void onLineEditNameChanged(const QString &error);
};

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>720</width>
<height>552</height>
<width>772</width>
<height>634</height>
</rect>
</property>
<property name="sizePolicy">
@ -16,18 +16,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>720</width>
<height>552</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>720</width>
<height>552</height>
</size>
</property>
<property name="baseSize">
<size>
<width>720</width>
@ -43,77 +31,76 @@
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<widget class="QLabel" name="label_Image">
<property name="geometry">
<rect>
<x>270</x>
<y>70</y>
<width>181</width>
<height>161</height>
</rect>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>20</number>
</property>
<property name="leftMargin">
<number>100</number>
</property>
<property name="rightMargin">
<number>100</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pLabelImage">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../res/Synergy.qrc">:/res/image/welcome.png</pixmap>
</property>
</widget>
<widget class="QLabel" name="label_Title">
<property name="geometry">
<rect>
<x>270</x>
<y>253</y>
<width>261</width>
<height>21</height>
</rect>
<property name="margin">
<number>30</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pLabelTitle">
<property name="font">
<font>
<family>Arial</family>
<weight>75</weight>
<family>Cantarell</family>
<pointsize>18</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style=&quot;font-size:18px&quot;&gt;Name your computer&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Name your computer</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<enum>Qt::PlainText</enum>
</property>
</widget>
<widget class="QLabel" name="label_Name">
<property name="geometry">
<rect>
<x>184</x>
<y>294</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_pLabelName">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style=&quot;font-size:13px;&quot;&gt;Computer name&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Computer name</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<enum>Qt::PlainText</enum>
</property>
<property name="margin">
<number>2</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_pLineEditName">
<property name="geometry">
<rect>
<x>300</x>
<y>293</y>
<width>230</width>
<height>20</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>230</width>
@ -124,92 +111,71 @@
<number>255</number>
</property>
</widget>
<widget class="QLabel" name="label_HelpTitle">
<property name="geometry">
<rect>
<x>132</x>
<y>354</y>
<width>481</width>
<height>16</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</item>
<item row="1" column="1">
<widget class="QLabel" name="m_pLabelError">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style=&quot;font-size: 13px;&quot;&gt;Call your computer something short and meaningful, but it must have: &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<string>m_pLabelError</string>
</property>
</widget>
<widget class="QLabel" name="label_HelpInfo">
<property name="geometry">
<rect>
<x>193</x>
<y>380</y>
<width>311</width>
<height>91</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</item>
</layout>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pHelpList">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;ul style=&quot;list-style-type:none; font-size: 13px;&quot;&gt;&lt;li style=&quot;line-height:140%&quot;&gt;- A different name from other computers &lt;/li&gt;&lt;li style=&quot;line-height:140%&quot;&gt;- Only these special characters _ - .&lt;/li&gt;&lt;li style=&quot;line-height:140%&quot;&gt;- No spaces &lt;/li&gt;&lt;li style=&quot;line-height:140%&quot;&gt;- Only english characters and numbers&lt;/li&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Call your computer something short and meaningful, but it must have:
- No spaces
- Only these special characters: _ - .
- Only English characters and numbers
- A different name from other computers
</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
<enum>Qt::MarkdownText</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="m_pButtonApply">
<property name="geometry">
<rect>
<x>650</x>
<y>510</y>
<width>56</width>
<height>25</height>
</rect>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Arial</family>
<weight>50</weight>
<bold>false</bold>
</font>
<property name="minimumSize">
<size>
<width>150</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
<widget class="QLabel" name="label_ErrorMessage">
<property name="geometry">
<rect>
<x>300</x>
<y>320</y>
<width>391</width>
<height>16</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: #EC4C47;
font-size: 13px;
font-family: Arial;
font-weight: bold;</string>
</property>
<property name="text">
<string/>
<string>Continue</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../res/Synergy.qrc"/>

View file

@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -15,18 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SetupWizardBlocker.h"
#include "MainWindow.h"
#include <QDesktopServices>
#include <QUrl>
#include "MainWindow.h"
#include "SetupWizardBlocker.h"
static const std::vector<const char *> blockerTitels = {
"No Wayland support",
"Wayland is not yet supported",
};
static const std::vector<const char *> blockerText = {
"We have detected your system is using Wayland. It is not currently \n"
"We have detected your system is using Wayland which is not currently \n"
"supported, but we are working on it. It's top of our priority list. \n"
"\n"
"Please switch to Xorg if you wish to continue using Synergy today.",
@ -37,9 +38,8 @@ SetupWizardBlocker::SetupWizardBlocker(
: m_MainWindow(mainWindow) {
setupUi(this);
label_Title->setText(blockerTitels[static_cast<int>(type)]);
label_HelpInfo->setText(blockerText[static_cast<int>(type)]);
m_pLabelTitle->setText(blockerTitels[static_cast<int>(type)]);
m_pLabelInfo->setText(blockerText[static_cast<int>(type)]);
connect(
m_pButtonSupport, &QPushButton::released, this,

View file

@ -6,39 +6,10 @@
<rect>
<x>0</x>
<y>0</y>
<width>720</width>
<height>580</height>
<width>750</width>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>720</width>
<height>580</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>720</width>
<height>580</height>
</size>
</property>
<property name="baseSize">
<size>
<width>720</width>
<height>580</height>
</size>
</property>
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
@ -48,14 +19,33 @@
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<widget class="QLabel" name="label_Image">
<property name="geometry">
<rect>
<x>278</x>
<y>87</y>
<width>165</width>
<height>165</height>
</rect>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>20</number>
</property>
<property name="bottomMargin">
<number>40</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pLabelImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
@ -66,109 +56,71 @@
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="label_Title">
<property name="geometry">
<rect>
<x>0</x>
<y>273</y>
<width>720</width>
<height>25</height>
</rect>
<property name="margin">
<number>30</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pLabelTitle">
<property name="font">
<font>
<family>Arial</family>
<pointsize>18</pointsize>
<weight>50</weight>
<bold>false</bold>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">Test header</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
<string notr="true">m_pLabelTitle</string>
</property>
</widget>
<widget class="QLabel" name="label_HelpInfo">
<property name="geometry">
<rect>
<x>153</x>
<y>321</y>
<width>455</width>
<height>150</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>13</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="m_pLabelInfo">
<property name="text">
<string>large text test large text test large text test</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
<string>m_pLabelInfo</string>
</property>
</widget>
<widget class="QPushButton" name="m_pButtonCancel">
<property name="geometry">
<rect>
<x>642</x>
<y>540</y>
<width>71</width>
<height>25</height>
</rect>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>13</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="m_pButtonSupport">
<property name="geometry">
<rect>
<x>500</x>
<y>540</y>
<width>131</width>
<height>25</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>13</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Online support</string>
<string>Get technical support</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="m_pButtonCancel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Exit</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../res/Synergy.qrc"/>

View file

@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AppConfig.h"
#include "MainWindow.h"
#include "QSynergyApplication.h"
#include "SetupWizard.h"
#include "SetupWizardBlocker.h"
#include "gui/AppConfig.h"
#include "gui/dotenv.h"
#include <QMessageBox>

View file

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2021 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
* Copyright (C) 2021 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -15,6 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "validators/ComputerNameValidator.h"
#include "validators/SpacesValidator.h"
@ -24,8 +24,8 @@
namespace validators {
AliasValidator::AliasValidator(QLineEdit *parent, QLabel *errors)
: LineEditValidator(parent, errors) {
AliasValidator::AliasValidator(QLineEdit *parent, ValidationError *error)
: LineEditValidator(parent, error) {
addValidator(
std::make_unique<SpacesValidator>("Computer name cannot contain spaces"));
addValidator(std::make_unique<ComputerNameValidator>(

View file

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2021 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
* Copyright (C) 2021 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -15,19 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ALIASVALIDATOR_H
#define ALIASVALIDATOR_H
#pragma once
#include "LineEditValidator.h"
#include "validators/ValidationError.h"
namespace validators {
class AliasValidator : public LineEditValidator {
public:
explicit AliasValidator(
QLineEdit *parent = nullptr, QLabel *errors = nullptr);
QLineEdit *parent = nullptr, ValidationError *error = nullptr);
};
} // namespace validators
#endif // ALIASVALIDATOR_H

View file

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2021 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
* Copyright (C) 2021 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -15,15 +14,21 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LineEditValidator.h"
#include "gui/constants.h"
#include <qvalidator.h>
namespace validators {
LineEditValidator::LineEditValidator(QLineEdit *parent, QLabel *errors)
: m_pErrors(errors),
m_pControl(parent) {
if (m_pErrors) {
m_pErrors->hide();
LineEditValidator::LineEditValidator(
QLineEdit *lineEdit, ValidationError *error)
: m_pError(error),
m_pLineEdit(lineEdit) {
if (!m_pLineEdit) {
qFatal("validator line edit not set");
}
}
@ -33,40 +38,27 @@ void LineEditValidator::addValidator(
}
QValidator::State LineEditValidator::validate(QString &input, int &pos) const {
if (!m_pControl) {
qFatal("Validator control not set");
return Invalid;
}
assert(m_pLineEdit);
QString error;
QString errorMessage;
for (const auto &validator : m_Validators) {
if (!validator->validate(input)) {
error = validator->getMessage();
errorMessage = validator->getMessage();
break;
}
}
if (error.isEmpty()) {
m_pControl->setStyleSheet("");
if (errorMessage.isEmpty()) {
m_pLineEdit->setStyleSheet("");
} else {
showError(error);
m_pControl->setStyleSheet("border: 1px solid #EC4C47");
m_pLineEdit->setStyleSheet(kStyleLineEditErrorBorder);
}
finished(error);
return Acceptable;
}
void LineEditValidator::showError(const QString &message) const {
if (m_pErrors) {
m_pErrors->setText(message);
if (m_pErrors->text().isEmpty()) {
m_pErrors->hide();
} else {
m_pErrors->show();
}
if (m_pError) {
m_pError->setMessage(errorMessage);
}
return errorMessage.isEmpty() ? Acceptable : Intermediate;
}
} // namespace validators

View file

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
* Copyright (C) 2021 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,32 +19,29 @@
#include "IStringValidator.h"
#include <QLabel>
#include <QLineEdit>
#include <QValidator>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <memory>
#include <vector>
#include "ValidationError.h"
namespace validators {
class LineEditValidator : public QValidator {
Q_OBJECT
public:
explicit LineEditValidator(
QLineEdit *parent = nullptr, QLabel *errors = nullptr);
QLineEdit *lineEdit = nullptr, ValidationError *error = nullptr);
QValidator::State validate(QString &input, int &pos) const override;
void addValidator(std::unique_ptr<IStringValidator> validator);
signals:
void finished(const QString &message) const;
private:
QLabel *m_pErrors = nullptr;
QLineEdit *m_pControl = nullptr;
ValidationError *m_pError = nullptr;
QLineEdit *m_pLineEdit = nullptr;
std::vector<std::unique_ptr<IStringValidator>> m_Validators;
void showError(const QString &message) const;
void setError(const QString &message) const;
};
} // namespace validators

View file

@ -17,10 +17,12 @@
*/
#include "ScreenNameValidator.h"
#include "validators/ComputerNameValidator.h"
#include "validators/EmptyStringValidator.h"
#include "validators/ScreenDuplicationsValidator.h"
#include "validators/SpacesValidator.h"
#include "validators/ValidationError.h"
#include <QRegularExpression>
#include <memory>
@ -28,8 +30,8 @@
namespace validators {
ScreenNameValidator::ScreenNameValidator(
QLineEdit *parent, QLabel *errors, const ScreenList *pScreens)
: LineEditValidator(parent, errors) {
QLineEdit *lineEdit, ValidationError *error, const ScreenList *pScreens)
: LineEditValidator(lineEdit, error) {
addValidator(
std::make_unique<EmptyStringValidator>("Computer name cannot be empty"));
addValidator(
@ -37,8 +39,8 @@ ScreenNameValidator::ScreenNameValidator(
addValidator(std::make_unique<ComputerNameValidator>(
"Contains invalid characters or is too long"));
addValidator(std::make_unique<ScreenDuplicationsValidator>(
"A computer with this name already exists", parent ? parent->text() : "",
pScreens));
"A computer with this name already exists",
lineEdit ? lineEdit->text() : "", pScreens));
}
} // namespace validators

View file

@ -1,7 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2021 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
* Copyright (C) 2021 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -15,21 +14,20 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCREENNAMEVALIDATOR_H
#define SCREENNAMEVALIDATOR_H
#pragma once
#include "LineEditValidator.h"
#include "ScreenList.h"
#include "validators/ValidationError.h"
namespace validators {
class ScreenNameValidator : public LineEditValidator {
public:
explicit ScreenNameValidator(
QLineEdit *parent = nullptr, QLabel *errors = nullptr,
QLineEdit *lineEdit = nullptr, ValidationError *error = nullptr,
const ScreenList *pScreens = nullptr);
};
} // namespace validators
#endif // SCREENNAMEVALIDATOR_H

View file

@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SPACESVALIDATOR_H
#define SPACESVALIDATOR_H

View file

@ -0,0 +1,55 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
*/
#include "ValidationError.h"
#include "gui/constants.h"
namespace validators {
void clear(QLabel *label) {
if (label) {
label->setStyleSheet(kStyleErrorInactiveLabel);
label->setText("");
}
}
ValidationError::ValidationError(QObject *parent, QLabel *label)
: QObject(parent),
m_pLabel(label) {
if (m_pLabel) {
clear(m_pLabel);
}
}
const QString &ValidationError::message() const { return m_message; }
void ValidationError::setMessage(const QString &message) {
m_message = message;
if (m_pLabel) {
if (message.isEmpty()) {
clear(m_pLabel);
} else {
m_pLabel->setStyleSheet(kStyleErrorActiveLabel);
m_pLabel->setText(message);
}
}
}
} // namespace validators

View file

@ -0,0 +1,36 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QLabel>
#include <QString>
#include <qobject.h>
namespace validators {
class ValidationError : QObject {
QString m_message;
QLabel *m_pLabel = nullptr;
public:
explicit ValidationError(QObject *parent, QLabel *label = nullptr);
const QString &message() const;
void setMessage(const QString &message);
};
} // namespace validators

View file

@ -128,7 +128,7 @@ private:
void throwNameError(int);
private:
ArchMutex m_mutex{};
Deps &m_deps;
static Deps s_deps;
Deps &m_deps;
ArchMutex m_mutex{};
};

View file

@ -18,16 +18,18 @@
#include "AppConfig.h"
#include "Config.h"
#include "gui/constants.h"
#include "ConfigScopes.h"
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QVariant>
#include <QtCore>
#include <QtNetwork>
#include <functional>
using synergy::gui::Config;
using ConfigScopes = synergy::gui::ConfigScopes;
using IConfigScopes = synergy::gui::IConfigScopes;
// this should be incremented each time the wizard is changed,
// which will force it to re-run for existing installations.
@ -64,7 +66,7 @@ const char *const AppConfig::m_SettingsName[] = {
"lastVersion",
"", // 15 = lastExpiringWarningTime, obsolete
"activationHasRun",
"minimizeToTray",
"", // 17 = minimizeToTray, obsolete
"", // 18 = ActivateEmail, obsolete
"loadFromSystemScope",
"groupServerChecked", // kServerGroupChecked
@ -85,23 +87,33 @@ const char *const AppConfig::m_SettingsName[] = {
"", // 35 = clientHostMode, obsolete
"", // 36 = serverClientMode, obsolete
"serviceEnabled",
"closeToTray"};
"closeToTray",
"mainWindowSize",
"mainWindowPosition",
};
static const char *logLevelNames[] = {"INFO", "DEBUG", "DEBUG1", "DEBUG2"};
AppConfig::AppConfig() { m_Config.registerReceiever(this); }
AppConfig::Deps AppConfig::s_Deps;
AppConfig::AppConfig(Deps &deps) : m_Deps(deps), m_ScreenName(deps.hostname()) {
m_Deps.scopes().registerReceiver(this);
}
void AppConfig::loadAllScopes() {
m_Config.loadAll();
m_Deps.scopes().loadAll();
// User settings exist and the load from system scope variable is true
if (m_Config.hasSetting(
settingName(Setting::kLoadSystemSettings), Config::Scope::User)) {
if (m_Deps.scopes().hasSetting(
settingName(Setting::kLoadSystemSettings),
ConfigScopes::Scope::User)) {
setLoadFromSystemScope(m_LoadFromSystemScope);
}
// If user setting don't exist but system ones do, load the system settings
else if (m_Config.hasSetting(
settingName(Setting::kScreenName), Config::Scope::System)) {
else if (m_Deps.scopes().hasSetting(
settingName(Setting::kScreenName),
ConfigScopes::Scope::System)) {
setLoadFromSystemScope(true);
}
}
@ -111,66 +123,63 @@ void AppConfig::loadSettings() {
qDebug("loading settings");
m_ScreenName =
loadSetting(kScreenName, QHostInfo::localHostName()).toString();
if (m_ScreenName.isEmpty()) {
m_ScreenName = QHostInfo::localHostName();
}
loadCommonSettings();
loadScopeSettings();
loadSerialKey();
loadElevateMode();
m_Port = loadSetting(kPort, 24800).toInt();
m_Interface = loadSetting(kInterface).toString();
m_LogLevel = loadSetting(kLogLevel, 0).toInt();
m_LogToFile = loadSetting(kLogToFile, false).toBool();
m_LogFilename =
loadSetting(kLogFilename, logDir() + "synergy.log").toString();
m_WizardLastRun = loadCommonSetting(kWizardLastRun, 0).toInt();
m_StartedBefore = loadSetting(kStartedBefore, false).toBool();
emit loaded();
}
QVariant elevateMode = loadSetting(kElevateModeEnum);
if (!elevateMode.isValid()) {
elevateMode = loadSetting(
kElevateMode, QVariant(static_cast<int>(kDefaultElevateMode)));
}
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
void AppConfig::loadCommonSettings() {
using enum Setting;
m_AutoHide = loadSetting(kAutoHide, false).toBool();
m_LastVersion = loadSetting(kLastVersion, "Unknown").toString();
m_ActivationHasRun = loadSetting(kActivationHasRun, false).toBool();
m_MinimizeToTray = loadSetting(kMinimizeToTray, false).toBool();
m_WizardLastRun = loadCommonSetting(kWizardLastRun, m_WizardLastRun).toInt();
m_LoadFromSystemScope =
loadCommonSetting(kLoadSystemSettings, false).toBool();
m_ServerGroupChecked = loadSetting(kServerGroupChecked, false).toBool();
m_UseExternalConfig = loadSetting(kUseExternalConfig, false).toBool();
m_ConfigFile =
loadSetting(kConfigFile, QDir::homePath() + "/" + m_ConfigFilename)
.toString();
m_UseInternalConfig = loadSetting(kUseInternalConfig, false).toBool();
m_ClientGroupChecked = loadSetting(kClientGroupChecked, false).toBool();
m_ServerHostname = loadSetting(kServerHostname).toString();
m_PreventSleep = loadSetting(kPreventSleep, false).toBool();
m_LanguageSync = loadSetting(kLanguageSync, false).toBool();
m_InvertScrollDirection = loadSetting(kInvertScrollDirection, false).toBool();
m_licenseNextCheck = loadCommonSetting(kLicenseNextCheck, 0).toULongLong();
m_InvertConnection = loadSetting(kInvertConnection, false).toBool();
loadCommonSetting(kLoadSystemSettings, m_LoadFromSystemScope).toBool();
m_licenseNextCheck =
loadCommonSetting(kLicenseNextCheck, m_licenseNextCheck).toULongLong();
}
// only change the serial key if the settings being loaded contains a key
bool loadSerial = m_Config.hasSetting(
settingName(kLoadSystemSettings), Config::Scope::Current);
if (loadSerial) {
const auto &serialKey = loadSetting(kSerialKey, "").toString().trimmed();
if (!serialKey.isEmpty()) {
m_SerialKey = serialKey;
}
}
void AppConfig::loadScopeSettings() {
using enum Setting;
m_ScreenName = loadSetting(kScreenName, m_ScreenName).toString();
m_Port = loadSetting(kPort, m_Port).toInt();
m_Interface = loadSetting(kInterface, m_Interface).toString();
m_LogLevel = loadSetting(kLogLevel, m_LogLevel).toInt();
m_LogToFile = loadSetting(kLogToFile, m_LogToFile).toBool();
m_LogFilename = loadSetting(kLogFilename, m_LogFilename).toString();
m_StartedBefore = loadSetting(kStartedBefore, m_StartedBefore).toBool();
m_AutoHide = loadSetting(kAutoHide, m_AutoHide).toBool();
m_LastVersion = loadSetting(kLastVersion, m_LastVersion).toString();
m_ActivationHasRun =
loadSetting(kActivationHasRun, m_ActivationHasRun).toBool();
m_ServerGroupChecked =
loadSetting(kServerGroupChecked, m_ServerGroupChecked).toBool();
m_UseExternalConfig =
loadSetting(kUseExternalConfig, m_UseExternalConfig).toBool();
m_ConfigFile = loadSetting(kConfigFile, m_ConfigFile).toString();
m_UseInternalConfig =
loadSetting(kUseInternalConfig, m_UseInternalConfig).toBool();
m_ClientGroupChecked =
loadSetting(kClientGroupChecked, m_ClientGroupChecked).toBool();
m_ServerHostname = loadSetting(kServerHostname, m_ServerHostname).toString();
m_PreventSleep = loadSetting(kPreventSleep, m_PreventSleep).toBool();
m_LanguageSync = loadSetting(kLanguageSync, m_LanguageSync).toBool();
m_InvertScrollDirection =
loadSetting(kInvertScrollDirection, m_InvertScrollDirection).toBool();
m_InvertConnection =
loadSetting(kInvertConnection, m_InvertConnection).toBool();
m_ServiceEnabled = loadSetting(kServiceEnabled, m_ServiceEnabled).toBool();
m_CloseToTray = loadSetting(kCloseToTray, m_CloseToTray).toBool();
m_TlsEnabled = loadSetting(kTlsEnabled, m_TlsEnabled).toBool();
m_TlsCertPath = loadSetting(kTlsCertPath, defaultTlsCertPath()).toString();
m_TlsCertPath = loadSetting(kTlsCertPath, m_TlsCertPath).toString();
m_TlsKeyLength = loadSetting(kTlsKeyLength, m_TlsKeyLength).toString();
emit loaded();
m_MainWindowPosition = loadOptional<QPoint>(
kMainWindowPosition, [](QVariant v) { return v.toPoint(); });
m_MainWindowSize = loadOptional<QSize>(
kMainWindowSize, [](QVariant v) { return v.toSize(); });
}
void AppConfig::saveSettings() {
@ -192,13 +201,13 @@ void AppConfig::saveSettings() {
setSetting(kLogToFile, m_LogToFile);
setSetting(kLogFilename, m_LogFilename);
setSetting(kStartedBefore, m_StartedBefore);
setSetting(kElevateModeEnum, static_cast<int>(m_ElevateMode));
setSetting(kElevateMode, static_cast<int>(m_ElevateMode));
setSetting(kElevateModeLegacy, m_ElevateMode == ElevateAlways);
setSetting(kTlsEnabled, m_TlsEnabled);
setSetting(kAutoHide, m_AutoHide);
setSetting(kSerialKey, m_SerialKey);
setSetting(kLastVersion, m_LastVersion);
setSetting(kActivationHasRun, m_ActivationHasRun);
setSetting(kMinimizeToTray, m_MinimizeToTray);
setSetting(kUseExternalConfig, m_UseExternalConfig);
setSetting(kConfigFile, m_ConfigFile);
setSetting(kUseInternalConfig, m_UseInternalConfig);
@ -209,13 +218,13 @@ void AppConfig::saveSettings() {
setSetting(kInvertConnection, m_InvertConnection);
setSetting(kServiceEnabled, m_ServiceEnabled);
setSetting(kCloseToTray, m_CloseToTray);
// See enum ElevateMode declaration to understand why this setting is bool
setSetting(kElevateMode, m_ElevateMode == ElevateAlways);
setOptional(kMainWindowSize, m_MainWindowSize);
setOptional(kMainWindowPosition, m_MainWindowPosition);
}
setModified(false);
saved();
emit saved();
if (m_TlsChanged) {
m_TlsChanged = false;
@ -223,8 +232,49 @@ void AppConfig::saveSettings() {
}
}
void AppConfig::loadSerialKey() {
using enum Setting;
// only set the serial key if the current settings scope has they key.
bool shouldLoad = m_Deps.scopes().hasSetting(
settingName(kLoadSystemSettings), ConfigScopes::Scope::Current);
if (!shouldLoad) {
qDebug("no serial key in current scope, skipping");
return;
}
const auto &serialKey =
loadSetting(kSerialKey, m_SerialKey).toString().trimmed();
if (serialKey.isEmpty()) {
qDebug("serial key is empty, skipping");
return;
}
m_SerialKey = serialKey;
}
void AppConfig::loadElevateMode() {
using enum Setting;
if (!m_Deps.scopes().hasSetting(settingName(kElevateMode))) {
qDebug("elevate mode not set yet, skipping");
return;
}
QVariant elevateMode = loadSetting(kElevateMode);
if (!elevateMode.isValid()) {
qDebug("elevate mode not valid, loading legacy setting");
elevateMode = loadSetting(
kElevateModeLegacy, QVariant(static_cast<int>(kDefaultElevateMode)));
}
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
}
QString AppConfig::defaultTlsCertPath() const {
QDir path(m_CoreInterface.getProfileDir());
QDir path(m_Deps.profileDir());
path = path.filePath("SSL");
path = path.filePath("Synergy.pem");
return path.absolutePath();
@ -236,16 +286,35 @@ QString AppConfig::settingName(Setting name) {
}
template <typename T> void AppConfig::setSetting(Setting name, T value) {
m_Config.setSetting(settingName(name), value);
m_Deps.scopes().setSetting(settingName(name), value);
}
template <typename T> void AppConfig::setCommonSetting(Setting name, T value) {
m_Config.setSetting(settingName(name), value, Config::Scope::User);
m_Config.setSetting(settingName(name), value, Config::Scope::System);
m_Deps.scopes().setSetting(
settingName(name), value, ConfigScopes::Scope::User);
m_Deps.scopes().setSetting(
settingName(name), value, ConfigScopes::Scope::System);
}
QVariant AppConfig::loadSetting(Setting name, const QVariant &defaultValue) {
return m_Config.loadSetting(settingName(name), defaultValue);
return m_Deps.scopes().loadSetting(settingName(name), defaultValue);
}
template <typename T>
std::optional<T>
AppConfig::loadOptional(Setting name, std::function<T(QVariant)> toType) const {
if (m_Deps.scopes().hasSetting(settingName(name))) {
return toType(m_Deps.scopes().loadSetting(settingName(name)));
} else {
return std::nullopt;
}
}
template <typename T>
void AppConfig::setOptional(Setting name, const std::optional<T> &value) {
if (value.has_value()) {
m_Deps.scopes().setSetting(settingName(name), value.value());
}
}
QVariant
@ -253,28 +322,30 @@ AppConfig::loadCommonSetting(Setting name, const QVariant &defaultValue) const {
QVariant result(defaultValue);
QString setting(settingName(name));
if (m_Config.hasSetting(setting)) {
result = m_Config.loadSetting(setting, defaultValue);
} else if (m_Config.getScope() == Config::Scope::System) {
if (m_Config.hasSetting(setting, Config::Scope::User)) {
result = m_Config.loadSetting(setting, defaultValue, Config::Scope::User);
if (m_Deps.scopes().hasSetting(setting)) {
result = m_Deps.scopes().loadSetting(setting, defaultValue);
} else if (m_Deps.scopes().getScope() == ConfigScopes::Scope::System) {
if (m_Deps.scopes().hasSetting(setting, ConfigScopes::Scope::User)) {
result = m_Deps.scopes().loadSetting(
setting, defaultValue, ConfigScopes::Scope::User);
}
} else if (m_Config.hasSetting(setting, Config::Scope::System)) {
result = m_Config.loadSetting(setting, defaultValue, Config::Scope::System);
} else if (m_Deps.scopes().hasSetting(setting, ConfigScopes::Scope::System)) {
result = m_Deps.scopes().loadSetting(
setting, defaultValue, ConfigScopes::Scope::System);
}
return result;
}
void AppConfig::loadScope(Config::Scope scope) {
void AppConfig::loadScope(ConfigScopes::Scope scope) {
if (m_Config.getScope() != scope) {
if (m_Deps.scopes().getScope() != scope) {
setDefaultValues();
m_Config.setScope(scope);
if (m_Config.hasSetting(
settingName(Setting::kScreenName), m_Config.getScope())) {
m_Deps.scopes().setScope(scope);
if (m_Deps.scopes().hasSetting(
settingName(Setting::kScreenName), m_Deps.scopes().getScope())) {
// If the user already has settings, then load them up now.
m_Config.loadAll();
m_Deps.scopes().loadAll();
}
}
}
@ -285,10 +356,10 @@ void AppConfig::setLoadFromSystemScope(bool value) {
if (value) {
qDebug("loading system settings scope");
loadScope(Config::Scope::System);
loadScope(ConfigScopes::Scope::System);
} else {
qDebug("loading user settings scope");
loadScope(Config::Scope::User);
loadScope(ConfigScopes::Scope::User);
}
/*
@ -298,10 +369,10 @@ void AppConfig::setLoadFromSystemScope(bool value) {
m_LoadFromSystemScope = value;
}
bool AppConfig::isWritable() const { return m_Config.isWritable(); }
bool AppConfig::isWritable() const { return m_Deps.scopes().isWritable(); }
bool AppConfig::isSystemScoped() const {
return m_Config.getScope() == Config::Scope::System;
return m_Deps.scopes().getScope() == ConfigScopes::Scope::System;
}
template <typename T>
@ -329,12 +400,12 @@ void AppConfig::persistLogDir() const {
// Begin getters
///////////////////////////////////////////////////////////////////////////////
IConfigScopes &AppConfig::scopes() { return m_Deps.scopes(); }
bool AppConfig::activationHasRun() const { return m_ActivationHasRun; }
QString AppConfig::serialKey() const { return m_SerialKey; }
Config &AppConfig::config() { return m_Config; }
const QString &AppConfig::screenName() const { return m_ScreenName; }
int AppConfig::port() const { return m_Port; }
@ -385,8 +456,6 @@ bool AppConfig::preventSleep() const { return m_PreventSleep; }
bool AppConfig::invertConnection() const { return m_InvertConnection; }
bool AppConfig::minimizeToTray() const { return m_MinimizeToTray; }
QString AppConfig::tlsCertPath() const { return m_TlsCertPath; }
QString AppConfig::tlsKeyLength() const { return m_TlsKeyLength; }
@ -409,6 +478,14 @@ QString AppConfig::serverHostname() const { return m_ServerHostname; }
void AppConfig::setActivationHasRun(bool value) { m_ActivationHasRun = value; }
std::optional<QSize> AppConfig::mainWindowSize() const {
return m_MainWindowSize;
}
std::optional<QPoint> AppConfig::mainWindowPosition() const {
return m_MainWindowPosition;
}
///////////////////////////////////////////////////////////////////////////////
// End getters
///////////////////////////////////////////////////////////////////////////////
@ -497,10 +574,6 @@ void AppConfig::setElevateMode(ElevateMode em) {
void AppConfig::setAutoHide(bool b) { setSettingModified(m_AutoHide, b); }
void AppConfig::setMinimizeToTray(bool newValue) {
setSettingModified(m_MinimizeToTray, newValue);
}
void AppConfig::setLicenseNextCheck(unsigned long long time) {
setSettingModified(m_licenseNextCheck, time);
}
@ -530,6 +603,14 @@ void AppConfig::setInvertConnection(bool value) {
emit invertConnectionChanged();
}
void AppConfig::setMainWindowSize(const QSize &size) {
m_MainWindowSize = size;
}
void AppConfig::setMainWindowPosition(const QPoint &position) {
m_MainWindowPosition = position;
}
///////////////////////////////////////////////////////////////////////////////
// End setters
///////////////////////////////////////////////////////////////////////////////

View file

@ -19,25 +19,24 @@
#pragma once
#include "CommonConfig.h"
#include "Config.h"
#include "gui/CoreInterface.h"
#include "gui/ElevateMode.h"
#include "gui/IAppConfig.h"
#include "ConfigScopes.h"
#include "CoreInterface.h"
#include "ElevateMode.h"
#include "IAppConfig.h"
#include <QDir>
#include <QHostInfo>
#include <QObject>
#include <QPoint>
#include <QSize>
#include <QString>
#include <QVariant>
#include <mutex>
class QSettings;
class SettingsDialog;
class ServerConfig;
class LicenseHandler;
class ActivationDialog;
enum class ProcessMode { kService, kDesktop };
const ElevateMode kDefaultElevateMode = ElevateAsNeeded;
const QString kDefaultLogFile = "synergy.log";
#if defined(Q_OS_WIN)
const ProcessMode kDefaultProcessMode = ProcessMode::kService;
@ -58,12 +57,6 @@ class AppConfig : public QObject,
public synergy::gui::IAppConfig {
Q_OBJECT
friend class SettingsDialog;
friend class MainWindow;
friend class SetupWizard;
friend class ServerConfig;
friend class ActivationDialog;
private:
enum class Setting {
kScreenName = 0,
@ -74,8 +67,8 @@ private:
kLogFilename = 5,
kWizardLastRun = 6,
kStartedBefore = 7,
kElevateMode = 8,
kElevateModeEnum = 9,
kElevateModeLegacy = 8,
kElevateMode = 9,
// 10 = edition, obsolete (using serial key instead)
kTlsEnabled = 11,
kAutoHide = 12,
@ -83,7 +76,7 @@ private:
kLastVersion = 14,
// 15 = last expire time, obsolete
kActivationHasRun = 16,
kMinimizeToTray = 17,
// 17 = minimize to tray, obsolete
// 18 = activate email, obsolete
kLoadSystemSettings = 19,
kServerGroupChecked = 20,
@ -105,21 +98,37 @@ private:
// 36 = server-client-mode, obsolete
kServiceEnabled = 37,
kCloseToTray = 38,
kMainWindowSize = 39,
kMainWindowPosition = 40,
};
public:
explicit AppConfig();
struct Deps {
virtual ~Deps() = default;
virtual QString profileDir() const {
return m_coreInterface.getProfileDir();
}
virtual synergy::gui::IConfigScopes &scopes() { return m_Scopes; }
virtual QString hostname() const { return QHostInfo::localHostName(); }
/// @brief Underlying configuration reader/writer
synergy::gui::Config &config();
private:
[[no_unique_address]] CoreInterface m_coreInterface;
synergy::gui::ConfigScopes m_Scopes;
};
/// @brief Saves the setting to the current scope
explicit AppConfig() : AppConfig(s_Deps) {}
explicit AppConfig(Deps &deps);
synergy::gui::IConfigScopes &scopes();
void saveSettings() override;
void loadAllScopes();
void loadSettings() override;
/**
* Getters
*/
void setActivationHasRun(bool value);
bool isWritable() const;
bool isSystemScoped() const;
const QString &screenName() const;
@ -151,19 +160,14 @@ public:
QString serverHostname() const;
QString lastVersion() const;
bool serviceEnabled() const;
bool minimizeToTray() const;
bool closeToTray() const;
QString serialKey() const;
bool activationHasRun() const;
bool tlsEnabled() const override;
QString tlsCertPath() const override;
QString tlsKeyLength() const override;
private:
/// @brief Loads the setting from the current scope
void loadSettings() override;
static QString settingName(AppConfig::Setting name);
std::optional<QSize> mainWindowSize() const;
std::optional<QPoint> mainWindowPosition() const;
/**
* Setters
@ -192,14 +196,14 @@ private:
void setUseInternalConfig(bool);
void setClientGroupChecked(bool);
void setServerHostname(const QString &);
void setMinimizeToTray(bool b);
void setLastVersion(const QString &version);
void setServiceEnabled(bool enabled);
void setCloseToTray(bool minimize);
void setActivationHasRun(bool value);
void setTlsCertPath(const QString &path);
void setTlsKeyLength(const QString &length);
void setInvertConnection(bool value);
void setMainWindowSize(const QSize &size);
void setMainWindowPosition(const QPoint &position);
/// @brief Sets the user preference to load from SystemScope.
/// @param [in] value
@ -208,8 +212,27 @@ private:
/// scope settings.
void setLoadFromSystemScope(bool value);
/// @brief Loads config from the underlying reader/writer
void loadAllScopes();
private:
static QString settingName(AppConfig::Setting name);
void loadSerialKey();
void loadElevateMode();
void loadCommonSettings();
void loadScopeSettings();
/**
* @brief Loads a setting if it exists, otherwise returns `std::nullopt`
*
* @param toType A function to convert the QVariant to the desired type.
*/
template <typename T>
std::optional<T>
loadOptional(Setting name, std::function<T(QVariant)> toType) const;
/**
* @brief Sets a setting if the value is not `std::nullopt`.
*/
template <typename T>
void setOptional(Setting name, const std::optional<T> &value);
/// @brief Sets the value of a setting
/// @param [in] name The Setting to be saved
@ -243,7 +266,7 @@ private:
/// @brief This method loads config from specified scope
/// @param [in] scope which should be loaded.
void loadScope(synergy::gui::Config::Scope scope);
void loadScope(synergy::gui::ConfigScopes::Scope scope);
/// @brief This function sets default values
/// for settings that shouldn't be copied from between scopes.
@ -254,14 +277,14 @@ private:
*/
QString defaultTlsCertPath() const;
synergy::gui::Config m_Config;
CoreInterface m_CoreInterface;
QString m_ScreenName = "";
static Deps s_Deps;
Deps &m_Deps;
QString m_ScreenName;
int m_Port = 24800;
QString m_Interface = "";
int m_LogLevel = 0;
bool m_LogToFile = false;
QString m_LogFilename = "";
QString m_LogFilename = logDir() + kDefaultLogFile;
int m_WizardLastRun = 0;
bool m_StartedBefore = false;
ElevateMode m_ElevateMode = kDefaultElevateMode;
@ -272,21 +295,22 @@ private:
QString m_LastVersion = "";
unsigned long long m_licenseNextCheck = 0;
bool m_ActivationHasRun = false;
bool m_MinimizeToTray = true;
bool m_InvertScrollDirection = false;
bool m_LanguageSync = true;
bool m_PreventSleep = false;
bool m_InvertConnection = false;
bool m_ServerGroupChecked = false;
bool m_UseExternalConfig = false;
QString m_ConfigFile = "";
QString m_ConfigFile = QDir::homePath() + "/" + m_ConfigFilename;
bool m_UseInternalConfig = false;
bool m_ClientGroupChecked = false;
QString m_ServerHostname = "";
bool m_ServiceEnabled = kDefaultProcessMode == ProcessMode::kService;
bool m_CloseToTray = false;
QString m_TlsCertPath = "";
QString m_TlsCertPath = defaultTlsCertPath();
QString m_TlsKeyLength = "2048";
std::optional<QSize> m_MainWindowSize;
std::optional<QPoint> m_MainWindowPosition;
/**
* @brief Flag is set when any TLS is setting is changed, and is reset

View file

@ -47,9 +47,9 @@ QString CommandProcess::run() {
if (int code = process.exitCode(); !success || code != 0) {
qFatal(
"Command failed: %s %s\nCode: %d\nError: %s", qUtf8Printable(m_Command),
"command failed: %s %s\ncode: %d\nerror: %s", qUtf8Printable(m_Command),
qUtf8Printable(m_Arguments.join(" ")), code,
error.isEmpty() ? "None" : qUtf8Printable(error));
error.isEmpty() ? "none" : qUtf8Printable(error));
}
emit finished();

View file

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Config.h"
#include "ConfigScopes.h"
#include "CommonConfig.h"
@ -68,7 +68,7 @@ void loadWindowsLegacy(QSettings &settings) {
}
#endif
Config::Config() {
ConfigScopes::ConfigScopes() {
QSettings::setPath(
QSettings::Format::IniFormat, QSettings::Scope::SystemScope,
getSystemSettingPath());
@ -88,20 +88,20 @@ Config::Config() {
load();
}
Config::~Config() {
while (!m_pReceievers.empty()) {
m_pReceievers.pop_back();
ConfigScopes::~ConfigScopes() {
while (!m_pReceivers.empty()) {
m_pReceivers.pop_back();
}
}
void Config::load() {
void ConfigScopes::load() {
#if defined(Q_OS_WIN)
// This call is needed for backwardcapability with old settings.
loadWindowsLegacy(*m_pSystemSettings);
#endif
}
bool Config::hasSetting(const QString &name, Scope scope) const {
bool ConfigScopes::hasSetting(const QString &name, Scope scope) const {
switch (scope) {
case Scope::User:
return m_pUserSettings->contains(name);
@ -112,9 +112,11 @@ bool Config::hasSetting(const QString &name, Scope scope) const {
}
}
bool Config::isWritable() const { return currentSettings()->isWritable(); }
bool ConfigScopes::isWritable() const {
return currentSettings()->isWritable();
}
QVariant Config::loadSetting(
QVariant ConfigScopes::loadSetting(
const QString &name, const QVariant &defaultValue, Scope scope) const {
switch (scope) {
case Scope::User:
@ -126,21 +128,23 @@ QVariant Config::loadSetting(
}
}
void Config::setScope(Config::Scope scope) { m_CurrentScope = scope; }
void ConfigScopes::setScope(ConfigScopes::Scope scope) {
m_CurrentScope = scope;
}
Config::Scope Config::getScope() const { return m_CurrentScope; }
ConfigScopes::Scope ConfigScopes::getScope() const { return m_CurrentScope; }
void Config::loadAll() {
for (auto &i : m_pReceievers) {
void ConfigScopes::loadAll() {
for (auto &i : m_pReceivers) {
i->loadSettings();
}
}
void Config::saveAll() {
void ConfigScopes::saveAll() {
// Save if there are any unsaved changes otherwise skip
if (unsavedChanges()) {
for (auto &i : m_pReceievers) {
for (auto &i : m_pReceivers) {
i->saveSettings();
}
@ -151,7 +155,7 @@ void Config::saveAll() {
}
}
QSettings *Config::currentSettings() const {
QSettings *ConfigScopes::currentSettings() const {
if (m_CurrentScope == Scope::User) {
return m_pUserSettings.get();
} else {
@ -159,16 +163,16 @@ QSettings *Config::currentSettings() const {
}
}
void Config::registerReceiever(CommonConfig *receiver) {
m_pReceievers.push_back(receiver);
void ConfigScopes::registerReceiver(CommonConfig *receiver) {
m_pReceivers.push_back(receiver);
}
bool Config::unsavedChanges() const {
bool ConfigScopes::unsavedChanges() const {
if (m_unsavedChanges) {
return true;
}
for (const auto &i : m_pReceievers) {
for (const auto &i : m_pReceivers) {
if (i->modified()) {
return true;
}
@ -176,6 +180,12 @@ bool Config::unsavedChanges() const {
return false;
}
void Config::markUnsaved() { m_unsavedChanges = true; }
void ConfigScopes::markUnsaved() { m_unsavedChanges = true; }
void ConfigScopes::setSetting(
const QString &name, const QVariant &value, Scope scope) {
currentSettings()->setValue(name, value);
m_unsavedChanges = true;
}
} // namespace synergy::gui

View file

@ -14,8 +14,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "IConfigScopes.h"
#include <QSettings>
#include <QVariant>
#include <memory>
@ -25,31 +28,31 @@ namespace synergy::gui {
class CommonConfig;
/// @brief A general config reader and writer for user and gloabl settings
class Config : private QObject {
class ConfigScopes : public IConfigScopes {
public:
enum class Scope { Current, System, User };
explicit Config();
~Config() override;
explicit ConfigScopes();
virtual ~ConfigScopes();
/// @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 = Scope::Current) const;
bool
hasSetting(const QString &name, Scope scope = Scope::Current) const override;
/// @brief Checks if the current scope settings writable
/// @return bool True if the current scope writable
bool isWritable() const;
bool isWritable() const override;
/// @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 <typename T>
void setSetting(const QString &name, T value, Scope scope = Scope::Current);
void setSetting(
const QString &name, const QVariant &value,
Scope scope = Scope::Current) override;
/// @brief Loads a setting
/// @param [in] name The setting to be loaded
@ -58,35 +61,35 @@ public:
/// scope
QVariant loadSetting(
const QString &name, const QVariant &defaultValue = QVariant(),
Scope scope = Scope::Current) const;
Scope scope = Scope::Current) const override;
/// @brief Changes the setting save and load location between System and User
/// scope
/// @param [in] scope The scope to set
void setScope(Scope scope = Scope::User);
void setScope(Scope scope = Scope::User) override;
/// @brief Get the current scope the settings are loading and save from.
/// @return Scope An enum defining the current scope
Scope getScope() const;
Scope getScope() const override;
/// @brief trigger a config load across all registered classes
void loadAll();
void loadAll() override;
/// @brief trigger a config save across all registered classes
void saveAll();
void saveAll() override;
/// @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 *currentSettings() const;
QSettings *currentSettings() const override;
/// @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 requests to save and load settings
void registerReceiever(CommonConfig *receiver);
void registerReceiver(CommonConfig *receiver) override;
/// @brief Checks if any registered class has any unsaved changes
/// @return bool True if any registered class has unsaved changes
@ -100,16 +103,10 @@ private:
std::unique_ptr<QSettings> m_pSystemSettings;
/// @brief Receivers of load/save callbacks
std::list<CommonConfig *> m_pReceievers;
std::list<CommonConfig *> m_pReceivers;
/// @brief Is set to true when settings are changed
bool m_unsavedChanges = false;
};
template <typename T>
void Config::setSetting(const QString &name, T value, Scope scope) {
currentSettings()->setValue(name, value);
m_unsavedChanges = true;
}
} // namespace synergy::gui

View file

@ -0,0 +1,51 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gui/CommonConfig.h"
#include <QSettings>
#include <QString>
#include <QVariant>
namespace synergy::gui {
class IConfigScopes {
public:
enum class Scope { Current, System, User };
virtual ~IConfigScopes() = default;
virtual void registerReceiver(CommonConfig *receiver) = 0;
virtual void loadAll() = 0;
virtual bool
hasSetting(const QString &name, Scope scope = Scope::Current) const = 0;
virtual QVariant loadSetting(
const QString &name, const QVariant &defaultValue = QVariant(),
Scope scope = Scope::Current) const = 0;
virtual void setSetting(
const QString &name, const QVariant &value,
Scope scope = Scope::Current) = 0;
virtual Scope getScope() const = 0;
virtual void setScope(Scope scope = Scope::User) = 0;
virtual bool isWritable() const = 0;
virtual QSettings *currentSettings() const = 0;
virtual void saveAll() = 0;
};
} // namespace synergy::gui

View file

@ -58,7 +58,7 @@ QString openSslWindowsDir() {
// if the path still isn't found, something is seriously wrong.
if (!openSslDir.exists()) {
qFatal() << "OpenSSL dir not found: " << openSslDir;
qFatal() << "openssl dir not found: " << openSslDir;
}
return QDir::cleanPath(openSslDir.absolutePath());
@ -77,7 +77,7 @@ QString openSslWindowsBinary() {
// if the path still isn't found, something is seriously wrong.
if (!QFile::exists(path)) {
qFatal() << "OpenSSL binary not found: " << path;
qFatal() << "openssl binary not found: " << path;
}
return path;

View file

@ -20,7 +20,6 @@
#include "IAppConfig.h"
#include "license/License.h"
#include <stdexcept>
namespace synergy::gui {

View file

@ -28,23 +28,39 @@ const bool kLicensingEnabled = false;
const auto kColorWhite = "#ffffff";
const auto kColorPrimary = "#ff7c00";
const auto kColorSecondary = "#4285f4";
const auto kColorTertiary = "#33b2cc";
const auto kColorError = "#ec4c47";
const auto kColorNotice = "#3b67d3";
const auto kLinkStyleWhite = QString("color: %1").arg(kColorWhite);
const auto kLinkStylePrimary = QString("color: %1").arg(kColorPrimary);
const auto kLinkStyleSecondary = QString("color: %1").arg(kColorSecondary);
const auto kLinkBuy = R"(<a href="%1" style="%2">Buy now</a>)";
const auto kLinkRenew = R"(<a href="%1" style="%2">Renew now</a>)";
const auto kLinkDownload = R"(<a href="%1" style="%2">Download now</a>)";
const auto kLinkBuy = R"(<a href="%1" style="color: %2">Buy now</a>)";
const auto kLinkRenew = R"(<a href="%1" style="color: %2">Renew now</a>)";
const auto kLinkDownload = R"(<a href="%1" style="color: %2">Download now</a>)";
const auto kUrlSourceQuery = "source=gui";
const auto kUrlWebsite = "https://symless.com";
const auto kUrlProduct = QString("%1/synergy").arg(kUrlWebsite);
const auto kUrlPurchase =
QString("%1/purchase?%2").arg(kUrlProduct).arg(kUrlSourceQuery);
QString("%1/purchase?%2").arg(kUrlProduct, kUrlSourceQuery);
const auto kUrlContact =
QString("%1/contact?%2").arg(kUrlProduct).arg(kUrlSourceQuery);
const auto kUrlHelp =
QString("%1/help?%2").arg(kUrlProduct).arg(kUrlSourceQuery);
QString("%1/contact?%2").arg(kUrlProduct, kUrlSourceQuery);
const auto kUrlHelp = QString("%1/help?%2").arg(kUrlProduct, kUrlSourceQuery);
const auto kUrlDownload =
QString("%1/download?%2").arg(kUrlProduct).arg(kUrlSourceQuery);
QString("%1/download?%2").arg(kUrlProduct, kUrlSourceQuery);
const auto kStyleLineEditErrorBorder =
QString("border: 1px solid %1; border-radius: 2px; padding: 2px;")
.arg(kColorError);
const auto kStyleErrorActiveLabel = //
QString("padding: 3px 5px; border-radius: 3px; "
"background-color: %1; color: %2")
.arg(kColorError, kColorWhite);
const auto kStyleErrorInactiveLabel = //
QString("padding: 3px 5px; border-radius: 3px;"
"background-color: none");
const auto kStyleNoticeLabel = //
QString("padding: 3px 5px; border-radius: 3px;"
"background-color: %1; color: %2")
.arg(kColorNotice, kColorWhite);

View file

@ -38,8 +38,7 @@ QString licenseNotice(const License &license) {
}
QString trialLicenseNotice(const License &license) {
const QString buyLink =
QString(kLinkBuy).arg(kUrlPurchase).arg(kLinkStyleWhite);
const QString buyLink = QString(kLinkBuy).arg(kUrlPurchase).arg(kColorWhite);
if (license.isExpired()) {
return QString("<p>Your trial has expired. %1</p>").arg(buyLink);
} else {
@ -57,7 +56,7 @@ QString trialLicenseNotice(const License &license) {
QString subscriptionLicenseNotice(const License &license) {
const QString renewLink =
QString(kLinkRenew).arg(kUrlPurchase).arg(kLinkStyleWhite);
QString(kLinkRenew).arg(kUrlPurchase).arg(kColorWhite);
if (license.isExpired()) {
return QString("<p>Your license has expired. %1</p>").arg(renewLink);
} else {

View file

@ -0,0 +1,55 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
*/
#include "gui/CoreInterface.h"
#include "shared/gui/QtCoreTest.h"
#include <gtest/gtest.h>
class CoreInterfaceTests : public QtCoreTest {};
TEST_F(CoreInterfaceTests, getProfileDir_noMock_returnsNonEmpty) {
CoreInterface coreInterface;
QString profileDir = coreInterface.getProfileDir();
EXPECT_FALSE(profileDir.isEmpty());
}
TEST_F(CoreInterfaceTests, getInstalledDir_noMock_returnsNonEmpty) {
CoreInterface coreInterface;
QString installedDir = coreInterface.getInstalledDir();
EXPECT_FALSE(installedDir.isEmpty());
}
TEST_F(CoreInterfaceTests, getArch_noMock_returnsNonEmpty) {
CoreInterface coreInterface;
QString arch = coreInterface.getArch();
EXPECT_FALSE(arch.isEmpty());
}
TEST_F(CoreInterfaceTests, getSerialKeyFilePath_noMock_returnsNonEmpty) {
CoreInterface coreInterface;
QString serialKeyFilePath = coreInterface.getSerialKeyFilePath();
EXPECT_FALSE(serialKeyFilePath.isEmpty());
}

View file

@ -17,26 +17,24 @@
#include "test/shared/TestEventQueue.h"
#include "base/Log.h"
#include "base/SimpleEventQueueBuffer.h"
#include "base/TMethodEventJob.h"
#include "common/stdexcept.h"
void TestEventQueue::raiseQuitEvent() { addEvent(Event(Event::kQuit)); }
void TestEventQueue::initQuitTimeout(double timeout) {
assert(m_quitTimeoutTimer == nullptr);
m_quitTimeoutTimer = newOneShotTimer(timeout, NULL);
assert(m_pQuitTimeoutTimer == nullptr);
m_pQuitTimeoutTimer = newOneShotTimer(timeout, NULL);
adoptHandler(
Event::kTimer, m_quitTimeoutTimer,
Event::kTimer, m_pQuitTimeoutTimer,
new TMethodEventJob<TestEventQueue>(
this, &TestEventQueue::handleQuitTimeout));
}
void TestEventQueue::cleanupQuitTimeout() {
removeHandler(Event::kTimer, m_quitTimeoutTimer);
delete m_quitTimeoutTimer;
m_quitTimeoutTimer = nullptr;
removeHandler(Event::kTimer, m_pQuitTimeoutTimer);
delete m_pQuitTimeoutTimer;
m_pQuitTimeoutTimer = nullptr;
}
void TestEventQueue::handleQuitTimeout(const Event &, void *vclient) {

View file

@ -23,7 +23,7 @@ class EventQueueTimer;
class TestEventQueue : public EventQueue {
public:
TestEventQueue() : m_quitTimeoutTimer(nullptr) {}
TestEventQueue() : m_pQuitTimeoutTimer(nullptr) {}
void handleQuitTimeout(const Event &, void *vclient);
void raiseQuitEvent();
@ -34,5 +34,5 @@ private:
void timeoutThread(void *);
private:
EventQueueTimer *m_quitTimeoutTimer;
EventQueueTimer *m_pQuitTimeoutTimer;
};

View file

@ -23,16 +23,12 @@
class QtCoreTest : public ::testing::Test {
public:
static void SetUpTestSuite() {
GTEST_LOG_(INFO) << "Qt core app setup";
char **argv = nullptr;
int argc = 0;
s_app = std::make_unique<QCoreApplication>(argc, argv);
}
static void TearDownTestSuite() {
s_app.reset();
GTEST_LOG_(INFO) << "Qt core app teardown";
}
static void TearDownTestSuite() { s_app.reset(); }
static std::unique_ptr<QCoreApplication> s_app;
};

View file

@ -23,16 +23,12 @@
class QtTest : public ::testing::Test {
public:
static void SetUpTestSuite() {
GTEST_LOG_(INFO) << "Qt app setup";
char **argv = nullptr;
int argc = 0;
s_app = std::make_unique<QApplication>(argc, argv);
}
static void TearDownTestSuite() {
s_app.reset();
GTEST_LOG_(INFO) << "Qt app teardown";
}
static void TearDownTestSuite() { s_app.reset(); }
static std::unique_ptr<QApplication> s_app;
};

View file

@ -31,6 +31,7 @@ using ::testing::NiceMock;
using PollEntries = std::vector<IArchNetwork::PollEntry>;
using PollFD = struct pollfd[];
namespace {
struct MockDeps : public ArchNetworkBSD::Deps {
MockDeps() {
ON_CALL(*this, makePollFD(_)).WillByDefault([this](nfds_t n) {
@ -47,19 +48,7 @@ struct MockDeps : public ArchNetworkBSD::Deps {
std::shared_ptr<PollFD> m_pollFD;
};
#ifndef NDEBUG
TEST(ArchNetworkBSDTests, pollSocket_negativeNum_death) {
MockDeps deps;
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
EXPECT_DEATH({ networkBSD.pollSocket(entries.data(), -1, 1); }, "num > 0");
}
#endif // DEBUG
} // namespace
TEST(ArchNetworkBSDTests, pollSocket_zeroEntries_callsSleep) {
MockDeps deps;

View file

@ -0,0 +1,108 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
*/
#include "gui/AppConfig.h"
#include "gmock/gmock.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using namespace testing;
namespace {
class MockScopes : public synergy::gui::IConfigScopes {
public:
MOCK_METHOD(
void, registerReceiver, (synergy::gui::CommonConfig * receiver),
(override));
MOCK_METHOD(void, loadAll, (), (override));
MOCK_METHOD(
bool, hasSetting, (const QString &name, Scope scope), (const, override));
MOCK_METHOD(
QVariant, loadSetting,
(const QString &name, const QVariant &defaultValue, Scope scope),
(const, override));
MOCK_METHOD(
void, setSetting,
(const QString &name, const QVariant &value, Scope scope), (override));
MOCK_METHOD(Scope, getScope, (), (const, override));
MOCK_METHOD(void, setScope, (Scope scope), (override));
MOCK_METHOD(bool, isWritable, (), (const, override));
MOCK_METHOD(QSettings *, currentSettings, (), (const, override));
MOCK_METHOD(void, saveAll, (), (override));
};
struct MockDeps : public AppConfig::Deps {
NiceMock<MockScopes> m_scopes;
MockDeps() {
ON_CALL(*this, profileDir()).WillByDefault(Return("stub"));
ON_CALL(*this, scopes()).WillByDefault(ReturnRef(m_scopes));
ON_CALL(*this, hostname()).WillByDefault(Return("stub"));
}
MOCK_METHOD(QString, profileDir, (), (const, override));
MOCK_METHOD(synergy::gui::IConfigScopes &, scopes, (), (override));
MOCK_METHOD(QString, hostname, (), (const, override));
};
} // namespace
class AppConfigTests : public Test {};
TEST_F(AppConfigTests, ctor_byDefault_screenNameIsHostname) {
NiceMock<MockDeps> deps;
ON_CALL(deps, hostname()).WillByDefault(Return("test"));
AppConfig appConfig(deps);
ASSERT_EQ(appConfig.screenName().toStdString(), "test");
}
TEST_F(AppConfigTests, loadAllScopes_byDefault_callsScopesLoadAll) {
NiceMock<MockDeps> deps;
AppConfig appConfig(deps);
EXPECT_CALL(deps.m_scopes, loadAll());
appConfig.loadAllScopes();
}
TEST_F(AppConfigTests, loadSettings_byDefault_callsScopesLoadSetting) {
NiceMock<MockDeps> deps;
AppConfig appConfig(deps);
ON_CALL(deps.m_scopes, hasSetting(_, _)).WillByDefault(Return(true));
ON_CALL(deps.m_scopes, loadSetting(_, _, _))
.WillByDefault(Return(QVariant("test")));
EXPECT_CALL(deps.m_scopes, loadSetting(_, _, _)).Times(AnyNumber());
appConfig.loadSettings();
ASSERT_EQ(appConfig.screenName().toStdString(), "test");
}
TEST_F(AppConfigTests, saveSettings_byDefault_callsScopesSetSetting) {
NiceMock<MockDeps> deps;
AppConfig appConfig(deps);
ON_CALL(deps.m_scopes, isWritable()).WillByDefault(Return(true));
EXPECT_CALL(deps.m_scopes, setSetting(_, _, _)).Times(AnyNumber());
appConfig.saveSettings();
}