""" Système de signaux Qt pour communication Orchestrator → GUI Permet une communication thread-safe entre les composants """ from PyQt5.QtCore import QObject, pyqtSignal from typing import Callable, Dict, Any class GUISignals(QObject): """ Signaux Qt pour communication entre l'Orchestrator et la GUI. Ces signaux permettent une communication thread-safe et asynchrone entre le backend (Orchestrator) et l'interface utilisateur. Signals: log_message: Émet un message de log (emoji: str, message: str, level: str) update_stats: Met à jour les statistiques (stats: dict) show_dialog: Affiche un dialogue interactif (title: str, message: str, on_accept: callable, on_reject: callable) mode_changed: Notifie un changement de mode (mode: str) status_changed: Notifie un changement de statut (is_running: bool) """ # Signal pour ajouter un message de log # Paramètres: (emoji: str, message: str, level: str) log_message = pyqtSignal(str, str, str) # Signal pour mettre à jour les statistiques # Paramètre: (stats: dict) contenant actions_count, patterns_count, etc. update_stats = pyqtSignal(dict) # Signal pour afficher un dialogue interactif # Paramètres: (title: str, message: str, on_accept: object, on_reject: object) show_dialog = pyqtSignal(str, str, object, object) # Signal pour notifier un changement de mode # Paramètre: (mode: str) - 'shadow', 'assist', 'copilot', 'auto' mode_changed = pyqtSignal(str) # Signal pour notifier un changement de statut # Paramètre: (is_running: bool) status_changed = pyqtSignal(bool) def __init__(self): """Initialise le système de signaux.""" super().__init__() def emit_log(self, emoji: str, message: str, level: str = "info"): """ Émet un signal de log. Args: emoji: Emoji à afficher message: Message de log level: Niveau du log ('info', 'success', 'warning', 'error') Examples: >>> signals = GUISignals() >>> signals.emit_log("👀", "J'observe vos actions", "info") """ self.log_message.emit(emoji, message, level) def emit_stats_update(self, stats: Dict[str, Any]): """ Émet un signal de mise à jour des statistiques. Args: stats: Dictionnaire contenant les statistiques { 'actions_count': int, 'patterns_count': int, 'workflows_count': int, 'finetuning_status': str, 'finetuning_progress': int } Examples: >>> signals = GUISignals() >>> signals.emit_stats_update({ ... 'actions_count': 12, ... 'patterns_count': 2, ... 'workflows_count': 1 ... }) """ self.update_stats.emit(stats) def emit_dialog(self, title: str, message: str, on_accept: Callable, on_reject: Callable): """ Émet un signal pour afficher un dialogue interactif. Args: title: Titre du dialogue message: Message du dialogue on_accept: Callback appelé si l'utilisateur accepte on_reject: Callback appelé si l'utilisateur refuse Examples: >>> signals = GUISignals() >>> def accept(): ... print("Accepté") >>> def reject(): ... print("Refusé") >>> signals.emit_dialog( ... "Confirmation", ... "Voulez-vous continuer ?", ... accept, ... reject ... ) """ self.show_dialog.emit(title, message, on_accept, on_reject) def emit_mode_change(self, mode: str): """ Émet un signal de changement de mode. Args: mode: Nouveau mode ('shadow', 'assist', 'copilot', 'auto') Examples: >>> signals = GUISignals() >>> signals.emit_mode_change("assist") """ self.mode_changed.emit(mode) def emit_status_change(self, is_running: bool): """ Émet un signal de changement de statut. Args: is_running: True si le système est en cours d'exécution Examples: >>> signals = GUISignals() >>> signals.emit_status_change(True) """ self.status_changed.emit(is_running) if __name__ == "__main__": """Tests du système de signaux""" from PyQt5.QtWidgets import QApplication import sys app = QApplication(sys.argv) print("Test du système de signaux Qt") print("=" * 50) # Créer une instance de signaux signals = GUISignals() # Compteurs pour vérifier les émissions log_count = 0 stats_count = 0 dialog_count = 0 mode_count = 0 status_count = 0 # Connecter des slots de test def on_log(emoji, message, level): global log_count log_count += 1 print(f"\n✓ Log reçu: {emoji} {message} [{level}]") def on_stats(stats): global stats_count stats_count += 1 print(f"\n✓ Stats reçues: {stats}") def on_dialog(title, message, on_accept, on_reject): global dialog_count dialog_count += 1 print(f"\n✓ Dialogue reçu: {title} - {message}") def on_mode(mode): global mode_count mode_count += 1 print(f"\n✓ Mode changé: {mode}") def on_status(is_running): global status_count status_count += 1 print(f"\n✓ Statut changé: {'En cours' if is_running else 'Arrêté'}") # Connecter les signaux signals.log_message.connect(on_log) signals.update_stats.connect(on_stats) signals.show_dialog.connect(on_dialog) signals.mode_changed.connect(on_mode) signals.status_changed.connect(on_status) print("\n1. Test émission de log:") signals.emit_log("👀", "Test message", "info") print("\n2. Test émission de stats:") signals.emit_stats_update({ 'actions_count': 12, 'patterns_count': 2, 'workflows_count': 1 }) print("\n3. Test émission de dialogue:") signals.emit_dialog( "Test", "Message de test", lambda: print("Accepté"), lambda: print("Refusé") ) print("\n4. Test émission de changement de mode:") signals.emit_mode_change("assist") print("\n5. Test émission de changement de statut:") signals.emit_status_change(True) # Traiter les événements Qt app.processEvents() # Vérifier les compteurs print("\n" + "=" * 50) print("Résultats:") print(f" Logs émis: {log_count}") print(f" Stats émises: {stats_count}") print(f" Dialogues émis: {dialog_count}") print(f" Modes émis: {mode_count}") print(f" Statuts émis: {status_count}") if all([log_count == 1, stats_count == 1, dialog_count == 1, mode_count == 1, status_count == 1]): print("\n✅ Tous les tests passent!") else: print("\n❌ Certains tests ont échoué")