v0.5.5 - Ameliorations ergonomie

Changements :
- Horloge en temps reel : le label de date se met a jour chaque seconde
- Molette de souris ciblee : scroll les cartes ou le journal selon la position du curseur (plus de conflit entre les deux zones)
- Feedback de progression : le journal affiche l'etat de chaque depot au debut et a la fin de la verification (a jour, hors ligne, erreur, changements disponibles)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 19:25:09 +01:00
parent 6438605d7c
commit 0e92b76687
3 changed files with 44 additions and 9 deletions

Binary file not shown.

View File

@@ -5,7 +5,7 @@ Accès lecture seule uniquement (fetch/pull/checkout, jamais de push).
Tous les chemins sont relatifs à l'emplacement de l'exécutable.
"""
VERSION = "0.5.4"
VERSION = "0.5.5"
import subprocess
import sys
@@ -528,9 +528,10 @@ class App(tk.Tk):
self.status_label = ttk.Label(header, text="Verification en cours...", style="Status.TLabel")
self.status_label.pack(side="right")
# Date
date_label = ttk.Label(self, text=datetime.now().strftime(" %d/%m/%Y %H:%M:%S"), style="Status.TLabel")
date_label.pack(anchor="w", padx=15)
# Date (mise a jour chaque seconde)
self.date_label = ttk.Label(self, text="", style="Status.TLabel")
self.date_label.pack(anchor="w", padx=15)
self._tick_clock()
# Panneau principal (PanedWindow vertical : cartes en haut, log en bas)
paned = ttk.PanedWindow(self, orient="vertical")
@@ -551,8 +552,8 @@ class App(tk.Tk):
self.canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
# Scroll avec la molette
self.canvas.bind_all("<MouseWheel>", lambda e: self.canvas.yview_scroll(int(-1 * (e.delta / 120)), "units"))
# Scroll avec la molette : cible le bon widget selon la position du curseur
self.bind_all("<MouseWheel>", self._on_mousewheel)
# Panneau de log en bas
log_frame = tk.Frame(paned, bg="#181825")
@@ -599,6 +600,26 @@ class App(tk.Tk):
self.btn_open_log = ttk.Button(btn_frame, text="Ouvrir les logs", command=self._open_log)
self.btn_open_log.pack(side="right", padx=(0, 10))
def _tick_clock(self):
"""Met à jour le label de date chaque seconde."""
self.date_label.configure(text=datetime.now().strftime(" %d/%m/%Y %H:%M:%S"))
self.after(1000, self._tick_clock)
def _on_mousewheel(self, event):
"""Scroll le bon widget selon où se trouve la souris."""
w = event.widget
while w is not None:
if w is self.canvas or w is self.scroll_frame:
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
return
if w is self.log_text:
self.log_text.yview_scroll(int(-1 * (event.delta / 120)), "units")
return
try:
w = w.master
except AttributeError:
break
def _check_self_update_then_repos(self):
"""Vérifie d'abord la MAJ du programme, puis les repos."""
self.status_label.configure(text="Verification auto-update...")
@@ -684,13 +705,27 @@ class App(tk.Tk):
done = 0
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {executor.submit(check_repo, repo): i for i, repo in enumerate(self.repos_config)}
futures = {}
for i, repo in enumerate(self.repos_config):
self._log_gui(f"[{repo['name']}] Verification...", "dim")
futures[executor.submit(check_repo, repo)] = i
for future in as_completed(futures):
idx = futures[future]
res = future.result()
results[idx] = res
done += 1
self._log_gui(f"[{res['name']}] Verification terminee", "info")
# Résumé concis selon le statut
if res.get("offline"):
self._log_gui(f"[{res['name']}] Hors ligne", "warning")
elif res.get("error"):
self._log_gui(f"[{res['name']}] Erreur : {res['error']}", "error")
elif res.get("needs_clone"):
self._log_gui(f"[{res['name']}] A cloner", "warning")
elif res["up_to_date"]:
self._log_gui(f"[{res['name']}] A jour", "success")
else:
count = len(res["commits"]) + len(res["local_changes"])
self._log_gui(f"[{res['name']}] {count} changement(s) disponible(s)", "warning")
self.after(0, lambda d=done, t=total: self.status_label.configure(text=f"Verification {d}/{t}..."))
self.repo_results = results

View File

@@ -1 +1 @@
0.5.4
0.5.5