feat(gui): Ajout bouton Arrêter pour stopper le traitement en cours

This commit is contained in:
2026-03-02 22:04:00 +01:00
parent b46ea83900
commit bf30f622d9
4 changed files with 276 additions and 11 deletions

View File

@@ -302,6 +302,9 @@ class App:
# --- Résultats ---
self._last_outdir: Optional[Path] = None
# --- Contrôle d'arrêt ---
self._stop_requested = False
# --- Construction UI ---
self._build_ui()
@@ -471,16 +474,28 @@ class App:
ToolTip(self._vlm_check, "Envoie chaque page comme image à un VLM local (Ollama)\npour détecter les noms que le regex a pu manquer.")
# =============================================================
# BOUTON LANCER
# BOUTONS LANCER / STOPPER
# =============================================================
buttons_frame = tk.Frame(main, bg=CLR_BG)
buttons_frame.pack(fill=tk.X, padx=pad_x, pady=(0, 4))
self.btn_run = tk.Button(
main, text="Lancer la pseudonymisation",
buttons_frame, text="Lancer la pseudonymisation",
font=self._f_button, bg=CLR_PRIMARY, fg="white",
activebackground="#1d4ed8", activeforeground="white",
relief=tk.FLAT, cursor="hand2", pady=10,
command=self._run,
)
self.btn_run.pack(fill=tk.X, padx=pad_x, pady=(0, 4))
self.btn_run.pack(fill=tk.X)
self.btn_stop = tk.Button(
buttons_frame, text="Arrêter le traitement",
font=self._f_button, bg=CLR_RED, fg="white",
activebackground="#b91c1c", activeforeground="white",
relief=tk.FLAT, cursor="hand2", pady=10,
command=self._stop,
)
# NE PAS pack — sera affiché pendant le traitement
# Lien aide
help_lbl = tk.Label(
@@ -710,10 +725,18 @@ class App:
)
return
self.btn_run.config(state=tk.DISABLED, bg="#93c5fd", text="Traitement en cours...")
self._stop_requested = False
self.btn_run.pack_forget()
self.btn_stop.pack(fill=tk.X)
self._show_progress(total=len(pdfs))
self._hide_results()
threading.Thread(target=self._worker, args=(folder, pdfs), daemon=True).start()
def _stop(self):
"""Demande l'arrêt du traitement en cours."""
self._stop_requested = True
self.btn_stop.config(state=tk.DISABLED, bg="#fca5a5", text="Arrêt en cours...")
self.status_var.set("Arrêt demandé, fin du document en cours...")
def _worker(self, folder: Path, pdfs: List[Path]):
import time
@@ -726,6 +749,11 @@ class App:
global_counts: Dict[str, int] = {}
for i, pdf in enumerate(pdfs, start=1):
# Vérifier si l'arrêt a été demandé
if self._stop_requested:
self.queue.put(UiMessage(kind=MsgType.LOG, text=f"\n⚠️ Arrêt demandé par l'utilisateur"))
break
self.queue.put(UiMessage(
kind=MsgType.PROGRESS, current=i, total=len(pdfs),
filename=pdf.name,
@@ -783,11 +811,24 @@ class App:
total_time = time.time() - start_time
total_masked = sum(global_counts.values())
self.queue.put(UiMessage(
kind=MsgType.DONE, ok=ok, ko=ko, masked=total_masked,
outdir=str(outdir), total_time=total_time,
))
if ok:
# Message différent si arrêt demandé
if self._stop_requested:
self.queue.put(UiMessage(
kind=MsgType.DONE, ok=ok, ko=ko, masked=total_masked,
outdir=str(outdir) if ok > 0 else "", total_time=total_time,
))
self.queue.put(UiMessage(
kind=MsgType.LOG,
text=f"⚠️ TRAITEMENT INTERROMPU : {ok} fichiers traités, {len(pdfs) - ok - ko} ignorés",
))
else:
self.queue.put(UiMessage(
kind=MsgType.DONE, ok=ok, ko=ko, masked=total_masked,
outdir=str(outdir), total_time=total_time,
))
if ok and global_counts:
self.queue.put(UiMessage(
kind=MsgType.LOG,
text="RÉSUMÉ DU LOT : " + ", ".join(f"{k}={v}" for k, v in sorted(global_counts.items())),
@@ -863,8 +904,14 @@ class App:
def _on_done(self, msg: UiMessage):
self._hide_progress()
self.btn_run.config(state=tk.NORMAL, bg=CLR_PRIMARY, text="Lancer la pseudonymisation")
self.status_var.set(f"Terminé : {msg.ok} OK, {msg.ko} erreurs.")
self.btn_stop.pack_forget()
self.btn_stop.config(state=tk.NORMAL, bg=CLR_RED, text="Arrêter le traitement")
self.btn_run.pack(fill=tk.X)
if self._stop_requested:
self.status_var.set(f"Interrompu : {msg.ok} traités, {msg.ko} erreurs.")
else:
self.status_var.set(f"Terminé : {msg.ok} OK, {msg.ko} erreurs.")
if msg.outdir:
self._last_outdir = Path(msg.outdir)