feat: Change to local user ini (not native)
Windows registry is horrible to deal with and makes it impractical to pass settings to the Core when run via daemon on Windows. - Pass settings path to Core when launched via daemon - Introduce portable mode detection logic on Windows - Generalize `m_settingsFile` use - Reduce #ifdef size for Settings ctor path logic
This commit is contained in:
parent
3ece50e292
commit
bb1394ceeb
7 changed files with 56 additions and 36 deletions
|
|
@ -20,45 +20,42 @@ Settings *Settings::instance()
|
||||||
|
|
||||||
void Settings::setSettingFile(const QString &settingsFile)
|
void Settings::setSettingFile(const QString &settingsFile)
|
||||||
{
|
{
|
||||||
if (instance()->m_portableSettingsFile == settingsFile) {
|
if (instance()->settingsFile() == settingsFile) {
|
||||||
qDebug().noquote() << "settings file already in use";
|
qDebug("settings file already set, skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance()->m_portableSettingsFile = settingsFile;
|
|
||||||
if (instance()->m_settings)
|
if (instance()->m_settings)
|
||||||
instance()->m_settings->deleteLater();
|
instance()->m_settings->deleteLater();
|
||||||
instance()->m_settings = new QSettings(instance()->m_portableSettingsFile, QSettings::IniFormat);
|
|
||||||
instance()->m_settingsProxy->load(instance()->m_portableSettingsFile);
|
instance()->m_settings = new QSettings(settingsFile, QSettings::IniFormat);
|
||||||
qInfo().noquote() << "settings file:" << instance()->m_settings->fileName();
|
instance()->m_settingsProxy->load(settingsFile);
|
||||||
|
qInfo().noquote() << "settings file changed:" << instance()->m_settings->fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::Settings(QObject *parent) : QObject(parent)
|
Settings::Settings(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
QString fileToLoad;
|
QString fileToLoad;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
m_portableSettingsFile = m_portableSettingsFile.arg(QCoreApplication::applicationDirPath(), kAppName);
|
const auto portableFile = portableSettingsFile();
|
||||||
if (QFile(m_portableSettingsFile).exists()) {
|
qDebug().noquote() << "checking for portable settings file at:" << portableFile;
|
||||||
fileToLoad = m_portableSettingsFile;
|
if (QFile(portableFile).exists())
|
||||||
m_settings = new QSettings(fileToLoad, QSettings::IniFormat);
|
fileToLoad = portableFile;
|
||||||
} else {
|
|
||||||
m_settings = new QSettings(QSettings::NativeFormat, QSettings::UserScope, kAppName, kAppName);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (!qEnvironmentVariable("XDG_CONFIG_HOME").isEmpty())
|
if (!qEnvironmentVariable("XDG_CONFIG_HOME").isEmpty())
|
||||||
fileToLoad = QStringLiteral("%1/%2/%2.conf").arg(qEnvironmentVariable("XDG_CONFIG_HOME"), kAppName);
|
fileToLoad = QStringLiteral("%1/%2/%2.conf").arg(qEnvironmentVariable("XDG_CONFIG_HOME"), kAppName);
|
||||||
|
#endif
|
||||||
else if (QFile(UserSettingFile).exists())
|
else if (QFile(UserSettingFile).exists())
|
||||||
fileToLoad = UserSettingFile;
|
fileToLoad = UserSettingFile;
|
||||||
else if (QFile(SystemSettingFile).exists())
|
else if (QFile(SystemSettingFile).exists())
|
||||||
fileToLoad = SystemSettingFile;
|
fileToLoad = SystemSettingFile;
|
||||||
else
|
else
|
||||||
fileToLoad = UserSettingFile;
|
fileToLoad = UserSettingFile;
|
||||||
m_settings = new QSettings(fileToLoad, QSettings::IniFormat);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
m_settings = new QSettings(fileToLoad, QSettings::IniFormat);
|
||||||
m_settingsProxy = std::make_shared<QSettingsProxy>();
|
m_settingsProxy = std::make_shared<QSettingsProxy>();
|
||||||
m_settingsProxy->load(fileToLoad);
|
m_settingsProxy->load(fileToLoad);
|
||||||
qInfo().noquote() << "settings file:" << m_settings->fileName();
|
qInfo().noquote() << "initial settings file:" << m_settings->fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::cleanSettings()
|
void Settings::cleanSettings()
|
||||||
|
|
@ -143,7 +140,7 @@ QVariant Settings::defaultValue(const QString &key)
|
||||||
return 4; // INFO
|
return 4; // INFO
|
||||||
|
|
||||||
if (key == Daemon::Elevate)
|
if (key == Daemon::Elevate)
|
||||||
return Settings::isNativeMode();
|
return !Settings::isPortableMode();
|
||||||
|
|
||||||
if (key == Core::UpdateUrl)
|
if (key == Core::UpdateUrl)
|
||||||
return kUrlUpdateCheck;
|
return kUrlUpdateCheck;
|
||||||
|
|
@ -155,10 +152,12 @@ QVariant Settings::defaultValue(const QString &key)
|
||||||
return 24800;
|
return 24800;
|
||||||
|
|
||||||
if (key == Core::ProcessMode) {
|
if (key == Core::ProcessMode) {
|
||||||
if (Settings::isNativeMode())
|
#ifdef Q_OS_WIN
|
||||||
|
if (!Settings::isPortableMode())
|
||||||
return Settings::ProcessMode::Service;
|
return Settings::ProcessMode::Service;
|
||||||
else
|
#endif
|
||||||
return Settings::ProcessMode::Desktop;
|
|
||||||
|
return Settings::ProcessMode::Desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == Daemon::LogFile) {
|
if (key == Daemon::LogFile) {
|
||||||
|
|
@ -196,14 +195,13 @@ QStringList Settings::validKeys()
|
||||||
|
|
||||||
bool Settings::isWritable()
|
bool Settings::isWritable()
|
||||||
{
|
{
|
||||||
if (Settings::isNativeMode())
|
|
||||||
return true;
|
|
||||||
return instance()->m_settings->isWritable();
|
return instance()->m_settings->isWritable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::isNativeMode()
|
bool Settings::isPortableMode()
|
||||||
{
|
{
|
||||||
return instance()->m_settings->format() == QSettings::NativeFormat;
|
// Enable portable mode only if the portable settings file exists in the expected location.
|
||||||
|
return QFile(portableSettingsFile()).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::settingsFile()
|
QString Settings::settingsFile()
|
||||||
|
|
@ -213,8 +211,11 @@ QString Settings::settingsFile()
|
||||||
|
|
||||||
QString Settings::settingsPath()
|
QString Settings::settingsPath()
|
||||||
{
|
{
|
||||||
if (instance()->isNativeMode())
|
#ifdef Q_OS_WIN
|
||||||
|
if (!isPortableMode())
|
||||||
return SystemDir;
|
return SystemDir;
|
||||||
|
#endif
|
||||||
|
|
||||||
return QFileInfo(instance()->m_settings->fileName()).absolutePath();
|
return QFileInfo(instance()->m_settings->fileName()).absolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,3 +264,10 @@ void Settings::restoreDefaultSettings()
|
||||||
instance()->setValue(key, defaultValue(key));
|
instance()->setValue(key, defaultValue(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Settings::portableSettingsFile()
|
||||||
|
{
|
||||||
|
static const auto filename =
|
||||||
|
QStringLiteral("%1/settings/%2.conf").arg(QCoreApplication::applicationDirPath(), kAppName);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class Settings : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
inline const static auto UserDir = QStringLiteral("%1/AppData/Local/%2").arg(QDir::homePath(), kAppName);
|
inline const static auto UserDir = QStringLiteral("%1/AppData/Roaming/%2").arg(QDir::homePath(), kAppName);
|
||||||
inline const static auto SystemDir = QStringLiteral("%1ProgramData/%2").arg(QDir::rootPath(), kAppName);
|
inline const static auto SystemDir = QStringLiteral("%1ProgramData/%2").arg(QDir::rootPath(), kAppName);
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
inline const static auto UserDir = QStringLiteral("%1/Library/%2").arg(QDir::homePath(), kAppName);
|
inline const static auto UserDir = QStringLiteral("%1/Library/%2").arg(QDir::homePath(), kAppName);
|
||||||
|
|
@ -28,6 +28,7 @@ public:
|
||||||
inline const static auto UserDir = QStringLiteral("%1/.config/%2").arg(QDir::homePath(), kAppName);
|
inline const static auto UserDir = QStringLiteral("%1/.config/%2").arg(QDir::homePath(), kAppName);
|
||||||
inline const static auto SystemDir = QStringLiteral("/etc/%1").arg(kAppName);
|
inline const static auto SystemDir = QStringLiteral("/etc/%1").arg(kAppName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline const static auto UserSettingFile = QStringLiteral("%1/%2.conf").arg(UserDir, kAppName);
|
inline const static auto UserSettingFile = QStringLiteral("%1/%2.conf").arg(UserDir, kAppName);
|
||||||
inline const static auto SystemSettingFile = QStringLiteral("%1/%2.conf").arg(SystemDir, kAppName);
|
inline const static auto SystemSettingFile = QStringLiteral("%1/%2.conf").arg(SystemDir, kAppName);
|
||||||
|
|
||||||
|
|
@ -120,7 +121,7 @@ public:
|
||||||
static void restoreDefaultSettings();
|
static void restoreDefaultSettings();
|
||||||
static QVariant defaultValue(const QString &key);
|
static QVariant defaultValue(const QString &key);
|
||||||
static bool isWritable();
|
static bool isWritable();
|
||||||
static bool isNativeMode();
|
static bool isPortableMode();
|
||||||
static QString settingsFile();
|
static QString settingsFile();
|
||||||
static QString settingsPath();
|
static QString settingsPath();
|
||||||
static QString tlsDir();
|
static QString tlsDir();
|
||||||
|
|
@ -132,6 +133,7 @@ public:
|
||||||
static void save(bool emitSaving = true);
|
static void save(bool emitSaving = true);
|
||||||
static QStringList validKeys();
|
static QStringList validKeys();
|
||||||
static int logLevelToInt(const QString &level = "INFO");
|
static int logLevelToInt(const QString &level = "INFO");
|
||||||
|
static QString portableSettingsFile();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void settingsChanged(const QString key);
|
void settingsChanged(const QString key);
|
||||||
|
|
@ -145,7 +147,6 @@ private:
|
||||||
void cleanSettings();
|
void cleanSettings();
|
||||||
|
|
||||||
QSettings *m_settings = nullptr;
|
QSettings *m_settings = nullptr;
|
||||||
QString m_portableSettingsFile = QStringLiteral("%1/settings/%2.conf");
|
|
||||||
std::shared_ptr<QSettingsProxy> m_settingsProxy;
|
std::shared_ptr<QSettingsProxy> m_settingsProxy;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ void clearSettings(bool enableRestart)
|
||||||
profileDir.removeRecursively();
|
profileDir.removeRecursively();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (!Settings::isNativeMode()) {
|
if (Settings::isPortableMode()) {
|
||||||
// make a new empty portable settings file
|
// make a new empty portable settings file
|
||||||
if (profileDir.mkpath(Settings::settingsPath())) {
|
if (profileDir.mkpath(Settings::settingsPath())) {
|
||||||
QFile file(Settings::settingsFile());
|
QFile file(Settings::settingsFile());
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,7 @@ void CoreProcess::start(std::optional<ProcessMode> processModeOption)
|
||||||
if (processMode == ProcessMode::Desktop) {
|
if (processMode == ProcessMode::Desktop) {
|
||||||
startForegroundProcess(args);
|
startForegroundProcess(args);
|
||||||
} else if (processMode == ProcessMode::Service) {
|
} else if (processMode == ProcessMode::Service) {
|
||||||
|
args.append({QStringLiteral("--settings"), Settings::settingsFile()});
|
||||||
startProcessFromDaemon(args);
|
startProcessFromDaemon(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,8 +271,9 @@ void SettingsDialog::updateControls()
|
||||||
ui->comboTlsKeyLength->setEnabled(writable);
|
ui->comboTlsKeyLength->setEnabled(writable);
|
||||||
ui->cbCloseToTray->setEnabled(writable);
|
ui->cbCloseToTray->setEnabled(writable);
|
||||||
|
|
||||||
// Handle enable and disable of service items
|
// Portable mode only ever applies to Windows.
|
||||||
if (Settings::isNativeMode()) {
|
// Daemon options should only be available on Windows when *not* in portable mode.
|
||||||
|
if (!Settings::isPortableMode()) {
|
||||||
ui->groupService->setEnabled(writable);
|
ui->groupService->setEnabled(writable);
|
||||||
ui->cbElevateDaemon->setEnabled(writable && serviceChecked);
|
ui->cbElevateDaemon->setEnabled(writable && serviceChecked);
|
||||||
} else if (ui->groupService->isVisibleTo(ui->tabAdvanced)) {
|
} else if (ui->groupService->isVisibleTo(ui->tabAdvanced)) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ void SettingsTests::initTestCase()
|
||||||
oldSettings.remove();
|
oldSettings.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsTests::setSettingsFile()
|
void SettingsTests::setSettingFile()
|
||||||
{
|
{
|
||||||
Settings::setSettingFile(m_settingsFile);
|
Settings::setSettingFile(m_settingsFile);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class SettingsTests : public QObject
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
// Test are run in order top to bottom
|
// Test are run in order top to bottom
|
||||||
void setSettingsFile();
|
void setSettingFile();
|
||||||
void settingsFile();
|
void settingsFile();
|
||||||
void settingsPath();
|
void settingsPath();
|
||||||
void tlsDir();
|
void tlsDir();
|
||||||
|
|
@ -24,9 +24,18 @@ private Q_SLOTS:
|
||||||
void checkValidSettings();
|
void checkValidSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static const QString m_settingsPath = QStringLiteral("tmp/test");
|
inline static const QString m_settingsPathTemp = QStringLiteral("tmp/test");
|
||||||
inline static const QString m_settingsFile = QStringLiteral("%1/Deskflow.conf").arg(m_settingsPath);
|
inline static const QString m_settingsFile = QStringLiteral("%1/Deskflow.conf").arg(m_settingsPathTemp);
|
||||||
inline static const QString m_expectedTlsDir = QStringLiteral("tmp/test/%1").arg(kTlsDirName);
|
|
||||||
|
// Gotcha: On Windows non-portable mode, additional config files such as TLS config are saved
|
||||||
|
// in 'Program Data' and are not stored in the same place as the settings file.
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
inline static const QString m_settingsPath = Settings::SystemDir;
|
||||||
|
#else
|
||||||
|
inline static const QString m_settingsPath = m_settingsPathTemp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline static const QString m_expectedTlsDir = QStringLiteral("%1/%2").arg(m_settingsPath, kTlsDirName);
|
||||||
inline static const QString m_expectedTlsLocalDB =
|
inline static const QString m_expectedTlsLocalDB =
|
||||||
QStringLiteral("%1/%2").arg(m_expectedTlsDir, kTlsFingerprintLocalFilename);
|
QStringLiteral("%1/%2").arg(m_expectedTlsDir, kTlsFingerprintLocalFilename);
|
||||||
inline static const QString m_expectedTlsServerDB =
|
inline static const QString m_expectedTlsServerDB =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue