Skip to content

Commit 61b6dae

Browse files
committed
Sync selection and improve spinbox Enter handling
Ensure selection state is synchronized after initialization by calling _populate_from_settings and a new _post_init_sync_selection to set _current_edit_index. Install event filters on camera numeric spinboxes and their lineEdits, and improve Enter-key handling so interpretText() is invoked on the correct spinbox (whether the event comes from the spinbox or its lineEdit) before applying camera settings. Introduce _selected_detected_camera helper to centralize retrieval of the selected detected camera and use it to control the Add button enablement; simplify scan-related UI enable/disable logic and remove duplicated state handling. Miscellaneous cleanup and minor refactors in camera_config_dialog.py.
1 parent f66553d commit 61b6dae

1 file changed

Lines changed: 55 additions & 14 deletions

File tree

dlclivegui/gui/camera_config/camera_config_dialog.py

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,15 @@ def __init__(
7171
self._settings_scroll_contents: QWidget | None = None
7272

7373
self._setup_ui()
74-
self._populate_from_settings()
7574
self._connect_signals()
75+
self._populate_from_settings()
76+
self._post_init_sync_selection()
77+
78+
def _post_init_sync_selection(self) -> None:
79+
"""Ensure current selection state is reflected in _current_edit_index."""
80+
row = self.active_cameras_list.currentRow()
81+
if row >= 0:
82+
self._on_active_camera_selected(row)
7683

7784
@property
7885
def dlc_camera_id(self) -> str | None:
@@ -94,6 +101,9 @@ def showEvent(self, event):
94101
self._working_settings = self._multi_camera_settings.model_copy(deep=True)
95102
self._current_edit_index = None
96103

104+
self._populate_from_settings()
105+
self._post_init_sync_selection()
106+
97107
# Maintain overlay geometry when resizing
98108
def resizeEvent(self, event):
99109
super().resizeEvent(event)
@@ -126,7 +136,7 @@ def eventFilter(self, obj, event):
126136
# Intercept Enter in FPS and crop spinboxes
127137
if event.type() == QEvent.KeyPress and isinstance(event, QKeyEvent):
128138
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
129-
if obj in (
139+
spinboxes = (
130140
self.cam_fps,
131141
self.cam_width,
132142
self.cam_height,
@@ -136,15 +146,22 @@ def eventFilter(self, obj, event):
136146
self.cam_crop_y0,
137147
self.cam_crop_x1,
138148
self.cam_crop_y1,
139-
):
140-
# Commit any pending text → value
149+
)
150+
151+
def _matches(sb):
152+
return obj is sb or obj is getattr(sb, "lineEdit", lambda: None)()
153+
154+
if any(_matches(sb) for sb in spinboxes):
141155
try:
142-
obj.interpretText()
156+
# If event came from lineEdit, interpretText still belongs to the spinbox
157+
for sb in spinboxes:
158+
if _matches(sb):
159+
sb.interpretText()
160+
break
143161
except Exception:
144162
pass
145-
# Apply settings to persist crop/FPS to CameraSettings
163+
146164
self._apply_camera_settings()
147-
# Consume so OK isn't triggered
148165
return True
149166

150167
return super().eventFilter(obj, event)
@@ -226,6 +243,24 @@ def _on_close_cleanup(self) -> None:
226243
# -------------------------------
227244
def _setup_ui(self) -> None:
228245
setup_camera_config_dialog_ui(self)
246+
for sb in (
247+
self.cam_fps,
248+
self.cam_width,
249+
self.cam_height,
250+
self.cam_exposure,
251+
self.cam_gain,
252+
self.cam_crop_x0,
253+
self.cam_crop_y0,
254+
self.cam_crop_x1,
255+
self.cam_crop_y1,
256+
):
257+
try:
258+
sb.installEventFilter(self)
259+
le = sb.lineEdit()
260+
if le is not None:
261+
le.installEventFilter(self)
262+
except Exception:
263+
pass
229264

230265
def _position_scan_overlay(self) -> None:
231266
"""Position scan overlay to cover the available_cameras_list area."""
@@ -325,8 +360,8 @@ def _update_button_states(self) -> None:
325360

326361
self.preview_btn.setEnabled(has_active_selection or self._preview.state == PreviewState.LOADING)
327362

328-
available_row = self.available_cameras_list.currentRow()
329-
self.add_camera_btn.setEnabled(available_row >= 0 and not scan_running)
363+
self.available_cameras_list.currentRow()
364+
self.add_camera_btn.setEnabled((self._selected_detected_camera() is not None) and not scan_running)
330365

331366
def _sync_preview_ui(self) -> None:
332367
"""Update buttons/overlays based on preview state only."""
@@ -395,6 +430,16 @@ def _format_camera_label(self, cam: CameraSettings, index: int = -1) -> str:
395430
dlc_indicator = " [DLC]" if this_id == self._dlc_camera_id and cam.enabled else ""
396431
return f"{status} {cam.name} [{cam.backend}:{cam.index}]{dlc_indicator}"
397432

433+
def _selected_detected_camera(self) -> DetectedCamera | None:
434+
row = self.available_cameras_list.currentRow()
435+
if row < 0:
436+
return None
437+
item = self.available_cameras_list.item(row)
438+
if not item:
439+
return None
440+
detected = item.data(Qt.ItemDataRole.UserRole)
441+
return detected if isinstance(detected, DetectedCamera) else None
442+
398443
def _update_active_list_item(self, row: int, cam: CameraSettings) -> None:
399444
"""Refresh the active camera list row text and color."""
400445
item = self.active_cameras_list.item(row)
@@ -479,7 +524,6 @@ def _is_scan_running(self) -> bool:
479524
def _set_scan_state(self, state: CameraScanState, message: str | None = None) -> None:
480525
"""Single source of truth for scan-related UI controls."""
481526
self._scan_state = state
482-
483527
scanning = state in (CameraScanState.RUNNING, CameraScanState.CANCELING)
484528

485529
# Overlay message
@@ -500,10 +544,8 @@ def _set_scan_state(self, state: CameraScanState, message: str | None = None) ->
500544
# Disable discovery inputs while scanning
501545
self.backend_combo.setEnabled(not scanning)
502546
self.refresh_btn.setEnabled(not scanning)
503-
504547
# Available list + add flow blocked while scanning (structure edits disallowed)
505548
self.available_cameras_list.setEnabled(not scanning)
506-
self.add_camera_btn.setEnabled(False if scanning else (self.available_cameras_list.currentRow() >= 0))
507549

508550
self._update_button_states()
509551

@@ -644,8 +686,7 @@ def _on_available_camera_selected(self, row: int) -> None:
644686
if self._scan_worker and self._scan_worker.isRunning():
645687
self.add_camera_btn.setEnabled(False)
646688
return
647-
item = self.available_cameras_list.item(row) if row >= 0 else None
648-
detected = item.data(Qt.ItemDataRole.UserRole) if item else None
689+
detected = self._selected_detected_camera()
649690
self.add_camera_btn.setEnabled(isinstance(detected, DetectedCamera))
650691

651692
def _on_available_camera_double_clicked(self, item: QListWidgetItem) -> None:

0 commit comments

Comments
 (0)