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 = {};