@@ -78,6 +78,7 @@ class UpdateDownloader(QThread):
7878 """Thread for downloading the update file."""
7979 progress = pyqtSignal (int , int ) # downloaded_bytes, total_bytes
8080 finished = pyqtSignal (str ) # путь к скачанному файлу
81+ canceled = pyqtSignal ()
8182 error = pyqtSignal (str )
8283
8384 def __init__ (self , url : str , expected_size : int = 0 ):
@@ -91,6 +92,7 @@ def stop(self):
9192 self ._is_running = False
9293
9394 def run (self ):
95+ path = None
9496 try :
9597 # Use requests context manager to ensure connection closure
9698 with requests .get (self .url , stream = True , timeout = 30 , allow_redirects = True ) as response :
@@ -121,6 +123,7 @@ def run(self):
121123 os .remove (path )
122124 except OSError :
123125 pass
126+ self .canceled .emit ()
124127 return
125128
126129 if chunk :
@@ -138,10 +141,24 @@ def run(self):
138141 self .progress .emit (downloaded_size , total_size )
139142 last_emitted_size = downloaded_size
140143
141- if self ._is_running :
142- self .finished .emit (path )
144+ if not self ._is_running :
145+ try :
146+ os .remove (path )
147+ except OSError :
148+ pass
149+ self .canceled .emit ()
150+ return
151+
152+ self .finished .emit (path )
143153
144154 except Exception as e :
155+ if path and not self ._is_running :
156+ try :
157+ os .remove (path )
158+ except OSError :
159+ pass
160+ self .canceled .emit ()
161+ return
145162 logger .error (f"Download failed: { e } " )
146163 self .error .emit (str (e ))
147164
@@ -193,6 +210,7 @@ def _start_download(self, url, size):
193210 self ._downloader = UpdateDownloader (url , size )
194211 self ._downloader .progress .connect (self .progress_dialog .set_progress )
195212 self ._downloader .finished .connect (self ._on_download_finished )
213+ self ._downloader .canceled .connect (self ._on_download_canceled )
196214 self ._downloader .error .connect (self ._on_download_error )
197215
198216 self .progress_dialog .canceled .connect (self ._downloader .stop )
@@ -201,13 +219,20 @@ def _start_download(self, url, size):
201219
202220 def _on_download_error (self , error_msg ):
203221 self .progress_dialog .close ()
222+ self ._downloader = None
204223 # If main window is not created yet (check on startup), NotificationService won't work
205224 if NotificationService ().main_window :
206225 NotificationService ().show_toast ("error" , "Ошибка" , f"Ошибка скачивания: { error_msg } " )
207226 else :
208227 # Use standard QMessageBox as a fallback
209228 QMessageBox .critical (self .parent_widget , "Ошибка" , f"Ошибка скачивания:\n { error_msg } " )
210229
230+ def _on_download_canceled (self ):
231+ self .progress_dialog .close ()
232+ self ._downloader = None
233+ if NotificationService ().main_window :
234+ NotificationService ().show_toast ("info" , "Обновление" , "Скачивание обновления отменено." )
235+
211236 def _on_download_finished (self , file_path ):
212237 # Force set 100% so user sees completion
213238 self .progress_dialog .set_progress (100 , 100 )
@@ -216,6 +241,7 @@ def _on_download_finished(self, file_path):
216241
217242 def _show_install_confirmation (self , file_path ):
218243 self .progress_dialog .close ()
244+ self ._downloader = None
219245 dialog = InstallConfirmDialog (self .parent_widget )
220246 if dialog .exec_ () == QDialog .Accepted :
221247 self ._install_update (file_path )
0 commit comments