Source code for prsctrl_gui.init

"""Initialize the GUI"""
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication
from .ui.main_window import MainWindow
from .utility.config import AppConfig
import signal

import logging
log = logging.getLogger(__name__)

from . import resources
# This is necessary to set the taskbar icon
import ctypes
try:
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(u'n205.prsctrl-gui.1')
except:
    pass # not windows

[docs] def run() -> int: """ Initializes the application and runs it. Returns: int: The exit status code. """ log.debug("Starting app") app: QApplication = QApplication(sys.argv) icon_path = resources.get_resource_path("icons/icon.png") app.setWindowIcon(QIcon(icon_path)) window: MainWindow = MainWindow() window.show() # Close app on keyboard interrupt signal.signal(signal.SIGINT, lambda *_: [window.app_exit(), app.quit()]) exitcode = app.exec() log.info("Saving configuration") AppConfig.finalize() return sys.exit(exitcode)
import sys import traceback from PyQt6 import QtCore, QtWidgets from os import path, makedirs from devctrl.utility.log import ColorFormatter, PackageFilter from devctrl.utility.file_io import get_date_for_filename AppConfig.initialize() # Init logging log_dir = path.expanduser(AppConfig.MAIN_CFG.get_or("log_dir", "~/.cache/prsctrl-gui.log")) makedirs(log_dir, exist_ok=True) log_path = path.join(log_dir, get_date_for_filename() + "_prsctrl-gui.log") log_format = "%(asctime)s [%(levelname)s] [%(name)s/%(funcName)s] %(message)s" log_stdout = logging.StreamHandler() log_stdout.setFormatter(ColorFormatter(log_format)) PackageFilter.DEBUG_FOR_PKG = ["prsctrl-gui", "prsctrl", "devctrl", "__main__", "mqutil"] log_stdout.addFilter(PackageFilter()) log_file = logging.FileHandler(log_path) log_file.addFilter(PackageFilter()) log_file.setFormatter(logging.Formatter(log_format)) logger = logging.getLogger() # root logger logger.addHandler(log_stdout) logger.addHandler(log_file) logger.setLevel(logging.DEBUG) # Mechanism to catch, log and display uncaught exceptions # This is taken from: # https://timlehr.com/2018/01/python-exception-hooks-with-qt-message-box/index.html handler = logging.StreamHandler(stream=sys.stdout) log.addHandler(handler)
[docs] def show_exception_box(log_msg): """Checks if a QApplication instance is available and shows a messagebox with the exception message. If unavailable (non-console application), log an additional notice. """ if QtWidgets.QApplication.instance() is not None: errorbox = QtWidgets.QMessageBox() errorbox.setWindowTitle("An Unexpected Error Occurred") errorbox.setText(log_msg) errorbox.exec() else: log.debug("No QApplication instance available.")
[docs] class UncaughtHook(QtCore.QObject): _exception_caught = QtCore.pyqtSignal(object) def __init__(self, *args, show_traceback=False, **kwargs): super(UncaughtHook, self).__init__(*args, **kwargs) self.show_traceback = show_traceback # this registers the exception_hook() function as hook with the Python interpreter sys.excepthook = self.exception_hook # connect signal to execute the message box function always on main thread self._exception_caught.connect(show_exception_box)
[docs] def exception_hook(self, exc_type, exc_value, exc_traceback): """Function handling uncaught exceptions. It is triggered each time an uncaught exception occurs. """ if issubclass(exc_type, KeyboardInterrupt): # ignore keyboard interrupt to support console applications sys.__excepthook__(exc_type, exc_value, exc_traceback) else: exc_info = (exc_type, exc_value, exc_traceback) log_msg = f"{exc_type.__name__}: {exc_value}\n" if self.show_traceback: log_msg += "\n".join(traceback.format_tb(exc_traceback)) log.critical(f"Uncaught exception:\n {log_msg}", exc_info=exc_info) # trigger message box show self._exception_caught.emit(log_msg)
if AppConfig.MAIN_CFG.get_or("error_show_dialog", True): # create a global instance of our class to register the hook qt_exception_hook = UncaughtHook(show_traceback=AppConfig.MAIN_CFG.get_or("error_stack_trace", False))