summaryrefslogtreecommitdiff
path: root/ui/main_window.py
diff options
context:
space:
mode:
Diffstat (limited to 'ui/main_window.py')
-rw-r--r--ui/main_window.py93
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}"))