Add debug console for games and use same QApplication base for Rare and helper
This commit is contained in:
parent
43369ae143
commit
dace98b567
61
rare/app.py
61
rare/app.py
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
67
rare/widgets/rare_app.py
Normal 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)
|
Loading…
Reference in a new issue