From a61390716db8de7c25da627d0e1b3b9ae4ca325c Mon Sep 17 00:00:00 2001 From: Wes Ladd Date: Tue, 14 Jul 2026 20:39:05 -0500 Subject: [PATCH] Reset confirmation layout after dismissal --- CHANGELOG.md | 1 + carveracontroller/main.py | 7 +++ tests/integration/test_confirm_popup.py | 70 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/integration/test_confirm_popup.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 603ca7b9..ea155d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Enhancement: Added a warning popup if the controller version is lower than the firmware. This is not a supported config - Enhancement: Added Auto Ext. Out toggle to spindle dropdown and Config and Run screen. This can be used to automatically run a vacuum or compressor when the spindle is running - Fixed: Restore Keyboard Jogging state after Probing Popup is closed +- Fixed: Confirmation dialogs no longer retain expanded layouts from laser and resume warnings - Fixed: Repeated firmware checks now happen just once - Fixed: UI widget updates from the SerialMonitor() now dispatched via the main thread. This should reduce the number of RecycleView related crashes - Fixed: Spindle temp reporting when running Analog type spindle without rpm reporting diff --git a/carveracontroller/main.py b/carveracontroller/main.py index be17e511..79031d51 100644 --- a/carveracontroller/main.py +++ b/carveracontroller/main.py @@ -445,6 +445,10 @@ class BoxStencil(BoxLayout, StencilView): class ConfirmPopup(ModalView): + DEFAULT_SIZE_HINT = (0.5, 0.4) + DEFAULT_POS_HINT = {"right": 0.75, "top": 0.7} + DEFAULT_TITLE_SIZE_HINT_Y = 0.4 + showing = False def __init__(self, **kwargs): @@ -455,6 +459,9 @@ def on_open(self): def on_dismiss(self): self.showing = False + self.size_hint = self.DEFAULT_SIZE_HINT + self.pos_hint = self.DEFAULT_POS_HINT.copy() + self.lb_title.size_hint_y = self.DEFAULT_TITLE_SIZE_HINT_Y class UnlockPopup(ModalView): diff --git a/tests/integration/test_confirm_popup.py b/tests/integration/test_confirm_popup.py new file mode 100644 index 00000000..f5ed90af --- /dev/null +++ b/tests/integration/test_confirm_popup.py @@ -0,0 +1,70 @@ +"""Regression tests for reusable confirmation-dialog state.""" + +from tests.integration.conftest import pump_frames + + +def assert_next_standard_confirmation_uses_default_layout(root): + root.confirm_popup.dismiss() + pump_frames(2) + root.open_setting_restore_confirm_popup() + pump_frames(2) + + popup = root.confirm_popup + assert tuple(popup.size_hint) == (0.5, 0.4) + assert popup.pos_hint == {"right": 0.75, "top": 0.7} + assert popup.lb_title.size_hint_y == 0.4 + + popup.dismiss() + pump_frames(2) + + +def test_laser_confirmation_layout_does_not_leak_into_next_dialog(kivy_app): + root = kivy_app.root + popup = root.confirm_popup + + root.enable_laser_mode_confirm_popup() + pump_frames(2) + assert tuple(popup.size_hint) == (0.6, 0.7) + assert popup.pos_hint == {"center_x": 0.5, "center_y": 0.5} + assert popup.lb_title.size_hint_y is None + + assert_next_standard_confirmation_uses_default_layout(root) + + +def test_resume_confirmation_layout_does_not_leak_into_next_dialog(kivy_app, monkeypatch): + app = kivy_app + root = app.root + popup = root.confirm_popup + original_state = { + "selected_remote_filename": app.selected_remote_filename, + "selected_local_filename": app.selected_local_filename, + "lines": root.lines, + "_last_loaded_file_key": root._last_loaded_file_key, + "loading_file": getattr(root, "loading_file", False), + "selected_file_line_count": root.selected_file_line_count, + "file_has_ocodes": root.file_has_ocodes, + } + + try: + app.selected_remote_filename = "job.nc" + app.selected_local_filename = "" + root.lines = ["G0 X0"] + root._last_loaded_file_key = "job.nc" + root.loading_file = False + root.selected_file_line_count = 1 + root.file_has_ocodes = False + monkeypatch.setattr(root.controller, "playStartLineCommand", lambda *args, **kwargs: ["G0 X0"]) + + root.open_resume_playback_confirm_popup("job.nc", 1) + pump_frames(2) + assert tuple(popup.size_hint) == (0.8, 0.8) + assert popup.pos_hint == {"center_x": 0.5, "center_y": 0.5} + + assert_next_standard_confirmation_uses_default_layout(root) + finally: + if popup.parent: + popup.dismiss() + pump_frames(2) + for name, value in original_state.items(): + target = app if name.startswith("selected_") and name.endswith("_filename") else root + setattr(target, name, value)