diff --git a/portprotonqt/app.py b/portprotonqt/app.py index 69fb1f9..e475b85 100644 --- a/portprotonqt/app.py +++ b/portprotonqt/app.py @@ -36,7 +36,7 @@ def main(): # Обработка флага --fullscreen if args.fullscreen: - logger.info("Запуск в полноэкранном режиме по флагу --fullscreen") + logger.info("Launching in fullscreen mode due to --fullscreen flag") save_fullscreen_config(True) window.showFullScreen() @@ -47,13 +47,28 @@ def main(): def recreate_tray(): nonlocal tray - tray.hide_tray() + if tray: + logger.debug("Recreating system tray") + tray.cleanup() + tray = None current_theme = read_theme_from_config() tray = SystemTray(app, current_theme) tray.show_action.triggered.connect(window.show) tray.hide_action.triggered.connect(window.hide) + def cleanup_on_exit(): + nonlocal tray, window + app.aboutToQuit.disconnect() # Disconnect to prevent further calls + if tray: + tray.cleanup() + tray = None + if window: + window.close() + window = None + app.quit() + window.settings_saved.connect(recreate_tray) + app.aboutToQuit.connect(cleanup_on_exit) window.show() diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 7897bc3..3f52448 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -1852,14 +1852,46 @@ class MainWindow(QMainWindow): self.checkProcessTimer.start(500) def closeEvent(self, event): + """Завершает все дочерние процессы и сохраняет настройки при закрытии окна.""" + # Завершаем все игровые процессы for proc in self.game_processes: try: + parent = psutil.Process(proc.pid) + children = parent.children(recursive=True) + for child in children: + try: + logger.debug(f"Terminating child process {child.pid}") + child.terminate() + except psutil.NoSuchProcess: + logger.debug(f"Child process {child.pid} already terminated") + psutil.wait_procs(children, timeout=5) + for child in children: + if child.is_running(): + logger.debug(f"Killing child process {child.pid}") + child.kill() + logger.debug(f"Terminating process group {proc.pid}") os.killpg(os.getpgid(proc.pid), signal.SIGTERM) - except ProcessLookupError: - pass # процесс уже завершился + except (psutil.NoSuchProcess, ProcessLookupError) as e: + logger.debug(f"Process {proc.pid} already terminated: {e}") + self.game_processes = [] # Очищаем список процессов + + # Сохраняем настройки окна if not read_fullscreen_config(): + logger.debug(f"Saving window geometry: {self.width()}x{self.height()}") save_window_geometry(self.width(), self.height()) - save_card_size(self.card_width) + + # Очищаем таймеры и другие ресурсы + if hasattr(self, 'games_load_timer') and self.games_load_timer.isActive(): + self.games_load_timer.stop() + if hasattr(self, 'settingsDebounceTimer') and self.settingsDebounceTimer.isActive(): + self.settingsDebounceTimer.stop() + if hasattr(self, 'searchDebounceTimer') and self.searchDebounceTimer.isActive(): + self.searchDebounceTimer.stop() + if hasattr(self, 'checkProcessTimer') and self.checkProcessTimer and self.checkProcessTimer.isActive(): + self.checkProcessTimer.stop() + self.checkProcessTimer.deleteLater() + self.checkProcessTimer = None + event.accept() diff --git a/portprotonqt/tray.py b/portprotonqt/tray.py index ba6ea0f..281c790 100644 --- a/portprotonqt/tray.py +++ b/portprotonqt/tray.py @@ -7,12 +7,13 @@ from portprotonqt.config_utils import read_theme_from_config class SystemTray: def __init__(self, app, theme=None): + self.app = app self.theme_manager = ThemeManager() self.theme = theme if theme is not None else default_styles self.current_theme_name = read_theme_from_config() self.tray = QSystemTrayIcon() self.tray.setIcon(cast(QIcon, self.theme_manager.get_icon("ppqt-tray", self.current_theme_name))) - self.tray.setToolTip("PortProton QT") + self.tray.setToolTip("PortProtonQt") self.tray.setVisible(True) # Создаём меню @@ -32,4 +33,16 @@ class SystemTray: def hide_tray(self): """Скрыть иконку трея""" - self.tray.hide() + if self.tray: + self.tray.setVisible(False) + self.tray.setContextMenu(None) + + def cleanup(self): + """Очистка ресурсов трея""" + self.hide_tray() + if self.menu: + self.menu.deleteLater() + self.menu = None + if self.tray: + self.tray.deleteLater() + self.tray = None