Skip to content

Commit 55e5c52

Browse files
committed
Show dirty state for Apply Settings button
Add a visual "dirty" state for the Apply Settings button to make unapplied camera config edits more visible. Introduces _set_apply_dirty to toggle button text, icon and tooltip, and a _mark_dirty handler that is connected to various input signals (valueChanged, currentIndexChanged, stateChanged). Ensure the dirty/state is cleared when populating settings and after a successful apply, and unify/replace previous ad-hoc enable calls so the button reliably reflects pending edits.
1 parent af3564f commit 55e5c52

1 file changed

Lines changed: 24 additions & 1 deletion

File tree

dlclivegui/gui/camera_config_dialog.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,17 @@ def _camera_identity_key(self, cam: CameraSettings) -> tuple:
785785
return (backend, "device_id", device_id)
786786
return (backend, "index", int(cam.index))
787787

788+
def _set_apply_dirty(self, dirty: bool) -> None:
789+
"""Visually mark Apply Settings button as 'dirty' (pending edits)."""
790+
if dirty:
791+
self.apply_settings_btn.setText("Apply Settings *")
792+
self.apply_settings_btn.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MessageBoxWarning))
793+
self.apply_settings_btn.setToolTip("You have unapplied changes. Click to apply them.")
794+
else:
795+
self.apply_settings_btn.setText("Apply Settings")
796+
self.apply_settings_btn.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_DialogApplyButton))
797+
self.apply_settings_btn.setToolTip("")
798+
788799
# -------------------------------
789800
# Signals / population
790801
# -------------------------------
@@ -805,6 +816,11 @@ def _connect_signals(self) -> None:
805816
self.cancel_btn.clicked.connect(self.reject)
806817
self.scan_started.connect(lambda _: setattr(self, "_dialog_active", True))
807818
self.scan_finished.connect(lambda: setattr(self, "_dialog_active", False))
819+
820+
def _mark_dirty(*_args):
821+
self.apply_settings_btn.setEnabled(True)
822+
self._set_apply_dirty(True)
823+
808824
for sb in (
809825
self.cam_fps,
810826
self.cam_crop_x0,
@@ -815,7 +831,10 @@ def _connect_signals(self) -> None:
815831
self.cam_height,
816832
):
817833
if hasattr(sb, "valueChanged"):
818-
sb.valueChanged.connect(lambda _=None: self.apply_settings_btn.setEnabled(True))
834+
sb.valueChanged.connect(_mark_dirty)
835+
836+
self.cam_rotation.currentIndexChanged.connect(lambda *_: _mark_dirty())
837+
self.cam_enabled_checkbox.stateChanged.connect(lambda *_: _mark_dirty())
819838
self.cam_rotation.currentIndexChanged.connect(lambda _: self.apply_settings_btn.setEnabled(True))
820839

821840
def _populate_from_settings(self) -> None:
@@ -1107,6 +1126,8 @@ def _load_camera_to_form(self, cam: CameraSettings) -> None:
11071126
self.cam_crop_y1.setValue(cam.crop_y1)
11081127
self.apply_settings_btn.setEnabled(True)
11091128
self._set_detected_labels(cam)
1129+
self.apply_settings_btn.setEnabled(False)
1130+
self._set_apply_dirty(False)
11101131

11111132
def _write_form_to_cam(self, cam: CameraSettings) -> None:
11121133
cam.enabled = bool(self.cam_enabled_checkbox.isChecked())
@@ -1535,6 +1556,8 @@ def _cam_diff(old: CameraSettings, new: CameraSettings) -> dict:
15351556
else:
15361557
self._append_status("[Apply] Applied without restart (crop/rotation update is live).")
15371558

1559+
self.apply_settings_btn.setEnabled(False)
1560+
self._set_apply_dirty(False)
15381561
return True
15391562

15401563
except Exception as exc:

0 commit comments

Comments
 (0)