diff --git a/.gitignore b/.gitignore
index 72ceca0cb..c0a47f406 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ Brewfile.lock.json
*.code-workspace
.env*
/scripts/*.egg-info
+/*.user
+*.ui.autosave
diff --git a/.vscode/launch.json b/.vscode/launch.json
index ca1e56e0e..f0639c554 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,55 +2,68 @@
"version": "0.2.0",
"configurations": [
{
- "name": "gui lldb",
+ "name": "gui unix",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/bin/synergy",
- "preLaunchTask": "build-kill"
+ "preLaunchTask": "kill-build"
},
{
- "name": "unittests lldb",
+ "name": "gui windows",
+ "type": "cppvsdbg",
+ "cwd": "${workspaceRoot}/build/bin",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/bin/synergy",
+ "internalConsoleOptions": "openOnSessionStart",
+ "preLaunchTask": "kill-build"
+ },
+ {
+ "name": "unittests unix",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/bin/unittests",
"preLaunchTask": "build"
},
{
- "name": "integtests lldb",
+ "name": "unittests windows",
+ "type": "cppvsdbg",
+ "cwd": "${workspaceRoot}/build/bin",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/bin/unittests",
+ "internalConsoleOptions": "openOnSessionStart",
+ "preLaunchTask": "build"
+ },
+ {
+ "name": "integtests unix",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/bin/integtests",
"preLaunchTask": "build"
},
{
- "name": "win daemon attach",
+ "name": "integtests windows",
+ "type": "cppvsdbg",
+ "cwd": "${workspaceRoot}/build/bin",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/bin/integtests",
+ "internalConsoleOptions": "openOnSessionStart",
+ "preLaunchTask": "build"
+ },
+ {
+ "name": "daemon windows",
+ "type": "cppvsdbg",
+ "cwd": "${workspaceRoot}/build/bin",
+ "request": "launch",
+ "program": "${workspaceFolder}/build/bin/synergyd",
+ "args": ["-f"],
+ "internalConsoleOptions": "openOnSessionStart",
+ "preLaunchTask": "build"
+ },
+ {
+ "name": "daemon windows attach",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}"
- },
- {
- "name": "win daemon attach - lldb",
- "type": "lldb",
- "request": "attach",
- "program": "${workspaceFolder}/build/bin/synergyd"
- },
- {
- "name": "win daemon launch",
- "type": "cppvsdbg",
- "cwd": "${workspaceRoot}/build/bin",
- "request": "launch",
- "program": "${workspaceFolder}/build/bin/synergyd",
- "args": ["-f"],
- "internalConsoleOptions": "openOnSessionStart"
- },
- {
- "name": "win daemon launch - rebuild",
- "type": "cppvsdbg",
- "cwd": "${workspaceRoot}/build/bin",
- "request": "launch",
- "program": "${workspaceFolder}/build/bin/synergyd",
- "args": ["-f"],
- "preLaunchTask": "build"
}
]
}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 10615f208..822405ca9 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -22,7 +22,7 @@
},
{
"label": "tests",
- "dependsOn": ["unittests", "integtests"],
+ "dependsOn": ["integtests", "unittests"],
"problemMatcher": []
},
{
@@ -31,24 +31,43 @@
"command": "killall synergy; killall synergyc; killall synergys || true",
"windows": {
"command": "taskkill /F /IM synergy.exe /IM synergyc.exe /IM synergys.exe; $true"
+ },
+ "presentation": {
+ "reveal": "silent"
}
},
{
- "label": "build-kill",
- "dependsOn": ["build", "kill"]
+ "label": "kill-build",
+ "dependsOn": ["kill", "build"],
+ "problemMatcher": []
},
{
"label": "gui",
"type": "process",
"command": "${workspaceFolder}/build/bin/synergy",
- "dependsOn": ["build", "kill"]
+ "dependsOn": ["build", "kill"],
+ "problemMatcher": [],
+ "windows": {
+ "command": "${workspaceFolder}/build/bin/synergy.exe"
+ }
},
{
- "label": "windows daemon",
+ "label": "restart daemon",
"type": "shell",
- "command": "python scripts/windows_daemon.py",
+ "command": "python scripts/daemon.py --restart",
"dependsOn": ["build"]
},
+ {
+ "label": "reinstall daemon",
+ "type": "shell",
+ "command": "python scripts/daemon.py --reinstall",
+ "dependsOn": ["build"]
+ },
+ {
+ "label": "stop daemon",
+ "type": "shell",
+ "command": "python scripts/daemon.py --stop"
+ },
{
"label": "clean-gcda",
"type": "shell",
diff --git a/ChangeLog b/ChangeLog
index 15b5181ea..220fe70df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -57,6 +57,7 @@ Enhancements:
- #7403 Solve low hanging reliability and maintainability issues
- #7404 Restore integtests and add to CI as warning comment on failure
- #7406 Migrate scripts from `requirements.txt` to `pyproject.toml`
+- #7407 Implement safer memory use, improve dev env, fixed GUI bugs
# 1.14.6
diff --git a/cmake/Libraries.cmake b/cmake/Libraries.cmake
index ea590395c..1bff3664a 100644
--- a/cmake/Libraries.cmake
+++ b/cmake/Libraries.cmake
@@ -1,19 +1,3 @@
-# Synergy -- mouse and keyboard sharing utility
-# Copyright (C) 2012-2024 Symless Ltd.
-# Copyright (C) 2009-2012 Nick Bolton
-#
-# 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 .
-
macro(configure_libs)
set(libs)
@@ -295,6 +279,9 @@ macro(configure_windows_libs)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/res/win/version.rc.in
${CMAKE_BINARY_DIR}/src/version.rc @ONLY)
+ find_openssl_dir_win32(OPENSSL_PATH)
+ add_definitions(-DOPENSSL_PATH="${OPENSSL_PATH}")
+
endmacro()
macro(configure_openssl)
@@ -383,3 +370,36 @@ macro(configure_python)
set(PYTHON_BIN "${CMAKE_BINARY_DIR}/python/bin/python")
endif()
endmacro()
+
+#
+# Find the OpenSSL directory on Windows based on the location of the first
+# `openssl` binary found.
+#
+function(find_openssl_dir_win32 result)
+
+ execute_process(
+ COMMAND where openssl
+ OUTPUT_VARIABLE OPENSSL_PATH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ # It's possible that there are multiple OpenSSL installations on the system,
+ # which is the case on GitHub runners. For now we'll pick the first one, but
+ # that's probably not very robust. Maybe our choco config could install to a
+ # specific location?
+ string(REGEX REPLACE "\r?\n" ";" OPENSSL_PATH_LIST ${OPENSSL_PATH})
+ message(STATUS "Found OpenSSL binaries at: ${OPENSSL_PATH_LIST}")
+
+ list(GET OPENSSL_PATH_LIST 0 OPENSSL_FIRST_PATH)
+ message(STATUS "First OpenSSL binary: ${OPENSSL_FIRST_PATH}")
+
+ get_filename_component(OPENSSL_BIN_DIR ${OPENSSL_FIRST_PATH} DIRECTORY)
+ message(STATUS "OpenSSL bin dir: ${OPENSSL_BIN_DIR}")
+
+ get_filename_component(OPENSSL_DIR ${OPENSSL_BIN_DIR} DIRECTORY)
+ message(STATUS "OpenSSL install root dir: ${OPENSSL_DIR}")
+
+ set(${result}
+ ${OPENSSL_DIR}
+ PARENT_SCOPE)
+
+endfunction()
diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake
index 441b0e470..0b03ce1db 100644
--- a/cmake/Packaging.cmake
+++ b/cmake/Packaging.cmake
@@ -51,8 +51,6 @@ macro(configure_windows_packaging)
set(CPACK_PACKAGE_VERSION ${SYNERGY_VERSION_MS})
set(QT_PATH $ENV{CMAKE_PREFIX_PATH})
- find_openssl_dir_win32(OPENSSL_PATH)
-
configure_files(${CMAKE_CURRENT_SOURCE_DIR}/res/dist/wix
${CMAKE_BINARY_DIR}/installer)
@@ -157,36 +155,3 @@ macro(configure_files srcDir destDir)
endforeach(templateFile)
endmacro(configure_files)
-
-#
-# Find the OpenSSL directory on Windows based on the location of the first
-# `openssl` binary found.
-#
-function(find_openssl_dir_win32 result)
-
- execute_process(
- COMMAND where openssl
- OUTPUT_VARIABLE OPENSSL_PATH
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- # It's possible that there are multiple OpenSSL installations on the system,
- # which is the case on GitHub runners. For now we'll pick the first one, but
- # that's probably not very robust. Maybe our choco config could install to a
- # specific location?
- string(REGEX REPLACE "\r?\n" ";" OPENSSL_PATH_LIST ${OPENSSL_PATH})
- message(STATUS "Found OpenSSL binaries at: ${OPENSSL_PATH_LIST}")
-
- list(GET OPENSSL_PATH_LIST 0 OPENSSL_FIRST_PATH)
- message(STATUS "First OpenSSL binary: ${OPENSSL_FIRST_PATH}")
-
- get_filename_component(OPENSSL_BIN_DIR ${OPENSSL_FIRST_PATH} DIRECTORY)
- message(STATUS "OpenSSL bin dir: ${OPENSSL_BIN_DIR}")
-
- get_filename_component(OPENSSL_DIR ${OPENSSL_BIN_DIR} DIRECTORY)
- message(STATUS "OpenSSL install root dir: ${OPENSSL_DIR}")
-
- set(${result}
- ${OPENSSL_DIR}
- PARENT_SCOPE)
-
-endfunction()
diff --git a/scripts/daemon.py b/scripts/daemon.py
new file mode 100644
index 000000000..40a34ddd7
--- /dev/null
+++ b/scripts/daemon.py
@@ -0,0 +1,192 @@
+import os, sys, time, subprocess, argparse
+import lib.windows as windows
+import lib.file_utils as file_utils
+import lib.env as env
+import lib.colors as colors
+import psutil
+
+DEFAULT_BIN_NAME = "synergyd"
+DEFAULT_SOURCE_DIR = os.path.join("build", "temp", "bin")
+DEFAULT_TARGET_DIR = os.path.join("build", "bin")
+SERVICE_NOT_RUNNING_ERROR = 2
+ERROR_ACCESS_VIOLATION = 0xC0000005
+IGNORE_PROCESSES = ["synergy.exe"]
+
+
+class Context:
+ def __init__(self, verbose):
+ self.verbose = verbose
+
+
+def main():
+ """Entry point for the script."""
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--reinstall", action="store_true")
+ parser.add_argument("--stop", action="store_true")
+ parser.add_argument("--restart", action="store_true")
+ parser.add_argument("--pause-on-exit", action="store_true")
+ parser.add_argument("--source-dir", default=DEFAULT_SOURCE_DIR)
+ parser.add_argument("--target-dir", default=DEFAULT_TARGET_DIR)
+ parser.add_argument("--bin-name", default=DEFAULT_BIN_NAME)
+ parser.add_argument("--verbose", action="store_true")
+ args = parser.parse_args()
+
+ if not env.is_windows():
+ print(
+ f"{colors.ERROR_TEXT} This script is only supported on Windows",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ context = Context(args.verbose)
+
+ try:
+ if args.reinstall:
+ reinstall(context, args.source_dir, args.target_dir, args.bin_name)
+ elif args.stop:
+ stop(context, args.target_dir)
+ elif args.restart:
+ restart(context, args.source_dir, args.target_dir)
+ else:
+ print("No action specified", file=sys.stderr)
+ exit(1)
+ except Exception as e:
+ print(f"{colors.ERROR_TEXT} {e}", file=sys.stderr)
+
+ if args.pause_on_exit:
+ input("Press enter to continue...")
+
+
+def print_verbose(context, message):
+ if context.verbose:
+ print(message)
+
+
+def ensure_admin():
+ if not windows.is_admin():
+ windows.relaunch_as_admin(__file__)
+ sys.exit()
+
+
+def restart(context, source_dir, target_dir):
+ """Stops the daemon service, copies files, and restarts the daemon service."""
+
+ ensure_admin()
+ stop(context, target_dir)
+ copy_files(source_dir, target_dir)
+ start()
+
+
+def reinstall(context, source_dir, target_dir, bin_name):
+ """Stops and uninstalls daemon service, copies files, and reinstalls the daemon service."""
+
+ ensure_admin()
+ stop(context, target_dir)
+
+ source_bin_path = f"{os.path.join(source_dir, bin_name)}.exe"
+
+ copy_files(source_dir, target_dir)
+
+ print("Removing old daemon service")
+ try:
+ subprocess.run([source_bin_path, "/uninstall"], shell=True, check=True)
+ except subprocess.CalledProcessError as e:
+ check_access_violation(e.returncode, source_bin_path)
+ if e.returncode != 0:
+ print(
+ f"{colors.WARNING_TEXT} Uninstall failed, return code: {e.returncode}",
+ file=sys.stderr,
+ )
+
+ target_bin_path = os.path.join(target_dir, bin_name + ".exe")
+
+ try:
+ print("Installing daemon service")
+ subprocess.run([target_bin_path, "/install"], shell=True, check=True)
+ except subprocess.CalledProcessError as e:
+ check_access_violation(e.returncode, target_bin_path)
+ if e.returncode != 0:
+ print(f"{colors.WARNING_TEXT} Install failed, return code: {e.returncode}")
+
+
+def copy_files(source_dir, target_dir):
+ options = file_utils.CopyOptions(ignore_errors=True, verbose=False)
+ print(f"Copying files from {source_dir} to {target_dir}")
+ file_utils.copy(f"{source_dir}/*", target_dir, options)
+
+
+def stop(context, target_dir):
+ ensure_admin()
+ print("Stopping daemon service")
+ try:
+ subprocess.run(["net", "stop", "synergy"], shell=True, check=True)
+ except subprocess.CalledProcessError as e:
+ if e.returncode == SERVICE_NOT_RUNNING_ERROR:
+ print_verbose(context, "Daemon service not running")
+ else:
+ raise e
+
+ # Wait for Windows to release the file handles after process termination.
+ wait_for_stop(context, target_dir)
+
+
+def start():
+ ensure_admin()
+ print("Starting daemon service")
+ subprocess.run(["net", "start", "synergy"], shell=True, check=True)
+
+
+def wait_for_stop(context, target_dir):
+ if is_any_process_running(context, target_dir):
+ print("Waiting for file handles to release...", end="", flush=True)
+ while is_any_process_running(context, target_dir):
+ if not context.verbose:
+ print(".", end="", flush=True)
+ time.sleep(1)
+ if not context.verbose:
+ print()
+
+
+def check_access_violation(return_code, bin_path):
+ if return_code == ERROR_ACCESS_VIOLATION:
+ print(
+ f"{colors.WARNING_TEXT} Process crashed with memory access violation: {bin_path}",
+ file=sys.stderr,
+ )
+
+
+def is_ignored_process(exe):
+ for ignore_process in IGNORE_PROCESSES:
+ if exe.endswith(ignore_process):
+ return True
+ return False
+
+
+def is_any_process_running(context, dir):
+ """Check if there is any running process that contains the given directory."""
+
+ print_verbose(context, f"Checking if any process is running in: {dir}")
+
+ for proc in psutil.process_iter(attrs=["name", "exe"]):
+ exe = proc.info["exe"]
+
+ if not exe:
+ print_verbose(context, f"Skipping process with no exe: {proc}")
+ continue
+
+ if is_ignored_process(exe):
+ print_verbose(context, f"Ignoring process: {exe}")
+ continue
+
+ try:
+ if dir.lower() in exe.lower():
+ print_verbose(context, f"Process found: {exe}")
+ return True
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
+ pass
+
+ return False
+
+
+main()
diff --git a/scripts/fancy_copy.py b/scripts/fancy_copy.py
index 3d6e69a43..b6490efc7 100644
--- a/scripts/fancy_copy.py
+++ b/scripts/fancy_copy.py
@@ -3,6 +3,7 @@
import argparse
import lib.env as env
import lib.file_utils as file_utils
+import lib.colors as colors
def main():
@@ -34,7 +35,7 @@ def main():
if not args.ignore_errors:
raise e
else:
- print(f"Error: {e}")
+ print(f"{colors.ERROR_TEXT} {e}")
if __name__ == "__main__":
diff --git a/scripts/lib/colors.py b/scripts/lib/colors.py
new file mode 100644
index 000000000..64956cf4d
--- /dev/null
+++ b/scripts/lib/colors.py
@@ -0,0 +1,8 @@
+import colorama # type: ignore
+from colorama import Fore # type: ignore
+
+colorama.init()
+
+ERROR_TEXT = f"{Fore.RED}Error:{Fore.RESET}"
+WARNING_TEXT = f"{Fore.YELLOW}Warning:{Fore.RESET}"
+HINT_TEXT = f"{Fore.LIGHTBLUE_EX}Hint:{Fore.RESET}"
diff --git a/scripts/lib/file_utils.py b/scripts/lib/file_utils.py
index 278c0cfae..9b4a04c79 100644
--- a/scripts/lib/file_utils.py
+++ b/scripts/lib/file_utils.py
@@ -1,9 +1,6 @@
import glob, os, shutil, sys
-
-import colorama # type: ignore
-from colorama import Fore # type: ignore
-
-colorama.init()
+import lib.env as env
+import lib.colors as colors
class CopyOptions:
@@ -24,24 +21,24 @@ def copy(source, target, options):
context = CopyContext()
if options.verbose:
print(f"Copying files from {source} to {target}")
- for match in glob.glob(source):
- if os.path.isfile(match):
- copy_file(match, target, options, context)
- elif os.path.isdir(match):
- copy_dir(match, target, options, context)
- else:
- raise RuntimeError(f"Path {match} is not a file or directory")
+ try:
+ for match in glob.glob(source):
- if context.errors and options.ignore_errors:
- print(
- f"{Fore.YELLOW}WARNING:{Fore.RESET} Ignored {context.errors} copy error(s)"
- )
+ if os.path.isfile(match):
+ copy_file(match, target, options, context)
+ elif os.path.isdir(match):
+ copy_dir(match, target, options, context)
+ else:
+ raise RuntimeError(f"Path {match} is not a file or directory")
+ finally:
+ if context.errors and options.ignore_errors:
+ print(f"{colors.WARNING_TEXT} Ignored {context.errors} copy error(s)")
- if context.permission_error:
- print(
- f"{Fore.BLUE}HINT:{Fore.RESET} A permission error may mean that the file is in use"
- )
+ if context.permission_error and env.is_windows():
+ print(
+ f"{colors.HINT_TEXT} A Windows file permission error may mean that the file is in use"
+ )
def copy_dir(match, target, options, context):
@@ -50,12 +47,8 @@ def copy_dir(match, target, options, context):
try:
shutil.copytree(match, target, dirs_exist_ok=True)
-
- except PermissionError as e:
- context.permission_error = True
- handle_copy_error(e, options, context)
except Exception as e:
- handle_copy_error(e, options, context)
+ handle_all_copy_errors(e, options, context)
def copy_file(match, target, options, context):
@@ -64,17 +57,33 @@ def copy_file(match, target, options, context):
try:
shutil.copy(match, target)
- except PermissionError as e:
- context.permission_error = True
- handle_copy_error(e, options, context)
except Exception as e:
- handle_copy_error(e, options, context)
+ handle_all_copy_errors(e, options, context)
-def handle_copy_error(e, options, context):
- context.errors += 1
+def handle_all_copy_errors(error, options, context):
+
+ if isinstance(error, shutil.Error):
+ for _, _, file_error in error.args[0]:
+ handle_copy_error(file_error, options, context)
+ else:
+ handle_copy_error(error, options, context)
if not options.ignore_errors:
- raise e
- else:
- print(f"{Fore.YELLOW}WARNING:{Fore.RESET} Copy failed: {e}", file=sys.stderr)
+ raise error
+
+
+def handle_copy_error(error, options, context):
+ if isinstance(error, PermissionError):
+ context.permission_error = True
+
+ if isinstance(error, str):
+ context.permission_error = error.startswith("[Errno 13] Permission denied")
+
+ context.errors += 1
+
+ if options.ignore_errors:
+ print(
+ f"{colors.WARNING_TEXT} Copy failed: {error}",
+ file=sys.stderr,
+ )
diff --git a/scripts/windows_daemon.py b/scripts/windows_daemon.py
deleted file mode 100644
index daf36a1d0..000000000
--- a/scripts/windows_daemon.py
+++ /dev/null
@@ -1,112 +0,0 @@
-import os, sys, time, subprocess, argparse, glob
-import lib.windows as windows
-import lib.file_utils as file_utils
-import psutil
-
-DEFAULT_BIN_NAME = "synergyd"
-DEFAULT_SOURCE_DIR = os.path.join("build", "temp", "bin")
-DEFAULT_TARGET_DIR = os.path.join("build", "bin")
-SERVICE_NOT_RUNNING_ERROR = 2
-ERROR_ACCESS_VIOLATION = 0xC0000005
-
-
-def main():
- """Entry point for the script."""
-
- parser = argparse.ArgumentParser()
- parser.add_argument("--pause-on-exit", action="store_true")
- parser.add_argument("--source-dir", default=DEFAULT_SOURCE_DIR)
- parser.add_argument("--target-dir", default=DEFAULT_TARGET_DIR)
- parser.add_argument("--bin-name", default=DEFAULT_BIN_NAME)
- args = parser.parse_args()
-
- if not windows.is_admin():
- windows.relaunch_as_admin(__file__)
- sys.exit()
-
- try:
- reinstall(
- args.source_dir,
- args.target_dir,
- args.bin_name,
- )
- except Exception as e:
- print(f"Error: {e}", file=sys.stderr)
-
- if args.pause_on_exit:
- input("Press enter to continue...")
-
-
-def reinstall(source_dir, target_dir, bin_name):
- """Stops the running daemon service, copies files, and reinstalls."""
-
- print("Stopping daemon service")
- try:
- subprocess.run(["net", "stop", "synergy"], shell=True, check=True)
- except subprocess.CalledProcessError as e:
- if e.returncode == SERVICE_NOT_RUNNING_ERROR:
- print("Daemon service not running")
- else:
- raise e
-
- source_bin_path = f"{os.path.join(source_dir, bin_name)}.exe"
-
- # Wait for Windows to release the file handles after process termination.
- while is_any_process_running(target_dir):
- print("Waiting for file handles to release")
- time.sleep(1)
-
- options = file_utils.CopyOptions(ignore_errors=True, verbose=False)
- print(f"Copying files from {source_dir} to {target_dir}")
- file_utils.copy(f"{source_dir}/*", target_dir, options)
-
- print("Removing old daemon service")
- try:
- subprocess.run([source_bin_path, "/uninstall"], shell=True, check=True)
- except subprocess.CalledProcessError as e:
- check_access_violation(e.returncode, source_bin_path)
- if e.returncode != 0:
- print(
- f"Warning: Uninstall failed, return code: {e.returncode}",
- file=sys.stderr,
- )
-
- target_bin_path = os.path.join(target_dir, bin_name + ".exe")
-
- try:
- print("Installing daemon service")
- subprocess.run([target_bin_path, "/install"], shell=True, check=True)
- except subprocess.CalledProcessError as e:
- check_access_violation(e.returncode, target_bin_path)
- if e.returncode != 0:
- print(f"Warning: Install failed, return code: {e.returncode}")
-
-
-def check_access_violation(return_code, bin_path):
- if return_code == ERROR_ACCESS_VIOLATION:
- print(
- f"Warning: Process crashed with memory access violation: {bin_path}",
- file=sys.stderr,
- )
-
-
-def is_any_process_running(dir):
- """Check if there is any running process that contains the given directory."""
-
- print(f"Checking if any process is running in: {dir}")
- for proc in psutil.process_iter(attrs=["name", "exe"]):
- exe = proc.info["exe"]
-
- if not exe:
- continue
-
- try:
- if dir.lower() in exe.lower():
- print(f"Process found: {exe}")
- return True
- except (psutil.NoSuchProcess, psutil.AccessDenied):
- pass
- return False
-
-
-main()
diff --git a/src/gui/src/AboutDialog.cpp b/src/gui/src/AboutDialog.cpp
index 03f3adc93..c06a4fab7 100644
--- a/src/gui/src/AboutDialog.cpp
+++ b/src/gui/src/AboutDialog.cpp
@@ -24,7 +24,7 @@ AboutDialog::AboutDialog(MainWindow *parent, const AppConfig &config)
Ui::AboutDialogBase() {
setupUi(this);
- m_versionChecker.setApp(parent->appPath(config.synergycName()));
+ m_versionChecker.setApp(parent->appPath(config.coreClientName()));
QString version = SYNERGY_VERSION;
#ifdef GIT_SHA_SHORT
diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp
index c119be711..f2cabf067 100644
--- a/src/gui/src/ActivationDialog.cpp
+++ b/src/gui/src/ActivationDialog.cpp
@@ -1,17 +1,31 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2016 Synergy Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file LICENSE that should have accompanied this file.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
#include "ActivationDialog.h"
-#include "ActivationNotifier.h"
#include "AppConfig.h"
#include "CancelActivationDialog.h"
-#include "FailedLoginDialog.h"
#include "LicenseManager.h"
#include "MainWindow.h"
-#include "QUtility.h"
+#include "shared/EditionType.h"
#include "ui_ActivationDialog.h"
-#include
+#include
#include
#include
-#include
ActivationDialog::ActivationDialog(
QWidget *parent, AppConfig &appConfig, LicenseManager &licenseManager)
@@ -38,15 +52,18 @@ void ActivationDialog::refreshSerialKey() {
ActivationDialog::~ActivationDialog() { delete ui; }
void ActivationDialog::reject() {
- if (m_LicenseManager->activeEdition() == kUnregistered) {
- CancelActivationDialog cancelActivationDialog(this);
- if (QDialog::Accepted == cancelActivationDialog.exec()) {
- m_LicenseManager->skipActivation();
- } else {
- return;
- }
+ // don't show the cancel confirmation dialog if they've already registered,
+ // since it's not revent to customers who are changing their serial key.
+ if (m_LicenseManager->activeEdition() != kUnregistered) {
+ QDialog::reject();
+ return;
+ }
+
+ // the user is told that the 'No' button will exit the app.
+ CancelActivationDialog cancelActivationDialog(this);
+ if (cancelActivationDialog.exec() == QDialog::Rejected) {
+ QApplication::exit();
}
- QDialog::reject();
}
void ActivationDialog::accept() {
@@ -82,7 +99,7 @@ void ActivationDialog::accept() {
.arg((daysLeft == 1) ? "" : "s")
.arg((daysLeft == 1) ? "s" : "");
- if (m_appConfig->isCryptoAvailable()) {
+ if (m_appConfig->cryptoAvailable()) {
m_appConfig->generateCertificate();
thanksMessage =
thanksMessage.arg("If you're using SSL, "
diff --git a/src/gui/src/ActivationDialog.h b/src/gui/src/ActivationDialog.h
index b752d1fc6..ff50ebe56 100644
--- a/src/gui/src/ActivationDialog.h
+++ b/src/gui/src/ActivationDialog.h
@@ -1,5 +1,21 @@
-#ifndef ACTIVATIONDIALOG_H
-#define ACTIVATIONDIALOG_H
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2016 Synergy 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 .
+ */
+
+#pragma once
#include
#include
@@ -30,5 +46,3 @@ private:
AppConfig *m_appConfig;
LicenseManager *m_LicenseManager;
};
-
-#endif // ACTIVATIONDIALOG_H
diff --git a/src/gui/src/ActivationDialog.ui b/src/gui/src/ActivationDialog.ui
index 7180b7757..e89c2ac91 100644
--- a/src/gui/src/ActivationDialog.ui
+++ b/src/gui/src/ActivationDialog.ui
@@ -6,8 +6,8 @@
0
0
- 410
- 211
+ 477
+ 241
@@ -18,7 +18,6 @@
- 75
true
@@ -30,7 +29,7 @@
-
- <html><head/><body><p>This can be found on your <a href="https://symless.com/synergy/account?source=gui"><span style=" text-decoration: none; color: #4285F4;">account</span></a> page.</p></body></html>
+ <html><head/><body><p>Your serial key is on your <a href="https://symless.com/synergy/account?source=gui"><span style=" text-decoration: underline; color:#4285f4;">account</span></a> page. Don't have a license? <a href="https://symless.com/synergy/purchase?source=gui"><span style=" text-decoration: underline; color:#007af4;">Purchase Synergy</span></a></p></body></html>
true
@@ -47,9 +46,12 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;">
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p></body></html>
diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp
index f5e844a17..e095b0c1f 100644
--- a/src/gui/src/AppConfig.cpp
+++ b/src/gui/src/AppConfig.cpp
@@ -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
@@ -18,32 +18,35 @@
#include "AppConfig.h"
-#include "ConfigWriter.h"
+#include "Config.h"
#include "SslCertificate.h"
+#include
#include
#include
#include
#include
+#include
+
+using synergy::gui::Config;
+
+// this should be incremented each time the wizard is changed,
+// which will force it to re-run for existing installations.
+const int kWizardVersion = 8;
-using GUI::Config::ConfigWriter;
#if defined(Q_OS_WIN)
-const char AppConfig::m_SynergysName[] = "synergys.exe";
-const char AppConfig::m_SynergycName[] = "synergyc.exe";
-const char AppConfig::m_SynergyLogDir[] = "log/";
-const char AppConfig::m_SynergyConfigName[] = "synergy.sgc";
-const ProcessMode kDefaultProcessMode = ProcessMode::kService;
+const char AppConfig::m_CoreServerName[] = "synergys.exe";
+const char AppConfig::m_CoreClientName[] = "synergyc.exe";
+const char AppConfig::m_LogDir[] = "log/";
+const char AppConfig::m_ConfigFilename[] = "synergy.sgc";
#else
-const char AppConfig::m_SynergysName[] = "synergys";
-const char AppConfig::m_SynergycName[] = "synergyc";
-const char AppConfig::m_SynergyLogDir[] = "/var/log/";
-const char AppConfig::m_SynergyConfigName[] = "synergy.conf";
-const ProcessMode kDefaultProcessMode = ProcessMode::kDesktop;
+const char AppConfig::m_CoreServerName[] = "synergys";
+const char AppConfig::m_CoreClientName[] = "synergyc";
+const char AppConfig::m_LogDir[] = "/var/log/";
+const char AppConfig::m_ConfigFilename[] = "synergy.conf";
#endif
-const ElevateMode kDefaultElevateMode = ElevateAsNeeded;
-
-const char *AppConfig::m_SynergySettingsName[] = {
+const char *const AppConfig::m_SettingsName[] = {
"screenName",
"port",
"interface",
@@ -80,55 +83,38 @@ const char *AppConfig::m_SynergySettingsName[] = {
"licenseNextCheck",
"initiateConnectionFromServer",
"clientHostMode",
- "serverClientMode"};
+ "serverClientMode",
+ "serviceEnabled",
+ "minimizeOnClose"};
static const char *logLevelNames[] = {"INFO", "DEBUG", "DEBUG1", "DEBUG2"};
-AppConfig::AppConfig(bool globalLoad)
- : m_ScreenName(),
- m_Port(24800),
- m_Interface(),
- m_LogLevel(0),
- m_LogToFile(),
- m_WizardLastRun(0),
- m_ProcessMode(kDefaultProcessMode),
- m_StartedBefore(),
- m_ElevateMode(kDefaultElevateMode),
- m_Edition(kUnregistered),
- m_CryptoEnabled(false),
- m_AutoHide(false),
- m_LastExpiringWarningTime(0),
- m_ActivationHasRun(),
- m_MinimizeToTray(false),
- m_ServerGroupChecked(),
- m_UseExternalConfig(),
- m_UseInternalConfig(),
- m_ClientGroupChecked(),
- m_LoadFromSystemScope() {
+AppConfig::AppConfig() {
+ m_Config.registerReceiever(this);
+ load();
+}
- auto writer = ConfigWriter::make();
-
- // Register this class to receive global load and saves
- writer->registerClass(this);
-
- // HACK: enable global load by default but allow it to be disabled for tests.
- // when run in a test environment, this function causes a segfault.
- if (globalLoad) {
- writer->globalLoad();
- }
+void AppConfig::load() {
+ m_Config.loadAll();
// User settings exist and the load from system scope variable is true
- if (writer->hasSetting(
- settingName(Setting::kLoadSystemSettings), ConfigWriter::kUser)) {
+ if (m_Config.hasSetting(
+ settingName(Setting::kLoadSystemSettings), Config::Scope::User)) {
setLoadFromSystemScope(m_LoadFromSystemScope);
}
// If user setting don't exist but system ones do, load the system settings
- else if (writer->hasSetting(
- settingName(Setting::kScreenName), ConfigWriter::kSystem)) {
+ else if (m_Config.hasSetting(
+ settingName(Setting::kScreenName), Config::Scope::System)) {
setLoadFromSystemScope(true);
}
}
+void AppConfig::applyAppSettings() const {
+ QApplication::setQuitOnLastWindowClosed(!m_MinimizeOnClose);
+}
+
+Config &AppConfig::config() { return m_Config; }
+
const QString &AppConfig::screenName() const { return m_ScreenName; }
int AppConfig::port() const { return m_Port; }
@@ -141,18 +127,13 @@ bool AppConfig::logToFile() const { return m_LogToFile; }
const QString &AppConfig::logFilename() const { return m_LogFilename; }
-QString AppConfig::synergyLogDir() const {
+QString AppConfig::logDir() const {
// by default log to home dir
return QDir::home().absolutePath() + "/";
}
-QString AppConfig::synergyProgramDir() const {
- // synergy binaries should be in the same dir.
- return QCoreApplication::applicationDirPath() + "/";
-}
-
-void AppConfig::persistLogDir() {
- QDir dir = synergyLogDir();
+void AppConfig::persistLogDir() const {
+ QDir dir = logDir();
// persist the log directory
if (!dir.exists()) {
@@ -160,18 +141,11 @@ void AppConfig::persistLogDir() {
}
}
-const QString AppConfig::logFilenameCmd() const {
- QString filename = m_LogFilename;
-#if defined(Q_OS_WIN)
- // wrap in quotes in case username contains spaces.
- filename = QString("\"%1\"").arg(filename);
-#endif
- return filename;
-}
-
QString AppConfig::logLevelText() const { return logLevelNames[logLevel()]; }
-ProcessMode AppConfig::processMode() const { return m_ProcessMode; }
+ProcessMode AppConfig::processMode() const {
+ return m_ServiceEnabled ? ProcessMode::kService : ProcessMode::kDesktop;
+}
bool AppConfig::wizardShouldRun() const {
return m_WizardLastRun < kWizardVersion;
@@ -180,141 +154,137 @@ bool AppConfig::wizardShouldRun() const {
bool AppConfig::startedBefore() const { return m_StartedBefore; }
void AppConfig::loadSettings() {
+ using enum AppConfig::Setting;
+
m_ScreenName =
- loadSetting(Setting::kScreenName, QHostInfo::localHostName()).toString();
+ loadSetting(kScreenName, QHostInfo::localHostName()).toString();
if (m_ScreenName.isEmpty()) {
m_ScreenName = QHostInfo::localHostName();
}
- m_Port = loadSetting(Setting::kPort, 24800).toInt();
- m_Interface = loadSetting(Setting::kInterfaceSetting).toString();
- m_LogLevel = loadSetting(Setting::kLogLevel, 0).toInt();
- m_LogToFile = loadSetting(Setting::kLogToFile, false).toBool();
+ m_Port = loadSetting(kPort, 24800).toInt();
+ m_Interface = loadSetting(kInterfaceSetting).toString();
+ m_LogLevel = loadSetting(kLogLevel, 0).toInt();
+ m_LogToFile = loadSetting(kLogToFile, false).toBool();
m_LogFilename =
- loadSetting(Setting::kLogFilename, synergyLogDir() + "synergy.log")
- .toString();
- m_WizardLastRun = loadCommonSetting(Setting::kWizardLastRun, 0).toInt();
- m_StartedBefore = loadSetting(Setting::kStartedBefore, false).toBool();
+ loadSetting(kLogFilename, logDir() + "synergy.log").toString();
+ m_WizardLastRun = loadCommonSetting(kWizardLastRun, 0).toInt();
+ m_StartedBefore = loadSetting(kStartedBefore, false).toBool();
- { // Scope related code together
- // TODO Investigate why kElevateModeEnum isn't loaded fully
- QVariant elevateMode = loadSetting(Setting::kElevateModeEnum);
- if (!elevateMode.isValid()) {
- elevateMode = loadSetting(
- Setting::kElevateModeSetting,
- QVariant(static_cast(kDefaultElevateMode)));
- }
- m_ElevateMode = static_cast(elevateMode.toInt());
+ QVariant elevateMode = loadSetting(kElevateModeEnum);
+ if (!elevateMode.isValid()) {
+ elevateMode = loadSetting(
+ kElevateModeSetting, QVariant(static_cast(kDefaultElevateMode)));
}
+ m_ElevateMode = static_cast(elevateMode.toInt());
- m_ActivateEmail = loadSetting(Setting::kActivateEmail, "").toString();
- m_CryptoEnabled = loadSetting(Setting::kCryptoEnabled, true).toBool();
- m_AutoHide = loadSetting(Setting::kAutoHide, false).toBool();
- m_lastVersion = loadSetting(Setting::kLastVersion, "Unknown").toString();
- m_LastExpiringWarningTime =
- loadSetting(Setting::kLastExpireWarningTime, 0).toInt();
- m_ActivationHasRun = loadSetting(Setting::kActivationHasRun, false).toBool();
- m_MinimizeToTray = loadSetting(Setting::kMinimizeToTray, false).toBool();
+ m_ActivateEmail = loadSetting(kActivateEmail, "").toString();
+ m_CryptoEnabled = loadSetting(kCryptoEnabled, true).toBool();
+ m_AutoHide = loadSetting(kAutoHide, false).toBool();
+ m_LastVersion = loadSetting(kLastVersion, "Unknown").toString();
+ m_LastExpiringWarningTime = loadSetting(kLastExpireWarningTime, 0).toInt();
+ m_ActivationHasRun = loadSetting(kActivationHasRun, false).toBool();
+ m_MinimizeToTray = loadSetting(kMinimizeToTray, false).toBool();
m_LoadFromSystemScope =
- loadCommonSetting(Setting::kLoadSystemSettings, false).toBool();
- m_ServerGroupChecked =
- loadSetting(Setting::kGroupServerCheck, false).toBool();
- m_UseExternalConfig =
- loadSetting(Setting::kUseExternalConfig, false).toBool();
+ loadCommonSetting(kLoadSystemSettings, false).toBool();
+ m_ServerGroupChecked = loadSetting(kGroupServerCheck, false).toBool();
+ m_UseExternalConfig = loadSetting(kUseExternalConfig, false).toBool();
m_ConfigFile =
- loadSetting(
- Setting::kConfigFile, QDir::homePath() + "/" + m_SynergyConfigName)
+ loadSetting(kConfigFile, QDir::homePath() + "/" + m_ConfigFilename)
.toString();
- m_UseInternalConfig =
- loadSetting(Setting::kUseInternalConfig, false).toBool();
- m_ClientGroupChecked =
- loadSetting(Setting::kGroupClientCheck, false).toBool();
- m_ServerHostname = loadSetting(Setting::kServerHostname).toString();
- m_PreventSleep = loadSetting(Setting::kPreventSleep, false).toBool();
- m_LanguageSync = loadSetting(Setting::kLanguageSync, false).toBool();
- m_InvertScrollDirection =
- loadSetting(Setting::kInvertScrollDirection, false).toBool();
- m_guid = loadCommonSetting(Setting::kGuid, QUuid::createUuid()).toString();
- m_licenseRegistryUrl = loadCommonSetting(
- Setting::kLicenseRegistryUrl,
- "https://api2.prod.symless.com/license/register")
- .toString();
- m_licenseNextCheck =
- loadCommonSetting(Setting::kLicenseNextCheck, 0).toULongLong();
- m_ClientHostMode = loadSetting(Setting::kClientHostMode, true).toBool();
- m_ServerClientMode = loadSetting(Setting::kServerClientMode, true).toBool();
+ m_UseInternalConfig = loadSetting(kUseInternalConfig, false).toBool();
+ m_ClientGroupChecked = loadSetting(kGroupClientCheck, 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_Guid = loadCommonSetting(kGuid, QUuid::createUuid()).toString();
+ m_licenseNextCheck = loadCommonSetting(kLicenseNextCheck, 0).toULongLong();
+ m_ClientHostMode = loadSetting(kClientHostMode, true).toBool();
+ m_ServerClientMode = loadSetting(kServerClientMode, true).toBool();
m_InitiateConnectionFromServer =
- loadSetting(Setting::kInitiateConnectionFromServer, false).toBool();
+ loadSetting(kInitiateConnectionFromServer, false).toBool();
// only change the serial key if the settings being loaded contains a key
- bool updateSerial = ConfigWriter::make()->hasSetting(
- settingName(Setting::kLoadSystemSettings), ConfigWriter::kCurrent);
+ bool updateSerial = m_Config.hasSetting(
+ settingName(kLoadSystemSettings), Config::Scope::Current);
// if the setting exists and is not empty
- updateSerial =
- updateSerial &&
- !loadSetting(Setting::kSerialKey, "").toString().trimmed().isEmpty();
+ updateSerial = updateSerial &&
+ !loadSetting(kSerialKey, "").toString().trimmed().isEmpty();
if (updateSerial) {
- m_Serialkey = loadSetting(Setting::kSerialKey, "").toString().trimmed();
+ m_Serialkey = loadSetting(kSerialKey, "").toString().trimmed();
m_Edition = static_cast(
- loadSetting(Setting::kEditionSetting, kUnregistered).toInt());
+ loadSetting(kEditionSetting, kUnregistered).toInt());
}
- // Set the default path of the TLS certificate file in the users DIR
- QString certificateFilename =
- QString("%1/%2/%3")
- .arg(m_CoreInterface.getProfileDir(), "SSL", "Synergy.pem");
+ m_ServiceEnabled = loadSetting(kServiceEnabled, m_ServiceEnabled).toBool();
- m_TLSCertificatePath =
- loadSetting(Setting::kTLSCertPath, certificateFilename).toString();
- m_TLSKeyLength = loadSetting(Setting::kTLSKeyLength, "2048").toString();
+ try {
+ // Set the default path of the TLS certificate file in the users DIR
+ QString certificateFilename =
+ QString("%1/%2/%3")
+ .arg(m_CoreInterface.getProfileDir(), "SSL", "Synergy.pem");
- if (getCryptoEnabled()) {
+ m_TlsCertPath = loadSetting(kTlsCertPath, certificateFilename).toString();
+ m_TlsKeyLength = loadSetting(kTlsKeyLength, "2048").toString();
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
+ qFatal("Failed to get profile dir, unable to configure TLS");
+ }
+
+ if (cryptoEnabled()) {
generateCertificate();
}
+
+ applyAppSettings();
}
void AppConfig::saveSettings() {
- setCommonSetting(Setting::kWizardLastRun, m_WizardLastRun);
- setCommonSetting(Setting::kLoadSystemSettings, m_LoadFromSystemScope);
- setCommonSetting(Setting::kGroupClientCheck, m_ClientGroupChecked);
- setCommonSetting(Setting::kGroupServerCheck, m_ServerGroupChecked);
- setCommonSetting(Setting::kGuid, m_guid);
- setCommonSetting(Setting::kLicenseRegistryUrl, m_licenseRegistryUrl);
- setCommonSetting(Setting::kLicenseNextCheck, m_licenseNextCheck);
+ using enum Setting;
+
+ setCommonSetting(kWizardLastRun, m_WizardLastRun);
+ setCommonSetting(kLoadSystemSettings, m_LoadFromSystemScope);
+ setCommonSetting(kGroupClientCheck, m_ClientGroupChecked);
+ setCommonSetting(kGroupServerCheck, m_ServerGroupChecked);
+ setCommonSetting(kGuid, m_Guid);
+ setCommonSetting(kLicenseNextCheck, m_licenseNextCheck);
if (isWritable()) {
- setSetting(Setting::kScreenName, m_ScreenName);
- setSetting(Setting::kPort, m_Port);
- setSetting(Setting::kInterfaceSetting, m_Interface);
- setSetting(Setting::kLogLevel, m_LogLevel);
- setSetting(Setting::kLogToFile, m_LogToFile);
- setSetting(Setting::kLogFilename, m_LogFilename);
- setSetting(Setting::kStartedBefore, m_StartedBefore);
- // Refer to enum ElevateMode declaration for insight in to why this
- // flag is mapped this way
- setSetting(Setting::kElevateModeSetting, m_ElevateMode == ElevateAlways);
- setSetting(Setting::kElevateModeEnum, static_cast(m_ElevateMode));
- setSetting(Setting::kEditionSetting, m_Edition);
- setSetting(Setting::kCryptoEnabled, m_CryptoEnabled);
- setSetting(Setting::kAutoHide, m_AutoHide);
- setSetting(Setting::kSerialKey, m_Serialkey);
- setSetting(Setting::kLastVersion, m_lastVersion);
- setSetting(Setting::kLastExpireWarningTime, m_LastExpiringWarningTime);
- setSetting(Setting::kActivationHasRun, m_ActivationHasRun);
- setSetting(Setting::kMinimizeToTray, m_MinimizeToTray);
- setSetting(Setting::kUseExternalConfig, m_UseExternalConfig);
- setSetting(Setting::kConfigFile, m_ConfigFile);
- setSetting(Setting::kUseInternalConfig, m_UseInternalConfig);
- setSetting(Setting::kServerHostname, m_ServerHostname);
- setSetting(Setting::kPreventSleep, m_PreventSleep);
- setSetting(Setting::kLanguageSync, m_LanguageSync);
- setSetting(Setting::kInvertScrollDirection, m_InvertScrollDirection);
- setSetting(Setting::kClientHostMode, m_ClientHostMode);
- setSetting(Setting::kServerClientMode, m_ServerClientMode);
+ setSetting(kScreenName, m_ScreenName);
+ setSetting(kPort, m_Port);
+ setSetting(kInterfaceSetting, m_Interface);
+ setSetting(kLogLevel, m_LogLevel);
+ setSetting(kLogToFile, m_LogToFile);
+ setSetting(kLogFilename, m_LogFilename);
+ setSetting(kStartedBefore, m_StartedBefore);
+ setSetting(kElevateModeEnum, static_cast(m_ElevateMode));
+ setSetting(kEditionSetting, m_Edition);
+ setSetting(kCryptoEnabled, m_CryptoEnabled);
+ setSetting(kAutoHide, m_AutoHide);
+ setSetting(kSerialKey, m_Serialkey);
+ setSetting(kLastVersion, m_LastVersion);
+ setSetting(kLastExpireWarningTime, m_LastExpiringWarningTime);
+ setSetting(kActivationHasRun, m_ActivationHasRun);
+ setSetting(kMinimizeToTray, m_MinimizeToTray);
+ setSetting(kUseExternalConfig, m_UseExternalConfig);
+ setSetting(kConfigFile, m_ConfigFile);
+ setSetting(kUseInternalConfig, m_UseInternalConfig);
+ setSetting(kServerHostname, m_ServerHostname);
+ setSetting(kPreventSleep, m_PreventSleep);
+ setSetting(kLanguageSync, m_LanguageSync);
+ setSetting(kInvertScrollDirection, m_InvertScrollDirection);
+ setSetting(kClientHostMode, m_ClientHostMode);
+ setSetting(kServerClientMode, m_ServerClientMode);
+ setSetting(kServiceEnabled, m_ServiceEnabled);
+ setSetting(kMinimizeOnClose, m_MinimizeOnClose);
+
+ // See enum ElevateMode declaration to understand why this setting is bool
+ setSetting(kElevateModeSetting, m_ElevateMode == ElevateAlways);
}
- m_unsavedChanges = false;
+ setModified(false);
+ applyAppSettings();
}
#ifdef SYNERGY_ENABLE_LICENSING
@@ -326,10 +296,10 @@ AppConfig &AppConfig::activationHasRun(bool value) {
}
#endif
-QString AppConfig::lastVersion() const { return m_lastVersion; }
+QString AppConfig::lastVersion() const { return m_LastVersion; }
void AppConfig::setLastVersion(const QString &version) {
- setSettingModified(m_lastVersion, version);
+ setSettingModified(m_LastVersion, version);
}
void AppConfig::setScreenName(const QString &s) {
@@ -389,9 +359,9 @@ void AppConfig::setLastExpiringWarningTime(int newValue) {
}
#endif
-QString AppConfig::synergysName() const { return m_SynergysName; }
+QString AppConfig::coreServerName() const { return m_CoreServerName; }
-QString AppConfig::synergycName() const { return m_SynergycName; }
+QString AppConfig::coreClientName() const { return m_CoreClientName; }
ElevateMode AppConfig::elevateMode() { return m_ElevateMode; }
@@ -404,7 +374,7 @@ void AppConfig::setCryptoEnabled(bool newValue) {
setSettingModified(m_CryptoEnabled, newValue);
}
-bool AppConfig::isCryptoAvailable() const {
+bool AppConfig::cryptoAvailable() const {
bool result{true};
#ifdef SYNERGY_ENABLE_LICENSING
@@ -416,19 +386,19 @@ bool AppConfig::isCryptoAvailable() const {
return result;
}
-bool AppConfig::getCryptoEnabled() const {
- return isCryptoAvailable() && m_CryptoEnabled;
+bool AppConfig::cryptoEnabled() const {
+ return cryptoAvailable() && m_CryptoEnabled;
}
void AppConfig::setAutoHide(bool b) { setSettingModified(m_AutoHide, b); }
-bool AppConfig::getAutoHide() { return m_AutoHide; }
+bool AppConfig::autoHide() { return m_AutoHide; }
void AppConfig::setMinimizeToTray(bool newValue) {
setSettingModified(m_MinimizeToTray, newValue);
}
-bool AppConfig::getInvertScrollDirection() const {
+bool AppConfig::invertScrollDirection() const {
return m_InvertScrollDirection;
}
@@ -436,17 +406,13 @@ void AppConfig::setLicenseNextCheck(unsigned long long time) {
setSettingModified(m_licenseNextCheck, time);
}
-const QString &AppConfig::getLicenseRegistryUrl() const {
- return m_licenseRegistryUrl;
-}
-
-unsigned long long AppConfig::getLicenseNextCheck() const {
+unsigned long long AppConfig::licenseNextCheck() const {
return m_licenseNextCheck;
}
-const QString &AppConfig::getGuid() const { return m_guid; }
+const QString &AppConfig::guid() const { return m_Guid; }
-bool AppConfig::getLanguageSync() const { return m_LanguageSync; }
+bool AppConfig::languageSync() const { return m_LanguageSync; }
void AppConfig::setInvertScrollDirection(bool newValue) {
setSettingModified(m_InvertScrollDirection, newValue);
@@ -456,17 +422,17 @@ void AppConfig::setLanguageSync(bool newValue) {
setSettingModified(m_LanguageSync, newValue);
}
-bool AppConfig::getPreventSleep() const { return m_PreventSleep; }
+bool AppConfig::preventSleep() const { return m_PreventSleep; }
-bool AppConfig::getClientHostMode() const {
- return (m_ClientHostMode && getInitiateConnectionFromServer());
+bool AppConfig::clientHostMode() const {
+ return (m_ClientHostMode && initiateConnectionFromServer());
}
-bool AppConfig::getServerClientMode() const {
- return (m_ServerClientMode && getInitiateConnectionFromServer());
+bool AppConfig::serverClientMode() const {
+ return (m_ServerClientMode && initiateConnectionFromServer());
}
-bool AppConfig::getInitiateConnectionFromServer() const {
+bool AppConfig::initiateConnectionFromServer() const {
return m_InitiateConnectionFromServer;
}
@@ -474,57 +440,53 @@ void AppConfig::setPreventSleep(bool newValue) {
setSettingModified(m_PreventSleep, newValue);
}
-bool AppConfig::getMinimizeToTray() { return m_MinimizeToTray; }
+bool AppConfig::minimizeToTray() { return m_MinimizeToTray; }
QString AppConfig::settingName(Setting name) {
auto index = static_cast(name);
- return m_SynergySettingsName[index];
+ return m_SettingsName[index];
}
template void AppConfig::setSetting(Setting name, T value) {
- ConfigWriter::make()->setSetting(settingName(name), value);
+ m_Config.setSetting(settingName(name), value);
}
template void AppConfig::setCommonSetting(Setting name, T value) {
- ConfigWriter::make()->setSetting(
- settingName(name), value, ConfigWriter::kUser);
- ConfigWriter::make()->setSetting(
- settingName(name), value, ConfigWriter::kSystem);
+ m_Config.setSetting(settingName(name), value, Config::Scope::User);
+ m_Config.setSetting(settingName(name), value, Config::Scope::System);
}
QVariant AppConfig::loadSetting(Setting name, const QVariant &defaultValue) {
- return ConfigWriter::make()->loadSetting(settingName(name), defaultValue);
+ return m_Config.loadSetting(settingName(name), defaultValue);
}
QVariant
AppConfig::loadCommonSetting(Setting name, const QVariant &defaultValue) const {
QVariant result(defaultValue);
QString setting(settingName(name));
- auto &writer = *ConfigWriter::make();
- if (writer.hasSetting(setting)) {
- result = writer.loadSetting(setting, defaultValue);
- } else if (writer.getScope() == ConfigWriter::kSystem) {
- if (writer.hasSetting(setting, ConfigWriter::kUser)) {
- result = writer.loadSetting(setting, defaultValue, ConfigWriter::kUser);
+ 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);
}
- } else if (writer.hasSetting(setting, ConfigWriter::kSystem)) {
- result = writer.loadSetting(setting, defaultValue, ConfigWriter::kSystem);
+ } else if (m_Config.hasSetting(setting, Config::Scope::System)) {
+ result = m_Config.loadSetting(setting, defaultValue, Config::Scope::System);
}
return result;
}
-void AppConfig::loadScope(ConfigWriter::Scope scope) {
- auto writer = ConfigWriter::make();
+void AppConfig::loadScope(Config::Scope scope) {
- if (writer->getScope() != scope) {
+ if (m_Config.getScope() != scope) {
setDefaultValues();
- writer->setScope(scope);
- if (writer->hasSetting(
- settingName(Setting::kScreenName), writer->getScope())) {
+ m_Config.setScope(scope);
+ if (m_Config.hasSetting(
+ settingName(Setting::kScreenName), m_Config.getScope())) {
// If the user already has settings, then load them up now.
- writer->globalLoad();
+ m_Config.loadAll();
}
}
}
@@ -534,9 +496,9 @@ void AppConfig::setDefaultValues() { m_InitiateConnectionFromServer = false; }
void AppConfig::setLoadFromSystemScope(bool value) {
if (value) {
- loadScope(ConfigWriter::kSystem);
+ loadScope(Config::Scope::System);
} else {
- loadScope(ConfigWriter::kUser);
+ loadScope(Config::Scope::User);
}
/*
@@ -546,25 +508,23 @@ void AppConfig::setLoadFromSystemScope(bool value) {
m_LoadFromSystemScope = value;
}
-bool AppConfig::isWritable() const {
- return ConfigWriter::make()->isWritable();
-}
+bool AppConfig::isWritable() const { return m_Config.isWritable(); }
bool AppConfig::isSystemScoped() const {
- return ConfigWriter::make()->getScope() == ConfigWriter::kSystem;
+ return m_Config.getScope() == Config::Scope::System;
}
-bool AppConfig::getServerGroupChecked() const { return m_ServerGroupChecked; }
+bool AppConfig::serverGroupChecked() const { return m_ServerGroupChecked; }
-bool AppConfig::getUseExternalConfig() const { return m_UseExternalConfig; }
+bool AppConfig::useExternalConfig() const { return m_UseExternalConfig; }
-const QString &AppConfig::getConfigFile() const { return m_ConfigFile; }
+const QString &AppConfig::configFile() const { return m_ConfigFile; }
-bool AppConfig::getUseInternalConfig() const { return m_UseInternalConfig; }
+bool AppConfig::useInternalConfig() const { return m_UseInternalConfig; }
-bool AppConfig::getClientGroupChecked() const { return m_ClientGroupChecked; }
+bool AppConfig::clientGroupChecked() const { return m_ClientGroupChecked; }
-QString AppConfig::getServerHostname() const { return m_ServerHostname; }
+QString AppConfig::serverHostname() const { return m_ServerHostname; }
void AppConfig::setServerGroupChecked(bool newValue) {
setSettingModified(m_ServerGroupChecked, newValue);
@@ -602,28 +562,43 @@ template
void AppConfig::setSettingModified(T &variable, const T &newValue) {
if (variable != newValue) {
variable = newValue;
- m_unsavedChanges = true;
+ setModified(true);
}
}
-void AppConfig::setTLSCertPath(const QString &path) {
- m_TLSCertificatePath = path;
-}
+void AppConfig::setTlsCertPath(const QString &path) { m_TlsCertPath = path; }
-QString AppConfig::getTLSCertPath() const { return m_TLSCertificatePath; }
+QString AppConfig::tlsCertPath() const { return m_TlsCertPath; }
-QString AppConfig::getTLSKeyLength() const { return m_TLSKeyLength; }
+QString AppConfig::tlsKeyLength() const { return m_TlsKeyLength; }
-void AppConfig::setTLSKeyLength(const QString &length) {
- if (m_TLSKeyLength != length) {
- m_TLSKeyLength = length;
+void AppConfig::setTlsKeyLength(const QString &length) {
+ if (m_TlsKeyLength != length) {
+ m_TlsKeyLength = length;
generateCertificate(true);
}
}
void AppConfig::generateCertificate(bool forceGeneration) const {
- SslCertificate sslCertificate;
- sslCertificate.generateCertificate(
- getTLSCertPath(), getTLSKeyLength(), forceGeneration);
- emit sslToggled();
+ try {
+ SslCertificate sslCertificate;
+ sslCertificate.generateCertificate(
+ tlsCertPath(), tlsKeyLength(), forceGeneration);
+ emit sslToggled();
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
+ qFatal("Failed to configure TLS");
+ }
}
+
+void AppConfig::setServiceEnabled(bool enabled) {
+ setSettingModified(m_ServiceEnabled, enabled);
+}
+
+bool AppConfig::serviceEnabled() const { return m_ServiceEnabled; }
+
+void AppConfig::setMinimizeOnClose(bool minimize) {
+ setSettingModified(m_MinimizeOnClose, minimize);
+}
+
+bool AppConfig::minimizeOnClose() const { return m_MinimizeOnClose; }
diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h
index d66c50f9b..72124fba0 100644
--- a/src/gui/src/AppConfig.h
+++ b/src/gui/src/AppConfig.h
@@ -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,165 +16,122 @@
* along with this program. If not, see .
*/
-#if !defined(APPCONFIG_H)
+#pragma once
-#define APPCONFIG_H
-
-#include "ConfigBase.h"
-#include "ConfigWriter.h"
+#include "CommonConfig.h"
+#include "Config.h"
#include "CoreInterface.h"
#include "ElevateMode.h"
+#include "LicenseManager.h"
+#include "shared/EditionType.h"
+
#include
#include
#include
#include
-#include
-
-// this should be incremented each time a new page is added. this is
-// saved to settings when the user finishes running the wizard. if
-// the saved wizard version is lower than this number, the wizard
-// will be displayed. each version incrememnt should be described
-// here...
-//
-// 1: first version
-// 2: added language page
-// 3: added premium page and removed
-// 4: ssl plugin 'ns' v1.0
-// 5: ssl plugin 'ns' v1.1
-// 6: ssl plugin 'ns' v1.2
-// 7: serial key activation
-// 8: Visual Studio 2015 support
-//
-const int kWizardVersion = 8;
class QSettings;
class SettingsDialog;
-class ServerConfig;
class LicenseRegister;
+class ServerConfig;
+class LicenseManager;
+class ActivationDialog;
+class LicenseRegistry;
enum class ProcessMode { kService, kDesktop };
-class AppConfig : public QObject, public GUI::Config::ConfigBase {
+const ElevateMode kDefaultElevateMode = ElevateAsNeeded;
+
+#if defined(Q_OS_WIN)
+const ProcessMode kDefaultProcessMode = ProcessMode::kService;
+#else
+const ProcessMode kDefaultProcessMode = ProcessMode::kDesktop;
+#endif
+
+/// @brief Reads and writes application specific settings
+class AppConfig : public QObject, public synergy::gui::CommonConfig {
Q_OBJECT
friend class SettingsDialog;
friend class MainWindow;
friend class SetupWizard;
friend class ServerConfig;
+ friend class LicenseManager;
+ friend class ActivationDialog;
+ friend class LicenseRegistry;
public:
- explicit AppConfig(bool globalLoad = true);
+ explicit AppConfig();
+
+ /// @brief Underlying configuration reader/writer
+ synergy::gui::Config &config();
+
+ void saveSettings() override;
+ void applyAppSettings() const;
+
+ /// @brief Generates TLS certificate
+ /// @param [in] bool forceGeneration Generate certificate even if it's exists.
+ void generateCertificate(bool forceGeneration = false) const;
+
+ /**
+ * Getters
+ */
bool isWritable() const;
bool isSystemScoped() const;
-
const QString &screenName() const;
int port() const;
const QString &networkInterface() const;
int logLevel() const;
bool logToFile() const;
const QString &logFilename() const;
- const QString logFilenameCmd() const;
QString logLevelText() const;
ProcessMode processMode() const;
bool wizardShouldRun() const;
bool startedBefore() const;
-
-#ifdef SYNERGY_ENABLE_LICENSING
- void setEdition(Edition);
- Edition edition() const;
- void setSerialKey(const QString &serial);
- void clearSerialKey();
- QString serialKey() const;
- int lastExpiringWarningTime() const;
- void setLastExpiringWarningTime(int t);
-#endif
-
- QString synergysName() const;
- QString synergycName() const;
- QString synergyProgramDir() const;
- QString synergyLogDir() const;
-
- void persistLogDir();
+ QString coreServerName() const;
+ QString coreClientName() const;
+ QString logDir() const;
+ void persistLogDir() const;
ElevateMode elevateMode();
-
- bool isCryptoAvailable() const;
- void setCryptoEnabled(bool e);
- bool getCryptoEnabled() const;
-
- void setAutoHide(bool b);
- bool getAutoHide();
- void setInvertScrollDirection(bool b);
- bool getInvertScrollDirection() const;
- void setLicenseNextCheck(unsigned long long);
- const QString &getLicenseRegistryUrl() const;
- unsigned long long getLicenseNextCheck() const;
- const QString &getGuid() const;
- void setLanguageSync(bool b);
- bool getLanguageSync() const;
- void setPreventSleep(bool b);
- bool getPreventSleep() const;
- bool getClientHostMode() const;
- bool getServerClientMode() const;
- bool getInitiateConnectionFromServer() const;
-#ifdef SYNERGY_ENABLE_LICENSING
- bool activationHasRun() const;
- AppConfig &activationHasRun(bool value);
-#endif
- /// @brief Sets the user preference to load from SystemScope.
- /// @param [in] value
- /// True - This will set the variable and load the global scope
- /// settings. False - This will set the variable and load the user
- /// scope settings.
- void setLoadFromSystemScope(bool value);
-
- bool getServerGroupChecked() const;
- bool getUseExternalConfig() const;
- const QString &getConfigFile() const;
- bool getUseInternalConfig() const;
- bool getClientGroupChecked() const;
- QString getServerHostname() const;
+ bool cryptoAvailable() const;
+ bool cryptoEnabled() const;
+ bool autoHide();
+ bool invertScrollDirection() const;
+ unsigned long long licenseNextCheck() const;
+ const QString &guid() const;
+ bool languageSync() const;
+ bool preventSleep() const;
+ bool clientHostMode() const;
+ bool serverClientMode() const;
+ bool initiateConnectionFromServer() const;
+ bool serverGroupChecked() const;
+ bool useExternalConfig() const;
+ const QString &configFile() const;
+ bool useInternalConfig() const;
+ bool clientGroupChecked() const;
+ QString serverHostname() const;
+ QString lastVersion() const;
+ bool serviceEnabled() const;
+ bool minimizeToTray();
+ bool minimizeOnClose() const;
/// @brief Gets the current TLS certificate path
/// @return QString The path to the cert
- QString getTLSCertPath() const;
+ QString tlsCertPath() const;
/// @brief Get the key length to be used for the private key of a TLS cert
/// @return QString The key length in bits
- QString getTLSKeyLength() const;
+ QString tlsKeyLength() const;
- void setServerGroupChecked(bool);
- void setUseExternalConfig(bool);
- void setConfigFile(const QString &);
- void setUseInternalConfig(bool);
- void setClientGroupChecked(bool);
- void setServerHostname(const QString &);
- void setClientHostMode(bool newValue);
- void setServerClientMode(bool newValue);
-
- /// @brief Set the path to the TLS/SSL certificate file that will be used
- /// @param [in] path The path to the Certificate
- void setTLSCertPath(const QString &path);
-
- /// @brief Sets the key length of the private key to use in a TLS connection
- /// @param [in] QString length The key length eg: 1024, 2048, 4096
- void setTLSKeyLength(const QString &length);
-
- QString lastVersion() const;
-
- void setMinimizeToTray(bool b);
- bool getMinimizeToTray();
-
- void saveSettings() override;
- void setLastVersion(const QString &version);
-
- /// @brief Generates TLS certificate
- /// @param [in] bool forceGeneration Generate certificate even if it's exists.
- void generateCertificate(bool forceGeneration = false) const;
+#ifdef SYNERGY_ENABLE_LICENSING
+ Edition edition() const;
+ QString serialKey() const;
+ int lastExpiringWarningTime() const;
+ bool activationHasRun() const;
+#endif
protected:
- /// @brief The enumeration to easily access the names of the setting inside
- /// m_SynergySettingsName
enum class Setting {
kScreenName,
kPort,
@@ -202,8 +159,8 @@ protected:
kUseInternalConfig,
kGroupClientCheck,
kServerHostname,
- kTLSCertPath,
- kTLSKeyLength,
+ kTlsCertPath,
+ kTlsKeyLength,
kPreventSleep,
kLanguageSync,
kInvertScrollDirection,
@@ -212,9 +169,20 @@ protected:
kLicenseNextCheck,
kInitiateConnectionFromServer,
kClientHostMode,
- kServerClientMode
+ kServerClientMode,
+ kServiceEnabled,
+ kMinimizeOnClose
};
+ static QString settingName(AppConfig::Setting name);
+
+ /// @brief Loads the setting from the current scope
+ void loadSettings() override;
+
+ /**
+ * Setters
+ */
+
void setScreenName(const QString &s);
void setPort(int i);
void setNetworkInterface(const QString &s);
@@ -224,70 +192,48 @@ protected:
void setWizardHasRun();
void setStartedBefore(bool b);
void setElevateMode(ElevateMode em);
+ void setCryptoEnabled(bool e);
+ void setEdition(Edition);
+ void setSerialKey(const QString &serial);
+ void clearSerialKey();
+ void setLastExpiringWarningTime(int t);
+ void setAutoHide(bool b);
+ void setInvertScrollDirection(bool b);
+ void setLicenseNextCheck(unsigned long long);
+ void setLanguageSync(bool b);
+ void setPreventSleep(bool b);
+ void setServerGroupChecked(bool);
+ void setUseExternalConfig(bool);
+ void setConfigFile(const QString &);
+ void setUseInternalConfig(bool);
+ void setClientGroupChecked(bool);
+ void setServerHostname(const QString &);
+ void setClientHostMode(bool newValue);
+ void setServerClientMode(bool newValue);
+ AppConfig &activationHasRun(bool value);
+ void setMinimizeToTray(bool b);
+ void setLastVersion(const QString &version);
+ void setServiceEnabled(bool enabled);
+ void setMinimizeOnClose(bool minimize);
- /// @brief loads the setting from the current scope
- /// @param ignoreSystem should the load feature ignore the globalScope setting
- /// that was saved
- void loadSettings() override;
- static QString settingName(AppConfig::Setting name);
+ /// @brief Sets the user preference to load from SystemScope.
+ /// @param [in] value
+ /// True - This will set the variable and load the global scope
+ /// settings. False - This will set the variable and load the user
+ /// scope settings.
+ void setLoadFromSystemScope(bool value);
+
+ /// @brief Set the path to the TLS/SSL certificate file that will be used
+ /// @param [in] path The path to the Certificate
+ void setTlsCertPath(const QString &path);
+
+ /// @brief Sets the key length of the private key to use in a TLS connection
+ /// @param [in] QString length The key length eg: 1024, 2048, 4096
+ void setTlsKeyLength(const QString &length);
private:
- QString m_ScreenName;
- int m_Port;
- QString m_Interface;
- int m_LogLevel;
- bool m_LogToFile;
- QString m_LogFilename;
- int m_WizardLastRun;
- ProcessMode m_ProcessMode;
- bool m_StartedBefore;
- ElevateMode m_ElevateMode;
- Edition m_Edition;
- QString m_ActivateEmail;
- bool m_CryptoEnabled;
- bool m_AutoHide;
- QString m_Serialkey;
- QString m_lastVersion;
- QString m_guid;
- QString m_licenseRegistryUrl;
- unsigned long long m_licenseNextCheck;
- int m_LastExpiringWarningTime;
- bool m_ActivationHasRun;
- bool m_MinimizeToTray;
- bool m_InvertScrollDirection = false;
- bool m_LanguageSync = true;
- bool m_PreventSleep = false;
- bool m_InitiateConnectionFromServer = false;
- bool m_ClientHostMode = true;
- bool m_ServerClientMode = true;
-
- bool m_ServerGroupChecked;
- bool m_UseExternalConfig;
- QString m_ConfigFile;
- bool m_UseInternalConfig;
- bool m_ClientGroupChecked;
- QString m_ServerHostname;
-
- QString m_TLSCertificatePath; /// @brief The path to the TLS certificate file
- QString m_TLSKeyLength; /// @brief The key length of the TLS cert to make
-
- bool m_LoadFromSystemScope; /// @brief should the setting be loaded from
- /// SystemScope
- /// If the user has settings but this is
- /// true then system settings will be
- /// loaded instead of the users
-
- CoreInterface m_CoreInterface;
-
- static const char m_SynergysName[];
- static const char m_SynergycName[];
- static const char m_SynergyLogDir[];
-
- /// @brief Contains the string values of the settings names that will be saved
- static const char *m_SynergySettingsName[];
-
- /// @brief Contains the name of the default configuration filename
- static const char m_SynergyConfigName[];
+ /// @brief Loads config from the underlying reader/writer
+ void load();
/// @brief Sets the value of a setting
/// @param [in] name The Setting to be saved
@@ -312,12 +258,6 @@ private:
QVariant loadCommonSetting(
AppConfig::Setting name, const QVariant &defaultValue = QVariant()) const;
- /// @brief As the settings will be accessible by multiple objects this lock
- /// will ensure that
- /// it cant be modified by more that one object at a time if the
- /// setting is being switched from system to user.
- std::mutex m_settings_lock;
-
/// @brief Sets the setting in the config checking if it has changed and
/// flagging that settings
/// needs to be saved if the setting was different
@@ -327,15 +267,79 @@ private:
/// @brief This method loads config from specified scope
/// @param [in] scope which should be loaded.
- void loadScope(GUI::Config::ConfigWriter::Scope scope);
+ void loadScope(synergy::gui::Config::Scope scope);
/// @brief This function sets default values
/// for settings that shouldn't be copied from between scopes.
void setDefaultValues();
+ synergy::gui::Config m_Config;
+ CoreInterface m_CoreInterface;
+ QString m_ScreenName = "";
+ int m_Port = 24800;
+ QString m_Interface = "";
+ int m_LogLevel = 0;
+ bool m_LogToFile = false;
+ QString m_LogFilename = "";
+ int m_WizardLastRun = 0;
+ bool m_StartedBefore = false;
+ ElevateMode m_ElevateMode = kDefaultElevateMode;
+ Edition m_Edition = Edition::kUnregistered;
+ QString m_ActivateEmail = "";
+ bool m_CryptoEnabled = false;
+ bool m_AutoHide = false;
+ QString m_Serialkey = "";
+ QString m_LastVersion = "";
+ QString m_Guid = "";
+ unsigned long long m_licenseNextCheck = 0;
+ int m_LastExpiringWarningTime = 0;
+ bool m_ActivationHasRun = false;
+ bool m_MinimizeToTray = true;
+ bool m_InvertScrollDirection = false;
+ bool m_LanguageSync = true;
+ bool m_PreventSleep = false;
+ bool m_InitiateConnectionFromServer = false;
+ bool m_ClientHostMode = true;
+ bool m_ServerClientMode = true;
+ bool m_ServerGroupChecked = false;
+ bool m_UseExternalConfig = false;
+ QString m_ConfigFile = "";
+ bool m_UseInternalConfig = false;
+ bool m_ClientGroupChecked = false;
+ QString m_ServerHostname = "";
+ bool m_ServiceEnabled = kDefaultProcessMode == ProcessMode::kService;
+ bool m_MinimizeOnClose = true;
+
+ /// @brief The path to the TLS certificate file
+ QString m_TlsCertPath = "";
+
+ /// @brief The key length of the TLS cert to make
+ QString m_TlsKeyLength = "";
+
+ /// @brief should the setting be loaded from
+ /// SystemScope
+ /// If the user has settings but this is
+ /// true then system settings will be
+ /// loaded instead of the users
+ bool m_LoadFromSystemScope = false;
+
+ /// @brief As the settings will be accessible by multiple objects this lock
+ /// will ensure that
+ /// it cant be modified by more that one object at a time if the
+ /// setting is being switched from system to user.
+ std::mutex m_settings_lock;
+
+ static const char m_CoreServerName[];
+ static const char m_CoreClientName[];
+ static const char m_LogDir[];
+
+ /// @brief Contains the string values of the settings names that will be saved
+ static const char *const m_SettingsName[];
+
+ /// @brief Contains the name of the default configuration filename
+ static const char m_ConfigFilename[];
+
signals:
void sslToggled() const;
void screenNameChanged() const;
};
-
-#endif
diff --git a/src/gui/src/CancelActivationDialog.ui b/src/gui/src/CancelActivationDialog.ui
index 054b3fe6f..c34d487ad 100644
--- a/src/gui/src/CancelActivationDialog.ui
+++ b/src/gui/src/CancelActivationDialog.ui
@@ -7,7 +7,7 @@
0
0
400
- 165
+ 246
@@ -17,9 +17,7 @@
-
- Are you sure?
-
-If you don't activate Synergy you'll be missing out on some great features.
+ <html><head/><body><p>You'll need to purchase a license to use this build of Synergy.</p><p><a href="https://symless.com/synergy/purchase?source=gui"><span style=" text-decoration: underline; color:#007af4;">Purchase Synergy</span></a></p><p>If you'd prefer to use the community edition instead, visit us on GitHub.</p><p><a href="https://github.com/symless/synergy-core"><span style=" text-decoration: underline; color:#007af4;">GitHub project</span></a></p><p>Would you like to go back and enter a serial key?</p><p>Choosing 'No' will quit Synergy.</p></body></html>
true
@@ -30,14 +28,17 @@ If you don't activate Synergy you'll be missing out on some great features.
-
-
-
- <html><head/><body><p><a href="https://symless.com/pricing?source=gui"><span style=" text-decoration: underline; color:#0000ff;">Buy now</span></a></p></body></html>
+
+
+ Qt::Vertical
-
- true
+
+
+ 20
+ 40
+
-
+
-
diff --git a/src/gui/src/ClientConnection.cpp b/src/gui/src/ClientConnection.cpp
index fb25b0eeb..2197caa94 100644
--- a/src/gui/src/ClientConnection.cpp
+++ b/src/gui/src/ClientConnection.cpp
@@ -59,13 +59,13 @@ QString ClientConnection::getMessage(const QString &line) const {
message =
QObject::tr("Connection failed.\nYou can’t name 2 computers the same.");
} else {
- QHostAddress address(m_parent.appConfig().getServerHostname());
+ QHostAddress address(m_parent.appConfig().serverHostname());
if (address.isNull()) {
message =
QObject::tr(
"We can’t connect to the server \"%1\" try to connect using the "
"server IP address and check your firewall settings.")
- .arg(m_parent.appConfig().getServerHostname());
+ .arg(m_parent.appConfig().serverHostname());
}
}
diff --git a/src/gui/src/CommandProcess.cpp b/src/gui/src/CommandProcess.cpp
index dcaa63ce2..8a54e6554 100644
--- a/src/gui/src/CommandProcess.cpp
+++ b/src/gui/src/CommandProcess.cpp
@@ -18,7 +18,6 @@
#include "CommandProcess.h"
#include
-#include
CommandProcess::CommandProcess(
QString cmd, QStringList arguments, QString input)
@@ -32,7 +31,8 @@ QString CommandProcess::run() {
process.start(m_Command, m_Arguments);
bool success = process.waitForStarted();
- QString output, error;
+ QString output;
+ QString error;
if (success) {
if (!m_Input.isEmpty()) {
process.write(m_Input.toStdString().c_str());
@@ -45,12 +45,11 @@ QString CommandProcess::run() {
}
}
- int code = process.exitCode();
- if (!error.isEmpty() || !success || code != 0) {
- throw std::runtime_error(QString("Code: %1\nError: %2")
- .arg(process.exitCode())
- .arg(error.isEmpty() ? "Unknown" : error)
- .toStdString());
+ if (int code = process.exitCode(); !success || code != 0) {
+ qFatal(
+ "Command failed: %s %s\nCode: %d\nError: %s", qUtf8Printable(m_Command),
+ qUtf8Printable(m_Arguments.join(" ")), code,
+ error.isEmpty() ? "None" : qUtf8Printable(error));
}
emit finished();
diff --git a/src/gui/src/CommonConfig.h b/src/gui/src/CommonConfig.h
new file mode 100644
index 000000000..e6fae87c8
--- /dev/null
+++ b/src/gui/src/CommonConfig.h
@@ -0,0 +1,36 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2020 Symless Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file LICENSE that should have accompanied this file.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+namespace synergy::gui {
+
+/// @brief Common configuration interface
+class CommonConfig {
+public:
+ CommonConfig() = default;
+ virtual ~CommonConfig() = default;
+ virtual void loadSettings() = 0;
+ virtual void saveSettings() = 0;
+ bool modified() const { return m_modified; }
+ void setModified(bool modified) { m_modified = modified; }
+
+private:
+ bool m_modified = false;
+};
+
+} // namespace synergy::gui
diff --git a/src/gui/src/ConfigWriter.cpp b/src/gui/src/Config.cpp
similarity index 50%
rename from src/gui/src/ConfigWriter.cpp
rename to src/gui/src/Config.cpp
index 26b04b4c1..81444542d 100644
--- a/src/gui/src/ConfigWriter.cpp
+++ b/src/gui/src/Config.cpp
@@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2020-2020 Symless Ltd.
+ * Copyright (C) 2020 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,21 +15,21 @@
* along with this program. If not, see .
*/
-#include
+#include "Config.h"
+
+#include "CommonConfig.h"
#include
#include
+#include
+#include
-#include "ConfigBase.h"
-#include "ConfigWriter.h"
-
-namespace {
+namespace synergy::gui {
QString getSystemSettingPath() {
const QString settingFilename("SystemConfig.ini");
QString path;
#if defined(Q_OS_WIN)
- // Program file
path = QCoreApplication::applicationDirPath() + "\\";
#elif defined(Q_OS_DARWIN)
// Global preferances dir
@@ -46,7 +46,7 @@ QString getSystemSettingPath() {
}
#if defined(Q_OS_WIN)
-void loadOldSystemSettings(QSettings &settings) {
+void loadWindowsLegacy(QSettings &settings) {
if (!QFile(settings.fileName()).exists()) {
QSettings::setPath(
QSettings::IniFormat, QSettings::SystemScope, "SystemConfig.ini");
@@ -68,147 +68,114 @@ void loadOldSystemSettings(QSettings &settings) {
}
#endif
-} // namespace
-
-namespace GUI {
-namespace Config {
-// Assignment of static variable
-ConfigWriter *ConfigWriter::s_pConfiguration = nullptr;
-
-ConfigWriter *ConfigWriter::make() {
- // Only one ConfigWriter can exist at any one time (Singleton)
- if (!s_pConfiguration) {
- s_pConfiguration = new ConfigWriter();
- }
- return s_pConfiguration;
-}
-
-ConfigWriter::ConfigWriter() {
+Config::Config() {
QSettings::setPath(
QSettings::Format::IniFormat, QSettings::Scope::SystemScope,
getSystemSettingPath());
// Config will default to User settings if they exist,
// otherwise it will load System setting and save them to User settings
- m_pSettingsSystem = new QSettings(
+ m_pSystemSettings = std::make_unique(
QSettings::Format::IniFormat, QSettings::Scope::SystemScope,
QCoreApplication::organizationName(),
QCoreApplication::applicationName());
+ // default to user scope.
+ // if we set the scope specifically then we also have to set the application
+ // name and the organisation name which breaks backwards compatibility.
+ m_pUserSettings = std::make_unique();
+
+ load();
+}
+
+Config::~Config() {
+ while (!m_pReceievers.empty()) {
+ m_pReceievers.pop_back();
+ }
+}
+
+void Config::load() {
#if defined(Q_OS_WIN)
// This call is needed for backwardcapability with old settings.
- loadOldSystemSettings(*m_pSettingsSystem);
+ loadWindowsLegacy(*m_pSystemSettings);
#endif
-
- // defaults to user scope, if we set the scope specifically then we also have
- // to set
- // the application name and the organisation name which breaks backwards
- // compatibility See #6730
- m_pSettingsUser = new QSettings();
-
- // Set scope to user for initially
- m_pSettingsCurrent = m_pSettingsUser;
}
-void ConfigWriter::destroy() { destroy(s_pConfiguration); }
-
-ConfigWriter::~ConfigWriter() {
- while (!m_pCallerList.empty()) {
- m_pCallerList.pop_back();
- }
- m_pSettingsCurrent = nullptr; // this only references other pointers
- destroy(m_pSettingsSystem);
- destroy(m_pSettingsUser);
-}
-
-bool ConfigWriter::hasSetting(const QString &name, Scope scope) const {
+bool Config::hasSetting(const QString &name, Scope scope) const {
switch (scope) {
- case kUser:
- return m_pSettingsUser->contains(name);
- case kSystem:
- return m_pSettingsSystem->contains(name);
+ case Scope::User:
+ return m_pUserSettings->contains(name);
+ case Scope::System:
+ return m_pSystemSettings->contains(name);
default:
- return m_pSettingsCurrent->contains(name);
+ return currentSettings()->contains(name);
}
}
-bool ConfigWriter::isWritable() const {
- return m_pSettingsCurrent->isWritable();
-}
+bool Config::isWritable() const { return currentSettings()->isWritable(); }
-QVariant ConfigWriter::loadSetting(
- const QString &name, const QVariant &defaultValue, Scope scope) {
+QVariant Config::loadSetting(
+ const QString &name, const QVariant &defaultValue, Scope scope) const {
switch (scope) {
- case kUser:
- return m_pSettingsUser->value(name, defaultValue);
- case kSystem:
- return m_pSettingsSystem->value(name, defaultValue);
+ case Scope::User:
+ return m_pUserSettings->value(name, defaultValue);
+ case Scope::System:
+ return m_pSystemSettings->value(name, defaultValue);
default:
- return m_pSettingsCurrent->value(name, defaultValue);
+ return currentSettings()->value(name, defaultValue);
}
}
-void ConfigWriter::setScope(ConfigWriter::Scope scope) {
- if (m_CurrentScope != scope) {
- m_CurrentScope = scope;
- switch (scope) {
- case kUser:
- m_pSettingsCurrent = m_pSettingsUser;
- break;
- case kSystem:
- m_pSettingsCurrent = m_pSettingsSystem;
- break;
- default:
- // setScope should never be kCurrent
- assert(scope);
- }
- }
-}
+void Config::setScope(Config::Scope scope) { m_CurrentScope = scope; }
-ConfigWriter::Scope ConfigWriter::getScope() const { return m_CurrentScope; }
+Config::Scope Config::getScope() const { return m_CurrentScope; }
-void ConfigWriter::globalLoad() {
- for (auto &i : m_pCallerList) {
+void Config::loadAll() {
+ for (auto &i : m_pReceievers) {
i->loadSettings();
}
}
-void ConfigWriter::globalSave() {
+void Config::saveAll() {
// Save if there are any unsaved changes otherwise skip
if (unsavedChanges()) {
- for (auto &i : m_pCallerList) {
+ for (auto &i : m_pReceievers) {
i->saveSettings();
}
- m_pSettingsUser->sync();
- m_pSettingsSystem->sync();
+ m_pUserSettings->sync();
+ m_pSystemSettings->sync();
m_unsavedChanges = false;
}
}
-QSettings &ConfigWriter::settings() { return *m_pSettingsCurrent; }
-
-void ConfigWriter::registerClass(ConfigBase *receiver) {
- m_pCallerList.push_back(receiver);
+QSettings *Config::currentSettings() const {
+ if (m_CurrentScope == Scope::User) {
+ return m_pUserSettings.get();
+ } else {
+ return m_pSystemSettings.get();
+ }
}
-bool ConfigWriter::unsavedChanges() const {
+void Config::registerReceiever(CommonConfig *receiver) {
+ m_pReceievers.push_back(receiver);
+}
+
+bool Config::unsavedChanges() const {
if (m_unsavedChanges) {
return true;
}
- for (const auto &i : m_pCallerList) {
+ for (const auto &i : m_pReceievers) {
if (i->modified()) {
- // If any class returns true there is no point checking more
return true;
}
}
- // If this line is reached no class has unsaved changes
return false;
}
-void ConfigWriter::markUnsaved() { m_unsavedChanges = true; }
-} // namespace Config
-} // namespace GUI
+void Config::markUnsaved() { m_unsavedChanges = true; }
+
+} // namespace synergy::gui
diff --git a/src/gui/src/Config.h b/src/gui/src/Config.h
new file mode 100644
index 000000000..24da15148
--- /dev/null
+++ b/src/gui/src/Config.h
@@ -0,0 +1,115 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2020 Symless Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file LICENSE that should have accompanied this file.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include
+#include
+#include
+
+namespace synergy::gui {
+
+class CommonConfig;
+
+/// @brief A general config reader and writer for user and gloabl settings
+class Config : private QObject {
+
+public:
+ enum class Scope { Current, System, User };
+
+ explicit Config();
+ ~Config() override;
+
+ /// @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;
+
+ /// @brief Checks if the current scope settings writable
+ /// @return bool True if the current scope writable
+ bool isWritable() const;
+
+ /// @brief Sets the value of a setting
+ /// @param [in] name The Setting to be saved
+ /// @param [in] value The Value to be saved (Templated)
+ /// @param [in] scope The scope to get the value from, default is current
+ /// scope
+ template
+ void setSetting(const QString &name, T value, Scope scope = Scope::Current);
+
+ /// @brief Loads a setting
+ /// @param [in] name The setting to be loaded
+ /// @param [in] defaultValue The default value of the setting
+ /// @param [in] scope The scope to get the value from, default is current
+ /// scope
+ QVariant loadSetting(
+ const QString &name, const QVariant &defaultValue = QVariant(),
+ Scope scope = Scope::Current) const;
+
+ /// @brief Changes the setting save and load location between System and User
+ /// scope
+ /// @param [in] scope The scope to set
+ void setScope(Scope scope = Scope::User);
+
+ /// @brief Get the current scope the settings are loading and save from.
+ /// @return Scope An enum defining the current scope
+ Scope getScope() const;
+
+ /// @brief trigger a config load across all registered classes
+ void loadAll();
+
+ /// @brief trigger a config save across all registered classes
+ void saveAll();
+
+ /// @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;
+
+ /// @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);
+
+ /// @brief Checks if any registered class has any unsaved changes
+ /// @return bool True if any registered class has unsaved changes
+ bool unsavedChanges() const;
+
+private:
+ void load();
+
+ Scope m_CurrentScope = Scope::User;
+ std::unique_ptr m_pUserSettings;
+ std::unique_ptr m_pSystemSettings;
+
+ /// @brief Receivers of load/save callbacks
+ std::list m_pReceievers;
+
+ /// @brief Is set to true when settings are changed
+ bool m_unsavedChanges = false;
+};
+
+template
+void Config::setSetting(const QString &name, T value, Scope scope) {
+ currentSettings()->setValue(name, value);
+ m_unsavedChanges = true;
+}
+
+} // namespace synergy::gui
diff --git a/src/gui/src/ConfigBase.h b/src/gui/src/ConfigBase.h
deleted file mode 100644
index 49ac9ee99..000000000
--- a/src/gui/src/ConfigBase.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2020 - 2020 Symless Ltd.
- *
- * This package is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * found in the file LICENSE that should have accompanied this file.
- *
- * This package is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef SYNERGY_CORE_CONFIGBASE_H
-#define SYNERGY_CORE_CONFIGBASE_H
-
-namespace GUI {
-namespace Config {
-
-///@brief This abstract class will be used by all classes that use the
-/// ConfigWriter
-/// to allow global saving and loading
-class ConfigBase {
-public:
- ConfigBase() = default;
-
- virtual ~ConfigBase() = default;
-
- /// @brief The function that is called when the settings need to be loaded
- /// from file
- virtual void loadSettings() = 0;
-
- /// @brief The function that is called when the settings need to be saved to
- /// file
- virtual void saveSettings() = 0;
-
- /// @brief Returns true if the class has marked itself with having unsaved
- /// changes
- bool modified() const { return m_unsavedChanges; }
-
-protected:
- /// @brief Does the class have unsaved changes in it.
- bool m_unsavedChanges = false;
-};
-} // namespace Config
-} // namespace GUI
-#endif // SYNERGY_CORE_CONFIGBASE_H
diff --git a/src/gui/src/ConfigWriter.h b/src/gui/src/ConfigWriter.h
deleted file mode 100644
index 870e0d1a8..000000000
--- a/src/gui/src/ConfigWriter.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2020 - 2020 Symless Ltd.
- *
- * This package is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * found in the file LICENSE that should have accompanied this file.
- *
- * This package is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#ifndef SYNERGY_CORE_CONFIGWRITER_H
-#define SYNERGY_CORE_CONFIGWRITER_H
-
-#include
-#include
-
-/// @brief Contains GUI code
-namespace GUI {
-/// @brief Contains Configuration code
-namespace Config {
-
-// Forward declare the class referenced by pointer
-class ConfigBase;
-
-class ConfigWriter : private QObject {
-
-public:
- /// @brief the public way to construct the configuration calls
- /// The pointer returned is owned by this class and should not be
- /// stored by other classes.
- static ConfigWriter *make();
-
- /// @brief the public way to destroy the configuration class
- static void destroy();
-
- ~ConfigWriter() override;
-
- ///@brief An Enumeration of all the scopes available
- enum Scope { kCurrent, kSystem, kUser };
-
- /// @brief Checks if the setting exists
- /// @param [in] name The name of the setting to check
- /// @param [in] scope The scope to search in
- /// @return bool True if the current scope has the named setting
- bool hasSetting(const QString &name, Scope scope = kCurrent) const;
-
- /// @brief Checks if the current scope settings writable
- /// @return bool True if the current scope writable
- bool isWritable() const;
-
- /// @brief Sets the value of a setting
- /// @param [in] name The Setting to be saved
- /// @param [in] value The Value to be saved (Templated)
- /// @param [in] scope The scope to get the value from, default is current
- /// scope
- template
- void setSetting(const QString &name, T value, Scope scope = kCurrent);
-
- /// @brief Loads a setting
- /// @param [in] name The setting to be loaded
- /// @param [in] defaultValue The default value of the setting
- /// @param [in] scope The scope to get the value from, default is current
- /// scope
- QVariant loadSetting(
- const QString &name, const QVariant &defaultValue = QVariant(),
- Scope scope = kCurrent);
-
- /// @brief Changes the setting save and load location between System and User
- /// scope
- /// @param [in] scope The scope to set
- void setScope(Scope scope = kUser);
-
- /// @brief Get the current scope the settings are loading and save from.
- /// @return Scope An enum defining the current scope
- Scope getScope() const;
-
- /// @brief trigger a config load across all registered classes
- void globalLoad();
-
- /// @brief trigger a config save across all registered classes
- void globalSave();
-
- /// @brief Returns the current scopes settings object
- /// If more specialize control into the settings is needed this can
- /// provide direct access to the settings file handler
- /// @return QSettings The Settings object as a reference
- QSettings &settings();
-
- /// @brief This marks the settings as unsaved if the settings() was used to
- /// directly affect the config file
- void markUnsaved();
-
- /// @brief Register a class to receives globalLoad and globalSave events
- /// @param [in] ConfigBase The class that will receive the events
- void registerClass(ConfigBase *receiver);
-
- /// @brief Checks if any registered class has any unsaved changes
- /// @return bool True if any registered class has unsaved changes
- bool unsavedChanges() const;
-
-protected:
- Scope m_CurrentScope = kUser; /// @brief The current scope of the settings
-
- QSettings *m_pSettingsCurrent =
- nullptr; /// @brief The currently active settings
- QSettings *m_pSettingsUser = nullptr; /// @brief The user specific settings
- QSettings *m_pSettingsSystem = nullptr; /// @brief The system wide settings
-
-private:
- /// @brief Contains a list all all classes that hook into the writer.
- /// This allows all classes that save settings to be called an updated
- /// on a save and reload by any other class
- std::list m_pCallerList;
-
- /// @brief if this class modified settings then set the flag
- bool m_unsavedChanges = false;
-
- /// @brief The constructor, as this is a singolton we want to control who can
- /// call the constructor
- ConfigWriter();
-
- /// @brief the pointer of the ConfigWriter for singolton use
- static ConfigWriter *s_pConfiguration;
-
- /// @brief deletes pointers and sets the value to null
- template static inline void destroy(T *&p) {
- delete p;
- p = 0;
- }
-};
-
-// Implementation of a template function needs to be visible to all calls thus
-// is must be in the header Moved so its not bulking out the class definition
-template
-void ConfigWriter::setSetting(const QString &name, T value, Scope scope) {
- switch (scope) {
- case kUser:
- m_pSettingsUser->setValue(name, value);
- break;
- case kSystem:
- m_pSettingsSystem->setValue(name, value);
- break;
- default:
- m_pSettingsCurrent->setValue(name, value);
- break;
- }
- m_unsavedChanges = true;
-}
-} // namespace Config
-} // namespace GUI
-#endif // SYNERGY_CORE_CONFIGWRITER_H
diff --git a/src/gui/src/CoreInterface.cpp b/src/gui/src/CoreInterface.cpp
index 6b9c6b7fd..43b95c3ba 100644
--- a/src/gui/src/CoreInterface.cpp
+++ b/src/gui/src/CoreInterface.cpp
@@ -18,13 +18,11 @@
#include "CoreInterface.h"
#include "CommandProcess.h"
-#include "QUtility.h"
#include
#include
#include
#include
-#include
static const char kCoreBinary[] = "syntool";
@@ -34,16 +32,14 @@ static const char kSerialKeyFilename[] = "Synergy.subkey";
static const char kSerialKeyFilename[] = ".synergy.subkey";
#endif
-CoreInterface::CoreInterface() {}
-
QString CoreInterface::getProfileDir() {
QStringList args("--get-profile-dir");
- return run(args);
+ return QDir::cleanPath(run(args));
}
QString CoreInterface::getInstalledDir() {
QStringList args("--get-installed-dir");
- return run(args);
+ return QDir::cleanPath(run(args));
}
QString CoreInterface::getArch() {
@@ -52,11 +48,12 @@ QString CoreInterface::getArch() {
}
QString CoreInterface::getSerialKeyFilePath() {
- QString filename = getProfileDir() + QDir::separator() + kSerialKeyFilename;
- return filename;
+ auto filename = getProfileDir() + QDir::separator() + kSerialKeyFilename;
+ return QDir::cleanPath(filename);
}
-QString CoreInterface::run(const QStringList &args, const QString &input) {
+QString
+CoreInterface::run(const QStringList &args, const QString &input) const {
QString program(QCoreApplication::applicationDirPath() + "/" + kCoreBinary);
CommandProcess commandProcess(program, args, input);
diff --git a/src/gui/src/CoreInterface.h b/src/gui/src/CoreInterface.h
index ffce03747..8cabff22c 100644
--- a/src/gui/src/CoreInterface.h
+++ b/src/gui/src/CoreInterface.h
@@ -21,11 +21,9 @@
class CoreInterface {
public:
- CoreInterface();
-
QString getProfileDir();
QString getInstalledDir();
QString getArch();
QString getSerialKeyFilePath();
- QString run(const QStringList &args, const QString &input = "");
+ QString run(const QStringList &args, const QString &input = "") const;
};
diff --git a/src/gui/src/ElevateMode.h b/src/gui/src/ElevateMode.h
index 0d87f4e98..d2099912e 100644
--- a/src/gui/src/ElevateMode.h
+++ b/src/gui/src/ElevateMode.h
@@ -33,5 +33,3 @@
// ElevateNever | false | false
//
enum ElevateMode { ElevateAsNeeded = 0, ElevateAlways = 1, ElevateNever = 2 };
-
-extern const ElevateMode kDefaultElevateMode;
diff --git a/src/gui/src/LicenseManager.cpp b/src/gui/src/LicenseManager.cpp
index 39ef75d5b..1ea44b40a 100644
--- a/src/gui/src/LicenseManager.cpp
+++ b/src/gui/src/LicenseManager.cpp
@@ -16,7 +16,10 @@
*/
#include "LicenseManager.h"
+
+#include "ActivationNotifier.h"
#include "AppConfig.h"
+
#include
#include
#include
@@ -66,7 +69,7 @@ void checkSerialKey(const SerialKey &serialKey, bool acceptExpired) {
} // namespace
LicenseManager::LicenseManager(AppConfig *appConfig)
- : m_AppConfig(appConfig),
+ : m_pAppConfig(appConfig),
m_serialKey(appConfig->edition()),
m_registry(*appConfig) {}
@@ -76,14 +79,14 @@ void LicenseManager::setSerialKey(SerialKey serialKey, bool acceptExpired) {
if (serialKey != m_serialKey) {
using std::swap;
swap(serialKey, m_serialKey);
- m_AppConfig->setSerialKey(QString::fromStdString(m_serialKey.toString()));
+ m_pAppConfig->setSerialKey(QString::fromStdString(m_serialKey.toString()));
emit showLicenseNotice(getLicenseNotice());
validateSerialKey();
m_registry.scheduleRegistration();
if (m_serialKey.edition() != serialKey.edition()) {
- m_AppConfig->setEdition(m_serialKey.edition());
+ m_pAppConfig->setEdition(m_serialKey.edition());
emit editionChanged(m_serialKey.edition());
}
}
@@ -119,13 +122,14 @@ QString LicenseManager::activeEditionName() const {
const SerialKey &LicenseManager::serialKey() const { return m_serialKey; }
void LicenseManager::refresh() {
- if (!m_AppConfig->serialKey().isEmpty()) {
+ if (!m_pAppConfig->serialKey().isEmpty()) {
try {
- SerialKey serialKey(m_AppConfig->serialKey().toStdString());
+ SerialKey serialKey(m_pAppConfig->serialKey().toStdString());
setSerialKey(serialKey, true);
- } catch (...) {
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
m_serialKey = SerialKey();
- m_AppConfig->clearSerialKey();
+ m_pAppConfig->clearSerialKey();
}
}
if (!m_serialKey.isValid()) {
@@ -133,10 +137,6 @@ void LicenseManager::refresh() {
}
}
-void LicenseManager::skipActivation() const {
- notifyActivation("skip:unknown");
-}
-
QString LicenseManager::getEditionName(Edition const edition, bool trial) {
SerialKeyEdition KeyEdition(edition);
std::string name = KeyEdition.getProductName();
diff --git a/src/gui/src/LicenseManager.h b/src/gui/src/LicenseManager.h
index 69473f781..42caf1b70 100644
--- a/src/gui/src/LicenseManager.h
+++ b/src/gui/src/LicenseManager.h
@@ -17,13 +17,11 @@
#pragma once
-#include
-#include
-#include
-#include
-#include
-
#include "LicenseRegistry.h"
+#include "shared/EditionType.h"
+#include "shared/SerialKey.h"
+
+#include
class AppConfig;
@@ -37,14 +35,13 @@ public:
Edition activeEdition() const;
QString activeEditionName() const;
const SerialKey &serialKey() const;
- void skipActivation() const;
void notifyUpdate(QString fromVersion, QString toVersion) const;
static QString getEditionName(Edition edition, bool trial = false);
void notifyActivation(QString identity) const;
QString getLicenseNotice() const;
private:
- AppConfig *m_AppConfig;
+ AppConfig *m_pAppConfig;
SerialKey m_serialKey;
LicenseRegistry m_registry;
diff --git a/src/gui/src/LicenseRegistry.cpp b/src/gui/src/LicenseRegistry.cpp
index 45d09f3bd..9b36708bc 100644
--- a/src/gui/src/LicenseRegistry.cpp
+++ b/src/gui/src/LicenseRegistry.cpp
@@ -23,6 +23,9 @@
#include "LicenseRegistry.h"
#include
+const char *const kLicenseRegistryUrl =
+ "https://api2.prod.symless.com/license/register";
+
LicenseRegistry::LicenseRegistry(AppConfig &config) : m_config(config) {
connect(&m_timer, SIGNAL(timeout()), this, SLOT(registerLicense()));
}
@@ -30,8 +33,7 @@ LicenseRegistry::LicenseRegistry(AppConfig &config) : m_config(config) {
void LicenseRegistry::registerLicense() {
m_timer.stop();
if (m_config.edition() == Edition::kBusiness) {
- const auto REGISTER_LICENSE_URL = m_config.getLicenseRegistryUrl();
- const auto url = QUrl(REGISTER_LICENSE_URL);
+ const auto url = QUrl(kLicenseRegistryUrl);
auto request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
@@ -73,18 +75,18 @@ QByteArray LicenseRegistry::getRequestData() const {
data["guid"] = guid;
data["guid_type"] = "system";
} else {
- data["guid"] = m_config.getGuid();
+ data["guid"] = m_config.guid();
data["guid_type"] = "synergy";
}
data["key"] = m_config.serialKey();
- data["is_server"] = m_config.getServerGroupChecked();
+ data["is_server"] = m_config.serverGroupChecked();
return QJsonDocument(data).toJson();
}
void LicenseRegistry::scheduleRegistration() {
- const auto nextCheck = m_config.getLicenseNextCheck();
+ const auto nextCheck = m_config.licenseNextCheck();
const auto currentTimestamp = static_cast(time(nullptr));
if (currentTimestamp >= nextCheck) {
diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp
index 110382584..bc617f969 100644
--- a/src/gui/src/MainWindow.cpp
+++ b/src/gui/src/MainWindow.cpp
@@ -16,11 +16,6 @@
* along with this program. If not, see .
*/
-#define DOWNLOAD_URL "http://symless.com/?source=gui"
-#define HELP_URL "http://symless.com/help?source=gui"
-
-#include
-
#include "MainWindow.h"
#include "AboutDialog.h"
@@ -29,8 +24,8 @@
#include "LicenseManager.h"
#include "ServerConfigDialog.h"
#include "SettingsDialog.h"
-#include
-#include
+#include "shared/EditionType.h"
+#include
#if defined(Q_OS_MAC)
#include "OSXHelpers.h"
@@ -42,39 +37,46 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#if defined(Q_OS_MAC)
#include
#endif
-static const int debugLogLevel = 1;
+static const char *const kDownloadUrl = "https://symless.com/?source=gui";
+static const char *const kHelpUrl = "https://symless.com/help?source=gui";
+static const int kRetryDelay = 1000;
+static const int kDebugLogLevel = 1;
-static const char *synergyLightIconFiles[] = {
+#if defined(Q_OS_MAC)
+
+static const char *const kLightIconFiles[] = {
":/res/icons/64x64/synergy-light-disconnected.png",
":/res/icons/64x64/synergy-light-disconnected.png",
":/res/icons/64x64/synergy-light-connected.png",
":/res/icons/64x64/synergy-light-transfering.png",
":/res/icons/64x64/synergy-light-disconnected.png"};
-static const char *synergyDarkIconFiles[] = {
+static const char *const kDarkIconFiles[] = {
":/res/icons/64x64/synergy-dark-disconnected.png",
":/res/icons/64x64/synergy-dark-disconnected.png",
":/res/icons/64x64/synergy-dark-connected.png",
":/res/icons/64x64/synergy-dark-transfering.png",
- ":/res/icons/64x64/synergy-dark-disconnected.png" // synergyPendingRetry
-};
+ ":/res/icons/64x64/synergy-dark-disconnected.png"};
-static const char *synergyDefaultIconFiles[] = {
- ":/res/icons/16x16/synergy-disconnected.png", // synergyDisconnected
- ":/res/icons/16x16/synergy-disconnected.png", // synergyConnecting
- ":/res/icons/16x16/synergy-connected.png", // synergyConnected
- ":/res/icons/16x16/synergy-transfering.png", // synergyListening
- ":/res/icons/16x16/synergy-disconnected.png" // synergyPendingRetry
-};
+#endif
+
+static const char *const kDefaultIconFiles[] = {
+ ":/res/icons/16x16/synergy-disconnected.png",
+ ":/res/icons/16x16/synergy-disconnected.png",
+ ":/res/icons/16x16/synergy-connected.png",
+ ":/res/icons/16x16/synergy-transfering.png",
+ ":/res/icons/16x16/synergy-disconnected.png"};
#ifdef SYNERGY_ENABLE_LICENSING
MainWindow::MainWindow(AppConfig &appConfig, LicenseManager &licenseManager)
@@ -84,21 +86,9 @@ MainWindow::MainWindow(AppConfig &appConfig)
:
#ifdef SYNERGY_ENABLE_LICENSING
m_LicenseManager(&licenseManager),
- m_ActivationDialogRunning(false),
#endif
- m_AppConfig(&appConfig),
- m_pSynergy(NULL),
- m_SynergyState(synergyDisconnected),
- m_ServerConfig(5, 3, m_AppConfig, this),
- m_AlreadyHidden(false),
- m_pMenuBar(NULL),
- m_pMenuFile(NULL),
- m_pMenuEdit(NULL),
- m_pMenuWindow(NULL),
- m_pMenuHelp(NULL),
- m_pCancelButton(NULL),
- m_ExpectedRunningState(kStopped),
- m_SecureSocket(false),
+ m_AppConfig(appConfig),
+ m_ServerConfig(5, 3, &m_AppConfig, this),
m_serverConnection(*this),
m_clientConnection(*this) {
@@ -109,16 +99,19 @@ MainWindow::MainWindow(AppConfig &appConfig)
m_pRadioGroupClient->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
+ m_ServerConfig.loadSettings();
+
createMenuBar();
loadSettings();
initConnections();
m_pWidgetUpdate->hide();
- m_VersionChecker.setApp(appPath(appConfig.synergycName()));
+ m_VersionChecker.setApp(appPath(appConfig.coreClientName()));
updateScreenName();
connect(
- m_AppConfig, SIGNAL(screenNameChanged()), this, SLOT(updateScreenName()));
+ appConfigPtr(), SIGNAL(screenNameChanged()), this,
+ SLOT(updateScreenName()));
m_pLabelIpAddresses->setText(
tr("This computer's IP addresses: %1").arg(getIPAddresses()));
@@ -172,14 +165,14 @@ MainWindow::MainWindow(AppConfig &appConfig)
#endif
connect(
- m_AppConfig, SIGNAL(sslToggled()), this, SLOT(updateLocalFingerprint()),
- Qt::QueuedConnection);
+ appConfigPtr(), SIGNAL(sslToggled()), this,
+ SLOT(updateLocalFingerprint()), Qt::QueuedConnection);
updateWindowTitle();
- QString lastVersion = m_AppConfig->lastVersion();
+ QString lastVersion = m_AppConfig.lastVersion();
if (lastVersion != SYNERGY_VERSION) {
- m_AppConfig->setLastVersion(SYNERGY_VERSION);
+ m_AppConfig.setLastVersion(SYNERGY_VERSION);
#ifdef SYNERGY_ENABLE_LICENSING
m_LicenseManager->notifyUpdate(lastVersion, SYNERGY_VERSION);
@@ -193,13 +186,12 @@ MainWindow::MainWindow(AppConfig &appConfig)
MainWindow::~MainWindow() {
if (appConfig().processMode() == ProcessMode::kDesktop) {
- m_ExpectedRunningState = kStopped;
+ m_ExpectedRunningState = RuningState::Stopped;
try {
stopDesktop();
- } catch (...) {
- // do not throw, since throwing from a dtor can result in unreliable
- // behaviour.
- qCritical() << "error stopping desktop in main window destructor";
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
+ qFatal("Failed to stop synergy desktop process");
}
}
}
@@ -207,16 +199,15 @@ MainWindow::~MainWindow() {
void MainWindow::open() {
std::array trayMenu = {
- m_pActionStartSynergy, m_pActionStopSynergy, nullptr,
- m_pActionMinimize, m_pActionRestore, nullptr,
- m_pActionQuit};
+ m_pActionStartCore, m_pActionStopCore, nullptr, m_pActionMinimize,
+ m_pActionRestore, nullptr, m_pActionQuit};
m_trayIcon.create(trayMenu, [this](QObject const *o, const char *s) {
connect(o, s, this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
- setIcon(synergyDisconnected);
+ setIcon(CoreState::Disconnected);
});
- if (appConfig().getAutoHide()) {
+ if (appConfig().autoHide()) {
hide();
} else {
showNormal();
@@ -229,7 +220,7 @@ void MainWindow::open() {
// confuses first time users, who think synergy has crashed).
if (appConfig().startedBefore() &&
appConfig().processMode() == ProcessMode::kDesktop) {
- startSynergy();
+ startCore();
}
}
@@ -251,8 +242,8 @@ void MainWindow::createMenuBar() {
#endif
m_pMenuBar->addAction(m_pMenuHelp->menuAction());
- m_pMenuFile->addAction(m_pActionStartSynergy);
- m_pMenuFile->addAction(m_pActionStopSynergy);
+ m_pMenuFile->addAction(m_pActionStartCore);
+ m_pMenuFile->addAction(m_pActionStopCore);
m_pMenuFile->addSeparator();
m_pMenuFile->addAction(m_pActivate);
m_pMenuFile->addSeparator();
@@ -269,19 +260,18 @@ void MainWindow::createMenuBar() {
}
void MainWindow::loadSettings() {
- enableServer(appConfig().getServerGroupChecked());
- enableClient(appConfig().getClientGroupChecked());
+ enableServer(appConfig().serverGroupChecked());
+ enableClient(appConfig().clientGroupChecked());
- m_pLineEditHostname->setText(appConfig().getServerHostname());
+ m_pLineEditHostname->setText(appConfig().serverHostname());
m_pLineEditClienIp->setText(serverConfig().getClientAddress());
}
void MainWindow::initConnections() {
connect(m_pActionMinimize, SIGNAL(triggered()), this, SLOT(hide()));
connect(m_pActionRestore, SIGNAL(triggered()), this, SLOT(showNormal()));
- connect(
- m_pActionStartSynergy, SIGNAL(triggered()), this, SLOT(actionStart()));
- connect(m_pActionStopSynergy, SIGNAL(triggered()), this, SLOT(stopSynergy()));
+ connect(m_pActionStartCore, SIGNAL(triggered()), this, SLOT(actionStart()));
+ connect(m_pActionStopCore, SIGNAL(triggered()), this, SLOT(stopCore()));
connect(m_pActionQuit, SIGNAL(triggered()), qApp, SLOT(quit()));
connect(
&m_VersionChecker, SIGNAL(updateFound(const QString &)), this,
@@ -289,35 +279,34 @@ void MainWindow::initConnections() {
}
void MainWindow::saveSettings() {
- // program settings
appConfig().setServerGroupChecked(m_pRadioGroupServer->isChecked());
appConfig().setClientGroupChecked(m_pRadioGroupClient->isChecked());
appConfig().setServerHostname(m_pLineEditHostname->text());
serverConfig().setClientAddress(m_pLineEditClienIp->text());
- /* Save everything */
- GUI::Config::ConfigWriter::make()->globalSave();
+ appConfig().config().saveAll();
}
-void MainWindow::setIcon(qSynergyState state) const {
+void MainWindow::setIcon(CoreState state) const {
QIcon icon;
+ auto index = static_cast(state);
#ifdef Q_OS_MAC
switch (getOSXIconsTheme()) {
case IconsTheme::ICONS_DARK:
- icon.addFile(synergyDarkIconFiles[state]);
+ icon.addFile(kDarkIconFiles[index]);
break;
case IconsTheme::ICONS_LIGHT:
- icon.addFile(synergyLightIconFiles[state]);
+ icon.addFile(kLightIconFiles[index]);
break;
case IconsTheme::ICONS_TEMPLATE:
default:
- icon.addFile(synergyDarkIconFiles[state]);
+ icon.addFile(kDarkIconFiles[index]);
icon.setIsMask(true);
break;
}
#else
- icon.addFile(synergyDefaultIconFiles[state]);
+ icon.addFile(kDefaultIconFiles[index]);
#endif
m_trayIcon.set(icon);
@@ -335,8 +324,8 @@ void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason) {
}
void MainWindow::logOutput() {
- if (m_pSynergy) {
- QString text(m_pSynergy->readAllStandardOutput());
+ if (m_pCoreProcess) {
+ QString text(m_pCoreProcess->readAllStandardOutput());
for (QString line : text.split(QRegularExpression("\r|\n|\r\n"))) {
if (!line.isEmpty()) {
appendLogRaw(line);
@@ -346,8 +335,8 @@ void MainWindow::logOutput() {
}
void MainWindow::logError() {
- if (m_pSynergy) {
- appendLogRaw(m_pSynergy->readAllStandardError());
+ if (m_pCoreProcess) {
+ appendLogRaw(m_pCoreProcess->readAllStandardError());
}
}
@@ -357,7 +346,7 @@ void MainWindow::updateFound(const QString &version) {
"Version %1 is now available to "
"download.
")
.arg(version)
- .arg(DOWNLOAD_URL));
+ .arg(kDownloadUrl));
}
void MainWindow::appendLogInfo(const QString &text) {
@@ -365,7 +354,7 @@ void MainWindow::appendLogInfo(const QString &text) {
}
void MainWindow::appendLogDebug(const QString &text) {
- if (appConfig().logLevel() >= debugLogLevel) {
+ if (appConfig().logLevel() >= kDebugLogLevel) {
appendLogRaw(getTimeStamp() + " DEBUG: " + text);
}
}
@@ -395,7 +384,7 @@ void MainWindow::handleIdleService(const QString &text) {
// only start if there is no active service running
if (!line.isEmpty() && line.contains("service status: idle") &&
appConfig().startedBefore()) {
- startSynergy();
+ startCore();
}
}
}
@@ -428,7 +417,7 @@ void MainWindow::checkConnected(const QString &line) {
}
if (line.contains("connected to server") || line.contains("has connected")) {
- setSynergyState(synergyConnected);
+ setCoreState(CoreState::Connected);
if (!appConfig().startedBefore() && isVisible()) {
QMessageBox::information(
@@ -440,13 +429,13 @@ void MainWindow::checkConnected(const QString &line) {
appConfig().setStartedBefore(true);
}
} else if (line.contains("started server")) {
- setSynergyState(synergyListening);
+ setCoreState(CoreState::Listening);
} else if (
line.contains("disconnected from server") ||
line.contains("process exited")) {
- setSynergyState(synergyDisconnected);
+ setCoreState(CoreState::Disconnected);
} else if (line.contains("connecting to")) {
- setSynergyState(synergyConnecting);
+ setCoreState(CoreState::Connecting);
}
}
@@ -474,7 +463,7 @@ void MainWindow::checkFingerprint(const QString &line) {
static bool messageBoxAlreadyShown = false;
if (!messageBoxAlreadyShown) {
- stopSynergy();
+ stopCore();
messageBoxAlreadyShown = true;
QMessageBox::StandardButton fingerprintReply = QMessageBox::information(
@@ -493,7 +482,7 @@ void MainWindow::checkFingerprint(const QString &line) {
if (fingerprintReply == QMessageBox::Yes) {
// restart core process after trusting fingerprint.
Fingerprint::trustedServers().trust(fingerprint);
- startSynergy();
+ startCore();
}
messageBoxAlreadyShown = false;
@@ -536,9 +525,9 @@ QString MainWindow::getTimeStamp() {
return '[' + current.toString(Qt::ISODate) + ']';
}
-void MainWindow::restartSynergy() {
- stopSynergy();
- startSynergy();
+void MainWindow::restartCore() {
+ stopCore();
+ startCore();
}
void MainWindow::showEvent(QShowEvent *event) {
@@ -548,7 +537,7 @@ void MainWindow::showEvent(QShowEvent *event) {
void MainWindow::clearLog() { m_pLogOutput->clear(); }
-void MainWindow::startSynergy() {
+void MainWindow::startCore() {
saveSettings();
#ifdef Q_OS_MAC
@@ -564,12 +553,10 @@ void MainWindow::startSynergy() {
}
m_LicenseManager->registerLicense();
#endif
- bool desktopMode = appConfig().processMode() == ProcessMode::kDesktop;
- bool serviceMode = appConfig().processMode() == ProcessMode::kService;
appendLogDebug("starting process");
- m_ExpectedRunningState = kStarted;
- setSynergyState(synergyConnecting);
+ m_ExpectedRunningState = RuningState::Started;
+ setCoreState(CoreState::Connecting);
QString app;
QStringList args;
@@ -580,8 +567,10 @@ void MainWindow::startSynergy() {
args << "--name" << appConfig().screenName();
- if (desktopMode) {
- setSynergyProcess(new QProcess(this));
+ ProcessMode mode = appConfig().processMode();
+
+ if (mode == ProcessMode::kDesktop) {
+ m_pCoreProcess = std::make_unique(this);
} else {
// tell client/server to talk to daemon through ipc.
args << "--ipc";
@@ -611,25 +600,30 @@ void MainWindow::startSynergy() {
#endif
#if defined(Q_OS_WIN)
- if (m_AppConfig->getCryptoEnabled()) {
+ if (m_AppConfig.cryptoEnabled()) {
args << "--enable-crypto";
- args << "--tls-cert"
- << QString("\"%1\"").arg(m_AppConfig->getTLSCertPath());
+ args << "--tls-cert" << m_AppConfig.tlsCertPath();
+ }
+
+ try {
+ // on windows, the profile directory changes depending on the user that
+ // launched the process (e.g. when launched with elevation). setting the
+ // profile dir on launch ensures it uses the same profile dir is used
+ // no matter how its relaunched.
+ args << "--profile-dir" << getProfileRootForArg();
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
+ qFatal("Failed to get profile dir, skipping arg");
}
- // on windows, the profile directory changes depending on the user that
- // launched the process (e.g. when launched with elevation). setting the
- // profile dir on launch ensures it uses the same profile dir is used
- // no matter how its relaunched.
- args << "--profile-dir" << getProfileRootForArg();
#else
- if (m_AppConfig->getCryptoEnabled()) {
+ if (m_AppConfig.cryptoEnabled()) {
args << "--enable-crypto";
- args << "--tls-cert" << m_AppConfig->getTLSCertPath();
+ args << "--tls-cert" << m_AppConfig.tlsCertPath();
}
#endif
- if (m_AppConfig->getPreventSleep()) {
+ if (m_AppConfig.preventSleep()) {
args << "--prevent-sleep";
}
@@ -639,28 +633,26 @@ void MainWindow::startSynergy() {
appendLogInfo(
"starting " +
- QString(synergyType() == synergyServer ? "server" : "client"));
+ QString(coreMode() == CoreMode::Server ? "server" : "client"));
- if ((synergyType() == synergyClient && !clientArgs(args, app)) ||
- (synergyType() == synergyServer && !serverArgs(args, app))) {
- stopSynergy();
+ if ((coreMode() == CoreMode::Client && !clientArgs(args, app)) ||
+ (coreMode() == CoreMode::Server && !serverArgs(args, app))) {
+ stopCore();
return;
}
- if (desktopMode) {
+ if (mode == ProcessMode::kDesktop) {
connect(
- synergyProcess(), SIGNAL(finished(int, QProcess::ExitStatus)), this,
- SLOT(synergyFinished(int, QProcess::ExitStatus)));
+ m_pCoreProcess.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this,
+ SLOT(coreProcessExit(int, QProcess::ExitStatus)));
connect(
- synergyProcess(), SIGNAL(readyReadStandardOutput()), this,
+ m_pCoreProcess.get(), SIGNAL(readyReadStandardOutput()), this,
SLOT(logOutput()));
connect(
- synergyProcess(), SIGNAL(readyReadStandardError()), this,
+ m_pCoreProcess.get(), SIGNAL(readyReadStandardError()), this,
SLOT(logError()));
}
- qDebug() << args;
-
// show command if debug log level...
if (appConfig().logLevel() >= 4) {
appendLogInfo(QString("command: %1 %2").arg(app, args.join(" ")));
@@ -671,9 +663,9 @@ void MainWindow::startSynergy() {
if (appConfig().logToFile())
appendLogInfo("log file: " + appConfig().logFilename());
- if (desktopMode) {
- synergyProcess()->start(app, args);
- if (!synergyProcess()->waitForStarted()) {
+ if (mode == ProcessMode::kDesktop) {
+ m_pCoreProcess->start(app, args);
+ if (!m_pCoreProcess->waitForStarted()) {
show();
QMessageBox::warning(
this, tr("Program can not be started"),
@@ -684,9 +676,7 @@ void MainWindow::startSynergy() {
.arg(app)));
return;
}
- }
-
- if (serviceMode) {
+ } else if (mode == ProcessMode::kService) {
QString command(app + " " + args.join(" "));
m_IpcClient.sendCommand(command, appConfig().elevateMode());
}
@@ -694,19 +684,19 @@ void MainWindow::startSynergy() {
void MainWindow::actionStart() {
m_clientConnection.setCheckConnection(true);
- startSynergy();
+ startCore();
}
void MainWindow::retryStart() {
// This function is only called after a failed start
// Only start synergy if the current state is pending retry
- if (m_SynergyState == synergyPendingRetry) {
- startSynergy();
+ if (m_CoreState == CoreState::PendingRetry) {
+ startCore();
}
}
bool MainWindow::clientArgs(QStringList &args, QString &app) {
- app = appPath(appConfig().synergycName());
+ app = appPath(appConfig().coreClientName());
if (!QFile::exists(app)) {
show();
@@ -716,38 +706,31 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
return false;
}
-#if defined(Q_OS_WIN)
- // wrap in quotes so a malicious user can't start \Program.exe as admin.
- app = QString("\"%1\"").arg(app);
-#endif
-
if (appConfig().logToFile()) {
appConfig().persistLogDir();
- args << "--log" << appConfig().logFilenameCmd();
+ args << "--log" << appConfig().logFilename();
}
- if (appConfig().getLanguageSync()) {
+ if (appConfig().languageSync()) {
args << "--sync-language";
}
- if (appConfig().getInvertScrollDirection()) {
+ if (appConfig().invertScrollDirection()) {
args << "--invert-scroll";
}
- if (m_pLineEditHostname->text().isEmpty() &&
- !appConfig().getClientHostMode()) {
- show();
- QMessageBox::warning(
- this, tr("Hostname is empty"),
- tr("Please fill in a hostname for the synergy "
- "client to connect to."));
- return false;
- }
-
- if (appConfig().getClientHostMode()) {
+ if (appConfig().clientHostMode()) {
args << "--host";
args << ":" + QString::number(appConfig().port());
} else {
+ if (m_pLineEditHostname->text().isEmpty()) {
+ show();
+ QMessageBox::warning(
+ this, tr("IP/hostname is empty"),
+ tr("Please enter a server hostname or IP address."));
+ return false;
+ }
+
QString hostName = m_pLineEditHostname->text();
// if interface is IPv6 - ensure that ip is in square brackets
if (hostName.count(':') > 1) {
@@ -766,8 +749,8 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
QString MainWindow::configFilename() {
QString configFullPath;
- if (appConfig().getUseExternalConfig()) {
- configFullPath = appConfig().getConfigFile();
+ if (appConfig().useExternalConfig()) {
+ configFullPath = appConfig().configFile();
} else {
QStringList errors;
for (auto path :
@@ -818,11 +801,12 @@ QString MainWindow::address() const {
}
QString MainWindow::appPath(const QString &name) {
- return appConfig().synergyProgramDir() + name;
+ QDir dir(QCoreApplication::applicationDirPath());
+ return dir.filePath(name);
}
bool MainWindow::serverArgs(QStringList &args, QString &app) {
- app = appPath(appConfig().synergysName());
+ app = appPath(appConfig().coreServerName());
if (!QFile::exists(app)) {
QMessageBox::warning(
@@ -831,33 +815,24 @@ bool MainWindow::serverArgs(QStringList &args, QString &app) {
return false;
}
- if (appConfig().getServerClientMode() &&
- m_pLineEditClienIp->text().isEmpty()) {
+ if (appConfig().serverClientMode() && m_pLineEditClienIp->text().isEmpty()) {
QMessageBox::warning(
this, tr("Client IP address or name is empty"),
tr("Please fill in a client IP address or name."));
return false;
}
-#if defined(Q_OS_WIN)
- // wrap in quotes so a malicious user can't start \Program.exe as admin.
- app = QString("\"%1\"").arg(app);
-#endif
-
if (appConfig().logToFile()) {
appConfig().persistLogDir();
- args << "--log" << appConfig().logFilenameCmd();
+ args << "--log" << appConfig().logFilename();
}
QString configFilename = this->configFilename();
if (configFilename.isEmpty()) {
return false;
}
-#if defined(Q_OS_WIN)
- // wrap in quotes in case username contains spaces.
- configFilename = QString("\"%1\"").arg(configFilename);
-#endif
+
args << "-c" << configFilename << "--address" << address();
appendLogInfo("config file: " + configFilename);
@@ -870,10 +845,10 @@ bool MainWindow::serverArgs(QStringList &args, QString &app) {
return true;
}
-void MainWindow::stopSynergy() {
+void MainWindow::stopCore() {
appendLogDebug("stopping process");
- m_ExpectedRunningState = kStopped;
+ m_ExpectedRunningState = RuningState::Stopped;
if (appConfig().processMode() == ProcessMode::kService) {
stopService();
@@ -881,7 +856,7 @@ void MainWindow::stopSynergy() {
stopDesktop();
}
- setSynergyState(synergyDisconnected);
+ setCoreState(CoreState::Disconnected);
// reset so that new connects cause auto-hide.
m_AlreadyHidden = false;
@@ -894,87 +869,92 @@ void MainWindow::stopService() {
void MainWindow::stopDesktop() {
QMutexLocker locker(&m_StopDesktopMutex);
- if (!synergyProcess()) {
+ if (!m_pCoreProcess) {
return;
}
appendLogInfo("stopping synergy desktop process");
- if (synergyProcess()->isOpen()) {
- synergyProcess()->close();
+ if (m_pCoreProcess->isOpen()) {
+ m_pCoreProcess->close();
}
- delete synergyProcess();
- setSynergyProcess(NULL);
+ m_pCoreProcess->reset();
}
-void MainWindow::synergyFinished(int exitCode, QProcess::ExitStatus) {
+void MainWindow::coreProcessExit(int exitCode, QProcess::ExitStatus) {
if (exitCode == 0) {
- appendLogInfo(QString("process exited normally"));
+ appendLogInfo("process exited normally");
} else {
appendLogError(QString("process exited with error code: %1").arg(exitCode));
}
- if (m_ExpectedRunningState == kStarted) {
+ if (m_ExpectedRunningState == RuningState::Started) {
- setSynergyState(synergyPendingRetry);
- QTimer::singleShot(1000, this, SLOT(retryStart()));
- appendLogInfo(QString("detected process not running, auto restarting"));
+ if (coreState() != CoreState::PendingRetry) {
+ QTimer::singleShot(kRetryDelay, this, SLOT(retryStart()));
+ appendLogInfo("detected process not running, auto restarting");
+ } else {
+ appendLogInfo("detected process not running, already auto restarting");
+ }
+
+ setCoreState(CoreState::PendingRetry);
} else {
- setSynergyState(synergyDisconnected);
+ setCoreState(CoreState::Disconnected);
}
}
-void MainWindow::setSynergyState(qSynergyState state) {
+void MainWindow::setCoreState(CoreState state) {
// always assume connection is not secure when connection changes
// to anything except connected. the only way the padlock shows is
// when the correct TLS version string is detected.
- if (state != synergyConnected) {
+ if (state != CoreState::Connected) {
secureSocket(false);
}
- if (synergyState() == state)
+ if (coreState() == state)
return;
- if ((state == synergyConnected) || (state == synergyConnecting) ||
- (state == synergyListening) || (state == synergyPendingRetry)) {
+ if ((state == CoreState::Connected) || (state == CoreState::Connecting) ||
+ (state == CoreState::Listening) || (state == CoreState::PendingRetry)) {
disconnect(
- m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStartSynergy,
+ m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStartCore,
SLOT(trigger()));
connect(
- m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStopSynergy,
+ m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStopCore,
SLOT(trigger()));
+
m_pButtonToggleStart->setText(tr("&Stop"));
m_pButtonApply->setEnabled(true);
- } else if (state == synergyDisconnected) {
+
+ m_pActionStartCore->setEnabled(false);
+ m_pActionStopCore->setEnabled(true);
+
+ } else if (state == CoreState::Disconnected) {
disconnect(
- m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStopSynergy,
+ m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStopCore,
SLOT(trigger()));
connect(
- m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStartSynergy,
+ m_pButtonToggleStart, SIGNAL(clicked()), m_pActionStartCore,
SLOT(trigger()));
+
m_pButtonToggleStart->setText(tr("&Start"));
m_pButtonApply->setEnabled(false);
- }
- bool running = false;
- if (state == synergyConnected || state == synergyListening) {
- running = true;
+ m_pActionStartCore->setEnabled(true);
+ m_pActionStopCore->setEnabled(false);
}
- m_pActionStartSynergy->setEnabled(!running);
- m_pActionStopSynergy->setEnabled(running);
-
switch (state) {
- case synergyListening: {
- if (synergyType() == synergyServer) {
+ case CoreState::Listening: {
+ if (coreMode() == CoreMode::Server) {
setStatus(
tr("Synergy is waiting for clients").arg(m_SecureSocketVersion));
}
break;
}
- case synergyConnected: {
+ case CoreState::Connected: {
if (m_SecureSocket) {
setStatus(
tr("Synergy is connected (with %1)").arg(m_SecureSocketVersion));
@@ -984,20 +964,20 @@ void MainWindow::setSynergyState(qSynergyState state) {
}
break;
}
- case synergyConnecting:
+ case CoreState::Connecting:
setStatus(tr("Synergy is starting..."));
break;
- case synergyPendingRetry:
+ case CoreState::PendingRetry:
setStatus(tr("There was an error, retrying..."));
break;
- case synergyDisconnected:
+ case CoreState::Disconnected:
setStatus(tr("Synergy is not running"));
break;
}
setIcon(state);
- m_SynergyState = state;
+ m_CoreState = state;
}
void MainWindow::setVisible(bool visible) {
@@ -1057,8 +1037,8 @@ void MainWindow::setEdition(Edition edition) {
#ifdef SYNERGY_ENABLE_LICENSING
void MainWindow::InvalidLicense() {
- stopSynergy();
- m_AppConfig->activationHasRun(false);
+ stopCore();
+ m_AppConfig.activationHasRun(false);
}
void MainWindow::showLicenseNotice(const QString ¬ice) {
@@ -1074,7 +1054,15 @@ void MainWindow::showLicenseNotice(const QString ¬ice) {
#endif
void MainWindow::updateLocalFingerprint() {
- if (m_AppConfig->getCryptoEnabled() && Fingerprint::local().fileExists() &&
+ bool fingerprintExists = false;
+ try {
+ fingerprintExists = Fingerprint::local().fileExists();
+ } catch (const std::exception &e) {
+ qDebug() << e.what();
+ qFatal("Failed to check if fingerprint exists");
+ }
+
+ if (m_AppConfig.cryptoEnabled() && fingerprintExists &&
m_pRadioGroupServer->isChecked()) {
m_pLabelFingerprint->setVisible(true);
} else {
@@ -1105,7 +1093,7 @@ void MainWindow::on_m_pActionAbout_triggered() {
}
void MainWindow::on_m_pActionHelp_triggered() {
- QDesktopServices::openUrl(QUrl(HELP_URL));
+ QDesktopServices::openUrl(QUrl(kHelpUrl));
}
void MainWindow::updateWindowTitle() {
@@ -1123,12 +1111,12 @@ void MainWindow::updateWindowTitle() {
void MainWindow::on_m_pActionSettings_triggered() {
auto result = SettingsDialog(this, appConfig()).exec();
if (result == QDialog::Accepted) {
- enableServer(appConfig().getServerGroupChecked());
- enableClient(appConfig().getClientGroupChecked());
- auto state = synergyState();
- if ((state == synergyConnected) || (state == synergyConnecting) ||
- (state == synergyListening)) {
- restartSynergy();
+ enableServer(appConfig().serverGroupChecked());
+ enableClient(appConfig().clientGroupChecked());
+ auto state = coreState();
+ if ((state == CoreState::Connected) || (state == CoreState::Connecting) ||
+ (state == CoreState::Listening)) {
+ restartCore();
}
}
}
@@ -1168,10 +1156,10 @@ void MainWindow::showConfigureServer(const QString &message) {
auto result = dlg.exec();
if (result == QDialog::Accepted) {
- auto state = synergyState();
- if ((state == synergyConnected) || (state == synergyConnecting) ||
- (state == synergyListening)) {
- restartSynergy();
+ auto state = coreState();
+ if ((state == CoreState::Connected) || (state == CoreState::Connecting) ||
+ (state == CoreState::Listening)) {
+ restartCore();
}
}
}
@@ -1188,7 +1176,7 @@ void MainWindow::on_m_pActivate_triggered() {
void MainWindow::on_m_pButtonApply_clicked() {
m_clientConnection.setCheckConnection(true);
- restartSynergy();
+ restartCore();
}
#ifdef SYNERGY_ENABLE_LICENSING
@@ -1214,7 +1202,7 @@ int MainWindow::raiseActivationDialog() {
void MainWindow::on_windowShown() {
#ifdef SYNERGY_ENABLE_LICENSING
auto serialKey = m_LicenseManager->serialKey();
- if (!m_AppConfig->activationHasRun() && !serialKey.isValid()) {
+ if (!m_AppConfig.activationHasRun() && !serialKey.isValid()) {
setEdition(Edition::kUnregistered);
raiseActivationDialog();
}
@@ -1232,7 +1220,7 @@ QString MainWindow::getProfileRootForArg() {
dir.replace("/.synergy", "");
#endif
- return QString("\"%1\"").arg(dir);
+ return dir;
}
void MainWindow::secureSocket(bool secureSocket) {
@@ -1254,7 +1242,7 @@ void MainWindow::on_m_pLabelFingerprint_linkActivated(const QString &) {
}
void MainWindow::windowStateChanged() {
- if (windowState() == Qt::WindowMinimized && appConfig().getMinimizeToTray())
+ if (windowState() == Qt::WindowMinimized && appConfig().minimizeToTray())
hide();
}
@@ -1267,11 +1255,11 @@ void MainWindow::updateScreenName() {
}
void MainWindow::enableServer(bool enable) {
- m_AppConfig->setServerGroupChecked(enable);
+ m_AppConfig.setServerGroupChecked(enable);
m_pRadioGroupServer->setChecked(enable);
if (enable) {
- if (m_AppConfig->getServerClientMode()) {
+ if (m_AppConfig.serverClientMode()) {
m_pLabelClientIp->show();
m_pLineEditClienIp->show();
m_pButtonConnectToClient->show();
@@ -1296,11 +1284,11 @@ void MainWindow::enableServer(bool enable) {
}
void MainWindow::enableClient(bool enable) {
- m_AppConfig->setClientGroupChecked(enable);
+ m_AppConfig.setClientGroupChecked(enable);
m_pRadioGroupClient->setChecked(enable);
if (enable) {
- if (m_AppConfig->getClientHostMode()) {
+ if (m_AppConfig.clientHostMode()) {
m_pLabelServerName->hide();
m_pLineEditHostname->hide();
m_pButtonConnect->hide();
@@ -1318,23 +1306,16 @@ void MainWindow::enableClient(bool enable) {
}
}
-void MainWindow::closeEvent(QCloseEvent *event) {
-#if defined(Q_OS_LINUX)
- QCoreApplication::quit();
-#endif
- QWidget::closeEvent(event);
-}
-
void MainWindow::on_m_pRadioGroupServer_clicked(bool) {
enableServer(true);
enableClient(false);
- m_AppConfig->saveSettings();
+ m_AppConfig.saveSettings();
}
void MainWindow::on_m_pRadioGroupClient_clicked(bool) {
enableClient(true);
enableServer(false);
- m_AppConfig->saveSettings();
+ m_AppConfig.saveSettings();
}
void MainWindow::on_m_pButtonConnect_clicked() { on_m_pButtonApply_clicked(); }
diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h
index fe808d2fd..0b3e740bb 100644
--- a/src/gui/src/MainWindow.h
+++ b/src/gui/src/MainWindow.h
@@ -24,13 +24,14 @@
#include
#include
#include
+#include
#include "ui_MainWindowBase.h"
#include "ActivationDialog.h"
#include "AppConfig.h"
#include "ClientConnection.h"
-#include "ConfigWriter.h"
+#include "Config.h"
#include "QIpcClient.h"
#include "ServerConfig.h"
#include "ServerConnection.h"
@@ -70,34 +71,35 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase {
friend class ClientConnection;
public:
- enum qSynergyState {
- synergyDisconnected,
- synergyConnecting,
- synergyConnected,
- synergyListening,
- synergyPendingRetry
+ enum class CoreState {
+ Disconnected,
+ Connecting,
+ Connected,
+ Listening,
+ PendingRetry
};
- enum qSynergyType { synergyClient, synergyServer };
+ enum class CoreMode { Client, Server };
- enum qLevel { Error, Info };
+ enum class LogLevel { Error, Info };
- enum qRuningState { kStarted, kStopped };
+ enum class RuningState { Started, Stopped };
public:
#ifdef SYNERGY_ENABLE_LICENSING
MainWindow(AppConfig &appConfig, LicenseManager &licenseManager);
#else
- MainWindow(AppConfig &appConfig);
+ explicit MainWindow(AppConfig &appConfig);
#endif
- ~MainWindow();
+ ~MainWindow() override;
public:
void setVisible(bool visible);
- int synergyType() const {
- return m_pRadioGroupClient->isChecked() ? synergyClient : synergyServer;
+ CoreMode coreMode() const {
+ auto isClient = m_pRadioGroupClient->isChecked();
+ return isClient ? CoreMode::Client : CoreMode::Server;
}
- int synergyState() const { return m_SynergyState; }
+ CoreState coreState() const { return m_CoreState; }
QString hostname() const { return m_pLineEditHostname->text(); }
QString configFilename();
QString address() const;
@@ -124,8 +126,8 @@ public slots:
void appendLogInfo(const QString &text);
void appendLogDebug(const QString &text);
void appendLogError(const QString &text);
- void startSynergy();
- void retryStart(); // If the connection failed this will retry a startSynergy
+ void startCore();
+ void retryStart();
void actionStart();
void handleIdleService(const QString &text);
@@ -140,30 +142,26 @@ protected slots:
void on_m_pActionHelp_triggered();
void on_m_pActionSettings_triggered();
void on_m_pActivate_triggered();
- void synergyFinished(int exitCode, QProcess::ExitStatus);
+ void coreProcessExit(int exitCode, QProcess::ExitStatus);
void trayActivated(QSystemTrayIcon::ActivationReason reason);
- void stopSynergy();
+ void stopCore();
void logOutput();
void logError();
void updateFound(const QString &version);
void saveSettings();
protected:
- // TODO This should be properly using the ConfigWriter system.
- QSettings &settings() {
- return GUI::Config::ConfigWriter::make()->settings();
- }
- AppConfig &appConfig() { return *m_AppConfig; }
- AppConfig const &appConfig() const { return *m_AppConfig; }
- QProcess *synergyProcess() { return m_pSynergy; }
- void setSynergyProcess(QProcess *p) { m_pSynergy = p; }
+ QSettings &settings() { return *appConfig().config().currentSettings(); }
+ AppConfig &appConfig() { return m_AppConfig; }
+ AppConfig const &appConfig() const { return m_AppConfig; }
+ AppConfig *appConfigPtr() { return &m_AppConfig; }
void initConnections();
void createMenuBar();
void createStatusBar();
void createTrayIcon();
void loadSettings();
- void setIcon(qSynergyState state) const;
- void setSynergyState(qSynergyState state);
+ void setIcon(CoreState state) const;
+ void setCoreState(CoreState state);
bool checkForApp(int which, QString &app);
bool clientArgs(QStringList &args, QString &app);
bool serverArgs(QStringList &args, QString &app);
@@ -175,13 +173,6 @@ protected:
void stopDesktop();
void enableServer(bool enable);
void enableClient(bool enable);
- void closeEvent(QCloseEvent *event) override;
-
-#if defined(Q_OS_WIN)
- bool isServiceRunning(QString name);
-#else
- bool isServiceRunning();
-#endif
QString getProfileRootForArg();
void checkConnected(const QString &line);
@@ -194,43 +185,50 @@ protected:
void checkLicense(const QString &line);
#endif
QString getTimeStamp();
- void restartSynergy();
+ void restartCore();
- void showEvent(QShowEvent *);
+ void showEvent(QShowEvent *) override;
void secureSocket(bool secureSocket);
void windowStateChanged();
private:
+ void updateWindowTitle();
+
#ifdef SYNERGY_ENABLE_LICENSING
- LicenseManager *m_LicenseManager;
- bool m_ActivationDialogRunning;
- QStringList m_PendingClientNames;
+ LicenseManager *m_LicenseManager = nullptr;
#endif
- AppConfig *m_AppConfig;
- QProcess *m_pSynergy;
- int m_SynergyState;
+
+ AppConfig &m_AppConfig;
ServerConfig m_ServerConfig;
- bool m_AlreadyHidden;
- VersionChecker m_VersionChecker;
- QIpcClient m_IpcClient;
- QMenuBar *m_pMenuBar;
- QMenu *m_pMenuFile;
- QMenu *m_pMenuEdit;
- QMenu *m_pMenuWindow;
- QMenu *m_pMenuHelp;
- QAbstractButton *m_pCancelButton;
- TrayIcon m_trayIcon;
- qRuningState m_ExpectedRunningState;
- QMutex m_StopDesktopMutex;
- bool m_SecureSocket; // brief Is the program running a secure socket protocol
- // (SSL/TLS)
- QString m_SecureSocketVersion; // brief Contains the version of the Secure
- // Socket currently active
ServerConnection m_serverConnection;
ClientConnection m_clientConnection;
+ VersionChecker m_VersionChecker;
+ QIpcClient m_IpcClient;
+ TrayIcon m_trayIcon;
+ QMutex m_StopDesktopMutex;
- void updateWindowTitle();
+#ifdef SYNERGY_ENABLE_LICENSING
+ bool m_ActivationDialogRunning = false;
+ QStringList m_PendingClientNames;
+#endif
+
+ RuningState m_ExpectedRunningState = RuningState::Stopped;
+ std::unique_ptr m_pCoreProcess;
+ QMenuBar *m_pMenuBar = nullptr;
+ QMenu *m_pMenuFile = nullptr;
+ QMenu *m_pMenuEdit = nullptr;
+ QMenu *m_pMenuWindow = nullptr;
+ QMenu *m_pMenuHelp = nullptr;
+ QAbstractButton *m_pCancelButton = nullptr;
+ CoreState m_CoreState = CoreState::Disconnected;
+ bool m_AlreadyHidden = false;
+
+ /// @brief Is the program running a secure socket protocol (SSL/TLS)
+ bool m_SecureSocket = false;
+
+ /// @brief Contains the version of the Secure Socket currently active
+ QString m_SecureSocketVersion = "";
private slots:
void on_m_pButtonApply_clicked();
diff --git a/src/gui/src/MainWindowBase.ui b/src/gui/src/MainWindowBase.ui
index de3593ecf..999a175e8 100644
--- a/src/gui/src/MainWindowBase.ui
+++ b/src/gui/src/MainWindowBase.ui
@@ -6,8 +6,8 @@
0
0
- 720
- 552
+ 750
+ 650
@@ -18,8 +18,8 @@
- 720
- 552
+ 750
+ 550
@@ -357,7 +357,7 @@ background-color: rgba(192,192,192, 0.1);
- &Configure server
+ &Configure
@@ -692,7 +692,6 @@ background-color: rgba(192,192,192, 0.1);
Arial
-1
- 88
true
@@ -789,7 +788,7 @@ top: 3px;
Ctrl+Q
-
+
&Start
@@ -797,10 +796,10 @@ top: 3px;
Run
- Ctrl+S
+ Ctrl+S
-
+
false
@@ -811,7 +810,7 @@ top: 3px;
Stop
- Ctrl+T
+ Ctrl+T
@@ -894,7 +893,7 @@ top: 3px;
m_pButtonToggleStart
clicked()
- m_pActionStartSynergy
+ m_pActionStartCore
trigger()
diff --git a/src/gui/src/QSynergyApplication.cpp b/src/gui/src/QSynergyApplication.cpp
index 8692971da..ce6a6bc30 100644
--- a/src/gui/src/QSynergyApplication.cpp
+++ b/src/gui/src/QSynergyApplication.cpp
@@ -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
@@ -17,32 +17,31 @@
*/
#include "QSynergyApplication.h"
+
#include "MainWindow.h"
#include
#include
-QSynergyApplication *QSynergyApplication::s_Instance = NULL;
-
QSynergyApplication::QSynergyApplication(int &argc, char **argv)
: QApplication(argc, argv) {
- s_Instance = this;
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.
+ setStyle("Fusion");
}
-QSynergyApplication::~QSynergyApplication() {}
-
-void QSynergyApplication::commitData(QSessionManager &) {
+void QSynergyApplication::commitData(const QSessionManager &) const {
foreach (QWidget *widget, topLevelWidgets()) {
MainWindow *mainWindow = qobject_cast(widget);
if (mainWindow)
mainWindow->saveSettings();
}
}
-
-QSynergyApplication *QSynergyApplication::getInstance() { return s_Instance; }
diff --git a/src/gui/src/QSynergyApplication.h b/src/gui/src/QSynergyApplication.h
index c483e5878..be4a47dea 100644
--- a/src/gui/src/QSynergyApplication.h
+++ b/src/gui/src/QSynergyApplication.h
@@ -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,9 +16,7 @@
* along with this program. If not, see .
*/
-#if !defined(QSYNERGYAPPLICATION__H)
-
-#define QSYNERGYAPPLICATION__H
+#pragma once
#include
@@ -27,15 +25,7 @@ class QSessionManager;
class QSynergyApplication : public QApplication {
public:
QSynergyApplication(int &argc, char **argv);
- ~QSynergyApplication();
+ ~QSynergyApplication() override = default;
-public:
- void commitData(QSessionManager &manager);
-
- static QSynergyApplication *getInstance();
-
-private:
- static QSynergyApplication *s_Instance;
+ void commitData(const QSessionManager &manager) const;
};
-
-#endif
diff --git a/src/gui/src/Screen.h b/src/gui/src/Screen.h
index f8a6221ca..4b2253506 100644
--- a/src/gui/src/Screen.h
+++ b/src/gui/src/Screen.h
@@ -16,23 +16,20 @@
* along with this program. If not, see .
*/
-#if !defined(SCREEN__H)
+#pragma once
-#define SCREEN__H
+#include "ScreenConfig.h"
#include
#include
#include
#include
-#include "BaseConfig.h"
-
class QSettings;
class QTextStream;
-
class ScreenSettingsDialog;
-class Screen : public BaseConfig {
+class Screen : public ScreenConfig {
friend QDataStream &operator<<(QDataStream &outStream, const Screen &screen);
friend QDataStream &operator>>(QDataStream &inStream, Screen &screen);
friend class ScreenSettingsDialog;
@@ -102,5 +99,3 @@ private:
QDataStream &operator<<(QDataStream &outStream, const Screen &screen);
QDataStream &operator>>(QDataStream &inStream, Screen &screen);
-
-#endif
diff --git a/src/gui/src/BaseConfig.cpp b/src/gui/src/ScreenConfig.cpp
similarity index 77%
rename from src/gui/src/BaseConfig.cpp
rename to src/gui/src/ScreenConfig.cpp
index c7dab36e7..55042a76f 100644
--- a/src/gui/src/BaseConfig.cpp
+++ b/src/gui/src/ScreenConfig.cpp
@@ -16,14 +16,14 @@
* along with this program. If not, see .
*/
-#include "BaseConfig.h"
+#include "ScreenConfig.h"
-const char *BaseConfig::m_ModifierNames[] = {"shift", "ctrl", "alt",
- "meta", "super", "none"};
+const char *ScreenConfig::m_ModifierNames[] = {"shift", "ctrl", "alt",
+ "meta", "super", "none"};
-const char *BaseConfig::m_FixNames[] = {
+const char *ScreenConfig::m_FixNames[] = {
"halfDuplexCapsLock", "halfDuplexNumLock", "halfDuplexScrollLock",
"xtestIsXineramaUnaware"};
-const char *BaseConfig::m_SwitchCornerNames[] = {
+const char *ScreenConfig::m_SwitchCornerNames[] = {
"top-left", "top-right", "bottom-left", "bottom-right"};
diff --git a/src/gui/src/BaseConfig.h b/src/gui/src/ScreenConfig.h
similarity index 93%
rename from src/gui/src/BaseConfig.h
rename to src/gui/src/ScreenConfig.h
index becfd623e..61e78b037 100644
--- a/src/gui/src/BaseConfig.h
+++ b/src/gui/src/ScreenConfig.h
@@ -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,15 +16,14 @@
* along with this program. If not, see .
*/
-#if !defined(BASECONFIG_H)
-
-#define BASECONFIG_H
+#pragma once
#include
#include
#include
-class BaseConfig {
+/// @brief Screen configuration base class
+class ScreenConfig {
public:
enum Modifier {
DefaultMod = -1,
@@ -46,8 +45,8 @@ public:
enum Fix { CapsLock, NumLock, ScrollLock, XTest, NumFixes };
protected:
- BaseConfig() {}
- virtual ~BaseConfig() {}
+ explicit ScreenConfig() = default;
+ ~ScreenConfig() = default;
protected:
template
@@ -101,5 +100,3 @@ private:
static const char *m_FixNames[];
static const char *m_SwitchCornerNames[];
};
-
-#endif
diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp
index e8f633823..08264c5d1 100644
--- a/src/gui/src/ServerConfig.cpp
+++ b/src/gui/src/ServerConfig.cpp
@@ -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
@@ -17,7 +17,9 @@
*/
#include "ServerConfig.h"
+
#include "AddClientDialog.h"
+#include "Config.h"
#include "Hotkey.h"
#include "MainWindow.h"
@@ -26,6 +28,8 @@
#include
#include
+using synergy::gui::Config;
+
static const struct {
int x;
int y;
@@ -42,25 +46,20 @@ const int serverDefaultIndex = 7;
ServerConfig::ServerConfig(
int numColumns, int numRows, AppConfig *appConfig, MainWindow *mainWindow)
- :
-
+ : m_pAppConfig(appConfig),
+ m_pMainWindow(mainWindow),
m_Screens(numColumns),
m_NumColumns(numColumns),
m_NumRows(numRows),
- m_pAppConfig(appConfig),
- m_EnableDragAndDrop(false),
- m_DisableLockToScreen(false),
- m_ClipboardSharing(true),
- m_ClipboardSharingSize(defaultClipboardSharingSize()),
- m_pMainWindow(mainWindow) {
- GUI::Config::ConfigWriter::make()->registerClass(this);
- ServerConfig::loadSettings();
+ m_ClipboardSharingSize(defaultClipboardSharingSize()) {
+ appConfig->config().registerReceiever(this);
}
ServerConfig::~ServerConfig() {
try {
ServerConfig::saveSettings();
} catch (const std::exception &e) {
+ qDebug() << e.what();
m_pMainWindow->appendLogError(e.what());
}
}
@@ -165,8 +164,7 @@ void ServerConfig::saveSettings() {
settings().endGroup();
m_pAppConfig->saveSettings();
- // Tell the config writer there are changes
- GUI::Config::ConfigWriter::make()->markUnsaved();
+ m_pAppConfig->config().markUnsaved();
}
void ServerConfig::loadSettings() {
@@ -422,12 +420,12 @@ void ServerConfig::updateServerName() {
}
}
-const QString &ServerConfig::getConfigFile() const {
- return m_pAppConfig->getConfigFile();
+const QString &ServerConfig::configFile() const {
+ return m_pAppConfig->configFile();
}
-bool ServerConfig::getUseExternalConfig() const {
- return m_pAppConfig->getUseExternalConfig();
+bool ServerConfig::useExternalConfig() const {
+ return m_pAppConfig->useExternalConfig();
}
bool ServerConfig::isFull() const {
@@ -543,25 +541,23 @@ size_t ServerConfig::setClipboardSharingSize(size_t size) {
}
void ServerConfig::setClientAddress(const QString &address) {
- if (m_pAppConfig->getServerClientMode()) {
- m_clientAddress = address;
+ if (m_pAppConfig->serverClientMode()) {
+ m_ClientAddress = address;
}
}
QString ServerConfig::getClientAddress() const {
QString clientAddress;
- if (m_pAppConfig->getServerClientMode()) {
- clientAddress = m_clientAddress.trimmed();
+ if (m_pAppConfig->serverClientMode()) {
+ clientAddress = m_ClientAddress.trimmed();
}
return clientAddress;
}
QSettings &ServerConfig::settings() {
- using GUI::Config::ConfigWriter;
-
- return ConfigWriter::make()->settings();
+ return *m_pAppConfig->config().currentSettings();
}
bool ServerConfig::isHotkeysAvailable() const {
diff --git a/src/gui/src/ServerConfig.h b/src/gui/src/ServerConfig.h
index 7b3610434..d0e13655b 100644
--- a/src/gui/src/ServerConfig.h
+++ b/src/gui/src/ServerConfig.h
@@ -16,15 +16,13 @@
* along with this program. If not, see .
*/
-#if !defined(SERVERCONFIG__H)
-
-#define SERVERCONFIG__H
+#pragma once
#include
-#include "BaseConfig.h"
-#include "ConfigBase.h"
+#include "CommonConfig.h"
#include "Hotkey.h"
+#include "ScreenConfig.h"
#include "ScreenList.h"
class QTextStream;
@@ -35,7 +33,7 @@ class ServerConfigDialog;
class MainWindow;
class AppConfig;
-class ServerConfig : public BaseConfig, public GUI::Config::ConfigBase {
+class ServerConfig : public ScreenConfig, public synergy::gui::CommonConfig {
friend class ServerConfigDialog;
friend class ServerConnection;
friend QTextStream &
@@ -45,16 +43,10 @@ public:
ServerConfig(
int numColumns, int numRows, AppConfig *appConfig,
MainWindow *mainWindow);
-
- ServerConfig(const ServerConfig &src) = default;
- ServerConfig(ServerConfig &&) = default;
- ~ServerConfig();
- ServerConfig &operator=(const ServerConfig &src) = default;
- ServerConfig &operator=(ServerConfig &&) = delete;
+ ~ServerConfig() override;
bool operator==(const ServerConfig &sc) const;
-public:
const ScreenList &screens() const { return m_Screens; }
int numColumns() const { return m_NumColumns; }
int numRows() const { return m_NumRows; }
@@ -84,8 +76,8 @@ public:
int autoAddScreen(const QString name);
const QString &getServerName() const;
void updateServerName();
- const QString &getConfigFile() const;
- bool getUseExternalConfig() const;
+ const QString &configFile() const;
+ bool useExternalConfig() const;
bool isFull() const;
bool isScreenExists(const QString &screenName) const;
void addClient(const QString &clientName);
@@ -129,27 +121,28 @@ private:
void addToFirstEmptyGrid(const QString &clientName);
private:
+ bool m_HasHeartbeat = false;
+ int m_Heartbeat = 0;
+ bool m_RelativeMouseMoves = false;
+ bool m_Win32KeepForeground = false;
+ bool m_HasSwitchDelay = false;
+ int m_SwitchDelay = 0;
+ bool m_HasSwitchDoubleTap = false;
+ int m_SwitchDoubleTap = 0;
+ int m_SwitchCornerSize = 0;
+ bool m_EnableDragAndDrop = false;
+ bool m_DisableLockToScreen = false;
+ bool m_ClipboardSharing = true;
+ QString m_ClientAddress = "";
+ QList m_SwitchCorners;
+ HotkeyList m_Hotkeys;
+
+ AppConfig *m_pAppConfig;
+ MainWindow *m_pMainWindow;
ScreenList m_Screens;
int m_NumColumns;
int m_NumRows;
- bool m_HasHeartbeat;
- int m_Heartbeat;
- bool m_RelativeMouseMoves;
- bool m_Win32KeepForeground;
- bool m_HasSwitchDelay;
- int m_SwitchDelay;
- bool m_HasSwitchDoubleTap;
- int m_SwitchDoubleTap;
- int m_SwitchCornerSize;
- QList m_SwitchCorners;
- HotkeyList m_Hotkeys;
- AppConfig *m_pAppConfig;
- bool m_EnableDragAndDrop;
- bool m_DisableLockToScreen;
- bool m_ClipboardSharing;
size_t m_ClipboardSharingSize;
- QString m_clientAddress;
- MainWindow *m_pMainWindow;
};
QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config);
@@ -160,5 +153,3 @@ enum {
kAutoAddScreenManualClient,
kAutoAddScreenIgnore
};
-
-#endif
diff --git a/src/gui/src/ServerConfigDialog.cpp b/src/gui/src/ServerConfigDialog.cpp
index edaee081b..3b49881da 100644
--- a/src/gui/src/ServerConfigDialog.cpp
+++ b/src/gui/src/ServerConfigDialog.cpp
@@ -33,9 +33,9 @@ ServerConfigDialog::ServerConfigDialog(
QWidget *parent, ServerConfig &config, AppConfig &appConfig)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::ServerConfigDialogBase(),
- m_OrigServerConfig(config),
- m_OrigServerAppConfigUseExternalConfig(config.getUseExternalConfig()),
- m_OrigServerAppConfigExternalConfigFile(config.getConfigFile()),
+ m_OriginalServerConfig(config),
+ m_OriginalServerConfigIsExternal(config.useExternalConfig()),
+ m_OriginalServerConfigUsesExternalFile(config.configFile()),
m_ServerConfig(config),
m_ScreenSetupModel(
serverConfig().screens(), serverConfig().numColumns(),
@@ -44,9 +44,8 @@ ServerConfigDialog::ServerConfigDialog(
m_appConfig(appConfig) {
setupUi(this);
- m_pEditConfigFile->setText(serverConfig().getConfigFile());
- m_pCheckBoxUseExternalConfig->setChecked(
- serverConfig().getUseExternalConfig());
+ m_pEditConfigFile->setText(serverConfig().configFile());
+ m_pCheckBoxUseExternalConfig->setChecked(serverConfig().useExternalConfig());
m_pCheckBoxHeartbeat->setChecked(serverConfig().hasHeartbeat());
m_pSpinBoxHeartbeat->setValue(serverConfig().heartbeat());
@@ -62,13 +61,13 @@ ServerConfigDialog::ServerConfigDialog(
m_pSpinBoxSwitchDoubleTap->setValue(serverConfig().switchDoubleTap());
m_pCheckBoxCornerTopLeft->setChecked(
- serverConfig().switchCorner(BaseConfig::TopLeft));
+ serverConfig().switchCorner(ScreenConfig::TopLeft));
m_pCheckBoxCornerTopRight->setChecked(
- serverConfig().switchCorner(BaseConfig::TopRight));
+ serverConfig().switchCorner(ScreenConfig::TopRight));
m_pCheckBoxCornerBottomLeft->setChecked(
- serverConfig().switchCorner(BaseConfig::BottomLeft));
+ serverConfig().switchCorner(ScreenConfig::BottomLeft));
m_pCheckBoxCornerBottomRight->setChecked(
- serverConfig().switchCorner(BaseConfig::BottomRight));
+ serverConfig().switchCorner(ScreenConfig::BottomRight));
m_pSpinBoxSwitchCornerSize->setValue(serverConfig().switchCornerSize());
m_pCheckBoxDisableLockToScreen->setChecked(
serverConfig().disableLockToScreen());
@@ -186,25 +185,25 @@ ServerConfigDialog::ServerConfigDialog(
connect(
m_pCheckBoxCornerTopLeft, &QCheckBox::stateChanged, this,
[this](const int &v) {
- serverConfig().setSwitchCorner(BaseConfig::TopLeft, v);
+ serverConfig().setSwitchCorner(ScreenConfig::TopLeft, v);
onChange();
});
connect(
m_pCheckBoxCornerTopRight, &QCheckBox::stateChanged, this,
[this](const int &v) {
- serverConfig().setSwitchCorner(BaseConfig::TopRight, v);
+ serverConfig().setSwitchCorner(ScreenConfig::TopRight, v);
onChange();
});
connect(
m_pCheckBoxCornerBottomLeft, &QCheckBox::stateChanged, this,
[this](const int &v) {
- serverConfig().setSwitchCorner(BaseConfig::BottomLeft, v);
+ serverConfig().setSwitchCorner(ScreenConfig::BottomLeft, v);
onChange();
});
connect(
m_pCheckBoxCornerBottomRight, &QCheckBox::stateChanged, this,
[this](const int &v) {
- serverConfig().setSwitchCorner(BaseConfig::BottomRight, v);
+ serverConfig().setSwitchCorner(ScreenConfig::BottomRight, v);
onChange();
});
connect(
@@ -261,14 +260,14 @@ void ServerConfigDialog::accept() {
// now that the dialog has been accepted, copy the new server config to the
// original one, which is a reference to the one in MainWindow.
- setOrigServerConfig(serverConfig());
+ setOriginalServerConfig(serverConfig());
QDialog::accept();
}
void ServerConfigDialog::reject() {
- serverConfig().setUseExternalConfig(m_OrigServerAppConfigUseExternalConfig);
- serverConfig().setConfigFile(m_OrigServerAppConfigExternalConfigFile);
+ serverConfig().setUseExternalConfig(m_OriginalServerConfigIsExternal);
+ serverConfig().setConfigFile(m_OriginalServerConfigUsesExternalFile);
QDialog::reject();
}
@@ -460,10 +459,9 @@ bool ServerConfigDialog::addComputer(const QString &clientName, bool doSilent) {
void ServerConfigDialog::onChange() {
bool isAppConfigDataEqual =
- m_OrigServerAppConfigUseExternalConfig ==
- serverConfig().getUseExternalConfig() &&
- m_OrigServerAppConfigExternalConfigFile == serverConfig().getConfigFile();
+ m_OriginalServerConfigIsExternal == serverConfig().useExternalConfig() &&
+ m_OriginalServerConfigUsesExternalFile == serverConfig().configFile();
m_pButtonBox->button(QDialogButtonBox::Ok)
->setEnabled(
- !isAppConfigDataEqual || !(m_OrigServerConfig == m_ServerConfig));
+ !isAppConfigDataEqual || !(m_OriginalServerConfig == m_ServerConfig));
}
diff --git a/src/gui/src/ServerConfigDialog.h b/src/gui/src/ServerConfigDialog.h
index 31722f753..3fbf7f8d7 100644
--- a/src/gui/src/ServerConfigDialog.h
+++ b/src/gui/src/ServerConfigDialog.h
@@ -61,15 +61,17 @@ protected slots:
protected:
bool addComputer(const QString &clientName, bool doSilent);
ServerConfig &serverConfig() { return m_ServerConfig; }
- void setOrigServerConfig(const ServerConfig &s) { m_OrigServerConfig = s; }
+ void setOriginalServerConfig(const ServerConfig &s) {
+ m_OriginalServerConfig = s;
+ }
ScreenSetupModel &model() { return m_ScreenSetupModel; }
AppConfig &appConfig() { return m_appConfig; }
private:
- ServerConfig &m_OrigServerConfig;
- bool m_OrigServerAppConfigUseExternalConfig;
- QString m_OrigServerAppConfigExternalConfigFile;
+ ServerConfig &m_OriginalServerConfig;
ServerConfig m_ServerConfig;
+ bool m_OriginalServerConfigIsExternal;
+ QString m_OriginalServerConfigUsesExternalFile;
ScreenSetupModel m_ScreenSetupModel;
QString m_Message;
AppConfig &m_appConfig;
diff --git a/src/gui/src/ServerConnection.cpp b/src/gui/src/ServerConnection.cpp
index 2528a2b25..a5359667d 100644
--- a/src/gui/src/ServerConnection.cpp
+++ b/src/gui/src/ServerConnection.cpp
@@ -30,7 +30,7 @@ ServerConnection::ServerConnection(MainWindow &parent) : m_parent(parent) {}
void ServerConnection::update(const QString &line) {
ServerMessage message(line);
- if (!m_parent.appConfig().getUseExternalConfig() &&
+ if (!m_parent.appConfig().useExternalConfig() &&
message.isNewClientMessage() &&
!m_ignoredClients.contains(message.getClientName())) {
addClient(message.getClientName());
@@ -73,6 +73,6 @@ void ServerConnection::configureClient(const QString &clientName) {
&m_parent, m_parent.serverConfig(), m_parent.appConfig());
if (dlg.addClient(clientName) && dlg.exec() == QDialog::Accepted) {
- m_parent.restartSynergy();
+ m_parent.restartCore();
}
}
diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp
index f28117bde..6e233f914 100644
--- a/src/gui/src/SettingsDialog.cpp
+++ b/src/gui/src/SettingsDialog.cpp
@@ -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
@@ -15,14 +15,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
#include "SettingsDialog.h"
-#include "validators/ScreenNameValidator.h"
#include "AppConfig.h"
-#include "CoreInterface.h"
#include "MainWindow.h"
-#include "QSynergyApplication.h"
-#include "QUtility.h"
#include "SslCertificate.h"
#include "UpgradeDialog.h"
@@ -31,6 +28,7 @@
#include
#include
#include
+#include
SettingsDialog::SettingsDialog(QWidget *parent, AppConfig &config)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
@@ -43,15 +41,15 @@ SettingsDialog::SettingsDialog(QWidget *parent, AppConfig &config)
loadFromConfig();
m_isSystemAtStart = appConfig().isSystemScoped();
- buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
- enableControls(appConfig().isWritable());
-
- m_pCheckBoxLanguageSync->setEnabled(isClientMode());
- m_pCheckBoxScrollDirection->setEnabled(isClientMode());
+ updateControlsEnabled();
const auto &serveConfig = m_pMainWindow->serverConfig();
- m_pLineEditScreenName->setValidator(new validators::ScreenNameValidator(
- m_pLineEditScreenName, m_pLabelNameError, (&serveConfig.screens())));
+ m_screenNameValidator = std::make_unique(
+ 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,
@@ -86,6 +84,11 @@ SettingsDialog::SettingsDialog(QWidget *parent, AppConfig &config)
}
void SettingsDialog::accept() {
+ if (!m_nameError.isEmpty()) {
+ QMessageBox::warning(this, tr("Invalid screen name"), m_nameError);
+ return;
+ }
+
appConfig().setLoadFromSystemScope(m_pRadioSystemScope->isChecked());
appConfig().setScreenName(m_pLineEditScreenName->text());
appConfig().setPort(m_pSpinBoxPort->value());
@@ -98,13 +101,15 @@ void SettingsDialog::accept() {
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().setTlsCertPath(m_pLineEditCertificatePath->text());
+ appConfig().setTlsKeyLength(m_pComboBoxKeyLength->currentText());
appConfig().setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked());
appConfig().setLanguageSync(m_pCheckBoxLanguageSync->isChecked());
appConfig().setInvertScrollDirection(m_pCheckBoxScrollDirection->isChecked());
appConfig().setClientHostMode(m_pCheckBoxClientHostMode->isChecked());
appConfig().setServerClientMode(m_pCheckBoxServerClientMode->isChecked());
+ appConfig().setServiceEnabled(m_pCheckBoxServiceEnabled->isChecked());
+ appConfig().setMinimizeOnClose(m_pCheckBoxMinimizeOnClose->isChecked());
appConfig().saveSettings();
QDialog::accept();
@@ -127,18 +132,17 @@ void SettingsDialog::loadFromConfig() {
m_pComboLogLevel->setCurrentIndex(appConfig().logLevel());
m_pCheckBoxLogToFile->setChecked(appConfig().logToFile());
m_pLineEditLogFilename->setText(appConfig().logFilename());
- m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide());
- m_pCheckBoxPreventSleep->setChecked(appConfig().getPreventSleep());
- m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray());
- m_pLineEditCertificatePath->setText(appConfig().getTLSCertPath());
- m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
- m_pCheckBoxLanguageSync->setChecked(m_appConfig.getLanguageSync());
- m_pCheckBoxScrollDirection->setChecked(
- m_appConfig.getInvertScrollDirection());
- m_pCheckBoxClientHostMode->setChecked(m_appConfig.getClientHostMode());
- m_pCheckBoxServerClientMode->setChecked(m_appConfig.getServerClientMode());
-
- setupSeurity();
+ 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.cryptoEnabled());
+ m_pCheckBoxLanguageSync->setChecked(m_appConfig.languageSync());
+ m_pCheckBoxScrollDirection->setChecked(m_appConfig.invertScrollDirection());
+ m_pCheckBoxClientHostMode->setChecked(m_appConfig.clientHostMode());
+ m_pCheckBoxServerClientMode->setChecked(m_appConfig.serverClientMode());
+ m_pCheckBoxServiceEnabled->setChecked(m_appConfig.serviceEnabled());
+ m_pCheckBoxMinimizeOnClose->setChecked(m_appConfig.minimizeOnClose());
if (m_appConfig.isSystemScoped()) {
m_pRadioSystemScope->setChecked(true);
@@ -146,44 +150,42 @@ void SettingsDialog::loadFromConfig() {
m_pRadioUserScope->setChecked(true);
}
-#if defined(Q_OS_WIN)
- m_pComboElevate->setCurrentIndex(static_cast(appConfig().elevateMode()));
-
-#else
- // elevate checkbox is only useful on ms windows.
- m_pLabelElevate->hide();
- m_pComboElevate->hide();
-#endif
-
- m_pCheckBoxClientHostMode->setVisible(
- isClientMode() && appConfig().getInitiateConnectionFromServer());
- m_pCheckBoxServerClientMode->setVisible(
- !isClientMode() && appConfig().getInitiateConnectionFromServer());
+ updateTlsControls();
}
-void SettingsDialog::setupSeurity() {
- // If the tls file exists test its key length
- if (QFile(appConfig().getTLSCertPath()).exists()) {
- updateKeyLengthOnFile(appConfig().getTLSCertPath());
+void SettingsDialog::updateTlsControls() {
+ if (QFile(appConfig().tlsCertPath()).exists()) {
+ updateKeyLengthOnFile(appConfig().tlsCertPath());
} else {
m_pComboBoxKeyLength->setCurrentIndex(
- m_pComboBoxKeyLength->findText(appConfig().getTLSKeyLength()));
+ m_pComboBoxKeyLength->findText(appConfig().tlsKeyLength()));
}
- m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
+ m_pCheckBoxEnableCrypto->setChecked(m_appConfig.cryptoEnabled());
- if (appConfig().getClientGroupChecked()) {
- m_pLabelKeyLength->hide();
- m_pComboBoxKeyLength->hide();
- m_pLabelCertificate->hide();
- m_pLineEditCertificatePath->hide();
- m_pPushButtonBrowseCert->hide();
- m_pPushButtonRegenCert->hide();
- }
+ updateTlsControlsEnabled();
+}
+
+void SettingsDialog::updateTlsControlsEnabled() {
+ auto clientMode = appConfig().clientGroupChecked();
+ auto cryptoAvailable = appConfig().cryptoAvailable();
+ auto tlsChecked = m_pCheckBoxEnableCrypto->isChecked();
+ auto enabled = !clientMode && cryptoAvailable && tlsChecked;
+
+ qDebug(
+ "TLS controls enabled=%d, client=%d, crypto=%d, checked=%d", enabled,
+ clientMode, cryptoAvailable, tlsChecked);
+
+ m_pLabelKeyLength->setEnabled(enabled);
+ m_pComboBoxKeyLength->setEnabled(enabled);
+ m_pLabelCertificate->setEnabled(enabled);
+ m_pLineEditCertificatePath->setEnabled(enabled);
+ m_pPushButtonBrowseCert->setEnabled(enabled);
+ m_pPushButtonRegenCert->setEnabled(enabled);
}
bool SettingsDialog::isClientMode() const {
- return (m_pMainWindow->synergyType() == MainWindow::synergyClient);
+ return (m_pMainWindow->coreMode() == MainWindow::CoreMode::Client);
}
void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i) {
@@ -192,7 +194,6 @@ void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i) {
m_pLabelLogPath->setEnabled(checked);
m_pLineEditLogFilename->setEnabled(checked);
m_pButtonBrowseLog->setEnabled(checked);
- buttonBox->button(QDialogButtonBox::Save)->setEnabled(isModified());
}
void SettingsDialog::on_m_pButtonBrowseLog_clicked() {
@@ -206,17 +207,9 @@ void SettingsDialog::on_m_pButtonBrowseLog_clicked() {
}
void SettingsDialog::on_m_pCheckBoxEnableCrypto_clicked(bool checked) {
- if (appConfig().isCryptoAvailable()) {
- m_pLabelKeyLength->setEnabled(checked);
- m_pComboBoxKeyLength->setEnabled(checked);
- m_pLabelCertificate->setEnabled(checked);
- m_pLineEditCertificatePath->setEnabled(checked);
- m_pPushButtonBrowseCert->setEnabled(checked);
- m_pPushButtonRegenCert->setEnabled(checked);
+ updateTlsControlsEnabled();
- buttonBox->button(QDialogButtonBox::Save)->setEnabled(isModified());
- } else {
- m_pCheckBoxEnableCrypto->setChecked(false);
+ if (!appConfig().cryptoAvailable()) {
#ifdef SYNERGY_ENABLE_LICENSING
auto edition = appConfig().edition();
@@ -238,9 +231,7 @@ void SettingsDialog::on_m_pRadioSystemScope_toggled(bool checked) {
// We only need to test the System scoped Radio as they are connected
appConfig().setLoadFromSystemScope(checked);
loadFromConfig();
- buttonBox->button(QDialogButtonBox::Save)
- ->setEnabled(m_isSystemAtStart != checked);
- enableControls(appConfig().isWritable());
+ updateControlsEnabled();
}
void SettingsDialog::on_m_pPushButtonBrowseCert_clicked() {
@@ -252,24 +243,23 @@ void SettingsDialog::on_m_pPushButtonBrowseCert_clicked() {
if (!fileName.isEmpty()) {
m_pLineEditCertificatePath->setText(fileName);
// If the tls file exists test its key length and update
- if (QFile(appConfig().getTLSCertPath()).exists()) {
+ if (QFile(appConfig().tlsCertPath()).exists()) {
updateKeyLengthOnFile(fileName);
}
}
- updateRegenButton();
+ updateTlsRegenerateButton();
}
void SettingsDialog::on_m_pComboBoxKeyLength_currentIndexChanged(int index) {
- buttonBox->button(QDialogButtonBox::Save)->setEnabled(isModified());
- updateRegenButton();
+ updateTlsRegenerateButton();
}
-void SettingsDialog::updateRegenButton() {
+void SettingsDialog::updateTlsRegenerateButton() {
// Disable the Regenerate cert button if the key length is different to saved
auto keyChanged =
- appConfig().getTLSKeyLength() != m_pComboBoxKeyLength->currentText();
+ appConfig().tlsKeyLength() != m_pComboBoxKeyLength->currentText();
auto pathChanged =
- appConfig().getTLSCertPath() != m_pLineEditCertificatePath->text();
+ appConfig().tlsCertPath() != m_pLineEditCertificatePath->text();
// NOR the above bools, if any have changed regen should be disabled as it
// will be done on save
auto nor = !(keyChanged || pathChanged);
@@ -287,82 +277,65 @@ void SettingsDialog::updateKeyLengthOnFile(const QString &path) {
auto index = m_pComboBoxKeyLength->findText(length);
m_pComboBoxKeyLength->setCurrentIndex(index);
// Also update what is in the appconfig to match the file itself
- appConfig().setTLSKeyLength(length);
+ appConfig().setTlsKeyLength(length);
}
-bool SettingsDialog::isModified() {
- return (
- !m_pLineEditScreenName->text().isEmpty() &&
- m_pLabelNameError->text().isEmpty() &&
- (appConfig().screenName() != m_pLineEditScreenName->text() ||
- appConfig().port() != m_pSpinBoxPort->value() ||
- appConfig().networkInterface() != m_pLineEditInterface->text() ||
- appConfig().logLevel() != m_pComboLogLevel->currentIndex() ||
- appConfig().logToFile() != m_pCheckBoxLogToFile->isChecked() ||
- appConfig().logFilename() != m_pLineEditLogFilename->text() ||
- appConfig().elevateMode() !=
- static_cast(m_pComboElevate->currentIndex()) ||
- appConfig().getAutoHide() != m_pCheckBoxAutoHide->isChecked() ||
- appConfig().getPreventSleep() != m_pCheckBoxPreventSleep->isChecked() ||
- appConfig().getMinimizeToTray() !=
- m_pCheckBoxMinimizeToTray->isChecked() ||
- appConfig().getTLSCertPath() != m_pLineEditCertificatePath->text() ||
- appConfig().getTLSKeyLength() != m_pComboBoxKeyLength->currentText() ||
- appConfig().getCryptoEnabled() != m_pCheckBoxEnableCrypto->isChecked() ||
- appConfig().isSystemScoped() != m_isSystemAtStart ||
- appConfig().getLanguageSync() != m_pCheckBoxLanguageSync->isChecked() ||
- appConfig().getClientHostMode() !=
- m_pCheckBoxClientHostMode->isChecked() ||
- appConfig().getServerClientMode() !=
- m_pCheckBoxServerClientMode->isChecked() ||
- appConfig().getInvertScrollDirection() !=
- m_pCheckBoxScrollDirection->isChecked()));
-}
+void SettingsDialog::updateControlsEnabled() {
+ bool writable = appConfig().isWritable();
-void SettingsDialog::enableControls(bool enable) {
- m_pLineEditScreenName->setEnabled(enable);
- m_pSpinBoxPort->setEnabled(enable);
- m_pLineEditInterface->setEnabled(enable);
- m_pComboLogLevel->setEnabled(enable);
- m_pCheckBoxLogToFile->setEnabled(enable);
- m_pComboElevate->setEnabled(enable);
- m_pCheckBoxAutoHide->setEnabled(enable);
- m_pCheckBoxPreventSleep->setEnabled(enable);
- m_pCheckBoxMinimizeToTray->setEnabled(enable);
- m_pLineEditCertificatePath->setEnabled(enable);
- m_pComboBoxKeyLength->setEnabled(enable);
- m_pPushButtonBrowseCert->setEnabled(enable);
- m_pCheckBoxEnableCrypto->setEnabled(enable);
- m_labelAdminRightsMessage->setVisible(!enable);
- m_pCheckBoxLanguageSync->setEnabled(enable);
- m_pCheckBoxScrollDirection->setEnabled(enable);
- m_pCheckBoxClientHostMode->setEnabled(enable);
- m_pCheckBoxServerClientMode->setEnabled(enable);
+ m_pLineEditScreenName->setEnabled(writable);
+ m_pSpinBoxPort->setEnabled(writable);
+ m_pLineEditInterface->setEnabled(writable);
+ m_pComboLogLevel->setEnabled(writable);
+ m_pCheckBoxLogToFile->setEnabled(writable);
+ 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);
+ m_pCheckBoxEnableCrypto->setEnabled(writable);
+ m_pCheckBoxClientHostMode->setEnabled(writable);
+ m_pCheckBoxServerClientMode->setEnabled(writable);
+ m_pCheckBoxServiceEnabled->setEnabled(writable);
+ m_pCheckBoxMinimizeOnClose->setEnabled(writable);
- if (enable) {
- m_pLabelLogPath->setEnabled(m_pCheckBoxLogToFile->isChecked());
- m_pLineEditLogFilename->setEnabled(m_pCheckBoxLogToFile->isChecked());
- m_pButtonBrowseLog->setEnabled(m_pCheckBoxLogToFile->isChecked());
- m_pLabelKeyLength->setEnabled(m_pCheckBoxEnableCrypto->isChecked());
- m_pComboBoxKeyLength->setEnabled(m_pCheckBoxEnableCrypto->isChecked());
- m_pLabelCertificate->setEnabled(m_pCheckBoxEnableCrypto->isChecked());
- m_pLineEditCertificatePath->setEnabled(
- m_pCheckBoxEnableCrypto->isChecked());
- m_pPushButtonBrowseCert->setEnabled(m_pCheckBoxEnableCrypto->isChecked());
- updateRegenButton();
- } else {
- m_pLabelLogPath->setEnabled(enable);
- m_pLineEditLogFilename->setEnabled(enable);
- m_pButtonBrowseLog->setEnabled(enable);
- m_pLabelKeyLength->setEnabled(enable);
- m_pComboBoxKeyLength->setEnabled(enable);
- m_pLabelCertificate->setEnabled(enable);
- m_pLineEditCertificatePath->setEnabled(enable);
- m_pPushButtonBrowseCert->setEnabled(enable);
- m_pPushButtonRegenCert->setEnabled(enable);
+ m_pCheckBoxLanguageSync->setEnabled(writable && isClientMode());
+ m_pCheckBoxScrollDirection->setEnabled(writable && isClientMode());
+
+#if !defined(Q_OS_WIN)
+ m_pCheckBoxServiceEnabled->setEnabled(false);
+#endif
+
+ m_pCheckBoxClientHostMode->setEnabled(
+ writable && isClientMode() && appConfig().initiateConnectionFromServer());
+ m_pCheckBoxServerClientMode->setEnabled(
+ writable && !isClientMode() &&
+ appConfig().initiateConnectionFromServer());
+
+ m_pLabelLogPath->setEnabled(writable && m_pCheckBoxLogToFile->isChecked());
+ m_pLineEditLogFilename->setEnabled(
+ writable && m_pCheckBoxLogToFile->isChecked());
+ m_pButtonBrowseLog->setEnabled(writable && m_pCheckBoxLogToFile->isChecked());
+
+ updateTlsControlsEnabled();
+
+ if (writable) {
+ updateTlsRegenerateButton();
}
+
+#if defined(Q_OS_WIN)
+ m_pComboElevate->setCurrentIndex(static_cast(appConfig().elevateMode()));
+#else
+ // elevate checkbox is only usable on ms windows.
+ m_pLabelElevate->setEnabled(false);
+ m_pComboElevate->setEnabled(false);
+#endif
+
+ updateTlsControls();
}
-void SettingsDialog::onChange() {
- buttonBox->button(QDialogButtonBox::Save)->setEnabled(isModified());
+void SettingsDialog::on_m_pScreenNameValidator_finished(const QString &error) {
+ m_nameError = error;
}
diff --git a/src/gui/src/SettingsDialog.h b/src/gui/src/SettingsDialog.h
index d0af1287d..e1917dede 100644
--- a/src/gui/src/SettingsDialog.h
+++ b/src/gui/src/SettingsDialog.h
@@ -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,15 +16,15 @@
* along with this program. If not, see .
*/
-#if !defined(SETTINGSDIALOG_H)
-
-#define SETTINGSDIALOG_H
+#pragma once
#include "ui_SettingsDialogBase.h"
-#include
-#include
#include "CoreInterface.h"
+#include "validators/ScreenNameValidator.h"
+
+#include
+#include
class MainWindow;
class AppConfig;
@@ -35,49 +35,46 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase {
public:
SettingsDialog(QWidget *parent, AppConfig &config);
static QString browseForSynergyc(
- QWidget *parent, const QString &programDir, const QString &synergycName);
+ QWidget *parent, const QString &programDir,
+ const QString &coreClientName);
static QString browseForSynergys(
- QWidget *parent, const QString &programDir, const QString &synergysName);
+ QWidget *parent, const QString &programDir,
+ const QString &coreServerName);
protected:
void accept() override;
void reject() override;
AppConfig &appConfig() { return m_appConfig; }
- /// @brief Causes the dialog to load all the settings from m_appConfig
+ /// @brief Load all settings.
void loadFromConfig();
- /// @brief Check if the regenerate button should be enabled or disabled and
- /// sets it
- void updateRegenButton();
+ /// @brief Enables or disables the TLS regenerate button.
+ void updateTlsRegenerateButton();
- /// @brief Updates the key length value based on the loaded file
- /// @param [in] QString path The path to the file to test
+ /// @brief Updates the key length value based on the loaded file.
void updateKeyLengthOnFile(const QString &path);
- /// @brief Check if there are modifications.
- /// @return true if there are modifications.
- bool isModified();
+ /// @brief Enables controls when they should be.
+ void updateControlsEnabled();
- /// @brief Enables\disables all controls.
- void enableControls(bool enabled);
-
- /// @brief This method setups security section in setting
- void setupSeurity();
-
- /// @brief Returns true if current mode is a client mode
bool isClientMode() const;
+ void updateTlsControls();
+ void updateTlsControlsEnabled();
private:
MainWindow *m_pMainWindow;
AppConfig &m_appConfig;
CoreInterface m_CoreInterface;
+ std::unique_ptr m_screenNameValidator;
/// @brief Stores settings scope at start of settings dialog
/// This is neccessary to restore state if user changes
/// the scope and doesn't save changes
bool m_isSystemAtStart = false;
+ QString m_nameError = "";
+
private slots:
void on_m_pCheckBoxEnableCrypto_clicked(bool checked);
void on_m_pCheckBoxLogToFile_stateChanged(int);
@@ -100,8 +97,5 @@ private slots:
/// haven't changed
void on_m_pPushButtonRegenCert_clicked();
- /// @brief This slot handles common functionality for all fields.
- void onChange();
+ void on_m_pScreenNameValidator_finished(const QString &error);
};
-
-#endif
diff --git a/src/gui/src/SettingsDialogBase.ui b/src/gui/src/SettingsDialogBase.ui
index a92485191..5d9bfda30 100644
--- a/src/gui/src/SettingsDialogBase.ui
+++ b/src/gui/src/SettingsDialogBase.ui
@@ -6,8 +6,8 @@
0
0
- 404
- 819
+ 417
+ 786
@@ -38,64 +38,6 @@
5
- -
-
-
-
- 0
- 0
-
-
-
- Security
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 3
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Advanced
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 3
-
-
-
-
-
@@ -181,7 +123,7 @@ background-color: rgba(192,192,192, 0.1);
- &Level
+ Level
m_pComboLogLevel
@@ -285,8 +227,213 @@ background-color: rgba(192,192,192, 0.1);
- -
-
+
-
+
+
+ .QFrame{
+border: 1px solid rgba(192,192,192, 0.2);
+border-radius: 4px;
+background-color: rgba(192,192,192, 0.1);
+}
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 17
+
+
+ 17
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ 0
+
+
+
+ Computer &name
+
+
+ m_pLineEditScreenName
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Maximum
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+ true
+
+
+ 255
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ P&ort
+
+
+ m_pSpinBoxPort
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ 65535
+
+
+ 24800
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Network IP
+
+
+ m_pLineEditInterface
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ Minimize to tray on close
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Qt::LeftToRight
+
+
+ Minimize to system &tray
+
+
+
+
+
+ -
+
+
+ Hide window on start
+
+
+
+
+
+
+ -
+
0
@@ -294,12 +441,12 @@ background-color: rgba(192,192,192, 0.1);
- Logs
+ Security
- -
-
+
-
+
Qt::Vertical
@@ -337,104 +484,125 @@ background-color: rgba(192,192,192, 0.1);
QFrame::Raised
- -
+
-
- Invert scroll direction on this computer
+ Invert scroll direction on this computer (client mode)
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Host mode
-
-
-
- -
-
-
- Specify when the Synergy service should run at an elevated privilege level
-
-
- 0
-
-
-
-
- As Needed
-
-
- -
-
- Always
-
-
- -
-
- Never
-
-
-
-
- -
+
-
- &Use server's keyboard language on this machine
+ Use server's keyboard language on this computer (client mode)
- -
-
+
-
+
- Client mode
+ Use background service (daemon)
- -
-
-
-
- 0
- 0
-
-
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Elevate privileges (service required)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Specify when the Synergy service should run at an elevated privilege level
+
+
+ 0
+
+
-
+
+ As Needed
+
+
+ -
+
+ Always
+
+
+ -
+
+ Never
+
+
+
+
+
+
+ -
+
- Elevate privileges
+ Stop this computer from sleeping
+ -
+
+
+ QLayout::SetNoConstraint
+
+
-
+
+
+ Use server as a client
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Use client in host mode
+
+
+
+
+
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 3
-
-
-
-
-
@@ -472,7 +640,7 @@ background-color: rgba(192,192,192, 0.1);
true
- Enable &TLS encryption
+ Enable TLS encryption
@@ -628,6 +796,61 @@ background-color: rgba(192,192,192, 0.1);
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Advanced
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Logs
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 3
+
+
+
+
-
@@ -654,13 +877,6 @@ background-color: rgba(192,192,192, 0.1);
6
-
-
-
-
- Current user
-
-
-
-
@@ -671,33 +887,18 @@ background-color: rgba(192,192,192, 0.1);
- -
-
-
- false
-
-
-
- 0
- 0
-
-
-
-
- 50
- false
-
-
+
-
+
- Note: Only Admins can edit settings for all users.
+ Current user
- -
-
+
-
+
Qt::Horizontal
@@ -706,56 +907,8 @@ background-color: rgba(192,192,192, 0.1);
- -
-
-
- 0
-
-
- 1
-
-
- 0
-
-
- 6
-
-
-
-
-
- false
-
-
-
- 0
- 0
-
-
-
- Enable Auto Config
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#007af4;">Install Bonjour</span></a></p></body></html>
-
-
- Qt::RichText
-
-
-
-
-
- -
-
+
-
+
Qt::Vertical
@@ -770,244 +923,56 @@ background-color: rgba(192,192,192, 0.1);
- -
-
-
- .QFrame{
-border: 1px solid rgba(192,192,192, 0.2);
-border-radius: 4px;
-background-color: rgba(192,192,192, 0.1);
-}
-
+
-
+
+
+ Qt::Vertical
-
- QFrame::StyledPanel
+
+ QSizePolicy::Fixed
-
- QFrame::Raised
+
+
+ 20
+ 3
+
-
-
- 17
-
-
- 17
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 75
- 0
-
-
-
- Computer name
-
-
- m_pLineEditScreenName
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Maximum
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- true
-
-
- 255
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- color: #EC4C47;
-font-size: 13px;
-font-family: Arial;
-font-weight: bold;
-
-
-
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
- P&ort
-
-
- m_pSpinBoxPort
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
- 65535
-
-
- 24800
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Network IP
-
-
- m_pLineEditInterface
-
-
-
- -
-
-
- true
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- &Hide on startup
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- Qt::LeftToRight
-
-
- Minimize to system &tray
-
-
-
-
-
- -
-
-
- Stop this computer from sleeping
-
-
-
-
-
+
- m_pCheckBoxAutoConfig
+ m_pLineEditScreenName
+ m_pSpinBoxPort
+ m_pLineEditInterface
+ m_pCheckBoxMinimizeOnClose
+ m_pCheckBoxMinimizeToTray
+ m_pCheckBoxAutoHide
+ m_pCheckBoxEnableCrypto
+ m_pComboBoxKeyLength
+ m_pLineEditCertificatePath
+ m_pPushButtonBrowseCert
+ m_pPushButtonRegenCert
+ m_pCheckBoxLogToFile
+ m_pComboLogLevel
+ m_pLineEditLogFilename
+ m_pButtonBrowseLog
+ m_pRadioUserScope
+ m_pRadioSystemScope
+ m_pCheckBoxPreventSleep
+ m_pCheckBoxServiceEnabled
+ m_pComboElevate
+ m_pCheckBoxScrollDirection
+ m_pCheckBoxLanguageSync
+ m_pCheckBoxServerClientMode
+ m_pCheckBoxClientHostMode
- buttonBox
+ m_pButtonBox
accepted()
SettingsDialogBase
accept()
@@ -1023,7 +988,7 @@ font-weight: bold;
- buttonBox
+ m_pButtonBox
rejected()
SettingsDialogBase
reject()
diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp
index 98224cde8..5cec5608c 100644
--- a/src/gui/src/SslCertificate.cpp
+++ b/src/gui/src/SslCertificate.cpp
@@ -23,21 +23,72 @@
#include
#include
-static const char kCertificateKeyLength[] =
- "rsa:"; // RSA Bit length (e.g. 1024/2048/4096)
-static const char kCertificateHashAlgorithm[] =
- "-sha256"; // fingerprint hashing algorithm
-static const char kCertificateLifetime[] = "365";
-static const char kCertificateSubjectInfo[] = "/CN=Synergy";
-static const char kCertificateFilename[] = "Synergy.pem";
-static const char kSslDir[] = "SSL";
-static const char kUnixOpenSslCommand[] = "openssl";
+// RSA Bit length (e.g. 1024/2048/4096)
+static const char *const kCertificateKeyLength = "rsa:";
+
+// fingerprint hashing algorithm
+static const char *const kCertificateHashAlgorithm = "-sha256";
+
+static const char *const kCertificateLifetime = "365";
+static const char *const kCertificateSubjectInfo = "/CN=Synergy";
+static const char *const kCertificateFilename = "Synergy.pem";
+static const char *const kSslDir = "SSL";
#if defined(Q_OS_WIN)
-static const char kWinOpenSslBinary[] = "OpenSSL\\openssl.exe";
-static const char kConfigFile[] = "OpenSSL\\synergy.conf";
+static const char *const kWinOpenSslDir = "OpenSSL";
+static const char *const kWinOpenSslBinary = "openssl.exe";
+static const char *const kConfigFile = "synergy.conf";
+#elif defined(Q_OS_UNIX)
+static const char *const kUnixOpenSslCommand = "openssl";
#endif
+namespace synergy::gui {
+#if defined(Q_OS_WIN)
+
+QString openSslWindowsDir() {
+
+ auto appDir = QDir(QCoreApplication::applicationDirPath());
+ auto openSslDir = QDir(appDir.filePath(kWinOpenSslDir));
+
+ // in production, openssl is deployed with the app.
+ // in development, we can use the openssl path available at compile-time.
+ if (!openSslDir.exists()) {
+ openSslDir = QDir(OPENSSL_PATH);
+ }
+
+ // if the path still isn't found, something is seriously wrong.
+ if (!openSslDir.exists()) {
+ qFatal() << "OpenSSL dir not found: " << openSslDir;
+ }
+
+ return QDir::cleanPath(openSslDir.absolutePath());
+}
+
+QString openSslWindowsBinary() {
+ auto dir = QDir(openSslWindowsDir());
+ auto path = dir.filePath(kWinOpenSslBinary);
+
+ // when installed, there is no openssl bin dir; it's installed at the base.
+ // in development, we use the standard dir structure for openssl (bin dir).
+ if (!QFile::exists(path)) {
+ auto binDir = QDir(dir.filePath("bin"));
+ path = binDir.filePath(kWinOpenSslBinary);
+ }
+
+ // if the path still isn't found, something is seriously wrong.
+ if (!QFile::exists(path)) {
+ qFatal() << "OpenSSL binary not found: " << path;
+ }
+
+ return path;
+}
+
+#endif
+
+} // namespace synergy::gui
+
+using namespace synergy::gui;
+
SslCertificate::SslCertificate(QObject *parent) : QObject(parent) {
m_ProfileDir = m_CoreInterface.getProfileDir();
if (m_ProfileDir.isEmpty()) {
@@ -48,17 +99,16 @@ SslCertificate::SslCertificate(QObject *parent) : QObject(parent) {
bool SslCertificate::runTool(const QStringList &args) {
QString program;
#if defined(Q_OS_WIN)
- program = QCoreApplication::applicationDirPath();
- program.append("\\").append(kWinOpenSslBinary);
+ program = openSslWindowsBinary();
#else
program = kUnixOpenSslCommand;
#endif
QStringList environment;
#if defined(Q_OS_WIN)
- environment << QString("OPENSSL_CONF=%1\\%2")
- .arg(QCoreApplication::applicationDirPath())
- .arg(kConfigFile);
+ auto openSslDir = QDir(openSslWindowsDir());
+ auto config = QDir::cleanPath(openSslDir.filePath(kConfigFile));
+ environment << QString("OPENSSL_CONF=%1").arg(config);
#endif
QProcess process;
@@ -73,8 +123,7 @@ bool SslCertificate::runTool(const QStringList &args) {
standardError = process.readAllStandardError().trimmed();
}
- int code = process.exitCode();
- if (!success || code != 0) {
+ if (int code = process.exitCode(); !success || code != 0) {
emit error(QString("SSL tool failed: %1\n\nCode: %2\nError: %3")
.arg(program)
.arg(process.exitCode())
@@ -99,9 +148,7 @@ void SslCertificate::generateCertificate(
const QString pathToUse = path.isEmpty() ? filename : path;
- // If path is empty use filename
- QFile file(pathToUse);
- if (!file.exists() || forceGen) {
+ if (QFile file(pathToUse); !file.exists() || forceGen) {
QStringList arguments;
// self signed certificate
@@ -123,8 +170,7 @@ void SslCertificate::generateCertificate(
arguments.append("-newkey");
arguments.append(keySize);
- QDir sslDir(sslDirPath);
- if (!sslDir.exists()) {
+ if (QDir sslDir(sslDirPath); !sslDir.exists()) {
sslDir.mkpath(".");
}
@@ -161,7 +207,7 @@ void SslCertificate::generateFingerprint(const QString &certificateFilename) {
}
// find the fingerprint from the tool output
- int i = m_ToolOutput.indexOf("=");
+ auto i = m_ToolOutput.indexOf("=");
if (i != -1) {
i++;
QString fingerprint = m_ToolOutput.mid(i, m_ToolOutput.size() - i);
diff --git a/src/gui/src/main.cpp b/src/gui/src/main.cpp
index 1b8d6e1f4..3626475af 100644
--- a/src/gui/src/main.cpp
+++ b/src/gui/src/main.cpp
@@ -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
@@ -35,6 +35,8 @@
#include
#endif
+using namespace synergy::gui;
+
class QThreadImpl : public QThread {
public:
static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
@@ -53,10 +55,6 @@ int main(int argc, char *argv[]) {
::setenv("QT_BEARER_POLL_TIMEOUT", "-1", 1);
#endif
-#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
-#endif
-
QCoreApplication::setOrganizationName("Synergy");
QCoreApplication::setOrganizationDomain("http://symless.com/");
QCoreApplication::setApplicationName("Synergy");
@@ -78,17 +76,11 @@ int main(int argc, char *argv[]) {
}
#endif
-#ifndef Q_OS_WIN
- QApplication::setQuitOnLastWindowClosed(false);
-#endif
-
AppConfig appConfig;
qRegisterMetaType("Edition");
-#ifdef SYNERGY_ENABLE_LICENSING
- LicenseManager licenseManager(&appConfig);
-#endif
#ifdef SYNERGY_ENABLE_LICENSING
+ LicenseManager licenseManager(&appConfig);
MainWindow mainWindow(appConfig, licenseManager);
#else
MainWindow mainWindow(appConfig);
@@ -114,7 +106,7 @@ int main(int argc, char *argv[]) {
mainWindow.open();
}
- return app.exec();
+ return QSynergyApplication::exec();
}
#if defined(Q_OS_MAC)
diff --git a/src/gui/src/validators/LineEditValidator.cpp b/src/gui/src/validators/LineEditValidator.cpp
index 7604437c4..d0192bed6 100644
--- a/src/gui/src/validators/LineEditValidator.cpp
+++ b/src/gui/src/validators/LineEditValidator.cpp
@@ -33,19 +33,27 @@ void LineEditValidator::addValidator(
}
QValidator::State LineEditValidator::validate(QString &input, int &pos) const {
- if (m_pControl) {
- showError("");
- m_pControl->setStyleSheet("");
+ if (!m_pControl) {
+ qFatal("Validator control not set");
+ return Invalid;
+ }
- for (const auto &validator : m_Validators) {
- if (!validator->validate(input)) {
- m_pControl->setStyleSheet("border: 1px solid #EC4C47");
- showError(validator->getMessage());
- break;
- }
+ QString error;
+ for (const auto &validator : m_Validators) {
+ if (!validator->validate(input)) {
+ error = validator->getMessage();
+ break;
}
}
+ if (error.isEmpty()) {
+ m_pControl->setStyleSheet("");
+ } else {
+ showError(error);
+ m_pControl->setStyleSheet("border: 1px solid #EC4C47");
+ }
+
+ finished(error);
return Acceptable;
}
diff --git a/src/gui/src/validators/LineEditValidator.h b/src/gui/src/validators/LineEditValidator.h
index c7c87aa0e..b82af7e55 100644
--- a/src/gui/src/validators/LineEditValidator.h
+++ b/src/gui/src/validators/LineEditValidator.h
@@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2012-2021 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
@@ -15,27 +15,31 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#ifndef LINEEDITVALIDATOR_H
-#define LINEEDITVALIDATOR_H
-#include
-#include
-
-#include
-#include
-#include
+#pragma once
#include "IStringValidator.h"
+#include
+#include
+#include
+#include
+#include
+
namespace validators {
class LineEditValidator : public QValidator {
+ Q_OBJECT
+
public:
explicit LineEditValidator(
QLineEdit *parent = nullptr, QLabel *errors = nullptr);
QValidator::State validate(QString &input, int &pos) const override;
void addValidator(std::unique_ptr validator);
+signals:
+ void finished(const QString &message) const;
+
private:
QLabel *m_pErrors = nullptr;
QLineEdit *m_pControl = nullptr;
@@ -45,5 +49,3 @@ private:
};
} // namespace validators
-
-#endif // LINEEDITVALIDATOR_H
diff --git a/src/lib/server/Config.cpp b/src/lib/server/Config.cpp
index 2ce3edddf..37dbac3ce 100644
--- a/src/lib/server/Config.cpp
+++ b/src/lib/server/Config.cpp
@@ -558,9 +558,9 @@ String Config::formatInterval(const Interval &x) {
(int)(x.second * 100.0f + 0.5f));
}
-String Config::getClientAddress() const { return m_clientAddress; }
+String Config::getClientAddress() const { return m_ClientAddress; }
-bool Config::isClientMode() const { return (!m_clientAddress.empty()); }
+bool Config::isClientMode() const { return (!m_ClientAddress.empty()); }
void Config::readSection(ConfigReadContext &s) {
static const char s_section[] = "section:";
@@ -659,7 +659,7 @@ void Config::readSectionOptions(ConfigReadContext &s) {
} else if (name == "clipboardSharingSize") {
addOption("", kOptionClipboardSharingSize, s.parseInt(value));
} else if (name == "clientAddress") {
- m_clientAddress = value;
+ m_ClientAddress = value;
} else {
handled = false;
}
diff --git a/src/lib/server/Config.h b/src/lib/server/Config.h
index bee6692e1..f3149f590 100644
--- a/src/lib/server/Config.h
+++ b/src/lib/server/Config.h
@@ -479,7 +479,7 @@ private:
InputFilter m_inputFilter;
bool m_hasLockToScreenAction;
IEventQueue *m_events;
- String m_clientAddress;
+ String m_ClientAddress;
};
//! Configuration read context
diff --git a/src/test/integtests/gui/MainWindowTests.cpp b/src/test/integtests/gui/MainWindowTests.cpp
index ec25d9f6b..4f2c621ec 100644
--- a/src/test/integtests/gui/MainWindowTests.cpp
+++ b/src/test/integtests/gui/MainWindowTests.cpp
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-// TODO: fix randomly freezing on windows
+// TODO: fix test freezing only on windows
#ifndef WIN32
#include "MainWindow.h"
@@ -51,18 +51,16 @@ public:
};
TestMainWindow() {
- m_appConfig = std::make_shared(false);
-
#ifdef SYNERGY_ENABLE_LICENSING
- m_licenseManager = std::make_shared(m_appConfig.get());
+ m_licenseManager = std::make_shared(&m_appConfig);
m_mainWindow =
- std::make_shared(*m_appConfig, *m_licenseManager);
+ std::make_shared(m_appConfig, *m_licenseManager);
#else
- m_mainWindow = std::make_shared(*m_appConfig);
+ m_mainWindow = std::make_shared(m_appConfig);
#endif
}
- std::shared_ptr m_appConfig;
+ AppConfig m_appConfig;
std::shared_ptr m_licenseManager;
std::shared_ptr m_mainWindow;
};
diff --git a/src/test/integtests/main.cpp b/src/test/integtests/main.cpp
index 7052dd96a..b46889f8b 100644
--- a/src/test/integtests/main.cpp
+++ b/src/test/integtests/main.cpp
@@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2012-2016 Symless Ltd.
+ * Copyright (C) 2012 Symless Ltd.
* Copyright (C) 2011 Nick Bolton
*
* This package is free software; you can redistribute it and/or
@@ -18,21 +18,19 @@
#include "arch/Arch.h"
#include "base/Log.h"
+#include "shared/ExitTimeout.h"
#if SYSAPI_WIN32
#include "arch/win32/ArchMiscWindows.h"
#endif
-#include
#include
-#include
-#define LOCK_TIMEOUT 30
-
-void lock(const std::string &lockFile);
-void unlock(const std::string &lockFile);
+using synergy::test::ExitTimeout;
int main(int argc, char **argv) {
+ ExitTimeout exitTimeout(1, "Integration tests");
+
#if SYSAPI_WIN32
// record window instance for tray icon, etc
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
@@ -44,53 +42,10 @@ int main(int argc, char **argv) {
Log log;
log.setFilter(kDEBUG2);
- std::string lockFile;
- for (int i = 0; i < argc; i++) {
- const std::string option(argv[i]);
- if (option.find("--lock-file") != std::string::npos) {
- lockFile = argv[i + 1];
- }
- }
-
- if (!lockFile.empty()) {
- lock(lockFile);
- }
-
::testing::GTEST_FLAG(throw_on_failure) = true;
testing::InitGoogleTest(&argc, argv);
- int result = RUN_ALL_TESTS();
-
- if (!lockFile.empty()) {
- unlock(lockFile);
- }
-
// return code 1 means the test failed.
// any other non-zero code is probably a memory error.
- return result;
+ return RUN_ALL_TESTS();
}
-
-void lock(const std::string &lockFile) {
- double start = ARCH->time();
-
- // keep checking until timeout is reached.
- while ((ARCH->time() - start) < LOCK_TIMEOUT) {
-
- std::ifstream is(lockFile.c_str());
- bool noLock = !is;
- is.close();
-
- if (noLock) {
- break;
- }
-
- // check every second if file has gone.
- ARCH->sleep(1);
- }
-
- // write empty lock file.
- std::ofstream os(lockFile.c_str());
- os.close();
-}
-
-void unlock(const std::string &lockFile) { remove(lockFile.c_str()); }
diff --git a/src/test/shared/ExitTimeout.cpp b/src/test/shared/ExitTimeout.cpp
new file mode 100644
index 000000000..3aa33e8f3
--- /dev/null
+++ b/src/test/shared/ExitTimeout.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 .
+ */
+
+#include "ExitTimeout.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace synergy::test {
+
+const auto checkMilliseconds = std::chrono::milliseconds(100);
+
+using std::chrono::duration_cast;
+using std::chrono::steady_clock;
+
+bool timeoutReached(const steady_clock::time_point &start, const int minutes) {
+ auto now = steady_clock::now();
+ auto duration = duration_cast(now - start);
+ return duration.count() >= minutes;
+}
+
+ExitTimeout::ExitTimeout(const int minutes, const std::string_view &name)
+ : m_minutes(minutes),
+ m_name(name),
+ m_thread(std::make_unique([this]() { run(); })) {}
+
+ExitTimeout::~ExitTimeout() {
+ m_running = false;
+ m_thread->join();
+}
+
+void ExitTimeout::run() const {
+ auto start = steady_clock::now();
+ while (m_running) {
+ std::this_thread::sleep_for(checkMilliseconds);
+ if (timeoutReached(start, m_minutes)) {
+ std::cerr << m_name << " timed out after " << m_minutes << " minute(s)"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+}
+
+} // namespace synergy::test
diff --git a/src/test/shared/ExitTimeout.h b/src/test/shared/ExitTimeout.h
new file mode 100644
index 000000000..1f9c71536
--- /dev/null
+++ b/src/test/shared/ExitTimeout.h
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace synergy::test {
+
+/**
+ * @brief Exits the program after a specified timeout, unless destroyed.
+ *
+ * The `std::thread` class is used instead of `std::jthread` as Apple Clang has
+ * no `std::jthread` support: https://en.cppreference.com/w/cpp/compiler_support
+ *
+ * TODO: Switch to regular Clang instead of Apple Clang:
+ * https://symless.atlassian.net/browse/S1-1754
+ */
+class ExitTimeout {
+public:
+ ExitTimeout(const int minutes, const std::string_view &name);
+ ~ExitTimeout();
+ void run() const;
+
+private:
+ bool m_running = true;
+ int m_minutes = 0;
+ std::string_view m_name;
+ std::unique_ptr m_thread;
+};
+
+} // namespace synergy::test
diff --git a/src/test/unittests/main.cpp b/src/test/unittests/main.cpp
index 86b4ad7d9..cff778469 100644
--- a/src/test/unittests/main.cpp
+++ b/src/test/unittests/main.cpp
@@ -1,6 +1,6 @@
/*
* synergy -- mouse and keyboard sharing utility
- * Copyright (C) 2012-2016 Symless Ltd.
+ * Copyright (C) 2012 Symless Ltd.
* Copyright (C) 2011 Nick Bolton
*
* This package is free software; you can redistribute it and/or
@@ -18,15 +18,19 @@
#include "arch/Arch.h"
#include "base/Log.h"
+#include "shared/ExitTimeout.h"
#if SYSAPI_WIN32
#include "arch/win32/ArchMiscWindows.h"
#endif
-#include
#include
+using synergy::test::ExitTimeout;
+
int main(int argc, char **argv) {
+ ExitTimeout exitTimeout(1, "Integration tests");
+
#if SYSAPI_WIN32
// HACK: shouldn't be needed, but logging fails without this.
ArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));