deskflow/src/lib/gui/dialogs/SettingsDialog.cpp

489 lines
22 KiB
C++
Raw Normal View History

2012-06-10 16:50:54 +00:00
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2012 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2008 Volker Lanz <vl@fidra.de>
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
2012-06-10 16:50:54 +00:00
*/
Implement safer memory use, improve dev env, fixed GUI bugs (#7407) * Improve dev script for daemon * Ignore `.user` files created by Qt * Add `FORCE_DESKTOP_PROCESS` option * Catch errors related to getting profile dir * Disable IPC entirely if forced desktop * Use in-class init for AppConfig members * Refactor config to use safer memory management * Improve launch config to make OS-specific debugger usage clearer * Re-enable MainWindowTests on Windows, further refactor for memory safety, fixed some include orders * Remove dead singleton code * Swap order of tests * Use HTTPs for URLs * Fixed compile errors for `SYNERGY_ENABLE_LICENSING` compile path * Restore exec function call * Remove extra link in cancel dialog * Fixed broken link on activation cancel UI * Close dialog if activated * Fixed macOS enum ref to kCurrentProcess * Improve wording on cancel activation dialog * WIP - Test timeout (compile error) * Finished timeout logic (with smart pointer) * Include string_view * Switch to thread from jthread (maybe not supported by macOS compiler?) * Improve comment * Disable test on Windows * Add TODO related to jthread on macOS * Refactor settings and paths on Windows * Launch in desktop mode on Windows * Remove arg quote wraps which break desktop mode * Fixed qFatal on Linux * Remove test value * Follow original `AppConfig` accessor convention * Disable service checkbox if not Windows * Simplify TLS control enable logic * Update command and Git ignore * Fixed code style * Fixed include consistency * Fixed includes in validator * Fixed lint errors * Update ChangeLog * Use smart pointer for core process * Remove unneccesary default operators * Don't halt on stderr
2024-07-22 16:48:02 +00:00
2012-06-10 16:50:54 +00:00
#include "SettingsDialog.h"
#include "common/PlatformInfo.h"
#include "ui_SettingsDialog.h"
#include "common/I18N.h"
#include "common/Settings.h"
#include "gui/Messages.h"
#include "gui/TlsUtility.h"
#include "gui/core/NetworkMonitor.h"
#include <QComboBox>
#include <QDir>
#include <QFileDialog>
#include <QMessageBox>
2012-06-10 16:50:54 +00:00
using namespace deskflow::gui;
Improve UI design and reduce over-use of `#ifdef` (#7413) * Rename `LicenseManager` to `License` * Rename `LicenseManager` to `License` * Move License class to gui lib * Rename license related classes * Refactor serial key parsing * Don't fail fast on containers * Move licensed product name from config to code * Fixed formatting * Update code coverage generator and fixed args * WIP: Converting license to chrono * WIP: Fixed compile errors, tests failing * Fixed all serial key and license tests * Disable verbose logging * Add missing </p> * Add missing include * Revert code coverage config * Handle parse errors * Move more classes into the new gui lib and improve license/serial object ownership * WIP: Fixing signal/slots in MainWindow * Fixed slot for about to quit * Rename manual slots to solve auto-connection warnings * Fixed logging issue * By default, don't close to tray * Add .env support and furthe refactor license code, also fixed some copyright dates * Remove test code * Fixed memory error in .env parser and refactor more licensing display code * Fixed color inconsistencies * Fixed link colors and made log view expand * Disable server components rather than hiding * Reset years of blind UI layout fiddling * Fixed clean Qt task * Only show notice when time limited * Fixed main window layout * Show connected clients * Set 15 spacing * Auto connect on start * More intentional screen size * Fixed tests related to license * Tests for expiry notifications * Reorg tests and remove death test * Update gtest * Tests for dotenv parser * Test command process * What the heck is that doing there? * Merge constants headers * Fixed magic includes * Remove helper function * Remove comment * Remove extern decl * Update ChangeLog
2024-07-26 22:53:52 +00:00
SettingsDialog::SettingsDialog(QWidget *parent, const IServerConfig &serverConfig)
: QDialog(parent),
ui{std::make_unique<Ui::SettingsDialog>()},
m_serverConfig(serverConfig)
{
Improve UI design and reduce over-use of `#ifdef` (#7413) * Rename `LicenseManager` to `License` * Rename `LicenseManager` to `License` * Move License class to gui lib * Rename license related classes * Refactor serial key parsing * Don't fail fast on containers * Move licensed product name from config to code * Fixed formatting * Update code coverage generator and fixed args * WIP: Converting license to chrono * WIP: Fixed compile errors, tests failing * Fixed all serial key and license tests * Disable verbose logging * Add missing </p> * Add missing include * Revert code coverage config * Handle parse errors * Move more classes into the new gui lib and improve license/serial object ownership * WIP: Fixing signal/slots in MainWindow * Fixed slot for about to quit * Rename manual slots to solve auto-connection warnings * Fixed logging issue * By default, don't close to tray * Add .env support and furthe refactor license code, also fixed some copyright dates * Remove test code * Fixed memory error in .env parser and refactor more licensing display code * Fixed color inconsistencies * Fixed link colors and made log view expand * Disable server components rather than hiding * Reset years of blind UI layout fiddling * Fixed clean Qt task * Only show notice when time limited * Fixed main window layout * Show connected clients * Set 15 spacing * Auto connect on start * More intentional screen size * Fixed tests related to license * Tests for expiry notifications * Reorg tests and remove death test * Update gtest * Tests for dotenv parser * Test command process * What the heck is that doing there? * Merge constants headers * Fixed magic includes * Remove helper function * Remove comment * Remove extern decl * Update ChangeLog
2024-07-26 22:53:52 +00:00
ui->setupUi(this);
// hide advanced options on macOS and portable windows
if (deskflow::platform::isMac() || (deskflow::platform::isWindows() && Settings::isPortableMode())) {
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabAdvanced));
}
// set up the language combo
I18N::reDetectLanguages();
ui->comboLanguage->addItems(I18N::detectedLanguages());
ui->comboLanguage->setCurrentText(I18N::toNativeName(I18N::currentLanguage()));
updateText();
ui->comboTlsKeyLength->setItemIcon(0, QIcon::fromTheme(QStringLiteral("security-medium")));
ui->comboTlsKeyLength->setItemIcon(1, QIcon::fromTheme(QIcon::ThemeIcon::SecurityHigh));
ui->lblTlsCertInfo->setFixedSize(28, 28);
ui->rbIconMono->setIcon(QIcon::fromTheme(QStringLiteral("%1-symbolic").arg(kRevFqdnName)));
ui->rbIconColorful->setIcon(QIcon::fromTheme(kRevFqdnName));
// force the first tab, since qt creator sets the active tab as the last one
// the developer was looking at, and it's easy to accidentally save that.
ui->tabWidget->setCurrentIndex(0);
// Populate the list of IP addresses
NetworkMonitor networkMonitor(this);
for (const auto &address : networkMonitor.getAvailableIPv4Addresses()) {
QString ipString = address;
if (ui->comboInterface->findText(ipString) == -1) {
ui->comboInterface->addItem(ipString, ipString);
}
}
loadFromConfig();
adjustSize();
QApplication::processEvents();
setFixedHeight(height());
setWindowFlags((windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMinMaxButtonsHint);
setButtonBoxEnabledButtons();
initConnections();
}
void SettingsDialog::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
updateText();
}
}
void SettingsDialog::initConnections() const
{
connect(this, &SettingsDialog::shown, this, &SettingsDialog::showReadOnlyMessage, Qt::QueuedConnection);
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, this, &SettingsDialog::loadFromConfig);
connect(
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this,
&SettingsDialog::resetToDefault
);
connect(ui->groupSecurity, &QGroupBox::toggled, this, &SettingsDialog::updateTlsControlsEnabled);
connect(ui->groupService, &QGroupBox::toggled, this, &SettingsDialog::updateControls);
connect(ui->btnTlsRegenCert, &QPushButton::clicked, this, &SettingsDialog::regenCertificates);
connect(ui->comboTlsKeyLength, &QComboBox::currentIndexChanged, this, &SettingsDialog::updateRequestedKeySize);
connect(ui->btnTlsCertPath, &QPushButton::clicked, this, &SettingsDialog::browseCertificatePath);
connect(ui->btnBrowseLog, &QPushButton::clicked, this, &SettingsDialog::browseLogPath);
connect(ui->groupLogToFile, &QGroupBox::toggled, this, &SettingsDialog::setLogToFile);
connect(ui->comboLogLevel, &QComboBox::currentIndexChanged, this, &SettingsDialog::logLevelChanged);
connect(ui->comboLanguage, &QComboBox::currentTextChanged, this, [](const QString &lang) {
const auto shortName = I18N::nativeTo639Name(lang);
I18N::setLanguage(shortName);
});
// Connect modifiable controls
connect(ui->rbIconMono, &QRadioButton::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->sbPort, &QSpinBox::valueChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->comboLogLevel, &QComboBox::currentIndexChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->comboInterface, &QComboBox::currentIndexChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->comboTlsKeyLength, &QComboBox::currentIndexChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->comboLanguage, &QComboBox::currentIndexChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbAutoHide, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbPreventSleep, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbCloseToTray, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbElevateDaemon, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbAutoUpdate, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbGuiDebug, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbUseWlClipboard, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbShowVersion, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->cbRequireClientCert, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->groupLogToFile, &QGroupBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->groupService, &QGroupBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->groupSecurity, &QGroupBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->lineLogFilename, &QLineEdit::textChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
connect(ui->lineTlsCertPath, &QLineEdit::textChanged, this, &SettingsDialog::setButtonBoxEnabledButtons);
}
void SettingsDialog::regenCertificates()
{
if (TlsUtility::generateCertificate()) {
QMessageBox::information(this, tr("TLS Certificate Regenerated"), tr("TLS certificate regenerated successfully."));
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
updateKeyLengthOnFile(certificate);
}
}
void SettingsDialog::browseCertificatePath()
{
QString fileName = QFileDialog::getSaveFileName(
this, tr("Select a TLS certificate to use..."), ui->lineTlsCertPath->text(), "Cert (*.pem)", nullptr,
QFileDialog::DontConfirmOverwrite
);
if (!fileName.isEmpty()) {
ui->lineTlsCertPath->setText(fileName);
if (QFile(fileName).exists()) {
updateKeyLengthOnFile(fileName);
} else {
qDebug("no tls certificate file at: %s", qUtf8Printable(fileName));
}
}
}
void SettingsDialog::browseLogPath()
{
QString fileName =
QFileDialog::getSaveFileName(this, tr("Save log file to..."), ui->lineLogFilename->text(), "Logs (*.log *.txt)");
if (!fileName.isEmpty()) {
ui->lineLogFilename->setText(fileName);
}
}
void SettingsDialog::setLogToFile(bool logToFile)
{
ui->widgetLogFilename->setEnabled(logToFile);
}
void SettingsDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
2024-10-21 04:08:10 +00:00
Q_EMIT shown();
}
void SettingsDialog::showReadOnlyMessage()
{
if (Settings::isWritable())
return;
messages::showReadOnlySettings(this, Settings::settingsFile());
}
void SettingsDialog::updateText()
{
// Set Tooltip for the logLevel Items
ui->comboLogLevel->setItemData(0, tr("Required messages"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(1, tr("Non-fatal errors"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(2, tr("General warnings"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(3, tr("Notable events"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(4, tr("General events [Default]"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(5, tr("Debug entries"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(6, tr("More debug output"), Qt::ToolTipRole);
ui->comboLogLevel->setItemData(7, tr("Verbose debug output"), Qt::ToolTipRole);
ui->buttonBox->button(QDialogButtonBox::Save)->setToolTip(tr("Close and save changes"));
ui->buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(tr("Close and forget changes"));
ui->buttonBox->button(QDialogButtonBox::Reset)->setToolTip(tr("Reset to stored values"));
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setToolTip(tr("Reset to default values"));
}
void SettingsDialog::accept()
{
Settings::setValue(Settings::Core::Port, ui->sbPort->value());
Settings::setValue(Settings::Core::Interface, ui->comboInterface->currentData());
Settings::setValue(Settings::Log::Level, ui->comboLogLevel->currentIndex());
Settings::setValue(Settings::Log::ToFile, ui->groupLogToFile->isChecked());
Settings::setValue(Settings::Log::File, ui->lineLogFilename->text());
Settings::setValue(Settings::Daemon::Elevate, ui->cbElevateDaemon->isChecked());
Settings::setValue(Settings::Gui::Autohide, ui->cbAutoHide->isChecked());
Settings::setValue(Settings::Gui::AutoUpdateCheck, ui->cbAutoUpdate->isChecked());
Settings::setValue(Settings::Core::PreventSleep, ui->cbPreventSleep->isChecked());
Settings::setValue(Settings::Security::Certificate, ui->lineTlsCertPath->text());
Settings::setValue(Settings::Security::KeySize, ui->comboTlsKeyLength->currentText().toInt());
Settings::setValue(Settings::Security::TlsEnabled, ui->groupSecurity->isChecked());
Settings::setValue(Settings::Gui::CloseToTray, ui->cbCloseToTray->isChecked());
Settings::setValue(Settings::Gui::SymbolicTrayIcon, ui->rbIconMono->isChecked());
Settings::setValue(Settings::Security::CheckPeers, ui->cbRequireClientCert->isChecked());
Settings::setValue(Settings::Core::Language, I18N::nativeTo639Name(ui->comboLanguage->currentText()));
Settings::setValue(Settings::Log::GuiDebug, ui->cbGuiDebug->isChecked());
Settings::setValue(Settings::Core::UseWlClipboard, ui->cbUseWlClipboard->isChecked());
Settings::setValue(Settings::Gui::ShowVersionInTitle, ui->cbShowVersion->isChecked());
Settings::ProcessMode mode;
if (ui->groupService->isChecked())
mode = Settings::ProcessMode::Service;
else
mode = Settings::ProcessMode::Desktop;
Settings::setValue(Settings::Core::ProcessMode, mode);
QDialog::accept();
}
void SettingsDialog::loadFromConfig()
{
ui->sbPort->setValue(Settings::value(Settings::Core::Port).toInt());
ui->comboLogLevel->setCurrentIndex(Settings::value(Settings::Log::Level).toInt());
ui->groupLogToFile->setChecked(Settings::value(Settings::Log::ToFile).toBool());
ui->lineLogFilename->setText(Settings::value(Settings::Log::File).toString());
ui->cbAutoHide->setChecked(Settings::value(Settings::Gui::Autohide).toBool());
ui->cbPreventSleep->setChecked(Settings::value(Settings::Core::PreventSleep).toBool());
ui->cbCloseToTray->setChecked(Settings::value(Settings::Gui::CloseToTray).toBool());
ui->cbElevateDaemon->setChecked(Settings::value(Settings::Daemon::Elevate).toBool());
ui->cbAutoUpdate->setChecked(Settings::value(Settings::Gui::AutoUpdateCheck).toBool());
ui->cbGuiDebug->setChecked(Settings::value(Settings::Log::GuiDebug).toBool());
ui->cbUseWlClipboard->setChecked(Settings::value(Settings::Core::UseWlClipboard).toBool());
ui->cbShowVersion->setChecked(Settings::value(Settings::Gui::ShowVersionInTitle).toBool());
const auto processMode = Settings::value(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
ui->groupService->setChecked(processMode == Settings::ProcessMode::Service);
if (!deskflow::platform::isWindows())
ui->groupService->setVisible(false);
if (Settings::value(Settings::Gui::SymbolicTrayIcon).toBool())
ui->rbIconMono->setChecked(true);
else
ui->rbIconColorful->setChecked(true);
ui->lblDebugWarning->setVisible(Settings::value(Settings::Log::Level).toInt() > 4);
ui->comboInterface->setCurrentText(Settings::value(Settings::Core::Interface).toString());
if (ui->comboInterface->currentIndex() <= 0) {
ui->comboInterface->setCurrentIndex(0);
m_interfaceSetOnLoad = false;
} else {
m_interfaceSetOnLoad = true;
}
qDebug() << "load from config done";
updateControls();
2012-06-10 16:50:54 +00:00
}
void SettingsDialog::updateTlsControls()
{
const auto certificate = Settings::value(Settings::Security::Certificate).toString();
if (QFile(certificate).exists()) {
updateKeyLengthOnFile(certificate);
}
ui->comboTlsKeyLength->setCurrentText(Settings::value(Settings::Security::KeySize).toString());
ui->lineTlsCertPath->setText(certificate);
ui->cbRequireClientCert->setChecked(Settings::value(Settings::Security::CheckPeers).toBool());
ui->groupSecurity->setChecked(TlsUtility::isEnabled());
ui->groupSecurity->setEnabled(Settings::isWritable());
updateTlsControlsEnabled();
Implement safer memory use, improve dev env, fixed GUI bugs (#7407) * Improve dev script for daemon * Ignore `.user` files created by Qt * Add `FORCE_DESKTOP_PROCESS` option * Catch errors related to getting profile dir * Disable IPC entirely if forced desktop * Use in-class init for AppConfig members * Refactor config to use safer memory management * Improve launch config to make OS-specific debugger usage clearer * Re-enable MainWindowTests on Windows, further refactor for memory safety, fixed some include orders * Remove dead singleton code * Swap order of tests * Use HTTPs for URLs * Fixed compile errors for `SYNERGY_ENABLE_LICENSING` compile path * Restore exec function call * Remove extra link in cancel dialog * Fixed broken link on activation cancel UI * Close dialog if activated * Fixed macOS enum ref to kCurrentProcess * Improve wording on cancel activation dialog * WIP - Test timeout (compile error) * Finished timeout logic (with smart pointer) * Include string_view * Switch to thread from jthread (maybe not supported by macOS compiler?) * Improve comment * Disable test on Windows * Add TODO related to jthread on macOS * Refactor settings and paths on Windows * Launch in desktop mode on Windows * Remove arg quote wraps which break desktop mode * Fixed qFatal on Linux * Remove test value * Follow original `AppConfig` accessor convention * Disable service checkbox if not Windows * Simplify TLS control enable logic * Update command and Git ignore * Fixed code style * Fixed include consistency * Fixed includes in validator * Fixed lint errors * Update ChangeLog * Use smart pointer for core process * Remove unneccesary default operators * Don't halt on stderr
2024-07-22 16:48:02 +00:00
}
void SettingsDialog::updateTlsControlsEnabled()
{
const auto writable = Settings::isWritable();
const auto tlsChecked = ui->groupSecurity->isChecked();
auto enabled = writable && tlsChecked;
ui->lblTlsKeyLength->setEnabled(enabled);
ui->comboTlsKeyLength->setEnabled(enabled);
ui->lblTlsCert->setEnabled(enabled);
ui->widgetTlsCert->setEnabled(enabled);
ui->btnTlsRegenCert->setEnabled(enabled);
ui->cbRequireClientCert->setEnabled(enabled && !isClientMode());
}
bool SettingsDialog::isClientMode() const
{
return Settings::value(Settings::Core::CoreMode) == Settings::CoreMode::Client;
}
void SettingsDialog::updateKeyLengthOnFile(const QString &path)
{
Refactored core process management and IPC client (#7425) * Also ignore `command_pre` for Fedora itself * Improve warning message * Fixed layout issues on main window * Restore fusion theme for Windows dark mode * Further correct main window layout * Set CWD for launch on Windows to same dir as .env * Use signals for tray icon instead of callback * Reduce complexity for setting tray icon * Further reduce tray icon complexity * Reduce tray retry time * Fixed tray not showing on macOS * Refactor function names * Move tray icon to lib * Decouple server connection class * Move server connection to lib * Move client config to lib * Remove redundant forward declarations * Fixed some namespaces in the new lib * Move core process code to new class * Improve member names on new process class * Remove copy/pasta code * Move OSX helpers to lib * Add .mm to lib config * Fixed copyright * Improve reliability of log line handling * Fixed TLS certificate generate bugs * Remove client list * Refactor core process handling to fix various problems * Fixed process/connection status bugs * Fixed function signature issue on macOS * Fixed override warnings * Fixed string format warning * Save `wasStarted` state and use that instead * Use only filename in dialog * Use lambda for simple slot * Scroll to bottom if at bottome * Set value based on position before text added and set horizontal scroll too * Add 1px tollerance for Linux * Simplify start/stop mutex * Always stop service on restart * Increase scroll bottom threshold to 2 * Log warning instead of critical * Fixed long-standing dir CD-up hack * Remove include * Remove include * Fixed rogue dumbisense includes * Account for optional distro_like * Add QAction include to solve incomplete type * Remove rogue #pragma * Static cast log value * Solve event queue delete warning * Fixed integ test on Windows 10 * Reduce enum verbosity * Use static instance instead of global * Make function const * Use unique_ptr instead of new and delete, and made some functions const * Fixed smart pointer use * Fixed variable shadowing * Fixed wrong use of using * Fixed missing namespace using * Simplify TLS error handling * Improve UX around certificate errors and success * Decouple app config from core process through interface * First iteration of core process test * Mark dtor as override * Rename attach launch entry * Add TODO * Create proxy for process * Move IPC client to deps * Fixed warnings * Reorganize new GUI lib dir structure * Update includes to reflect new paths * Reorg GUI tests * Abstract IPC client * Refactor about screen * Fixed .ui warnings * Remove redundant include * Fixed typo * Fixed typos and add spelling * Fixed misleading function name * Improve comment * Improve code coverage for core process * Remove noisy log line * Make global const * Use default dtor * Use vector instead of new * Make ctor explicit * Make ctor explicit (2) * Use enum class * Fixed bad enum * Stub out core tool * Stub out dir operation * Extract byte functions * Add missing return path * Simplify byte/int functions * Fix truncation * Use ctor member assignment * Fixed segfault in process proxy * Fixed print warning * Make function const * Cleanup header * Fixed missing name * Update ChangeLog * Make more functions const
2024-08-07 14:05:18 +00:00
if (!QFile(path).exists()) {
qFatal("tls certificate file not found: %s", qUtf8Printable(path));
}
auto length = TlsUtility::getCertKeyLength(path);
auto labelIcon = QPixmap(QIcon::fromTheme(QIcon::ThemeIcon::SecurityLow).pixmap(24, 24));
if (length == 2048)
labelIcon = QPixmap(QIcon::fromTheme(QStringLiteral("security-medium")).pixmap(24, 24));
if (length == 4096)
labelIcon = QPixmap(QIcon::fromTheme(QIcon::ThemeIcon::SecurityHigh).pixmap(24, 24));
ui->lblTlsCertInfo->setPixmap(labelIcon);
ui->lblTlsCertInfo->setToolTip(QStringLiteral("Key length: %1 bits").arg(QString::number(length)));
}
void SettingsDialog::updateControls()
{
const bool writable = Settings::isWritable();
const bool serviceChecked = ui->groupService->isChecked();
const bool logToFile = ui->groupLogToFile->isChecked();
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(writable);
ui->sbPort->setEnabled(writable);
ui->comboInterface->setEnabled(writable);
ui->comboLogLevel->setEnabled(writable);
ui->groupLogToFile->setEnabled(writable);
ui->cbAutoHide->setEnabled(writable);
ui->cbAutoUpdate->setEnabled(writable);
ui->cbPreventSleep->setEnabled(writable);
ui->lineTlsCertPath->setEnabled(writable);
ui->comboTlsKeyLength->setEnabled(writable);
ui->cbCloseToTray->setEnabled(writable);
// Portable mode only ever applies to Windows.
// Daemon options should only be available on Windows when *not* in portable mode.
if (!Settings::isPortableMode()) {
ui->groupService->setEnabled(writable);
ui->cbElevateDaemon->setEnabled(writable && serviceChecked);
} else if (ui->groupService->isVisibleTo(ui->tabAdvanced)) {
ui->groupService->setVisible(false);
}
// wl-clipboard support only works on wayland.
// options should only be available when we are *not* running on wayland.
if (deskflow::platform::isWayland()) {
ui->cbUseWlClipboard->setEnabled(writable);
} else if (ui->widgetWlClipboard->isVisibleTo(ui->tabAdvanced)) {
ui->widgetWlClipboard->setVisible(false);
}
ui->widgetLogFilename->setEnabled(writable && logToFile);
Implement safer memory use, improve dev env, fixed GUI bugs (#7407) * Improve dev script for daemon * Ignore `.user` files created by Qt * Add `FORCE_DESKTOP_PROCESS` option * Catch errors related to getting profile dir * Disable IPC entirely if forced desktop * Use in-class init for AppConfig members * Refactor config to use safer memory management * Improve launch config to make OS-specific debugger usage clearer * Re-enable MainWindowTests on Windows, further refactor for memory safety, fixed some include orders * Remove dead singleton code * Swap order of tests * Use HTTPs for URLs * Fixed compile errors for `SYNERGY_ENABLE_LICENSING` compile path * Restore exec function call * Remove extra link in cancel dialog * Fixed broken link on activation cancel UI * Close dialog if activated * Fixed macOS enum ref to kCurrentProcess * Improve wording on cancel activation dialog * WIP - Test timeout (compile error) * Finished timeout logic (with smart pointer) * Include string_view * Switch to thread from jthread (maybe not supported by macOS compiler?) * Improve comment * Disable test on Windows * Add TODO related to jthread on macOS * Refactor settings and paths on Windows * Launch in desktop mode on Windows * Remove arg quote wraps which break desktop mode * Fixed qFatal on Linux * Remove test value * Follow original `AppConfig` accessor convention * Disable service checkbox if not Windows * Simplify TLS control enable logic * Update command and Git ignore * Fixed code style * Fixed include consistency * Fixed includes in validator * Fixed lint errors * Update ChangeLog * Use smart pointer for core process * Remove unneccesary default operators * Don't halt on stderr
2024-07-22 16:48:02 +00:00
updateTlsControls();
}
void SettingsDialog::updateRequestedKeySize() const
{
if (ui->comboTlsKeyLength->currentText() == Settings::value(Settings::Security::KeySize).toString())
return;
Settings::setValue(Settings::Security::KeySize, ui->comboTlsKeyLength->currentText());
}
void SettingsDialog::logLevelChanged()
{
ui->lblDebugWarning->setVisible(ui->comboLogLevel->currentIndex() > 4);
}
bool SettingsDialog::isModified() const
{
const auto processMode = Settings::value(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
const bool ignoreInterface = !m_interfaceSetOnLoad && (ui->comboInterface->currentIndex() == 0);
bool modified =
(ui->sbPort->value() != Settings::value(Settings::Core::Port).toInt()) ||
(ui->comboLogLevel->currentIndex() != Settings::value(Settings::Log::Level).toInt()) ||
(ui->groupLogToFile->isChecked() != Settings::value(Settings::Log::ToFile).toBool()) ||
(ui->lineLogFilename->text() != Settings::value(Settings::Log::File).toString()) ||
(ui->cbAutoHide->isChecked() != Settings::value(Settings::Gui::Autohide).toBool()) ||
(ui->cbPreventSleep->isChecked() != Settings::value(Settings::Core::PreventSleep).toBool()) ||
(ui->cbCloseToTray->isChecked() != Settings::value(Settings::Gui::CloseToTray).toBool()) ||
(ui->cbElevateDaemon->isChecked() != Settings::value(Settings::Daemon::Elevate).toBool()) ||
(ui->cbAutoUpdate->isChecked() != Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) ||
(ui->cbGuiDebug->isChecked() != Settings::value(Settings::Log::GuiDebug).toBool()) ||
(ui->cbUseWlClipboard->isChecked() != Settings::value(Settings::Core::UseWlClipboard).toBool()) ||
(ui->cbShowVersion->isChecked() != Settings::value(Settings::Gui::ShowVersionInTitle).toBool()) ||
(ui->rbIconMono->isChecked() != Settings::value(Settings::Gui::SymbolicTrayIcon).toBool()) ||
(ui->groupService->isChecked() != (processMode == Settings::ProcessMode::Service)) ||
(ui->lineTlsCertPath->text() != Settings::value(Settings::Security::Certificate).toString()) ||
(ui->comboTlsKeyLength->currentText() != Settings::value(Settings::Security::KeySize).toString()) ||
(ui->groupSecurity->isChecked() != Settings::value(Settings::Security::TlsEnabled).toBool()) ||
(ui->cbRequireClientCert->isChecked() != Settings::value(Settings::Security::CheckPeers).toBool()) ||
(I18N::nativeTo639Name(ui->comboLanguage->currentText()) != Settings::value(Settings::Core::Language).toString());
if (!ignoreInterface)
modified = modified || ui->comboInterface->currentText() != Settings::value(Settings::Core::Interface).toString();
return modified;
}
bool SettingsDialog::isDefault() const
{
const auto processMode = Settings::defaultValue(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
return (
(ui->sbPort->value() == Settings::defaultValue(Settings::Core::Port).toInt()) &&
(ui->comboLogLevel->currentIndex() == Settings::defaultValue(Settings::Log::Level).toInt()) &&
(ui->groupLogToFile->isChecked() == Settings::defaultValue(Settings::Log::ToFile).toBool()) &&
(ui->lineLogFilename->text() == Settings::defaultValue(Settings::Log::File).toString()) &&
(ui->cbAutoHide->isChecked() == Settings::defaultValue(Settings::Gui::Autohide).toBool()) &&
(ui->cbPreventSleep->isChecked() == Settings::defaultValue(Settings::Core::PreventSleep).toBool()) &&
(ui->cbCloseToTray->isChecked() == Settings::defaultValue(Settings::Gui::CloseToTray).toBool()) &&
(ui->cbElevateDaemon->isChecked() == Settings::defaultValue(Settings::Daemon::Elevate).toBool()) &&
(ui->cbAutoUpdate->isChecked() == Settings::defaultValue(Settings::Gui::AutoUpdateCheck).toBool()) &&
(ui->cbGuiDebug->isChecked() == Settings::defaultValue(Settings::Log::GuiDebug).toBool()) &&
(ui->cbUseWlClipboard->isChecked() == Settings::defaultValue(Settings::Core::UseWlClipboard).toBool()) &&
(ui->cbShowVersion->isChecked() == Settings::defaultValue(Settings::Gui::ShowVersionInTitle).toBool()) &&
(ui->rbIconMono->isChecked() == Settings::defaultValue(Settings::Gui::SymbolicTrayIcon).toBool()) &&
(ui->groupService->isChecked() == (processMode == Settings::ProcessMode::Service)) &&
(ui->comboInterface->currentIndex() == 0) &&
(ui->lineTlsCertPath->text() == Settings::defaultValue(Settings::Security::Certificate).toString()) &&
(ui->comboTlsKeyLength->currentText() == Settings::defaultValue(Settings::Security::KeySize).toString()) &&
(ui->groupSecurity->isChecked() == Settings::defaultValue(Settings::Security::TlsEnabled).toBool()) &&
(ui->cbRequireClientCert->isChecked() == Settings::defaultValue(Settings::Security::CheckPeers).toBool()) &&
(ui->comboLanguage->currentText() == "English")
);
}
void SettingsDialog::resetToDefault()
{
ui->sbPort->setValue(Settings::defaultValue(Settings::Core::Port).toInt());
ui->comboLogLevel->setCurrentIndex(Settings::defaultValue(Settings::Log::Level).toInt());
ui->groupLogToFile->setChecked(Settings::defaultValue(Settings::Log::ToFile).toBool());
ui->lineLogFilename->setText(Settings::defaultValue(Settings::Log::File).toString());
ui->cbAutoHide->setChecked(Settings::defaultValue(Settings::Gui::Autohide).toBool());
ui->cbPreventSleep->setChecked(Settings::defaultValue(Settings::Core::PreventSleep).toBool());
ui->cbCloseToTray->setChecked(Settings::defaultValue(Settings::Gui::CloseToTray).toBool());
ui->cbElevateDaemon->setChecked(Settings::defaultValue(Settings::Daemon::Elevate).toBool());
ui->cbAutoUpdate->setChecked(Settings::defaultValue(Settings::Gui::AutoUpdateCheck).toBool());
ui->cbGuiDebug->setChecked(Settings::defaultValue(Settings::Log::GuiDebug).toBool());
ui->cbUseWlClipboard->setChecked(Settings::defaultValue(Settings::Core::UseWlClipboard).toBool());
ui->cbShowVersion->setChecked(Settings::defaultValue(Settings::Gui::ShowVersionInTitle).toBool());
const auto processMode = Settings::defaultValue(Settings::Core::ProcessMode).value<Settings::ProcessMode>();
ui->groupService->setChecked(processMode == Settings::ProcessMode::Service);
if (!deskflow::platform::isWindows())
ui->groupService->setVisible(false);
if (Settings::defaultValue(Settings::Gui::SymbolicTrayIcon).toBool())
ui->rbIconMono->setChecked(true);
else
ui->rbIconColorful->setChecked(true);
ui->lblDebugWarning->setVisible(false);
ui->comboInterface->setCurrentIndex(0);
qDebug() << "reset to default values";
updateControls();
setButtonBoxEnabledButtons();
}
void SettingsDialog::setButtonBoxEnabledButtons() const
{
const bool modified = isModified();
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(modified);
ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(modified);
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(!isDefault());
}
SettingsDialog::~SettingsDialog() = default;