v0.1-sprint0: Esqueleto completo AR-ShipDesign

- Estructura completa de carpetas (236 módulos stub + implementados)
- pyproject.toml, requirements, .gitignore, LICENSE (propietario)
- core/project.py: serialización .arsd (ZIP con JSON)
- core/units.py: conversiones SI <-> imperial completas
- ui/main_window.py: layout DELFTship-style con todos los paneles
  - Árbol de proyecto (dock izquierda)
  - Tabs de módulos (centro)
  - Panel de propiedades (dock derecha)
  - Panel hidrostáticos en vivo (inferior, fijo)
- ui/i18n: español e inglés
- ui/themes: tema claro y oscuro
- utils/logger.py, settings.py, validation.py
- data/liquids.json: 15 líquidos navales
- data/stability_criteria.json: IMO IS Code 2008, A.749(18), USCG
- tests/test_startup.py: 12 tests, todos PASSED
- Módulo scantling/ ISO 12215 (stubs Sprint 2.5)
- Módulo fabrication/molds/ para moldes FRP (stubs Sprint 13B)
- Módulo fabrication/ para CNC plasma/router/laser (stubs Sprint 13)
This commit is contained in:
2026-05-26 22:10:18 -04:00
commit 0dbc2a4518
266 changed files with 4249 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
"""
Gestión de configuración de usuario con QSettings.
Persiste preferencias: idioma, tema, unidades, archivos recientes, etc.
"""
from __future__ import annotations
from PySide6.QtCore import QSettings
APP_NAME = "ARShipDesign"
ORG_NAME = "AlvaroRodriguez"
# Claves de configuración
KEY_LANGUAGE = "ui/language"
KEY_THEME = "ui/theme"
KEY_UNITS = "ui/units"
KEY_RECENT_FILES = "project/recentFiles"
KEY_MAX_RECENT = "project/maxRecentFiles"
KEY_WINDOW_GEOMETRY = "ui/windowGeometry"
KEY_WINDOW_STATE = "ui/windowState"
KEY_HYDRO_DENSITY = "calc/waterDensity"
KEY_LOG_LEVEL = "system/logLevel"
def get_settings() -> QSettings:
"""Retorna la instancia de QSettings de la aplicación."""
return QSettings(ORG_NAME, APP_NAME)
def get_language() -> str:
s = get_settings()
return s.value(KEY_LANGUAGE, "es")
def set_language(lang: str) -> None:
s = get_settings()
s.setValue(KEY_LANGUAGE, lang)
def get_theme() -> str:
s = get_settings()
return s.value(KEY_THEME, "dark")
def set_theme(theme: str) -> None:
s = get_settings()
s.setValue(KEY_THEME, theme)
def get_units() -> str:
"""'si' o 'imperial'"""
s = get_settings()
return s.value(KEY_UNITS, "si")
def set_units(units: str) -> None:
s = get_settings()
s.setValue(KEY_UNITS, units)
def get_recent_files() -> list[str]:
s = get_settings()
val = s.value(KEY_RECENT_FILES, [])
if isinstance(val, str):
return [val]
return list(val) if val else []
def add_recent_file(path: str) -> None:
s = get_settings()
recent = get_recent_files()
if path in recent:
recent.remove(path)
recent.insert(0, path)
max_recent = int(s.value(KEY_MAX_RECENT, 10))
recent = recent[:max_recent]
s.setValue(KEY_RECENT_FILES, recent)
def get_water_density() -> float:
"""Densidad del agua de mar en kg/m³ (por defecto 1025)."""
s = get_settings()
return float(s.value(KEY_HYDRO_DENSITY, 1025.0))
def get_log_level() -> str:
s = get_settings()
return s.value(KEY_LOG_LEVEL, "INFO")