diff options
Diffstat (limited to 'ui/main_window.py')
| -rw-r--r-- | ui/main_window.py | 93 |
1 files changed, 71 insertions, 22 deletions
diff --git a/ui/main_window.py b/ui/main_window.py index c258424..671cab1 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -29,18 +29,21 @@ class _WheelBlocker(QObject): return True return super().eventFilter(obj, event) -class _CtrlTabStrip(QWidget): - """Thin vertical strip shown on the left edge when the Control Panel dock is hidden. - Clicking it restores the dock. Safety feature — operator can never lose the panel.""" +class _DockTabStrip(QWidget): + """Thin strip shown on an edge when its dock is hidden. Clicking it + restores the dock. Safety feature — operator can never lose the panel.""" clicked = pyqtSignal() - def __init__(self, parent=None): + def __init__(self, label: str, color: str = "#3b82f6", arrow: str = "▶", parent=None): super().__init__(parent) + self._label = label + self._color = color + self._arrow = arrow self.setObjectName("ctrlTabStrip") self.setFixedWidth(22) self.setCursor(Qt.CursorShape.PointingHandCursor) - self.setToolTip("Show Control Panel") + self.setToolTip(f"Show {label.title()}") def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: @@ -50,7 +53,7 @@ class _CtrlTabStrip(QWidget): def paintEvent(self, _event): p = QPainter(self) p.setRenderHint(QPainter.RenderHint.Antialiasing) - p.fillRect(self.rect(), QColor("#3b82f6")) + p.fillRect(self.rect(), QColor(self._color)) p.setPen(QColor("#ffffff")) font = QFont() font.setPointSize(8) @@ -60,31 +63,32 @@ class _CtrlTabStrip(QWidget): p.rotate(-90.0) text_rect = QRect(-self.height() // 2, -self.width() // 2, self.height(), self.width()) - p.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, "CONTROL PANEL ▶") + p.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, f"{self._label} {self._arrow}") p.end() class _DockTitleBar(QWidget): - """Custom title bar for the Control Panel QDockWidget. - Replaces native title bar; provides Add and Close buttons.""" + """Custom title bar for a QDockWidget. Replaces the native title bar; + provides an optional Add button plus a Close button.""" - def __init__(self, dock: QDockWidget, add_callback, parent=None): + def __init__(self, dock: QDockWidget, title: str, add_callback=None, parent=None): super().__init__(parent) self.setObjectName("controlPanelHeader") self.setFixedHeight(30) lay = QHBoxLayout(self) lay.setContentsMargins(8, 0, 4, 0); lay.setSpacing(4) - lbl = QLabel("CONTROL PANEL"); lbl.setObjectName("panelHeader") + lbl = QLabel(title); lbl.setObjectName("panelHeader") lay.addWidget(lbl, 1) - add_btn = QPushButton("+"); add_btn.setObjectName("devicesSmallBtn") - add_btn.setFixedSize(24, 22); add_btn.setToolTip("Add control widget") - add_btn.clicked.connect(add_callback) - lay.addWidget(add_btn) + if add_callback is not None: + add_btn = QPushButton("+"); add_btn.setObjectName("devicesSmallBtn") + add_btn.setFixedSize(24, 22); add_btn.setToolTip(f"Add to {title.title()}") + add_btn.clicked.connect(add_callback) + lay.addWidget(add_btn) close_btn = QPushButton("✕"); close_btn.setObjectName("devicesSmallBtn") - close_btn.setFixedSize(22, 22); close_btn.setToolTip("Hide Control Panel") + close_btn.setFixedSize(22, 22); close_btn.setToolTip(f"Hide {title.title()}") close_btn.clicked.connect(dock.hide) lay.addWidget(close_btn) @@ -98,6 +102,7 @@ from core.signal_processor import SignalProcessor from core.profile import Profile, ProfileManager from ui.control_panel import ControlPanel +from ui.namespace_panel import NamespacePanel from ui.strip_chart import StripChartWidget from ui.profile_manager_ui import ProfileButton from ui.windows.config_window import ConfigWindow @@ -189,11 +194,11 @@ class MainWindow(QMainWindow): self._act_ctrl_panel.setCheckable(True); self._act_ctrl_panel.setChecked(True) self._act_ctrl_panel.triggered.connect(self._on_view_ctrl_panel) self._view_menu.addAction(self._act_ctrl_panel) - self._view_menu.addSeparator() - act_config = QAction("Configuration", self) - act_config.triggered.connect(lambda: self._open_config(0)) - self._view_menu.addAction(act_config) + self._act_namespace = QAction("Namespace", self) + self._act_namespace.setCheckable(True); self._act_namespace.setChecked(False) + self._act_namespace.triggered.connect(self._on_view_namespace) + self._view_menu.addAction(self._act_namespace) self._view_plugin_sep = self._view_menu.addSeparator() self._view_plugin_sep.setVisible(False) @@ -202,6 +207,11 @@ class MainWindow(QMainWindow): lambda: self._view_menu.exec(view_btn.mapToGlobal(view_btn.rect().bottomLeft())) ) tb.addWidget(view_btn) + + config_btn = QPushButton("⚙ Configure"); config_btn.setObjectName("toolbarSectionBtn") + config_btn.clicked.connect(lambda: self._open_config(0)) + tb.addWidget(config_btn) + tb.addWidget(_sep()) self._run_btn = QPushButton("▶ RUN") @@ -246,7 +256,7 @@ class MainWindow(QMainWindow): root = QHBoxLayout(central); root.setContentsMargins(0,0,0,0); root.setSpacing(0) # Side tab strip — shown when Control Panel dock is hidden - self._ctrl_tab = _CtrlTabStrip() + self._ctrl_tab = _DockTabStrip("CONTROL PANEL") self._ctrl_tab.setVisible(False) self._ctrl_tab.clicked.connect(self._show_ctrl_panel) root.addWidget(self._ctrl_tab) @@ -254,6 +264,10 @@ class MainWindow(QMainWindow): self._chart = StripChartWidget(self.engine, self.registry, self.processor) root.addWidget(self._chart, 1) + # No collapse-strip for Namespace — it's a configuration/reference + # tool, not something the operator needs a can't-lose-it affordance + # for during a run (unlike Control Panel). View menu brings it back. + # ── Control Panel dock ──────────────────────────────────────────── self._ctrl = ControlPanel(self.registry, processor=self.processor, engine=self.engine) self._ctrl.setMinimumWidth(200); self._ctrl.setMaximumWidth(340) @@ -271,9 +285,29 @@ class MainWindow(QMainWindow): Qt.DockWidgetArea.RightDockWidgetArea ) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self._ctrl_dock) - self._ctrl_dock.setTitleBarWidget(_DockTitleBar(self._ctrl_dock, self._ctrl._on_add)) + self._ctrl_dock.setTitleBarWidget(_DockTitleBar(self._ctrl_dock, "CONTROL PANEL", self._ctrl._on_add)) self._ctrl_dock.visibilityChanged.connect(self._on_ctrl_dock_visibility) + # ── Namespace dock ─────────────────────────────────────────────── + self._namespace = NamespacePanel(self.registry, self.processor) + self._namespace.setMinimumWidth(260) + + self._namespace_dock = QDockWidget("Namespace", self) + self._namespace_dock.setObjectName("namespaceDock") + self._namespace_dock.setWidget(self._namespace) + self._namespace_dock.setFeatures( + QDockWidget.DockWidgetFeature.DockWidgetMovable | + QDockWidget.DockWidgetFeature.DockWidgetClosable + ) + self._namespace_dock.setAllowedAreas( + Qt.DockWidgetArea.LeftDockWidgetArea | + Qt.DockWidgetArea.RightDockWidgetArea + ) + self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self._namespace_dock) + self._namespace_dock.setTitleBarWidget(_DockTitleBar(self._namespace_dock, "NAMESPACE")) + self._namespace_dock.visibilityChanged.connect(self._on_namespace_dock_visibility) + self._namespace_dock.hide() # closed by default — opt-in config tool, not shown on startup + sb = QStatusBar(); self.setStatusBar(sb) self._status = QLabel("Ready"); sb.addWidget(self._status) self._log_lbl = QLabel(""); sb.addPermanentWidget(self._log_lbl) @@ -303,9 +337,24 @@ class MainWindow(QMainWindow): self._ctrl_dock.show() self._ctrl_dock.raise_() + def _on_namespace_dock_visibility(self, visible: bool): + if hasattr(self, "_act_namespace"): + self._act_namespace.setChecked(visible) + + def _on_view_namespace(self, checked: bool): + if checked: + self._namespace_dock.show(); self._namespace_dock.raise_() + else: + self._namespace_dock.hide() + + def _show_namespace_panel(self): + self._namespace_dock.show() + self._namespace_dock.raise_() + def _connect_signals(self): self.engine.new_data.connect(self.processor.on_raw_batch) self.processor.processed_data.connect(self._chart.on_new_data) + self.processor.processed_data.connect(self._namespace.on_processed_data) self.engine.channel_unit_changed.connect(self._chart.refresh_pane_unit) self.engine.log_started.connect(lambda p: self._log_lbl.setText(f"● {p}")) self.engine.log_stopped.connect(lambda p: self._log_lbl.setText(f"✓ {p}")) |
