Implement safer memory use, improve dev env, fixed GUI bugs (#7407)
* Improve dev script for daemon * Ignore `.user` files created by Qt * Add `FORCE_DESKTOP_PROCESS` option * Catch errors related to getting profile dir * Disable IPC entirely if forced desktop * Use in-class init for AppConfig members * Refactor config to use safer memory management * Improve launch config to make OS-specific debugger usage clearer * Re-enable MainWindowTests on Windows, further refactor for memory safety, fixed some include orders * Remove dead singleton code * Swap order of tests * Use HTTPs for URLs * Fixed compile errors for `SYNERGY_ENABLE_LICENSING` compile path * Restore exec function call * Remove extra link in cancel dialog * Fixed broken link on activation cancel UI * Close dialog if activated * Fixed macOS enum ref to kCurrentProcess * Improve wording on cancel activation dialog * WIP - Test timeout (compile error) * Finished timeout logic (with smart pointer) * Include string_view * Switch to thread from jthread (maybe not supported by macOS compiler?) * Improve comment * Disable test on Windows * Add TODO related to jthread on macOS * Refactor settings and paths on Windows * Launch in desktop mode on Windows * Remove arg quote wraps which break desktop mode * Fixed qFatal on Linux * Remove test value * Follow original `AppConfig` accessor convention * Disable service checkbox if not Windows * Simplify TLS control enable logic * Update command and Git ignore * Fixed code style * Fixed include consistency * Fixed includes in validator * Fixed lint errors * Update ChangeLog * Use smart pointer for core process * Remove unneccesary default operators * Don't halt on stderr
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -14,3 +14,5 @@ Brewfile.lock.json
|
||||
*.code-workspace
|
||||
.env*
|
||||
/scripts/*.egg-info
|
||||
/*.user
|
||||
*.ui.autosave
|
||||
|
||||
71
.vscode/launch.json
vendored
71
.vscode/launch.json
vendored
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
31
.vscode/tasks.json
vendored
31
.vscode/tasks.json
vendored
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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()
|
||||
|
||||
@ -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()
|
||||
|
||||
192
scripts/daemon.py
Normal file
192
scripts/daemon.py
Normal file
@ -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()
|
||||
@ -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__":
|
||||
|
||||
8
scripts/lib/colors.py
Normal file
8
scripts/lib/colors.py
Normal file
@ -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}"
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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()
|
||||
@ -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
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <shared/EditionType.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
#include <iostream>
|
||||
|
||||
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, "
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LicenseManager.h>
|
||||
#include <QDialog>
|
||||
@ -30,5 +46,3 @@ private:
|
||||
AppConfig *m_appConfig;
|
||||
LicenseManager *m_LicenseManager;
|
||||
};
|
||||
|
||||
#endif // ACTIVATIONDIALOG_H
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>410</width>
|
||||
<height>211</height>
|
||||
<width>477</width>
|
||||
<height>241</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -18,7 +18,6 @@
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
@ -30,7 +29,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
@ -47,9 +46,12 @@
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!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></string>
|
||||
</property>
|
||||
<property name="acceptRichText">
|
||||
|
||||
@ -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 <QApplication>
|
||||
#include <QPushButton>
|
||||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <qapplication.h>
|
||||
|
||||
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<int>(kDefaultElevateMode)));
|
||||
}
|
||||
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
|
||||
QVariant elevateMode = loadSetting(kElevateModeEnum);
|
||||
if (!elevateMode.isValid()) {
|
||||
elevateMode = loadSetting(
|
||||
kElevateModeSetting, QVariant(static_cast<int>(kDefaultElevateMode)));
|
||||
}
|
||||
m_ElevateMode = static_cast<ElevateMode>(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<Edition>(
|
||||
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<int>(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<int>(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<int>(name);
|
||||
return m_SynergySettingsName[index];
|
||||
return m_SettingsName[index];
|
||||
}
|
||||
|
||||
template <typename T> void AppConfig::setSetting(Setting name, T value) {
|
||||
ConfigWriter::make()->setSetting(settingName(name), value);
|
||||
m_Config.setSetting(settingName(name), value);
|
||||
}
|
||||
|
||||
template <typename T> 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 <typename T>
|
||||
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; }
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <QObject>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <mutex>
|
||||
#include <shared/EditionType.h>
|
||||
|
||||
// this should be incremented each time a new page is added. this is
|
||||
// saved to settings when the user finishes running the wizard. if
|
||||
// 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
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>165</height>
|
||||
<height>246</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -17,9 +17,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Are you sure?
|
||||
|
||||
If you don't activate Synergy you'll be missing out on some great features.</string>
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@ -30,14 +28,17 @@ If you don't activate Synergy you'll be missing out on some great features.</str
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
#include "CommandProcess.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <stdexcept>
|
||||
|
||||
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();
|
||||
|
||||
36
src/gui/src/CommonConfig.h
Normal file
36
src/gui/src/CommonConfig.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include "Config.h"
|
||||
|
||||
#include "CommonConfig.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#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>(
|
||||
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<QSettings>();
|
||||
|
||||
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
|
||||
115
src/gui/src/Config.h
Normal file
115
src/gui/src/Config.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QSettings>
|
||||
#include <QVariant>
|
||||
#include <memory>
|
||||
|
||||
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 <typename T>
|
||||
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<QSettings> m_pUserSettings;
|
||||
std::unique_ptr<QSettings> m_pSystemSettings;
|
||||
|
||||
/// @brief Receivers of load/save callbacks
|
||||
std::list<CommonConfig *> m_pReceievers;
|
||||
|
||||
/// @brief Is set to true when settings are changed
|
||||
bool m_unsavedChanges = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void Config::setSetting(const QString &name, T value, Scope scope) {
|
||||
currentSettings()->setValue(name, value);
|
||||
m_unsavedChanges = true;
|
||||
}
|
||||
|
||||
} // namespace synergy::gui
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SYNERGY_CORE_CONFIGWRITER_H
|
||||
#define SYNERGY_CORE_CONFIGWRITER_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <QVariant>
|
||||
|
||||
/// @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 <typename T>
|
||||
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<ConfigBase *> 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 <class T> 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 <typename T>
|
||||
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
|
||||
@ -18,13 +18,11 @@
|
||||
#include "CoreInterface.h"
|
||||
|
||||
#include "CommandProcess.h"
|
||||
#include "QUtility.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QtGlobal>
|
||||
#include <stdexcept>
|
||||
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -33,5 +33,3 @@
|
||||
// ElevateNever | false | false
|
||||
//
|
||||
enum ElevateMode { ElevateAsNeeded = 0, ElevateAlways = 1, ElevateNever = 2 };
|
||||
|
||||
extern const ElevateMode kDefaultElevateMode;
|
||||
|
||||
@ -16,7 +16,10 @@
|
||||
*/
|
||||
|
||||
#include "LicenseManager.h"
|
||||
|
||||
#include "ActivationNotifier.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QLocale>
|
||||
#include <QThread>
|
||||
@ -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();
|
||||
|
||||
@ -17,13 +17,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ActivationNotifier.h>
|
||||
#include <QObject>
|
||||
#include <shared/EditionType.h>
|
||||
#include <shared/SerialKey.h>
|
||||
#include <utility>
|
||||
|
||||
#include "LicenseRegistry.h"
|
||||
#include "shared/EditionType.h"
|
||||
#include "shared/SerialKey.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@ -23,6 +23,9 @@
|
||||
#include "LicenseRegistry.h"
|
||||
#include <QSysInfo>
|
||||
|
||||
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<unsigned long long>(time(nullptr));
|
||||
|
||||
if (currentTimestamp >= nextCheck) {
|
||||
|
||||
@ -16,11 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DOWNLOAD_URL "http://symless.com/?source=gui"
|
||||
#define HELP_URL "http://symless.com/help?source=gui"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include "AboutDialog.h"
|
||||
@ -29,8 +24,8 @@
|
||||
#include "LicenseManager.h"
|
||||
#include "ServerConfigDialog.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include <QPushButton>
|
||||
#include <shared/EditionType.h>
|
||||
#include "shared/EditionType.h"
|
||||
#include <memory>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include "OSXHelpers.h"
|
||||
@ -42,39 +37,46 @@
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QPushButton>
|
||||
#include <QRegularExpression>
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtNetwork>
|
||||
#include <array>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#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<QAction *, 7> 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<int>(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 <b>%1</b> is now available to "
|
||||
"<a href=\"%2\">download</a>.</p>")
|
||||
.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<QProcess>(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(); }
|
||||
|
||||
@ -24,13 +24,14 @@
|
||||
#include <QSettings>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QThread>
|
||||
#include <memory>
|
||||
|
||||
#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<QProcess> 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();
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>720</width>
|
||||
<height>552</height>
|
||||
<width>750</width>
|
||||
<height>650</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -18,8 +18,8 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>720</width>
|
||||
<height>552</height>
|
||||
<width>750</width>
|
||||
<height>550</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -357,7 +357,7 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Configure server</string>
|
||||
<string>&Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -692,7 +692,6 @@ background-color: rgba(192,192,192, 0.1);
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>-1</pointsize>
|
||||
<weight>88</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
@ -789,7 +788,7 @@ top: 3px;</string>
|
||||
<string notr="true">Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_pActionStartSynergy">
|
||||
<action name="m_pActionStartCore">
|
||||
<property name="text">
|
||||
<string>&Start</string>
|
||||
</property>
|
||||
@ -797,10 +796,10 @@ top: 3px;</string>
|
||||
<string>Run</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true">Ctrl+S</string>
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_pActionStopSynergy">
|
||||
<action name="m_pActionStopCore">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -811,7 +810,7 @@ top: 3px;</string>
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true">Ctrl+T</string>
|
||||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowStatus">
|
||||
@ -894,7 +893,7 @@ top: 3px;</string>
|
||||
<connection>
|
||||
<sender>m_pButtonToggleStart</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>m_pActionStartSynergy</receiver>
|
||||
<receiver>m_pActionStartCore</receiver>
|
||||
<slot>trigger()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
||||
@ -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 <QtCore>
|
||||
#include <QtGui>
|
||||
|
||||
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<MainWindow *>(widget);
|
||||
if (mainWindow)
|
||||
mainWindow->saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
QSynergyApplication *QSynergyApplication::getInstance() { return s_Instance; }
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(QSYNERGYAPPLICATION__H)
|
||||
|
||||
#define QSYNERGYAPPLICATION__H
|
||||
#pragma once
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -16,23 +16,20 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(SCREEN__H)
|
||||
#pragma once
|
||||
|
||||
#define SCREEN__H
|
||||
#include "ScreenConfig.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#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
|
||||
|
||||
@ -16,14 +16,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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"};
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(BASECONFIG_H)
|
||||
|
||||
#define BASECONFIG_H
|
||||
#pragma once
|
||||
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
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 <typename T1, typename T2>
|
||||
@ -101,5 +100,3 @@ private:
|
||||
static const char *m_FixNames[];
|
||||
static const char *m_SwitchCornerNames[];
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -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 <QPushButton>
|
||||
#include <QtCore>
|
||||
|
||||
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 {
|
||||
|
||||
@ -16,15 +16,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(SERVERCONFIG__H)
|
||||
|
||||
#define SERVERCONFIG__H
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
|
||||
#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<bool> 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<bool> 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
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <QMessageBox>
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <memory>
|
||||
|
||||
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<validators::ScreenNameValidator>(
|
||||
m_pLineEditScreenName, nullptr, (&serveConfig.screens()));
|
||||
connect(
|
||||
m_screenNameValidator.get(), SIGNAL(finished(QString)), this,
|
||||
SLOT(on_m_pScreenNameValidator_finished(QString)));
|
||||
m_pLineEditScreenName->setValidator(m_screenNameValidator.get());
|
||||
|
||||
connect(
|
||||
m_pLineEditLogFilename, SIGNAL(textChanged(QString)), this,
|
||||
@ -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<int>(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<ElevateMode>(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<int>(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;
|
||||
}
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(SETTINGSDIALOG_H)
|
||||
|
||||
#define SETTINGSDIALOG_H
|
||||
#pragma once
|
||||
|
||||
#include "ui_SettingsDialogBase.h"
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
|
||||
#include "CoreInterface.h"
|
||||
#include "validators/ScreenNameValidator.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
|
||||
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<validators::ScreenNameValidator> 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
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>404</width>
|
||||
<height>819</height>
|
||||
<width>417</width>
|
||||
<height>786</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -38,64 +38,6 @@
|
||||
<property name="verticalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupNetwork">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Security</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupAdvanced">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QFrame" name="m_pGroupLog1">
|
||||
<property name="styleSheet">
|
||||
@ -181,7 +123,7 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Level</string>
|
||||
<string>Level</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pComboLogLevel</cstring>
|
||||
@ -285,8 +227,213 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupLog">
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="m_pGroupBoxCommon">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">.QFrame{
|
||||
border: 1px solid rgba(192,192,192, 0.2);
|
||||
border-radius: 4px;
|
||||
background-color: rgba(192,192,192, 0.1);
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>17</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>17</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelComputerName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>75</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Computer &name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pLineEditScreenName</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pLineEditScreenName">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabel_20">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>P&ort</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pSpinBoxPort</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_pSpinBoxPort">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24800</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabel_21">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Network IP</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pLineEditInterface</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pLineEditInterface">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxMinimizeOnClose">
|
||||
<property name="text">
|
||||
<string>Minimize to tray on close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxMinimizeToTray">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Minimize to system &tray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxAutoHide">
|
||||
<property name="text">
|
||||
<string>Hide window on start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupNetwork">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -294,12 +441,12 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Logs</string>
|
||||
<string>Security</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@ -337,104 +484,125 @@ background-color: rgba(192,192,192, 0.1);
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0" colspan="3">
|
||||
<item row="7" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxScrollDirection">
|
||||
<property name="text">
|
||||
<string>Invert scroll direction on this computer</string>
|
||||
<string>Invert scroll direction on this computer (client mode)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxClientHostMode">
|
||||
<property name="text">
|
||||
<string>Host mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="m_pComboElevate">
|
||||
<property name="toolTip">
|
||||
<string>Specify when the Synergy service should run at an elevated privilege level</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>As Needed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Always</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Never</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxLanguageSync">
|
||||
<property name="text">
|
||||
<string>&Use server's keyboard language on this machine</string>
|
||||
<string>Use server's keyboard language on this computer (client mode)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxServerClientMode">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxServiceEnabled">
|
||||
<property name="text">
|
||||
<string>Client mode</string>
|
||||
<string>Use background service (daemon)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="m_pLabelElevate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="3" column="0" rowspan="3" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelElevate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Elevate privileges (service required)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_pComboElevate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Specify when the Synergy service should run at an elevated privilege level</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>As Needed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Always</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Never</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxPreventSleep">
|
||||
<property name="text">
|
||||
<string>Elevate privileges</string>
|
||||
<string>Stop this computer from sleeping</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxServerClientMode">
|
||||
<property name="text">
|
||||
<string>Use server as a client</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxClientHostMode">
|
||||
<property name="text">
|
||||
<string>Use client in host mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QFrame" name="m_pGroupSecurity">
|
||||
<property name="styleSheet">
|
||||
@ -472,7 +640,7 @@ background-color: rgba(192,192,192, 0.1);
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable &TLS encryption</string>
|
||||
<string>Enable TLS encryption</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -628,6 +796,61 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupAdvanced">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="m_pLabelGroupLog">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Logs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QFrame" name="m_pGroupScope">
|
||||
<property name="styleSheet">
|
||||
@ -654,13 +877,6 @@ background-color: rgba(192,192,192, 0.1);
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="m_pRadioUserScope">
|
||||
<property name="text">
|
||||
<string>Current user</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="m_pRadioSystemScope">
|
||||
<property name="text">
|
||||
@ -671,33 +887,18 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="m_labelAdminRightsMessage">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="m_pRadioUserScope">
|
||||
<property name="text">
|
||||
<string>Note: Only Admins can edit settings for all users.</string>
|
||||
<string>Current user</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<item row="18" column="0">
|
||||
<widget class="QDialogButtonBox" name="m_pButtonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -706,56 +907,8 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<layout class="QGridLayout" name="m_pGridLayoutNetwork">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxAutoConfig">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Auto Config</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="m_pLabelInstallBonjour">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="#"><span style=" text-decoration: underline; color:#007af4;">Install Bonjour</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="19" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<item row="11" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@ -770,244 +923,56 @@ background-color: rgba(192,192,192, 0.1);
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="m_pGroupBoxCommon">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">.QFrame{
|
||||
border: 1px solid rgba(192,192,192, 0.2);
|
||||
border-radius: 4px;
|
||||
background-color: rgba(192,192,192, 0.1);
|
||||
}
|
||||
</string>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>17</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>17</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelComputerName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>75</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Computer name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pLineEditScreenName</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pLineEditScreenName">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelNameError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: #EC4C47;
|
||||
font-size: 13px;
|
||||
font-family: Arial;
|
||||
font-weight: bold;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabel_20">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>P&ort</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pSpinBoxPort</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_pSpinBoxPort">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24800</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabel_21">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Network IP</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_pLineEditInterface</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pLineEditInterface">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxAutoHide">
|
||||
<property name="text">
|
||||
<string>&Hide on startup</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxMinimizeToTray">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Minimize to system &tray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxPreventSleep">
|
||||
<property name="text">
|
||||
<string>Stop this computer from sleeping</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>m_pCheckBoxAutoConfig</tabstop>
|
||||
<tabstop>m_pLineEditScreenName</tabstop>
|
||||
<tabstop>m_pSpinBoxPort</tabstop>
|
||||
<tabstop>m_pLineEditInterface</tabstop>
|
||||
<tabstop>m_pCheckBoxMinimizeOnClose</tabstop>
|
||||
<tabstop>m_pCheckBoxMinimizeToTray</tabstop>
|
||||
<tabstop>m_pCheckBoxAutoHide</tabstop>
|
||||
<tabstop>m_pCheckBoxEnableCrypto</tabstop>
|
||||
<tabstop>m_pComboBoxKeyLength</tabstop>
|
||||
<tabstop>m_pLineEditCertificatePath</tabstop>
|
||||
<tabstop>m_pPushButtonBrowseCert</tabstop>
|
||||
<tabstop>m_pPushButtonRegenCert</tabstop>
|
||||
<tabstop>m_pCheckBoxLogToFile</tabstop>
|
||||
<tabstop>m_pComboLogLevel</tabstop>
|
||||
<tabstop>m_pLineEditLogFilename</tabstop>
|
||||
<tabstop>m_pButtonBrowseLog</tabstop>
|
||||
<tabstop>m_pRadioUserScope</tabstop>
|
||||
<tabstop>m_pRadioSystemScope</tabstop>
|
||||
<tabstop>m_pCheckBoxPreventSleep</tabstop>
|
||||
<tabstop>m_pCheckBoxServiceEnabled</tabstop>
|
||||
<tabstop>m_pComboElevate</tabstop>
|
||||
<tabstop>m_pCheckBoxScrollDirection</tabstop>
|
||||
<tabstop>m_pCheckBoxLanguageSync</tabstop>
|
||||
<tabstop>m_pCheckBoxServerClientMode</tabstop>
|
||||
<tabstop>m_pCheckBoxClientHostMode</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../res/Synergy.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<sender>m_pButtonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SettingsDialogBase</receiver>
|
||||
<slot>accept()</slot>
|
||||
@ -1023,7 +988,7 @@ font-weight: bold;</string>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<sender>m_pButtonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SettingsDialogBase</receiver>
|
||||
<slot>reject()</slot>
|
||||
|
||||
@ -23,21 +23,72 @@
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
|
||||
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);
|
||||
|
||||
@ -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 <cstdlib>
|
||||
#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>("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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LINEEDITVALIDATOR_H
|
||||
#define LINEEDITVALIDATOR_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <qvalidator.h>
|
||||
#pragma once
|
||||
|
||||
#include "IStringValidator.h"
|
||||
|
||||
#include <QValidator>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
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<IStringValidator> 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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ private:
|
||||
InputFilter m_inputFilter;
|
||||
bool m_hasLockToScreenAction;
|
||||
IEventQueue *m_events;
|
||||
String m_clientAddress;
|
||||
String m_ClientAddress;
|
||||
};
|
||||
|
||||
//! Configuration read context
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// 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<AppConfig>(false);
|
||||
|
||||
#ifdef SYNERGY_ENABLE_LICENSING
|
||||
m_licenseManager = std::make_shared<LicenseManager>(m_appConfig.get());
|
||||
m_licenseManager = std::make_shared<LicenseManager>(&m_appConfig);
|
||||
m_mainWindow =
|
||||
std::make_shared<MainWindowProxy>(*m_appConfig, *m_licenseManager);
|
||||
std::make_shared<MainWindowProxy>(m_appConfig, *m_licenseManager);
|
||||
#else
|
||||
m_mainWindow = std::make_shared<MainWindowProxy>(*m_appConfig);
|
||||
m_mainWindow = std::make_shared<MainWindowProxy>(m_appConfig);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<AppConfig> m_appConfig;
|
||||
AppConfig m_appConfig;
|
||||
std::shared_ptr<LicenseManager> m_licenseManager;
|
||||
std::shared_ptr<MainWindowProxy> m_mainWindow;
|
||||
};
|
||||
|
||||
@ -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 <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
|
||||
#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()); }
|
||||
|
||||
61
src/test/shared/ExitTimeout.cpp
Normal file
61
src/test/shared/ExitTimeout.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ExitTimeout.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
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<std::chrono::minutes>(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<std::thread>([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
|
||||
47
src/test/shared/ExitTimeout.h
Normal file
47
src/test/shared/ExitTimeout.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
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<std::thread> m_thread;
|
||||
};
|
||||
|
||||
} // namespace synergy::test
|
||||
@ -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 <QApplication>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user