143 lines
5.7 KiB
Python
143 lines
5.7 KiB
Python
import logging
|
|
import os
|
|
import platform
|
|
import sys
|
|
import time
|
|
import traceback
|
|
from argparse import Namespace
|
|
|
|
import legendary
|
|
from PyQt5.QtCore import QSettings, QTranslator, QT_VERSION_STR, PYQT_VERSION_STR, QObject, pyqtSignal, pyqtSlot, Qt
|
|
from PyQt5.QtGui import QIcon
|
|
from PyQt5.QtWidgets import QApplication, QMessageBox
|
|
|
|
import rare.resources.resources
|
|
from rare.utils import paths
|
|
from rare.utils.misc import set_color_pallete, set_style_sheet, get_static_style
|
|
|
|
|
|
class RareAppException(QObject):
|
|
exception = pyqtSignal(object, object, object)
|
|
|
|
def __init__(self, parent=None):
|
|
super(RareAppException, self).__init__(parent=parent)
|
|
self.logger = logging.getLogger(type(self).__name__)
|
|
sys.excepthook = self._excepthook
|
|
self.exception.connect(self._on_exception)
|
|
|
|
def _excepthook(self, exc_type: object, exc_value: object, exc_tb: object):
|
|
self.exception.emit(exc_type, exc_value, exc_tb)
|
|
|
|
def _handler(self, exc_type, exc_value, exc_tb) -> bool:
|
|
return False
|
|
|
|
@pyqtSlot(object, object, object)
|
|
def _on_exception(self, exc_type, exc_value, exc_tb):
|
|
message = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
|
|
if self._handler(exc_type, exc_value, exc_tb):
|
|
return
|
|
self.logger.fatal(message)
|
|
action = QMessageBox.warning(
|
|
None, exc_type.__name__, message,
|
|
buttons=QMessageBox.Ignore | QMessageBox.Abort,
|
|
defaultButton=QMessageBox.Abort
|
|
)
|
|
if action == QMessageBox.Abort:
|
|
QApplication.quit()
|
|
|
|
|
|
class RareApp(QApplication):
|
|
def __init__(self, args: Namespace, log_file: str):
|
|
super(RareApp, self).__init__(sys.argv)
|
|
self.logger = logging.getLogger(type(self).__name__)
|
|
self._hook = RareAppException(self)
|
|
self.setQuitOnLastWindowClosed(False)
|
|
self.setAttribute(Qt.AA_DontUseNativeDialogs, True)
|
|
|
|
self.setApplicationName("Rare")
|
|
self.setOrganizationName("Rare")
|
|
|
|
# Create directories after QStandardPaths has been initialized
|
|
paths.create_dirs()
|
|
|
|
# Clean any existing logging handlers from library imports
|
|
for handler in logging.root.handlers[:]:
|
|
logging.root.removeHandler(handler)
|
|
|
|
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
|
|
file_handler = logging.FileHandler(
|
|
filename=os.path.join(paths.log_dir(), log_file.format(start_time)),
|
|
encoding="utf-8",
|
|
)
|
|
file_handler.setFormatter(fmt=logging.Formatter("[%(name)s] %(levelname)s: %(message)s"))
|
|
|
|
# Set up common logging channel to stderr
|
|
if args.debug:
|
|
logging.basicConfig(
|
|
format="[%(name)s] %(levelname)s: %(message)s",
|
|
level=logging.DEBUG,
|
|
stream=sys.stderr,
|
|
)
|
|
file_handler.setLevel(logging.DEBUG)
|
|
logging.root.addHandler(file_handler)
|
|
logging.getLogger().setLevel(level=logging.DEBUG)
|
|
# keep requests, asyncio and pillow quiet
|
|
logging.getLogger("requests").setLevel(logging.WARNING)
|
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
logging.getLogger("asyncio").setLevel(logging.WARNING)
|
|
else:
|
|
logging.basicConfig(
|
|
format="[%(name)s] %(levelname)s: %(message)s",
|
|
level=logging.INFO,
|
|
stream=sys.stderr,
|
|
)
|
|
file_handler.setLevel(logging.DEBUG)
|
|
logging.root.addHandler(file_handler)
|
|
self.logger.info(
|
|
f"Launching Rare version {rare.__version__} Codename: {rare.__codename__}\n"
|
|
f" - Using Legendary {legendary.__version__} Codename: {legendary.__codename__} as backend\n"
|
|
f" - Operating System: {platform.system()}, Python version: {platform.python_version()}\n"
|
|
f" - Running {sys.executable} {' '.join(sys.argv)}\n"
|
|
f" - Qt version: {QT_VERSION_STR}, PyQt version: {PYQT_VERSION_STR}"
|
|
)
|
|
|
|
self.settings = QSettings()
|
|
|
|
# Translator
|
|
self.translator = QTranslator()
|
|
self.qt_translator = QTranslator()
|
|
|
|
# Style
|
|
# lk: this is a bit silly but serves well until we have a class
|
|
# lk: store the default qt style name from the system on startup as a property for later reference
|
|
self.setProperty("rareDefaultQtStyle", self.style().objectName())
|
|
if (
|
|
self.settings.value("color_scheme", None) is None
|
|
and self.settings.value("style_sheet", None) is None
|
|
):
|
|
self.settings.setValue("color_scheme", "")
|
|
self.settings.setValue("style_sheet", "RareStyle")
|
|
|
|
if color_scheme := self.settings.value("color_scheme", False):
|
|
self.settings.setValue("style_sheet", "")
|
|
set_color_pallete(color_scheme)
|
|
elif style_sheet := self.settings.value("style_sheet", False):
|
|
self.settings.setValue("color_scheme", "")
|
|
set_style_sheet(style_sheet)
|
|
else:
|
|
self.setStyleSheet(get_static_style())
|
|
self.setWindowIcon(QIcon(":/images/Rare.png"))
|
|
|
|
def load_translator(self, lang: str):
|
|
if os.path.isfile(f := os.path.join(paths.resources_path, "languages", f"{lang}.qm")):
|
|
self.translator.load(f)
|
|
self.logger.info(f"Your language is supported: {lang}")
|
|
elif not lang == "en":
|
|
self.logger.info("Your language is not supported")
|
|
self.installTranslator(self.translator)
|
|
|
|
# translator for qt stuff
|
|
if os.path.isfile(f := os.path.join(paths.resources_path, f"qt_{lang}.qm")):
|
|
self.qt_translator = QTranslator()
|
|
self.qt_translator.load(f)
|
|
self.installTranslator(self.qt_translator)
|