Refactor local/global save/load and show dev thanks message (#7423)
* WIP: Show dev thanks message * Improve error messages and guard license code * Print core command * Allow license tests when licensing disabled by default * Don't check invalid serial key * Fixed typo * Add error checking * Use shared ptr instead of static deps * Actually save and load the setting * Add dev thanks vars to CI * Show thanks message after connected * Refactor hack-job of local/global save/load to remove coupling and use Qt events system * Simplify config loading * Overloads for optionals * Fixed global config scope not loaded * Save message state before showing to avoid multiple messages * Update ChangeLog * Fixed lint warnings * Make function const * Reduce verbosity * Remove dead code, show version on start, tidy up lint warnings * Make product name code safer * Connect on enter press * Only show server specific wording when on server * Add emit commands * Log info and error * Remove deaad code * Remove test member * Disable start context menu action unless usable * Show more relvant connect message * Fixed close to tray not applied, and simplified restart core logic * Remove redundant include
This commit is contained in:
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -27,6 +27,7 @@ env:
|
||||
SYNERGY_PRODUCT_NAME: ${{ vars.SYNERGY_PRODUCT_NAME }}
|
||||
SYNERGY_PACKAGE_PREFIX: ${{ vars.SYNERGY_PACKAGE_PREFIX }}
|
||||
SYNERGY_ENABLE_LICENSING: ${{ vars.SYNERGY_ENABLE_LICENSING }}
|
||||
SYNERGY_SHOW_DEV_THANKS: ${{ vars.SYNERGY_SHOW_DEV_THANKS }}
|
||||
PACKAGE_BUILD: ${{ !github.event.pull_request.draft }}
|
||||
PACKAGE_UPLOAD: ${{ !github.event.pull_request.draft && github.event_name != 'schedule' }}
|
||||
UPLOAD_TO_GITHUB: ${{ github.event_name == 'pull_request' && !github.event.pull_request.draft }}
|
||||
|
||||
@ -66,6 +66,7 @@ Enhancements:
|
||||
- #7421 Only load core after settings have fully loaded
|
||||
- #7419 Introduce 'Advanced' tab to Preferences window
|
||||
- #7422 Handle empty value for computer name setting
|
||||
- #7423 Refactor local/global save/load and show dev thanks message
|
||||
|
||||
# 1.14.6
|
||||
|
||||
|
||||
@ -60,6 +60,11 @@ macro(configure_definitions)
|
||||
add_definitions(-DSYNERGY_PRODUCT_NAME="${PRODUCT_NAME}")
|
||||
endif()
|
||||
|
||||
if(SHOW_DEV_THANKS)
|
||||
message(STATUS "Enabling dev thanks message")
|
||||
add_definitions(-DSYNERGY_SHOW_DEV_THANKS=1)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(STATUS "Disabling debug build")
|
||||
add_definitions(-DNDEBUG)
|
||||
@ -108,6 +113,9 @@ macro(configure_options)
|
||||
# licensing is off by default to make life easier for contributors.
|
||||
set(DEFAULT_ENABLE_LICENSING OFF)
|
||||
|
||||
# by default, show the dev thanks message.
|
||||
set(DEFAULT_SHOW_DEV_THANKS ON)
|
||||
|
||||
if("$ENV{SYNERGY_BUILD_MINIMAL}" STREQUAL "true")
|
||||
set(DEFAULT_BUILD_GUI OFF)
|
||||
set(DEFAULT_BUILD_INSTALLER OFF)
|
||||
@ -129,11 +137,16 @@ macro(configure_options)
|
||||
set(DEFAULT_ENABLE_COVERAGE ON)
|
||||
endif()
|
||||
|
||||
if("$ENV{SYNERGY_SHOW_DEV_THANKS}" STREQUAL "false")
|
||||
set(DEFAULT_SHOW_DEV_THANKS OFF)
|
||||
endif()
|
||||
|
||||
option(BUILD_GUI "Build GUI" ${DEFAULT_BUILD_GUI})
|
||||
option(BUILD_INSTALLER "Build installer" ${DEFAULT_BUILD_INSTALLER})
|
||||
option(BUILD_TESTS "Build tests" ${DEFAULT_BUILD_TESTS})
|
||||
option(BUILD_UNIFIED "Build unified binary" ${DEFAULT_BUILD_UNIFIED})
|
||||
option(ENABLE_LICENSING "Enable licensing" ${DEFAULT_ENABLE_LICENSING})
|
||||
option(ENABLE_COVERAGE "Enable test coverage" ${DEFAULT_ENABLE_COVERAGE})
|
||||
option(SHOW_DEV_THANKS "Show dev thanks message" ${DEFAULT_SHOW_DEV_THANKS})
|
||||
|
||||
endmacro()
|
||||
|
||||
@ -24,23 +24,14 @@
|
||||
#include "OSXHelpers.h"
|
||||
#endif
|
||||
|
||||
#ifdef GIT_SHA_SHORT
|
||||
const QString kVersionAppend = GIT_SHA_SHORT;
|
||||
#else
|
||||
const QString kVersionAppend;
|
||||
#endif
|
||||
#include "gui/version.h"
|
||||
|
||||
AboutDialog::AboutDialog(MainWindow *parent, const AppConfig &config)
|
||||
AboutDialog::AboutDialog(MainWindow *parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
|
||||
Ui::AboutDialogBase() {
|
||||
setupUi(this);
|
||||
|
||||
QString version(SYNERGY_VERSION);
|
||||
if (!kVersionAppend.isEmpty()) {
|
||||
version.append(QString(" (%1)").arg(kVersionAppend));
|
||||
}
|
||||
|
||||
m_pLabelSynergyVersion->setText(version);
|
||||
m_pLabelSynergyVersion->setText(synergy::gui::version());
|
||||
|
||||
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();
|
||||
QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy");
|
||||
|
||||
@ -30,7 +30,7 @@ class QString;
|
||||
class AboutDialog : public QDialog, public Ui::AboutDialogBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AboutDialog(MainWindow *parent, const AppConfig &config);
|
||||
explicit AboutDialog(MainWindow *parent);
|
||||
int exec() override;
|
||||
|
||||
private:
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "gui/LicenseHandler.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/license_notices.h"
|
||||
#include "gui/styles.h"
|
||||
#include "license/ProductEdition.h"
|
||||
#include "license/parse_serial_key.h"
|
||||
#include "ui_ActivationDialog.h"
|
||||
@ -107,7 +108,6 @@ void ActivationDialog::accept() {
|
||||
}
|
||||
|
||||
showSuccessDialog();
|
||||
m_pAppConfig->setActivationHasRun(true);
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
@ -122,6 +122,7 @@ void ActivationDialog::showResultDialog(
|
||||
QMessageBox::information(
|
||||
this, title,
|
||||
"Heads up, the serial key you entered was the same as last time.");
|
||||
QDialog::accept();
|
||||
break;
|
||||
|
||||
case kInvalid:
|
||||
|
||||
@ -22,11 +22,14 @@
|
||||
#include "ActivationDialog.h"
|
||||
#include "ServerConfigDialog.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include "gui/ConfigScopes.h"
|
||||
#include "gui/LicenseHandler.h"
|
||||
#include "gui/TlsFingerprint.h"
|
||||
#include "gui/VersionChecker.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/license_notices.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/styles.h"
|
||||
#include "license/License.h"
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
@ -58,12 +61,6 @@ using namespace synergy::license;
|
||||
static const int kRetryDelay = 1000;
|
||||
static const int kDebugLogLevel = 1;
|
||||
|
||||
#ifdef SYNERGY_PRODUCT_NAME
|
||||
const QString kProductName = SYNERGY_PRODUCT_NAME;
|
||||
#else
|
||||
const QString kProductName;
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
|
||||
static const char *const kLightIconFiles[] = {
|
||||
@ -89,9 +86,10 @@ static const char *const kDefaultIconFiles[] = {
|
||||
":/res/icons/16x16/synergy-transfering.png",
|
||||
":/res/icons/16x16/synergy-disconnected.png"};
|
||||
|
||||
MainWindow::MainWindow(AppConfig &appConfig)
|
||||
: m_AppConfig(appConfig),
|
||||
m_ServerConfig(5, 3, &m_AppConfig, this),
|
||||
MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig)
|
||||
: m_ConfigScopes(configScopes),
|
||||
m_AppConfig(appConfig),
|
||||
m_ServerConfig(appConfig, *this),
|
||||
m_ServerConnection(*this),
|
||||
m_ClientConnection(*this),
|
||||
m_TlsUtility(appConfig, m_LicenseHandler.license()),
|
||||
@ -101,21 +99,13 @@ MainWindow::MainWindow(AppConfig &appConfig)
|
||||
setupControls();
|
||||
connectSlots();
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
// TODO: only connect permenantly to ipc when switching to service mode.
|
||||
// if switching from service to desktop, connect only to stop the service
|
||||
// and don't retry.
|
||||
m_IpcClient.connectToHost();
|
||||
|
||||
#endif
|
||||
|
||||
// handled by `onCreated`
|
||||
emit created();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
try {
|
||||
if (appConfig().processMode() == ProcessMode::kDesktop) {
|
||||
if (m_AppConfig.processMode() == ProcessMode::kDesktop) {
|
||||
m_ExpectedRunningState = RuningState::Stopped;
|
||||
stopDesktop();
|
||||
}
|
||||
@ -132,18 +122,16 @@ MainWindow::~MainWindow() {
|
||||
|
||||
void MainWindow::restoreWindow() {
|
||||
|
||||
const auto &config = appConfig();
|
||||
|
||||
const auto &size = config.mainWindowSize();
|
||||
if (size.has_value()) {
|
||||
const auto &windowSize = m_AppConfig.mainWindowSize();
|
||||
if (windowSize.has_value()) {
|
||||
qDebug("restoring main window size");
|
||||
resize(size.value());
|
||||
resize(windowSize.value());
|
||||
}
|
||||
|
||||
const auto &position = config.mainWindowPosition();
|
||||
if (position.has_value()) {
|
||||
const auto &windowPosition = m_AppConfig.mainWindowPosition();
|
||||
if (windowPosition.has_value()) {
|
||||
qDebug("restoring main window position");
|
||||
move(position.value());
|
||||
move(windowPosition.value());
|
||||
}
|
||||
|
||||
// give the window chance to restore its size and position before the window
|
||||
@ -159,10 +147,9 @@ void MainWindow::saveWindow() {
|
||||
}
|
||||
|
||||
qDebug("saving window size and position");
|
||||
auto &config = appConfig();
|
||||
config.setMainWindowSize(size());
|
||||
config.setMainWindowPosition(pos());
|
||||
config.saveSettings();
|
||||
m_AppConfig.setMainWindowSize(size());
|
||||
m_AppConfig.setMainWindowPosition(pos());
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
void MainWindow::setupControls() {
|
||||
@ -210,7 +197,8 @@ void MainWindow::connectSlots() const {
|
||||
Qt::QueuedConnection);
|
||||
|
||||
connect(
|
||||
&m_AppConfig, &AppConfig::loaded, this, &MainWindow::onAppConfigLoaded);
|
||||
&m_ConfigScopes, &ConfigScopes::saving, this,
|
||||
&MainWindow::onConfigScopesSaving, Qt::DirectConnection);
|
||||
|
||||
connect(
|
||||
&m_AppConfig, &AppConfig::tlsChanged, this,
|
||||
@ -267,20 +255,30 @@ void MainWindow::connectSlots() const {
|
||||
&MainWindow::onWindowSaveTimerTimeout);
|
||||
}
|
||||
|
||||
void MainWindow::onAppAboutToQuit() { m_AppConfig.saveSettings(); }
|
||||
void MainWindow::onAppAboutToQuit() { m_ConfigScopes.save(); }
|
||||
|
||||
void MainWindow::onCreated() {
|
||||
// it may seem a bit over-complicated to load the app config through a
|
||||
// signal/slot, but there is a good reason: intentionality; we want to
|
||||
// ensure that the ctor is fully executed before we start loading the
|
||||
// app config. a signal is the clearest way to communicate this.
|
||||
m_AppConfig.loadAllScopes();
|
||||
|
||||
const auto serverEnabled = appConfig().serverGroupChecked();
|
||||
const auto clientEnabled = appConfig().clientGroupChecked();
|
||||
if (serverEnabled || clientEnabled) {
|
||||
startCore();
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
// TODO: only connect permenantly to ipc when switching to service mode.
|
||||
// if switching from service to desktop, connect only to stop the service
|
||||
// and don't retry.
|
||||
m_IpcClient.connectToHost();
|
||||
|
||||
#endif
|
||||
|
||||
m_ConfigScopes.signalReady();
|
||||
|
||||
applyCloseToTray();
|
||||
|
||||
if (kLicensingEnabled && !m_AppConfig.serialKey().isEmpty()) {
|
||||
m_LicenseHandler.changeSerialKey(m_AppConfig.serialKey());
|
||||
}
|
||||
|
||||
updateScreenName();
|
||||
applyConfig();
|
||||
restoreWindow();
|
||||
}
|
||||
|
||||
void MainWindow::onShown() {
|
||||
@ -299,7 +297,7 @@ void MainWindow::onLicenseHandlerSerialKeyChanged(const QString &serialKey) {
|
||||
|
||||
if (m_AppConfig.serialKey() != serialKey) {
|
||||
m_AppConfig.setSerialKey(serialKey);
|
||||
m_AppConfig.saveSettings();
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,16 +306,7 @@ void MainWindow::onLicenseHandlerInvalidLicense() {
|
||||
showActivationDialog();
|
||||
}
|
||||
|
||||
void MainWindow::onAppConfigLoaded() {
|
||||
QApplication::setQuitOnLastWindowClosed(!m_AppConfig.closeToTray());
|
||||
if (!m_AppConfig.serialKey().isEmpty()) {
|
||||
m_LicenseHandler.changeSerialKey(m_AppConfig.serialKey());
|
||||
}
|
||||
|
||||
updateScreenName();
|
||||
applyConfig();
|
||||
restoreWindow();
|
||||
}
|
||||
void MainWindow::onConfigScopesSaving() { m_ServerConfig.commit(); }
|
||||
|
||||
void MainWindow::onAppConfigTlsChanged() {
|
||||
updateLocalFingerprint();
|
||||
@ -421,7 +410,7 @@ bool MainWindow::on_m_pActionSave_triggered() {
|
||||
QString fileName =
|
||||
QFileDialog::getSaveFileName(this, QString("Save configuration as..."));
|
||||
|
||||
if (!fileName.isEmpty() && !serverConfig().save(fileName)) {
|
||||
if (!fileName.isEmpty() && !m_ServerConfig.save(fileName)) {
|
||||
QMessageBox::warning(
|
||||
this, QString("Save failed"),
|
||||
QString("Could not save configuration to file."));
|
||||
@ -432,8 +421,8 @@ bool MainWindow::on_m_pActionSave_triggered() {
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pActionAbout_triggered() {
|
||||
AboutDialog dlg(this, appConfig());
|
||||
dlg.exec();
|
||||
AboutDialog about(this);
|
||||
about.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pActionHelp_triggered() {
|
||||
@ -442,13 +431,14 @@ void MainWindow::on_m_pActionHelp_triggered() {
|
||||
|
||||
void MainWindow::on_m_pActionSettings_triggered() {
|
||||
auto result =
|
||||
SettingsDialog(this, appConfig(), m_LicenseHandler.license()).exec();
|
||||
SettingsDialog(this, m_AppConfig, m_LicenseHandler.license()).exec();
|
||||
if (result == QDialog::Accepted) {
|
||||
enableServer(appConfig().serverGroupChecked());
|
||||
enableClient(appConfig().clientGroupChecked());
|
||||
auto state = m_CoreState;
|
||||
if ((state == CoreState::Connected) || (state == CoreState::Connecting) ||
|
||||
(state == CoreState::Listening)) {
|
||||
m_ConfigScopes.save();
|
||||
|
||||
applyConfig();
|
||||
applyCloseToTray();
|
||||
|
||||
if (isCoreActive()) {
|
||||
restartCore();
|
||||
}
|
||||
}
|
||||
@ -460,6 +450,14 @@ void MainWindow::on_m_pButtonConfigureServer_clicked() {
|
||||
|
||||
void MainWindow::on_m_pActivate_triggered() { showActivationDialog(); }
|
||||
|
||||
void MainWindow::on_m_pLineEditHostname_returnPressed() {
|
||||
m_pButtonConnect->click();
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pLineEditClientIp_returnPressed() {
|
||||
m_pButtonConnectToClient->click();
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pButtonApply_clicked() {
|
||||
m_ClientConnection.setCheckConnection(true);
|
||||
restartCore();
|
||||
@ -477,13 +475,13 @@ void MainWindow::on_m_pLabelFingerprint_linkActivated(const QString &) {
|
||||
void MainWindow::on_m_pRadioGroupServer_clicked(bool) {
|
||||
enableServer(true);
|
||||
enableClient(false);
|
||||
m_AppConfig.saveSettings();
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pRadioGroupClient_clicked(bool) {
|
||||
enableClient(true);
|
||||
enableServer(false);
|
||||
m_AppConfig.saveSettings();
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
void MainWindow::on_m_pButtonConnect_clicked() { on_m_pButtonApply_clicked(); }
|
||||
@ -527,7 +525,7 @@ void MainWindow::open() {
|
||||
setIcon(CoreState::Disconnected);
|
||||
});
|
||||
|
||||
if (appConfig().autoHide()) {
|
||||
if (m_AppConfig.autoHide()) {
|
||||
hide();
|
||||
} else {
|
||||
showNormal();
|
||||
@ -538,8 +536,8 @@ void MainWindow::open() {
|
||||
// only start if user has previously started. this stops the gui from
|
||||
// auto hiding before the user has configured synergy (which of course
|
||||
// confuses first time users, who think synergy has crashed).
|
||||
if (appConfig().startedBefore() &&
|
||||
appConfig().processMode() == ProcessMode::kDesktop) {
|
||||
if (m_AppConfig.startedBefore() &&
|
||||
m_AppConfig.processMode() == ProcessMode::kDesktop) {
|
||||
startCore();
|
||||
}
|
||||
}
|
||||
@ -580,20 +578,24 @@ void MainWindow::createMenuBar() {
|
||||
}
|
||||
|
||||
void MainWindow::applyConfig() {
|
||||
enableServer(appConfig().serverGroupChecked());
|
||||
enableClient(appConfig().clientGroupChecked());
|
||||
enableServer(m_AppConfig.serverGroupChecked());
|
||||
enableClient(m_AppConfig.clientGroupChecked());
|
||||
|
||||
m_pLineEditHostname->setText(appConfig().serverHostname());
|
||||
m_pLineEditClientIp->setText(serverConfig().getClientAddress());
|
||||
m_pLineEditHostname->setText(m_AppConfig.serverHostname());
|
||||
m_pLineEditClientIp->setText(m_ServerConfig.getClientAddress());
|
||||
}
|
||||
|
||||
void MainWindow::applyCloseToTray() const {
|
||||
QApplication::setQuitOnLastWindowClosed(!m_AppConfig.closeToTray());
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings() {
|
||||
appConfig().setServerGroupChecked(m_pRadioGroupServer->isChecked());
|
||||
appConfig().setClientGroupChecked(m_pRadioGroupClient->isChecked());
|
||||
appConfig().setServerHostname(m_pLineEditHostname->text());
|
||||
serverConfig().setClientAddress(m_pLineEditClientIp->text());
|
||||
m_AppConfig.setServerGroupChecked(m_pRadioGroupServer->isChecked());
|
||||
m_AppConfig.setClientGroupChecked(m_pRadioGroupClient->isChecked());
|
||||
m_AppConfig.setServerHostname(m_pLineEditHostname->text());
|
||||
m_ServerConfig.setClientAddress(m_pLineEditClientIp->text());
|
||||
|
||||
appConfig().scopes().saveAll();
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
void MainWindow::setIcon(CoreState state) const {
|
||||
@ -622,19 +624,22 @@ void MainWindow::setIcon(CoreState state) const {
|
||||
}
|
||||
|
||||
void MainWindow::appendLogInfo(const QString &text) {
|
||||
qInfo("%s", text.toStdString().c_str());
|
||||
|
||||
processCoreLogLine(getTimeStamp() + " INFO: " + text);
|
||||
}
|
||||
|
||||
void MainWindow::appendLogDebug(const QString &text) {
|
||||
qDebug("%s", text.toStdString().c_str());
|
||||
|
||||
if (appConfig().logLevel() >= kDebugLogLevel) {
|
||||
if (m_AppConfig.logLevel() >= kDebugLogLevel) {
|
||||
processCoreLogLine(getTimeStamp() + " DEBUG: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::appendLogError(const QString &text) {
|
||||
onIpcClientReadLogLine(getTimeStamp() + " ERROR: " + text);
|
||||
qCritical("%s", text.toStdString().c_str());
|
||||
processCoreLogLine(getTimeStamp() + " ERROR: " + text);
|
||||
}
|
||||
|
||||
void MainWindow::processCoreLogLine(const QString &text) {
|
||||
@ -644,7 +649,7 @@ void MainWindow::processCoreLogLine(const QString &text) {
|
||||
}
|
||||
|
||||
// only start if there is no active service running
|
||||
if (line.contains("service status: idle") && appConfig().startedBefore()) {
|
||||
if (line.contains("service status: idle") && m_AppConfig.startedBefore()) {
|
||||
startCore();
|
||||
}
|
||||
|
||||
@ -689,15 +694,11 @@ void MainWindow::checkConnected(const QString &line) {
|
||||
if (line.contains("connected to server") || line.contains("has connected")) {
|
||||
setCoreState(CoreState::Connected);
|
||||
|
||||
if (!appConfig().startedBefore() && isVisible()) {
|
||||
QMessageBox::information(
|
||||
this, "Synergy",
|
||||
QString("Synergy is now connected. You can close the "
|
||||
"config window and Synergy will remain connected in "
|
||||
"the background."));
|
||||
|
||||
appConfig().setStartedBefore(true);
|
||||
if (isVisible()) {
|
||||
showFirstRunMessage();
|
||||
showDevThanksMessage();
|
||||
}
|
||||
|
||||
} else if (line.contains("started server")) {
|
||||
setCoreState(CoreState::Listening);
|
||||
} else if (
|
||||
@ -803,8 +804,53 @@ void MainWindow::showEvent(QShowEvent *event) {
|
||||
emit shown();
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
if (!m_AppConfig.closeToTray()) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("window will hide to tray");
|
||||
if (!m_AppConfig.showCloseReminder()) {
|
||||
return;
|
||||
}
|
||||
|
||||
messages::showCloseReminder(this);
|
||||
m_AppConfig.setShowCloseReminder(false);
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
void MainWindow::showFirstRunMessage() {
|
||||
if (m_AppConfig.startedBefore()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_AppConfig.setStartedBefore(true);
|
||||
m_ConfigScopes.save();
|
||||
|
||||
const auto isServer = coreMode() == CoreMode::Server;
|
||||
messages::showFirstRunMessage(
|
||||
this, m_AppConfig.closeToTray(), m_AppConfig.enableService(), isServer);
|
||||
}
|
||||
|
||||
void MainWindow::showDevThanksMessage() {
|
||||
if (!m_AppConfig.showDevThanks()) {
|
||||
qDebug("skipping dev thanks message, disabled in settings");
|
||||
return;
|
||||
}
|
||||
|
||||
if (kLicensingEnabled) {
|
||||
qDebug("licensing enabled, skipping dev thanks message");
|
||||
return;
|
||||
}
|
||||
|
||||
m_AppConfig.setShowDevThanks(false);
|
||||
m_ConfigScopes.save();
|
||||
|
||||
messages::showDevThanks(this, kProductName);
|
||||
}
|
||||
|
||||
void MainWindow::startCore() {
|
||||
appendLogDebug("starting core process");
|
||||
appendLogInfo(QString("starting core %1 process").arg(coreModeString()));
|
||||
|
||||
saveSettings();
|
||||
|
||||
@ -828,11 +874,11 @@ void MainWindow::startCore() {
|
||||
|
||||
args << "-f"
|
||||
<< "--no-tray"
|
||||
<< "--debug" << appConfig().logLevelText();
|
||||
<< "--debug" << m_AppConfig.logLevelText();
|
||||
|
||||
args << "--name" << appConfig().screenName();
|
||||
args << "--name" << m_AppConfig.screenName();
|
||||
|
||||
ProcessMode mode = appConfig().processMode();
|
||||
ProcessMode mode = m_AppConfig.processMode();
|
||||
|
||||
if (mode == ProcessMode::kDesktop) {
|
||||
m_pCoreProcess = std::make_unique<QProcess>(this);
|
||||
@ -850,7 +896,7 @@ void MainWindow::startCore() {
|
||||
// unnecessary restarts when synergy was started elevated or
|
||||
// when it is not allowed to elevate. In these cases restarting
|
||||
// the server is fruitless.
|
||||
if (appConfig().elevateMode() == ElevateAsNeeded) {
|
||||
if (m_AppConfig.elevateMode() == ElevateAsNeeded) {
|
||||
args << "--stop-on-desk-switch";
|
||||
}
|
||||
#endif
|
||||
@ -896,10 +942,6 @@ void MainWindow::startCore() {
|
||||
if (!m_pLogOutput->toPlainText().isEmpty())
|
||||
onIpcClientReadLogLine("");
|
||||
|
||||
appendLogInfo(
|
||||
"starting " +
|
||||
QString(coreMode() == CoreMode::Server ? "server" : "client"));
|
||||
|
||||
if ((coreMode() == CoreMode::Client && !clientArgs(args, app)) ||
|
||||
(coreMode() == CoreMode::Server && !serverArgs(args, app))) {
|
||||
onActionStopCoreTriggered();
|
||||
@ -918,15 +960,14 @@ void MainWindow::startCore() {
|
||||
&MainWindow::onCoreProcessReadyReadStandardError);
|
||||
}
|
||||
|
||||
// show command if debug log level...
|
||||
if (appConfig().logLevel() >= 4) {
|
||||
if (m_AppConfig.logLevel() >= kDebugLogLevel) {
|
||||
appendLogInfo(QString("command: %1 %2").arg(app, args.join(" ")));
|
||||
}
|
||||
|
||||
appendLogInfo("log level: " + appConfig().logLevelText());
|
||||
appendLogInfo("log level: " + m_AppConfig.logLevelText());
|
||||
|
||||
if (appConfig().logToFile())
|
||||
appendLogInfo("log file: " + appConfig().logFilename());
|
||||
if (m_AppConfig.logToFile())
|
||||
appendLogInfo("log file: " + m_AppConfig.logFilename());
|
||||
|
||||
if (mode == ProcessMode::kDesktop) {
|
||||
m_pCoreProcess->start(app, args);
|
||||
@ -944,12 +985,12 @@ void MainWindow::startCore() {
|
||||
}
|
||||
} else if (mode == ProcessMode::kService) {
|
||||
QString command(app + " " + args.join(" "));
|
||||
m_IpcClient.sendCommand(command, appConfig().elevateMode());
|
||||
m_IpcClient.sendCommand(command, m_AppConfig.elevateMode());
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::clientArgs(QStringList &args, QString &app) {
|
||||
app = appPath(appConfig().coreClientName());
|
||||
app = appPath(m_AppConfig.coreClientName());
|
||||
|
||||
if (!QFile::exists(app)) {
|
||||
show();
|
||||
@ -959,22 +1000,22 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (appConfig().logToFile()) {
|
||||
appConfig().persistLogDir();
|
||||
args << "--log" << appConfig().logFilename();
|
||||
if (m_AppConfig.logToFile()) {
|
||||
m_AppConfig.persistLogDir();
|
||||
args << "--log" << m_AppConfig.logFilename();
|
||||
}
|
||||
|
||||
if (appConfig().languageSync()) {
|
||||
if (m_AppConfig.languageSync()) {
|
||||
args << "--sync-language";
|
||||
}
|
||||
|
||||
if (appConfig().invertScrollDirection()) {
|
||||
if (m_AppConfig.invertScrollDirection()) {
|
||||
args << "--invert-scroll";
|
||||
}
|
||||
|
||||
if (appConfig().invertConnection()) {
|
||||
if (m_AppConfig.invertConnection()) {
|
||||
args << "--host";
|
||||
args << ":" + QString::number(appConfig().port());
|
||||
args << ":" + QString::number(m_AppConfig.port());
|
||||
} else {
|
||||
if (m_pLineEditHostname->text().isEmpty()) {
|
||||
show();
|
||||
@ -994,7 +1035,7 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
|
||||
hostName.push_back(']');
|
||||
}
|
||||
}
|
||||
args << hostName + ":" + QString::number(appConfig().port());
|
||||
args << hostName + ":" + QString::number(m_AppConfig.port());
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1002,8 +1043,8 @@ bool MainWindow::clientArgs(QStringList &args, QString &app) {
|
||||
|
||||
QString MainWindow::configFilename() {
|
||||
QString configFullPath;
|
||||
if (appConfig().useExternalConfig()) {
|
||||
configFullPath = appConfig().configFile();
|
||||
if (m_AppConfig.useExternalConfig()) {
|
||||
configFullPath = m_AppConfig.configFile();
|
||||
} else {
|
||||
QStringList errors;
|
||||
for (auto path :
|
||||
@ -1023,7 +1064,7 @@ QString MainWindow::configFilename() {
|
||||
continue;
|
||||
}
|
||||
|
||||
serverConfig().save(configFile);
|
||||
m_ServerConfig.save(configFile);
|
||||
configFile.close();
|
||||
configFullPath = configFile.fileName();
|
||||
|
||||
@ -1040,7 +1081,7 @@ QString MainWindow::configFilename() {
|
||||
}
|
||||
|
||||
QString MainWindow::address() const {
|
||||
QString i = appConfig().networkInterface();
|
||||
QString i = m_AppConfig.networkInterface();
|
||||
// if interface is IPv6 - ensure that ip is in square brackets
|
||||
if (i.count(':') > 1) {
|
||||
if (i[0] != '[') {
|
||||
@ -1050,7 +1091,7 @@ QString MainWindow::address() const {
|
||||
i.push_back(']');
|
||||
}
|
||||
}
|
||||
return (!i.isEmpty() ? i : "") + ":" + QString::number(appConfig().port());
|
||||
return (!i.isEmpty() ? i : "") + ":" + QString::number(m_AppConfig.port());
|
||||
}
|
||||
|
||||
QString MainWindow::appPath(const QString &name) const {
|
||||
@ -1059,7 +1100,7 @@ QString MainWindow::appPath(const QString &name) const {
|
||||
}
|
||||
|
||||
bool MainWindow::serverArgs(QStringList &args, QString &app) {
|
||||
app = appPath(appConfig().coreServerName());
|
||||
app = appPath(m_AppConfig.coreServerName());
|
||||
|
||||
if (!QFile::exists(app)) {
|
||||
QMessageBox::warning(
|
||||
@ -1068,17 +1109,17 @@ bool MainWindow::serverArgs(QStringList &args, QString &app) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (appConfig().invertConnection() && m_pLineEditClientIp->text().isEmpty()) {
|
||||
if (m_AppConfig.invertConnection() && m_pLineEditClientIp->text().isEmpty()) {
|
||||
QMessageBox::warning(
|
||||
this, QString("Client IP address or name is empty"),
|
||||
QString("Please fill in a client IP address or name."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (appConfig().logToFile()) {
|
||||
appConfig().persistLogDir();
|
||||
if (m_AppConfig.logToFile()) {
|
||||
m_AppConfig.persistLogDir();
|
||||
|
||||
args << "--log" << appConfig().logFilename();
|
||||
args << "--log" << m_AppConfig.logFilename();
|
||||
}
|
||||
|
||||
QString configFilename = this->configFilename();
|
||||
@ -1089,8 +1130,8 @@ bool MainWindow::serverArgs(QStringList &args, QString &app) {
|
||||
args << "-c" << configFilename << "--address" << address();
|
||||
appendLogInfo("config file: " + configFilename);
|
||||
|
||||
if (kLicensingEnabled && !appConfig().serialKey().isEmpty()) {
|
||||
args << "--serial-key" << appConfig().serialKey();
|
||||
if (kLicensingEnabled && !m_AppConfig.serialKey().isEmpty()) {
|
||||
args << "--serial-key" << m_AppConfig.serialKey();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1101,9 +1142,9 @@ void MainWindow::stopCore() {
|
||||
|
||||
m_ExpectedRunningState = RuningState::Stopped;
|
||||
|
||||
if (appConfig().processMode() == ProcessMode::kService) {
|
||||
if (m_AppConfig.processMode() == ProcessMode::kService) {
|
||||
stopService();
|
||||
} else if (appConfig().processMode() == ProcessMode::kDesktop) {
|
||||
} else if (m_AppConfig.processMode() == ProcessMode::kDesktop) {
|
||||
stopDesktop();
|
||||
}
|
||||
|
||||
@ -1115,7 +1156,7 @@ void MainWindow::stopCore() {
|
||||
|
||||
void MainWindow::stopService() {
|
||||
// send empty command to stop service from laucning anything.
|
||||
m_IpcClient.sendCommand("", appConfig().elevateMode());
|
||||
m_IpcClient.sendCommand("", m_AppConfig.elevateMode());
|
||||
}
|
||||
|
||||
void MainWindow::stopDesktop() {
|
||||
@ -1229,8 +1270,31 @@ void MainWindow::setVisible(bool visible) {
|
||||
}
|
||||
|
||||
MainWindow::CoreMode MainWindow::coreMode() const {
|
||||
auto isClient = m_pRadioGroupClient->isChecked();
|
||||
return isClient ? CoreMode::Client : CoreMode::Server;
|
||||
using enum CoreMode;
|
||||
|
||||
auto serverChecked = m_pRadioGroupServer->isChecked();
|
||||
auto clientChecked = m_pRadioGroupClient->isChecked();
|
||||
|
||||
if (serverChecked) {
|
||||
return Server;
|
||||
} else if (clientChecked) {
|
||||
return Client;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
QString MainWindow::coreModeString() const {
|
||||
using enum CoreMode;
|
||||
|
||||
switch (coreMode()) {
|
||||
case Server:
|
||||
return "server";
|
||||
case Client:
|
||||
return "client";
|
||||
default:
|
||||
qFatal("invalid core mode");
|
||||
}
|
||||
}
|
||||
|
||||
QString MainWindow::getIPAddresses() const {
|
||||
@ -1291,22 +1355,22 @@ void MainWindow::updateLocalFingerprint() {
|
||||
}
|
||||
}
|
||||
|
||||
LicenseHandler &MainWindow::licenseHandler() { return m_LicenseHandler; }
|
||||
|
||||
void MainWindow::updateWindowTitle() {
|
||||
QString MainWindow::productName() const {
|
||||
if (kLicensingEnabled) {
|
||||
setWindowTitle(m_LicenseHandler.productName());
|
||||
return m_LicenseHandler.productName();
|
||||
} else if (!kProductName.isEmpty()) {
|
||||
return kProductName;
|
||||
} else {
|
||||
setWindowTitle(kProductName);
|
||||
qFatal("product name not set");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateWindowTitle() { setWindowTitle(productName()); }
|
||||
|
||||
void MainWindow::autoAddScreen(const QString name) {
|
||||
|
||||
if (m_ActivationDialogRunning) {
|
||||
// TODO: refactor this code
|
||||
// add this screen to the pending list and check this list until
|
||||
// users finish activation dialog
|
||||
// add this screen to the pending list if the activation dialog is running.
|
||||
m_PendingClientNames.append(name);
|
||||
return;
|
||||
}
|
||||
@ -1316,7 +1380,7 @@ void MainWindow::autoAddScreen(const QString name) {
|
||||
switch (r) {
|
||||
case kAutoAddScreenManualServer:
|
||||
showConfigureServer(QString("Please add the server (%1) to the grid.")
|
||||
.arg(appConfig().screenName()));
|
||||
.arg(m_AppConfig.screenName()));
|
||||
break;
|
||||
|
||||
case kAutoAddScreenManualClient:
|
||||
@ -1328,18 +1392,18 @@ void MainWindow::autoAddScreen(const QString name) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showConfigureServer(const QString &message) {
|
||||
bool MainWindow::isCoreActive() const {
|
||||
using enum CoreState;
|
||||
|
||||
ServerConfigDialog dlg(this, serverConfig(), appConfig());
|
||||
dlg.message(message);
|
||||
auto result = dlg.exec();
|
||||
auto state = m_CoreState;
|
||||
return (state == Connected) || (state == Connecting) || (state == Listening);
|
||||
}
|
||||
|
||||
if (result == QDialog::Accepted) {
|
||||
auto state = m_CoreState;
|
||||
if ((state == Connected) || (state == Connecting) || (state == Listening)) {
|
||||
restartCore();
|
||||
}
|
||||
void MainWindow::showConfigureServer(const QString &message) {
|
||||
ServerConfigDialog dialog(this, serverConfig(), m_AppConfig);
|
||||
dialog.message(message);
|
||||
if ((dialog.exec() == QDialog::Accepted) && isCoreActive()) {
|
||||
restartCore();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1354,6 +1418,11 @@ int MainWindow::showActivationDialog() {
|
||||
int result = activationDialog.exec();
|
||||
m_ActivationDialogRunning = false;
|
||||
|
||||
if (result == QDialog::Accepted) {
|
||||
m_AppConfig.setActivationHasRun(true);
|
||||
m_ConfigScopes.save();
|
||||
}
|
||||
|
||||
if (!m_PendingClientNames.empty()) {
|
||||
foreach (const QString &name, m_PendingClientNames) {
|
||||
autoAddScreen(name);
|
||||
@ -1391,23 +1460,33 @@ void MainWindow::updateScreenName() {
|
||||
m_pLabelComputerName->setText(
|
||||
QString("This computer's name: %1 "
|
||||
R"((<a href="#" style="color: %2">change</a>))")
|
||||
.arg(appConfig().screenName())
|
||||
.arg(m_AppConfig.screenName())
|
||||
.arg(kColorSecondary));
|
||||
serverConfig().updateServerName();
|
||||
m_ServerConfig.updateServerName();
|
||||
}
|
||||
|
||||
void MainWindow::enableServer(bool enable) {
|
||||
qDebug(enable ? "server enabled" : "server disabled");
|
||||
m_AppConfig.setServerGroupChecked(enable);
|
||||
m_pRadioGroupServer->setChecked(enable);
|
||||
m_pWidgetServer->setEnabled(enable);
|
||||
m_pWidgetServerInverse->setVisible(m_AppConfig.invertConnection());
|
||||
m_pButtonToggleStart->setEnabled(true);
|
||||
|
||||
if (enable) {
|
||||
m_pButtonToggleStart->setEnabled(true);
|
||||
m_pActionStartCore->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::enableClient(bool enable) {
|
||||
qDebug(enable ? "client enabled" : "client disabled");
|
||||
m_AppConfig.setClientGroupChecked(enable);
|
||||
m_pRadioGroupClient->setChecked(enable);
|
||||
m_pWidgetClient->setEnabled(enable);
|
||||
m_pWidgetClient->setVisible(!m_AppConfig.invertConnection());
|
||||
m_pButtonToggleStart->setEnabled(true);
|
||||
|
||||
if (enable) {
|
||||
m_pButtonToggleStart->setEnabled(true);
|
||||
m_pActionStartCore->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,22 +79,23 @@ public:
|
||||
PendingRetry
|
||||
};
|
||||
|
||||
enum class CoreMode { Client, Server };
|
||||
enum class CoreMode { None, Client, Server };
|
||||
enum class LogLevel { Error, Info };
|
||||
enum class RuningState { Started, Stopped };
|
||||
|
||||
public:
|
||||
explicit MainWindow(AppConfig &appConfig);
|
||||
explicit MainWindow(
|
||||
synergy::gui::ConfigScopes &configScopes, AppConfig &appConfig);
|
||||
~MainWindow() override;
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
CoreMode coreMode() const;
|
||||
QString coreModeString() const;
|
||||
QString address() const;
|
||||
QString appPath(const QString &name) const;
|
||||
void open();
|
||||
ServerConfig &serverConfig() { return m_ServerConfig; }
|
||||
void autoAddScreen(const QString name);
|
||||
LicenseHandler &licenseHandler();
|
||||
int showActivationDialog();
|
||||
void appendLogInfo(const QString &text);
|
||||
void appendLogDebug(const QString &text);
|
||||
@ -110,7 +111,7 @@ public slots:
|
||||
private slots:
|
||||
void onCreated();
|
||||
void onShown();
|
||||
void onAppConfigLoaded();
|
||||
void onConfigScopesSaving();
|
||||
void onAppConfigTlsChanged();
|
||||
void onAppConfigScreenNameChanged();
|
||||
void onAppConfigInvertConnection();
|
||||
@ -142,15 +143,17 @@ private slots:
|
||||
void on_m_pActionHelp_triggered();
|
||||
void on_m_pActionSettings_triggered();
|
||||
void on_m_pActivate_triggered();
|
||||
void on_m_pLineEditHostname_returnPressed();
|
||||
void on_m_pLineEditClientIp_returnPressed();
|
||||
|
||||
private:
|
||||
QSettings &settings() { return *appConfig().scopes().currentSettings(); }
|
||||
AppConfig &appConfig() { return m_AppConfig; }
|
||||
AppConfig const &appConfig() const { return m_AppConfig; }
|
||||
void createMenuBar();
|
||||
void createStatusBar();
|
||||
void createTrayIcon();
|
||||
void applyConfig();
|
||||
void applyCloseToTray() const;
|
||||
void setIcon(CoreState state) const;
|
||||
void setCoreState(CoreState state);
|
||||
bool checkForApp(int which, QString &app);
|
||||
@ -172,6 +175,7 @@ private:
|
||||
QString getTimeStamp() const;
|
||||
void restartCore();
|
||||
void showEvent(QShowEvent *) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void secureSocket(bool secureSocket);
|
||||
void windowStateChanged();
|
||||
void connectSlots() const;
|
||||
@ -183,6 +187,7 @@ private:
|
||||
void updateScreenName();
|
||||
void saveSettings();
|
||||
QString configFilename();
|
||||
bool isCoreActive() const;
|
||||
void showConfigureServer(const QString &message);
|
||||
void showConfigureServer() { showConfigureServer(""); }
|
||||
void showLicenseNotice();
|
||||
@ -192,6 +197,9 @@ private:
|
||||
void setupControls();
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void moveEvent(QMoveEvent *event) override;
|
||||
void showFirstRunMessage();
|
||||
void showDevThanksMessage();
|
||||
QString productName() const;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
void checkOSXNotification(const QString &line);
|
||||
@ -216,9 +224,10 @@ private:
|
||||
bool m_SecureSocket = false;
|
||||
QString m_SecureSocketVersion = "";
|
||||
bool m_SaveWindow = false;
|
||||
|
||||
AppConfig &m_AppConfig;
|
||||
LicenseHandler m_LicenseHandler;
|
||||
|
||||
synergy::gui::ConfigScopes &m_ConfigScopes;
|
||||
AppConfig &m_AppConfig;
|
||||
ServerConfig m_ServerConfig;
|
||||
ServerConnection m_ServerConnection;
|
||||
ClientConnection m_ClientConnection;
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QFrame" name="m_pGroupServer">
|
||||
<widget class="QGroupBox" name="m_pGroupServer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@ -268,7 +268,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="m_pGroupClient">
|
||||
<widget class="QGroupBox" name="m_pGroupClient">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@ -599,6 +599,9 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_pActionStartCore">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Start</string>
|
||||
</property>
|
||||
|
||||
@ -24,18 +24,4 @@
|
||||
#include <QtGui>
|
||||
|
||||
QSynergyApplication::QSynergyApplication(int &argc, char **argv)
|
||||
: QApplication(argc, argv) {
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
void QSynergyApplication::commitData(const QSessionManager &) const {
|
||||
foreach (QWidget *widget, topLevelWidgets()) {
|
||||
MainWindow *mainWindow = qobject_cast<MainWindow *>(widget);
|
||||
if (mainWindow)
|
||||
mainWindow->saveSettings();
|
||||
}
|
||||
}
|
||||
: QApplication(argc, argv) {}
|
||||
|
||||
@ -26,6 +26,4 @@ class QSynergyApplication : public QApplication {
|
||||
public:
|
||||
QSynergyApplication(int &argc, char **argv);
|
||||
~QSynergyApplication() override = default;
|
||||
|
||||
void commitData(const QSessionManager &manager) const;
|
||||
};
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
#include "ScreenSettingsDialog.h"
|
||||
#include "Screen.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/styles.h"
|
||||
#include "validators/AliasValidator.h"
|
||||
#include "validators/ScreenNameValidator.h"
|
||||
#include "validators/ValidationError.h"
|
||||
|
||||
@ -21,8 +21,6 @@
|
||||
#include "AddClientDialog.h"
|
||||
#include "Hotkey.h"
|
||||
#include "MainWindow.h"
|
||||
#include "gui/ConfigScopes.h"
|
||||
#include "gui/constants.h"
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QMessageBox>
|
||||
@ -44,23 +42,14 @@ static const struct {
|
||||
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),
|
||||
AppConfig &appConfig, MainWindow &mainWindow, int columns, int rows)
|
||||
: m_pAppConfig(&appConfig),
|
||||
m_pMainWindow(&mainWindow),
|
||||
m_Screens(columns),
|
||||
m_Columns(columns),
|
||||
m_Rows(rows),
|
||||
m_ClipboardSharingSize(defaultClipboardSharingSize()) {
|
||||
appConfig->scopes().registerReceiver(this);
|
||||
}
|
||||
|
||||
ServerConfig::~ServerConfig() {
|
||||
try {
|
||||
ServerConfig::saveSettings();
|
||||
} catch (const std::exception &e) {
|
||||
qDebug() << e.what();
|
||||
m_pMainWindow->appendLogError(e.what());
|
||||
}
|
||||
recall();
|
||||
}
|
||||
|
||||
bool ServerConfig::save(const QString &fileName) const {
|
||||
@ -75,8 +64,8 @@ bool ServerConfig::save(const QString &fileName) const {
|
||||
}
|
||||
|
||||
bool ServerConfig::operator==(const ServerConfig &sc) const {
|
||||
return m_Screens == sc.m_Screens && m_NumColumns == sc.m_NumColumns &&
|
||||
m_NumRows == sc.m_NumRows && m_HasHeartbeat == sc.m_HasHeartbeat &&
|
||||
return m_Screens == sc.m_Screens && m_Columns == sc.m_Columns &&
|
||||
m_Rows == sc.m_Rows && m_HasHeartbeat == sc.m_HasHeartbeat &&
|
||||
m_Heartbeat == sc.m_Heartbeat &&
|
||||
m_RelativeMouseMoves == sc.m_RelativeMouseMoves &&
|
||||
m_Win32KeepForeground == sc.m_Win32KeepForeground &&
|
||||
@ -99,7 +88,7 @@ void ServerConfig::save(QFile &file) const {
|
||||
outStream << *this;
|
||||
}
|
||||
|
||||
void ServerConfig::init() {
|
||||
void ServerConfig::setupScreens() {
|
||||
switchCorners().clear();
|
||||
screens().clear();
|
||||
hotkeys().clear();
|
||||
@ -114,7 +103,9 @@ void ServerConfig::init() {
|
||||
addScreen(Screen());
|
||||
}
|
||||
|
||||
void ServerConfig::saveSettings() {
|
||||
void ServerConfig::commit() {
|
||||
qDebug("committing server config");
|
||||
|
||||
settings().beginGroup("internalConfig");
|
||||
settings().remove("");
|
||||
|
||||
@ -163,7 +154,9 @@ void ServerConfig::saveSettings() {
|
||||
settings().endGroup();
|
||||
}
|
||||
|
||||
void ServerConfig::loadSettings() {
|
||||
void ServerConfig::recall() {
|
||||
qDebug("recalling server config");
|
||||
|
||||
settings().beginGroup("internalConfig");
|
||||
|
||||
setNumColumns(settings().value("numColumns", 5).toInt());
|
||||
@ -171,7 +164,7 @@ void ServerConfig::loadSettings() {
|
||||
|
||||
// we need to know the number of columns and rows before we can set up
|
||||
// ourselves
|
||||
init();
|
||||
setupScreens();
|
||||
|
||||
haveHeartbeat(settings().value("hasHeartbeat", false).toBool());
|
||||
setHeartbeat(settings().value("heartbeat", 5000).toInt());
|
||||
@ -398,7 +391,6 @@ int ServerConfig::autoAddScreen(const QString name) {
|
||||
return kAutoAddScreenManualClient;
|
||||
}
|
||||
|
||||
saveSettings();
|
||||
return kAutoAddScreenOk;
|
||||
}
|
||||
|
||||
@ -410,7 +402,6 @@ void ServerConfig::updateServerName() {
|
||||
for (auto &screen : screens()) {
|
||||
if (screen.isServer()) {
|
||||
screen.setName(m_pAppConfig->screenName());
|
||||
saveSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -553,5 +544,5 @@ QString ServerConfig::getClientAddress() const {
|
||||
}
|
||||
|
||||
QSettings &ServerConfig::settings() {
|
||||
return *m_pAppConfig->scopes().currentSettings();
|
||||
return *m_pAppConfig->scopes().activeSettings();
|
||||
}
|
||||
|
||||
@ -21,10 +21,12 @@
|
||||
#include "Hotkey.h"
|
||||
#include "ScreenConfig.h"
|
||||
#include "ScreenList.h"
|
||||
#include "gui/CommonConfig.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
const auto kDefaultColumns = 5;
|
||||
const auto kDefaultRows = 3;
|
||||
|
||||
class QTextStream;
|
||||
class QSettings;
|
||||
class QString;
|
||||
@ -33,7 +35,7 @@ class ServerConfigDialog;
|
||||
class MainWindow;
|
||||
class AppConfig;
|
||||
|
||||
class ServerConfig : public ScreenConfig, public synergy::gui::CommonConfig {
|
||||
class ServerConfig : public ScreenConfig {
|
||||
friend class ServerConfigDialog;
|
||||
friend class ServerConnection;
|
||||
friend QTextStream &
|
||||
@ -41,15 +43,15 @@ class ServerConfig : public ScreenConfig, public synergy::gui::CommonConfig {
|
||||
|
||||
public:
|
||||
ServerConfig(
|
||||
int numColumns, int numRows, AppConfig *appConfig,
|
||||
MainWindow *mainWindow);
|
||||
~ServerConfig() override;
|
||||
AppConfig &appConfig, MainWindow &mainWindow,
|
||||
int columns = kDefaultColumns, int rows = kDefaultRows);
|
||||
~ServerConfig() = default;
|
||||
|
||||
bool operator==(const ServerConfig &sc) const;
|
||||
|
||||
const ScreenList &screens() const { return m_Screens; }
|
||||
int numColumns() const { return m_NumColumns; }
|
||||
int numRows() const { return m_NumRows; }
|
||||
int numColumns() const { return m_Columns; }
|
||||
int numRows() const { return m_Rows; }
|
||||
bool hasHeartbeat() const { return m_HasHeartbeat; }
|
||||
int heartbeat() const { return m_Heartbeat; }
|
||||
bool relativeMouseMoves() const { return m_RelativeMouseMoves; }
|
||||
@ -68,8 +70,7 @@ public:
|
||||
size_t clipboardSharingSize() const { return m_ClipboardSharingSize; }
|
||||
static size_t defaultClipboardSharingSize();
|
||||
|
||||
void saveSettings() override;
|
||||
void loadSettings() override;
|
||||
void commit();
|
||||
bool save(const QString &fileName) const;
|
||||
void save(QFile &file) const;
|
||||
int numScreens() const;
|
||||
@ -84,13 +85,15 @@ public:
|
||||
QString getClientAddress() const;
|
||||
void setClientAddress(const QString &address);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void recall();
|
||||
void setupScreens();
|
||||
QSettings &settings();
|
||||
ScreenList &screens() { return m_Screens; }
|
||||
void setScreens(const ScreenList &screens) { m_Screens = screens; }
|
||||
void addScreen(const Screen &screen) { m_Screens.append(screen); }
|
||||
void setNumColumns(int n) { m_NumColumns = n; }
|
||||
void setNumRows(int n) { m_NumRows = n; }
|
||||
void setNumColumns(int n) { m_Columns = n; }
|
||||
void setNumRows(int n) { m_Rows = n; }
|
||||
void haveHeartbeat(bool on) { m_HasHeartbeat = on; }
|
||||
void setHeartbeat(int val) { m_Heartbeat = val; }
|
||||
void setRelativeMouseMoves(bool on) { m_RelativeMouseMoves = on; }
|
||||
@ -109,11 +112,7 @@ protected:
|
||||
size_t setClipboardSharingSize(size_t size);
|
||||
QList<bool> &switchCorners() { return m_SwitchCorners; }
|
||||
HotkeyList &hotkeys() { return m_Hotkeys; }
|
||||
|
||||
void init();
|
||||
int adjacentScreenIndex(int idx, int deltaColumn, int deltaRow) const;
|
||||
|
||||
private:
|
||||
bool findScreenName(const QString &name, int &index);
|
||||
bool fixNoServer(const QString &name, int &index);
|
||||
int showAddClientDialog(const QString &clientName);
|
||||
@ -139,8 +138,8 @@ private:
|
||||
AppConfig *m_pAppConfig;
|
||||
MainWindow *m_pMainWindow;
|
||||
ScreenList m_Screens;
|
||||
int m_NumColumns;
|
||||
int m_NumRows;
|
||||
int m_Columns;
|
||||
int m_Rows;
|
||||
size_t m_ClipboardSharingSize;
|
||||
};
|
||||
|
||||
|
||||
@ -332,7 +332,7 @@
|
||||
</widget>
|
||||
<widget class="QWidget" name="m_pTabAdvanced">
|
||||
<attribute name="title">
|
||||
<string>Advanced server settings</string>
|
||||
<string>Advanced</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
@ -839,289 +839,284 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Advanced config</string>
|
||||
<string>Config file</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Core server config file</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Use a Core server config file to create complex screen layouts that are not possible with the simple grid-based screen layout editor.
|
||||
|
||||
[How to write a config file](https://symless.com/synergy/help/creating-text-config-files)
|
||||
|
||||
Enabling this setting will disable the server config GUI.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::MarkdownText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p style="text-align: center; font-family: Arial; font-size: 18px; line-height: 25px;">Config override</p></body></html></string>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxUseExternalConfig">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Core server config file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p style="text-align: center; font-size: 13px; font-family: Arial; line-hegiht: 18px;">If you have a config file and want to override all setttings with this file.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_pCheckBoxUseExternalConfig">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use configuration file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>96</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Config file path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pEditConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pButtonBrowseConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../res/Synergy.qrc">
|
||||
<normaloff>:/res/icons/64x64/folder.png</normaloff>:/res/icons/64x64/folder.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_pLabelConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>96</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Config file path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_pEditConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pButtonBrowseConfigFile">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../res/Synergy.qrc">
|
||||
<normaloff>:/res/icons/64x64/folder.png</normaloff>:/res/icons/64x64/folder.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
@ -69,10 +69,10 @@ void ServerConnection::addClient(const QString &clientName) {
|
||||
}
|
||||
|
||||
void ServerConnection::configureClient(const QString &clientName) {
|
||||
ServerConfigDialog dlg(
|
||||
ServerConfigDialog dialog(
|
||||
&m_parent, m_parent.serverConfig(), m_parent.appConfig());
|
||||
|
||||
if (dlg.addClient(clientName) && dlg.exec() == QDialog::Accepted) {
|
||||
if (dialog.addClient(clientName) && dialog.exec() == QDialog::Accepted) {
|
||||
m_parent.restartCore();
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ SettingsDialog::SettingsDialog(
|
||||
m_pMainWindow = dynamic_cast<MainWindow *>(parent);
|
||||
|
||||
loadFromConfig();
|
||||
m_isSystemAtStart = appConfig().isSystemScoped();
|
||||
m_wasOriginallySystemScope = appConfig().isActiveScopeSystem();
|
||||
updateControlsEnabled();
|
||||
|
||||
const auto &serveConfig = m_pMainWindow->serverConfig();
|
||||
@ -86,18 +86,17 @@ void SettingsDialog::accept() {
|
||||
appConfig().setTlsEnabled(m_pCheckBoxEnableCrypto->isChecked());
|
||||
appConfig().setLanguageSync(m_pCheckBoxLanguageSync->isChecked());
|
||||
appConfig().setInvertScrollDirection(m_pCheckBoxScrollDirection->isChecked());
|
||||
appConfig().setServiceEnabled(m_pCheckBoxServiceEnabled->isChecked());
|
||||
appConfig().setEnableService(m_pCheckBoxServiceEnabled->isChecked());
|
||||
appConfig().setCloseToTray(m_pCheckBoxCloseToTray->isChecked());
|
||||
appConfig().setInvertConnection(m_pInvertConnection->isChecked());
|
||||
|
||||
appConfig().saveSettings();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void SettingsDialog::reject() {
|
||||
// We should restore scope at start if the user rejects changes.
|
||||
if (appConfig().isSystemScoped() != m_isSystemAtStart) {
|
||||
appConfig().setLoadFromSystemScope(m_isSystemAtStart);
|
||||
// restore original system scope value on reject.
|
||||
if (appConfig().isActiveScopeSystem() != m_wasOriginallySystemScope) {
|
||||
appConfig().setLoadFromSystemScope(m_wasOriginallySystemScope);
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
@ -117,10 +116,10 @@ void SettingsDialog::loadFromConfig() {
|
||||
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.tlsEnabled());
|
||||
m_pCheckBoxLanguageSync->setChecked(m_appConfig.languageSync());
|
||||
m_pCheckBoxScrollDirection->setChecked(m_appConfig.invertScrollDirection());
|
||||
m_pCheckBoxServiceEnabled->setChecked(m_appConfig.serviceEnabled());
|
||||
m_pCheckBoxServiceEnabled->setChecked(m_appConfig.enableService());
|
||||
m_pCheckBoxCloseToTray->setChecked(m_appConfig.closeToTray());
|
||||
|
||||
if (m_appConfig.isSystemScoped()) {
|
||||
if (m_appConfig.isActiveScopeSystem()) {
|
||||
m_pRadioSystemScope->setChecked(true);
|
||||
} else {
|
||||
m_pRadioUserScope->setChecked(true);
|
||||
@ -147,14 +146,15 @@ void SettingsDialog::updateTlsControls() {
|
||||
}
|
||||
|
||||
void SettingsDialog::updateTlsControlsEnabled() {
|
||||
bool writable = appConfig().isActiveScopeWritable();
|
||||
auto clientMode = appConfig().clientGroupChecked();
|
||||
auto tlsAvailable = m_tlsUtility.isAvailableAndEnabled();
|
||||
auto tlsChecked = m_pCheckBoxEnableCrypto->isChecked();
|
||||
auto enabled = !clientMode && tlsAvailable && tlsChecked;
|
||||
auto enabled = writable && !clientMode && tlsAvailable && tlsChecked;
|
||||
|
||||
qDebug(
|
||||
"tls enabled=%d, client=%d, available=%d, checked=%d", enabled,
|
||||
clientMode, tlsAvailable, tlsChecked);
|
||||
"tls enabled=%d, writable=%d, client=%d, available=%d, checked=%d",
|
||||
enabled, writable, clientMode, tlsAvailable, tlsChecked);
|
||||
|
||||
m_pLabelKeyLength->setEnabled(enabled);
|
||||
m_pComboBoxKeyLength->setEnabled(enabled);
|
||||
@ -165,7 +165,7 @@ void SettingsDialog::updateTlsControlsEnabled() {
|
||||
}
|
||||
|
||||
bool SettingsDialog::isClientMode() const {
|
||||
return (m_pMainWindow->coreMode() == MainWindow::CoreMode::Client);
|
||||
return m_pMainWindow->coreMode() == MainWindow::CoreMode::Client;
|
||||
}
|
||||
|
||||
void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i) {
|
||||
@ -254,7 +254,7 @@ void SettingsDialog::updateKeyLengthOnFile(const QString &path) {
|
||||
}
|
||||
|
||||
void SettingsDialog::updateControlsEnabled() {
|
||||
bool writable = appConfig().isWritable();
|
||||
bool writable = appConfig().isActiveScopeWritable();
|
||||
|
||||
m_pLineEditScreenName->setEnabled(writable);
|
||||
m_pSpinBoxPort->setEnabled(writable);
|
||||
|
||||
@ -76,7 +76,7 @@ private:
|
||||
/// @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;
|
||||
bool m_wasOriginallySystemScope = false;
|
||||
|
||||
private slots:
|
||||
void on_m_pCheckBoxEnableCrypto_clicked(bool checked);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2012-2016 Symless Ltd.
|
||||
* Copyright (C) 2012 Symless Ltd.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -17,18 +17,16 @@
|
||||
|
||||
#include "SetupWizard.h"
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/styles.h"
|
||||
#include "validators/ScreenNameValidator.h"
|
||||
#include "validators/ValidationError.h"
|
||||
|
||||
SetupWizard::SetupWizard(MainWindow &mainWindow) : m_mainWindow(mainWindow) {
|
||||
|
||||
SetupWizard::SetupWizard(AppConfig &appConfig) : m_appConfig(appConfig) {
|
||||
setupUi(this);
|
||||
|
||||
m_pLabelError->setStyleSheet(kStyleErrorActiveLabel);
|
||||
|
||||
m_pLineEditName->setText(m_mainWindow.appConfig().screenName());
|
||||
m_pLineEditName->setText(appConfig.screenName());
|
||||
m_pLineEditName->setValidator(new validators::ScreenNameValidator(
|
||||
m_pLineEditName, new validators::ValidationError(this, m_pLabelError)));
|
||||
|
||||
@ -39,13 +37,8 @@ SetupWizard::SetupWizard(MainWindow &mainWindow) : m_mainWindow(mainWindow) {
|
||||
}
|
||||
|
||||
void SetupWizard::accept() {
|
||||
AppConfig &appConfig = m_mainWindow.appConfig();
|
||||
|
||||
appConfig.setWizardHasRun();
|
||||
appConfig.setScreenName(m_pLineEditName->text());
|
||||
appConfig.saveSettings();
|
||||
|
||||
m_mainWindow.open();
|
||||
m_appConfig.setWizardHasRun();
|
||||
m_appConfig.setScreenName(m_pLineEditName->text());
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
|
||||
#include "ui_SetupWizardBase.h"
|
||||
|
||||
#include "gui/AppConfig.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QObject>
|
||||
|
||||
@ -28,14 +30,14 @@ class SetupWizard : public QDialog, public Ui::SetupWizardBase {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SetupWizard(MainWindow &mainWindow);
|
||||
explicit SetupWizard(AppConfig &appConfig);
|
||||
|
||||
protected:
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
private:
|
||||
MainWindow &m_mainWindow;
|
||||
AppConfig &m_appConfig;
|
||||
|
||||
public slots:
|
||||
void onLineEditNameChanged(const QString &error);
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>772</width>
|
||||
<height>634</height>
|
||||
<width>764</width>
|
||||
<height>612</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -36,10 +36,10 @@
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>100</number>
|
||||
<number>150</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>100</number>
|
||||
<number>150</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
@ -54,7 +54,7 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<item alignment="Qt::AlignHCenter|Qt::AlignTop">
|
||||
<widget class="QLabel" name="m_pLabelImage">
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -63,11 +63,11 @@
|
||||
<pixmap resource="../res/Synergy.qrc">:/res/image/welcome.png</pixmap>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>30</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<item alignment="Qt::AlignHCenter|Qt::AlignTop">
|
||||
<widget class="QLabel" name="m_pLabelTitle">
|
||||
<property name="font">
|
||||
<font>
|
||||
@ -86,6 +86,15 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="m_pLabelName">
|
||||
<property name="text">
|
||||
@ -121,7 +130,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<item alignment="Qt::AlignHCenter|Qt::AlignTop">
|
||||
<widget class="QLabel" name="m_pHelpList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2016 Symless Ltd.
|
||||
* Copyright (C) 2021 Symless Ltd.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -33,9 +33,7 @@ static const std::vector<const char *> blockerText = {
|
||||
"Please switch to Xorg if you wish to continue using Synergy today.",
|
||||
};
|
||||
|
||||
SetupWizardBlocker::SetupWizardBlocker(
|
||||
MainWindow &mainWindow, qBlockerType type)
|
||||
: m_MainWindow(mainWindow) {
|
||||
SetupWizardBlocker::SetupWizardBlocker(BlockerType type) {
|
||||
setupUi(this);
|
||||
|
||||
m_pLabelTitle->setText(blockerTitels[static_cast<int>(type)]);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2012-2016 Symless Ltd.
|
||||
* Copyright (C) 2021 Symless Ltd.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -16,7 +16,9 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui_SetupWizardBlocker.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class MainWindow;
|
||||
@ -25,13 +27,10 @@ class SetupWizardBlocker : public QDialog, public Ui::SetupWizardBlocker {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class qBlockerType { waylandDetected };
|
||||
explicit SetupWizardBlocker(MainWindow &mainWindow, qBlockerType type);
|
||||
enum class BlockerType { Wayland };
|
||||
explicit SetupWizardBlocker(BlockerType type);
|
||||
|
||||
protected:
|
||||
void onlineSupport();
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
MainWindow &m_MainWindow;
|
||||
};
|
||||
|
||||
@ -21,9 +21,16 @@
|
||||
#include "SetupWizard.h"
|
||||
#include "SetupWizardBlocker.h"
|
||||
#include "gui/AppConfig.h"
|
||||
#include "gui/ConfigScopes.h"
|
||||
#include "gui/constants.h"
|
||||
#include "gui/dotenv.h"
|
||||
#include "gui/messages.h"
|
||||
#include "gui/version.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QObject>
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
|
||||
@ -46,19 +53,23 @@ bool checkMacAssistiveDevices();
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
/* Workaround for QTBUG-40332 - "High ping when QNetworkAccessManager is
|
||||
* instantiated" */
|
||||
::setenv("QT_BEARER_POLL_TIMEOUT", "-1", 1);
|
||||
#endif
|
||||
|
||||
dotenv(".env");
|
||||
|
||||
QCoreApplication::setOrganizationName("Synergy");
|
||||
QCoreApplication::setOrganizationDomain("http://symless.com/");
|
||||
QCoreApplication::setApplicationName("Synergy");
|
||||
QCoreApplication::setOrganizationName(kAppName);
|
||||
QCoreApplication::setApplicationName(kAppName);
|
||||
QCoreApplication::setOrganizationDomain(kAppDomain);
|
||||
|
||||
QSynergyApplication app(argc, argv);
|
||||
qInstallMessageHandler(synergy::gui::messages::messageHandler);
|
||||
|
||||
qInfo("Synergy v%s", synergy::gui::version().toUtf8().constData());
|
||||
|
||||
dotenv(".env");
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
|
||||
@ -75,31 +86,41 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
#endif
|
||||
|
||||
AppConfig appConfig;
|
||||
qRegisterMetaType<Edition>("Edition");
|
||||
|
||||
MainWindow mainWindow(appConfig);
|
||||
ConfigScopes configScopes;
|
||||
AppConfig appConfig(configScopes);
|
||||
|
||||
QObject::connect(
|
||||
&configScopes, &ConfigScopes::saving, &appConfig,
|
||||
[&appConfig]() { appConfig.commit(); }, Qt::DirectConnection);
|
||||
|
||||
std::unique_ptr<SetupWizardBlocker> setupBlocker;
|
||||
if (qgetenv("XDG_SESSION_TYPE") == "wayland") {
|
||||
SetupWizardBlocker blocked(SetupWizardBlocker::BlockerType::Wayland);
|
||||
blocked.exec();
|
||||
qInfo("wayland detected, exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (appConfig.wizardShouldRun()) {
|
||||
SetupWizard wizard(appConfig);
|
||||
auto result = wizard.exec();
|
||||
if (result != QDialog::Accepted) {
|
||||
qInfo("wizard cancelled, exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
configScopes.save();
|
||||
}
|
||||
|
||||
MainWindow mainWindow(configScopes, appConfig);
|
||||
|
||||
QObject::connect(
|
||||
&app, &QSynergyApplication::aboutToQuit, &mainWindow,
|
||||
&MainWindow::onAppAboutToQuit);
|
||||
|
||||
std::unique_ptr<SetupWizardBlocker> setupBlocker;
|
||||
if (qgetenv("XDG_SESSION_TYPE") == "wayland") {
|
||||
setupBlocker.reset(new SetupWizardBlocker(
|
||||
mainWindow, SetupWizardBlocker::qBlockerType::waylandDetected));
|
||||
setupBlocker->show();
|
||||
return QApplication::exec();
|
||||
}
|
||||
|
||||
std::unique_ptr<SetupWizard> setupWizard;
|
||||
if (appConfig.wizardShouldRun()) {
|
||||
setupWizard.reset(new SetupWizard(mainWindow));
|
||||
setupWizard->show();
|
||||
} else {
|
||||
mainWindow.open();
|
||||
}
|
||||
|
||||
mainWindow.open();
|
||||
return QSynergyApplication::exec();
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
#include "LineEditValidator.h"
|
||||
|
||||
#include "gui/constants.h"
|
||||
#include "gui/styles.h"
|
||||
#include <qvalidator.h>
|
||||
|
||||
namespace validators {
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
#include "ValidationError.h"
|
||||
|
||||
#include "gui/constants.h"
|
||||
#include "gui/styles.h"
|
||||
|
||||
namespace validators {
|
||||
|
||||
|
||||
@ -49,8 +49,6 @@ static const int s_family[] = {
|
||||
|
||||
static const int s_type[] = {SOCK_DGRAM, SOCK_STREAM};
|
||||
|
||||
ArchNetworkBSD::Deps ArchNetworkBSD::s_deps;
|
||||
|
||||
#if !HAVE_INET_ATON
|
||||
// parse dotted quad addresses. we don't bother with the weird BSD'ism
|
||||
// of handling octal and hex and partial forms.
|
||||
@ -274,13 +272,13 @@ int ArchNetworkBSD::pollSocket(PollEntry pe[], int num, double timeout) {
|
||||
// return if nothing to do
|
||||
if (num == 0) {
|
||||
if (timeout > 0.0) {
|
||||
m_deps.sleep(timeout);
|
||||
m_pDeps->sleep(timeout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocate space for translated query
|
||||
auto pfdPtr = m_deps.makePollFD(1 + num);
|
||||
auto pfdPtr = m_pDeps->makePollFD(1 + num);
|
||||
auto *pfd = pfdPtr.get();
|
||||
|
||||
// translate query
|
||||
@ -308,14 +306,14 @@ int ArchNetworkBSD::pollSocket(PollEntry pe[], int num, double timeout) {
|
||||
int t = (timeout < 0.0) ? -1 : static_cast<int>(1000.0 * timeout);
|
||||
|
||||
// do the poll
|
||||
n = m_deps.poll(pfd, n, t);
|
||||
n = m_pDeps->poll(pfd, n, t);
|
||||
|
||||
// reset the unblock pipe
|
||||
if (n > 0 && unblockPipe != nullptr && (pfd[num].revents & POLLIN) != 0) {
|
||||
// the unblock event was signalled. flush the pipe.
|
||||
char dummy[100];
|
||||
do {
|
||||
m_deps.read(unblockPipe[0], dummy, sizeof(dummy));
|
||||
m_pDeps->read(unblockPipe[0], dummy, sizeof(dummy));
|
||||
} while (errno != EAGAIN);
|
||||
|
||||
// don't count this unblock pipe in return value
|
||||
@ -326,7 +324,7 @@ int ArchNetworkBSD::pollSocket(PollEntry pe[], int num, double timeout) {
|
||||
if (n == -1) {
|
||||
if (errno == EINTR) {
|
||||
// interrupted system call
|
||||
m_deps.testCancelThread();
|
||||
m_pDeps->testCancelThread();
|
||||
return 0;
|
||||
}
|
||||
throwError(errno);
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "arch/IArchMultithread.h"
|
||||
#include "arch/IArchNetwork.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
@ -69,6 +70,7 @@ public:
|
||||
|
||||
//! Berkeley (BSD) sockets implementation of IArchNetwork
|
||||
class ArchNetworkBSD : public IArchNetwork {
|
||||
|
||||
public:
|
||||
struct Deps {
|
||||
virtual ~Deps() = default;
|
||||
@ -79,8 +81,8 @@ public:
|
||||
virtual void testCancelThread();
|
||||
};
|
||||
|
||||
explicit ArchNetworkBSD() : m_deps(s_deps) {}
|
||||
explicit ArchNetworkBSD(Deps &deps) : m_deps(deps) {}
|
||||
explicit ArchNetworkBSD(std::shared_ptr<Deps> deps = std::make_shared<Deps>())
|
||||
: m_pDeps(deps) {}
|
||||
ArchNetworkBSD(ArchNetworkBSD const &) = delete;
|
||||
ArchNetworkBSD(ArchNetworkBSD &&) = delete;
|
||||
~ArchNetworkBSD() override;
|
||||
@ -128,7 +130,6 @@ private:
|
||||
void throwNameError(int);
|
||||
|
||||
private:
|
||||
static Deps s_deps;
|
||||
Deps &m_deps;
|
||||
std::shared_ptr<Deps> m_pDeps;
|
||||
ArchMutex m_mutex{};
|
||||
};
|
||||
|
||||
@ -86,146 +86,156 @@ const char *const AppConfig::m_SettingsName[] = {
|
||||
"initiateConnectionFromServer", // kInvertConnection
|
||||
"", // 35 = clientHostMode, obsolete
|
||||
"", // 36 = serverClientMode, obsolete
|
||||
"serviceEnabled",
|
||||
"enableService",
|
||||
"closeToTray",
|
||||
"mainWindowSize",
|
||||
"mainWindowPosition",
|
||||
"showDevThanks",
|
||||
"showCloseReminder",
|
||||
};
|
||||
|
||||
static const char *logLevelNames[] = {"INFO", "DEBUG", "DEBUG1", "DEBUG2"};
|
||||
|
||||
AppConfig::Deps AppConfig::s_Deps;
|
||||
|
||||
AppConfig::AppConfig(Deps &deps) : m_Deps(deps), m_ScreenName(deps.hostname()) {
|
||||
|
||||
m_Deps.scopes().registerReceiver(this);
|
||||
AppConfig::AppConfig(
|
||||
synergy::gui::IConfigScopes &scopes, std::shared_ptr<Deps> deps)
|
||||
: m_scopes(scopes),
|
||||
m_pDeps(deps),
|
||||
m_ScreenName(deps->hostname()) {
|
||||
determineScope();
|
||||
recall();
|
||||
}
|
||||
|
||||
void AppConfig::loadAllScopes() {
|
||||
m_Deps.scopes().loadAll();
|
||||
|
||||
// User settings exist and the load from system scope variable is true
|
||||
if (m_Deps.scopes().hasSetting(
|
||||
settingName(Setting::kLoadSystemSettings),
|
||||
ConfigScopes::Scope::User)) {
|
||||
setLoadFromSystemScope(m_LoadFromSystemScope);
|
||||
}
|
||||
// If user setting don't exist but system ones do, load the system settings
|
||||
else if (m_Deps.scopes().hasSetting(
|
||||
settingName(Setting::kScreenName),
|
||||
ConfigScopes::Scope::System)) {
|
||||
setLoadFromSystemScope(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::loadSettings() {
|
||||
void AppConfig::recall() {
|
||||
using enum AppConfig::Setting;
|
||||
|
||||
qDebug("loading settings");
|
||||
qDebug("recalling app config");
|
||||
|
||||
loadCommonSettings();
|
||||
loadScopeSettings();
|
||||
loadSerialKey();
|
||||
loadElevateMode();
|
||||
|
||||
emit loaded();
|
||||
recallFromAllScopes();
|
||||
recallFromCurrentScope();
|
||||
}
|
||||
|
||||
void AppConfig::loadCommonSettings() {
|
||||
void AppConfig::recallFromAllScopes() {
|
||||
using enum Setting;
|
||||
|
||||
m_WizardLastRun = loadCommonSetting(kWizardLastRun, m_WizardLastRun).toInt();
|
||||
m_WizardLastRun = findInAllScopes(kWizardLastRun, m_WizardLastRun).toInt();
|
||||
m_LoadFromSystemScope =
|
||||
loadCommonSetting(kLoadSystemSettings, m_LoadFromSystemScope).toBool();
|
||||
findInAllScopes(kLoadSystemSettings, m_LoadFromSystemScope).toBool();
|
||||
m_licenseNextCheck =
|
||||
loadCommonSetting(kLicenseNextCheck, m_licenseNextCheck).toULongLong();
|
||||
findInAllScopes(kLicenseNextCheck, m_licenseNextCheck).toULongLong();
|
||||
}
|
||||
|
||||
void AppConfig::loadScopeSettings() {
|
||||
void AppConfig::recallFromCurrentScope() {
|
||||
using enum Setting;
|
||||
|
||||
loadScreenName();
|
||||
recallScreenName();
|
||||
recallSerialKey();
|
||||
recallElevateMode();
|
||||
|
||||
m_Port = loadSetting(kPort, m_Port).toInt();
|
||||
m_Interface = loadSetting(kInterface, m_Interface).toString();
|
||||
m_LogLevel = loadSetting(kLogLevel, m_LogLevel).toInt();
|
||||
m_LogToFile = loadSetting(kLogToFile, m_LogToFile).toBool();
|
||||
m_LogFilename = loadSetting(kLogFilename, m_LogFilename).toString();
|
||||
m_StartedBefore = loadSetting(kStartedBefore, m_StartedBefore).toBool();
|
||||
m_AutoHide = loadSetting(kAutoHide, m_AutoHide).toBool();
|
||||
m_LastVersion = loadSetting(kLastVersion, m_LastVersion).toString();
|
||||
m_Port = getFromCurrentScope(kPort, m_Port).toInt();
|
||||
m_Interface = getFromCurrentScope(kInterface, m_Interface).toString();
|
||||
m_LogLevel = getFromCurrentScope(kLogLevel, m_LogLevel).toInt();
|
||||
m_LogToFile = getFromCurrentScope(kLogToFile, m_LogToFile).toBool();
|
||||
m_LogFilename = getFromCurrentScope(kLogFilename, m_LogFilename).toString();
|
||||
m_StartedBefore =
|
||||
getFromCurrentScope(kStartedBefore, m_StartedBefore).toBool();
|
||||
m_AutoHide = getFromCurrentScope(kAutoHide, m_AutoHide).toBool();
|
||||
m_LastVersion = getFromCurrentScope(kLastVersion, m_LastVersion).toString();
|
||||
m_ActivationHasRun =
|
||||
loadSetting(kActivationHasRun, m_ActivationHasRun).toBool();
|
||||
getFromCurrentScope(kActivationHasRun, m_ActivationHasRun).toBool();
|
||||
m_ServerGroupChecked =
|
||||
loadSetting(kServerGroupChecked, m_ServerGroupChecked).toBool();
|
||||
getFromCurrentScope(kServerGroupChecked, m_ServerGroupChecked).toBool();
|
||||
m_UseExternalConfig =
|
||||
loadSetting(kUseExternalConfig, m_UseExternalConfig).toBool();
|
||||
m_ConfigFile = loadSetting(kConfigFile, m_ConfigFile).toString();
|
||||
getFromCurrentScope(kUseExternalConfig, m_UseExternalConfig).toBool();
|
||||
m_ConfigFile = getFromCurrentScope(kConfigFile, m_ConfigFile).toString();
|
||||
m_UseInternalConfig =
|
||||
loadSetting(kUseInternalConfig, m_UseInternalConfig).toBool();
|
||||
getFromCurrentScope(kUseInternalConfig, m_UseInternalConfig).toBool();
|
||||
m_ClientGroupChecked =
|
||||
loadSetting(kClientGroupChecked, m_ClientGroupChecked).toBool();
|
||||
m_ServerHostname = loadSetting(kServerHostname, m_ServerHostname).toString();
|
||||
m_PreventSleep = loadSetting(kPreventSleep, m_PreventSleep).toBool();
|
||||
m_LanguageSync = loadSetting(kLanguageSync, m_LanguageSync).toBool();
|
||||
getFromCurrentScope(kClientGroupChecked, m_ClientGroupChecked).toBool();
|
||||
m_ServerHostname =
|
||||
getFromCurrentScope(kServerHostname, m_ServerHostname).toString();
|
||||
m_PreventSleep = getFromCurrentScope(kPreventSleep, m_PreventSleep).toBool();
|
||||
m_LanguageSync = getFromCurrentScope(kLanguageSync, m_LanguageSync).toBool();
|
||||
m_InvertScrollDirection =
|
||||
loadSetting(kInvertScrollDirection, m_InvertScrollDirection).toBool();
|
||||
getFromCurrentScope(kInvertScrollDirection, m_InvertScrollDirection)
|
||||
.toBool();
|
||||
m_InvertConnection =
|
||||
loadSetting(kInvertConnection, m_InvertConnection).toBool();
|
||||
m_ServiceEnabled = loadSetting(kServiceEnabled, m_ServiceEnabled).toBool();
|
||||
m_CloseToTray = loadSetting(kCloseToTray, m_CloseToTray).toBool();
|
||||
m_TlsEnabled = loadSetting(kTlsEnabled, m_TlsEnabled).toBool();
|
||||
m_TlsCertPath = loadSetting(kTlsCertPath, m_TlsCertPath).toString();
|
||||
m_TlsKeyLength = loadSetting(kTlsKeyLength, m_TlsKeyLength).toString();
|
||||
m_MainWindowPosition = loadOptional<QPoint>(
|
||||
kMainWindowPosition, [](QVariant v) { return v.toPoint(); });
|
||||
m_MainWindowSize = loadOptional<QSize>(
|
||||
kMainWindowSize, [](QVariant v) { return v.toSize(); });
|
||||
getFromCurrentScope(kInvertConnection, m_InvertConnection).toBool();
|
||||
m_EnableService =
|
||||
getFromCurrentScope(kEnableService, m_EnableService).toBool();
|
||||
m_CloseToTray = getFromCurrentScope(kCloseToTray, m_CloseToTray).toBool();
|
||||
m_TlsEnabled = getFromCurrentScope(kTlsEnabled, m_TlsEnabled).toBool();
|
||||
m_TlsCertPath = getFromCurrentScope(kTlsCertPath, m_TlsCertPath).toString();
|
||||
m_TlsKeyLength =
|
||||
getFromCurrentScope(kTlsKeyLength, m_TlsKeyLength).toString();
|
||||
m_MainWindowPosition = getFromCurrentScope<QPoint>(
|
||||
kMainWindowPosition, [](const QVariant &v) { return v.toPoint(); });
|
||||
m_MainWindowSize = getFromCurrentScope<QSize>(
|
||||
kMainWindowSize, [](const QVariant &v) { return v.toSize(); });
|
||||
m_ShowDevThanks =
|
||||
getFromCurrentScope(kShowDevThanks, m_ShowDevThanks).toBool();
|
||||
m_ShowCloseReminder =
|
||||
getFromCurrentScope(kShowCloseReminder, m_ShowCloseReminder).toBool();
|
||||
}
|
||||
|
||||
void AppConfig::saveSettings() {
|
||||
void AppConfig::recallScreenName() {
|
||||
using enum Setting;
|
||||
|
||||
qDebug("saving settings");
|
||||
const auto &screenName =
|
||||
getFromCurrentScope(kScreenName, m_ScreenName).toString().trimmed();
|
||||
|
||||
setCommonSetting(kWizardLastRun, m_WizardLastRun);
|
||||
setCommonSetting(kLoadSystemSettings, m_LoadFromSystemScope);
|
||||
setCommonSetting(kClientGroupChecked, m_ClientGroupChecked);
|
||||
setCommonSetting(kServerGroupChecked, m_ServerGroupChecked);
|
||||
setCommonSetting(kLicenseNextCheck, m_licenseNextCheck);
|
||||
|
||||
if (isWritable()) {
|
||||
setSetting(kScreenName, m_ScreenName);
|
||||
setSetting(kPort, m_Port);
|
||||
setSetting(kInterface, m_Interface);
|
||||
setSetting(kLogLevel, m_LogLevel);
|
||||
setSetting(kLogToFile, m_LogToFile);
|
||||
setSetting(kLogFilename, m_LogFilename);
|
||||
setSetting(kStartedBefore, m_StartedBefore);
|
||||
setSetting(kElevateMode, static_cast<int>(m_ElevateMode));
|
||||
setSetting(kElevateModeLegacy, m_ElevateMode == ElevateAlways);
|
||||
setSetting(kTlsEnabled, m_TlsEnabled);
|
||||
setSetting(kAutoHide, m_AutoHide);
|
||||
setSetting(kSerialKey, m_SerialKey);
|
||||
setSetting(kLastVersion, m_LastVersion);
|
||||
setSetting(kActivationHasRun, m_ActivationHasRun);
|
||||
setSetting(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(kInvertConnection, m_InvertConnection);
|
||||
setSetting(kServiceEnabled, m_ServiceEnabled);
|
||||
setSetting(kCloseToTray, m_CloseToTray);
|
||||
setOptional(kMainWindowSize, m_MainWindowSize);
|
||||
setOptional(kMainWindowPosition, m_MainWindowPosition);
|
||||
// for some reason, the screen name can be saved as an empty string
|
||||
// in the config file. this is probably a bug. if this happens, then default
|
||||
// back to the hostname.
|
||||
if (screenName.isEmpty()) {
|
||||
qWarning("screen name was empty in config, setting to hostname");
|
||||
m_ScreenName = m_pDeps->hostname();
|
||||
} else {
|
||||
m_ScreenName = screenName;
|
||||
}
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
void AppConfig::commit() {
|
||||
using enum Setting;
|
||||
|
||||
emit saved();
|
||||
qDebug("comitting app config");
|
||||
|
||||
saveToAllScopes(kWizardLastRun, m_WizardLastRun);
|
||||
saveToAllScopes(kLoadSystemSettings, m_LoadFromSystemScope);
|
||||
saveToAllScopes(kClientGroupChecked, m_ClientGroupChecked);
|
||||
saveToAllScopes(kServerGroupChecked, m_ServerGroupChecked);
|
||||
saveToAllScopes(kLicenseNextCheck, m_licenseNextCheck);
|
||||
|
||||
if (isActiveScopeWritable()) {
|
||||
setInCurrentScope(kScreenName, m_ScreenName);
|
||||
setInCurrentScope(kPort, m_Port);
|
||||
setInCurrentScope(kInterface, m_Interface);
|
||||
setInCurrentScope(kLogLevel, m_LogLevel);
|
||||
setInCurrentScope(kLogToFile, m_LogToFile);
|
||||
setInCurrentScope(kLogFilename, m_LogFilename);
|
||||
setInCurrentScope(kStartedBefore, m_StartedBefore);
|
||||
setInCurrentScope(kElevateMode, static_cast<int>(m_ElevateMode));
|
||||
setInCurrentScope(kElevateModeLegacy, m_ElevateMode == ElevateAlways);
|
||||
setInCurrentScope(kTlsEnabled, m_TlsEnabled);
|
||||
setInCurrentScope(kAutoHide, m_AutoHide);
|
||||
setInCurrentScope(kSerialKey, m_SerialKey);
|
||||
setInCurrentScope(kLastVersion, m_LastVersion);
|
||||
setInCurrentScope(kActivationHasRun, m_ActivationHasRun);
|
||||
setInCurrentScope(kUseExternalConfig, m_UseExternalConfig);
|
||||
setInCurrentScope(kConfigFile, m_ConfigFile);
|
||||
setInCurrentScope(kUseInternalConfig, m_UseInternalConfig);
|
||||
setInCurrentScope(kServerHostname, m_ServerHostname);
|
||||
setInCurrentScope(kPreventSleep, m_PreventSleep);
|
||||
setInCurrentScope(kLanguageSync, m_LanguageSync);
|
||||
setInCurrentScope(kInvertScrollDirection, m_InvertScrollDirection);
|
||||
setInCurrentScope(kInvertConnection, m_InvertConnection);
|
||||
setInCurrentScope(kEnableService, m_EnableService);
|
||||
setInCurrentScope(kCloseToTray, m_CloseToTray);
|
||||
setInCurrentScope(kShowDevThanks, m_ShowDevThanks);
|
||||
setInCurrentScope(kShowCloseReminder, m_ShowCloseReminder);
|
||||
|
||||
setInCurrentScope(kMainWindowSize, m_MainWindowSize);
|
||||
setInCurrentScope(kMainWindowPosition, m_MainWindowPosition);
|
||||
}
|
||||
|
||||
if (m_TlsChanged) {
|
||||
m_TlsChanged = false;
|
||||
@ -233,37 +243,45 @@ void AppConfig::saveSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::loadScreenName() {
|
||||
using enum Setting;
|
||||
void AppConfig::determineScope() {
|
||||
|
||||
const auto &screenName =
|
||||
loadSetting(kScreenName, m_ScreenName).toString().trimmed();
|
||||
qDebug("determining config scope");
|
||||
|
||||
// for some reason, the screen name can be saved as an empty string
|
||||
// in the config file. this is probably a bug. if this happens, then default
|
||||
// back to the hostname.
|
||||
if (screenName.isEmpty()) {
|
||||
qWarning("screen name was empty in config, setting to hostname");
|
||||
m_ScreenName = m_Deps.hostname();
|
||||
} else {
|
||||
m_ScreenName = screenName;
|
||||
// first, try to determine if the system scope should be used according to the
|
||||
// user scope...
|
||||
if (m_scopes.scopeContains(
|
||||
settingName(Setting::kLoadSystemSettings),
|
||||
ConfigScopes::Scope::User)) {
|
||||
auto loadFromSystemScope =
|
||||
m_scopes
|
||||
.getFromScope(
|
||||
settingName(Setting::kLoadSystemSettings),
|
||||
m_LoadFromSystemScope, ConfigScopes::Scope::User)
|
||||
.toBool();
|
||||
|
||||
setLoadFromSystemScope(loadFromSystemScope);
|
||||
}
|
||||
|
||||
// ...failing that, check the system scope instead to see if an arbitrary
|
||||
// required setting is present. if it is, then we can assume that the system
|
||||
// scope should be used.
|
||||
else if (m_scopes.scopeContains(
|
||||
settingName(Setting::kScreenName),
|
||||
ConfigScopes::Scope::System)) {
|
||||
setLoadFromSystemScope(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::loadSerialKey() {
|
||||
void AppConfig::recallSerialKey() {
|
||||
using enum Setting;
|
||||
|
||||
// only set the serial key if the current settings scope has they key.
|
||||
bool shouldLoad = m_Deps.scopes().hasSetting(
|
||||
settingName(kLoadSystemSettings), ConfigScopes::Scope::Current);
|
||||
|
||||
if (!shouldLoad) {
|
||||
if (!m_scopes.scopeContains(settingName(kLoadSystemSettings))) {
|
||||
qDebug("no serial key in current scope, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &serialKey =
|
||||
loadSetting(kSerialKey, m_SerialKey).toString().trimmed();
|
||||
getFromCurrentScope(kSerialKey, m_SerialKey).toString().trimmed();
|
||||
|
||||
if (serialKey.isEmpty()) {
|
||||
qDebug("serial key is empty, skipping");
|
||||
@ -273,18 +291,18 @@ void AppConfig::loadSerialKey() {
|
||||
m_SerialKey = serialKey;
|
||||
}
|
||||
|
||||
void AppConfig::loadElevateMode() {
|
||||
void AppConfig::recallElevateMode() {
|
||||
using enum Setting;
|
||||
|
||||
if (!m_Deps.scopes().hasSetting(settingName(kElevateMode))) {
|
||||
if (!m_scopes.scopeContains(settingName(kElevateMode))) {
|
||||
qDebug("elevate mode not set yet, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant elevateMode = loadSetting(kElevateMode);
|
||||
QVariant elevateMode = getFromCurrentScope(kElevateMode);
|
||||
if (!elevateMode.isValid()) {
|
||||
qDebug("elevate mode not valid, loading legacy setting");
|
||||
elevateMode = loadSetting(
|
||||
elevateMode = getFromCurrentScope(
|
||||
kElevateModeLegacy, QVariant(static_cast<int>(kDefaultElevateMode)));
|
||||
}
|
||||
|
||||
@ -292,7 +310,7 @@ void AppConfig::loadElevateMode() {
|
||||
}
|
||||
|
||||
QString AppConfig::defaultTlsCertPath() const {
|
||||
QDir path(m_Deps.profileDir());
|
||||
QDir path(m_pDeps->profileDir());
|
||||
path = path.filePath("SSL");
|
||||
path = path.filePath("Synergy.pem");
|
||||
return path.absolutePath();
|
||||
@ -303,103 +321,113 @@ QString AppConfig::settingName(Setting name) {
|
||||
return m_SettingsName[index];
|
||||
}
|
||||
|
||||
template <typename T> void AppConfig::setSetting(Setting name, T value) {
|
||||
m_Deps.scopes().setSetting(settingName(name), value);
|
||||
template <typename T> void AppConfig::setInCurrentScope(Setting name, T value) {
|
||||
m_scopes.setInScope(settingName(name), value);
|
||||
}
|
||||
|
||||
template <typename T> void AppConfig::setCommonSetting(Setting name, T value) {
|
||||
m_Deps.scopes().setSetting(
|
||||
settingName(name), value, ConfigScopes::Scope::User);
|
||||
m_Deps.scopes().setSetting(
|
||||
settingName(name), value, ConfigScopes::Scope::System);
|
||||
template <typename T> void AppConfig::saveToAllScopes(Setting name, T value) {
|
||||
m_scopes.setInScope(settingName(name), value, ConfigScopes::Scope::User);
|
||||
m_scopes.setInScope(settingName(name), value, ConfigScopes::Scope::System);
|
||||
}
|
||||
|
||||
QVariant AppConfig::loadSetting(Setting name, const QVariant &defaultValue) {
|
||||
return m_Deps.scopes().loadSetting(settingName(name), defaultValue);
|
||||
QVariant AppConfig::getFromCurrentScope(
|
||||
Setting name, const QVariant &defaultValue) const {
|
||||
return m_scopes.getFromScope(settingName(name), defaultValue);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::optional<T>
|
||||
AppConfig::loadOptional(Setting name, std::function<T(QVariant)> toType) const {
|
||||
if (m_Deps.scopes().hasSetting(settingName(name))) {
|
||||
return toType(m_Deps.scopes().loadSetting(settingName(name)));
|
||||
std::optional<T> AppConfig::getFromCurrentScope(
|
||||
Setting name, std::function<T(const QVariant &)> toType) const {
|
||||
if (m_scopes.scopeContains(settingName(name))) {
|
||||
return toType(m_scopes.getFromScope(settingName(name)));
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AppConfig::setOptional(Setting name, const std::optional<T> &value) {
|
||||
void AppConfig::setInCurrentScope(Setting name, const std::optional<T> &value) {
|
||||
if (value.has_value()) {
|
||||
m_Deps.scopes().setSetting(settingName(name), value.value());
|
||||
m_scopes.setInScope(settingName(name), value.value());
|
||||
}
|
||||
}
|
||||
|
||||
QVariant
|
||||
AppConfig::loadCommonSetting(Setting name, const QVariant &defaultValue) const {
|
||||
AppConfig::findInAllScopes(Setting name, const QVariant &defaultValue) const {
|
||||
using enum ConfigScopes::Scope;
|
||||
|
||||
QVariant result(defaultValue);
|
||||
QString setting(settingName(name));
|
||||
|
||||
if (m_Deps.scopes().hasSetting(setting)) {
|
||||
result = m_Deps.scopes().loadSetting(setting, defaultValue);
|
||||
} else if (m_Deps.scopes().getScope() == ConfigScopes::Scope::System) {
|
||||
if (m_Deps.scopes().hasSetting(setting, ConfigScopes::Scope::User)) {
|
||||
result = m_Deps.scopes().loadSetting(
|
||||
setting, defaultValue, ConfigScopes::Scope::User);
|
||||
if (m_scopes.scopeContains(setting)) {
|
||||
result = m_scopes.getFromScope(setting, defaultValue);
|
||||
} else if (m_scopes.activeScope() == System) {
|
||||
if (m_scopes.scopeContains(setting, User)) {
|
||||
result = m_scopes.getFromScope(setting, defaultValue, User);
|
||||
}
|
||||
} else if (m_Deps.scopes().hasSetting(setting, ConfigScopes::Scope::System)) {
|
||||
result = m_Deps.scopes().loadSetting(
|
||||
setting, defaultValue, ConfigScopes::Scope::System);
|
||||
} else if (m_scopes.scopeContains(setting, System)) {
|
||||
result = m_scopes.getFromScope(setting, defaultValue, System);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void AppConfig::loadScope(ConfigScopes::Scope scope) {
|
||||
using enum ConfigScopes::Scope;
|
||||
|
||||
if (m_Deps.scopes().getScope() != scope) {
|
||||
setDefaultValues();
|
||||
m_Deps.scopes().setScope(scope);
|
||||
if (m_Deps.scopes().hasSetting(
|
||||
settingName(Setting::kScreenName), m_Deps.scopes().getScope())) {
|
||||
// If the user already has settings, then load them up now.
|
||||
m_Deps.scopes().loadAll();
|
||||
}
|
||||
switch (scope) {
|
||||
case User:
|
||||
qDebug("loading user settings scope");
|
||||
break;
|
||||
|
||||
case System:
|
||||
qDebug("loading system settings scope");
|
||||
break;
|
||||
|
||||
default:
|
||||
qFatal("invalid scope");
|
||||
}
|
||||
|
||||
if (m_scopes.activeScope() == scope) {
|
||||
qDebug("already in required scope, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
m_scopes.setActiveScope(scope);
|
||||
|
||||
// only signal ready if there is at least one setting in the required scope.
|
||||
// this prevents the current settings from being set back to default.
|
||||
if (m_scopes.scopeContains(
|
||||
settingName(Setting::kScreenName), m_scopes.activeScope())) {
|
||||
m_scopes.signalReady();
|
||||
} else {
|
||||
qDebug("no screen name in scope, skipping");
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::setDefaultValues() { m_InvertConnection = false; }
|
||||
|
||||
void AppConfig::setLoadFromSystemScope(bool value) {
|
||||
using enum ConfigScopes::Scope;
|
||||
|
||||
if (value) {
|
||||
qDebug("loading system settings scope");
|
||||
loadScope(ConfigScopes::Scope::System);
|
||||
loadScope(System);
|
||||
} else {
|
||||
qDebug("loading user settings scope");
|
||||
loadScope(ConfigScopes::Scope::User);
|
||||
loadScope(User);
|
||||
}
|
||||
|
||||
/*
|
||||
* It's very imprortant to set this variable after loadScope
|
||||
* because during scope loading this variable can be rewritten with old value
|
||||
*/
|
||||
// set after loading scope since it may have been overridden.
|
||||
m_LoadFromSystemScope = value;
|
||||
}
|
||||
|
||||
bool AppConfig::isWritable() const { return m_Deps.scopes().isWritable(); }
|
||||
|
||||
bool AppConfig::isSystemScoped() const {
|
||||
return m_Deps.scopes().getScope() == ConfigScopes::Scope::System;
|
||||
bool AppConfig::isActiveScopeWritable() const {
|
||||
return m_scopes.isActiveScopeWritable();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AppConfig::setSettingModified(T &variable, const T &newValue) {
|
||||
if (variable != newValue) {
|
||||
variable = newValue;
|
||||
setModified(true);
|
||||
}
|
||||
bool AppConfig::isActiveScopeSystem() const {
|
||||
return m_scopes.activeScope() == ConfigScopes::Scope::System;
|
||||
}
|
||||
|
||||
QString AppConfig::logDir() const {
|
||||
// by default log to home dir
|
||||
return QDir::home().absolutePath() + "/";
|
||||
@ -418,7 +446,7 @@ void AppConfig::persistLogDir() const {
|
||||
// Begin getters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IConfigScopes &AppConfig::scopes() { return m_Deps.scopes(); }
|
||||
IConfigScopes &AppConfig::scopes() { return m_scopes; }
|
||||
|
||||
bool AppConfig::activationHasRun() const { return m_ActivationHasRun; }
|
||||
|
||||
@ -439,7 +467,7 @@ const QString &AppConfig::logFilename() const { return m_LogFilename; }
|
||||
QString AppConfig::logLevelText() const { return logLevelNames[logLevel()]; }
|
||||
|
||||
ProcessMode AppConfig::processMode() const {
|
||||
return m_ServiceEnabled ? ProcessMode::kService : ProcessMode::kDesktop;
|
||||
return m_EnableService ? ProcessMode::kService : ProcessMode::kDesktop;
|
||||
}
|
||||
|
||||
bool AppConfig::wizardShouldRun() const {
|
||||
@ -478,7 +506,7 @@ QString AppConfig::tlsCertPath() const { return m_TlsCertPath; }
|
||||
|
||||
QString AppConfig::tlsKeyLength() const { return m_TlsKeyLength; }
|
||||
|
||||
bool AppConfig::serviceEnabled() const { return m_ServiceEnabled; }
|
||||
bool AppConfig::enableService() const { return m_EnableService; }
|
||||
|
||||
bool AppConfig::closeToTray() const { return m_CloseToTray; }
|
||||
|
||||
@ -504,6 +532,10 @@ std::optional<QPoint> AppConfig::mainWindowPosition() const {
|
||||
return m_MainWindowPosition;
|
||||
}
|
||||
|
||||
bool AppConfig::showDevThanks() const { return m_ShowDevThanks; }
|
||||
|
||||
bool AppConfig::showCloseReminder() const { return m_ShowCloseReminder; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// End getters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -515,109 +547,94 @@ std::optional<QPoint> AppConfig::mainWindowPosition() const {
|
||||
void AppConfig::clearSerialKey() { m_SerialKey.clear(); }
|
||||
|
||||
void AppConfig::setTlsEnabled(bool value) {
|
||||
setSettingModified(m_TlsEnabled, value);
|
||||
m_TlsChanged = true;
|
||||
// we purposefully do not set the 'tls changed' flag when enabling/disabling
|
||||
// tls, since that would cause the certificate to regenerate, which could get
|
||||
// pretty annoying.
|
||||
|
||||
m_TlsEnabled = value;
|
||||
}
|
||||
|
||||
void AppConfig::setTlsCertPath(const QString &value) {
|
||||
setSettingModified(m_TlsCertPath, value);
|
||||
m_TlsChanged = true;
|
||||
m_TlsChanged = m_TlsCertPath != value;
|
||||
m_TlsCertPath = value;
|
||||
}
|
||||
|
||||
void AppConfig::setTlsKeyLength(const QString &value) {
|
||||
setSettingModified(m_TlsKeyLength, value);
|
||||
m_TlsChanged = true;
|
||||
m_TlsChanged = m_TlsKeyLength != value;
|
||||
m_TlsKeyLength = value;
|
||||
}
|
||||
void AppConfig::setSerialKey(const QString &serialKey) {
|
||||
setSettingModified(m_SerialKey, serialKey);
|
||||
setCommonSetting(Setting::kSerialKey, m_SerialKey);
|
||||
m_SerialKey = serialKey;
|
||||
saveToAllScopes(Setting::kSerialKey, m_SerialKey);
|
||||
}
|
||||
void AppConfig::setServerGroupChecked(bool newValue) {
|
||||
setSettingModified(m_ServerGroupChecked, newValue);
|
||||
m_ServerGroupChecked = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setUseExternalConfig(bool newValue) {
|
||||
setSettingModified(m_UseExternalConfig, newValue);
|
||||
m_UseExternalConfig = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setConfigFile(const QString &newValue) {
|
||||
setSettingModified(m_ConfigFile, newValue);
|
||||
m_ConfigFile = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setUseInternalConfig(bool newValue) {
|
||||
setSettingModified(m_UseInternalConfig, newValue);
|
||||
m_UseInternalConfig = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setClientGroupChecked(bool newValue) {
|
||||
setSettingModified(m_ClientGroupChecked, newValue);
|
||||
m_ClientGroupChecked = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setServerHostname(const QString &newValue) {
|
||||
setSettingModified(m_ServerHostname, newValue);
|
||||
m_ServerHostname = newValue;
|
||||
}
|
||||
void AppConfig::setLastVersion(const QString &version) {
|
||||
setSettingModified(m_LastVersion, version);
|
||||
m_LastVersion = version;
|
||||
}
|
||||
|
||||
void AppConfig::setScreenName(const QString &s) {
|
||||
setSettingModified(m_ScreenName, s);
|
||||
m_ScreenName = s;
|
||||
emit screenNameChanged();
|
||||
}
|
||||
|
||||
void AppConfig::setPort(int i) { setSettingModified(m_Port, i); }
|
||||
void AppConfig::setPort(int i) { m_Port = i; }
|
||||
|
||||
void AppConfig::setNetworkInterface(const QString &s) {
|
||||
setSettingModified(m_Interface, s);
|
||||
}
|
||||
void AppConfig::setNetworkInterface(const QString &s) { m_Interface = s; }
|
||||
|
||||
void AppConfig::setLogLevel(int i) { setSettingModified(m_LogLevel, i); }
|
||||
void AppConfig::setLogLevel(int i) { m_LogLevel = i; }
|
||||
|
||||
void AppConfig::setLogToFile(bool b) { setSettingModified(m_LogToFile, b); }
|
||||
void AppConfig::setLogToFile(bool b) { m_LogToFile = b; }
|
||||
|
||||
void AppConfig::setLogFilename(const QString &s) {
|
||||
setSettingModified(m_LogFilename, s);
|
||||
}
|
||||
void AppConfig::setLogFilename(const QString &s) { m_LogFilename = s; }
|
||||
|
||||
void AppConfig::setWizardHasRun() {
|
||||
setSettingModified(m_WizardLastRun, kWizardVersion);
|
||||
}
|
||||
void AppConfig::setWizardHasRun() { m_WizardLastRun = kWizardVersion; }
|
||||
|
||||
void AppConfig::setStartedBefore(bool b) {
|
||||
setSettingModified(m_StartedBefore, b);
|
||||
}
|
||||
void AppConfig::setStartedBefore(bool b) { m_StartedBefore = b; }
|
||||
|
||||
void AppConfig::setElevateMode(ElevateMode em) {
|
||||
setSettingModified(m_ElevateMode, em);
|
||||
}
|
||||
void AppConfig::setElevateMode(ElevateMode em) { m_ElevateMode = em; }
|
||||
|
||||
void AppConfig::setAutoHide(bool b) { setSettingModified(m_AutoHide, b); }
|
||||
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }
|
||||
|
||||
void AppConfig::setLicenseNextCheck(unsigned long long time) {
|
||||
setSettingModified(m_licenseNextCheck, time);
|
||||
m_licenseNextCheck = time;
|
||||
}
|
||||
|
||||
void AppConfig::setInvertScrollDirection(bool newValue) {
|
||||
setSettingModified(m_InvertScrollDirection, newValue);
|
||||
m_InvertScrollDirection = newValue;
|
||||
}
|
||||
|
||||
void AppConfig::setLanguageSync(bool newValue) {
|
||||
setSettingModified(m_LanguageSync, newValue);
|
||||
}
|
||||
void AppConfig::setLanguageSync(bool newValue) { m_LanguageSync = newValue; }
|
||||
|
||||
void AppConfig::setPreventSleep(bool newValue) {
|
||||
setSettingModified(m_PreventSleep, newValue);
|
||||
}
|
||||
void AppConfig::setPreventSleep(bool newValue) { m_PreventSleep = newValue; }
|
||||
|
||||
void AppConfig::setServiceEnabled(bool enabled) {
|
||||
setSettingModified(m_ServiceEnabled, enabled);
|
||||
}
|
||||
void AppConfig::setEnableService(bool enabled) { m_EnableService = enabled; }
|
||||
|
||||
void AppConfig::setCloseToTray(bool minimize) {
|
||||
setSettingModified(m_CloseToTray, minimize);
|
||||
}
|
||||
void AppConfig::setCloseToTray(bool minimize) { m_CloseToTray = minimize; }
|
||||
|
||||
void AppConfig::setInvertConnection(bool value) {
|
||||
setSettingModified(m_InvertConnection, value);
|
||||
m_InvertConnection = value;
|
||||
emit invertConnectionChanged();
|
||||
}
|
||||
|
||||
@ -629,6 +646,12 @@ void AppConfig::setMainWindowPosition(const QPoint &position) {
|
||||
m_MainWindowPosition = position;
|
||||
}
|
||||
|
||||
void AppConfig::setShowDevThanks(bool value) { m_ShowDevThanks = value; }
|
||||
|
||||
void AppConfig::setShowCloseReminder(bool value) {
|
||||
m_ShowCloseReminder = value;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// End setters
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommonConfig.h"
|
||||
#include "ConfigScopes.h"
|
||||
#include "CoreInterface.h"
|
||||
#include "ElevateMode.h"
|
||||
@ -31,7 +30,7 @@
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
enum class ProcessMode { kService, kDesktop };
|
||||
|
||||
@ -42,7 +41,13 @@ const QString kDefaultLogFile = "synergy.log";
|
||||
const ProcessMode kDefaultProcessMode = ProcessMode::kService;
|
||||
#else
|
||||
const ProcessMode kDefaultProcessMode = ProcessMode::kDesktop;
|
||||
#endif
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#ifdef SYNERGY_SHOW_DEV_THANKS
|
||||
const bool kDefaultShowDevThanks = true;
|
||||
#else
|
||||
const bool kDefaultShowDevThanks = false;
|
||||
#endif // SYNERGY_SHOW_DEV_THANKS
|
||||
|
||||
/**
|
||||
* @brief Simply reads and writes app settings.
|
||||
@ -52,9 +57,7 @@ const ProcessMode kDefaultProcessMode = ProcessMode::kDesktop;
|
||||
* instance is widely accessible, but that has previously led to this class
|
||||
* becoming a god object.
|
||||
*/
|
||||
class AppConfig : public QObject,
|
||||
public synergy::gui::CommonConfig,
|
||||
public synergy::gui::IAppConfig {
|
||||
class AppConfig : public QObject, public synergy::gui::IAppConfig {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
@ -96,10 +99,12 @@ private:
|
||||
kInvertConnection = 34,
|
||||
// 35 = client-host-mode, obsolete
|
||||
// 36 = server-client-mode, obsolete
|
||||
kServiceEnabled = 37,
|
||||
kEnableService = 37,
|
||||
kCloseToTray = 38,
|
||||
kMainWindowSize = 39,
|
||||
kMainWindowPosition = 40,
|
||||
kShowDevThanks = 41,
|
||||
kShowCloseReminder = 42,
|
||||
};
|
||||
|
||||
public:
|
||||
@ -108,29 +113,33 @@ public:
|
||||
virtual QString profileDir() const {
|
||||
return m_coreInterface.getProfileDir();
|
||||
}
|
||||
virtual synergy::gui::IConfigScopes &scopes() { return m_Scopes; }
|
||||
virtual QString hostname() const { return QHostInfo::localHostName(); }
|
||||
|
||||
private:
|
||||
[[no_unique_address]] CoreInterface m_coreInterface;
|
||||
synergy::gui::ConfigScopes m_Scopes;
|
||||
};
|
||||
|
||||
explicit AppConfig() : AppConfig(s_Deps) {}
|
||||
explicit AppConfig(Deps &deps);
|
||||
explicit AppConfig(
|
||||
synergy::gui::IConfigScopes &scopes,
|
||||
std::shared_ptr<Deps> deps = std::make_shared<Deps>());
|
||||
|
||||
synergy::gui::IConfigScopes &scopes();
|
||||
void saveSettings() override;
|
||||
void loadAllScopes();
|
||||
void loadSettings() override;
|
||||
|
||||
/**
|
||||
* @brief Commits the current settings to the active scope.
|
||||
* This should only be called when the settings are about to be saved.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
void determineScope();
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
|
||||
void setActivationHasRun(bool value);
|
||||
bool isWritable() const;
|
||||
bool isSystemScoped() const;
|
||||
bool isActiveScopeWritable() const;
|
||||
bool isActiveScopeSystem() const;
|
||||
const QString &screenName() const;
|
||||
int port() const;
|
||||
const QString &networkInterface() const;
|
||||
@ -159,7 +168,7 @@ public:
|
||||
bool clientGroupChecked() const;
|
||||
QString serverHostname() const;
|
||||
QString lastVersion() const;
|
||||
bool serviceEnabled() const;
|
||||
bool enableService() const;
|
||||
bool closeToTray() const;
|
||||
QString serialKey() const;
|
||||
bool activationHasRun() const;
|
||||
@ -168,6 +177,8 @@ public:
|
||||
QString tlsKeyLength() const override;
|
||||
std::optional<QSize> mainWindowSize() const;
|
||||
std::optional<QPoint> mainWindowPosition() const;
|
||||
bool showDevThanks() const;
|
||||
bool showCloseReminder() const;
|
||||
|
||||
/**
|
||||
* Setters
|
||||
@ -197,13 +208,15 @@ public:
|
||||
void setClientGroupChecked(bool);
|
||||
void setServerHostname(const QString &);
|
||||
void setLastVersion(const QString &version);
|
||||
void setServiceEnabled(bool enabled);
|
||||
void setEnableService(bool enabled);
|
||||
void setCloseToTray(bool minimize);
|
||||
void setTlsCertPath(const QString &path);
|
||||
void setTlsKeyLength(const QString &length);
|
||||
void setInvertConnection(bool value);
|
||||
void setMainWindowSize(const QSize &size);
|
||||
void setMainWindowPosition(const QPoint &position);
|
||||
void setShowDevThanks(bool show);
|
||||
void setShowCloseReminder(bool show);
|
||||
|
||||
/// @brief Sets the user preference to load from SystemScope.
|
||||
/// @param [in] value
|
||||
@ -214,11 +227,13 @@ public:
|
||||
|
||||
private:
|
||||
static QString settingName(AppConfig::Setting name);
|
||||
void loadScreenName();
|
||||
void loadSerialKey();
|
||||
void loadElevateMode();
|
||||
void loadCommonSettings();
|
||||
void loadScopeSettings();
|
||||
|
||||
void recall();
|
||||
void recallScreenName();
|
||||
void recallSerialKey();
|
||||
void recallElevateMode();
|
||||
void recallFromAllScopes();
|
||||
void recallFromCurrentScope();
|
||||
|
||||
/**
|
||||
* @brief Loads a setting if it exists, otherwise returns `std::nullopt`
|
||||
@ -226,60 +241,48 @@ private:
|
||||
* @param toType A function to convert the QVariant to the desired type.
|
||||
*/
|
||||
template <typename T>
|
||||
std::optional<T>
|
||||
loadOptional(Setting name, std::function<T(QVariant)> toType) const;
|
||||
std::optional<T> getFromCurrentScope(
|
||||
Setting name, std::function<T(const QVariant &)> toType) const;
|
||||
|
||||
/**
|
||||
* @brief Sets a setting if the value is not `std::nullopt`.
|
||||
*/
|
||||
template <typename T>
|
||||
void setOptional(Setting name, const std::optional<T> &value);
|
||||
void setInCurrentScope(Setting name, const std::optional<T> &value);
|
||||
|
||||
/// @brief Sets the value of a setting
|
||||
/// @param [in] name The Setting to be saved
|
||||
/// @param [in] value The Value to be saved
|
||||
template <typename T> void setSetting(AppConfig::Setting name, T value);
|
||||
template <typename T>
|
||||
void setInCurrentScope(AppConfig::Setting name, T value);
|
||||
|
||||
/// @brief Sets the value of a common setting
|
||||
/// which should have the same value for all scopes
|
||||
/// @param [in] name The Setting to be saved
|
||||
/// @param [in] value The Value to be saved
|
||||
template <typename T> void setCommonSetting(AppConfig::Setting name, T value);
|
||||
template <typename T> void saveToAllScopes(AppConfig::Setting name, T value);
|
||||
|
||||
/// @brief Loads a setting
|
||||
/// @param [in] name The setting to be loaded
|
||||
/// @param [in] defaultValue The default value of the setting
|
||||
QVariant loadSetting(
|
||||
AppConfig::Setting name, const QVariant &defaultValue = QVariant());
|
||||
|
||||
/// @brief Loads a common setting
|
||||
/// @param [in] name The setting to be loaded
|
||||
/// @param [in] defaultValue The default value of the setting
|
||||
QVariant loadCommonSetting(
|
||||
QVariant getFromCurrentScope(
|
||||
AppConfig::Setting name, const QVariant &defaultValue = QVariant()) const;
|
||||
|
||||
/// @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
|
||||
/// @param [in] variable the setting that will be changed
|
||||
/// @param [in] newValue The new value of the setting
|
||||
template <typename T> void setSettingModified(T &variable, const T &newValue);
|
||||
/**
|
||||
* @brief Finds a value by searching each scope starting with the current
|
||||
* scope.
|
||||
*/
|
||||
QVariant findInAllScopes(
|
||||
AppConfig::Setting name, const QVariant &defaultValue = QVariant()) const;
|
||||
|
||||
/// @brief This method loads config from specified scope
|
||||
/// @param [in] scope which should be loaded.
|
||||
void loadScope(synergy::gui::ConfigScopes::Scope scope);
|
||||
|
||||
/// @brief This function sets default values
|
||||
/// for settings that shouldn't be copied from between scopes.
|
||||
void setDefaultValues();
|
||||
|
||||
/**
|
||||
* @brief Gets a TLS certificate path based on the user's profile dir.
|
||||
*/
|
||||
QString defaultTlsCertPath() const;
|
||||
|
||||
static Deps s_Deps;
|
||||
Deps &m_Deps;
|
||||
synergy::gui::IConfigScopes &m_scopes;
|
||||
std::shared_ptr<Deps> m_pDeps;
|
||||
QString m_ScreenName;
|
||||
int m_Port = 24800;
|
||||
QString m_Interface = "";
|
||||
@ -306,12 +309,15 @@ private:
|
||||
bool m_UseInternalConfig = false;
|
||||
bool m_ClientGroupChecked = false;
|
||||
QString m_ServerHostname = "";
|
||||
bool m_ServiceEnabled = kDefaultProcessMode == ProcessMode::kService;
|
||||
bool m_CloseToTray = false;
|
||||
bool m_EnableService = kDefaultProcessMode == ProcessMode::kService;
|
||||
bool m_CloseToTray = true;
|
||||
QString m_TlsCertPath = defaultTlsCertPath();
|
||||
QString m_TlsKeyLength = "2048";
|
||||
std::optional<QSize> m_MainWindowSize;
|
||||
std::optional<QPoint> m_MainWindowPosition;
|
||||
bool m_ShowDevThanks = kDefaultShowDevThanks;
|
||||
bool m_LoadFromSystemScope = false;
|
||||
bool m_ShowCloseReminder = true;
|
||||
|
||||
/**
|
||||
* @brief Flag is set when any TLS is setting is changed, and is reset
|
||||
@ -319,19 +325,6 @@ private:
|
||||
*/
|
||||
bool m_TlsChanged = false;
|
||||
|
||||
/// @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[];
|
||||
@ -339,12 +332,10 @@ private:
|
||||
/// @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
|
||||
/// @brief Core config filename (not the Qt settings filename)
|
||||
static const char m_ConfigFilename[];
|
||||
|
||||
signals:
|
||||
void loaded();
|
||||
void saved();
|
||||
void tlsChanged();
|
||||
void screenNameChanged();
|
||||
void invertConnectionChanged();
|
||||
|
||||
@ -17,58 +17,81 @@
|
||||
|
||||
#include "ConfigScopes.h"
|
||||
|
||||
#include "CommonConfig.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
const auto kSystemConfigFilename = "SystemConfig.ini";
|
||||
const auto kUnixSystemConfigPath = "/usr/local/etc/symless/";
|
||||
|
||||
namespace synergy::gui {
|
||||
|
||||
QString getSystemSettingPath() {
|
||||
const QString settingFilename("SystemConfig.ini");
|
||||
QString path;
|
||||
const QString settingFilename(kSystemConfigFilename);
|
||||
#if defined(Q_OS_WIN)
|
||||
path = QCoreApplication::applicationDirPath() + "\\";
|
||||
return QCoreApplication::applicationDirPath() + "\\";
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
// Global preferances dir
|
||||
// Would be nice to use /library, but QT has no elevate system in place
|
||||
path = "/usr/local/etc/symless/";
|
||||
// it would be nice to use /Library dir, but qt has no elevate system.
|
||||
return kUnixSystemConfigPath + settingFilename;
|
||||
#elif defined(Q_OS_LINUX)
|
||||
// QT adds application and filename to the end of the path already on linux
|
||||
path = "/usr/local/etc/symless/";
|
||||
return path;
|
||||
// qt already adds application and filename to the end of the path on linux.
|
||||
return kUnixSystemConfigPath;
|
||||
#else
|
||||
assert("OS not supported");
|
||||
qFatal("unsupported platform");
|
||||
return "";
|
||||
#endif
|
||||
return path + settingFilename;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
void loadWindowsLegacy(QSettings &settings) {
|
||||
if (!QFile(settings.fileName()).exists()) {
|
||||
QSettings::setPath(
|
||||
QSettings::IniFormat, QSettings::SystemScope, "SystemConfig.ini");
|
||||
QSettings oldSystemSettings(
|
||||
QSettings::IniFormat, QSettings::SystemScope,
|
||||
QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName());
|
||||
|
||||
if (QFile(oldSystemSettings.fileName()).exists()) {
|
||||
for (const auto &key : oldSystemSettings.allKeys()) {
|
||||
settings.setValue(key, oldSystemSettings.value(key));
|
||||
}
|
||||
}
|
||||
|
||||
// Restore system settings path
|
||||
QSettings::setPath(
|
||||
QSettings::IniFormat, QSettings::SystemScope, getSystemSettingPath());
|
||||
if (QFile(settings.fileName()).exists()) {
|
||||
qDebug("system settings already exist, skipping legacy load");
|
||||
return;
|
||||
}
|
||||
|
||||
QSettings::setPath(
|
||||
QSettings::IniFormat, QSettings::SystemScope, kSystemConfigFilename);
|
||||
QSettings oldSystemSettings(
|
||||
QSettings::IniFormat, QSettings::SystemScope,
|
||||
QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName());
|
||||
|
||||
if (QFile(oldSystemSettings.fileName()).exists()) {
|
||||
for (const auto &key : oldSystemSettings.allKeys()) {
|
||||
settings.setValue(key, oldSystemSettings.value(key));
|
||||
}
|
||||
}
|
||||
|
||||
QSettings::setPath(
|
||||
QSettings::IniFormat, QSettings::SystemScope, getSystemSettingPath());
|
||||
}
|
||||
#endif
|
||||
|
||||
ConfigScopes::ConfigScopes() {
|
||||
auto orgName = QCoreApplication::organizationName();
|
||||
if (orgName.isEmpty()) {
|
||||
qFatal("unable to load config, organization name is empty");
|
||||
return;
|
||||
} else {
|
||||
qDebug() << "org name for config:" << orgName;
|
||||
}
|
||||
|
||||
auto appName = QCoreApplication::applicationName();
|
||||
if (appName.isEmpty()) {
|
||||
qFatal("unable to load config, application name is empty");
|
||||
return;
|
||||
} else {
|
||||
qDebug() << "app name for config:" << appName;
|
||||
}
|
||||
|
||||
// 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>();
|
||||
|
||||
qDebug() << "user settings path:" << m_pUserSettings->fileName();
|
||||
|
||||
QSettings::setPath(
|
||||
QSettings::Format::IniFormat, QSettings::Scope::SystemScope,
|
||||
getSystemSettingPath());
|
||||
@ -76,47 +99,57 @@ ConfigScopes::ConfigScopes() {
|
||||
// Config will default to User settings if they exist,
|
||||
// otherwise it will load System setting and save them to User settings
|
||||
m_pSystemSettings = std::make_unique<QSettings>(
|
||||
QSettings::Format::IniFormat, QSettings::Scope::SystemScope,
|
||||
QCoreApplication::organizationName(),
|
||||
QCoreApplication::applicationName());
|
||||
QSettings::Format::IniFormat, QSettings::Scope::SystemScope, orgName,
|
||||
appName);
|
||||
|
||||
// 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>();
|
||||
qDebug() << "system settings path:" << m_pSystemSettings->fileName();
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
ConfigScopes::~ConfigScopes() {
|
||||
while (!m_pReceivers.empty()) {
|
||||
m_pReceivers.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigScopes::load() {
|
||||
#if defined(Q_OS_WIN)
|
||||
// This call is needed for backwardcapability with old settings.
|
||||
loadWindowsLegacy(*m_pSystemSettings);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ConfigScopes::hasSetting(const QString &name, Scope scope) const {
|
||||
void ConfigScopes::signalReady() { emit ready(); }
|
||||
|
||||
void ConfigScopes::save() {
|
||||
qDebug("emitting config saving signal");
|
||||
emit saving();
|
||||
|
||||
qDebug("writing config to filesystem");
|
||||
m_pUserSettings->sync();
|
||||
m_pSystemSettings->sync();
|
||||
}
|
||||
|
||||
bool ConfigScopes::isActiveScopeWritable() const {
|
||||
return activeSettings()->isWritable();
|
||||
}
|
||||
|
||||
void ConfigScopes::setActiveScope(ConfigScopes::Scope scope) {
|
||||
m_currentScope = scope;
|
||||
}
|
||||
|
||||
ConfigScopes::Scope ConfigScopes::activeScope() const { return m_currentScope; }
|
||||
|
||||
bool ConfigScopes::scopeContains(const QString &name, Scope scope) const {
|
||||
switch (scope) {
|
||||
case Scope::User:
|
||||
return m_pUserSettings->contains(name);
|
||||
case Scope::System:
|
||||
return m_pSystemSettings->contains(name);
|
||||
default:
|
||||
return currentSettings()->contains(name);
|
||||
return activeSettings()->contains(name);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConfigScopes::isWritable() const {
|
||||
return currentSettings()->isWritable();
|
||||
QSettings *ConfigScopes::activeSettings() const {
|
||||
if (m_currentScope == Scope::User) {
|
||||
return m_pUserSettings.get();
|
||||
} else {
|
||||
return m_pSystemSettings.get();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ConfigScopes::loadSetting(
|
||||
QVariant ConfigScopes::getFromScope(
|
||||
const QString &name, const QVariant &defaultValue, Scope scope) const {
|
||||
switch (scope) {
|
||||
case Scope::User:
|
||||
@ -124,68 +157,23 @@ QVariant ConfigScopes::loadSetting(
|
||||
case Scope::System:
|
||||
return m_pSystemSettings->value(name, defaultValue);
|
||||
default:
|
||||
return currentSettings()->value(name, defaultValue);
|
||||
return activeSettings()->value(name, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigScopes::setScope(ConfigScopes::Scope scope) {
|
||||
m_CurrentScope = scope;
|
||||
}
|
||||
|
||||
ConfigScopes::Scope ConfigScopes::getScope() const { return m_CurrentScope; }
|
||||
|
||||
void ConfigScopes::loadAll() {
|
||||
for (auto &i : m_pReceivers) {
|
||||
i->loadSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigScopes::saveAll() {
|
||||
|
||||
// Save if there are any unsaved changes otherwise skip
|
||||
if (unsavedChanges()) {
|
||||
for (auto &i : m_pReceivers) {
|
||||
i->saveSettings();
|
||||
}
|
||||
|
||||
m_pUserSettings->sync();
|
||||
m_pSystemSettings->sync();
|
||||
|
||||
m_unsavedChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
QSettings *ConfigScopes::currentSettings() const {
|
||||
if (m_CurrentScope == Scope::User) {
|
||||
return m_pUserSettings.get();
|
||||
} else {
|
||||
return m_pSystemSettings.get();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigScopes::registerReceiver(CommonConfig *receiver) {
|
||||
m_pReceivers.push_back(receiver);
|
||||
}
|
||||
|
||||
bool ConfigScopes::unsavedChanges() const {
|
||||
if (m_unsavedChanges) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto &i : m_pReceivers) {
|
||||
if (i->modified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConfigScopes::markUnsaved() { m_unsavedChanges = true; }
|
||||
|
||||
void ConfigScopes::setSetting(
|
||||
void ConfigScopes::setInScope(
|
||||
const QString &name, const QVariant &value, Scope scope) {
|
||||
currentSettings()->setValue(name, value);
|
||||
m_unsavedChanges = true;
|
||||
switch (scope) {
|
||||
case Scope::User:
|
||||
m_pUserSettings->setValue(name, value);
|
||||
break;
|
||||
case Scope::System:
|
||||
m_pSystemSettings->setValue(name, value);
|
||||
break;
|
||||
default:
|
||||
activeSettings()->setValue(name, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace synergy::gui
|
||||
|
||||
@ -19,94 +19,44 @@
|
||||
|
||||
#include "IConfigScopes.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QVariant>
|
||||
#include <memory>
|
||||
|
||||
namespace synergy::gui {
|
||||
|
||||
class CommonConfig;
|
||||
|
||||
/// @brief A general config reader and writer for user and gloabl settings
|
||||
class ConfigScopes : public IConfigScopes {
|
||||
/// @brief Encapsulates Qt config for both user and global scopes.
|
||||
class ConfigScopes : public QObject, public IConfigScopes {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigScopes();
|
||||
virtual ~ConfigScopes();
|
||||
virtual ~ConfigScopes() = default;
|
||||
|
||||
/// @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 override;
|
||||
|
||||
/// @brief Checks if the current scope settings writable
|
||||
/// @return bool True if the current scope writable
|
||||
bool isWritable() const override;
|
||||
|
||||
/// @brief Sets the value of a setting
|
||||
/// @param [in] name The Setting to be saved
|
||||
/// @param [in] value The Value to be saved (Templated)
|
||||
/// @param [in] scope The scope to get the value from, default is current
|
||||
/// scope
|
||||
void setSetting(
|
||||
void signalReady() override;
|
||||
void save() override;
|
||||
bool scopeContains(
|
||||
const QString &name, Scope scope = Scope::Current) const override;
|
||||
bool isActiveScopeWritable() const override;
|
||||
void setInScope(
|
||||
const QString &name, const QVariant &value,
|
||||
Scope scope = Scope::Current) override;
|
||||
|
||||
/// @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(
|
||||
QVariant getFromScope(
|
||||
const QString &name, const QVariant &defaultValue = QVariant(),
|
||||
Scope scope = Scope::Current) const override;
|
||||
void setActiveScope(Scope scope = Scope::User) override;
|
||||
Scope activeScope() const override;
|
||||
QSettings *activeSettings() const override;
|
||||
|
||||
/// @brief Changes the setting save and load location between System and User
|
||||
/// scope
|
||||
/// @param [in] scope The scope to set
|
||||
void setScope(Scope scope = Scope::User) override;
|
||||
|
||||
/// @brief Get the current scope the settings are loading and save from.
|
||||
/// @return Scope An enum defining the current scope
|
||||
Scope getScope() const override;
|
||||
|
||||
/// @brief trigger a config load across all registered classes
|
||||
void loadAll() override;
|
||||
|
||||
/// @brief trigger a config save across all registered classes
|
||||
void saveAll() override;
|
||||
|
||||
/// @brief Returns the current scopes settings object
|
||||
/// If more specialize control into the settings is needed this can
|
||||
/// provide direct access to the settings file handler
|
||||
/// @return QSettings The Settings object as a reference
|
||||
QSettings *currentSettings() const override;
|
||||
|
||||
/// @brief This marks the settings as unsaved if the settings() was used to
|
||||
/// directly affect the config file
|
||||
void markUnsaved();
|
||||
|
||||
/// @brief Register a class to receives requests to save and load settings
|
||||
void registerReceiver(CommonConfig *receiver) override;
|
||||
|
||||
/// @brief Checks if any registered class has any unsaved changes
|
||||
/// @return bool True if any registered class has unsaved changes
|
||||
bool unsavedChanges() const;
|
||||
signals:
|
||||
void ready();
|
||||
void saving();
|
||||
|
||||
private:
|
||||
void load();
|
||||
|
||||
Scope m_CurrentScope = Scope::User;
|
||||
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_pReceivers;
|
||||
|
||||
/// @brief Is set to true when settings are changed
|
||||
bool m_unsavedChanges = false;
|
||||
};
|
||||
|
||||
} // namespace synergy::gui
|
||||
|
||||
@ -17,8 +17,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/CommonConfig.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
@ -31,21 +29,42 @@ public:
|
||||
|
||||
virtual ~IConfigScopes() = default;
|
||||
|
||||
virtual void registerReceiver(CommonConfig *receiver) = 0;
|
||||
virtual void loadAll() = 0;
|
||||
virtual Scope activeScope() const = 0;
|
||||
virtual void setActiveScope(Scope scope = Scope::User) = 0;
|
||||
virtual bool isActiveScopeWritable() const = 0;
|
||||
virtual QSettings *activeSettings() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Signals to listeners that the settings that they should read.
|
||||
*/
|
||||
virtual void signalReady() = 0;
|
||||
|
||||
/**
|
||||
* @brief Signalls to listeners to save and calls `sync` on underlying Qt
|
||||
* config.
|
||||
*
|
||||
*/
|
||||
virtual void save() = 0;
|
||||
|
||||
/**
|
||||
* @brief Check a scope for a config value (default is current scope).
|
||||
*/
|
||||
virtual bool
|
||||
hasSetting(const QString &name, Scope scope = Scope::Current) const = 0;
|
||||
virtual QVariant loadSetting(
|
||||
scopeContains(const QString &name, Scope scope = Scope::Current) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Load a config value from a scope (default is current scope).
|
||||
*/
|
||||
virtual QVariant getFromScope(
|
||||
const QString &name, const QVariant &defaultValue = QVariant(),
|
||||
Scope scope = Scope::Current) const = 0;
|
||||
virtual void setSetting(
|
||||
|
||||
/**
|
||||
* @brief Set a config value in a scope (default is current scope).
|
||||
*/
|
||||
virtual void setInScope(
|
||||
const QString &name, const QVariant &value,
|
||||
Scope scope = Scope::Current) = 0;
|
||||
virtual Scope getScope() const = 0;
|
||||
virtual void setScope(Scope scope = Scope::User) = 0;
|
||||
virtual bool isWritable() const = 0;
|
||||
virtual QSettings *currentSettings() const = 0;
|
||||
virtual void saveAll() = 0;
|
||||
};
|
||||
|
||||
} // namespace synergy::gui
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "LicenseHandler.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "license/ProductEdition.h"
|
||||
#include "license/parse_serial_key.h"
|
||||
|
||||
@ -41,6 +42,10 @@ LicenseHandler::ChangeSerialKeyResult
|
||||
LicenseHandler::changeSerialKey(const QString &hexString) {
|
||||
using enum LicenseHandler::ChangeSerialKeyResult;
|
||||
|
||||
if (!m_enabled) {
|
||||
qFatal("cannot set serial key, licensing is disabled");
|
||||
}
|
||||
|
||||
if (hexString.isEmpty()) {
|
||||
qFatal("serial key is empty");
|
||||
return kFatal;
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/constants.h"
|
||||
#include "license/License.h"
|
||||
#include "license/ProductEdition.h"
|
||||
|
||||
@ -44,11 +45,13 @@ public:
|
||||
void validate() const;
|
||||
QString productName() const;
|
||||
ChangeSerialKeyResult changeSerialKey(const QString &hexString);
|
||||
void setEnabled(bool enabled) { m_enabled = enabled; }
|
||||
|
||||
signals:
|
||||
void serialKeyChanged(const QString &serialKey) const;
|
||||
void invalidLicense() const;
|
||||
|
||||
private:
|
||||
bool m_enabled = kLicensingEnabled;
|
||||
License m_license = License::invalid();
|
||||
};
|
||||
|
||||
@ -56,13 +56,13 @@ QIpcClient::~QIpcClient() {
|
||||
void QIpcClient::connected() {
|
||||
|
||||
sendHello();
|
||||
infoMessage("connection established");
|
||||
emit infoMessage("connection established");
|
||||
}
|
||||
|
||||
void QIpcClient::connectToHost() {
|
||||
m_Enabled = true;
|
||||
|
||||
infoMessage("connecting to service...");
|
||||
emit infoMessage("connecting to service...");
|
||||
const auto port = static_cast<quint16>(kIpcPort);
|
||||
m_Socket->connectToHost(QHostAddress(QHostAddress::LocalHost), port);
|
||||
|
||||
@ -73,7 +73,7 @@ void QIpcClient::connectToHost() {
|
||||
}
|
||||
|
||||
void QIpcClient::disconnectFromHost() {
|
||||
infoMessage("service disconnect");
|
||||
emit infoMessage("service disconnect");
|
||||
m_Reader->stop();
|
||||
m_Socket->close();
|
||||
}
|
||||
@ -92,7 +92,7 @@ void QIpcClient::error(QAbstractSocket::SocketError error) {
|
||||
break;
|
||||
}
|
||||
|
||||
errorMessage(QString("ipc connection error, %1").arg(text));
|
||||
emit errorMessage(QString("ipc connection error, %1").arg(text));
|
||||
|
||||
QTimer::singleShot(1000, this, SLOT(retryConnect()));
|
||||
}
|
||||
@ -133,7 +133,9 @@ void QIpcClient::sendCommand(
|
||||
stream->writeRawData(elevateBuf, 1);
|
||||
}
|
||||
|
||||
void QIpcClient::handleReadLogLine(const QString &text) { readLogLine(text); }
|
||||
void QIpcClient::handleReadLogLine(const QString &text) {
|
||||
emit readLogLine(text);
|
||||
}
|
||||
|
||||
// TODO: qt must have a built in way of converting int to bytes.
|
||||
void QIpcClient::intToBytes(int value, char *buffer, int size) {
|
||||
|
||||
@ -32,6 +32,9 @@ bool TlsUtility::isAvailableAndEnabled() const {
|
||||
}
|
||||
|
||||
void TlsUtility::generateCertificate(bool replace) const {
|
||||
qDebug("generating tls certificate, "
|
||||
"all clients must trust the new fingerprint");
|
||||
|
||||
if (!isAvailableAndEnabled()) {
|
||||
qFatal("unable to generate tls certificate, "
|
||||
"tls is either not available or not enabled");
|
||||
|
||||
@ -19,25 +19,33 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
const auto kAppName = "Synergy";
|
||||
|
||||
// TODO: change to `com.symless`. we'll need to gracefully import old settings,
|
||||
// since qt uses this on some platforms when saving settings.
|
||||
const auto kAppDomain = "https://symless.com";
|
||||
|
||||
#ifdef SYNERGY_PRODUCT_NAME
|
||||
const QString kProductName = SYNERGY_PRODUCT_NAME;
|
||||
#else
|
||||
const QString kProductName;
|
||||
#endif
|
||||
|
||||
#ifdef SYNERGY_ENABLE_LICENSING
|
||||
const bool kLicensingEnabled = true;
|
||||
#else
|
||||
const bool kLicensingEnabled = false;
|
||||
#endif // SYNERGY_ENABLE_LICENSING
|
||||
|
||||
const auto kColorWhite = "#ffffff";
|
||||
const auto kColorPrimary = "#ff7c00";
|
||||
const auto kColorSecondary = "#4285f4";
|
||||
const auto kColorTertiary = "#33b2cc";
|
||||
const auto kColorError = "#ec4c47";
|
||||
const auto kColorNotice = "#3b67d3";
|
||||
|
||||
const auto kLinkBuy = R"(<a href="%1" style="color: %2">Buy now</a>)";
|
||||
const auto kLinkRenew = R"(<a href="%1" style="color: %2">Renew now</a>)";
|
||||
const auto kLinkDownload = R"(<a href="%1" style="color: %2">Download now</a>)";
|
||||
|
||||
const auto kUrlSourceQuery = "source=gui";
|
||||
const auto kUrlWebsite = "https://symless.com";
|
||||
const auto kUrlContribute = "https://github.com/symless/synergy-core";
|
||||
const auto kUrlGnomeTrayFix =
|
||||
"https://extensions.gnome.org/extension/2890/tray-icons-reloaded/";
|
||||
const auto kUrlProduct = QString("%1/synergy").arg(kUrlWebsite);
|
||||
const auto kUrlPurchase =
|
||||
QString("%1/purchase?%2").arg(kUrlProduct, kUrlSourceQuery);
|
||||
@ -46,21 +54,3 @@ const auto kUrlContact =
|
||||
const auto kUrlHelp = QString("%1/help?%2").arg(kUrlProduct, kUrlSourceQuery);
|
||||
const auto kUrlDownload =
|
||||
QString("%1/download?%2").arg(kUrlProduct, kUrlSourceQuery);
|
||||
|
||||
const auto kStyleLineEditErrorBorder =
|
||||
QString("border: 1px solid %1; border-radius: 2px; padding: 2px;")
|
||||
.arg(kColorError);
|
||||
|
||||
const auto kStyleErrorActiveLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px; "
|
||||
"background-color: %1; color: %2")
|
||||
.arg(kColorError, kColorWhite);
|
||||
|
||||
const auto kStyleErrorInactiveLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px;"
|
||||
"background-color: none");
|
||||
|
||||
const auto kStyleNoticeLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px;"
|
||||
"background-color: %1; color: %2")
|
||||
.arg(kColorNotice, kColorWhite);
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "constants.h"
|
||||
#include "license/License.h"
|
||||
#include "styles.h"
|
||||
|
||||
using License = synergy::license::License;
|
||||
|
||||
|
||||
159
src/lib/gui/messages.cpp
Normal file
159
src/lib/gui/messages.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 "messages.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "styles.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMessageBox>
|
||||
#include <QTime>
|
||||
|
||||
namespace synergy::gui::messages {
|
||||
|
||||
void messageHandler(
|
||||
QtMsgType type, const QMessageLogContext &context, const QString &message) {
|
||||
|
||||
auto datetime = QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm:ss");
|
||||
const auto filename = QString(context.file).split("/").last();
|
||||
auto function = context.function ? context.function : "";
|
||||
|
||||
QString typeString;
|
||||
auto out = stdout;
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
typeString = "DEBUG";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
typeString = "INFO";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
typeString = "WARNING";
|
||||
out = stderr;
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
typeString = "CRITICAL";
|
||||
out = stderr;
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
typeString = "FATAL";
|
||||
out = stderr;
|
||||
break;
|
||||
}
|
||||
|
||||
auto logLine = QString("[%1] %2: %3\n\t%4:%5, %6")
|
||||
.arg(datetime)
|
||||
.arg(typeString)
|
||||
.arg(message)
|
||||
.arg(filename)
|
||||
.arg(context.line)
|
||||
.arg(function);
|
||||
|
||||
auto logLineUtf = logLine.toUtf8();
|
||||
auto logLine_c = logLineUtf.constData();
|
||||
fprintf(out, "%s\n", logLine_c);
|
||||
|
||||
if (type == QtFatalMsg) {
|
||||
auto contextString =
|
||||
QString("%1:%2\n%3").arg(filename).arg(context.line).arg(function);
|
||||
|
||||
QMessageBox::critical(
|
||||
nullptr, "Fatal error",
|
||||
QString("<p>Sorry, a fatal error has occurred "
|
||||
"and the application must now exit.</p>"
|
||||
"<p>Please "
|
||||
R"(<a href="%1" style="color: %2">contact us</a>)"
|
||||
" and copy/paste the following error:</p>"
|
||||
"<pre>%3\n\n%4</pre>")
|
||||
.arg(kUrlContact, kColorSecondary, message, contextString));
|
||||
|
||||
// developers: if you hit this line in your debugger, traverse the stack to
|
||||
// find the cause of the fatal error.
|
||||
// important: crash the app on fatal error to prevent the app being used in
|
||||
// a broken state.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void showCloseReminder(QWidget *parent) {
|
||||
QString message =
|
||||
"<p>Synergy will continue to run in the background and can be accessed "
|
||||
"via the Synergy icon in your system notifications area. This setting "
|
||||
"can be disabled.</p>";
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
message += QString("<p>On some Linux systems such as GNOME 3, the "
|
||||
"notification area might be disabled. "
|
||||
"You may need to "
|
||||
R"(<a href="%1" %2>enable an extension</a>)"
|
||||
" to see the Synergy tray icon.</p>")
|
||||
.arg(kUrlGnomeTrayFix, kStyleLink);
|
||||
#endif
|
||||
|
||||
QMessageBox::information(parent, "Notification area icon", message);
|
||||
}
|
||||
|
||||
void showFirstRunMessage(
|
||||
QWidget *parent, bool closeToTray, bool enableService, bool isServer) {
|
||||
|
||||
auto message = QString("<p>Synergy is now connected!</p>");
|
||||
|
||||
if (isServer) {
|
||||
message +=
|
||||
"<p>Try moving your mouse to your other computer. Once there, go ahead "
|
||||
"and type something.</p>"
|
||||
"<p>Don't forget, you can copy and paste between computers too.</p>";
|
||||
} else {
|
||||
message += "<p>Try controlling this computer remotely.</p>";
|
||||
}
|
||||
|
||||
if (!closeToTray && !enableService) {
|
||||
message +=
|
||||
"<p>As you do not have the setting enabled to keep Synergy running in "
|
||||
"the background, you'll need to keep this window open or minimized to "
|
||||
"keep Synergy running.</p>";
|
||||
} else {
|
||||
message +=
|
||||
"<p>You can now close this window and Synergy will continue to run in "
|
||||
"the background. This setting can be disabled.</p>";
|
||||
}
|
||||
|
||||
QMessageBox::information(parent, "Connected", message);
|
||||
}
|
||||
|
||||
void showDevThanks(QWidget *parent, const QString &productName) {
|
||||
if (productName.isEmpty()) {
|
||||
qFatal("product name not set");
|
||||
}
|
||||
|
||||
QMessageBox::information(
|
||||
parent, "Thank you!",
|
||||
QString(
|
||||
"<p>Thanks for using %1.</p>"
|
||||
"<p>If you enjoy using this app, you can support the developers by "
|
||||
R"(<a href="%1" style="color: %2")>purchasing a license</a>)"
|
||||
" or "
|
||||
R"(<a href="%3" style="color: %4")>contributing code</a>.)"
|
||||
"</p>"
|
||||
"<p>This message will only appear once.</p>")
|
||||
.arg(
|
||||
productName, kUrlPurchase, kColorSecondary, kUrlContribute,
|
||||
kColorSecondary));
|
||||
}
|
||||
|
||||
} // namespace synergy::gui::messages
|
||||
36
src/lib/gui/messages.h
Normal file
36
src/lib/gui/messages.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2024 Symless Ltd.
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file LICENSE that should have accompanied this file.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMessageLogContext>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
namespace synergy::gui::messages {
|
||||
|
||||
void messageHandler(
|
||||
QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||
|
||||
void showFirstRunMessage(
|
||||
QWidget *parent, bool closeToTray, bool enableService, bool isServer);
|
||||
|
||||
void showCloseReminder(QWidget *parent);
|
||||
|
||||
void showDevThanks(QWidget *parent, const QString &productName);
|
||||
|
||||
} // namespace synergy::gui::messages
|
||||
49
src/lib/gui/styles.h
Normal file
49
src/lib/gui/styles.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2014 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 <QString>
|
||||
|
||||
const auto kColorWhite = "#ffffff";
|
||||
const auto kColorPrimary = "#ff7c00";
|
||||
const auto kColorSecondary = "#4285f4";
|
||||
const auto kColorTertiary = "#33b2cc";
|
||||
const auto kColorError = "#ec4c47";
|
||||
const auto kColorNotice = "#3b67d3";
|
||||
const auto kColorLightGrey = "#666666";
|
||||
|
||||
const auto kStyleLink = //
|
||||
QString("color: %1").arg(kColorSecondary);
|
||||
|
||||
const auto kStyleLineEditErrorBorder =
|
||||
QString("border: 1px solid %1; border-radius: 2px; padding: 2px;")
|
||||
.arg(kColorError);
|
||||
|
||||
const auto kStyleErrorActiveLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px; "
|
||||
"background-color: %1; color: %2")
|
||||
.arg(kColorError, kColorWhite);
|
||||
|
||||
const auto kStyleErrorInactiveLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px;"
|
||||
"background-color: none");
|
||||
|
||||
const auto kStyleNoticeLabel = //
|
||||
QString("padding: 3px 5px; border-radius: 3px;"
|
||||
"background-color: %1; color: %2")
|
||||
.arg(kColorNotice, kColorWhite);
|
||||
38
src/lib/gui/version.cpp
Normal file
38
src/lib/gui/version.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 "version.h"
|
||||
|
||||
const QString kVersion = SYNERGY_VERSION;
|
||||
|
||||
#ifdef GIT_SHA_SHORT
|
||||
const QString kVersionGitSha = GIT_SHA_SHORT;
|
||||
#else
|
||||
const QString kVersionGitSha;
|
||||
#endif
|
||||
|
||||
namespace synergy::gui {
|
||||
|
||||
QString version() {
|
||||
QString result(kVersion);
|
||||
if (!kVersionGitSha.isEmpty()) {
|
||||
result.append(QString(" (%1)").arg(kVersionGitSha));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace synergy::gui
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2020 Symless Ltd.
|
||||
* 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
|
||||
@ -17,20 +17,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
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;
|
||||
};
|
||||
QString version();
|
||||
|
||||
} // namespace synergy::gui
|
||||
@ -435,11 +435,13 @@ void Server::switchScreen(
|
||||
BaseClientProxy *dst, SInt32 x, SInt32 y, bool forScreensaver) {
|
||||
assert(dst != NULL);
|
||||
|
||||
// if trial is expired, exit the process
|
||||
License license(m_args.m_serialKey);
|
||||
if (license.isExpired()) {
|
||||
LOG((CLOG_ERR "trial has expired, aborting server"));
|
||||
exit(kExitSuccess);
|
||||
if (m_args.m_serialKey.isValid) {
|
||||
// if license is expired, exit the process
|
||||
License license(m_args.m_serialKey);
|
||||
if (license.isExpired()) {
|
||||
LOG((CLOG_ERR "trial has expired, aborting server"));
|
||||
exit(kExitSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/messages.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@ -26,6 +28,7 @@ public:
|
||||
char **argv = nullptr;
|
||||
int argc = 0;
|
||||
s_app = std::make_unique<QCoreApplication>(argc, argv);
|
||||
qInstallMessageHandler(synergy::gui::messages::messageHandler);
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() { s_app.reset(); }
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/messages.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@ -26,6 +28,7 @@ public:
|
||||
char **argv = nullptr;
|
||||
int argc = 0;
|
||||
s_app = std::make_unique<QApplication>(argc, argv);
|
||||
qInstallMessageHandler(synergy::gui::messages::messageHandler);
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() { s_app.reset(); }
|
||||
|
||||
@ -33,6 +33,8 @@ using PollFD = struct pollfd[];
|
||||
|
||||
namespace {
|
||||
struct MockDeps : public ArchNetworkBSD::Deps {
|
||||
std::shared_ptr<PollFD> m_pollFD;
|
||||
|
||||
MockDeps() {
|
||||
ON_CALL(*this, makePollFD(_)).WillByDefault([this](nfds_t n) {
|
||||
m_pollFD = ArchNetworkBSD::Deps::makePollFD(n);
|
||||
@ -40,29 +42,31 @@ struct MockDeps : public ArchNetworkBSD::Deps {
|
||||
});
|
||||
}
|
||||
|
||||
static std::shared_ptr<NiceMock<MockDeps>> makeNice() {
|
||||
return std::make_shared<NiceMock<MockDeps>>();
|
||||
}
|
||||
|
||||
MOCK_METHOD(void, sleep, (double), (override));
|
||||
MOCK_METHOD(int, poll, (struct pollfd *, nfds_t, int), (override));
|
||||
MOCK_METHOD(std::shared_ptr<PollFD>, makePollFD, (nfds_t), (override));
|
||||
MOCK_METHOD(ssize_t, read, (int, void *, size_t), (override));
|
||||
MOCK_METHOD(void, testCancelThread, (), (override));
|
||||
|
||||
std::shared_ptr<PollFD> m_pollFD;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_zeroEntries_callsSleep) {
|
||||
MockDeps deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
|
||||
EXPECT_CALL(deps, sleep(1)).Times(1);
|
||||
EXPECT_CALL(*deps, sleep(1)).Times(1);
|
||||
auto result = networkBSD.pollSocket(nullptr, 0, 1);
|
||||
|
||||
EXPECT_EQ(result, 0);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_mockAccessError_throws) {
|
||||
NiceMock<MockDeps> deps;
|
||||
ON_CALL(deps, poll(_, _, _)).WillByDefault([]() {
|
||||
auto deps = MockDeps::makeNice();
|
||||
ON_CALL(*deps, poll(_, _, _)).WillByDefault([]() {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
});
|
||||
@ -77,8 +81,8 @@ TEST(ArchNetworkBSDTests, pollSocket_mockAccessError_throws) {
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_pfdHasRevents_copiedToEntries) {
|
||||
NiceMock<MockDeps> deps;
|
||||
ON_CALL(deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
|
||||
auto deps = MockDeps::makeNice();
|
||||
ON_CALL(*deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
|
||||
pfd[0].revents = POLLIN | POLLOUT | POLLERR | POLLNVAL;
|
||||
return 0;
|
||||
});
|
||||
@ -93,50 +97,50 @@ TEST(ArchNetworkBSDTests, pollSocket_pfdHasRevents_copiedToEntries) {
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_nullSocket_fdIsNegativeOne) {
|
||||
NiceMock<MockDeps> deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
PollEntries entries{{nullptr, 0, 0}};
|
||||
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
|
||||
EXPECT_EQ(deps.m_pollFD[0].fd, -1);
|
||||
EXPECT_EQ(deps->m_pollFD[0].fd, -1);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_socketSet_fdWasSet) {
|
||||
NiceMock<MockDeps> deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
ArchSocketImpl socket{1, 0};
|
||||
PollEntries entries{{&socket, 0, 0}};
|
||||
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
|
||||
EXPECT_EQ(deps.m_pollFD[0].fd, 1);
|
||||
EXPECT_EQ(deps->m_pollFD[0].fd, 1);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_eventHasPollInBit_bitWasSet) {
|
||||
NiceMock<MockDeps> deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
ArchSocketImpl socket{1, 0};
|
||||
PollEntries entries{{&socket, IArchNetwork::kPOLLIN, 0}};
|
||||
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
|
||||
EXPECT_EQ(deps.m_pollFD[0].events, POLLIN);
|
||||
EXPECT_EQ(deps->m_pollFD[0].events, POLLIN);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_eventHasPollOutBit_bitWasSet) {
|
||||
NiceMock<MockDeps> deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
ArchSocketImpl socket{1, 0};
|
||||
PollEntries entries{{&socket, IArchNetwork::kPOLLOUT, 0}};
|
||||
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
|
||||
EXPECT_EQ(deps.m_pollFD[0].events, POLLOUT);
|
||||
EXPECT_EQ(deps->m_pollFD[0].events, POLLOUT);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_nullSocket_unblockPipeAppended) {
|
||||
NiceMock<MockDeps> deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
PollEntries entries{{nullptr, 0, 0}};
|
||||
|
||||
@ -144,42 +148,42 @@ TEST(ArchNetworkBSDTests, pollSocket_nullSocket_unblockPipeAppended) {
|
||||
|
||||
// interesting: unblock pipe fd comes from `getNetworkDataForThread` which
|
||||
// seems to differ depending on linux distro.
|
||||
EXPECT_GT(deps.m_pollFD[1].fd, -1);
|
||||
EXPECT_GT(deps->m_pollFD[1].fd, -1);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_unblockPipeReventsError_readCalled) {
|
||||
const auto unblockPipeIndex = 1;
|
||||
NiceMock<MockDeps> deps;
|
||||
ON_CALL(deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
|
||||
auto deps = MockDeps::makeNice();
|
||||
ON_CALL(*deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
|
||||
pfd[unblockPipeIndex].revents = POLLIN;
|
||||
return 1;
|
||||
});
|
||||
ON_CALL(deps, read(_, _, _)).WillByDefault([]() {
|
||||
ON_CALL(*deps, read(_, _, _)).WillByDefault([]() {
|
||||
errno = EAGAIN;
|
||||
return 0;
|
||||
});
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
PollEntries entries{{nullptr, 0, 0}};
|
||||
|
||||
EXPECT_CALL(deps, read(_, _, _)).Times(1);
|
||||
EXPECT_CALL(*deps, read(_, _, _)).Times(1);
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, pollSocket_interruptSystemCall_testCancelThread) {
|
||||
NiceMock<MockDeps> deps;
|
||||
ON_CALL(deps, poll(_, _, _)).WillByDefault([]() {
|
||||
auto deps = MockDeps::makeNice();
|
||||
ON_CALL(*deps, poll(_, _, _)).WillByDefault([]() {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
});
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
PollEntries entries{{nullptr, 0, 0}};
|
||||
|
||||
EXPECT_CALL(deps, testCancelThread()).Times(1);
|
||||
EXPECT_CALL(*deps, testCancelThread()).Times(1);
|
||||
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, isAnyAddr_goodAddress_returnsTrue) {
|
||||
MockDeps deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
std::unique_ptr<ArchNetAddressImpl> addr;
|
||||
addr.reset(networkBSD.newAnyAddr(IArchNetwork::kINET6));
|
||||
@ -190,7 +194,7 @@ TEST(ArchNetworkBSDTests, isAnyAddr_goodAddress_returnsTrue) {
|
||||
}
|
||||
|
||||
TEST(ArchNetworkBSDTests, isAnyAddr_badAddress_returnsFalse) {
|
||||
MockDeps deps;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ArchNetworkBSD networkBSD(deps);
|
||||
std::unique_ptr<ArchNetAddressImpl> addr;
|
||||
addr.reset(networkBSD.newAnyAddr(IArchNetwork::kINET6));
|
||||
|
||||
@ -27,37 +27,35 @@ namespace {
|
||||
|
||||
class MockScopes : public synergy::gui::IConfigScopes {
|
||||
public:
|
||||
MOCK_METHOD(void, signalReady, (), (override));
|
||||
MOCK_METHOD(
|
||||
void, registerReceiver, (synergy::gui::CommonConfig * receiver),
|
||||
(override));
|
||||
MOCK_METHOD(void, loadAll, (), (override));
|
||||
bool, scopeContains, (const QString &name, Scope scope),
|
||||
(const, override));
|
||||
MOCK_METHOD(
|
||||
bool, hasSetting, (const QString &name, Scope scope), (const, override));
|
||||
MOCK_METHOD(
|
||||
QVariant, loadSetting,
|
||||
QVariant, getFromScope,
|
||||
(const QString &name, const QVariant &defaultValue, Scope scope),
|
||||
(const, override));
|
||||
MOCK_METHOD(
|
||||
void, setSetting,
|
||||
void, setInScope,
|
||||
(const QString &name, const QVariant &value, Scope scope), (override));
|
||||
MOCK_METHOD(Scope, getScope, (), (const, override));
|
||||
MOCK_METHOD(void, setScope, (Scope scope), (override));
|
||||
MOCK_METHOD(bool, isWritable, (), (const, override));
|
||||
MOCK_METHOD(QSettings *, currentSettings, (), (const, override));
|
||||
MOCK_METHOD(void, saveAll, (), (override));
|
||||
MOCK_METHOD(Scope, activeScope, (), (const, override));
|
||||
MOCK_METHOD(void, setActiveScope, (Scope scope), (override));
|
||||
MOCK_METHOD(bool, isActiveScopeWritable, (), (const, override));
|
||||
MOCK_METHOD(QSettings *, activeSettings, (), (const, override));
|
||||
MOCK_METHOD(void, save, (), (override));
|
||||
};
|
||||
|
||||
struct MockDeps : public AppConfig::Deps {
|
||||
NiceMock<MockScopes> m_scopes;
|
||||
|
||||
MockDeps() {
|
||||
ON_CALL(*this, profileDir()).WillByDefault(Return("stub"));
|
||||
ON_CALL(*this, scopes()).WillByDefault(ReturnRef(m_scopes));
|
||||
ON_CALL(*this, hostname()).WillByDefault(Return("stub"));
|
||||
}
|
||||
|
||||
static std::shared_ptr<NiceMock<MockDeps>> makeNice() {
|
||||
return std::make_shared<NiceMock<MockDeps>>();
|
||||
}
|
||||
|
||||
MOCK_METHOD(QString, profileDir, (), (const, override));
|
||||
MOCK_METHOD(synergy::gui::IConfigScopes &, scopes, (), (override));
|
||||
MOCK_METHOD(QString, hostname, (), (const, override));
|
||||
};
|
||||
|
||||
@ -66,43 +64,36 @@ struct MockDeps : public AppConfig::Deps {
|
||||
class AppConfigTests : public Test {};
|
||||
|
||||
TEST_F(AppConfigTests, ctor_byDefault_screenNameIsHostname) {
|
||||
NiceMock<MockDeps> deps;
|
||||
ON_CALL(deps, hostname()).WillByDefault(Return("test"));
|
||||
NiceMock<MockScopes> scopes;
|
||||
auto deps = MockDeps::makeNice();
|
||||
ON_CALL(*deps, hostname()).WillByDefault(Return("test hostname"));
|
||||
|
||||
AppConfig appConfig(deps);
|
||||
AppConfig appConfig(scopes, deps);
|
||||
|
||||
ASSERT_EQ(appConfig.screenName().toStdString(), "test");
|
||||
ASSERT_EQ(appConfig.screenName().toStdString(), "test hostname");
|
||||
}
|
||||
|
||||
TEST_F(AppConfigTests, loadAllScopes_byDefault_callsScopesLoadAll) {
|
||||
NiceMock<MockDeps> deps;
|
||||
AppConfig appConfig(deps);
|
||||
TEST_F(AppConfigTests, ctor_byDefault_getsFromScope) {
|
||||
NiceMock<MockScopes> scopes;
|
||||
auto deps = MockDeps::makeNice();
|
||||
|
||||
EXPECT_CALL(deps.m_scopes, loadAll());
|
||||
ON_CALL(scopes, scopeContains(_, _)).WillByDefault(Return(true));
|
||||
ON_CALL(scopes, getFromScope(_, _, _))
|
||||
.WillByDefault(Return(QVariant("test screen")));
|
||||
EXPECT_CALL(scopes, getFromScope(_, _, _)).Times(AnyNumber());
|
||||
|
||||
appConfig.loadAllScopes();
|
||||
AppConfig appConfig(scopes, deps);
|
||||
|
||||
ASSERT_EQ(appConfig.screenName().toStdString(), "test screen");
|
||||
}
|
||||
|
||||
TEST_F(AppConfigTests, loadSettings_byDefault_callsScopesLoadSetting) {
|
||||
NiceMock<MockDeps> deps;
|
||||
AppConfig appConfig(deps);
|
||||
TEST_F(AppConfigTests, commit_byDefault_setsToScope) {
|
||||
NiceMock<MockScopes> scopes;
|
||||
auto deps = MockDeps::makeNice();
|
||||
AppConfig appConfig(scopes, deps);
|
||||
|
||||
ON_CALL(deps.m_scopes, hasSetting(_, _)).WillByDefault(Return(true));
|
||||
ON_CALL(deps.m_scopes, loadSetting(_, _, _))
|
||||
.WillByDefault(Return(QVariant("test")));
|
||||
EXPECT_CALL(deps.m_scopes, loadSetting(_, _, _)).Times(AnyNumber());
|
||||
ON_CALL(scopes, isActiveScopeWritable()).WillByDefault(Return(true));
|
||||
EXPECT_CALL(scopes, setInScope(_, _, _)).Times(AnyNumber());
|
||||
|
||||
appConfig.loadSettings();
|
||||
|
||||
ASSERT_EQ(appConfig.screenName().toStdString(), "test");
|
||||
}
|
||||
|
||||
TEST_F(AppConfigTests, saveSettings_byDefault_callsScopesSetSetting) {
|
||||
NiceMock<MockDeps> deps;
|
||||
AppConfig appConfig(deps);
|
||||
|
||||
ON_CALL(deps.m_scopes, isWritable()).WillByDefault(Return(true));
|
||||
EXPECT_CALL(deps.m_scopes, setSetting(_, _, _)).Times(AnyNumber());
|
||||
|
||||
appConfig.saveSettings();
|
||||
appConfig.commit();
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ const auto kFuture = system_clock::now() + hours(1);
|
||||
|
||||
TEST(LicenseHandlerTests, changeSerialKey_validExpiredLicense_returnsTrue) {
|
||||
LicenseHandler licenseHandler;
|
||||
licenseHandler.setEnabled(true);
|
||||
auto hexString = //
|
||||
"7B76313B70726F3B6E69636B20626F6C746F6E3B313B6"
|
||||
"E69636B4073796D6C6573732E636F6D3B203B303B307D";
|
||||
|
||||
Reference in New Issue
Block a user