"""État de configuration de la GUI V6 (G3-B), testable sans display ni fichiers. Détient les options simples exposées par l'onglet Configuration et sait produire des :class:`EngineSettings`. La résolution des profils s'appuie sur ``profile_defaults`` (jamais modifié) avec injection possible pour les tests. """ from __future__ import annotations from dataclasses import dataclass from pathlib import Path from typing import Callable, List, Optional from gui_v6.engine_bridge import EngineSettings @dataclass class ConfigState: """Options de configuration utilisateur (réglages simples G3-B).""" profile: Optional[str] = None raster_burn: bool = True use_local_ner: bool = True enable_eds: bool = False enable_gliner: bool = False output_dir: Optional[Path] = None ogc_label: Optional[str] = None manual_mask_required: bool = False manual_mask_template: Optional[Path] = None mask_color: str = "#000000" mask_marker_style: str = "brackets" mask_margin_x: int = 2 mask_margin_y: int = 1 mask_rounded_corners: bool = False def to_engine_settings(self, config_path: Optional[Path] = None) -> EngineSettings: return EngineSettings( make_vector_redaction=False, also_make_raster_burn=self.raster_burn, config_path=config_path, use_local_ner=self.use_local_ner, enable_eds=self.enable_eds, enable_gliner=self.enable_gliner, ogc_label=self.ogc_label, profile=self.profile, ) def list_profile_keys(lister: Optional[Callable[[], dict]] = None) -> List[str]: """Liste triée des clés de profils. Best-effort : [] si indisponible.""" if lister is None: from profile_defaults import list_effective_profiles lister = list_effective_profiles try: return sorted(lister().keys()) except Exception: return [] def default_profile_key(getter: Optional[Callable[[], str]] = None) -> Optional[str]: """Clé du profil par défaut, ou None si indisponible.""" if getter is None: from profile_defaults import get_default_profile_key getter = get_default_profile_key try: return getter() except Exception: return None