@@ -84,6 +84,8 @@ def __init__(self, program, args, env, working_dir=None):
8484 self .args = args
8585 self .env = env
8686 self .working_dir = working_dir
87+ self .cancel_requested = False
88+ self .process = None
8789
8890 def run (self ):
8991 """Exécute le processus de compilation."""
@@ -98,23 +100,56 @@ def run(self):
98100 bufsize = 1 ,
99101 )
100102
101- # Lire la sortie en temps réel
103+ import select
104+ import time
105+
106+ # Utiliser select pour lire stdout et stderr en temps réel
102107 while True :
103- line = proc .stdout .readline ()
104- if not line and proc .poll () is not None :
108+ # Vérifier si l'annulation a été demandée
109+ if self .cancel_requested :
110+ proc .terminate ()
111+ try :
112+ proc .wait (timeout = 5 ) # Attendre que le processus se termine
113+ except subprocess .TimeoutExpired :
114+ proc .kill () # Forcer la terminaison si nécessaire
115+ if self .finished :
116+ self .finished .emit (- 1 ) # Code spécial pour annulation
117+ return
118+
119+ # Vérifier si le processus est terminé
120+ if proc .poll () is not None :
105121 break
106- if line and self .output_ready :
107- self .output_ready .emit (line .rstrip ())
108122
109- # Lire stderr à la fin
110- stderr = proc .stderr .read ()
111- if stderr and self .error_ready :
112- for line in stderr .strip ().split ("\n " ):
123+ # Utiliser select pour attendre des données sur stdout ou stderr
124+ ready , _ , _ = select .select ([proc .stdout , proc .stderr ], [], [], 0.1 )
125+
126+ for stream in ready :
127+ if stream == proc .stdout and self .output_ready :
128+ line = proc .stdout .readline ()
129+ if line :
130+ self .output_ready .emit (line .rstrip ())
131+ elif stream == proc .stderr and self .error_ready :
132+ line = proc .stderr .readline ()
133+ if line :
134+ self .error_ready .emit (line .rstrip ())
135+
136+ time .sleep (0.01 ) # Petit délai pour éviter la surcharge CPU
137+
138+ # Lire tout ce qui reste dans les buffers après la fin du processus
139+ remaining_stdout = proc .stdout .read ()
140+ if remaining_stdout and self .output_ready :
141+ for line in remaining_stdout .strip ().split ("\n " ):
142+ if line :
143+ self .output_ready .emit (line .rstrip ())
144+
145+ remaining_stderr = proc .stderr .read ()
146+ if remaining_stderr and self .error_ready :
147+ for line in remaining_stderr .strip ().split ("\n " ):
113148 if line :
114149 self .error_ready .emit (line .rstrip ())
115150
116151 # Signaler la fin
117- return_code = proc .wait ()
152+ return_code = proc .returncode
118153 if self .finished :
119154 self .finished .emit (return_code )
120155
@@ -124,6 +159,10 @@ def run(self):
124159 if self .finished :
125160 self .finished .emit (1 )
126161
162+ def cancel (self ):
163+ """Demande l'annulation de la compilation."""
164+ self .cancel_requested = True
165+
127166
128167class EnginesStandaloneGui (QMainWindow ):
129168 """
@@ -358,6 +397,31 @@ def _setup_ui(self):
358397 self .compile_btn .clicked .connect (self ._run_compilation )
359398 actions_layout .addWidget (self .compile_btn )
360399
400+ # Cancel button
401+ self .cancel_btn = QPushButton ("Cancel" )
402+ self .cancel_btn .setMinimumHeight (32 )
403+ self .cancel_btn .setStyleSheet (
404+ """
405+ QPushButton {
406+ background-color: #f44336;
407+ color: white;
408+ font-size: 16px;
409+ font-weight: bold;
410+ border-radius: 6px;
411+ padding: 10px 20px;
412+ }
413+ QPushButton:hover {
414+ background-color: #d32f2f;
415+ }
416+ QPushButton:disabled {
417+ background-color: #666;
418+ }
419+ """
420+ )
421+ self .cancel_btn .clicked .connect (self ._cancel_compilation )
422+ self .cancel_btn .setEnabled (False ) # Disabled by default
423+ actions_layout .addWidget (self .cancel_btn )
424+
361425 button_row = QHBoxLayout ()
362426 button_row .setSpacing (10 )
363427
@@ -885,6 +949,7 @@ def _run_compilation(self):
885949 self .progress_bar .setVisible (True )
886950 self .progress_bar .setRange (0 , 0 ) # Indeterminate
887951 self .compile_btn .setEnabled (False )
952+ self .cancel_btn .setEnabled (True )
888953
889954 # Logger le début
890955 self ._log ("=" * 50 )
@@ -941,6 +1006,18 @@ def _run_compilation(self):
9411006 except Exception as e :
9421007 self ._log (f"Error: { str (e )} " )
9431008
1009+ def _cancel_compilation (self ):
1010+ """Annule la compilation en cours."""
1011+ if hasattr (self , 'compilation_thread' ) and self .compilation_thread and self .compilation_thread .isRunning ():
1012+ self ._log ("Cancelling compilation..." )
1013+ self .statusBar .showMessage (
1014+ "Cancelling compilation..."
1015+ if self .language == "en"
1016+ else "Annulation de la compilation..."
1017+ )
1018+ self .compilation_thread .cancel ()
1019+ self .cancel_btn .setEnabled (False )
1020+
9441021 def _on_compilation_error (self , message ):
9451022 """Affiche les erreurs de compilation."""
9461023 self ._log (f"STDERR: { message } " )
0 commit comments