From 42ff48d6372c9614346fe8b5978fb2368c989a23 Mon Sep 17 00:00:00 2001 From: WarmUpTill <19472752+WarmUpTill@users.noreply.github.com> Date: Tue, 26 May 2026 22:48:16 +0200 Subject: [PATCH] Add option to lock settings dialog with simple password This is meant as a simple tampering protection. The settings are not encrypted and the password is stored in plaintext. --- data/locale/en-US.ini | 7 ++++ forms/advanced-scene-switcher.ui | 7 ++++ lib/advanced-scene-switcher.cpp | 49 +++++++++++++++++++++--- lib/advanced-scene-switcher.hpp | 1 + lib/general.cpp | 66 ++++++++++++++++++++++++++++++++ lib/switcher-data.hpp | 2 + 6 files changed, 126 insertions(+), 6 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index b2a49c5b..c7d78e93 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -47,6 +47,13 @@ AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch="Always show macro search" AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs="Always show all feature tabs" AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs.tooltip="Show tabs that are normally hidden until first used in a macro (e.g. Action Queues, Variables, Twitch, Websockets)." +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock="Lock settings dialog with password" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title="Settings Locked" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.passwordLabel="Enter password:" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.wrongPassword="Wrong password!" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.newPasswordLabel="New password:" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.confirmPasswordLabel="Confirm password:" +AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.passwordMismatch="Passwords do not match!" AdvSceneSwitcher.generalTab.matchBehavior="Match behavior" AdvSceneSwitcher.generalTab.priority="Priority" AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)" diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 065e4ec3..aa5acd43 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -258,6 +258,13 @@ + + + + AdvSceneSwitcher.generalTab.generalBehavior.settingsLock + + + diff --git a/lib/advanced-scene-switcher.cpp b/lib/advanced-scene-switcher.cpp index cfae68a1..b7b9fd64 100644 --- a/lib/advanced-scene-switcher.cpp +++ b/lib/advanced-scene-switcher.cpp @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -718,19 +720,54 @@ static void LoadPlugins() } } +static bool settingsPasswordIsCorrect(QWidget *parent) +{ + bool ok; + QString input = QInputDialog::getText( + parent, + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title"), + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.passwordLabel"), + QLineEdit::Password, QString(), &ok); + + if (!ok) { + return false; + } + + if (input.toStdString() == switcher->settingsLockPassword) { + return true; + } + + QMessageBox::warning( + parent, + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title"), + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.wrongPassword")); + return false; +} + void OpenSettingsWindow() { if (switcher->settingsWindowOpened) { AdvSceneSwitcher::window->show(); AdvSceneSwitcher::window->raise(); AdvSceneSwitcher::window->activateWindow(); - } else { - AdvSceneSwitcher::window = - new AdvSceneSwitcher(static_cast( - obs_frontend_get_main_window())); - AdvSceneSwitcher::window->setAttribute(Qt::WA_DeleteOnClose); - AdvSceneSwitcher::window->show(); + return; } + + auto parent = + static_cast(obs_frontend_get_main_window()); + if (switcher->settingsLockEnabled && + !switcher->settingsLockPassword.empty() && + !settingsPasswordIsCorrect(parent)) { + return; + } + + AdvSceneSwitcher::window = new AdvSceneSwitcher(parent); + AdvSceneSwitcher::window->setAttribute(Qt::WA_DeleteOnClose); + AdvSceneSwitcher::window->show(); } void AdvSceneSwitcher::HighlightMacroSettingsButton(bool enable) diff --git a/lib/advanced-scene-switcher.hpp b/lib/advanced-scene-switcher.hpp index 47651ab4..f893d48b 100644 --- a/lib/advanced-scene-switcher.hpp +++ b/lib/advanced-scene-switcher.hpp @@ -68,6 +68,7 @@ public slots: void on_warnPluginLoadFailure_stateChanged(int state); void on_suppressCrashRecoveryDialog_stateChanged(int state); void on_hideLegacyTabs_stateChanged(int state); + void on_settingsLock_stateChanged(int state); void on_priorityUp_clicked(); void on_priorityDown_clicked(); void on_threadPriority_currentTextChanged(const QString &text); diff --git a/lib/general.cpp b/lib/general.cpp index 024b9e6f..e872f425 100644 --- a/lib/general.cpp +++ b/lib/general.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include namespace advss { @@ -243,6 +245,64 @@ void AdvSceneSwitcher::on_hideLegacyTabs_stateChanged(int state) ui->priorityBox->setVisible(!switcher->hideLegacyTabs); } +void AdvSceneSwitcher::on_settingsLock_stateChanged(int state) +{ + if (loading) { + return; + } + + if (!state) { + switcher->settingsLockEnabled = false; + switcher->settingsLockPassword = ""; + return; + } + + bool ok; + QString newPassword = QInputDialog::getText( + this, + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title"), + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.newPasswordLabel"), + QLineEdit::Password, QString(), &ok); + + const auto disablePassword = [this]() { + QSignalBlocker blocker(ui->settingsLock); + ui->settingsLock->setChecked(false); + ui->settingsLock->setCheckState(Qt::Unchecked); + switcher->settingsLockEnabled = false; + switcher->settingsLockPassword = ""; + }; + + if (!ok || newPassword.isEmpty()) { + disablePassword(); + return; + } + + QString confirm = QInputDialog::getText( + this, + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title"), + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.confirmPasswordLabel"), + QLineEdit::Password, QString(), &ok); + if (!ok || newPassword != confirm) { + if (ok) { + QMessageBox::warning( + this, + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.title"), + obs_module_text( + "AdvSceneSwitcher.generalTab.generalBehavior.settingsLock.passwordMismatch")); + } + disablePassword(); + return; + } + + switcher->settingsLockEnabled = true; + switcher->settingsLockPassword = newPassword.toStdString(); +} + void AdvSceneSwitcher::SetDeprecationWarnings() { QString toolTip = @@ -567,6 +627,9 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj) disableFilterComboboxFilter); obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure); obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs); + obs_data_set_bool(obj, "settingsLockEnabled", settingsLockEnabled); + obs_data_set_string(obj, "settingsLockPassword", + settingsLockPassword.c_str()); SaveFunctionPriorities(obj, functionNamesByPriority); @@ -638,6 +701,8 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj) warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure"); obs_data_set_default_bool(obj, "hideLegacyTabs", true); hideLegacyTabs = obs_data_get_bool(obj, "hideLegacyTabs"); + settingsLockEnabled = obs_data_get_bool(obj, "settingsLockEnabled"); + settingsLockPassword = obs_data_get_string(obj, "settingsLockPassword"); SetDefaultFunctionPriorities(obj); LoadFunctionPriorities(obj, functionNamesByPriority); @@ -960,6 +1025,7 @@ void AdvSceneSwitcher::SetupGeneralTab() ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure); ui->suppressCrashRecoveryDialog->setChecked(GetSuppressCrashDialog()); ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs); + ui->settingsLock->setChecked(switcher->settingsLockEnabled); populatePriorityFunctionList(ui->priorityList); populateThreadPriorityList(ui->threadPriority); diff --git a/lib/switcher-data.hpp b/lib/switcher-data.hpp index 84018dea..27d02162 100644 --- a/lib/switcher-data.hpp +++ b/lib/switcher-data.hpp @@ -163,6 +163,8 @@ public: bool disableHints = false; bool disableFilterComboboxFilter = false; bool hideLegacyTabs = true; + bool settingsLockEnabled = false; + std::string settingsLockPassword; bool saveWindowGeo = false; QPoint windowPos = {}; QSize windowSize = {};