Modulo 1: editor interactivo de tabla de offsets (Task 10)
- offsets_editor.py: OffsetsEditor (QTableWidget editable con zoom de celdas modificadas en ambar, invalidas en rojo; Aplicar reconstruye Hull y emite hull_changed; importar/exportar CSV; info bar con dimensiones). - main_window.py: OffsetsEditor inyectado como MOD_OFFSETS (F4); _load_hull_viewers recibe _skip_offsets_editor para evitar bucle; _on_hull_changed_from_editor propaga el Hull editado a todos los visores y al panel de hidrostáticos en vivo; ModuleArea.set_module_widget() para reemplazar placeholders en tiempo de setup. 86 tests pasan sin regresiones. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -633,6 +633,17 @@ class ModuleArea(QStackedWidget):
|
||||
lo.addWidget(sub)
|
||||
return w
|
||||
|
||||
def set_module_widget(self, idx: int, widget: QWidget) -> None:
|
||||
"""Sustituye el placeholder de un modulo por el widget real.
|
||||
|
||||
Preserva el indice: los modulos con indice mayor no se desplazan.
|
||||
"""
|
||||
old = self.widget(idx)
|
||||
if old is not None:
|
||||
self.removeWidget(old)
|
||||
old.deleteLater()
|
||||
self.insertWidget(idx, widget)
|
||||
|
||||
def activate(self, module_index: int) -> None:
|
||||
if 0 <= module_index < self.count():
|
||||
self.setCurrentIndex(module_index)
|
||||
@@ -849,6 +860,12 @@ class MainWindow(QMainWindow):
|
||||
if _vp is not None:
|
||||
_vp.set_canvas(_widget)
|
||||
|
||||
# Editor interactivo de offsets (sustituye el placeholder MOD_OFFSETS)
|
||||
from arshipdesign.ui.widgets.offsets_editor import OffsetsEditor
|
||||
self._offsets_editor = OffsetsEditor()
|
||||
self._offsets_editor.hull_changed.connect(self._on_hull_changed_from_editor)
|
||||
self._module_area.set_module_widget(ModuleArea.MOD_OFFSETS, self._offsets_editor)
|
||||
|
||||
# Dock izquierdo — capas
|
||||
self._layers_panel = LayersPanel(self._strings)
|
||||
self._dock_layers = QDockWidget("Capas", self)
|
||||
@@ -1266,16 +1283,19 @@ class MainWindow(QMainWindow):
|
||||
self._update_title()
|
||||
self._layers_panel.set_project(self._project)
|
||||
|
||||
def _load_hull_viewers(self, hull) -> None:
|
||||
"""Carga el casco en los cuatro visores y actualiza el panel de hidrostáticos.
|
||||
def _load_hull_viewers(self, hull, *, _skip_offsets_editor: bool = False) -> None:
|
||||
"""Carga el casco en todos los visores (2D, 3D, offsets) y actualiza hidrostáticos.
|
||||
|
||||
Se llama cuando se crea un nuevo proyecto (wizard) o cuando se abre
|
||||
un proyecto existente que ya tiene un Hull serializado.
|
||||
``_skip_offsets_editor=True`` evita el bucle de retroalimentacion cuando
|
||||
la llamada proviene del propio editor de offsets.
|
||||
"""
|
||||
# ── Visores 2D ────────────────────────────────────────────
|
||||
self._viewer_bodyplan.set_hull(hull)
|
||||
self._viewer_profile.set_hull(hull)
|
||||
self._viewer_plan.set_hull(hull)
|
||||
# ── Editor de offsets ─────────────────────────────────────
|
||||
if not _skip_offsets_editor:
|
||||
self._offsets_editor.set_hull(hull)
|
||||
# ── Visor 3D ──────────────────────────────────────────────
|
||||
if self._viewer_3d is not None:
|
||||
try:
|
||||
@@ -1285,6 +1305,13 @@ class MainWindow(QMainWindow):
|
||||
# ── Panel hidrostáticos ───────────────────────────────────
|
||||
self._update_hydrostatics(hull)
|
||||
|
||||
def _on_hull_changed_from_editor(self, hull) -> None:
|
||||
"""Slot: el editor de offsets reconstruyo el Hull — propagar a los demas visores."""
|
||||
self._current_hull = hull
|
||||
# _skip_offsets_editor=True para no re-poblar la tabla (ya esta actualizada)
|
||||
self._load_hull_viewers(hull, _skip_offsets_editor=True)
|
||||
self.statusBar().showMessage(f"Offsets actualizados — {hull.name}")
|
||||
|
||||
def _update_hydrostatics(self, hull) -> None:
|
||||
"""Calcula hidrostáticos al calado de diseño y actualiza la barra inferior.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user