feat(gui): câbler les 7 toggles catégories au moteur (P1-2)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,36 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Callable, List, Optional
|
||||
from typing import Callable, FrozenSet, List, Optional
|
||||
|
||||
from gui_v6.engine_bridge import EngineSettings
|
||||
|
||||
# Mapping centralisé champ ConfigState → CATÉGORIE moteur (Plan 1b / P1-2).
|
||||
#
|
||||
# Les 7 catégories doivent matcher EXACTEMENT le set accepté par
|
||||
# ``anonymizer_core_refactored_onnx.process_pdf(disabled_kinds=...)`` :
|
||||
# {"NOM", "DATE_NAISSANCE", "ETAB", "ADRESSE", "NIR", "TEL", "ADHERENT"}.
|
||||
#
|
||||
# Sémantique des booléens ``detect_*`` : True = « détecter cette catégorie »
|
||||
# (= masquer, comportement par défaut). False = laisser en clair → la catégorie
|
||||
# entre dans ``disabled_kinds``. Note : CODE_POSTAL suit le toggle ADRESSE côté
|
||||
# moteur (décision Dom 2026-06-26), aucun toggle dédié n'est exposé.
|
||||
#
|
||||
# L'ordre suit les 7 lignes de ``tab_config._DETECTION_OPTIONS`` :
|
||||
# Noms/prénoms · Dates de naissance · Établissements · Adresses/CP ·
|
||||
# N° sécurité sociale · Téléphones/e-mails · N° adhérent mutuelle.
|
||||
CATEGORY_FIELDS = {
|
||||
"detect_nom": "NOM",
|
||||
"detect_date_naissance": "DATE_NAISSANCE",
|
||||
"detect_etab": "ETAB",
|
||||
"detect_adresse": "ADRESSE",
|
||||
"detect_nir": "NIR",
|
||||
"detect_tel": "TEL",
|
||||
"detect_adherent": "ADHERENT",
|
||||
}
|
||||
# Catégories canoniques (ordre = ordre des toggles UI).
|
||||
DETECTION_CATEGORIES = tuple(CATEGORY_FIELDS.values())
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConfigState:
|
||||
@@ -33,6 +59,26 @@ class ConfigState:
|
||||
mask_margin_y: int = 1
|
||||
mask_rounded_corners: bool = False
|
||||
|
||||
# 7 toggles « Données à détecter » — tous ON par défaut (zéro changement).
|
||||
detect_nom: bool = True
|
||||
detect_date_naissance: bool = True
|
||||
detect_etab: bool = True
|
||||
detect_adresse: bool = True
|
||||
detect_nir: bool = True
|
||||
detect_tel: bool = True
|
||||
detect_adherent: bool = True
|
||||
|
||||
def disabled_kinds(self) -> FrozenSet[str]:
|
||||
"""Set des CATÉGORIES décochées (laissées en clair).
|
||||
|
||||
Défaut (tous les toggles ON) ⇒ ``frozenset()`` (no-op moteur).
|
||||
"""
|
||||
return frozenset(
|
||||
category
|
||||
for field_name, category in CATEGORY_FIELDS.items()
|
||||
if not getattr(self, field_name)
|
||||
)
|
||||
|
||||
def to_engine_settings(self, config_path: Optional[Path] = None) -> EngineSettings:
|
||||
return EngineSettings(
|
||||
make_vector_redaction=False,
|
||||
@@ -43,6 +89,7 @@ class ConfigState:
|
||||
enable_gliner=self.enable_gliner,
|
||||
ogc_label=self.ogc_label,
|
||||
profile=self.profile,
|
||||
disabled_kinds=self.disabled_kinds(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ Aucune logique de détection ici : on orchestre uniquement.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, Optional
|
||||
from typing import Any, Callable, Dict, FrozenSet, Optional
|
||||
|
||||
from engine_capabilities import capabilities_map
|
||||
|
||||
@@ -61,6 +61,9 @@ class EngineSettings:
|
||||
enable_gliner: bool = False
|
||||
ogc_label: Optional[str] = None
|
||||
profile: Optional[str] = None
|
||||
# Plan 1b (P1-2) — set des CATÉGORIES laissées en clair (toggles décochés).
|
||||
# Vide par défaut ⇒ aucun changement de comportement (tout est masqué).
|
||||
disabled_kinds: FrozenSet[str] = field(default_factory=frozenset)
|
||||
|
||||
|
||||
def _default_factories() -> dict[str, ManagerFactory]:
|
||||
@@ -206,6 +209,8 @@ def build_engine_kwargs(
|
||||
"also_make_raster_burn": settings.also_make_raster_burn,
|
||||
"config_path": settings.config_path,
|
||||
"ogc_label": settings.ogc_label,
|
||||
# Plan 1b (P1-2) — catégories décochées laissées en clair (set vide = no-op).
|
||||
"disabled_kinds": frozenset(settings.disabled_kinds or ()),
|
||||
}
|
||||
if managers is not None and settings.use_local_ner:
|
||||
kwargs.update(managers.as_kwargs())
|
||||
|
||||
@@ -26,14 +26,17 @@ _SUBTABS = [
|
||||
("shr", "🔄 Partage"),
|
||||
]
|
||||
|
||||
# Chaque ligne = (libellé, aide, champ ConfigState). Le champ relie le toggle
|
||||
# à la catégorie moteur (cf. gui_v6.config_state.CATEGORY_FIELDS). ON = détecter
|
||||
# (masquer) ; OFF = laisser en clair (entre dans disabled_kinds).
|
||||
_DETECTION_OPTIONS = [
|
||||
("Noms et prénoms", "Annuaire + IA"),
|
||||
("Dates de naissance", "Contexte naissance"),
|
||||
("Établissements", "FINESS + contexte"),
|
||||
("Adresses / CP", "Voie, ville, code"),
|
||||
("N° sécurité sociale", "NIR"),
|
||||
("Téléphones / e-mails", "Contact"),
|
||||
("N° adhérent mutuelle", "Identifiant local"),
|
||||
("Noms et prénoms", "Annuaire + IA", "detect_nom"),
|
||||
("Dates de naissance", "Contexte naissance", "detect_date_naissance"),
|
||||
("Établissements", "FINESS + contexte", "detect_etab"),
|
||||
("Adresses / CP", "Voie, ville, code", "detect_adresse"),
|
||||
("N° sécurité sociale", "NIR", "detect_nir"),
|
||||
("Téléphones / e-mails", "Contact", "detect_tel"),
|
||||
("N° adhérent mutuelle", "Identifiant local", "detect_adherent"),
|
||||
]
|
||||
|
||||
_MASK_COLORS = [
|
||||
@@ -353,8 +356,20 @@ class ConfigTab(ctk.CTkFrame):
|
||||
help_text=_HELP_DONNEES_DETECTER, help_title="Données à détecter",
|
||||
)
|
||||
det.pack(fill="both", expand=True)
|
||||
for label, hint in _DETECTION_OPTIONS:
|
||||
self._mini_toggle(det, label, hint, value=True).pack(fill="x", padx=12, pady=1)
|
||||
# Les 7 toggles « Données à détecter » sont câblés sur les booléens
|
||||
# detect_* de ConfigState (lecture initiale + écriture au changement).
|
||||
# ON = détecter/masquer ; OFF = laisser en clair (→ disabled_kinds).
|
||||
self._detect_toggles: dict[str, object] = {}
|
||||
for label, hint, field_name in _DETECTION_OPTIONS:
|
||||
toggle = self._mini_toggle(
|
||||
det,
|
||||
label,
|
||||
hint,
|
||||
value=bool(getattr(self._state, field_name)),
|
||||
command=lambda f=field_name: self._on_detect_toggle(f),
|
||||
)
|
||||
toggle.pack(fill="x", padx=12, pady=1)
|
||||
self._detect_toggles[field_name] = toggle
|
||||
|
||||
ner = ui_kit.Card(
|
||||
cols[1], p, title="🧠 Moteurs et masques",
|
||||
@@ -865,6 +880,16 @@ class ConfigTab(ctk.CTkFrame):
|
||||
def _on_profile(self, value: str) -> None:
|
||||
self._state.profile = value
|
||||
|
||||
def _on_detect_toggle(self, field_name: str) -> None:
|
||||
"""Recopie l'état d'un toggle « Données à détecter » dans ConfigState.
|
||||
|
||||
ON = détecter (masquer) ; OFF = laisser en clair. ``disabled_kinds()``
|
||||
de ConfigState dérive ensuite le set des catégories désactivées.
|
||||
"""
|
||||
toggle = self._detect_toggles.get(field_name)
|
||||
if toggle is not None:
|
||||
setattr(self._state, field_name, bool(toggle.get()))
|
||||
|
||||
def _on_ner(self) -> None:
|
||||
self._state.use_local_ner = self._tog_ner.get()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user