2025-03-10 14:07:16 +01:00

97 lines
3.3 KiB
Python

''' cpdctrl_gui/init.py '''
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication
from .ui.main_window import MainWindow
from .utility.config import AppConfig
from . import resources
# This is necessary to set the taskbar icon
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(u'n203.cpdctrl-gui.1')
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()
exitcode = app.exec()
log.info("Saving configuration")
AppConfig.finalize()
return sys.exit(exitcode)
import sys
import traceback
import logging
from PyQt6 import QtCore, QtWidgets
from os import path, makedirs
AppConfig.initialize()
log_path = path.expanduser(AppConfig.MAIN_CFG.get_or("path_log", "~/.cache/cpdctrl-gui.log"))
makedirs(path.dirname(log_path), exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] [%(name)s] %(message)s",
handlers=[
logging.FileHandler(log_path),
logging.StreamHandler()
]
)
log = logging.getLogger(__name__)
# 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)
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.setText("Oops. An unexpected error occured:\n{0}".format(log_msg))
errorbox.exec()
else:
log.debug("No QApplication instance available.")
class UncaughtHook(QtCore.QObject):
_exception_caught = QtCore.pyqtSignal(object)
def __init__(self, *args, **kwargs):
super(UncaughtHook, self).__init__(*args, **kwargs)
# 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)
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 = '\n'.join([''.join(traceback.format_tb(exc_traceback)),
'{0}: {1}'.format(exc_type.__name__, exc_value)])
log.critical(f"Uncaught exception:\n {log_msg}", exc_info=exc_info)
# trigger message box show
self._exception_caught.emit(log_msg)
# create a global instance of our class to register the hook
# qt_exception_hook = UncaughtHook()