forked from Boria138/PortProtonQt
fix: completly exit on app close
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@ -36,7 +36,7 @@ def main():
|
|||||||
|
|
||||||
# Обработка флага --fullscreen
|
# Обработка флага --fullscreen
|
||||||
if args.fullscreen:
|
if args.fullscreen:
|
||||||
logger.info("Запуск в полноэкранном режиме по флагу --fullscreen")
|
logger.info("Launching in fullscreen mode due to --fullscreen flag")
|
||||||
save_fullscreen_config(True)
|
save_fullscreen_config(True)
|
||||||
window.showFullScreen()
|
window.showFullScreen()
|
||||||
|
|
||||||
@ -47,13 +47,28 @@ def main():
|
|||||||
|
|
||||||
def recreate_tray():
|
def recreate_tray():
|
||||||
nonlocal tray
|
nonlocal tray
|
||||||
tray.hide_tray()
|
if tray:
|
||||||
|
logger.debug("Recreating system tray")
|
||||||
|
tray.cleanup()
|
||||||
|
tray = None
|
||||||
current_theme = read_theme_from_config()
|
current_theme = read_theme_from_config()
|
||||||
tray = SystemTray(app, current_theme)
|
tray = SystemTray(app, current_theme)
|
||||||
tray.show_action.triggered.connect(window.show)
|
tray.show_action.triggered.connect(window.show)
|
||||||
tray.hide_action.triggered.connect(window.hide)
|
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)
|
window.settings_saved.connect(recreate_tray)
|
||||||
|
app.aboutToQuit.connect(cleanup_on_exit)
|
||||||
|
|
||||||
window.show()
|
window.show()
|
||||||
|
|
||||||
|
@ -1852,14 +1852,46 @@ class MainWindow(QMainWindow):
|
|||||||
self.checkProcessTimer.start(500)
|
self.checkProcessTimer.start(500)
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
|
"""Завершает все дочерние процессы и сохраняет настройки при закрытии окна."""
|
||||||
|
# Завершаем все игровые процессы
|
||||||
for proc in self.game_processes:
|
for proc in self.game_processes:
|
||||||
try:
|
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)
|
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||||
except ProcessLookupError:
|
except (psutil.NoSuchProcess, ProcessLookupError) as e:
|
||||||
pass # процесс уже завершился
|
logger.debug(f"Process {proc.pid} already terminated: {e}")
|
||||||
|
|
||||||
|
self.game_processes = [] # Очищаем список процессов
|
||||||
|
|
||||||
|
# Сохраняем настройки окна
|
||||||
if not read_fullscreen_config():
|
if not read_fullscreen_config():
|
||||||
|
logger.debug(f"Saving window geometry: {self.width()}x{self.height()}")
|
||||||
save_window_geometry(self.width(), self.height())
|
save_window_geometry(self.width(), self.height())
|
||||||
|
|
||||||
save_card_size(self.card_width)
|
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()
|
event.accept()
|
||||||
|
@ -7,12 +7,13 @@ from portprotonqt.config_utils import read_theme_from_config
|
|||||||
|
|
||||||
class SystemTray:
|
class SystemTray:
|
||||||
def __init__(self, app, theme=None):
|
def __init__(self, app, theme=None):
|
||||||
|
self.app = app
|
||||||
self.theme_manager = ThemeManager()
|
self.theme_manager = ThemeManager()
|
||||||
self.theme = theme if theme is not None else default_styles
|
self.theme = theme if theme is not None else default_styles
|
||||||
self.current_theme_name = read_theme_from_config()
|
self.current_theme_name = read_theme_from_config()
|
||||||
self.tray = QSystemTrayIcon()
|
self.tray = QSystemTrayIcon()
|
||||||
self.tray.setIcon(cast(QIcon, self.theme_manager.get_icon("ppqt-tray", self.current_theme_name)))
|
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)
|
self.tray.setVisible(True)
|
||||||
|
|
||||||
# Создаём меню
|
# Создаём меню
|
||||||
@ -32,4 +33,16 @@ class SystemTray:
|
|||||||
|
|
||||||
def hide_tray(self):
|
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
|
||||||
|
Reference in New Issue
Block a user