"""Studio main window (PySide6) -- Sprint 2.5. Three areas: - Sidebar (left) -- user + role + capabilities they hold. - Central tab area -- Flash Console (Sprint 2.5) + placeholders for the project configurator that lands in Sprint 4. - Status bar -- session info + audit log path. """ from __future__ import annotations from PySide6.QtCore import Qt from PySide6.QtWidgets import ( QLabel, QListWidget, QMainWindow, QSplitter, QStatusBar, QTabWidget, QTextEdit, QVBoxLayout, QWidget, ) from arautopilot.core.rbac import capabilities_of from arautopilot.studio.editors.project_editor import ProjectEditorWidget from arautopilot.studio.flash_console import FlashConsoleWidget from arautopilot.studio.session import Session from arautopilot.version import __version__ class StudioMainWindow(QMainWindow): """Top-level Studio window.""" def __init__(self, session: Session) -> None: super().__init__() self._session = session self.setWindowTitle( f"AR-Autopilot Studio v{__version__} -- " f"{session.user.display_name} ({session.role.value})" ) self.resize(1100, 700) splitter = QSplitter(Qt.Orientation.Horizontal) splitter.addWidget(self._build_sidebar()) splitter.addWidget(self._build_central()) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1) splitter.setSizes([260, 840]) self.setCentralWidget(splitter) status = QStatusBar(self) status.showMessage(f"Audit log: {session.audit.path}") self.setStatusBar(status) # ----- UI ------------------------------------------------------------ def _build_sidebar(self) -> QWidget: w = QWidget() layout = QVBoxLayout(w) layout.setContentsMargins(8, 8, 8, 8) layout.addWidget(QLabel( f"{self._session.user.display_name}
" f"{self._session.role.value}" )) layout.addWidget(QLabel("Capabilities")) caps = QListWidget() for cap in sorted(capabilities_of(self._session.role), key=lambda c: c.value): caps.addItem(cap.value) layout.addWidget(caps, stretch=1) return w def _build_central(self) -> QWidget: tabs = QTabWidget() tabs.addTab(self._build_overview_tab(), "Overview") tabs.addTab(FlashConsoleWidget(self._session), "Flash Console") tabs.addTab(ProjectEditorWidget(self._session), "Project") tabs.addTab(self._placeholder_tab( "Telemetry -- Sprint 4.\n\n" "Live Modbus telemetry from the connected AR-NMEA-IO board." ), "Telemetry") return tabs def _build_overview_tab(self) -> QWidget: w = QWidget() layout = QVBoxLayout(w) layout.addWidget(QLabel( "

AR-Autopilot Studio

" "

Welcome. Use the Flash Console tab to compile and " "flash firmware to an AR-NMEA-IO board.

" "

The Project tab (Sprint 4) will let you configure a " "vessel and produce a deployable .appack.

" "

Every action you take is recorded in the audit log " "(see status bar at the bottom).

" )) layout.addStretch(1) return w def _placeholder_tab(self, text: str) -> QWidget: w = QWidget() layout = QVBoxLayout(w) edit = QTextEdit() edit.setReadOnly(True) edit.setPlainText(text) layout.addWidget(edit) return w