fix(gui): retours Dom GUI V6 — thème, Administration, Règles, aide

Cinq retours utilisateur sur l'exécutable Windows GUI V6.

- Thème : `_render()` vidait les widgets mais conservait le cache
  `_tab_frames`/`_visible_tab` → l'onglet Utilisation se vidait (TclError
  sur widget détruit) au changement de thème. Reset du cache dans
  `_render()` → onglet actif recréé proprement.
- Onglet principal « Configuration » → « Administration » (clé interne
  inchangée).
- Sous-onglet « Règles  2 » → « Règles » (le « 2 » était un badge non
  câblé).
- Actions de maquette non câblées (Partage Export/Import, Règles Nouvelle
  règle/Recharger/Tester/Fermer) désactivées + suffixe « (à venir) » via
  `_mockup_button` : plus aucune action morte qui semble fonctionner.
- Aide « ? » restaurée (façon V5) : `ui_kit.HelpButton`/`help_button`
  réutilisable ouvrant une fenêtre d'aide en français simple, posée sur
  Utilisation, Administration (Réglages/Masquage/Partage/Règles) et
  À propos. Partage : phrase visible + aide expliquant qu'on partage les
  réglages, jamais les documents patients.

`tests/unit/test_gui_v6_app_shell.py` : régression thème, libellés,
présence d'aide, navigation. 228 tests unit OK (0 régression), self-test
GUI V6 OK. V5/moteur/app_aivanov non touchés, aucune dépendance ajoutée.
Verdict Qwen requis avant push/build/diffusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 16:39:53 +02:00
parent 13b79db417
commit 6a0a5811a5
6 changed files with 328 additions and 9 deletions

View File

@@ -146,3 +146,88 @@ class ToggleRow(ctk.CTkFrame):
def get(self) -> bool:
return bool(self.var.get())
class HelpButton(ctk.CTkButton):
"""Petit bouton « ? » ouvrant une fenêtre d'aide en français simple.
Restaure l'affordance d'aide de la V5 (``ToolTip`` / « Comment ça marche ? »)
pour les utilisateurs non informaticiens.
"""
def __init__(self, master, palette: dict, text: str, *, title: str = "Aide", **kwargs):
self._palette = palette
self._help_text = text
self._help_title = title
self._window = None
super().__init__(
master,
text="?",
command=self.open_help,
width=26,
height=26,
corner_radius=13,
fg_color=palette["btn_sec_bg"],
hover_color=palette["card_border"],
text_color=palette["text_dim"],
border_color=palette["btn_sec_border"],
border_width=1,
font=font(13, "bold"),
**kwargs,
)
def open_help(self):
if self._window is not None:
try:
if self._window.winfo_exists():
self._window.lift()
self._window.focus_force()
return self._window
except Exception:
pass
p = self._palette
win = ctk.CTkToplevel(self)
win.title(self._help_title)
win.geometry("480x380")
win.minsize(360, 240)
try:
win.configure(fg_color=p["bg"])
except Exception:
pass
ctk.CTkLabel(
win, text=self._help_title, text_color=p["text"], font=font(15, "bold"), anchor="w"
).pack(fill="x", padx=16, pady=(14, 4))
box = ctk.CTkScrollableFrame(win, fg_color=p["card"])
box.pack(fill="both", expand=True, padx=12, pady=(0, 8))
ctk.CTkLabel(
box,
text=self._help_text,
text_color=p["text_dim"],
font=font(12),
justify="left",
wraplength=420,
anchor="w",
).pack(fill="x", padx=10, pady=10)
ctk.CTkButton(
win,
text="Fermer",
command=win.destroy,
fg_color=p["btn_sec_bg"],
hover_color=p["card_border"],
text_color=p["text"],
border_color=p["btn_sec_border"],
border_width=1,
corner_radius=CARD_RADIUS,
height=30,
).pack(padx=12, pady=(0, 12))
try:
win.transient(self.winfo_toplevel())
win.after(120, lambda: (win.lift(), win.focus_force()))
except Exception:
pass
self._window = win
return win
def help_button(master, palette: dict, text: str, title: str = "Aide") -> "HelpButton":
return HelpButton(master, palette, text, title=title)