"""Paso 4: selección de sistemas habilitados. Lee el catálogo maestro de sistemas y muestra checkboxes agrupados por categoría. Pre-selecciona los sistemas marcados como `default_for` el VesselType del paso 1. """ from __future__ import annotations from PySide6.QtWidgets import ( QCheckBox, QFrame, QGridLayout, QGroupBox, QLabel, QPushButton, QScrollArea, QVBoxLayout, QWidget, QWizardPage, ) from vmssailor.library import load_systems_catalog from vmssailor.studio.theme import C_FOG, ui_font class Step04Systems(QWizardPage): def __init__(self, parent: QWidget | None = None) -> None: super().__init__(parent) self.setTitle("Paso 4 · Sistemas instalados") self.setSubTitle( "Marca los sistemas que tendrá el buque. Esto define el menú lateral del Runtime y " "qué tags se generarán en sprints siguientes." ) outer = QVBoxLayout(self) outer.setSpacing(10) header = QLabel( "Pre-selección automática según tipo de buque. Ajusta marcando/desmarcando." ) header.setWordWrap(True) header.setStyleSheet(f"color: {C_FOG};") header.setFont(ui_font(10)) outer.addWidget(header) # Buttons row btn_row = QGridLayout() self._btn_select_defaults = QPushButton("Resetear a defaults del tipo") self._btn_select_all = QPushButton("Marcar todos") self._btn_select_none = QPushButton("Desmarcar todos") btn_row.addWidget(self._btn_select_defaults, 0, 0) btn_row.addWidget(self._btn_select_all, 0, 1) btn_row.addWidget(self._btn_select_none, 0, 2) outer.addLayout(btn_row) self._btn_select_defaults.clicked.connect(self._select_defaults) self._btn_select_all.clicked.connect(self._select_all) self._btn_select_none.clicked.connect(self._select_none) # Scroll area with category groups scroll = QScrollArea() scroll.setWidgetResizable(True) scroll.setFrameShape(QFrame.Shape.NoFrame) outer.addWidget(scroll, 1) content = QWidget() self._content_layout = QVBoxLayout(content) self._content_layout.setSpacing(14) scroll.setWidget(content) # Build categories self._checkboxes: dict[str, QCheckBox] = {} self._catalog = self._load_catalog_safe() self._build_categories() # Register field from vmssailor.studio.wizard.wizard import F_SYSTEMS self.registerField(F_SYSTEMS, self, "enabled_systems", "systemsChanged") # ----- Property API ------------------------------------------------ from PySide6.QtCore import Property, Signal systemsChanged = Signal() def get_enabled_systems(self) -> list[str]: return [sid for sid, cb in self._checkboxes.items() if cb.isChecked()] def set_enabled_systems(self, value: list[str]) -> None: for sid, cb in self._checkboxes.items(): cb.setChecked(sid in value) self.systemsChanged.emit() enabled_systems = Property( list, fget=get_enabled_systems, fset=set_enabled_systems, notify=systemsChanged, ) # ----- Internals --------------------------------------------------- def _load_catalog_safe(self) -> dict: try: return load_systems_catalog() except Exception: return {"categories": []} def _build_categories(self) -> None: for cat in self._catalog.get("categories", []): group = QGroupBox(cat.get("name", "—")) grid = QGridLayout(group) grid.setHorizontalSpacing(20) grid.setVerticalSpacing(6) for idx, sys in enumerate(cat.get("systems", [])): cb = QCheckBox(sys.get("name", sys["id"])) cb.setToolTip(f"id: {sys['id']}") cb.stateChanged.connect(self.systemsChanged.emit) self._checkboxes[sys["id"]] = cb grid.addWidget(cb, idx // 3, idx % 3) self._content_layout.addWidget(group) self._content_layout.addStretch(1) def _system_default_for(self, sys_id: str) -> list[str]: for cat in self._catalog.get("categories", []): for s in cat.get("systems", []): if s.get("id") == sys_id: return s.get("default_for", []) return [] def _select_defaults(self) -> None: from vmssailor.studio.wizard.wizard import F_VESSEL_TYPE v_type = self.field(F_VESSEL_TYPE) if not v_type: return for sid, cb in self._checkboxes.items(): cb.setChecked(v_type in self._system_default_for(sid)) def _select_all(self) -> None: for cb in self._checkboxes.values(): cb.setChecked(True) def _select_none(self) -> None: for cb in self._checkboxes.values(): cb.setChecked(False) def initializePage(self) -> None: # On first entry, pre-select defaults for the chosen vessel type. if not any(cb.isChecked() for cb in self._checkboxes.values()): self._select_defaults()