From 40b9dcd2787d4910ed1c06466f85468a38dce989 Mon Sep 17 00:00:00 2001 From: Lucia Poma Date: Wed, 8 Apr 2026 16:20:53 +0200 Subject: [PATCH] feat: possibility of disable electrode and its settings --- .../views/step1_view.py | 83 +++++++++++++++---- .../views/step3_view.py | 66 +++++++++++---- styles/light_theme.qss | 6 ++ 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/clinical_dbs_annotator/views/step1_view.py b/src/clinical_dbs_annotator/views/step1_view.py index b26c278..308282a 100644 --- a/src/clinical_dbs_annotator/views/step1_view.py +++ b/src/clinical_dbs_annotator/views/step1_view.py @@ -82,6 +82,10 @@ def __init__(self, parent_style): self.left_canvas = ElectrodeCanvas() self.right_canvas = ElectrodeCanvas() + + # Electrode disable state + self.left_electrode_enabled = True + self.right_electrode_enabled = True self.left_canvas.validation_callback = self._on_left_canvas_validation self.right_canvas.validation_callback = self._on_right_canvas_validation self._left_selection_valid = True @@ -238,8 +242,8 @@ def _create_settings_group(self) -> QGroupBox: amp_limits = STIMULATION_LIMITS["amplitude"] pw_limits = STIMULATION_LIMITS["pulse_width"] - left_group = QGroupBox("Left") - left_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.left_group = QGroupBox("Left") + self.left_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) left_group_layout = QVBoxLayout() freq_row = QHBoxLayout() @@ -313,10 +317,10 @@ def _create_settings_group(self) -> QGroupBox: left_config_layout.addWidget(self.left_config_label) left_group_layout.addWidget(self.left_config_box) left_group_layout.addStretch(1) - left_group.setLayout(left_group_layout) + self.left_group.setLayout(left_group_layout) - right_group = QGroupBox("Right") - right_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.right_group = QGroupBox("Right") + self.right_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) right_group_layout = QVBoxLayout() freq_row = QHBoxLayout() @@ -390,12 +394,12 @@ def _create_settings_group(self) -> QGroupBox: right_config_layout.addWidget(self.right_config_label) right_group_layout.addWidget(self.right_config_box) right_group_layout.addStretch(1) - right_group.setLayout(right_group_layout) + self.right_group.setLayout(right_group_layout) sidebar_layout.addWidget(model_group) sidebar_layout.addWidget(group_row) - sidebar_layout.addWidget(left_group) - sidebar_layout.addWidget(right_group) + sidebar_layout.addWidget(self.left_group) + sidebar_layout.addWidget(self.right_group) sidebar_layout.addStretch(1) # Wrap sidebar in a scroll area so it scrolls when rows overflow @@ -427,18 +431,24 @@ def _create_settings_group(self) -> QGroupBox: electrodes_layout = QVBoxLayout() electrodes_row = QHBoxLayout() - left_canvas_group = QGroupBox("Left electrode") + self.left_canvas_group = QGroupBox("Left electrode") + self.left_canvas_group.setCheckable(True) + self.left_canvas_group.setChecked(True) + self.left_canvas_group.toggled.connect(lambda checked: self._toggle_electrode('left', checked)) left_canvas_layout = QVBoxLayout() left_canvas_layout.addWidget(self.left_canvas, 1) - left_canvas_group.setLayout(left_canvas_layout) + self.left_canvas_group.setLayout(left_canvas_layout) - right_canvas_group = QGroupBox("Right electrode") + self.right_canvas_group = QGroupBox("Right electrode") + self.right_canvas_group.setCheckable(True) + self.right_canvas_group.setChecked(True) + self.right_canvas_group.toggled.connect(lambda checked: self._toggle_electrode('right', checked)) right_canvas_layout = QVBoxLayout() right_canvas_layout.addWidget(self.right_canvas, 1) - right_canvas_group.setLayout(right_canvas_layout) + self.right_canvas_group.setLayout(right_canvas_layout) - electrodes_row.addWidget(left_canvas_group, 1) - electrodes_row.addWidget(right_canvas_group, 1) + electrodes_row.addWidget(self.left_canvas_group, 1) + electrodes_row.addWidget(self.right_canvas_group, 1) electrodes_layout.addLayout(electrodes_row) electrodes_layout.addLayout(self._create_electrode_legend_layout()) @@ -878,6 +888,51 @@ def _create_clinical_scales_group(self) -> QGroupBox: return gb_clinical + def _toggle_electrode(self, side: str, checked: bool) -> None: + """Toggle electrode enable/disable state for canvas and settings.""" + from PySide6.QtWidgets import QGraphicsOpacityEffect + + if side == 'left': + self.left_electrode_enabled = checked + self.left_group.setEnabled(checked) + self.left_canvas.setEnabled(checked) + # Apply opacity to visually dim canvas and settings + for widget in (self.left_canvas, self.left_group): + if not checked: + effect = QGraphicsOpacityEffect(widget) + effect.setOpacity(0.3) + widget.setGraphicsEffect(effect) + else: + widget.setGraphicsEffect(None) + elif side == 'right': + self.right_electrode_enabled = checked + self.right_group.setEnabled(checked) + self.right_canvas.setEnabled(checked) + for widget in (self.right_canvas, self.right_group): + if not checked: + effect = QGraphicsOpacityEffect(widget) + effect.setOpacity(0.3) + widget.setGraphicsEffect(effect) + else: + widget.setGraphicsEffect(None) + + def _apply_preset_scales(self, scales: list[str]) -> None: + """Apply a list of preset scales to the clinical scales container.""" + # Remove any existing stretches from container + while self.clinical_scales_container.count(): + item = self.clinical_scales_container.takeAt(0) + if item.spacerItem(): + # Just remove the stretch, no widget to delete + continue + elif item.widget(): + item.widget().deleteLater() + + for scale_name in scales: + self._add_clinical_scale_row(scale_name, with_minus=True, on_remove=self.on_remove_callback) + + self._add_clinical_scale_row("", with_plus=True, on_add=self.on_add_callback) + self.clinical_scales_container.addStretch() + def _create_notes_group(self) -> QGroupBox: """Create the initial notes group box.""" gb_notes = QGroupBox("Initial notes") diff --git a/src/clinical_dbs_annotator/views/step3_view.py b/src/clinical_dbs_annotator/views/step3_view.py index 540138c..ec22c8c 100644 --- a/src/clinical_dbs_annotator/views/step3_view.py +++ b/src/clinical_dbs_annotator/views/step3_view.py @@ -68,6 +68,10 @@ def __init__(self, parent_style): self.left_canvas = ElectrodeCanvas() self.right_canvas = ElectrodeCanvas() + + # Electrode disable state + self.left_electrode_enabled = True + self.right_electrode_enabled = True self.left_canvas.validation_callback = self._on_left_canvas_validation self.right_canvas.validation_callback = self._on_right_canvas_validation self._left_selection_valid = True @@ -114,18 +118,24 @@ def _setup_ui(self) -> None: electrodes_layout = QVBoxLayout() electrodes_row = QHBoxLayout() - left_canvas_group = QGroupBox("Left electrode") + self.left_canvas_group = QGroupBox("Left electrode") + self.left_canvas_group.setCheckable(True) + self.left_canvas_group.setChecked(True) + self.left_canvas_group.toggled.connect(lambda checked: self._toggle_electrode('left', checked)) left_canvas_layout = QVBoxLayout() left_canvas_layout.addWidget(self.left_canvas, 1) - left_canvas_group.setLayout(left_canvas_layout) + self.left_canvas_group.setLayout(left_canvas_layout) - right_canvas_group = QGroupBox("Right electrode") + self.right_canvas_group = QGroupBox("Right electrode") + self.right_canvas_group.setCheckable(True) + self.right_canvas_group.setChecked(True) + self.right_canvas_group.toggled.connect(lambda checked: self._toggle_electrode('right', checked)) right_canvas_layout = QVBoxLayout() right_canvas_layout.addWidget(self.right_canvas, 1) - right_canvas_group.setLayout(right_canvas_layout) + self.right_canvas_group.setLayout(right_canvas_layout) - electrodes_row.addWidget(left_canvas_group, 1) - electrodes_row.addWidget(right_canvas_group, 1) + electrodes_row.addWidget(self.left_canvas_group, 1) + electrodes_row.addWidget(self.right_canvas_group, 1) electrodes_layout.addLayout(electrodes_row) electrodes_layout.addLayout(self._create_electrode_legend_layout()) @@ -206,8 +216,8 @@ def _create_stimulation_params_group(self) -> QWidget: amp_limits = STIMULATION_LIMITS["amplitude"] pw_limits = STIMULATION_LIMITS["pulse_width"] - left_group = QGroupBox("Left") - left_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.left_group = QGroupBox("Left") + self.left_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) left_group_layout = QVBoxLayout() freq_row = QHBoxLayout() @@ -281,10 +291,10 @@ def _create_stimulation_params_group(self) -> QWidget: left_config_layout.addWidget(self.left_config_label) left_group_layout.addWidget(self.left_config_box) left_group_layout.addStretch(1) - left_group.setLayout(left_group_layout) + self.left_group.setLayout(left_group_layout) - right_group = QGroupBox("Right") - right_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.right_group = QGroupBox("Right") + self.right_group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) right_group_layout = QVBoxLayout() freq_row = QHBoxLayout() @@ -358,11 +368,11 @@ def _create_stimulation_params_group(self) -> QWidget: right_config_layout.addWidget(self.right_config_label) right_group_layout.addWidget(self.right_config_box) right_group_layout.addStretch(1) - right_group.setLayout(right_group_layout) + self.right_group.setLayout(right_group_layout) sidebar_layout.addWidget(group_row) - sidebar_layout.addWidget(left_group) - sidebar_layout.addWidget(right_group) + sidebar_layout.addWidget(self.left_group) + sidebar_layout.addWidget(self.right_group) sidebar_layout.addStretch(1) return container @@ -616,6 +626,34 @@ def _create_session_scales_group(self) -> QGroupBox: return gb_scales + def _toggle_electrode(self, side: str, checked: bool) -> None: + """Toggle electrode enable/disable state for canvas and settings.""" + from PySide6.QtWidgets import QGraphicsOpacityEffect + + if side == 'left': + self.left_electrode_enabled = checked + self.left_group.setEnabled(checked) + self.left_canvas.setEnabled(checked) + # Apply opacity to visually dim canvas and settings + for widget in (self.left_canvas, self.left_group): + if not checked: + effect = QGraphicsOpacityEffect(widget) + effect.setOpacity(0.3) + widget.setGraphicsEffect(effect) + else: + widget.setGraphicsEffect(None) + elif side == 'right': + self.right_electrode_enabled = checked + self.right_group.setEnabled(checked) + self.right_canvas.setEnabled(checked) + for widget in (self.right_canvas, self.right_group): + if not checked: + effect = QGraphicsOpacityEffect(widget) + effect.setOpacity(0.3) + widget.setGraphicsEffect(effect) + else: + widget.setGraphicsEffect(None) + def _create_session_notes_group(self) -> QGroupBox: gb_notes = QGroupBox("Session notes") gb_notes.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) diff --git a/styles/light_theme.qss b/styles/light_theme.qss index 442a073..edad60a 100644 --- a/styles/light_theme.qss +++ b/styles/light_theme.qss @@ -312,6 +312,12 @@ QGroupBox::title { background-color: #ffffff; } +QGroupBox::indicator:unchecked { + border: 1px solid #475569; + border-radius: 2px; + margin-top: 2px; +} + /* Horizontal Lines */ QFrame[frameShape="4"] { background: #cbd5e1;