1
0
Fork 0
mirror of synced 2024-05-19 12:02:54 +12:00
Rare/rare/widgets/rare_app.py

160 lines
6.2 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,
QLibraryInfo,
QLocale,
)
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMessageBox
import rare.resources.resources
from rare.models.options import options
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.instance().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.setDesktopFileName("rare")
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(self)
# # Translator
# self.translator = QTranslator(self)
# self.qt_translator = QTranslator(self)
# 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(options.style_sheet.key, None) is None
and self.settings.value(options.color_scheme.key, None) is None
):
self.settings.setValue(options.color_scheme.key, options.color_scheme.default)
self.settings.setValue(options.style_sheet.key, options.style_sheet.default)
if color_scheme := self.settings.value(options.color_scheme.key, False):
self.settings.setValue(options.style_sheet.key, "")
set_color_pallete(color_scheme)
elif style_sheet := self.settings.value(options.style_sheet.key, False):
self.settings.setValue(options.color_scheme.key, "")
set_style_sheet(style_sheet)
else:
self.setStyleSheet(get_static_style())
self.setWindowIcon(QIcon(":/images/Rare.png"))
def load_translator(self, lang: str):
# translator for qt stuff
locale = QLocale(lang)
self.logger.info("Using locale: %s", locale.name())
translations = {
"qtbase": QLibraryInfo.location(QLibraryInfo.TranslationsPath),
"rare": os.path.join(paths.resources_path, "languages"),
}
for filename, path in translations.items():
translator = QTranslator(self)
if translator.load(locale, filename, "_", path):
self.logger.debug("Loaded translation file: %s", translator.filePath())
self.installTranslator(translator)
else:
self.logger.info("Couldn't find translation for locale: %s", locale.name())
translator.deleteLater()