Skip to content

Commit 1f5707e

Browse files
committed
Extract _make_two_field_row to layouts util
Move the _make_two_field_row helper out of CameraConfigDialog into dlclivegui/gui/misc/layouts.py as a shared utility. Update camera_config_dialog.py to import the new function and replace the in-class implementation with calls to the extracted helper, adjusting calls to use the new parameter names (key_width, gap). This centralizes common layout code and reduces duplication while preserving the previous value styling and column stretch behavior.
1 parent 35cfe9d commit 1f5707e

2 files changed

Lines changed: 93 additions & 71 deletions

File tree

dlclivegui/gui/camera_config_dialog.py

Lines changed: 14 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from dlclivegui.config import CameraSettings, MultiCameraSettings
3939

4040
from .misc.eliding_label import ElidingPathLabel
41+
from .misc.layouts import _make_two_field_row
4142

4243
LOGGER = logging.getLogger(__name__)
4344
LOGGER.setLevel(logging.DEBUG) # TODO @C-Achard remove for release
@@ -314,71 +315,6 @@ def _merge_backend_settings_back(self, opened_settings: CameraSettings) -> None:
314315
# -------------------------------
315316
# UI setup
316317
# -------------------------------
317-
def _make_two_field_row(
318-
self,
319-
left_label: str,
320-
left_widget: QWidget,
321-
right_label: str,
322-
right_widget: QWidget,
323-
left_stretch: int = 1,
324-
right_stretch: int = 1,
325-
*,
326-
label_min_width: int = 30,
327-
) -> QWidget:
328-
"""Create a compact two-field row widget: (label+value) (label+value), with clear label/value styling."""
329-
row = QWidget()
330-
layout = QHBoxLayout(row)
331-
layout.setContentsMargins(0, 0, 0, 0)
332-
layout.setSpacing(8)
333-
334-
def style_key(lbl: QLabel):
335-
# Muted label styling
336-
lbl.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
337-
# lbl.setMinimumWidth(label_min_width)
338-
# lbl.setStyleSheet(
339-
# """
340-
# QLabel {
341-
# color: rgba(255,255,255,0.65); /* works OK on dark themes */
342-
# color: palette(mid); /* fallback on light themes */
343-
# font-weight: 500;
344-
# }
345-
# """
346-
# )
347-
348-
def style_value(w: QWidget):
349-
# Make values stand out (works for QLabel and custom value widgets like ElidingPathLabel)
350-
# Using QSS that gives a subtle "field" look.
351-
w.setStyleSheet(
352-
"""
353-
QLabel, ElidingPathLabel {
354-
font-weight: 700;
355-
color: palette(text);
356-
background-color: rgba(127,127,127,0.12);
357-
border: 1px solid rgba(127,127,127,0.18);
358-
border-radius: 6px;
359-
padding: 2px 6px;
360-
}
361-
"""
362-
)
363-
if isinstance(w, QLabel):
364-
w.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
365-
366-
l1 = QLabel(left_label)
367-
style_key(l1)
368-
style_value(left_widget)
369-
370-
l2 = QLabel(right_label)
371-
style_key(l2)
372-
style_value(right_widget)
373-
374-
layout.addWidget(l1, 1)
375-
layout.addWidget(left_widget, left_stretch)
376-
layout.addSpacing(8)
377-
layout.addWidget(l2, 1)
378-
layout.addWidget(right_widget, right_stretch)
379-
380-
return row
381-
382318
def _set_detected_labels(self, cam: CameraSettings) -> None:
383319
"""Update the read-only detected labels based on cam.properties[backend]."""
384320
backend = (cam.backend or "").lower()
@@ -529,7 +465,9 @@ def _setup_ui(self) -> None:
529465

530466
self.cam_backend_label = QLabel("opencv")
531467
# self.settings_form.addRow("Backend:", self.cam_backend_label)
532-
id_backend_row = self._make_two_field_row("Index:", self.cam_index_label, "Backend:", self.cam_backend_label)
468+
id_backend_row = _make_two_field_row(
469+
"Index:", self.cam_index_label, "Backend:", self.cam_backend_label, key_width=120
470+
)
533471
self.settings_form.addRow(id_backend_row)
534472

535473
# --- Detected read-only labels (do NOT change requested values) ---
@@ -538,8 +476,13 @@ def _setup_ui(self) -> None:
538476

539477
self.detected_fps_label = QLabel("—")
540478
self.detected_fps_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
541-
detected_row = self._make_two_field_row(
542-
"Detected resolution:", self.detected_resolution_label, "Detected FPS:", self.detected_fps_label
479+
detected_row = _make_two_field_row(
480+
"Detected resolution:",
481+
self.detected_resolution_label,
482+
"Detected FPS:",
483+
self.detected_fps_label,
484+
key_width=120,
485+
gap=10,
543486
)
544487
self.settings_form.addRow(detected_row)
545488

@@ -554,7 +497,7 @@ def _setup_ui(self) -> None:
554497
self.cam_height.setValue(0)
555498
self.cam_height.setSpecialValueText("Auto")
556499

557-
res_row = self._make_two_field_row("W", self.cam_width, "H", self.cam_height)
500+
res_row = _make_two_field_row("W", self.cam_width, "H", self.cam_height, key_width=30)
558501
self.settings_form.addRow("Resolution:", res_row)
559502

560503
# --- FPS + Rotation grouped (CREATE cam_rotation ONCE) ---
@@ -571,7 +514,7 @@ def _setup_ui(self) -> None:
571514
self.cam_rotation.addItem("180°", 180)
572515
self.cam_rotation.addItem("270°", 270)
573516

574-
fps_rot_row = self._make_two_field_row("FPS", self.cam_fps, "Rot", self.cam_rotation)
517+
fps_rot_row = _make_two_field_row("FPS", self.cam_fps, "Rot", self.cam_rotation, key_width=30)
575518
self.settings_form.addRow("Capture:", fps_rot_row)
576519

577520
# --- Exposure + Gain grouped ---
@@ -587,7 +530,7 @@ def _setup_ui(self) -> None:
587530
self.cam_gain.setSpecialValueText("Auto")
588531
self.cam_gain.setDecimals(2)
589532

590-
exp_gain_row = self._make_two_field_row("Exp", self.cam_exposure, "Gain", self.cam_gain)
533+
exp_gain_row = _make_two_field_row("Exp", self.cam_exposure, "Gain", self.cam_gain, key_width=30)
591534
self.settings_form.addRow("Analog:", exp_gain_row)
592535

593536
# --- Crop row (keep as you already have it) ---

dlclivegui/gui/misc/layouts.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Utility functions to create common layouts."""
2+
3+
# dlclivegui/gui/misc/layouts.py
4+
from PySide6.QtCore import Qt
5+
from PySide6.QtWidgets import QGridLayout, QLabel, QSizePolicy, QWidget
6+
7+
8+
def _make_two_field_row(
9+
left_label: str,
10+
left_widget: QWidget,
11+
right_label: str,
12+
right_widget: QWidget,
13+
left_stretch: int = 1,
14+
right_stretch: int = 1,
15+
*,
16+
key_width: int = 100, # width for the "label" columns (Index:, Backend:, etc.)
17+
gap: int = 10, # space between the two pairs
18+
) -> QWidget:
19+
"""Two pairs in one row with aligned columns: [key][value] [key][value]."""
20+
21+
row = QWidget()
22+
grid = QGridLayout(row)
23+
grid.setContentsMargins(0, 0, 0, 0)
24+
grid.setHorizontalSpacing(10)
25+
grid.setVerticalSpacing(0)
26+
27+
# Key labels
28+
l1 = QLabel(left_label)
29+
l2 = QLabel(right_label)
30+
31+
for lbl in (l1, l2):
32+
lbl.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
33+
lbl.setFixedWidth(key_width)
34+
# lbl.setStyleSheet("QLabel { color: palette(mid); font-weight: 500; }")
35+
36+
def style_value(w: QWidget):
37+
w.setStyleSheet(
38+
"""
39+
QLabel, ElidingPathLabel {
40+
font-weight: 700;
41+
color: palette(text);
42+
background-color: rgba(127,127,127,0.12);
43+
border: 1px solid rgba(127,127,127,0.18);
44+
border-radius: 6px;
45+
padding: 2px 6px;
46+
}
47+
"""
48+
)
49+
if isinstance(w, QLabel):
50+
w.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
51+
52+
sp = w.sizePolicy()
53+
sp.setHorizontalPolicy(QSizePolicy.Preferred)
54+
w.setSizePolicy(sp)
55+
56+
style_value(left_widget)
57+
style_value(right_widget)
58+
59+
# Layout columns: 0=key1, 1=val1, 2=gap spacer, 3=key2, 4=val2
60+
grid.addWidget(l1, 0, 0)
61+
grid.addWidget(left_widget, 0, 1)
62+
63+
spacer = QWidget()
64+
spacer.setFixedWidth(gap)
65+
grid.addWidget(spacer, 0, 2)
66+
67+
grid.addWidget(l2, 0, 3)
68+
grid.addWidget(right_widget, 0, 4)
69+
70+
# Stretch values, not keys
71+
grid.setColumnStretch(1, left_stretch)
72+
grid.setColumnStretch(4, right_stretch)
73+
74+
# Prevent keys from stretching
75+
grid.setColumnStretch(0, 0)
76+
grid.setColumnStretch(3, 0)
77+
grid.setColumnStretch(2, 0)
78+
79+
return row

0 commit comments

Comments
 (0)