Merge pull request #237 from loathingKernel/fixups
Update for legendary 0.20.28
This commit is contained in:
commit
2a21ca8c66
|
@ -30,7 +30,7 @@ pywebview = [
|
|||
{ version = "^3.6.3", extras = ["cef"], platform = "windows", optional = true },
|
||||
{ version = "^3.6.3", extras = ["gtk"], platform = "linux", optional = true },
|
||||
]
|
||||
legendary-gl = "^0.20.27"
|
||||
legendary-gl = "^0.20.28"
|
||||
typing-extensions = "^4.3.0"
|
||||
|
||||
|
||||
|
|
|
@ -45,10 +45,7 @@ def main():
|
|||
)
|
||||
subparsers = parser.add_subparsers(title="Commands", dest="subparser")
|
||||
|
||||
launch_parser = subparsers.add_parser("launch")
|
||||
launch_parser.add_argument("app_name", help="Name of the app", metavar="<App Name>")
|
||||
|
||||
launch_minimal_parser = subparsers.add_parser("start")
|
||||
launch_minimal_parser = subparsers.add_parser("start", aliases=["launch"])
|
||||
launch_minimal_parser.add_argument("app_name", help="AppName of the game to launch",
|
||||
metavar="<App Name>", action="store")
|
||||
launch_minimal_parser.add_argument("--offline", help="Launch game offline",
|
||||
|
@ -56,11 +53,11 @@ def main():
|
|||
launch_minimal_parser.add_argument("--skip_update_check", help="Do not check for updates",
|
||||
action="store_true")
|
||||
launch_minimal_parser.add_argument('--wine-bin', dest='wine_bin', action='store', metavar='<wine binary>',
|
||||
default=os.environ.get('LGDRY_WINE_BINARY', None),
|
||||
help='Set WINE binary to use to launch the app')
|
||||
default=os.environ.get('LGDRY_WINE_BINARY', None),
|
||||
help='Set WINE binary to use to launch the app')
|
||||
launch_minimal_parser.add_argument('--wine-prefix', dest='wine_pfx', action='store', metavar='<wine pfx path>',
|
||||
default=os.environ.get('LGDRY_WINE_PREFIX', None),
|
||||
help='Set WINE prefix to use')
|
||||
default=os.environ.get('LGDRY_WINE_PREFIX', None),
|
||||
help='Set WINE prefix to use')
|
||||
launch_minimal_parser.add_argument("--ask-alyways-sync", help="Ask for cloud saves",
|
||||
action="store_true")
|
||||
|
||||
|
@ -80,10 +77,10 @@ def main():
|
|||
|
||||
if args.version:
|
||||
from rare import __version__, code_name
|
||||
|
||||
print(f"Rare {__version__} Codename: {code_name}")
|
||||
return
|
||||
if args.subparser == "start":
|
||||
|
||||
if args.subparser == "start" or args.subparser == "launch":
|
||||
from rare import game_launch_helper as helper
|
||||
helper.start_game(args)
|
||||
return
|
||||
|
@ -99,16 +96,10 @@ def main():
|
|||
from rare.utils.paths import data_dir
|
||||
|
||||
with open(os.path.join(data_dir, "lockfile"), "w") as file:
|
||||
if args.subparser == "launch":
|
||||
file.write(f"launch {args.app_name}")
|
||||
else:
|
||||
file.write("start")
|
||||
file.write("show")
|
||||
file.close()
|
||||
return
|
||||
|
||||
if args.subparser == "launch":
|
||||
args.silent = True
|
||||
|
||||
from rare.app import start
|
||||
|
||||
start(args)
|
||||
|
|
148
rare/app.py
148
rare/app.py
|
@ -1,4 +1,3 @@
|
|||
import configparser
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
|
@ -13,15 +12,18 @@ from typing import Optional
|
|||
import legendary
|
||||
import requests.exceptions
|
||||
from PyQt5.QtCore import QThreadPool, QTimer, QT_VERSION_STR, PYQT_VERSION_STR
|
||||
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||
from requests import HTTPError
|
||||
|
||||
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.shared import (
|
||||
LegendaryCoreSingleton,
|
||||
GlobalSignalsSingleton,
|
||||
ArgumentsSingleton,
|
||||
)
|
||||
from rare.shared.rare_core import RareCore
|
||||
from rare.utils import legendary_utils, config_helper
|
||||
from rare.utils.paths import cache_dir, tmp_dir
|
||||
from rare.widgets.rare_app import RareApp
|
||||
|
@ -54,66 +56,24 @@ def excepthook(exc_type, exc_value, exc_tb):
|
|||
|
||||
|
||||
class App(RareApp):
|
||||
mainwindow: Optional[MainWindow] = None
|
||||
tray_icon: Optional[QSystemTrayIcon] = None
|
||||
|
||||
def __init__(self, args: Namespace):
|
||||
super(App, self).__init__()
|
||||
self.args = ArgumentsSingleton(args) # add some options
|
||||
self.window_launched = False
|
||||
self.rare_core = RareCore(args=args)
|
||||
self.args = ArgumentsSingleton()
|
||||
self.signals = GlobalSignalsSingleton()
|
||||
self.core = LegendaryCoreSingleton()
|
||||
|
||||
# init Legendary
|
||||
try:
|
||||
self.core = LegendaryCoreSingleton(init=True)
|
||||
except configparser.MissingSectionHeaderError as e:
|
||||
logger.warning(f"Config is corrupt: {e}")
|
||||
if config_path := os.environ.get("XDG_CONFIG_HOME"):
|
||||
path = os.path.join(config_path, "legendary")
|
||||
else:
|
||||
path = os.path.expanduser("~/.config/legendary")
|
||||
with open(os.path.join(path, "config.ini"), "w") as config_file:
|
||||
config_file.write("[Legendary]")
|
||||
self.core = LegendaryCoreSingleton(init=True)
|
||||
if "Legendary" not in self.core.lgd.config.sections():
|
||||
self.core.lgd.config.add_section("Legendary")
|
||||
self.core.lgd.save_config()
|
||||
config_helper.init_config_handler(self.core)
|
||||
|
||||
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
|
||||
# programdata_path might be unset if logging in through the browser
|
||||
if self.core.egl_sync_enabled:
|
||||
if self.core.egl.programdata_path is None:
|
||||
self.core.lgd.config.remove_option("Legendary", "egl_sync")
|
||||
self.core.lgd.save_config()
|
||||
else:
|
||||
if not os.path.exists(self.core.egl.programdata_path):
|
||||
self.core.lgd.config.remove_option("Legendary", "egl_sync")
|
||||
self.core.lgd.save_config()
|
||||
|
||||
# set Application name for settings
|
||||
self.launch_dialog = None
|
||||
|
||||
self.signals = GlobalSignalsSingleton(init=True)
|
||||
self.image_manager = ImageManagerSingleton(init=True)
|
||||
|
||||
self.signals.exit_app.connect(self.exit_app)
|
||||
self.signals.send_notification.connect(
|
||||
lambda title: self.tray_icon.showMessage(
|
||||
self.tr("Download finished"),
|
||||
self.tr("Download finished. {} is playable now").format(title),
|
||||
QSystemTrayIcon.Information,
|
||||
4000,
|
||||
)
|
||||
if self.settings.value("notification", True, bool)
|
||||
else None
|
||||
)
|
||||
self.mainwindow: Optional[MainWindow] = None
|
||||
self.launch_dialog: Optional[LaunchDialog] = None
|
||||
|
||||
# launch app
|
||||
self.launch_dialog = LaunchDialog()
|
||||
self.launch_dialog = LaunchDialog(parent=None)
|
||||
self.launch_dialog.quit_app.connect(self.launch_dialog.close)
|
||||
self.launch_dialog.quit_app.connect(lambda ec: exit(ec))
|
||||
self.launch_dialog.start_app.connect(self.start_app)
|
||||
|
@ -140,12 +100,6 @@ class App(RareApp):
|
|||
td = abs(dt_exp - dt_now)
|
||||
self.timer.start(int(td.total_seconds() - 60) * 1000)
|
||||
|
||||
def show_mainwindow(self):
|
||||
if self.window_launched:
|
||||
self.mainwindow.show()
|
||||
else:
|
||||
self.mainwindow.show_window_centered()
|
||||
|
||||
def start_app(self):
|
||||
for igame in self.core.get_installed_list():
|
||||
if not os.path.exists(igame.install_path):
|
||||
|
@ -167,78 +121,26 @@ class App(RareApp):
|
|||
logger.info(f"{igame.title} needs verification")
|
||||
|
||||
self.mainwindow = MainWindow()
|
||||
self.tray_icon: TrayIcon = TrayIcon(self)
|
||||
self.tray_icon.exit_action.triggered.connect(self.exit_app)
|
||||
self.tray_icon.start_rare.triggered.connect(self.show_mainwindow)
|
||||
self.tray_icon.activated.connect(
|
||||
lambda r: self.show_mainwindow()
|
||||
if r == QSystemTrayIcon.DoubleClick
|
||||
else None
|
||||
)
|
||||
self.mainwindow.exit_app.connect(self.exit_app)
|
||||
|
||||
if not self.args.silent:
|
||||
self.mainwindow.show_window_centered()
|
||||
self.window_launched = True
|
||||
|
||||
if self.args.subparser == "launch":
|
||||
if self.args.app_name in [
|
||||
i.app_name for i in self.core.get_installed_list()
|
||||
]:
|
||||
logger.info(
|
||||
f"Launching {self.core.get_installed_game(self.args.app_name).title}"
|
||||
)
|
||||
self.mainwindow.tab_widget.games_tab.game_utils.prepare_launch(
|
||||
self.args.app_name
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"Could not find {self.args.app_name} in Games or it is not installed"
|
||||
)
|
||||
QMessageBox.warning(
|
||||
self.mainwindow,
|
||||
"Warning",
|
||||
self.tr(
|
||||
"Could not find {} in installed games. Did you modify the shortcut? "
|
||||
).format(self.args.app_name),
|
||||
)
|
||||
self.mainwindow.show()
|
||||
|
||||
if self.args.test_start:
|
||||
self.exit_app(0)
|
||||
|
||||
def tray(self, reason):
|
||||
if reason == QSystemTrayIcon.DoubleClick:
|
||||
self.mainwindow.show()
|
||||
logger.info("Show App")
|
||||
|
||||
def exit_app(self, exit_code=0):
|
||||
# FIXME: Fix this with the downlaod tab redesign
|
||||
if self.mainwindow is not None:
|
||||
if not self.args.offline and self.mainwindow.tab_widget.downloadTab.is_download_active:
|
||||
question = QMessageBox.question(
|
||||
self.mainwindow,
|
||||
self.tr("Close"),
|
||||
self.tr(
|
||||
"There is a download active. Do you really want to exit app?"
|
||||
),
|
||||
QMessageBox.Yes,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if question == QMessageBox.No:
|
||||
return
|
||||
else:
|
||||
# clear queue
|
||||
self.mainwindow.tab_widget.downloadTab.queue_widget.update_queue([])
|
||||
self.mainwindow.tab_widget.downloadTab.stop_download()
|
||||
# FIXME: End of FIXME
|
||||
self.mainwindow.timer.stop()
|
||||
self.mainwindow.hide()
|
||||
threadpool = QThreadPool.globalInstance()
|
||||
threadpool.waitForDone()
|
||||
self.core.exit()
|
||||
if self.timer is not None:
|
||||
self.timer.stop()
|
||||
self.timer.deleteLater()
|
||||
self.timer = None
|
||||
if self.mainwindow is not None:
|
||||
self.mainwindow.close()
|
||||
if self.tray_icon is not None:
|
||||
self.tray_icon.deleteLater()
|
||||
self.mainwindow = None
|
||||
self.rare_core.deleteLater()
|
||||
del self.rare_core
|
||||
self.processEvents()
|
||||
shutil.rmtree(tmp_dir)
|
||||
os.makedirs(tmp_dir)
|
||||
|
@ -284,3 +186,5 @@ def start(args):
|
|||
del app
|
||||
if exit_code != -133742:
|
||||
break
|
||||
|
||||
|
||||
|
|
|
@ -145,9 +145,9 @@ class InstallDialog(QDialog):
|
|||
self.ui.shortcut_cb.setChecked(False)
|
||||
self.ui.shortcut_cb.setToolTip(self.tr("Creating a shortcut is not supported on MacOS"))
|
||||
|
||||
self.ui.install_preqs_lbl.setVisible(False)
|
||||
self.ui.install_preqs_check.setVisible(False)
|
||||
self.ui.install_preqs_check.stateChanged.connect(lambda: self.non_reload_option_changed("install_preqs"))
|
||||
self.ui.install_prereqs_lbl.setVisible(False)
|
||||
self.ui.install_prereqs_check.setVisible(False)
|
||||
self.ui.install_prereqs_check.stateChanged.connect(lambda: self.non_reload_option_changed("install_prereqs"))
|
||||
|
||||
self.non_reload_option_changed("shortcut")
|
||||
|
||||
|
@ -155,7 +155,7 @@ class InstallDialog(QDialog):
|
|||
self.ui.verify_button.clicked.connect(self.verify_clicked)
|
||||
self.ui.install_button.clicked.connect(self.install_clicked)
|
||||
|
||||
self.ui.install_preqs_check.setChecked(self.dl_item.options.install_preqs)
|
||||
self.ui.install_prereqs_check.setChecked(self.dl_item.options.install_prereqs)
|
||||
|
||||
self.ui.install_dialog_layout.setSizeConstraint(QLayout.SetFixedSize)
|
||||
|
||||
|
@ -209,7 +209,7 @@ class InstallDialog(QDialog):
|
|||
self.dl_item.options.ignore_space = self.ui.ignore_space_check.isChecked()
|
||||
self.dl_item.options.no_install = self.ui.download_only_check.isChecked()
|
||||
self.dl_item.options.platform = self.ui.platform_combo_box.currentText()
|
||||
self.dl_item.options.install_preqs = self.ui.install_preqs_check.isChecked()
|
||||
self.dl_item.options.install_prereqs = self.ui.install_prereqs_check.isChecked()
|
||||
self.dl_item.options.create_shortcut = self.ui.shortcut_cb.isChecked()
|
||||
if self.sdl_list_cbs:
|
||||
self.dl_item.options.install_tag = [""]
|
||||
|
@ -254,8 +254,8 @@ class InstallDialog(QDialog):
|
|||
elif option == "shortcut":
|
||||
QSettings().setValue("create_shortcut", self.ui.shortcut_cb.isChecked())
|
||||
self.dl_item.options.create_shortcut = self.ui.shortcut_cb.isChecked()
|
||||
elif option == "install_preqs":
|
||||
self.dl_item.options.install_preqs = self.ui.install_preqs_check.isChecked()
|
||||
elif option == "install_prereqs":
|
||||
self.dl_item.options.install_prereqs = self.ui.install_prereqs_check.isChecked()
|
||||
|
||||
def cancel_clicked(self):
|
||||
if self.config_tags:
|
||||
|
@ -289,10 +289,10 @@ class InstallDialog(QDialog):
|
|||
self.ui.cancel_button.setEnabled(True)
|
||||
if pf.system() == "Windows" or ArgumentsSingleton().debug:
|
||||
if dl_item.igame.prereq_info and not dl_item.igame.prereq_info.get("installed", False):
|
||||
self.ui.install_preqs_check.setVisible(True)
|
||||
self.ui.install_preqs_lbl.setVisible(True)
|
||||
self.ui.install_preqs_check.setChecked(True)
|
||||
self.ui.install_preqs_check.setText(
|
||||
self.ui.install_prereqs_check.setVisible(True)
|
||||
self.ui.install_prereqs_lbl.setVisible(True)
|
||||
self.ui.install_prereqs_check.setChecked(True)
|
||||
self.ui.install_prereqs_check.setText(
|
||||
self.tr("Also install: {}").format(dl_item.igame.prereq_info.get("name", ""))
|
||||
)
|
||||
if self.silent:
|
||||
|
|
|
@ -2,17 +2,16 @@ import platform
|
|||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, QRunnable, QObject, QThreadPool, QSettings
|
||||
from PyQt5.QtWidgets import QDialog, qApp
|
||||
from PyQt5.QtWidgets import QDialog, QApplication
|
||||
from requests.exceptions import ConnectionError, HTTPError
|
||||
|
||||
from rare.components.dialogs.login import LoginDialog
|
||||
from rare.models.apiresults import ApiResults
|
||||
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton
|
||||
from rare.shared.image_manager import ImageManagerSingleton
|
||||
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton, ImageManagerSingleton
|
||||
from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog
|
||||
from rare.utils.misc import CloudWorker
|
||||
|
||||
logger = getLogger("Login")
|
||||
logger = getLogger("LoginDialog")
|
||||
|
||||
|
||||
class LaunchWorker(QRunnable):
|
||||
|
@ -82,14 +81,13 @@ class ApiRequestWorker(LaunchWorker):
|
|||
self.signals.result.emit(result, "32bit")
|
||||
|
||||
|
||||
class LaunchDialog(QDialog, Ui_LaunchDialog):
|
||||
class LaunchDialog(QDialog):
|
||||
quit_app = pyqtSignal(int)
|
||||
start_app = pyqtSignal()
|
||||
completed = 0
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(LaunchDialog, self).__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose, True)
|
||||
self.setWindowFlags(
|
||||
Qt.Window
|
||||
|
@ -101,19 +99,26 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
|
|||
| Qt.MSWindowsFixedSizeDialogHint
|
||||
)
|
||||
self.setWindowModality(Qt.WindowModal)
|
||||
self.ui = Ui_LaunchDialog()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.core = LegendaryCoreSingleton()
|
||||
self.args = ArgumentsSingleton()
|
||||
self.thread_pool = QThreadPool().globalInstance()
|
||||
self.api_results = ApiResults()
|
||||
|
||||
self.login_dialog = LoginDialog(core=self.core, parent=self)
|
||||
|
||||
def login(self):
|
||||
do_launch = True
|
||||
try:
|
||||
if self.args.offline:
|
||||
pass
|
||||
else:
|
||||
qApp.processEvents()
|
||||
QApplication.instance().processEvents()
|
||||
# Force an update check and notice in case there are API changes
|
||||
self.core.check_for_updates(force=True)
|
||||
self.core.force_show_update = True
|
||||
if self.core.login():
|
||||
logger.info("You are logged in")
|
||||
else:
|
||||
|
@ -122,8 +127,8 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
|
|||
logger.info(str(e))
|
||||
# Do not set parent, because it won't show a task bar icon
|
||||
# Update: Inherit the same parent as LaunchDialog
|
||||
do_launch = LoginDialog(core=self.core, parent=self.parent()).login()
|
||||
except ConnectionError as e:
|
||||
do_launch = self.login_dialog.login()
|
||||
except (HTTPError, ConnectionError) as e:
|
||||
logger.warning(e)
|
||||
self.args.offline = True
|
||||
finally:
|
||||
|
@ -143,7 +148,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
|
|||
def launch(self):
|
||||
|
||||
if not self.args.offline:
|
||||
self.image_info.setText(self.tr("Downloading Images"))
|
||||
self.ui.image_info.setText(self.tr("Downloading Images"))
|
||||
image_worker = ImageWorker()
|
||||
image_worker.signals.result.connect(self.handle_api_worker_result)
|
||||
image_worker.signals.progress.connect(self.update_image_progbar)
|
||||
|
@ -202,13 +207,13 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
|
|||
self.finish()
|
||||
|
||||
def update_image_progbar(self, i: int):
|
||||
self.image_prog_bar.setValue(i)
|
||||
self.ui.image_prog_bar.setValue(i)
|
||||
|
||||
def finish(self):
|
||||
self.completed += 1
|
||||
if self.completed == 2:
|
||||
logger.info("App starting")
|
||||
self.image_info.setText(self.tr("Starting..."))
|
||||
self.ui.image_info.setText(self.tr("Starting..."))
|
||||
ApiResultsSingleton(self.api_results)
|
||||
self.completed += 1
|
||||
self.start_app.emit()
|
||||
|
|
|
@ -36,8 +36,6 @@ class LoginDialog(QDialog):
|
|||
|
||||
def __init__(self, core: LegendaryCore, parent=None):
|
||||
super(LoginDialog, self).__init__(parent=parent)
|
||||
self.ui = Ui_LoginDialog()
|
||||
self.ui.setupUi(self)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose, True)
|
||||
self.setWindowFlags(
|
||||
Qt.Window
|
||||
|
@ -50,6 +48,8 @@ class LoginDialog(QDialog):
|
|||
| Qt.MSWindowsFixedSizeDialogHint
|
||||
)
|
||||
self.setWindowModality(Qt.WindowModal)
|
||||
self.ui = Ui_LoginDialog()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.core = core
|
||||
self.args = ArgumentsSingleton()
|
||||
|
@ -76,7 +76,10 @@ class LoginDialog(QDialog):
|
|||
self.ui.back_button.setEnabled(False)
|
||||
|
||||
self.landing_page.ui.login_browser_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
|
||||
self.landing_page.ui.login_browser_radio.clicked.connect(self.browser_radio_clicked)
|
||||
self.landing_page.ui.login_import_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
|
||||
self.landing_page.ui.login_import_radio.clicked.connect(self.import_radio_clicked)
|
||||
|
||||
self.ui.exit_button.clicked.connect(self.close)
|
||||
self.ui.back_button.clicked.connect(self.back_clicked)
|
||||
self.ui.next_button.clicked.connect(self.next_clicked)
|
||||
|
@ -90,15 +93,22 @@ class LoginDialog(QDialog):
|
|||
self.ui.next_button.setEnabled(True)
|
||||
self.login_stack.slideInIndex(self.pages.landing)
|
||||
|
||||
def browser_radio_clicked(self):
|
||||
self.login_stack.slideInIndex(self.pages.browser)
|
||||
self.ui.back_button.setEnabled(True)
|
||||
self.ui.next_button.setEnabled(False)
|
||||
|
||||
def import_radio_clicked(self):
|
||||
self.login_stack.slideInIndex(self.pages.import_egl)
|
||||
self.ui.back_button.setEnabled(True)
|
||||
self.ui.next_button.setEnabled(self.import_page.is_valid())
|
||||
|
||||
def next_clicked(self):
|
||||
if self.login_stack.currentIndex() == self.pages.landing:
|
||||
if self.landing_page.ui.login_browser_radio.isChecked():
|
||||
self.login_stack.slideInIndex(self.pages.browser)
|
||||
self.ui.next_button.setEnabled(False)
|
||||
self.browser_radio_clicked()
|
||||
if self.landing_page.ui.login_import_radio.isChecked():
|
||||
self.login_stack.slideInIndex(self.pages.import_egl)
|
||||
self.ui.next_button.setEnabled(self.import_page.is_valid())
|
||||
self.ui.back_button.setEnabled(True)
|
||||
self.import_radio_clicked()
|
||||
elif self.login_stack.currentIndex() == self.pages.browser:
|
||||
self.browser_page.do_login()
|
||||
elif self.login_stack.currentIndex() == self.pages.import_egl:
|
||||
|
|
|
@ -18,9 +18,6 @@ logger = getLogger("BrowserLogin")
|
|||
class BrowserLogin(QFrame):
|
||||
success = pyqtSignal()
|
||||
changed = pyqtSignal()
|
||||
login_url = (
|
||||
"https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect"
|
||||
)
|
||||
|
||||
def __init__(self, core: LegendaryCore, parent=None):
|
||||
super(BrowserLogin, self).__init__(parent=parent)
|
||||
|
@ -29,9 +26,10 @@ class BrowserLogin(QFrame):
|
|||
self.ui.setupUi(self)
|
||||
|
||||
self.core = core
|
||||
self.login_url = self.core.egs.get_auth_url()
|
||||
|
||||
self.sid_edit = IndicatorLineEdit(
|
||||
placeholder=self.tr("Insert SID here"), edit_func=self.text_changed, parent=self
|
||||
placeholder=self.tr("Insert authorizationCode here"), edit_func=self.text_changed, parent=self
|
||||
)
|
||||
self.ui.link_text.setText(self.login_url)
|
||||
self.ui.copy_button.setIcon(icon("mdi.content-copy", "fa.copy"))
|
||||
|
@ -56,7 +54,7 @@ class BrowserLogin(QFrame):
|
|||
text = text.strip()
|
||||
if text.startswith("{") and text.endswith("}"):
|
||||
try:
|
||||
text = json.loads(text).get("sid")
|
||||
text = json.loads(text).get("authorizationCode")
|
||||
except json.JSONDecodeError:
|
||||
return False, text, IndicatorLineEdit.reasons.wrong_format
|
||||
elif '"' in text:
|
||||
|
@ -67,10 +65,9 @@ class BrowserLogin(QFrame):
|
|||
|
||||
def do_login(self):
|
||||
self.ui.status_label.setText(self.tr("Logging in..."))
|
||||
sid = self.sid_edit.text()
|
||||
auth_code = self.sid_edit.text()
|
||||
try:
|
||||
token = self.core.auth_sid(sid)
|
||||
if self.core.auth_code(token):
|
||||
if self.core.auth_code(auth_code):
|
||||
logger.info(f"Successfully logged in as {self.core.lgd.userdata['displayName']}")
|
||||
self.success.emit()
|
||||
else:
|
||||
|
@ -80,13 +77,11 @@ class BrowserLogin(QFrame):
|
|||
logger.warning(e)
|
||||
|
||||
def open_browser(self):
|
||||
if webview_login.webview_available is False:
|
||||
logger.warning("You don't have webengine installed, " "you will need to manually copy the SID.")
|
||||
if not webview_login.webview_available:
|
||||
logger.warning("You don't have webengine installed, you will need to manually copy the authorizationCode.")
|
||||
QDesktopServices.openUrl(QUrl(self.login_url))
|
||||
else:
|
||||
if webview_login.do_webview_login(
|
||||
callback_sid=self.core.auth_sid, callback_code=self.core.auth_code
|
||||
):
|
||||
if webview_login.do_webview_login(callback_code=self.core.auth_ex_token):
|
||||
logger.info("Successfully logged in as " f"{self.core.lgd.userdata['displayName']}")
|
||||
self.success.emit()
|
||||
else:
|
||||
|
|
|
@ -5,6 +5,7 @@ from logging import getLogger
|
|||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QFrame, QFileDialog
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.utils.wine_helpers import read_registry, get_shell_folders
|
||||
|
||||
from rare.ui.components.dialogs.login.import_login import Ui_ImportLogin
|
||||
|
||||
|
@ -18,7 +19,7 @@ class ImportLogin(QFrame):
|
|||
localappdata = os.path.expandvars("%LOCALAPPDATA%")
|
||||
else:
|
||||
localappdata = os.path.join("drive_c/users", getuser(), "Local Settings/Application Data")
|
||||
appdata_path = os.path.join(localappdata, "EpicGamesLauncher/Saved/Config/Windows")
|
||||
egl_appdata = os.path.join(localappdata, "EpicGamesLauncher", "Saved", "Config", "Windows")
|
||||
found = False
|
||||
|
||||
def __init__(self, core: LegendaryCore, parent=None):
|
||||
|
@ -33,16 +34,19 @@ class ImportLogin(QFrame):
|
|||
self.text_egl_notfound = self.tr("Could not find EGL Program Data. ")
|
||||
|
||||
if os.name == "nt":
|
||||
if not self.core.egl.appdata_path and os.path.exists(self.appdata_path):
|
||||
self.core.egl.appdata_path = self.appdata_path
|
||||
if not self.core.egl.appdata_path and os.path.exists(self.egl_appdata):
|
||||
self.core.egl.appdata_path = self.egl_appdata
|
||||
if not self.core.egl.appdata_path:
|
||||
self.ui.status_label.setText(self.text_egl_notfound)
|
||||
else:
|
||||
self.ui.status_label.setText(self.text_egl_found)
|
||||
self.found = True
|
||||
else:
|
||||
if programdata_path := self.core.egl.programdata_path:
|
||||
if wine_pfx := programdata_path.split("drive_c")[0]:
|
||||
self.ui.prefix_combo.addItem(wine_pfx)
|
||||
self.ui.info_label.setText(
|
||||
self.tr("Please select the Wine prefix" " where Epic Games Launcher is installed. ")
|
||||
self.tr("Please select the Wine prefix where Epic Games Launcher is installed. ")
|
||||
+ self.ui.info_label.text()
|
||||
)
|
||||
prefixes = self.get_wine_prefixes()
|
||||
|
@ -62,7 +66,7 @@ class ImportLogin(QFrame):
|
|||
]
|
||||
prefixes = []
|
||||
for prefix in possible_prefixes:
|
||||
if os.path.exists(os.path.join(prefix, self.appdata_path)):
|
||||
if os.path.exists(os.path.join(prefix, self.egl_appdata)):
|
||||
prefixes.append(prefix)
|
||||
return prefixes
|
||||
|
||||
|
@ -73,18 +77,28 @@ class ImportLogin(QFrame):
|
|||
names = prefix_dialog.selectedFiles()
|
||||
self.ui.prefix_combo.setCurrentText(names[0])
|
||||
|
||||
def is_valid(self):
|
||||
def is_valid(self) -> bool:
|
||||
if os.name == "nt":
|
||||
return self.found
|
||||
else:
|
||||
return os.path.exists(os.path.join(self.ui.prefix_combo.currentText(), self.appdata_path))
|
||||
egl_wine_pfx = self.ui.prefix_combo.currentText()
|
||||
try:
|
||||
wine_folders = get_shell_folders(read_registry(egl_wine_pfx), egl_wine_pfx)
|
||||
self.egl_appdata = os.path.realpath(
|
||||
os.path.join(wine_folders['Local AppData'], 'EpicGamesLauncher', 'Saved', 'Config', 'Windows'))
|
||||
if path_exists := os.path.exists(self.egl_appdata):
|
||||
self.ui.status_label.setText(self.text_egl_found)
|
||||
return path_exists
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def do_login(self):
|
||||
self.ui.status_label.setText(self.tr("Loading..."))
|
||||
if os.name == "nt":
|
||||
pass
|
||||
else:
|
||||
self.core.egl.appdata_path = os.path.join(self.ui.prefix_combo.currentText(), self.appdata_path)
|
||||
logger.info(f'Using EGL appdata path at "{self.egl_appdata}"')
|
||||
self.core.egl.appdata_path = self.egl_appdata
|
||||
try:
|
||||
if self.core.auth_import():
|
||||
logger.info(f"Logged in as {self.core.lgd.userdata['displayName']}")
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import Qt, QSettings, QTimer, QSize
|
||||
from PyQt5.QtCore import Qt, QSettings, QTimer, QSize, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor
|
||||
from PyQt5.QtWidgets import QMainWindow, QApplication, QStatusBar, QScrollArea, QScroller, QComboBox
|
||||
from PyQt5.QtWidgets import QMainWindow, QApplication, QStatusBar, QScrollArea, QScroller, QComboBox, QMessageBox
|
||||
|
||||
from rare.components.tabs import TabWidget
|
||||
from rare.components.tray_icon import TrayIcon
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
|
||||
from rare.utils.paths import data_dir
|
||||
|
||||
logger = getLogger("Window")
|
||||
logger = getLogger("MainWindow")
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super(MainWindow, self).__init__()
|
||||
# int: exit code
|
||||
exit_app: pyqtSignal = pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(MainWindow, self).__init__(parent=parent)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||
self.core = LegendaryCoreSingleton()
|
||||
self.signals = GlobalSignalsSingleton()
|
||||
|
@ -46,8 +50,42 @@ class MainWindow(QMainWindow):
|
|||
self.timer.timeout.connect(self.timer_finished)
|
||||
self.timer.start(1000)
|
||||
|
||||
def show_window_centered(self):
|
||||
self.show()
|
||||
self.signals.exit_app.connect(self.on_exit_app)
|
||||
self.exit_code = 0
|
||||
self.accept_close = False
|
||||
|
||||
self.tray_icon: TrayIcon = TrayIcon(self)
|
||||
self.tray_icon.exit_action.triggered.connect(self.on_exit_app)
|
||||
self.tray_icon.start_rare.triggered.connect(self.show)
|
||||
self.tray_icon.activated.connect(
|
||||
lambda r: self.toggle()
|
||||
if r == self.tray_icon.DoubleClick
|
||||
else None
|
||||
)
|
||||
|
||||
self.signals.send_notification.connect(
|
||||
lambda title: self.tray_icon.showMessage(
|
||||
self.tr("Download finished"),
|
||||
self.tr("Download finished. {} is playable now").format(title),
|
||||
self.tray_icon.Information,
|
||||
4000,
|
||||
)
|
||||
if self.settings.value("notification", True, bool)
|
||||
else None
|
||||
)
|
||||
|
||||
self.window_launched = False
|
||||
|
||||
# enable kinetic scrolling
|
||||
for scroll_area in self.findChildren(QScrollArea):
|
||||
if not scroll_area.property("no_kinetic_scroll"):
|
||||
QScroller.grabGesture(scroll_area.viewport(), QScroller.LeftMouseButtonGesture)
|
||||
|
||||
# fix scrolling
|
||||
for combo_box in scroll_area.findChildren(QComboBox):
|
||||
combo_box.wheelEvent = lambda e: e.ignore()
|
||||
|
||||
def center_window(self):
|
||||
# get the margins of the decorated window
|
||||
margins = self.windowHandle().frameMargins()
|
||||
# get the screen the cursor is on
|
||||
|
@ -68,14 +106,23 @@ class MainWindow(QMainWindow):
|
|||
- self.rect().adjusted(0, 0, decor_width, decor_height).center()
|
||||
)
|
||||
|
||||
# enable kinetic scrolling
|
||||
for scroll_area in self.findChildren(QScrollArea):
|
||||
if not scroll_area.property("no_kinetic_scroll"):
|
||||
QScroller.grabGesture(scroll_area.viewport(), QScroller.LeftMouseButtonGesture)
|
||||
def show(self) -> None:
|
||||
super(MainWindow, self).show()
|
||||
if not self.window_launched:
|
||||
self.center_window()
|
||||
self.window_launched = True
|
||||
|
||||
# fix scrolling
|
||||
for combo_box in scroll_area.findChildren(QComboBox):
|
||||
combo_box.wheelEvent = lambda e: e.ignore()
|
||||
def hide(self) -> None:
|
||||
if self.settings.value("save_size", False, bool):
|
||||
size = self.size().width(), self.size().height()
|
||||
self.settings.setValue("window_size", size)
|
||||
super(MainWindow, self).hide()
|
||||
|
||||
def toggle(self):
|
||||
if self.isHidden():
|
||||
self.show()
|
||||
else:
|
||||
self.hide()
|
||||
|
||||
def timer_finished(self):
|
||||
file_path = os.path.join(data_dir, "lockfile")
|
||||
|
@ -83,30 +130,48 @@ class MainWindow(QMainWindow):
|
|||
file = open(file_path, "r")
|
||||
action = file.read()
|
||||
file.close()
|
||||
if action.startswith("launch"):
|
||||
game = action.replace("launch ", "").replace("\n", "")
|
||||
if game in [
|
||||
i.app_name for i in self.tab_widget.games_tab.game_list
|
||||
] and self.core.is_installed(game):
|
||||
self.tab_widget.games_tab.game_utils.prepare_launch(
|
||||
game, offline=self.args.offline
|
||||
)
|
||||
else:
|
||||
logger.info(f"Could not find {game} in Games")
|
||||
elif action.startswith("start"):
|
||||
if action.startswith("show"):
|
||||
self.show()
|
||||
os.remove(file_path)
|
||||
self.timer.start(1000)
|
||||
|
||||
@pyqtSlot()
|
||||
@pyqtSlot(int)
|
||||
def on_exit_app(self, exit_code=0) -> None:
|
||||
# FIXME: Fix this with the download tab redesign
|
||||
if not self.args.offline and self.tab_widget.downloadTab.is_download_active:
|
||||
question = QMessageBox.question(
|
||||
self,
|
||||
self.tr("Close"),
|
||||
self.tr(
|
||||
"There is a download active. Do you really want to exit app?"
|
||||
),
|
||||
QMessageBox.Yes,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if question == QMessageBox.No:
|
||||
return
|
||||
else:
|
||||
# clear queue
|
||||
self.tab_widget.downloadTab.queue_widget.update_queue([])
|
||||
self.tab_widget.downloadTab.stop_download()
|
||||
# FIXME: End of FIXME
|
||||
self.exit_code = exit_code
|
||||
self.close()
|
||||
|
||||
def close(self) -> bool:
|
||||
self.accept_close = True
|
||||
return super(MainWindow, self).close()
|
||||
|
||||
def closeEvent(self, e: QCloseEvent):
|
||||
if self.settings.value("save_size", False, bool):
|
||||
size = self.size().width(), self.size().height()
|
||||
self.settings.setValue("window_size", size)
|
||||
if self.settings.value("sys_tray", True, bool):
|
||||
self.hide()
|
||||
e.ignore()
|
||||
return
|
||||
elif self.args.offline:
|
||||
pass
|
||||
self.signals.exit_app.emit(0)
|
||||
e.ignore()
|
||||
if not self.accept_close:
|
||||
if self.settings.value("sys_tray", True, bool):
|
||||
self.hide()
|
||||
e.ignore()
|
||||
return
|
||||
self.timer.stop()
|
||||
self.tray_icon.deleteLater()
|
||||
self.hide()
|
||||
self.exit_app.emit(self.exit_code)
|
||||
super(MainWindow, self).closeEvent(e)
|
||||
e.accept()
|
||||
|
|
|
@ -98,7 +98,7 @@ class DownloadThread(QThread):
|
|||
# postinstall,
|
||||
# self.item.download.igame,
|
||||
# False,
|
||||
# self.item.options.install_preqs,
|
||||
# self.item.options.install_prereqs,
|
||||
# )
|
||||
self._handle_postinstall(postinstall, self.item.download.igame)
|
||||
|
||||
|
@ -140,7 +140,7 @@ class DownloadThread(QThread):
|
|||
logger.info("This game lists the following prequisites to be installed:")
|
||||
logger.info(f'- {postinstall["name"]}: {" ".join((postinstall["path"], postinstall["args"]))}')
|
||||
if platform.system() == "Windows":
|
||||
if not self.item.options.install_preqs:
|
||||
if not self.item.options.install_prereqs:
|
||||
logger.info("Marking prerequisites as installed...")
|
||||
self.core.prereq_installed(self.item.download.igame.app_name)
|
||||
else:
|
||||
|
|
|
@ -11,7 +11,7 @@ from rare.shared import (
|
|||
ArgumentsSingleton,
|
||||
ApiResultsSingleton,
|
||||
)
|
||||
from rare.shared.image_manager import ImageManagerSingleton
|
||||
from rare.shared import ImageManagerSingleton
|
||||
from rare.widgets.library_layout import LibraryLayout
|
||||
from rare.widgets.sliding_stack import SlidingStackedWidget
|
||||
from .cloud_save_utils import CloudSaveUtils
|
||||
|
|
|
@ -3,8 +3,8 @@ from PyQt5.QtWidgets import QFrame, QWidget, QMessageBox
|
|||
from legendary.models.game import Game
|
||||
|
||||
from rare.components.tabs.games.game_utils import GameUtils
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.ui.components.tabs.games.game_info.game_dlc import Ui_GameDlc
|
||||
from rare.ui.components.tabs.games.game_info.game_dlc_widget import Ui_GameDlcWidget
|
||||
from rare.models.install import InstallOptionsModel
|
||||
|
|
|
@ -27,7 +27,8 @@ from rare.shared import (
|
|||
GlobalSignalsSingleton,
|
||||
ArgumentsSingleton,
|
||||
)
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
||||
from rare.utils.legendary_utils import VerifyWorker
|
||||
from rare.utils.misc import get_size
|
||||
|
|
|
@ -11,7 +11,8 @@ from rare.shared import (
|
|||
ArgumentsSingleton,
|
||||
ApiResultsSingleton,
|
||||
)
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
||||
from rare.utils.extra_widgets import SideTabWidget
|
||||
from rare.utils.json_formatter import QJsonModel
|
||||
|
|
|
@ -7,8 +7,8 @@ from PyQt5.QtGui import QPixmap
|
|||
from PyQt5.QtWidgets import QFrame, QMessageBox, QAction
|
||||
|
||||
from rare.components.tabs.games.game_utils import GameUtils
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.utils.misc import create_desktop_link
|
||||
from rare.widgets.image_widget import ImageWidget
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ from PyQt5.QtCore import pyqtSignal, Qt
|
|||
from PyQt5.QtWidgets import QFrame, QAction
|
||||
from legendary.models.game import Game
|
||||
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.widgets.image_widget import ImageWidget
|
||||
|
||||
logger = getLogger("Uninstalled")
|
||||
|
|
|
@ -3,8 +3,8 @@ from PyQt5.QtGui import QPixmap
|
|||
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QFrame
|
||||
from legendary.models.game import Game
|
||||
|
||||
from rare.shared import LegendaryCoreSingleton
|
||||
from rare.shared.image_manager import ImageManagerSingleton, ImageSize
|
||||
from rare.shared import LegendaryCoreSingleton, ImageManagerSingleton
|
||||
from rare.shared.image_manager import ImageSize
|
||||
from rare.widgets.elide_label import ElideLabel
|
||||
from .library_widget import LibraryWidget
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton
|
||||
|
||||
from rare.shared import GlobalSignalsSingleton
|
||||
|
||||
|
||||
class DebugSettings(QWidget):
|
||||
def __init__(self):
|
||||
|
@ -9,6 +11,9 @@ class DebugSettings(QWidget):
|
|||
self.raise_runtime_exception_button = QPushButton("Raise Exception")
|
||||
self.layout().addWidget(self.raise_runtime_exception_button)
|
||||
self.raise_runtime_exception_button.clicked.connect(self.raise_exception)
|
||||
self.restart_button = QPushButton("Restart")
|
||||
self.layout().addWidget(self.restart_button)
|
||||
self.restart_button.clicked.connect(lambda: GlobalSignalsSingleton().exit_app.emit(-133742))
|
||||
|
||||
self.layout().addStretch(1)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ logger = getLogger("TrayIcon")
|
|||
|
||||
class TrayIcon(QSystemTrayIcon):
|
||||
def __init__(self, parent):
|
||||
super(TrayIcon, self).__init__(parent)
|
||||
super(TrayIcon, self).__init__(parent=parent)
|
||||
self.core = LegendaryCoreSingleton()
|
||||
|
||||
self.setIcon(QIcon(":/images/Rare.png"))
|
||||
|
@ -33,7 +33,7 @@ class TrayIcon(QSystemTrayIcon):
|
|||
if len(installed := self.core.get_installed_list()) < 5:
|
||||
last_played = [GameMeta(i.app_name) for i in sorted(installed, key=lambda x: x.title)]
|
||||
elif games := sorted(
|
||||
parent.mainwindow.tab_widget.games_tab.game_utils.game_meta.get_games(),
|
||||
parent.tab_widget.games_tab.game_utils.game_meta.get_games(),
|
||||
key=lambda x: x.last_played, reverse=True):
|
||||
last_played: List[GameMeta] = games[0:5]
|
||||
else:
|
||||
|
@ -46,7 +46,7 @@ class TrayIcon(QSystemTrayIcon):
|
|||
a.setProperty("app_name", game.app_name)
|
||||
self.game_actions.append(a)
|
||||
a.triggered.connect(
|
||||
lambda: parent.mainwindow.tab_widget.games_tab.game_utils.prepare_launch(
|
||||
lambda: parent.tab_widget.games_tab.game_utils.prepare_launch(
|
||||
self.sender().property("app_name"))
|
||||
)
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QRunnable, QThread
|
|||
from PyQt5.QtGui import QDesktopServices
|
||||
from PyQt5.QtNetwork import QLocalServer, QLocalSocket
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
from rare.widgets.rare_app import RareApp
|
||||
from .console import Console
|
||||
from .lgd_helper import get_launch_args, InitArgs, get_configured_process, LaunchArgs, GameArgsError
|
||||
from .message_models import ErrorModel, Actions, FinishedModel, BaseModel, StateChangedModel
|
||||
from ..shared import LegendaryCoreSingleton
|
||||
from ..widgets.rare_app import RareApp
|
||||
|
||||
|
||||
class PreLaunchThread(QRunnable):
|
||||
|
@ -25,9 +25,9 @@ class PreLaunchThread(QRunnable):
|
|||
pre_launch_command_finished = pyqtSignal(int) # exit_code
|
||||
error_occurred = pyqtSignal(str)
|
||||
|
||||
def __init__(self, args: InitArgs):
|
||||
def __init__(self, core: LegendaryCore, args: InitArgs):
|
||||
super(PreLaunchThread, self).__init__()
|
||||
self.core = LegendaryCoreSingleton()
|
||||
self.core = core
|
||||
self.app_name = args.app_name
|
||||
self.signals = self.Signals()
|
||||
|
||||
|
@ -69,7 +69,7 @@ class GameProcessApp(RareApp):
|
|||
self.game_process = QProcess()
|
||||
self.app_name = app_name
|
||||
self.logger = getLogger(self.app_name)
|
||||
self.core = LegendaryCoreSingleton(init=True)
|
||||
self.core = LegendaryCore()
|
||||
|
||||
lang = self.settings.value("language", self.core.language_code, type=str)
|
||||
self.load_translator(lang)
|
||||
|
@ -187,7 +187,7 @@ class GameProcessApp(RareApp):
|
|||
self.logger.error("Not logged in. Try to launch game offline")
|
||||
args.offline = True
|
||||
|
||||
worker = PreLaunchThread(args)
|
||||
worker = PreLaunchThread(self.core, args)
|
||||
worker.signals.ready_to_launch.connect(self.launch_game)
|
||||
worker.signals.error_occurred.connect(self.error_occurred)
|
||||
# worker.signals.started_pre_launch_command(None)
|
||||
|
|
|
@ -6,9 +6,11 @@ from logging import getLogger
|
|||
from typing import List
|
||||
|
||||
from PyQt5.QtCore import QProcess, QProcessEnvironment
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.models.game import InstalledGame, LaunchParameters
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
|
||||
|
||||
logger = getLogger("Helper")
|
||||
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ class LgndrInstallGameRealArgs:
|
|||
dlm_debug: bool = False
|
||||
yes: bool = False
|
||||
# Rare: Extra arguments
|
||||
install_preqs: bool = False
|
||||
install_prereqs: bool = False
|
||||
indirect_status: LgndrIndirectStatus = LgndrIndirectStatus()
|
||||
ui_update: Callable[[UIUpdate], None] = lambda ui: None
|
||||
dlm_signals: DLManagerSignals = DLManagerSignals()
|
||||
|
|
|
@ -248,7 +248,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
|
||||
postinstall = self.core.install_game(igame)
|
||||
if postinstall:
|
||||
self._handle_postinstall(postinstall, igame, yes=args.yes, choice=args.install_preqs)
|
||||
self._handle_postinstall(postinstall, igame, skip_prereqs=args.yes, choice=args.install_prereqs)
|
||||
|
||||
dlcs = self.core.get_dlc_for_game(game.app_name)
|
||||
if dlcs and not args.skip_dlcs:
|
||||
|
@ -301,7 +301,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
self.core.uninstall_tag(old_igame)
|
||||
self.core.install_game(old_igame)
|
||||
|
||||
def _handle_postinstall(self, postinstall, igame, yes=False, choice=True):
|
||||
def _handle_postinstall(self, postinstall, igame, skip_prereqs=False, choice=True):
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(LgndrIndirectStatus(), self.logger)
|
||||
# noinspection PyShadowingBuiltins
|
||||
|
@ -309,12 +309,12 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
# noinspection PyShadowingBuiltins
|
||||
def input(x): return 'y' if choice else 'i'
|
||||
|
||||
print('\nThis game lists the following prequisites to be installed:')
|
||||
print('\nThis game lists the following prerequisites to be installed:')
|
||||
print(f'- {postinstall["name"]}: {" ".join((postinstall["path"], postinstall["args"]))}')
|
||||
print('')
|
||||
|
||||
if os.name == 'nt':
|
||||
if yes:
|
||||
if skip_prereqs:
|
||||
c = 'n' # we don't want to launch anything, just silent install.
|
||||
else:
|
||||
choice = input('Do you wish to install the prerequisites? ([y]es, [n]o, [i]gnore): ')
|
||||
|
|
|
@ -31,7 +31,7 @@ class InstallOptionsModel:
|
|||
overlay: bool = False
|
||||
update: bool = False
|
||||
silent: bool = False
|
||||
install_preqs: bool = pf.system() == "Windows"
|
||||
install_prereqs: bool = pf.system() == "Windows"
|
||||
|
||||
def __post_init__(self):
|
||||
self.sdl_prompt: Callable[[str, str], list] = \
|
||||
|
@ -41,7 +41,7 @@ class InstallOptionsModel:
|
|||
return {
|
||||
k: getattr(self, k)
|
||||
for k in self.__dict__
|
||||
if k not in ["update", "silent", "create_shortcut", "overlay", "install_preqs"]
|
||||
if k not in ["update", "silent", "create_shortcut", "overlay", "install_prereqs"]
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,52 +5,34 @@ Each of the objects in this module should be instantiated ONCE
|
|||
and only ONCE!
|
||||
"""
|
||||
|
||||
import logging
|
||||
from argparse import Namespace
|
||||
from typing import Optional
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
|
||||
from rare.models.apiresults import ApiResults
|
||||
from rare.models.signals import GlobalSignals
|
||||
from .image_manager import ImageManager
|
||||
from .rare_core import RareCore
|
||||
|
||||
_legendary_core_singleton: Optional[LegendaryCore] = None
|
||||
_global_signals_singleton: Optional[GlobalSignals] = None
|
||||
_arguments_singleton: Optional[Namespace] = None
|
||||
_api_results_singleton: Optional[ApiResults] = None
|
||||
logger = logging.getLogger("Shared")
|
||||
|
||||
|
||||
def LegendaryCoreSingleton(init: bool = False) -> LegendaryCore:
|
||||
global _legendary_core_singleton
|
||||
if _legendary_core_singleton is None and not init:
|
||||
raise RuntimeError("Uninitialized use of LegendaryCoreSingleton")
|
||||
if _legendary_core_singleton is None:
|
||||
_legendary_core_singleton = LegendaryCore()
|
||||
return _legendary_core_singleton
|
||||
def ArgumentsSingleton() -> Optional[Namespace]:
|
||||
return RareCore.instance().args()
|
||||
|
||||
|
||||
def GlobalSignalsSingleton(init: bool = False) -> GlobalSignals:
|
||||
global _global_signals_singleton
|
||||
if _global_signals_singleton is None and not init:
|
||||
raise RuntimeError("Uninitialized use of GlobalSignalsSingleton")
|
||||
if _global_signals_singleton is None:
|
||||
_global_signals_singleton = GlobalSignals()
|
||||
return _global_signals_singleton
|
||||
def GlobalSignalsSingleton() -> GlobalSignals:
|
||||
return RareCore.instance().signals()
|
||||
|
||||
|
||||
def ArgumentsSingleton(args: Namespace = None) -> Optional[Namespace]:
|
||||
global _arguments_singleton
|
||||
if _arguments_singleton is None and args is None:
|
||||
raise RuntimeError("Uninitialized use of ArgumentsSingleton")
|
||||
if _arguments_singleton is None:
|
||||
_arguments_singleton = args
|
||||
return _arguments_singleton
|
||||
def LegendaryCoreSingleton() -> LegendaryCore:
|
||||
return RareCore.instance().core()
|
||||
|
||||
|
||||
def ImageManagerSingleton() -> ImageManager:
|
||||
return RareCore.instance().image_manager()
|
||||
|
||||
|
||||
def ApiResultsSingleton(res: ApiResults = None) -> Optional[ApiResults]:
|
||||
global _api_results_singleton
|
||||
if _api_results_singleton is None and res is None:
|
||||
raise RuntimeError("Uninitialized use of ApiResultsSingleton")
|
||||
if _api_results_singleton is None:
|
||||
_api_results_singleton = res
|
||||
return _api_results_singleton
|
||||
|
||||
return RareCore.instance().api_results(res)
|
||||
|
|
|
@ -7,7 +7,7 @@ import zlib
|
|||
from logging import getLogger
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Tuple, Dict, Union, Type, List, Callable, Optional
|
||||
from typing import Tuple, Dict, Union, Type, List, Callable
|
||||
|
||||
import requests
|
||||
from PyQt5.QtCore import (
|
||||
|
@ -26,7 +26,8 @@ from PyQt5.QtGui import (
|
|||
from PyQt5.QtWidgets import QApplication
|
||||
from legendary.models.game import Game
|
||||
|
||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
from rare.models.signals import GlobalSignals
|
||||
from rare.utils.paths import image_dir, resources_path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -111,10 +112,10 @@ class ImageManager(QObject):
|
|||
__dl_retries = 1
|
||||
__worker_app_names: List[str] = list()
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, signals: GlobalSignals, core: LegendaryCore):
|
||||
super(QObject, self).__init__()
|
||||
self.core = LegendaryCoreSingleton()
|
||||
self.signals = GlobalSignalsSingleton()
|
||||
self.signals = signals
|
||||
self.core = core
|
||||
|
||||
self.image_dir = Path(image_dir)
|
||||
if not self.image_dir.is_dir():
|
||||
|
@ -357,15 +358,3 @@ class ImageManager(QObject):
|
|||
"""
|
||||
image: QImage = self.__get_cover(QImage, app_name, color)
|
||||
return image
|
||||
|
||||
|
||||
_image_manager_singleton: Optional[ImageManager] = None
|
||||
|
||||
|
||||
def ImageManagerSingleton(init: bool = False) -> ImageManager:
|
||||
global _image_manager_singleton
|
||||
if _image_manager_singleton is None and not init:
|
||||
raise RuntimeError("Uninitialized use of ImageManagerSingleton")
|
||||
if _image_manager_singleton is None:
|
||||
_image_manager_singleton = ImageManager()
|
||||
return _image_manager_singleton
|
||||
|
|
133
rare/shared/rare_core.py
Normal file
133
rare/shared/rare_core.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
import configparser
|
||||
import os
|
||||
from argparse import Namespace
|
||||
from logging import getLogger
|
||||
from typing import Optional
|
||||
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
from rare.models.apiresults import ApiResults
|
||||
from rare.models.signals import GlobalSignals
|
||||
from .image_manager import ImageManager
|
||||
|
||||
logger = getLogger("RareCore")
|
||||
|
||||
|
||||
class RareCore(QObject):
|
||||
_instance: Optional['RareCore'] = None
|
||||
|
||||
def __init__(self, args: Namespace):
|
||||
if self._instance is not None:
|
||||
raise RuntimeError("RareCore already initialized")
|
||||
super(RareCore, self).__init__()
|
||||
self._args: Optional[Namespace] = None
|
||||
self._signals: Optional[GlobalSignals] = None
|
||||
self._core: Optional[LegendaryCore] = None
|
||||
self._image_manager: Optional[ImageManager] = None
|
||||
self._api_results: Optional[ApiResults] = None
|
||||
|
||||
self.args(args)
|
||||
self.signals(init=True)
|
||||
self.core(init=True)
|
||||
self.image_manager(init=True)
|
||||
|
||||
RareCore._instance = self
|
||||
|
||||
@staticmethod
|
||||
def instance() -> 'RareCore':
|
||||
if RareCore._instance is None:
|
||||
raise RuntimeError("Uninitialized use of RareCore")
|
||||
return RareCore._instance
|
||||
|
||||
def signals(self, init: bool = False) -> GlobalSignals:
|
||||
if self._signals is None and not init:
|
||||
raise RuntimeError("Uninitialized use of GlobalSignalsSingleton")
|
||||
if self._signals is not None and init:
|
||||
raise RuntimeError("GlobalSignals already initialized")
|
||||
if init:
|
||||
self._signals = GlobalSignals()
|
||||
return self._signals
|
||||
|
||||
def args(self, args: Namespace = None) -> Optional[Namespace]:
|
||||
if self._args is None and args is None:
|
||||
raise RuntimeError("Uninitialized use of ArgumentsSingleton")
|
||||
if self._args is not None and args is not None:
|
||||
raise RuntimeError("Arguments already initialized")
|
||||
if args is not None:
|
||||
self._args = args
|
||||
return self._args
|
||||
|
||||
def core(self, init: bool = False) -> LegendaryCore:
|
||||
if self._core is None and not init:
|
||||
raise RuntimeError("Uninitialized use of LegendaryCoreSingleton")
|
||||
if self._core is not None and init:
|
||||
raise RuntimeError("LegendaryCore already initialized")
|
||||
if init:
|
||||
try:
|
||||
self._core = LegendaryCore()
|
||||
except configparser.MissingSectionHeaderError as e:
|
||||
logger.warning(f"Config is corrupt: {e}")
|
||||
if config_path := os.environ.get("XDG_CONFIG_HOME"):
|
||||
path = os.path.join(config_path, "legendary")
|
||||
else:
|
||||
path = os.path.expanduser("~/.config/legendary")
|
||||
with open(os.path.join(path, "config.ini"), "w") as config_file:
|
||||
config_file.write("[Legendary]")
|
||||
self._core = LegendaryCore()
|
||||
if "Legendary" not in self._core.lgd.config.sections():
|
||||
self._core.lgd.config.add_section("Legendary")
|
||||
self._core.lgd.save_config()
|
||||
# workaround if egl sync enabled, but no programdata_path
|
||||
# programdata_path might be unset if logging in through the browser
|
||||
if self._core.egl_sync_enabled:
|
||||
if self._core.egl.programdata_path is None:
|
||||
self._core.lgd.config.remove_option("Legendary", "egl_sync")
|
||||
self._core.lgd.save_config()
|
||||
else:
|
||||
if not os.path.exists(self._core.egl.programdata_path):
|
||||
self._core.lgd.config.remove_option("Legendary", "egl_sync")
|
||||
self._core.lgd.save_config()
|
||||
return self._core
|
||||
|
||||
def image_manager(self, init: bool = False) -> ImageManager:
|
||||
if self._image_manager is None and not init:
|
||||
raise RuntimeError("Uninitialized use of ImageManagerSingleton")
|
||||
if self._image_manager is not None and init:
|
||||
raise RuntimeError("ImageManager already initialized")
|
||||
if self._image_manager is None:
|
||||
self._image_manager = ImageManager(self.signals(), self.core())
|
||||
return self._image_manager
|
||||
|
||||
def api_results(self, res: ApiResults = None) -> Optional[ApiResults]:
|
||||
if self._api_results is None and res is None:
|
||||
raise RuntimeError("Uninitialized use of ApiResultsSingleton")
|
||||
if self._api_results is not None and res is not None:
|
||||
raise RuntimeError("ApiResults already initialized")
|
||||
if res is not None:
|
||||
self._api_results = res
|
||||
return self._api_results
|
||||
|
||||
def deleteLater(self) -> None:
|
||||
del self._api_results
|
||||
self._api_results = None
|
||||
|
||||
self._image_manager.deleteLater()
|
||||
del self._image_manager
|
||||
self._image_manager = None
|
||||
|
||||
self._core.exit()
|
||||
del self._core
|
||||
self._core = None
|
||||
|
||||
self._signals.deleteLater()
|
||||
del self._signals
|
||||
self._signals = None
|
||||
|
||||
del self._args
|
||||
self._args = None
|
||||
|
||||
RareCore._instance = None
|
||||
|
||||
super(RareCore, self).deleteLater()
|
||||
|
|
@ -109,17 +109,17 @@ class Ui_InstallDialog(object):
|
|||
self.max_memory_info_label.setObjectName("max_memory_info_label")
|
||||
self.max_memory_layout.addWidget(self.max_memory_info_label)
|
||||
self.advanced_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.max_memory_layout)
|
||||
self.install_preqs_lbl = QtWidgets.QLabel(InstallDialog)
|
||||
self.install_preqs_lbl.setObjectName("install_preqs_lbl")
|
||||
self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_preqs_lbl)
|
||||
self.install_preqs_check = QtWidgets.QCheckBox(InstallDialog)
|
||||
self.install_prereqs_lbl = QtWidgets.QLabel(InstallDialog)
|
||||
self.install_prereqs_lbl.setObjectName("install_prereqs_lbl")
|
||||
self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_prereqs_lbl)
|
||||
self.install_prereqs_check = QtWidgets.QCheckBox(InstallDialog)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.install_preqs_check.setFont(font)
|
||||
self.install_preqs_check.setText("")
|
||||
self.install_preqs_check.setChecked(False)
|
||||
self.install_preqs_check.setObjectName("install_preqs_check")
|
||||
self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.install_preqs_check)
|
||||
self.install_prereqs_check.setFont(font)
|
||||
self.install_prereqs_check.setText("")
|
||||
self.install_prereqs_check.setChecked(False)
|
||||
self.install_prereqs_check.setObjectName("install_prereqs_check")
|
||||
self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.install_prereqs_check)
|
||||
self.dl_optimizations_label = QtWidgets.QLabel(InstallDialog)
|
||||
self.dl_optimizations_label.setObjectName("dl_optimizations_label")
|
||||
self.advanced_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.dl_optimizations_label)
|
||||
|
@ -216,7 +216,7 @@ class Ui_InstallDialog(object):
|
|||
self.max_memory_label.setText(_translate("InstallDialog", "Max shared memory"))
|
||||
self.max_memory_spin.setSuffix(_translate("InstallDialog", "MiB"))
|
||||
self.max_memory_info_label.setText(_translate("InstallDialog", "Less is slower (0: Default)"))
|
||||
self.install_preqs_lbl.setText(_translate("InstallDialog", "Install prerequisites"))
|
||||
self.install_prereqs_lbl.setText(_translate("InstallDialog", "Install prerequisites"))
|
||||
self.dl_optimizations_label.setText(_translate("InstallDialog", "Enable reordering"))
|
||||
self.force_download_label.setText(_translate("InstallDialog", "Force redownload"))
|
||||
self.ignore_space_label.setText(_translate("InstallDialog", "Ignore free space"))
|
||||
|
|
|
@ -185,14 +185,14 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="install_preqs_lbl">
|
||||
<widget class="QLabel" name="install_prereqs_lbl">
|
||||
<property name="text">
|
||||
<string>Install prerequisites</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="install_preqs_check">
|
||||
<widget class="QCheckBox" name="install_prereqs_check">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
|
|
|
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_InstallDialogAdvanced(object):
|
||||
def setupUi(self, InstallDialogAdvanced):
|
||||
InstallDialogAdvanced.setObjectName("InstallDialogAdvanced")
|
||||
InstallDialogAdvanced.resize(359, 208)
|
||||
InstallDialogAdvanced.resize(379, 208)
|
||||
self.install_dialog_advanced_layout = QtWidgets.QFormLayout(InstallDialogAdvanced)
|
||||
self.install_dialog_advanced_layout.setObjectName("install_dialog_advanced_layout")
|
||||
self.max_workers_label = QtWidgets.QLabel(InstallDialogAdvanced)
|
||||
|
@ -63,17 +63,17 @@ class Ui_InstallDialogAdvanced(object):
|
|||
self.max_memory_info_label.setObjectName("max_memory_info_label")
|
||||
self.max_memory_layout.addWidget(self.max_memory_info_label)
|
||||
self.install_dialog_advanced_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.max_memory_layout)
|
||||
self.install_preqs_lbl = QtWidgets.QLabel(InstallDialogAdvanced)
|
||||
self.install_preqs_lbl.setObjectName("install_preqs_lbl")
|
||||
self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_preqs_lbl)
|
||||
self.install_preqs_check = QtWidgets.QCheckBox(InstallDialogAdvanced)
|
||||
self.install_prereqs_lbl = QtWidgets.QLabel(InstallDialogAdvanced)
|
||||
self.install_prereqs_lbl.setObjectName("install_prereqs_lbl")
|
||||
self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_prereqs_lbl)
|
||||
self.install_prereqs_check = QtWidgets.QCheckBox(InstallDialogAdvanced)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.install_preqs_check.setFont(font)
|
||||
self.install_preqs_check.setText("")
|
||||
self.install_preqs_check.setChecked(False)
|
||||
self.install_preqs_check.setObjectName("install_preqs_check")
|
||||
self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.install_preqs_check)
|
||||
self.install_prereqs_check.setFont(font)
|
||||
self.install_prereqs_check.setText("")
|
||||
self.install_prereqs_check.setChecked(False)
|
||||
self.install_prereqs_check.setObjectName("install_prereqs_check")
|
||||
self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.install_prereqs_check)
|
||||
self.dl_optimizations_label = QtWidgets.QLabel(InstallDialogAdvanced)
|
||||
self.dl_optimizations_label.setObjectName("dl_optimizations_label")
|
||||
self.install_dialog_advanced_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.dl_optimizations_label)
|
||||
|
@ -119,7 +119,7 @@ class Ui_InstallDialogAdvanced(object):
|
|||
self.max_memory_label.setText(_translate("InstallDialogAdvanced", "Max shared memory"))
|
||||
self.max_memory_spin.setSuffix(_translate("InstallDialogAdvanced", "MiB"))
|
||||
self.max_memory_info_label.setText(_translate("InstallDialogAdvanced", "Less is slower (0: Default)"))
|
||||
self.install_preqs_lbl.setText(_translate("InstallDialogAdvanced", "Install prerequisites"))
|
||||
self.install_prereqs_lbl.setText(_translate("InstallDialogAdvanced", "Install prerequisites"))
|
||||
self.dl_optimizations_label.setText(_translate("InstallDialogAdvanced", "Enable reordering"))
|
||||
self.force_download_label.setText(_translate("InstallDialogAdvanced", "Force redownload"))
|
||||
self.ignore_space_label.setText(_translate("InstallDialogAdvanced", "Ignore free space"))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>359</width>
|
||||
<width>379</width>
|
||||
<height>208</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -102,14 +102,14 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="install_preqs_lbl">
|
||||
<widget class="QLabel" name="install_prereqs_lbl">
|
||||
<property name="text">
|
||||
<string>Install prerequisites</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="install_preqs_check">
|
||||
<widget class="QCheckBox" name="install_prereqs_check">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
|
|
|
@ -14,12 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_BrowserLogin(object):
|
||||
def setupUi(self, BrowserLogin):
|
||||
BrowserLogin.setObjectName("BrowserLogin")
|
||||
BrowserLogin.resize(400, 200)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(BrowserLogin.sizePolicy().hasHeightForWidth())
|
||||
BrowserLogin.setSizePolicy(sizePolicy)
|
||||
BrowserLogin.resize(182, 210)
|
||||
BrowserLogin.setWindowTitle("BrowserLogin")
|
||||
self.browser_layout = QtWidgets.QGridLayout(BrowserLogin)
|
||||
self.browser_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||
|
@ -78,7 +73,7 @@ class Ui_BrowserLogin(object):
|
|||
_translate = QtCore.QCoreApplication.translate
|
||||
self.open_button.setText(_translate("BrowserLogin", "Open Browser"))
|
||||
self.title_label.setText(_translate("BrowserLogin", "Login through browser"))
|
||||
self.info_label.setText(_translate("BrowserLogin", "Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the SID code in the input above."))
|
||||
self.info_label.setText(_translate("BrowserLogin", "Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the <b><code>authorizationCode</code></b> in the input above."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>246</width>
|
||||
<height>184</height>
|
||||
<width>182</width>
|
||||
<height>210</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -94,7 +94,7 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the SID code in the input above.</string>
|
||||
<string>Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the <b><code>authorizationCode</code></b> in the input above.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -14,12 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_ImportLogin(object):
|
||||
def setupUi(self, ImportLogin):
|
||||
ImportLogin.setObjectName("ImportLogin")
|
||||
ImportLogin.resize(400, 200)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(ImportLogin.sizePolicy().hasHeightForWidth())
|
||||
ImportLogin.setSizePolicy(sizePolicy)
|
||||
ImportLogin.resize(242, 120)
|
||||
ImportLogin.setWindowTitle("ImportLogin")
|
||||
self.import_layout = QtWidgets.QGridLayout(ImportLogin)
|
||||
self.import_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||
|
@ -51,6 +46,7 @@ class Ui_ImportLogin(object):
|
|||
font.setItalic(True)
|
||||
self.status_label.setFont(font)
|
||||
self.status_label.setText("")
|
||||
self.status_label.setWordWrap(True)
|
||||
self.status_label.setObjectName("status_label")
|
||||
self.import_layout.addWidget(self.status_label, 2, 1, 1, 2)
|
||||
self.info_label = QtWidgets.QLabel(ImportLogin)
|
||||
|
@ -68,7 +64,7 @@ class Ui_ImportLogin(object):
|
|||
|
||||
def retranslateUi(self, ImportLogin):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.prefix_label.setText(_translate("ImportLogin", "Select path"))
|
||||
self.prefix_label.setText(_translate("ImportLogin", "Select prefix"))
|
||||
self.title_label.setText(_translate("ImportLogin", "Import existing session from EGL"))
|
||||
self.prefix_tool.setText(_translate("ImportLogin", "Browse"))
|
||||
self.info_label.setText(_translate("ImportLogin", "You will get logged out from EGL in the process."))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>235</width>
|
||||
<width>242</width>
|
||||
<height>120</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="prefix_label">
|
||||
<property name="text">
|
||||
<string>Select path</string>
|
||||
<string>Select prefix</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
from typing import Callable
|
||||
from typing import Callable, Optional
|
||||
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.utils.config import LGDConf
|
||||
|
||||
config: LGDConf = None
|
||||
save_config: Callable[[], None] = None
|
||||
_config: Optional[LGDConf] = None
|
||||
_save_config: Optional[Callable[[], None]] = None
|
||||
|
||||
|
||||
def init_config_handler(core: LegendaryCore):
|
||||
global config, save_config
|
||||
config = core.lgd.config
|
||||
save_config = core.lgd.save_config
|
||||
global _config, _save_config
|
||||
_config = core.lgd.config
|
||||
_save_config = core.lgd.save_config
|
||||
|
||||
|
||||
def add_option(app_name: str, option: str, value: str):
|
||||
value = value.replace("%%", "%").replace("%", "%%")
|
||||
if not config.has_section(app_name):
|
||||
config[app_name] = {}
|
||||
if not _config.has_section(app_name):
|
||||
_config[app_name] = {}
|
||||
|
||||
config.set(app_name, option, value)
|
||||
save_config()
|
||||
_config.set(app_name, option, value)
|
||||
_save_config()
|
||||
|
||||
|
||||
def remove_option(app_name, option):
|
||||
if config.has_option(app_name, option):
|
||||
config.remove_option(app_name, option)
|
||||
if _config.has_option(app_name, option):
|
||||
_config.remove_option(app_name, option)
|
||||
|
||||
if config.has_section(app_name) and not config[app_name]:
|
||||
config.remove_section(app_name)
|
||||
if _config.has_section(app_name) and not _config[app_name]:
|
||||
_config.remove_section(app_name)
|
||||
|
||||
save_config()
|
||||
_save_config()
|
||||
|
||||
|
||||
def remove_section(app_name):
|
||||
if config.has_section(app_name):
|
||||
config.remove_section(app_name)
|
||||
save_config()
|
||||
if _config.has_section(app_name):
|
||||
_config.remove_section(app_name)
|
||||
_save_config()
|
||||
|
|
|
@ -54,7 +54,6 @@ class IndicatorReasons:
|
|||
|
||||
class IndicatorLineEdit(QWidget):
|
||||
textChanged = pyqtSignal(str)
|
||||
is_valid = False
|
||||
reasons = IndicatorReasons()
|
||||
|
||||
def __init__(
|
||||
|
@ -97,9 +96,10 @@ class IndicatorLineEdit(QWidget):
|
|||
layout.addWidget(self.indicator_label)
|
||||
|
||||
if not placeholder:
|
||||
_translate = QCoreApplication.translate
|
||||
_translate = QCoreApplication.instance().translate
|
||||
self.line_edit.setPlaceholderText(_translate(self.__class__.__name__, "Default"))
|
||||
|
||||
self.is_valid = False
|
||||
self.edit_func = edit_func
|
||||
self.save_func = save_func
|
||||
self.line_edit.textChanged.connect(self.__edit)
|
||||
|
@ -107,7 +107,7 @@ class IndicatorLineEdit(QWidget):
|
|||
self.line_edit.textChanged.connect(self.__save)
|
||||
|
||||
# lk: this can be placed here to trigger __edit
|
||||
# lk: it going to save the input again if it is valid which
|
||||
# lk: it is going to save the input again if it is valid which
|
||||
# lk: is ok to do given the checks don't misbehave (they shouldn't)
|
||||
# lk: however it is going to edit any "understood" bad input to good input
|
||||
# lk: and we might not want that (but the validity check reports on the edited string)
|
||||
|
@ -185,9 +185,6 @@ class PathEditIconProvider(QFileIconProvider):
|
|||
|
||||
|
||||
class PathEdit(IndicatorLineEdit):
|
||||
completer = QCompleter()
|
||||
compl_model = QFileSystemModel()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
path: str = "",
|
||||
|
@ -200,6 +197,9 @@ class PathEdit(IndicatorLineEdit):
|
|||
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
||||
parent=None,
|
||||
):
|
||||
self.completer = QCompleter()
|
||||
self.compl_model = QFileSystemModel()
|
||||
|
||||
try:
|
||||
self.compl_model.setOptions(
|
||||
QFileSystemModel.DontWatchForChanges
|
||||
|
@ -230,7 +230,7 @@ class PathEdit(IndicatorLineEdit):
|
|||
layout = self.layout()
|
||||
layout.addWidget(self.path_select)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
_translate = QCoreApplication.instance().translate
|
||||
self.path_select.setText(_translate("PathEdit", "Browse..."))
|
||||
|
||||
self.type_filter = type_filter
|
||||
|
@ -414,7 +414,7 @@ class SelectViewWidget(QWidget):
|
|||
class ImageLabel(QLabel):
|
||||
image = None
|
||||
img_size = None
|
||||
name = str()
|
||||
name = ""
|
||||
|
||||
def __init__(self):
|
||||
super(ImageLabel, self).__init__()
|
||||
|
|
|
@ -20,7 +20,6 @@ class RareApp(QApplication):
|
|||
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)
|
||||
|
||||
|
@ -36,7 +35,6 @@ class RareApp(QApplication):
|
|||
# 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
|
||||
|
|
Loading…
Reference in a new issue