Files
2026-07-13 12:07:23 +08:00

126 lines
3.8 KiB
Python

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")