import ctypes import platform import sys import traceback import webbrowser import types import threading import qdarkstyle # type: ignore from PySide6 import QtGui, QtWidgets, QtCore from loguru import logger from ..setting import SETTINGS from ..utility import get_icon_path from ..locale import _ Qt = QtCore.Qt def create_qapp(app_name: str = "VeighNa Trader") -> QtWidgets.QApplication: """ Create Qt Application. """ # Set up dark stylesheet qapp: QtWidgets.QApplication = QtWidgets.QApplication(sys.argv) qapp.setStyleSheet(qdarkstyle.load_stylesheet(qt_api="pyside6")) # Set up font font: QtGui.QFont = QtGui.QFont(SETTINGS["font.family"], SETTINGS["font.size"]) qapp.setFont(font) # Set up icon icon: QtGui.QIcon = QtGui.QIcon(get_icon_path(__file__, "vnpy.ico")) qapp.setWindowIcon(icon) # Set up windows process ID if "Windows" in platform.uname(): ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( app_name ) # Exception Handling exception_widget: ExceptionWidget = ExceptionWidget() def excepthook( exc_type: type[BaseException], exc_value: BaseException, exc_traceback: types.TracebackType | None ) -> None: """Show exception detail with QMessageBox.""" logger.opt(exception=(exc_type, exc_value, exc_traceback)).critical("Main thread exception") sys.__excepthook__(exc_type, exc_value, exc_traceback) msg: str = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback)) exception_widget.signal.emit(msg) sys.excepthook = excepthook def threading_excepthook(args: threading.ExceptHookArgs) -> None: """Show exception detail from background threads with QMessageBox.""" if args.exc_value and args.exc_traceback: logger.opt(exception=(args.exc_type, args.exc_value, args.exc_traceback)).critical("Background thread exception") sys.__excepthook__(args.exc_type, args.exc_value, args.exc_traceback) msg: str = "".join(traceback.format_exception(args.exc_type, args.exc_value, args.exc_traceback)) exception_widget.signal.emit(msg) threading.excepthook = threading_excepthook return qapp class ExceptionWidget(QtWidgets.QWidget): """""" signal: QtCore.Signal = QtCore.Signal(str) def __init__(self, parent: QtWidgets.QWidget | None = None) -> None: """""" super().__init__(parent) self.init_ui() self.signal.connect(self.show_exception) def init_ui(self) -> None: """""" self.setWindowTitle(_("触发异常")) self.setFixedSize(600, 600) self.msg_edit: QtWidgets.QTextEdit = QtWidgets.QTextEdit() self.msg_edit.setReadOnly(True) copy_button: QtWidgets.QPushButton = QtWidgets.QPushButton(_("复制")) copy_button.clicked.connect(self._copy_text) community_button: QtWidgets.QPushButton = QtWidgets.QPushButton(_("求助")) community_button.clicked.connect(self._open_community) close_button: QtWidgets.QPushButton = QtWidgets.QPushButton(_("关闭")) close_button.clicked.connect(self.close) hbox: QtWidgets.QHBoxLayout = QtWidgets.QHBoxLayout() hbox.addWidget(copy_button) hbox.addWidget(community_button) hbox.addWidget(close_button) vbox: QtWidgets.QVBoxLayout = QtWidgets.QVBoxLayout() vbox.addWidget(self.msg_edit) vbox.addLayout(hbox) self.setLayout(vbox) def show_exception(self, msg: str) -> None: """""" self.msg_edit.setText(msg) self.show() def _copy_text(self) -> None: """""" self.msg_edit.selectAll() self.msg_edit.copy() def _open_community(self) -> None: """""" webbrowser.open("https://www.vnpy.com/forum/forum/2-ti-wen-qiu-zhu")