""" Intégration Orchestrator ↔ GUI Module pour connecter l'Orchestrator à l'interface graphique """ import logging from typing import Optional from .human_logger import HumanLogger from .signals import GUISignals from .improved_gui import ImprovedGUI class OrchestratorGUIBridge: """ Pont entre l'Orchestrator et la GUI. Facilite la communication bidirectionnelle: - Orchestrator → GUI : Logs, stats, changements de mode - GUI → Orchestrator : Commandes (start, stop, pause) Attributes: orchestrator: Instance de l'Orchestrator gui: Instance de l'ImprovedGUI human_logger: Instance du HumanLogger signals: Signaux Qt pour communication """ def __init__(self, orchestrator, gui: Optional[ImprovedGUI] = None): """ Initialise le pont Orchestrator-GUI. Args: orchestrator: Instance de l'Orchestrator gui: Instance de l'ImprovedGUI (optionnel, sera créée si None) """ self.logger = logging.getLogger(__name__) self.orchestrator = orchestrator # Créer ou utiliser la GUI fournie if gui is None: self.gui = ImprovedGUI(orchestrator) else: self.gui = gui # Créer le HumanLogger self.human_logger = HumanLogger() # Utiliser les signaux de la GUI self.signals = self.gui.signals # Connecter les signaux self._connect_gui_to_orchestrator() self._inject_logging_into_orchestrator() self.logger.info("OrchestratorGUIBridge initialisé") def _connect_gui_to_orchestrator(self): """Connecte les signaux de la GUI à l'Orchestrator.""" # Boutons de contrôle self.gui.start_requested.connect(self._on_start_requested) self.gui.stop_requested.connect(self._on_stop_requested) self.gui.pause_requested.connect(self._on_pause_requested) self.logger.info("Signaux GUI → Orchestrator connectés") def _inject_logging_into_orchestrator(self): """Injecte le système de logging dans l'Orchestrator.""" # Ajouter les attributs nécessaires à l'Orchestrator self.orchestrator.human_logger = self.human_logger self.orchestrator.gui_signals = self.signals # Ajouter des méthodes helper à l'Orchestrator self.orchestrator.log_to_gui = self.log_to_gui self.orchestrator.update_gui_stats = self.update_gui_stats self.orchestrator.change_mode_gui = self.change_mode_gui self.logger.info("Logging injecté dans l'Orchestrator") def _on_start_requested(self): """Gestionnaire de demande de démarrage.""" self.logger.info("Démarrage demandé depuis la GUI") if hasattr(self.orchestrator, 'start'): try: self.orchestrator.start() self.signals.emit_status_change(True) self.log_to_gui("👀", "Système démarré en mode Observation", "success") except Exception as e: self.logger.error(f"Erreur au démarrage: {e}") self.log_to_gui("❌", f"Erreur au démarrage: {str(e)}", "error") def _on_stop_requested(self): """Gestionnaire de demande d'arrêt.""" self.logger.info("Arrêt demandé depuis la GUI") if hasattr(self.orchestrator, 'stop'): try: self.orchestrator.stop() self.signals.emit_status_change(False) self.log_to_gui("⏹", "Système arrêté", "info") except Exception as e: self.logger.error(f"Erreur à l'arrêt: {e}") self.log_to_gui("❌", f"Erreur à l'arrêt: {str(e)}", "error") def _on_pause_requested(self): """Gestionnaire de demande de pause.""" self.logger.info("Pause demandée depuis la GUI") if hasattr(self.orchestrator, 'pause'): try: self.orchestrator.pause() is_paused = getattr(self.orchestrator, 'is_paused', False) if is_paused: self.log_to_gui("⏸", "Système en pause", "warning") else: self.log_to_gui("▶", "Système repris", "success") except Exception as e: self.logger.error(f"Erreur à la pause: {e}") self.log_to_gui("❌", f"Erreur à la pause: {str(e)}", "error") def log_to_gui(self, emoji: str, message: str, level: str = "info"): """ Envoie un log à la GUI. Args: emoji: Emoji à afficher message: Message de log level: Niveau du log ('info', 'success', 'warning', 'error') Examples: >>> bridge.log_to_gui("👀", "Action observée", "info") """ self.signals.emit_log(emoji, message, level) def update_gui_stats(self, **stats): """ Met à jour les statistiques de la GUI. Args: **stats: Statistiques à mettre à jour (actions_count, patterns_count, workflows_count, etc.) Examples: >>> bridge.update_gui_stats( ... actions_count=12, ... patterns_count=2, ... workflows_count=1 ... ) """ self.signals.emit_stats_update(stats) def change_mode_gui(self, mode: str): """ Change le mode affiché dans la GUI. Args: mode: Nouveau mode ('shadow', 'assist', 'copilot', 'auto') Examples: >>> bridge.change_mode_gui("assist") """ self.signals.emit_mode_change(mode) def show(self): """Affiche la GUI.""" self.gui.show() def hide(self): """Masque la GUI.""" self.gui.hide() # Fonctions helper pour faciliter l'intégration def setup_gui_for_orchestrator(orchestrator) -> OrchestratorGUIBridge: """ Configure la GUI pour un Orchestrator. Fonction helper qui crée et configure automatiquement le pont entre l'Orchestrator et la GUI. Args: orchestrator: Instance de l'Orchestrator Returns: Instance du OrchestratorGUIBridge configuré Examples: >>> from geniusia2.core import Orchestrator >>> from geniusia2.gui import setup_gui_for_orchestrator >>> >>> orchestrator = Orchestrator() >>> bridge = setup_gui_for_orchestrator(orchestrator) >>> bridge.show() >>> >>> # Dans l'Orchestrator, utiliser: >>> orchestrator.log_to_gui("👀", "Message", "info") >>> orchestrator.update_gui_stats(actions_count=12) """ bridge = OrchestratorGUIBridge(orchestrator) return bridge def add_gui_logging_to_orchestrator(orchestrator, signals: GUISignals): """ Ajoute le logging GUI à un Orchestrator existant. Fonction helper pour ajouter uniquement le logging sans créer de nouvelle GUI. Args: orchestrator: Instance de l'Orchestrator signals: Signaux GUI à utiliser Examples: >>> orchestrator = Orchestrator() >>> gui = ImprovedGUI(orchestrator) >>> add_gui_logging_to_orchestrator(orchestrator, gui.signals) >>> >>> # Maintenant l'orchestrator peut logger: >>> orchestrator.log_to_gui("👀", "Message", "info") """ human_logger = HumanLogger() orchestrator.human_logger = human_logger orchestrator.gui_signals = signals # Méthodes helper def log_to_gui(emoji: str, message: str, level: str = "info"): signals.emit_log(emoji, message, level) def update_gui_stats(**stats): signals.emit_stats_update(stats) def change_mode_gui(mode: str): signals.emit_mode_change(mode) orchestrator.log_to_gui = log_to_gui orchestrator.update_gui_stats = update_gui_stats orchestrator.change_mode_gui = change_mode_gui if __name__ == "__main__": """Test de l'intégration Orchestrator-GUI""" import sys from PyQt5.QtWidgets import QApplication from PyQt5.QtCore import QTimer # Mock Orchestrator pour les tests class MockOrchestrator: def __init__(self): self.is_running = False self.is_paused = False self.actions_count = 0 self.patterns_count = 0 self.workflows_count = 0 def start(self): print("MockOrchestrator: start()") self.is_running = True def stop(self): print("MockOrchestrator: stop()") self.is_running = False def pause(self): print("MockOrchestrator: pause()") self.is_paused = not self.is_paused def simulate_action(self): """Simule une action observée""" self.actions_count += 1 self.log_to_gui("👀", f"Action #{self.actions_count} observée", "info") self.update_gui_stats( actions_count=self.actions_count, patterns_count=self.patterns_count, workflows_count=self.workflows_count ) app = QApplication(sys.argv) print("=" * 60) print("Test de l'intégration Orchestrator-GUI") print("=" * 60) # Créer un mock orchestrator orchestrator = MockOrchestrator() # Configurer la GUI bridge = setup_gui_for_orchestrator(orchestrator) bridge.show() print("\n✓ GUI créée et affichée") print("✓ Orchestrator connecté") # Simuler des événements def simulate_workflow(): print("\n📝 Simulation d'événements...") # Démarrer QTimer.singleShot(1000, lambda: [ print(" 1. Démarrage"), orchestrator.start(), bridge.signals.emit_status_change(True), bridge.log_to_gui("✅", "Système démarré", "success") ]) # Actions QTimer.singleShot(2000, lambda: [ print(" 2. Action 1"), orchestrator.simulate_action() ]) QTimer.singleShot(3000, lambda: [ print(" 3. Action 2"), orchestrator.simulate_action() ]) QTimer.singleShot(4000, lambda: [ print(" 4. Action 3"), orchestrator.simulate_action() ]) # Pattern détecté QTimer.singleShot(5000, lambda: [ print(" 5. Pattern détecté"), setattr(orchestrator, 'patterns_count', 1), bridge.log_to_gui("🎯", "Pattern détecté !", "success"), bridge.update_gui_stats( actions_count=orchestrator.actions_count, patterns_count=1, workflows_count=0 ) ]) # Changement de mode QTimer.singleShot(6000, lambda: [ print(" 6. Changement de mode"), bridge.change_mode_gui("assist"), bridge.log_to_gui("✅", "Mode Suggestions activé", "success") ]) QTimer.singleShot(500, simulate_workflow) print("\nTestez les boutons de la GUI:") print(" - Pause") print(" - Arrêter") print(" - System tray") sys.exit(app.exec_())