def run_gui(config: CoreConfig, start_arg: Optional[str] = None, diagnose: bool = False): logger.info("Starting UI") # Needed for High DPI usage of QIcons, otherwise only QImages are well scaled QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) QApplication.setHighDpiScaleFactorRoundingPolicy( Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) # The parsec app needs to be instanciated before qtrio runs in order # to be the default QApplication instance app = ParsecApp() assert QApplication.instance() is app return qtrio.run(_run_gui, app, config, start_arg, diagnose)
def run_gui(config: CoreConfig, start_arg: str = None, diagnose: bool = False): logger.info("Starting UI") # Needed for High DPI usage of QIcons, otherwise only QImages are well scaled QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) QApplication.setHighDpiScaleFactorRoundingPolicy( Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) app = ParsecApp() app.load_stylesheet() app.load_font() lang_key = lang.switch_language(config) event_bus = EventBus() with run_trio_thread() as jobs_ctx: win = MainWindow( jobs_ctx=jobs_ctx, event_bus=event_bus, config=config, minimize_on_close=config.gui_tray_enabled and systray_available(), ) result_queue = Queue(maxsize=1) class ThreadSafeNoQtSignal(ThreadSafeQtSignal): def __init__(self): self.qobj = None self.signal_name = "" self.args_types = () def emit(self, *args): pass jobs_ctx.submit_job( ThreadSafeNoQtSignal(), ThreadSafeNoQtSignal(), _start_ipc_server, config, win, start_arg, result_queue, ) if result_queue.get() == "already_running": # Another instance of Parsec already started, nothing more to do return if systray_available(): systray = Systray(parent=win) win.systray_notification.connect(systray.on_systray_notification) systray.on_close.connect(win.close_app) systray.on_show.connect(win.show_top) app.aboutToQuit.connect(before_quit(systray)) if config.gui_tray_enabled: app.setQuitOnLastWindowClosed(False) if config.gui_check_version_at_startup and not diagnose: CheckNewVersion(jobs_ctx=jobs_ctx, event_bus=event_bus, config=config, parent=win) win.show_window(skip_dialogs=diagnose, invitation_link=start_arg) win.show_top() win.new_instance_needed.emit(start_arg) def kill_window(*args): win.close_app(force=True) QApplication.quit() signal.signal(signal.SIGINT, kill_window) # QTimer wakes up the event loop periodically which allows us to close # the window even when it is in background. timer = QTimer() timer.start(1000 if diagnose else 400) timer.timeout.connect(kill_window if diagnose else lambda: None) if diagnose: diagnose_timer = QTimer() diagnose_timer.start(1000) diagnose_timer.timeout.connect(kill_window) if lang_key: event_bus.send(CoreEvent.GUI_CONFIG_CHANGED, gui_language=lang_key) if diagnose: with fail_on_first_exception(kill_window): return app.exec_() else: with log_pyqt_exceptions(): return app.exec_()