Files
Geniusia_v2/geniusia2/gui/signals.py
2026-03-05 00:20:25 +01:00

235 lines
7.3 KiB
Python

"""
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é")