feat(gui): addenda Dom GUI V6 — sous-onglet Profils, libellés, aide, bêta
Suite des retours Dom sur la GUI V6 (par-dessus 6a0a581).
Addendum Profils / Réglages :
- Nouveau sous-onglet Administration « 👤 Profils » : le profil actif devient
un objet lisible (nom, description, masque requis, template, listes locales
avec compteurs) — données réelles lues depuis profile_defaults.
- Fenêtre « Tableau des termes » (terms_table_window.py) : table scrollable
avec recherche/filtre, colonnes Type/Terme/Source ; reste lisible à 50+
termes. Ajouter/éditer/supprimer désactivés « (à venir) » (écriture par
profil non câblée).
- Réglages : « Profil métier » → « Profil d'anonymisation », « Sortie… » →
« Dossier de sortie… » (+ infobulle), hints moteurs (standard/optionnel/
plus lent), bouton « Voir le profil », « Ouvrir le tableau des termes ».
- Aide « ? » + infobulles (ui_kit.attach_tooltip) près des éléments ambigus.
- profile_view.py : logique pure (résumé profil + lignes du tableau),
testable sans display.
Addendum bêta : en-tête « aivanonym » + badge « bêta », titre fenêtre
« … — bêta ». Détail version conservé dans À propos.
tests/unit/test_gui_v6_profiles.py + ajouts shell. 237 tests unit OK
(228 → 237, 0 régression), self-test GUI V6 OK, navigation des 5 sous-onglets
+ thème OK. V5/moteur/app_aivanov/profile_defaults non touchés, 0 dépendance.
Aucun build/push sans GO Dom — validation visuelle Dom attendue.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
114
gui_v6/terms_table_window.py
Normal file
114
gui_v6/terms_table_window.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""Fenêtre « Tableau des termes » d'un profil (lisible même avec 50+ termes).
|
||||
|
||||
Table scrollable avec recherche/filtre — colonnes Type / Terme / Source (profil).
|
||||
Lecture seule pour l'instant : ajouter/supprimer/éditer sont désactivés et
|
||||
marqués « (à venir) » (l'écriture par profil n'est pas encore câblée).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tkinter as tk
|
||||
from typing import Optional
|
||||
|
||||
import customtkinter as ctk
|
||||
|
||||
from gui_v6 import ui_kit
|
||||
from gui_v6.profile_view import filter_term_rows
|
||||
|
||||
_TYPE_COLORS = {
|
||||
"À conserver": "success",
|
||||
"À masquer": "primary",
|
||||
"À ignorer": "text_muted",
|
||||
}
|
||||
|
||||
|
||||
class TermsTableWindow(ctk.CTkToplevel):
|
||||
def __init__(
|
||||
self,
|
||||
master,
|
||||
palette: dict,
|
||||
rows,
|
||||
*,
|
||||
title: str = "Tableau des termes",
|
||||
profile_label: str = "",
|
||||
) -> None:
|
||||
super().__init__(master)
|
||||
self._palette = palette
|
||||
self._rows = list(rows)
|
||||
self._profile_label = profile_label
|
||||
self._visible = list(self._rows)
|
||||
|
||||
self.title(title)
|
||||
self.geometry("740x560")
|
||||
self.minsize(520, 360)
|
||||
try:
|
||||
self.configure(fg_color=palette["bg"])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self._query = tk.StringVar()
|
||||
self._count_text = tk.StringVar(value="")
|
||||
self._build()
|
||||
self._refresh()
|
||||
try:
|
||||
self.transient(master)
|
||||
self.after(120, lambda: (self.lift(), self.focus_force()))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# -- coutures testables --------------------------------------------------
|
||||
def set_query(self, query: str) -> None:
|
||||
self._query.set(query)
|
||||
self._refresh()
|
||||
|
||||
def visible_count(self) -> int:
|
||||
return len(self._visible)
|
||||
|
||||
def add_is_disabled(self) -> bool:
|
||||
return str(self._add_btn.cget("state")) == "disabled"
|
||||
|
||||
# -- UI ------------------------------------------------------------------
|
||||
def _build(self) -> None:
|
||||
p = self._palette
|
||||
head = ctk.CTkFrame(self, fg_color="transparent")
|
||||
head.pack(fill="x", padx=12, pady=(12, 4))
|
||||
title = "Termes du profil"
|
||||
if self._profile_label:
|
||||
title += f" « {self._profile_label} »"
|
||||
ctk.CTkLabel(head, text=title, text_color=p["text"], font=ui_kit.font(15, "bold")).pack(side="left")
|
||||
|
||||
bar = ctk.CTkFrame(self, fg_color="transparent")
|
||||
bar.pack(fill="x", padx=12, pady=(0, 6))
|
||||
ctk.CTkLabel(bar, text="🔎 Rechercher :", text_color=p["text_dim"], font=ui_kit.font(12)).pack(side="left")
|
||||
entry = ctk.CTkEntry(bar, textvariable=self._query, width=240)
|
||||
entry.pack(side="left", padx=6)
|
||||
self._query.trace_add("write", lambda *_: self._refresh())
|
||||
self._add_btn = ui_kit.secondary_button(bar, p, "+ Ajouter (à venir)", command=lambda: None)
|
||||
self._add_btn.configure(state="disabled")
|
||||
self._add_btn.pack(side="right")
|
||||
|
||||
header = ctk.CTkFrame(self, fg_color=p["card"], corner_radius=6)
|
||||
header.pack(fill="x", padx=12)
|
||||
for text, width in [("TYPE", 130), ("TERME", 360), ("SOURCE (PROFIL)", 180)]:
|
||||
ctk.CTkLabel(header, text=text, width=width, anchor="w", text_color=p["text_muted"], font=ui_kit.font(10, "bold")).pack(side="left", padx=8, pady=4)
|
||||
|
||||
self._table = ctk.CTkScrollableFrame(self, fg_color=p["bg"])
|
||||
self._table.pack(fill="both", expand=True, padx=12, pady=(2, 4))
|
||||
|
||||
ctk.CTkLabel(self, textvariable=self._count_text, text_color=p["text_muted"], font=ui_kit.font(11), anchor="w").pack(fill="x", padx=14, pady=(0, 10))
|
||||
|
||||
def _refresh(self) -> None:
|
||||
p = self._palette
|
||||
self._visible = filter_term_rows(self._rows, self._query.get())
|
||||
for child in self._table.winfo_children():
|
||||
child.destroy()
|
||||
if not self._visible:
|
||||
ctk.CTkLabel(self._table, text="Aucun terme.", text_color=p["text_muted"], font=ui_kit.font(12)).pack(anchor="w", padx=8, pady=8)
|
||||
for type_label, term, source in self._visible:
|
||||
row = ctk.CTkFrame(self._table, fg_color="transparent")
|
||||
row.pack(fill="x", pady=1)
|
||||
color = p[_TYPE_COLORS.get(type_label, "text")]
|
||||
ctk.CTkLabel(row, text=type_label, width=130, anchor="w", text_color=color, font=ui_kit.font(11, "bold")).pack(side="left", padx=8)
|
||||
ctk.CTkLabel(row, text=term, width=360, anchor="w", text_color=p["text"], font=ui_kit.font(12)).pack(side="left", padx=8)
|
||||
ctk.CTkLabel(row, text=source, width=180, anchor="w", text_color=p["text_muted"], font=ui_kit.font(11)).pack(side="left", padx=8)
|
||||
self._count_text.set(f"{len(self._visible)} terme(s) affiché(s) sur {len(self._rows)}.")
|
||||
Reference in New Issue
Block a user