From be4f708493bf4d7981c7d61cf81e60a541e827eb Mon Sep 17 00:00:00 2001 From: Jason Farrar Date: Sat, 8 Aug 2026 22:47:54 +0100 Subject: [PATCH 1/4] fix: make admin reset delete gui.db and restart the app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously 'Empty Database & Restart' would delete and recreate gui.db, then only quit the application — requiring a manual relaunch. Now it deletes gui.db and uses os.execv to atomically restart the process. The startup logic in main.py handles recreating gui.db from the current schema spec. Project folders and data are unaffected — users can re-attach them via 'Add Existing Project' on startup. --- src/openstan/presenters/admin_presenter.py | 19 ++++++++++++------- src/openstan/views/admin_view.py | 5 +++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/openstan/presenters/admin_presenter.py b/src/openstan/presenters/admin_presenter.py index 754ca22..8e1bd31 100644 --- a/src/openstan/presenters/admin_presenter.py +++ b/src/openstan/presenters/admin_presenter.py @@ -1,4 +1,6 @@ +import os import shutil +import sys import traceback from pathlib import Path from typing import TYPE_CHECKING @@ -7,7 +9,6 @@ from PySide6.QtWidgets import QApplication, QMessageBox from openstan.components import StanErrorMessage, StanInfoMessage -from openstan.data.create_gui_db import create_gui_db from openstan.paths import Paths if TYPE_CHECKING: @@ -182,12 +183,14 @@ def remove_project_from_ui(self) -> None: @Slot() def empty_gui_db(self) -> None: - """Delete and recreate gui.db, then quit the application.""" + """Delete gui.db and restart the application.""" if not self._confirm( "Confirm Reset", "Reset the application?\n\n" - "This will permanently delete all projects, sessions, and users from gui.db " - "and close the application.\n\n" + "This will remove all project records, sessions, and users from gui.db " + "and restart the application.\n\n" + "Your project folders and data will not be affected — " + "you can re-attach them using 'Add Existing Project' on startup.\n\n" "This action cannot be undone.", icon=QMessageBox.Icon.Critical, ): @@ -201,14 +204,16 @@ def empty_gui_db(self) -> None: try: if gui_db_path.exists(): gui_db_path.unlink() - create_gui_db(gui_db_path) except Exception: # noqa: BLE001 traceback.print_exc() StanErrorMessage(parent=self.view).showMessage( - "Failed to recreate gui.db. The application will now close." + "Failed to delete gui.db. The application will now close." ) + QApplication.quit() + return - QApplication.quit() + # Restart — the new process will recreate gui.db on startup + os.execv(sys.executable, [sys.executable] + sys.argv) @Slot() def open_anonymise_tool(self) -> None: diff --git a/src/openstan/views/admin_view.py b/src/openstan/views/admin_view.py index d0f059a..24e38d5 100644 --- a/src/openstan/views/admin_view.py +++ b/src/openstan/views/admin_view.py @@ -104,8 +104,9 @@ def __init__(self, parent=None) -> None: lbl_empty_title = StanLabel("##### Reset Application") lbl_empty_info = StanLabel( - "Deletes and recreates gui.db, then closes the application. " - "All projects, sessions, and users will be permanently lost. " + "Removes all project records, sessions, and users from gui.db " + "and restarts the application. Project folders and data are not affected — " + "re-attach them using 'Add Existing Project' on startup. " "This action cannot be undone." ) lbl_empty_info.setWordWrap(True) From d9581f468e19a9e6a111182f0f9f728f86a5d7f1 Mon Sep 17 00:00:00 2001 From: Jason Farrar Date: Sat, 8 Aug 2026 22:54:53 +0100 Subject: [PATCH 2/4] fix: update button tooltip to match new reset behavior --- src/openstan/views/admin_view.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openstan/views/admin_view.py b/src/openstan/views/admin_view.py index 24e38d5..6b1a154 100644 --- a/src/openstan/views/admin_view.py +++ b/src/openstan/views/admin_view.py @@ -113,7 +113,8 @@ def __init__(self, parent=None) -> None: self.button_empty_db = StanButton("Empty Database && Restart") self.button_empty_db.setToolTip( - "Delete and recreate gui.db, then restart the application — all projects, sessions, and users will be permanently lost" + "Remove all project records, sessions, and users from gui.db and restart — " + "project folders and data are unaffected" ) self.button_empty_db.setStyleSheet( "StanButton { color: palette(highlight); font-weight: bold; }" From 499faf2ea168132d1d39a863c7247efeeab53655 Mon Sep 17 00:00:00 2001 From: Jason Farrar Date: Sat, 8 Aug 2026 22:56:05 +0100 Subject: [PATCH 3/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jason Farrar --- src/openstan/presenters/admin_presenter.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/openstan/presenters/admin_presenter.py b/src/openstan/presenters/admin_presenter.py index 8e1bd31..5c36137 100644 --- a/src/openstan/presenters/admin_presenter.py +++ b/src/openstan/presenters/admin_presenter.py @@ -213,7 +213,16 @@ def empty_gui_db(self) -> None: return # Restart — the new process will recreate gui.db on startup - os.execv(sys.executable, [sys.executable] + sys.argv) + argv = list(getattr(sys, "orig_argv", sys.argv)) + argv[0] = sys.executable + try: + os.execv(sys.executable, argv) + except OSError: # noqa: BLE001 + traceback.print_exc() + StanErrorMessage(parent=self.view).showMessage( + "Failed to restart the application. The application will now close." + ) + QApplication.quit() @Slot() def open_anonymise_tool(self) -> None: From 2bf1bcd68b2b3681fde033bf2cd83862baf26568 Mon Sep 17 00:00:00 2001 From: Jason Farrar Date: Sat, 8 Aug 2026 22:59:53 +0100 Subject: [PATCH 4/4] ruff check --fix --- src/openstan/presenters/admin_presenter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openstan/presenters/admin_presenter.py b/src/openstan/presenters/admin_presenter.py index 5c36137..44684ce 100644 --- a/src/openstan/presenters/admin_presenter.py +++ b/src/openstan/presenters/admin_presenter.py @@ -217,7 +217,7 @@ def empty_gui_db(self) -> None: argv[0] = sys.executable try: os.execv(sys.executable, argv) - except OSError: # noqa: BLE001 + except OSError: traceback.print_exc() StanErrorMessage(parent=self.view).showMessage( "Failed to restart the application. The application will now close."