1
0
Fork 0
mirror of synced 2024-06-23 08:40:45 +12:00

Add debug console for games and use same QApplication base for Rare and helper

This commit is contained in:
Dummerle 2022-06-23 21:26:08 +02:00
parent 43369ae143
commit dace98b567
No known key found for this signature in database
GPG key ID: AB68CC59CA39F2F1
4 changed files with 105 additions and 71 deletions

View file

@ -12,21 +12,19 @@ from typing import Optional
import legendary
import requests.exceptions
from PyQt5.QtCore import Qt, QThreadPool, QSettings, QTranslator, QTimer
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QThreadPool, QTimer
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox
from requests import HTTPError
# noinspection PyUnresolvedReferences
import rare.resources.resources
import rare
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.components.tray_icon import TrayIcon
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.shared.image_manager import ImageManagerSingleton
from rare.utils import legendary_utils, config_helper
from rare.utils.paths import cache_dir, resources_path, tmp_dir
from rare.utils.utils import set_color_pallete, set_style_sheet
from rare.utils.paths import cache_dir, tmp_dir
from rare.widgets.rare_app import RareApp
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
file_name = os.path.join(cache_dir, "logs", f"Rare_{start_time}.log")
@ -55,18 +53,14 @@ def excepthook(exc_type, exc_value, exc_tb):
QApplication.exit(1)
class App(QApplication):
class App(RareApp):
mainwindow: Optional[MainWindow] = None
tray_icon: Optional[QSystemTrayIcon] = None
def __init__(self, args: Namespace):
super(App, self).__init__(sys.argv)
super(App, self).__init__()
self.args = ArgumentsSingleton(args) # add some options
self.window_launched = False
self.setQuitOnLastWindowClosed(False)
if hasattr(Qt, "AA_UseHighDpiPixmaps"):
self.setAttribute(Qt.AA_UseHighDpiPixmaps)
# init Legendary
try:
@ -84,6 +78,9 @@ class App(QApplication):
self.core.lgd.config.add_section("Legendary")
self.core.lgd.save_config()
lang = self.settings.value("language", self.core.language_code, type=str)
self.load_translator(lang)
config_helper.init_config_handler(self.core)
# workaround if egl sync enabled, but no programdata_path
@ -99,9 +96,6 @@ class App(QApplication):
# set Application name for settings
self.launch_dialog = None
self.setApplicationName("Rare")
self.setOrganizationName("Rare")
self.settings = QSettings()
self.signals = GlobalSignalsSingleton(init=True)
self.image_manager = ImageManagerSingleton(init=True)
@ -118,43 +112,6 @@ class App(QApplication):
else None
)
# Translator
self.translator = QTranslator()
lang = self.settings.value("language", self.core.language_code, type=str)
if os.path.isfile(f := os.path.join(resources_path, "languages", f"{lang}.qm")):
self.translator.load(f)
logger.info(f"Your language is supported: {lang}")
elif not lang == "en":
logger.info("Your language is not supported")
self.installTranslator(self.translator)
# translator for qt stuff
if os.path.isfile(f := os.path.join(resources_path, f"qt_{lang}.qm")):
self.qt_translator = QTranslator()
self.qt_translator.load(f)
self.installTranslator(self.qt_translator)
# 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)
self.setWindowIcon(QIcon(":/images/Rare.png"))
# launch app
self.launch_dialog = LaunchDialog()
self.launch_dialog.quit_app.connect(self.launch_dialog.close)

View file

@ -7,14 +7,15 @@ from argparse import Namespace
from logging import getLogger
from typing import Union
from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QRunnable, QThreadPool
from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QRunnable, QThreadPool, QSettings
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtNetwork import QLocalServer, QLocalSocket
from PyQt5.QtWidgets import QApplication
from .lgd_helper import get_launch_args, InitArgs, get_configured_process, LaunchArgs, GameArgsError
from .message_models import ErrorModel, Actions, FinishedModel, BaseModel, StateChangedModel
from ..components.extra.console import Console
from ..shared import LegendaryCoreSingleton
from ..widgets.rare_app import RareApp
class PreLaunchThread(QRunnable):
@ -55,20 +56,28 @@ class PreLaunchThread(QRunnable):
return args
class GameProcessHelper(QObject):
class GameProcessApp(RareApp):
game_process: QProcess
server: QLocalServer
socket: QLocalSocket = None
exit_app = pyqtSignal()
console: Console
success: bool = True
def __init__(self, app_name: str):
super(GameProcessHelper, self).__init__()
super(GameProcessApp, self).__init__()
self.game_process = QProcess()
self.app_name = app_name
self.logger = getLogger(self.app_name)
self.core = LegendaryCoreSingleton(True)
lang = self.settings.value("language", self.core.language_code, type=str)
self.load_translator(lang)
if QSettings().value("show_console", False, bool):
self.console = Console()
self.console.show()
self.server = QLocalServer()
ret = self.server.listen(f"rare_{self.app_name}")
if not ret:
@ -83,6 +92,12 @@ class GameProcessHelper(QObject):
self.game_process.errorOccurred.connect(
lambda err: self.error_occurred(self.game_process.errorString()))
self.game_process.readyReadStandardOutput.connect(
lambda: self.console.log(
str(self.game_process.readAllStandardOutput().data(), "utf-8", "ignore")
)
)
self.start_time = time.time()
def new_server_connection(self):
@ -123,7 +138,8 @@ class GameProcessHelper(QObject):
if not args:
self.stop()
return
if self.console:
self.console.set_env(args.env)
self.start_time = time.time()
if args.is_origin_game:
@ -181,28 +197,26 @@ def start_game(args: Namespace):
level=logging.INFO,
)
app = QApplication(sys.argv)
helper = GameProcessHelper(args.app_name)
app = GameProcessApp(args.app_name)
def excepthook(exc_type, exc_value, exc_tb):
tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
helper.logger.fatal(tb)
app.logger.fatal(tb)
try:
helper.send_message(ErrorModel(
app.send_message(ErrorModel(
app_name=args.app_name,
action=Actions.error,
error_string=tb
))
except RuntimeError:
pass
helper.stop()
app.stop()
sys.excepthook = excepthook
if not helper.success:
if not app.success:
return
helper.start(args)
helper.exit_app.connect(lambda: app.exit(0))
app.start(args)
app.exit_app.connect(lambda: app.exit(0))
# this button is for debug. Closing with keyboard interrupt does not kill the server
# quit_button = QPushButton("Quit")

View file

@ -148,16 +148,12 @@ def get_launch_args(core: LegendaryCore, args: InitArgs = None) -> LaunchArgs:
def get_configured_process(env: dict = None):
proc = QProcess()
proc.setProcessChannelMode(QProcess.MergedChannels)
proc.readyReadStandardOutput.connect(
lambda: logger.info(
str(proc.readAllStandardOutput().data(), "utf-8", "ignore")
)
)
proc.readyReadStandardError.connect(
lambda: logger.info(
str(proc.readAllStandardError().data(), "utf-8", "ignore")
)
)
environment = QProcessEnvironment.systemEnvironment()
if env:
for e in env:

67
rare/widgets/rare_app.py Normal file
View file

@ -0,0 +1,67 @@
import os
import sys
from logging import getLogger
from PyQt5.QtCore import Qt, QSettings, QTranslator
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication
# noinspection PyUnresolvedReferences
from legendary.core import LegendaryCore
import rare.resources.resources
from rare.utils.paths import resources_path
from rare.utils.utils import set_color_pallete, set_style_sheet
class RareApp(QApplication):
logger = getLogger("RareApp")
def __init__(self):
super(RareApp, self).__init__(sys.argv)
self.setQuitOnLastWindowClosed(False)
self.core = LegendaryCore()
if hasattr(Qt, "AA_UseHighDpiPixmaps"):
self.setAttribute(Qt.AA_UseHighDpiPixmaps)
self.setApplicationName("Rare")
self.setOrganizationName("Rare")
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)
self.setWindowIcon(QIcon(":/images/Rare.png"))
def load_translator(self, lang: str):
if os.path.isfile(f := os.path.join(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(resources_path, f"qt_{lang}.qm")):
self.qt_translator = QTranslator()
self.qt_translator.load(f)
self.installTranslator(self.qt_translator)