/* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #include "Settings.h" #include "UrlConstants.h" #include #include #include Settings *Settings::instance() { static Settings m; return &m; } void Settings::setSettingFile(const QString &settingsFile) { if (instance()->m_portableSettingsFile == settingsFile) { qDebug().noquote() << "settings file already in use"; return; } instance()->m_portableSettingsFile = settingsFile; if (instance()->m_settings) instance()->m_settings->deleteLater(); instance()->m_settings = new QSettings(instance()->m_portableSettingsFile, QSettings::IniFormat); instance()->m_settingsProxy->load(instance()->m_portableSettingsFile); qInfo().noquote() << "settings file:" << instance()->m_settings->fileName(); } Settings::Settings(QObject *parent) : QObject(parent) { QString fileToLoad; #ifdef Q_OS_WIN m_portableSettingsFile = m_portableSettingsFile.arg(QCoreApplication::applicationDirPath(), kAppName); if (QFile(m_portableSettingsFile).exists()) { fileToLoad = m_portableSettingsFile; m_settings = new QSettings(fileToLoad, QSettings::IniFormat); } else { m_settings = new QSettings(QSettings::NativeFormat, QSettings::UserScope, kAppName, kAppName); } #else if (!qEnvironmentVariable("XDG_CONFIG_HOME").isEmpty()) fileToLoad = QStringLiteral("%1/%2/%2.conf").arg(qEnvironmentVariable("XDG_CONFIG_HOME"), kAppName); else if (QFile(UserSettingFile).exists()) fileToLoad = UserSettingFile; else if (QFile(SystemSettingFile).exists()) fileToLoad = SystemSettingFile; else fileToLoad = UserSettingFile; m_settings = new QSettings(fileToLoad, QSettings::IniFormat); #endif m_settingsProxy = std::make_shared(); m_settingsProxy->load(fileToLoad); qInfo().noquote() << "settings file:" << m_settings->fileName(); } void Settings::cleanSettings() { const QStringList keys = m_settings->allKeys(); for (const QString &key : keys) { if (!m_validKeys.contains(key)) m_settings->remove(key); if (m_settings->value(key).toString().isEmpty() && !m_settings->value(key).isValid()) m_settings->remove(key); } } QVariant Settings::defaultValue(const QString &key) { if ((key == Gui::Autohide) || (key == Core::StartedBefore) || (key == Core::PreventSleep) || (key == Server::ExternalConfig) || (key == Client::InvertScrollDirection) || (key == Log::ToFile)) { return false; } if ((key == Gui::CloseToTray) || (key == Gui::LogExpanded) || (key == Gui::SymbolicTrayIcon) || (key == Gui::CloseReminder) || (key == Security::TlsEnabled) || (key == Security::CheckPeers) || (key == Client::LanguageSync) || (key == Gui::ShowGenericClientFailureDialog)) { return true; } if (key == Core::ScreenName) return QSysInfo::machineHostName(); if (key == Gui::WindowGeometry) return QRect(); if (key == Security::Certificate) return QStringLiteral("%1/%2").arg(Settings::tlsDir(), kTlsCertificateFilename); if (key == Security::KeySize) return 2048; if (key == Log::File) return QStringLiteral("%1/%2").arg(QDir::homePath(), kDefaultLogFile); if (key == Log::Level) return 4; // INFO if (key == Client::Binary) return kCoreBinName; if (key == Server::Binary) return kCoreBinName; if (key == Daemon::Elevate) return Settings::isNativeMode(); if (key == Core::UpdateUrl) return kUrlUpdateCheck; if (key == Server::ExternalConfigFile) return QStringLiteral("%1/%2-server.conf").arg(Settings::settingsPath(), kAppId); if (key == Core::Port) return 24800; if (key == Core::ProcessMode) { if (Settings::isNativeMode()) return Settings::ProcessMode::Service; else return Settings::ProcessMode::Desktop; } if (key == Daemon::LogFile) { return QStringLiteral("%1/%2").arg(Settings::settingsPath(), kDaemonLogFilename); } return QVariant(); } QString Settings::logLevelText() { return Settings::m_logLevels.at(Settings::value(Log::Level).toInt()); } QSettingsProxy &Settings::proxy() { return *instance()->m_settingsProxy; } void Settings::save(bool emitSaving) { if (emitSaving) Q_EMIT instance()->serverSettingsChanged(); instance()->m_settings->sync(); } QStringList Settings::validKeys() { return Settings::m_validKeys; } bool Settings::isWritable() { if (Settings::isNativeMode()) return true; return instance()->m_settings->isWritable(); } bool Settings::isNativeMode() { return instance()->m_settings->format() == QSettings::NativeFormat; } QString Settings::settingsFile() { return instance()->m_settings->fileName(); } QString Settings::settingsPath() { if (instance()->isNativeMode()) return SystemDir; return QFileInfo(instance()->m_settings->fileName()).absolutePath(); } QString Settings::tlsDir() { return QStringLiteral("%1/%2").arg(instance()->settingsPath(), kTlsDirName); } QString Settings::tlsLocalDb() { return QStringLiteral("%1/%2").arg(instance()->tlsDir(), kTlsFingerprintLocalFilename); } QString Settings::tlsTrustedServersDb() { return QStringLiteral("%1/%2").arg(instance()->tlsDir(), kTlsFingerprintTrustedServersFilename); } QString Settings::tlsTrustedClientsDb() { return QStringLiteral("%1/%2").arg(instance()->tlsDir(), kTlsFingerprintTrustedClientsFilename); } void Settings::setValue(const QString &key, const QVariant &value) { if (instance()->m_settings->value(key) == value) return; if (!value.isValid()) instance()->m_settings->remove(key); else instance()->m_settings->setValue(key, value); instance()->m_settings->sync(); Q_EMIT instance()->settingsChanged(key); } QVariant Settings::value(const QString &key) { return instance()->m_settings->value(key, defaultValue(key)); } void Settings::restoreDefaultSettings() { for (const auto &key : m_validKeys) { instance()->setValue(key, defaultValue(key)); } }