1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Merge pull request #175 from loathingKernel/singletons

Implement global objects as functions that return a single instance
This commit is contained in:
Dummerle 2022-02-25 22:54:30 +01:00 committed by GitHub
commit 6d356daf1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 328 additions and 273 deletions

View file

@ -6,8 +6,9 @@ import shutil
import sys
import time
import traceback
from argparse import Namespace
from PyQt5.QtCore import QThreadPool, QSettings, QTranslator
from PyQt5.QtCore import Qt, QThreadPool, QSettings, QTranslator
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox
from requests import HTTPError
@ -15,7 +16,7 @@ from requests import HTTPError
import legendary
# noinspection PyUnresolvedReferences
import rare.resources.resources
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.utils.paths import cache_dir, resources_path, tmp_dir
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
@ -36,7 +37,7 @@ def excepthook(exc_type, exc_value, exc_tb):
print("Error")
if exc_tb == HTTPError:
try:
if shared.core.login():
if LegendaryCoreSingleton().login():
return
else:
raise ValueError
@ -54,15 +55,18 @@ class App(QApplication):
mainwindow: MainWindow = None
tray_icon: QSystemTrayIcon = None
def __init__(self):
def __init__(self, args: Namespace):
super(App, self).__init__(sys.argv)
self.args = shared.args # add some options
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:
self.core = shared.init_legendary()
self.core = LegendaryCoreSingleton()
except configparser.MissingSectionHeaderError as e:
logger.warning(f"Config is corrupt: {e}")
if config_path := os.environ.get("XDG_CONFIG_HOME"):
@ -71,7 +75,7 @@ class App(QApplication):
path = os.path.expanduser("~/.config/legendary")
with open(os.path.join(path, "config.ini"), "w") as config_file:
config_file.write("[Legendary]")
self.core = shared.init_legendary()
self.core = LegendaryCoreSingleton()
if "Legendary" not in self.core.lgd.config.sections():
self.core.lgd.config.add_section("Legendary")
self.core.lgd.save_config()
@ -95,7 +99,7 @@ class App(QApplication):
self.setOrganizationName("Rare")
self.settings = QSettings()
self.signals = shared.init_signals()
self.signals = GlobalSignalsSingleton()
self.signals.exit_app.connect(self.exit_app)
self.signals.send_notification.connect(
@ -159,7 +163,7 @@ class App(QApplication):
if self.window_launched:
self.mainwindow.show()
else:
self.mainwindow.show_window_centralized()
self.mainwindow.show_window_centered()
def start_app(self):
for igame in self.core.get_installed_list():
@ -184,32 +188,32 @@ class App(QApplication):
)
if not self.args.silent:
self.mainwindow.show_window_centralized()
self.mainwindow.show_window_centered()
self.window_launched = True
if shared.args.subparser == "launch":
if shared.args.app_name in [
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(shared.args.app_name).title}"
f"Launching {self.core.get_installed_game(self.args.app_name).title}"
)
self.mainwindow.tab_widget.games_tab.game_utils.prepare_launch(
shared.args.app_name
self.args.app_name
)
else:
logger.error(
f"Could not find {shared.args.app_name} in Games or it is not installed"
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(shared.args.app_name),
).format(self.args.app_name),
)
if shared.args.test_start:
if self.args.test_start:
self.exit_app(0)
def tray(self, reason):
@ -220,7 +224,7 @@ class App(QApplication):
def exit_app(self, exit_code=0):
# FIXME: Fix this with the downlaod tab redesign
if self.mainwindow is not None:
if not shared.args.offline and self.mainwindow.tab_widget.downloadTab.is_download_active:
if not self.args.offline and self.mainwindow.tab_widget.downloadTab.is_download_active:
question = QMessageBox.question(
self.mainwindow,
self.tr("Close"),
@ -255,7 +259,6 @@ class App(QApplication):
def start(args):
# set excepthook to show dialog with exception
sys.excepthook = excepthook
shared.init_args(args)
# configure logging
if args.debug:
@ -281,7 +284,7 @@ def start(args):
)
while True:
app = App()
app = App(args)
exit_code = app.exec_()
# if not restart
# restart app

View file

@ -11,7 +11,7 @@ from legendary.core import LegendaryCore
from legendary.models.downloading import ConditionCheckResult
from legendary.models.game import Game
from legendary.utils.selective_dl import games
from rare import shared
from rare.shared import LegendaryCoreSingleton, ApiResultsSingleton
from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog
from rare.utils.extra_widgets import PathEdit
from rare.utils.models import InstallDownloadModel, InstallQueueItemModel
@ -29,7 +29,8 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.api_results = ApiResultsSingleton()
self.dl_item = dl_item
self.dl_item.status_q = MPQueue()
self.app_name = self.dl_item.options.app_name
@ -55,8 +56,8 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.setWindowTitle(f'{self.windowTitle()} - {header} "{self.game.app_title}"')
if not self.dl_item.options.base_path:
self.dl_item.options.base_path = shared.core.lgd.config.get("Legendary", "install_dir",
fallback=os.path.expanduser("~/legendary"))
self.dl_item.options.base_path = self.core.lgd.config.get("Legendary", "install_dir",
fallback=os.path.expanduser("~/legendary"))
self.install_dir_edit = PathEdit(
path=self.dl_item.options.base_path,
@ -77,9 +78,9 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.warn_message.setVisible(False)
platforms = ["Windows"]
if dl_item.options.app_name in shared.api_results.bit32_games:
if dl_item.options.app_name in self.api_results.bit32_games:
platforms.append("Win32")
if dl_item.options.app_name in shared.api_results.mac_games:
if dl_item.options.app_name in self.api_results.mac_games:
platforms.append("Mac")
self.platform_combo_box.addItems(platforms)
self.platform_combo_box.currentIndexChanged.connect(
@ -296,7 +297,7 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.cancel_clicked()
class InstallInfoWorkerSignals(QObject):
class InstallInfoSignals(QObject):
result = pyqtSignal(InstallDownloadModel)
failed = pyqtSignal(str)
finished = pyqtSignal()
@ -305,7 +306,7 @@ class InstallInfoWorkerSignals(QObject):
class InstallInfoWorker(QRunnable):
def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel, game: Game = None):
super(InstallInfoWorker, self).__init__()
self.signals = InstallInfoWorkerSignals()
self.signals = InstallInfoSignals()
self.core = core
self.dl_item = dl_item
self.is_overlay_install = self.dl_item.options.overlay

View file

@ -7,7 +7,7 @@ from PyQt5.QtWidgets import QDialog, QApplication
from legendary.core import LegendaryCore
from requests.exceptions import ConnectionError, HTTPError
from rare import shared
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton
from rare.components.dialogs.login import LoginDialog
from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog
from rare.utils.models import ApiResults
@ -17,7 +17,7 @@ from rare.utils.utils import download_images, CloudWorker
logger = getLogger("Login")
class ApiSignals(QObject):
class LaunchDialogSignals(QObject):
image_progress = pyqtSignal(int)
result = pyqtSignal(object, str)
@ -25,32 +25,33 @@ class ApiSignals(QObject):
class ImageWorker(QRunnable):
def __init__(self, core: LegendaryCore):
super(ImageWorker, self).__init__()
self.core = core
self.signal = ApiSignals()
self.signals = LaunchDialogSignals()
self.setAutoDelete(True)
self.core = core
def run(self):
download_images(self.signal.image_progress, self.signal.result, self.core)
self.signal.image_progress.emit(100)
download_images(self.signals.image_progress, self.signals.result, self.core)
self.signals.image_progress.emit(100)
class ApiRequestWorker(QRunnable):
def __init__(self):
super(ApiRequestWorker, self).__init__()
self.signals = ApiSignals()
self.signals = LaunchDialogSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
def run(self) -> None:
if platform.system() == "Darwin" or "Mac" in shared.core.get_installed_platforms():
if platform.system() == "Darwin" or "Mac" in self.core.get_installed_platforms():
try:
result = shared.core.get_game_and_dlc_list(True, "Mac")
result = self.core.get_game_and_dlc_list(True, "Mac")
except HTTPError:
result = [], {}
self.signals.result.emit(result, "mac")
else:
self.signals.result.emit(([], {}), "mac")
try:
result = shared.core.get_game_and_dlc_list(True, "Win32")
result = self.core.get_game_and_dlc_list(True, "Win32")
except HTTPError:
result = [], {}
self.signals.result.emit(result, "32bit")
@ -68,8 +69,8 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
self.setWindowModality(Qt.WindowModal)
self.core = shared.core
self.offline = shared.args.offline
self.core = LegendaryCoreSingleton()
self.args = ArgumentsSingleton()
self.thread_pool = QThreadPool()
self.thread_pool.setMaxThreadCount(2)
self.api_results = ApiResults()
@ -77,7 +78,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
def login(self):
do_launch = True
try:
if self.offline:
if self.args.offline:
pass
else:
QApplication.processEvents()
@ -90,10 +91,10 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
do_launch = LoginDialog(core=self.core, parent=self).login()
except ConnectionError as e:
logger.warning(e)
self.offline = True
self.args.offline = True
finally:
if do_launch:
if not shared.args.silent:
if not self.args.silent:
self.show()
self.launch()
else:
@ -104,11 +105,11 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
if not os.path.exists(image_dir):
os.makedirs(image_dir)
if not self.offline:
if not self.args.offline:
self.image_info.setText(self.tr("Downloading Images"))
image_worker = ImageWorker(self.core)
image_worker.signal.image_progress.connect(self.update_image_progbar)
image_worker.signal.result.connect(self.handle_api_worker_result)
image_worker.signals.image_progress.connect(self.update_image_progbar)
image_worker.signals.result.connect(self.handle_api_worker_result)
self.thread_pool.start(image_worker)
# gamelist and no_asset games are from Image worker
@ -179,8 +180,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
if self.finished == 1:
logger.info("App starting")
self.image_info.setText(self.tr("Starting..."))
shared.args.offline = self.offline
shared.init_api_response(self.api_results)
ApiResultsSingleton(self.api_results)
self.start_app.emit()
else:
self.finished += 1

View file

@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSizePolicy, QLayout, QDialog, QMessageBox
from legendary.core import LegendaryCore
from rare import shared
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton
from rare.components.dialogs.login.browser_login import BrowserLogin
from rare.components.dialogs.login.import_login import ImportLogin
from rare.ui.components.dialogs.login.login_dialog import Ui_LoginDialog
@ -32,6 +32,7 @@ class LoginDialog(QDialog, Ui_LoginDialog):
self.setWindowModality(Qt.WindowModal)
self.core = core
self.args = ArgumentsSingleton()
self.browser_page = BrowserLogin(self.core, self.login_stack)
self.login_stack.insertWidget(self.pages.browser, self.browser_page)
@ -85,7 +86,7 @@ class LoginDialog(QDialog, Ui_LoginDialog):
self.import_page.do_login()
def login(self):
if shared.args.test_start:
if self.args.test_start:
return False
self.exec_()
return self.logged_in

View file

@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt, QSettings, QTimer, QSize
from PyQt5.QtGui import QCloseEvent, QCursor
from PyQt5.QtWidgets import QMainWindow, QApplication, QStatusBar
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.components.tabs import TabWidget
from rare.utils.paths import data_dir
@ -16,11 +16,11 @@ class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setAttribute(Qt.WA_DeleteOnClose)
self.settings = QSettings()
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.signals = shared.signals
self.offline = shared.args.offline
self.settings = QSettings()
self.setWindowTitle("Rare - GUI for legendary")
self.tab_widget = TabWidget(self)
@ -35,7 +35,7 @@ class MainWindow(QMainWindow):
self.resize(width, height)
if not shared.args.offline:
if not self.args.offline:
try:
from rare.utils.rpc import DiscordRPC
self.rpc = DiscordRPC()
@ -46,7 +46,7 @@ class MainWindow(QMainWindow):
self.timer.timeout.connect(self.timer_finished)
self.timer.start(1000)
def show_window_centralized(self):
def show_window_centered(self):
self.show()
# get the margins of the decorated window
margins = self.windowHandle().frameMargins()
@ -78,7 +78,7 @@ class MainWindow(QMainWindow):
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=shared.args.offline
game, offline=self.args.offline
)
else:
logger.info(f"Could not find {game} in Games")
@ -95,7 +95,7 @@ class MainWindow(QMainWindow):
self.hide()
e.ignore()
return
elif self.offline:
elif self.args.offline:
pass
self.signals.exit_app.emit(0)
e.ignore()

View file

@ -1,7 +1,7 @@
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.components.tabs.account import MiniWidget
from rare.components.tabs.downloads import DownloadsTab
from rare.components.tabs.games import GamesTab
@ -15,9 +15,10 @@ from rare.utils.utils import icon
class TabWidget(QTabWidget):
def __init__(self, parent):
super(TabWidget, self).__init__(parent=parent)
disabled_tab = 3 if not shared.args.offline else 1
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
disabled_tab = 3 if not self.args.offline else 1
self.setTabBar(MainTabBar(disabled_tab))
# lk: Figure out why this adds a white line at the top
# lk: despite setting qproperty-drawBase to 0 in the stylesheet
@ -26,7 +27,7 @@ class TabWidget(QTabWidget):
self.games_tab = GamesTab()
self.addTab(self.games_tab, self.tr("Games"))
if not shared.args.offline:
if not self.args.offline:
# updates = self.games_tab.default_widget.game_list.updates
self.downloadTab = DownloadsTab(self.games_tab.updates)
self.addTab(
@ -42,7 +43,7 @@ class TabWidget(QTabWidget):
self.addTab(self.store, self.tr("Store (Beta)"))
self.settings = SettingsTab(self)
if shared.args.debug:
if self.args.debug:
self.settings.addTab(DebugSettings(), "Debug")
# Space Tab
@ -102,7 +103,7 @@ class TabWidget(QTabWidget):
if tab_num == 0:
self.games_tab.layout().setCurrentIndex(0)
if not shared.args.offline and tab_num == 2:
if not self.args.offline and tab_num == 2:
self.store.load()
def resizeEvent(self, event):

View file

@ -2,15 +2,15 @@ import webbrowser
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QLabel, QPushButton
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
class MiniWidget(QWidget):
def __init__(self):
super(MiniWidget, self).__init__()
self.layout = QVBoxLayout()
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.layout.addWidget(QLabel("Account"))
username = self.core.lgd.userdata.get("display_name")
if not username:

View file

@ -15,7 +15,7 @@ from PyQt5.QtWidgets import (
from legendary.core import LegendaryCore
from legendary.models.downloading import UIUpdate
from legendary.models.game import Game, InstalledGame
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.tabs.downloads.dl_queue_widget import DlQueueWidget, DlWidget
from rare.components.tabs.downloads.download_thread import DownloadThread
@ -34,10 +34,10 @@ class DownloadsTab(QWidget, Ui_DownloadsTab):
def __init__(self, updates: list):
super(DownloadsTab, self).__init__()
self.setupUi(self)
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.active_game: Game = None
self.analysis = None
self.signals = shared.signals
self.kill_button.clicked.connect(self.stop_download)
@ -68,7 +68,7 @@ class DownloadsTab(QWidget, Ui_DownloadsTab):
self.signals.add_download.connect(
lambda app_name: self.add_update(self.core.get_installed_game(app_name))
)
shared.signals.game_uninstalled.connect(self.game_uninstalled)
self.signals.game_uninstalled.connect(self.game_uninstalled)
self.reset_infos()

View file

@ -13,7 +13,7 @@ from PyQt5.QtWidgets import QMessageBox
from legendary.core import LegendaryCore
from legendary.models.downloading import UIUpdate, WriterTask
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.utils.models import InstallQueueItemModel
from rare.utils.utils import create_desktop_link
@ -27,6 +27,7 @@ class DownloadThread(QThread):
def __init__(self, core: LegendaryCore, queue_item: InstallQueueItemModel):
super(DownloadThread, self).__init__()
self.core = core
self.signals = GlobalSignalsSingleton()
self.dlm = queue_item.download.dlmanager
self.no_install = queue_item.options.no_install
self.status_q = queue_item.status_q
@ -147,7 +148,7 @@ class DownloadThread(QThread):
game = self.core.get_game(self.igame.app_name)
if self.queue_item.options.overlay:
shared.signals.overlay_installation_finished.emit()
self.signals.overlay_installation_finished.emit()
self.core.finish_overlay_install(self.igame)
self.status.emit("finish")
return

View file

@ -4,7 +4,7 @@ from typing import Tuple, Dict, Union, List
from PyQt5.QtCore import QSettings, QObjectCleanupHandler
from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ApiResultsSingleton
from legendary.models.game import InstalledGame, Game
from rare.ui.components.tabs.games.games_tab import Ui_GamesTab
from rare.utils.extra_widgets import FlowLayout
@ -37,15 +37,17 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
def __init__(self, parent=None):
super(GamesTab, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.api_results = ApiResultsSingleton()
self.settings = QSettings()
self.game_list: List[Game] = shared.api_results.game_list
self.dlcs = shared.api_results.dlcs
self.bit32 = shared.api_results.bit32_games
self.mac_games = shared.api_results.mac_games
self.no_assets = shared.api_results.no_asset_games
self.game_list: List[Game] = self.api_results.game_list
self.dlcs = self.api_results.dlcs
self.bit32 = self.api_results.bit32_games
self.mac_games = self.api_results.mac_games
self.no_assets = self.api_results.no_asset_games
self.game_utils = GameUtils(parent=self)
@ -75,7 +77,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.head_bar.import_game.clicked.connect(lambda: self.setCurrentIndex(2))
self.no_asset_names = []
if not shared.args.offline:
if not self.args.offline:
for game in self.no_assets:
self.no_asset_names.append(game.app_name)
else:

View file

@ -9,7 +9,7 @@ from PyQt5.QtWidgets import QDialog, QMessageBox, QSizePolicy, QLayout, QApplica
from legendary.core import LegendaryCore
from legendary.models.game import SaveGameStatus, InstalledGame, SaveGameFile
from rare import shared
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton
from rare.ui.components.dialogs.sync_save_dialog import Ui_SyncSaveDialog
from rare.utils.utils import icon
@ -30,29 +30,29 @@ class DownloadModel:
path: str
class WorkerSignals(QObject):
class SaveSignals(QObject):
finished = pyqtSignal(str, str)
class SaveWorker(QRunnable):
signals = WorkerSignals()
def __init__(self, model: Union[UploadModel, DownloadModel]):
super(SaveWorker, self).__init__()
self.model = model
self.signals = SaveSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
self.api_results = ApiResultsSingleton()
self.model = model
def run(self) -> None:
try:
if isinstance(self.model, DownloadModel):
shared.core.download_saves(
self.core.download_saves(
self.model.app_name,
self.model.latest_save.manifest_name,
self.model.path,
)
else:
shared.core.upload_save(
self.core.upload_save(
self.model.app_name, self.model.path, self.model.date_time
)
except Exception as e:
@ -62,8 +62,8 @@ class SaveWorker(QRunnable):
try:
if isinstance(self.model, UploadModel):
logger.info("Updating cloud saves...")
result = shared.core.get_save_games(self.model.app_name)
shared.api_results.saves = result
result = self.core.get_save_games(self.model.app_name)
self.api_results.saves = result
except Exception as e:
self.signals.finished.emit(str(e), self.model.app_name)
logger.error(str(e))
@ -127,9 +127,11 @@ class CloudSaveUtils(QObject):
def __init__(self):
super(CloudSaveUtils, self).__init__()
self.core = shared.core
saves = shared.api_results.saves
if not shared.args.offline:
self.core = LegendaryCoreSingleton()
self.args = ArgumentsSingleton()
self.api_results = ApiResultsSingleton()
saves = self.api_results.saves
if not self.args.offline:
self.latest_saves = self.get_latest_saves(saves)
else:
self.latest_saves = dict()
@ -307,7 +309,7 @@ class CloudSaveUtils(QObject):
if not error_message:
self.sync_finished.emit(app_name)
self.latest_saves = self.get_latest_saves(shared.api_results.saves)
self.latest_saves = self.get_latest_saves(self.api_results.saves)
else:
QMessageBox.warning(
None,

View file

@ -1,7 +1,7 @@
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.utils.extra_widgets import SideTabWidget
from .game_dlc import GameDlc
from .game_info import GameInfo
@ -12,8 +12,8 @@ from ..game_utils import GameUtils
class GameInfoTabs(SideTabWidget):
def __init__(self, dlcs: dict, game_utils: GameUtils, parent=None):
super(GameInfoTabs, self).__init__(show_back=True, parent=parent)
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.info = GameInfo(self, game_utils)
self.addTab(self.info, self.tr("Information"))

View file

@ -3,7 +3,7 @@ from PyQt5.QtGui import QPixmap, QResizeEvent
from PyQt5.QtWidgets import QFrame, QWidget, QMessageBox
from legendary.models.game import Game
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.components.tabs.games.game_utils import GameUtils
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
@ -18,12 +18,13 @@ class GameDlc(QWidget, Ui_GameDlc):
def __init__(self, dlcs: dict, game_utils: GameUtils, parent=None):
super(GameDlc, self).__init__(parent=parent)
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.game_utils = game_utils
self.available_dlc_scroll.setProperty("noBorder", 1)
self.installed_dlc_scroll.setProperty("noBorder", 1)
self.signals = shared.signals
self.core = shared.core
self.dlcs = dlcs
self.installed_dlc_widgets = list()

View file

@ -6,7 +6,7 @@ from PyQt5.QtCore import pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QWidget, QMessageBox
from legendary.models.game import Game, InstalledGame
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
from rare.utils.legendary_utils import VerifyWorker
from rare.utils.models import InstallOptionsModel
@ -26,8 +26,9 @@ class GameInfo(QWidget, Ui_GameInfo):
def __init__(self, parent, game_utils):
super(GameInfo, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.game_utils = game_utils
if platform.system() == "Windows":
@ -47,7 +48,7 @@ class GameInfo(QWidget, Ui_GameInfo):
self.verify_pool = QThreadPool()
self.verify_pool.setMaxThreadCount(2)
if shared.args.offline:
if self.args.offline:
self.repair_button.setDisabled(True)
else:
self.repair_button.clicked.connect(self.repair)
@ -175,7 +176,7 @@ class GameInfo(QWidget, Ui_GameInfo):
else:
self.uninstall_button.setDisabled(False)
self.verify_button.setDisabled(False)
if not shared.args.offline:
if not self.args.offline:
self.repair_button.setDisabled(False)
self.game_actions_stack.setCurrentIndex(0)

View file

@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, QThreadPool
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWidgets import QWidget, QTreeView
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ApiResultsSingleton
from legendary.models.game import Game
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
from rare.utils.extra_widgets import SideTabWidget
@ -17,11 +17,12 @@ from rare.utils.utils import get_pixmap
class UninstalledInfoTabs(SideTabWidget):
def __init__(self, parent=None):
super(UninstalledInfoTabs, self).__init__(show_back=True, parent=parent)
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.info = UninstalledInfo()
self.info.install_button.setDisabled(shared.args.offline)
self.info.install_button.setDisabled(self.args.offline)
self.addTab(self.info, self.tr("Information"))
self.view = QTreeView()
@ -55,8 +56,9 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
def __init__(self, parent=None):
super(UninstalledInfo, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.api_results = ApiResultsSingleton()
self.install_button.clicked.connect(self.install_game)
if platform.system() != "Windows":
self.steam_worker = SteamWorker(self.core)
@ -83,9 +85,9 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
self.game = game
self.game_title.setText(f"<h2>{self.game.app_title}</h2>")
available_platforms = ["Windows"]
if self.game.app_name in shared.api_results.bit32_games:
if self.game.app_name in self.api_results.bit32_games:
available_platforms.append("32 Bit")
if self.game.app_name in shared.api_results.mac_games:
if self.game.app_name in self.api_results.mac_games:
available_platforms.append("macOS")
self.platform.setText(", ".join(available_platforms))

View file

@ -10,7 +10,7 @@ from PyQt5.QtCore import QObject, QSettings, QProcess, QProcessEnvironment, pyqt
from PyQt5.QtWidgets import QMessageBox, QPushButton
from legendary.models.game import LaunchParameters
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.extra.console import ConsoleWindow
from rare.components.tabs.games import CloudSaveUtils
@ -50,8 +50,10 @@ class GameUtils(QObject):
def __init__(self, parent=None):
super(GameUtils, self).__init__(parent=parent)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.core = shared.core
self.console = ConsoleWindow()
self.cloud_save_utils = CloudSaveUtils()
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
@ -80,7 +82,7 @@ class GameUtils(QObject):
if infos == 0:
return False
legendary_utils.uninstall(game.app_name, self.core, infos)
shared.signals.game_uninstalled.emit(app_name)
self.signals.game_uninstalled.emit(app_name)
return True
def prepare_launch(
@ -116,7 +118,7 @@ class GameUtils(QObject):
wine_pfx: str = None,
ask_always_sync: bool = False,
):
if shared.args.offline:
if self.args.offline:
offline = True
game = self.core.get_game(app_name)
igame = self.core.get_installed_game(app_name)
@ -253,7 +255,7 @@ class GameUtils(QObject):
self.running_games[game.app_name] = running_game
else:
origin_uri = self.core.get_origin_uri(game.app_name, shared.args.offline)
origin_uri = self.core.get_origin_uri(game.app_name, self.args.offline)
logger.info("Launch Origin Game: ")
if platform.system() == "Windows":
webbrowser.open(origin_uri)

View file

@ -6,7 +6,7 @@ from PyQt5.QtCore import pyqtSignal, QProcess, QSettings, Qt, QByteArray
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QGroupBox, QMessageBox, QAction, QLabel
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.components.tabs.games.game_utils import GameUtils
from rare.utils import utils
from rare.utils.utils import create_desktop_link
@ -22,7 +22,9 @@ class BaseInstalledWidget(QGroupBox):
def __init__(self, app_name, pixmap: QPixmap, game_utils: GameUtils):
super(BaseInstalledWidget, self).__init__()
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.game_utils = game_utils
self.syncing_cloud_saves = False
@ -53,7 +55,7 @@ class BaseInstalledWidget(QGroupBox):
pixmap.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation)
)
self.game_running = False
self.offline = shared.args.offline
self.offline = self.args.offline
self.update_available = False
if self.igame and self.core.lgd.assets:
try:
@ -120,7 +122,7 @@ class BaseInstalledWidget(QGroupBox):
uninstall = QAction(self.tr("Uninstall"), self)
uninstall.triggered.connect(
lambda: shared.signals.update_gamelist.emit([self.game.app_name])
lambda: self.signals.update_gamelist.emit([self.game.app_name])
if self.game_utils.uninstall_game(self.game.app_name)
else None
)

View file

@ -4,7 +4,7 @@ from PyQt5.QtCore import QEvent, pyqtSignal, QSize, Qt
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QLabel
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.components.tabs.games.game_widgets.base_installed_widget import (
BaseInstalledWidget,
)
@ -22,7 +22,7 @@ class InstalledIconWidget(BaseInstalledWidget):
self.setContextMenuPolicy(Qt.ActionsContextMenu)
self.layout = QVBoxLayout()
self.core = shared.core
self.core = LegendaryCoreSingleton()
if self.update_available:
logger.info(f"Update available for game: {self.game.app_name}")

View file

@ -3,7 +3,7 @@ from PyQt5.QtGui import QPaintEvent, QPainter, QPixmap, QPen, QFont, QColor
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QHBoxLayout, QWidget
from legendary.models.game import Game
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.utils.utils import (
get_pixmap,
optimal_text_background,
@ -21,6 +21,8 @@ class InstallingGameWidget(QWidget):
self.setProperty("noBorder", 1)
self.setLayout(QVBoxLayout())
self.core = LegendaryCoreSingleton()
self.pixmap = QPixmap()
w = 200
# self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation)
@ -42,7 +44,7 @@ class InstallingGameWidget(QWidget):
if not app_name:
self.game = None
return
self.game = shared.core.get_game(app_name)
self.game = self.core.get_game(app_name)
self.title_label.setText(f"<h4>{self.game.app_title}</h4>")
self.image_widget.set_game(self.game.app_name)
@ -59,9 +61,10 @@ class PaintWidget(QWidget):
def __init__(self):
super(PaintWidget, self).__init__()
self.core = LegendaryCoreSingleton()
def set_game(self, app_name: str):
game = shared.core.get_game(app_name, False)
game = self.core.get_game(app_name, False)
self.color_image = get_pixmap(game.app_name)
w = 200
self.color_image = self.color_image.scaled(

View file

@ -8,7 +8,7 @@ from PyQt5.QtWidgets import (
QComboBox,
)
from rare import shared
from rare.shared import ApiResultsSingleton
from rare.utils.extra_widgets import SelectViewWidget
from rare.utils.utils import icon
@ -18,6 +18,7 @@ class GameListHeadBar(QWidget):
def __init__(self, parent=None):
super(GameListHeadBar, self).__init__(parent=parent)
self.api_results = ApiResultsSingleton()
self.setLayout(QHBoxLayout())
# self.installed_only = QCheckBox(self.tr("Installed only"))
self.settings = QSettings()
@ -38,15 +39,15 @@ class GameListHeadBar(QWidget):
"installed",
"offline",
]
if shared.api_results.bit32_games:
if self.api_results.bit32_games:
self.filter.addItem(self.tr("32 Bit Games"))
self.available_filters.append("32bit")
if shared.api_results.mac_games:
if self.api_results.mac_games:
self.filter.addItem(self.tr("Mac games"))
self.available_filters.append("mac")
if shared.api_results.no_asset_games:
if self.api_results.no_asset_games:
self.filter.addItem(self.tr("Exclude Origin"))
self.available_filters.append("installable")

View file

@ -6,7 +6,7 @@ from typing import Tuple, Iterable
from PyQt5.QtCore import Qt, QThreadPool, QRunnable, pyqtSlot
from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.ui.components.tabs.games.import_sync.egl_sync_group import Ui_EGLSyncGroup
from rare.ui.components.tabs.games.import_sync.egl_sync_list_group import (
Ui_EGLSyncListGroup,
@ -22,6 +22,7 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
def __init__(self, parent=None):
super(EGLSyncGroup, self).__init__(parent=parent)
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.egl_path_info.setProperty("infoLabel", 1)
self.thread_pool = QThreadPool.globalInstance()
@ -32,7 +33,7 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
self.egl_path_info.setVisible(False)
else:
self.egl_path_edit = PathEdit(
path=shared.core.egl.programdata_path,
path=self.core.egl.programdata_path,
ph_text=self.tr(
"Path to the Wine prefix where EGL is installed, or the Manifests folder"
),
@ -44,10 +45,10 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
self.egl_path_edit.textChanged.connect(self.egl_path_changed)
self.egl_path_edit_layout.addWidget(self.egl_path_edit)
if not shared.core.egl.programdata_path:
if not self.core.egl.programdata_path:
self.egl_path_info.setText(self.tr("Updating..."))
wine_resolver = WineResolver(
PathSpec.egl_programdata, "default", shared.core
PathSpec.egl_programdata, "default", self.core
)
wine_resolver.signals.result_ready.connect(self.wine_resolver_cb)
self.thread_pool.start(wine_resolver)
@ -55,7 +56,7 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
self.egl_path_info_label.setVisible(False)
self.egl_path_info.setVisible(False)
self.egl_sync_check.setChecked(shared.core.egl_sync_enabled)
self.egl_sync_check.setChecked(self.core.egl_sync_enabled)
self.egl_sync_check.stateChanged.connect(self.egl_sync_changed)
self.import_list = EGLSyncListGroup(export=False, parent=self)
@ -109,22 +110,21 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
return True, path, ""
return False, path, PathEdit.reasons.dir_not_exist
@staticmethod
def egl_path_edit_save_cb(path):
def egl_path_edit_save_cb(self, path):
if not path or not os.path.exists(path):
# This is the same as "--unlink"
shared.core.egl.programdata_path = None
shared.core.lgd.config.remove_option("Legendary", "egl_programdata")
shared.core.lgd.config.remove_option("Legendary", "egl_sync")
self.core.egl.programdata_path = None
self.core.lgd.config.remove_option("Legendary", "egl_programdata")
self.core.lgd.config.remove_option("Legendary", "egl_sync")
# remove EGL GUIDs from all games, DO NOT remove .egstore folders because that would fuck things up.
for igame in shared.core.get_installed_list():
for igame in self.core.get_installed_list():
igame.egl_guid = ""
shared.core.install_game(igame)
self.core.install_game(igame)
else:
shared.core.egl.programdata_path = path
shared.core.lgd.config.set("Legendary", "egl_programdata", path)
self.core.egl.programdata_path = path
self.core.lgd.config.set("Legendary", "egl_programdata", path)
shared.core.lgd.save_config()
self.core.lgd.save_config()
def egl_path_changed(self, path):
if self.egl_path_edit.is_valid:
@ -138,9 +138,9 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
if state == Qt.Unchecked:
self.import_list.setEnabled(bool(self.import_list.items))
self.export_list.setEnabled(bool(self.export_list.items))
shared.core.lgd.config.remove_option("Legendary", "egl_sync")
self.core.lgd.config.remove_option("Legendary", "egl_sync")
else:
shared.core.lgd.config.set("Legendary", "egl_sync", str(True))
self.core.lgd.config.set("Legendary", "egl_sync", str(True))
# lk: do import/export here since automatic sync was selected
self.import_list.mark(Qt.Checked)
self.export_list.mark(Qt.Checked)
@ -149,15 +149,15 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
self.import_list.setEnabled(False)
self.export_list.setEnabled(False)
# self.update_lists()
shared.core.lgd.save_config()
self.core.lgd.save_config()
def update_lists(self):
# self.egl_watcher.blockSignals(True)
if have_path := bool(shared.core.egl.programdata_path) and os.path.exists(
shared.core.egl.programdata_path
if have_path := bool(self.core.egl.programdata_path) and os.path.exists(
self.core.egl.programdata_path
):
# NOTE: need to clear known manifests to force refresh
shared.core.egl.manifests.clear()
self.core.egl.manifests.clear()
self.egl_sync_check_label.setEnabled(have_path)
self.egl_sync_check.setEnabled(have_path)
self.import_list.populate(have_path)
@ -172,21 +172,22 @@ class EGLSyncListItem(QListWidgetItem):
super(EGLSyncListItem, self).__init__(parent=parent)
self.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
self.setCheckState(Qt.Unchecked)
self.core = LegendaryCoreSingleton()
self.game = game
self.export = export
if export:
self.setText(game.title)
else: # import
self.setText(shared.core.get_game(game.app_name).app_title)
self.setText(self.core.get_game(game.app_name).app_title)
def is_checked(self) -> bool:
return self.checkState() == Qt.Checked
def action(self) -> None:
if self.export:
error = shared.core.egl_export(self.game.app_name)
error = self.core.egl_export(self.game.app_name)
else:
error = shared.core.egl_import(self.game.app_name)
error = self.core.egl_import(self.game.app_name)
return error
@property
@ -202,6 +203,8 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup):
def __init__(self, export: bool, parent=None):
super(EGLSyncListGroup, self).__init__(parent=parent)
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.list.setProperty("noBorder", 1)
self.export = export
@ -210,12 +213,12 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup):
self.setTitle(self.tr("Exportable games"))
self.label.setText(self.tr("No games to export to EGL"))
self.action_button.setText(self.tr("Export"))
self.list_func = shared.core.egl_get_exportable
self.list_func = self.core.egl_get_exportable
else:
self.setTitle(self.tr("Importable games"))
self.label.setText(self.tr("No games to import from EGL"))
self.action_button.setText(self.tr("Import"))
self.list_func = shared.core.egl_get_importable
self.list_func = self.core.egl_get_importable
self.list.itemDoubleClicked.connect(
lambda item: item.setCheckState(Qt.Unchecked)
@ -265,7 +268,7 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup):
imported.append(item.app_name)
self.list.takeItem(self.list.row(item))
if not self.export and imported:
shared.signals.update_gamelist.emit(imported)
self.signals.update_gamelist.emit(imported)
self.populate(True)
if errors:
QMessageBox.warning(
@ -351,7 +354,7 @@ class EGLSyncItemWidget(QGroupBox):
if export:
self.app_title_label = QLabel(game.title)
else:
title = shared.core.get_game(game.app_name).app_title
title = self.core.get_game(game.app_name).app_title
self.app_title_label = QLabel(title)
self.layout.addWidget(self.app_title_label)
self.button = QPushButton(self.tr("Export") if export else self.tr("Import"))
@ -365,13 +368,13 @@ class EGLSyncItemWidget(QGroupBox):
self.setLayout(self.layout)
def export_game(self):
shared.core.egl_export(self.game.app_name)
self.core.egl_export(self.game.app_name)
# FIXME: on update_egl_widget this is going to crash because
# FIXME: the item is not removed from the list in the python's side
self.deleteLater()
def import_game(self):
shared.core.egl_import(self.game.app_name)
self.core.egl_import(self.game.app_name)
# FIXME: on update_egl_widget this is going to crash because
# FIXME: the item is not removed from the list in the python's side
self.deleteLater()

View file

@ -7,7 +7,7 @@ from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QTreeView, QHeaderView
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ApiResultsSingleton
from rare.ui.components.tabs.games.import_sync.import_group import Ui_ImportGroup
from rare.utils import legendary_utils
from rare.utils.extra_widgets import IndicatorLineEdit, PathEdit
@ -64,13 +64,16 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
def __init__(self, parent=None):
super(ImportGroup, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.app_name_list = [game.app_name for game in shared.api_results.game_list]
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.api_results = ApiResultsSingleton()
self.app_name_list = [game.app_name for game in self.api_results.game_list]
self.install_dir_list = [
game.metadata.get("customAttributes", {})
.get("FolderName", {})
.get("value", game.app_name)
for game in shared.api_results.game_list
for game in self.api_results.game_list
if not game.is_dlc
]
@ -87,7 +90,7 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
ph_text=self.tr("Use in case the app name was not found automatically"),
completer=AppNameCompleter(
app_names=[
(i.app_name, i.app_title) for i in shared.api_results.game_list
(i.app_name, i.app_title) for i in self.api_results.game_list
]
),
edit_func=self.app_name_edit_cb,
@ -162,15 +165,15 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
self.tr("Successfully imported {}").format(igame.title)
)
self.app_name.setText(str())
shared.signals.update_gamelist.emit([app_name])
self.signals.update_gamelist.emit([app_name])
if (
igame.version
!= self.core.get_asset(app_name, igame.platform, False).build_version
):
# update available
shared.signals.add_download.emit(igame.app_name)
shared.signals.update_download_tab_text.emit()
self.signals.add_download.emit(igame.app_name)
self.signals.update_download_tab_text.emit()
else:
logger.warning(f'Failed to import "{app_name}"')

View file

@ -2,7 +2,7 @@ from logging import getLogger
from PyQt5.QtWidgets import QGroupBox
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.ui.components.tabs.settings.dxvk import Ui_DxvkSettings
logger = getLogger("DXVK Settings")
@ -14,7 +14,7 @@ class DxvkSettings(QGroupBox, Ui_DxvkSettings):
self.setupUi(self)
self.name = name if name is not None else "default"
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.dxvk_options_map = {
"devinfo": self.devinfo,

View file

@ -7,7 +7,7 @@ from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QGroupBox, QMessageBox
from legendary.utils import eos
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.ui.components.tabs.settings.eos_widget import Ui_EosWidget
from rare.utils.models import InstallOptionsModel
@ -19,9 +19,9 @@ def get_wine_prefixes() -> List[str]:
prefixes = [p]
else:
prefixes = []
for i in shared.core.get_installed_list():
for i in LegendaryCoreSingleton().get_installed_list():
# get prefix from environment
env = shared.core.get_app_environment(i.app_name)
env = LegendaryCoreSingleton().get_app_environment(i.app_name)
if pfx := env.get("WINEPREFIX"):
if pfx not in prefixes and os.path.exists(os.path.join(pfx, "user.reg")):
prefixes.append(pfx)
@ -31,26 +31,28 @@ def get_wine_prefixes() -> List[str]:
return prefixes
class WorkerSignals(QObject):
class CheckForUpdateSignals(QObject):
update_available = pyqtSignal(bool)
class CheckForUpdateWorker(QRunnable):
def __init__(self):
super(CheckForUpdateWorker, self).__init__()
self.signals = CheckForUpdateSignals()
self.setAutoDelete(True)
self.signals = WorkerSignals()
self.core = LegendaryCoreSingleton()
def run(self) -> None:
shared.core.check_for_overlay_updates()
self.signals.update_available.emit(shared.core.overlay_update_available)
self.core.check_for_overlay_updates()
self.signals.update_available.emit(self.core.overlay_update_available)
class EosWidget(QGroupBox, Ui_EosWidget):
def __init__(self):
super(EosWidget, self).__init__()
self.setupUi(self)
self.core = shared.core
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
if platform.system() != "Windows":
self.setTitle(f"{self.title()} - {self.tr(' - This won´t work with Wine. It might work in the Future')}")
@ -64,8 +66,8 @@ class EosWidget(QGroupBox, Ui_EosWidget):
self.update_info_lbl.setVisible(False)
self.overlay = self.core.lgd.get_overlay_install_info()
shared.signals.overlay_installation_finished.connect(self.overlay_installation_finished)
shared.signals.wine_prefix_updated.connect(self.update_prefixes)
self.signals.overlay_installation_finished.connect(self.overlay_installation_finished)
self.signals.wine_prefix_updated.connect(self.update_prefixes)
self.update_check_button.clicked.connect(self.check_for_update)
self.install_button.clicked.connect(self.install_overlay)
@ -217,7 +219,7 @@ class EosWidget(QGroupBox, Ui_EosWidget):
options = InstallOptionsModel(app_name="", base_path=base_path,
platform="Windows", overlay=True)
shared.signals.install_game.emit(options)
self.signals.install_game.emit(options)
def uninstall_overlay(self):
if not self.core.is_overlay_installed():

View file

@ -5,7 +5,7 @@ from typing import Tuple
from PyQt5.QtCore import Qt, QRunnable, QObject, pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
import rare.shared as shared
from rare.shared import LegendaryCoreSingleton
from rare.components.tabs.settings.eos import EosWidget
from rare.components.tabs.settings.ubisoft_activation import UbiActivationHelper
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
@ -15,21 +15,22 @@ from rare.utils.utils import get_size
logger = getLogger("LegendarySettings")
class WorkerSignals(QObject):
class RefreshGameMetaSignals(QObject):
finished = pyqtSignal()
def __init__(self):
super(WorkerSignals, self).__init__()
super(RefreshGameMetaSignals, self).__init__()
class RefreshGameMetaWorker(QRunnable):
def __init__(self):
super(RefreshGameMetaWorker, self).__init__()
self.signals = RefreshGameMetaSignals()
self.setAutoDelete(True)
self.signals = WorkerSignals()
self.core = LegendaryCoreSingleton()
def run(self) -> None:
shared.core.get_game_and_dlc_list(True, force_refresh=True)
self.core.get_game_and_dlc_list(True, force_refresh=True)
self.signals.finished.emit()
@ -38,7 +39,7 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
super(LegendarySettings, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.core = LegendaryCoreSingleton()
# Default installation directory
self.install_dir = PathEdit(

View file

@ -3,7 +3,7 @@ from logging import getLogger
from PyQt5.QtWidgets import QFileDialog, QWidget
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.components.tabs.settings.dxvk import DxvkSettings
from rare.ui.components.tabs.settings.linux import Ui_LinuxSettings
from rare.utils.extra_widgets import PathEdit
@ -16,6 +16,9 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
super(LinuxSettings, self).__init__()
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.name = name if name is not None else "default"
# Wine prefix
@ -52,29 +55,27 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
def save_prefix(self, text: str):
self.save_setting(text, f"{self.name}.env", "WINEPREFIX")
self.save_setting(text, self.name, "wine_prefix")
shared.signals.wine_prefix_updated.emit()
self.signals.wine_prefix_updated.emit()
@staticmethod
def load_setting(section: str, setting: str, fallback: str = str()):
return shared.core.lgd.config.get(section, setting, fallback=fallback)
def load_setting(self, section: str, setting: str, fallback: str = str()):
return self.core.lgd.config.get(section, setting, fallback=fallback)
@staticmethod
def save_setting(text: str, section: str, setting: str):
def save_setting(self, text: str, section: str, setting: str):
if text:
if section not in shared.core.lgd.config.sections():
shared.core.lgd.config.add_section(section)
if section not in self.core.lgd.config.sections():
self.core.lgd.config.add_section(section)
logger.debug(f"Added {f'[{section}]'} configuration section")
shared.core.lgd.config.set(section, setting, text)
self.core.lgd.config.set(section, setting, text)
logger.debug(f"Set {setting} in {f'[{section}]'} to {text}")
else:
if shared.core.lgd.config.has_section(
if self.core.lgd.config.has_section(
section
) and shared.core.lgd.config.has_option(section, setting):
shared.core.lgd.config.remove_option(section, setting)
) and self.core.lgd.config.has_option(section, setting):
self.core.lgd.config.remove_option(section, setting)
logger.debug(f"Unset {setting} from {f'[{section}]'}")
if not shared.core.lgd.config[section]:
shared.core.lgd.config.remove_section(section)
if not self.core.lgd.config[section]:
self.core.lgd.config.remove_section(section)
logger.debug(f"Removed {f'[{section}]'} configuration section")
shared.core.lgd.save_config()
self.core.lgd.save_config()

View file

@ -7,8 +7,7 @@ from logging import getLogger
from PyQt5.QtCore import QSettings, Qt
from PyQt5.QtWidgets import QWidget, QMessageBox
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.components.tabs.settings.rpc import RPCSettings
from rare.ui.components.tabs.settings.rare import Ui_RareSettings
from rare.utils import utils
@ -35,7 +34,7 @@ class RareSettings(QWidget, Ui_RareSettings):
def __init__(self):
super(RareSettings, self).__init__()
self.setupUi(self)
self.core = shared.core
self.core = LegendaryCoreSingleton()
# (widget_name, option_name, default)
self.checkboxes = [
(self.sys_tray, "sys_tray", True),

View file

@ -6,26 +6,26 @@ from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool, QSize
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QPushButton
from legendary.models.game import Game
from rare import shared
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton
from rare.utils.utils import icon
logger = getLogger("Ubisoft")
class Signals(QObject):
class UbiGetInfoSignals(QObject):
worker_finished = pyqtSignal(set, set, str)
linked = pyqtSignal(str)
class UbiGetInfoWorker(QRunnable):
def __init__(self):
super(UbiGetInfoWorker, self).__init__()
self.signals = Signals()
self.signals = UbiGetInfoSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
def run(self) -> None:
try:
external_auths = shared.core.egs.get_external_auths()
external_auths = self.core.egs.get_external_auths()
for ext_auth in external_auths:
if ext_auth["type"] != "ubisoft":
continue
@ -35,11 +35,11 @@ class UbiGetInfoWorker(QRunnable):
self.signals.worker_finished.emit(set(), set(), "")
return
uplay_keys = shared.core.egs.store_get_uplay_codes()
uplay_keys = self.core.egs.store_get_uplay_codes()
key_list = uplay_keys["data"]["PartnerIntegration"]["accountUplayCodes"]
redeemed = {k["gameId"] for k in key_list if k["redeemedOnUplay"]}
entitlements = shared.core.egs.get_user_entitlements()
entitlements = self.core.egs.get_user_entitlements()
entitlements = {i["entitlementName"] for i in entitlements}
self.signals.worker_finished.emit(redeemed, entitlements, ubi_account_id)
except Exception as e:
@ -47,11 +47,16 @@ class UbiGetInfoWorker(QRunnable):
self.signals.worker_finished.emit(set(), set(), "error")
class UbiConnectSignals(QObject):
linked = pyqtSignal(str)
class UbiConnectWorker(QRunnable):
def __init__(self, ubi_account_id, partner_link_id):
super(UbiConnectWorker, self).__init__()
self.signals = Signals()
self.signals = UbiConnectSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
self.ubi_account_id = ubi_account_id
self.partner_link_id = partner_link_id
@ -61,10 +66,10 @@ class UbiConnectWorker(QRunnable):
self.signals.linked.emit("")
return
try:
shared.core.egs.store_claim_uplay_code(
self.core.egs.store_claim_uplay_code(
self.ubi_account_id, self.partner_link_id
)
shared.core.egs.store_redeem_uplay_codes(self.ubi_account_id)
self.core.egs.store_redeem_uplay_codes(self.ubi_account_id)
except Exception as e:
self.signals.linked.emit(str(e))
return
@ -75,6 +80,7 @@ class UbiConnectWorker(QRunnable):
class UbiLinkWidget(QWidget):
def __init__(self, game: Game, ubi_account_id):
super(UbiLinkWidget, self).__init__()
self.args = ArgumentsSingleton()
self.setLayout(QHBoxLayout())
self.game = game
self.ubi_account_id = ubi_account_id
@ -88,7 +94,7 @@ class UbiLinkWidget(QWidget):
self.layout().addWidget(self.ok_indicator)
self.link_button = QPushButton(
self.tr("Redeem to Ubisoft") + ": Test" if shared.args.debug else ""
self.tr("Redeem to Ubisoft") + ": Test" if self.args.debug else ""
)
self.layout().addWidget(self.link_button)
self.link_button.clicked.connect(self.activate)
@ -100,7 +106,7 @@ class UbiLinkWidget(QWidget):
icon("mdi.transit-connection-horizontal", color="grey").pixmap(20, 20)
)
if shared.args.debug:
if self.args.debug:
worker = UbiConnectWorker(None, None)
else:
worker = UbiConnectWorker(self.ubi_account_id, self.game.partner_link_id)
@ -126,8 +132,9 @@ class UbiLinkWidget(QWidget):
class UbiActivationHelper(QObject):
def __init__(self, widget: QWidget):
super(UbiActivationHelper, self).__init__()
self.core = LegendaryCoreSingleton()
self.args = ArgumentsSingleton()
self.widget = widget
self.core = shared.core
self.thread_pool = QThreadPool.globalInstance()
worker = UbiGetInfoWorker()
@ -196,7 +203,7 @@ class UbiActivationHelper(QObject):
self.widget.layout().addWidget(
QLabel(self.tr("You don't own any Ubisoft games"))
)
if shared.args.debug:
if self.args.debug:
widget = UbiLinkWidget(
Game(app_name="Test", app_title="This is a test game"),
ubi_account_id,

View file

@ -1,7 +1,7 @@
from PyQt5.QtWidgets import QStackedWidget, QTabWidget
from legendary.core import LegendaryCore
from rare import shared
from rare.shared import LegendaryCoreSingleton, ApiResultsSingleton
from rare.utils.paths import cache_dir
from .game_info import ShopGameInfo
from .search_results import SearchResults
@ -16,13 +16,14 @@ class Shop(QStackedWidget):
def __init__(self, core: LegendaryCore):
super(Shop, self).__init__()
self.core = core
self.api_results = ApiResultsSingleton()
self.api_core = ShopApiCore(
self.core.egs.session.headers["Authorization"],
self.core.language_code,
self.core.country_code,
)
self.shop = ShopWidget(cache_dir, core, self.api_core)
self.shop = ShopWidget(cache_dir, self.core, self.api_core)
self.wishlist_widget = Wishlist(self.api_core)
self.store_tabs = QTabWidget()
@ -35,7 +36,7 @@ class Shop(QStackedWidget):
self.addWidget(self.search_results)
self.search_results.show_info.connect(self.show_game_info)
self.info = ShopGameInfo(
[i.asset_infos["Windows"].namespace for i in shared.api_results.game_list],
[i.asset_infos["Windows"].namespace for i in self.api_results.game_list],
self.api_core,
)
self.addWidget(self.info)

View file

@ -13,7 +13,7 @@ from PyQt5.QtWidgets import (
QGridLayout,
)
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.components.tabs.shop.shop_models import ShopGame
from rare.ui.components.tabs.store.shop_game_info import Ui_shop_info
from rare.utils.extra_widgets import WaitingSpinner, ImageLabel
@ -30,6 +30,7 @@ class ShopGameInfo(QWidget, Ui_shop_info):
def __init__(self, installed_titles: list, api_core):
super(ShopGameInfo, self).__init__()
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.api_core = api_core
self.installed = installed_titles
self.open_store_button.clicked.connect(self.button_clicked)
@ -258,7 +259,7 @@ class ShopGameInfo(QWidget, Ui_shop_info):
self.wishlist.append(game["offer"]["title"])
def button_clicked(self):
QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{shared.core.language_code}/p/{self.slug}"))
QDesktopServices.openUrl(QUrl(f"https://www.epicgames.com/store/{self.core.language_code}/p/{self.slug}"))
class SocialButton(QPushButton):

View file

@ -3,13 +3,15 @@ from typing import List
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.utils.meta import GameMeta
class TrayIcon(QSystemTrayIcon):
def __init__(self, parent):
super(TrayIcon, self).__init__(parent)
self.core = LegendaryCoreSingleton()
self.setIcon(QIcon(":/images/Rare.png"))
self.setVisible(True)
self.setToolTip("Rare")
@ -24,7 +26,7 @@ class TrayIcon(QSystemTrayIcon):
self.text_action.setEnabled(False)
self.menu.addAction(self.text_action)
if len(installed := shared.core.get_installed_list()) < 5:
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(),
@ -36,7 +38,7 @@ class TrayIcon(QSystemTrayIcon):
self.game_actions = []
for game in last_played:
a = QAction(shared.core.get_game(game.app_name).app_title)
a = QAction(self.core.get_game(game.app_name).app_title)
a.setProperty("app_name", game.app_name)
self.game_actions.append(a)
a.triggered.connect(

View file

@ -1,31 +1,38 @@
from argparse import Namespace
from legendary.core import LegendaryCore
from rare.utils.models import ApiResults, Signals
from rare.utils.models import ApiResults, GlobalSignals
core: LegendaryCore = None
signals: Signals = None
args: Namespace = None
api_results: ApiResults = None
_legendary_core_singleton: LegendaryCore = None
_global_signals_singleton: GlobalSignals = None
_arguments_singleton: Namespace = None
_api_results_singleton: ApiResults = None
def init_legendary():
global core
core = LegendaryCore()
return core
def LegendaryCoreSingleton() -> LegendaryCore:
global _legendary_core_singleton
if _legendary_core_singleton is None:
_legendary_core_singleton = LegendaryCore()
return _legendary_core_singleton
def init_signals():
global signals
signals = Signals()
return signals
def GlobalSignalsSingleton() -> GlobalSignals:
global _global_signals_singleton
if _global_signals_singleton is None:
_global_signals_singleton = GlobalSignals()
return _global_signals_singleton
def init_args(a: Namespace):
global args
args = a
def ArgumentsSingleton(args: Namespace = None) -> Namespace:
global _arguments_singleton
if _arguments_singleton is None:
_arguments_singleton = args
return _arguments_singleton
def init_api_response(res: ApiResults):
global api_results
api_results = res
def ApiResultsSingleton(res: ApiResults = None) -> ApiResults:
global _api_results_singleton
if _api_results_singleton is None:
_api_results_singleton = res
return _api_results_singleton

View file

@ -8,7 +8,7 @@ from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
from legendary.core import LegendaryCore
from legendary.models.game import VerifyResult
from legendary.utils.lfs import validate_files
from rare import shared
from rare.shared import LegendaryCoreSingleton
from rare.utils import config_helper
logger = getLogger("Legendary Utils")
@ -102,19 +102,20 @@ class VerifyWorker(QRunnable):
def __init__(self, app_name):
super(VerifyWorker, self).__init__()
self.app_name = app_name
self.signals = VerifySignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
self.app_name = app_name
def run(self):
if not shared.core.is_installed(self.app_name):
if not self.core.is_installed(self.app_name):
logger.error(f'Game "{self.app_name}" is not installed')
return
logger.info(f'Loading installed manifest for "{self.app_name}"')
igame = shared.core.get_installed_game(self.app_name)
manifest_data, _ = shared.core.get_installed_manifest(self.app_name)
manifest = shared.core.load_manifest(manifest_data)
igame = self.core.get_installed_game(self.app_name)
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
manifest = self.core.load_manifest(manifest_data)
files = sorted(manifest.file_manifest_list.elements,
key=lambda a: a.filename.lower())
@ -148,7 +149,7 @@ class VerifyWorker(QRunnable):
# always write repair file, even if all match
if repair_file:
repair_filename = os.path.join(shared.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
repair_filename = os.path.join(self.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
with open(repair_filename, 'w') as f:
f.write('\n'.join(repair_file))
logger.debug(f'Written repair file to "{repair_filename}"')

View file

@ -121,7 +121,7 @@ class ApiResults:
)
class Signals(QObject):
class GlobalSignals(QObject):
exit_app = pyqtSignal(int) # exit code
send_notification = pyqtSignal(str) # app_title

View file

@ -6,7 +6,7 @@ import pypresence.exceptions
from PyQt5.QtCore import QObject, QSettings
from pypresence import Presence
from rare import shared
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
client_id = "830732538225360908"
logger = getLogger("RPC")
@ -17,8 +17,8 @@ class DiscordRPC(QObject):
super(DiscordRPC, self).__init__()
self.RPC = None
self.state = 1 # 0: game, 1: always active, 2: off
self.core = shared.core
self.signals = shared.signals
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.settings = QSettings()
if self.settings.value("rpc_enable", 0, int) == 1: # show always

View file

@ -7,7 +7,7 @@ import requests
from PyQt5.QtCore import pyqtSignal, QRunnable, QObject, QCoreApplication
from legendary.core import LegendaryCore
from rare import shared
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton
from rare.utils.paths import data_dir, cache_dir
replace_chars = ",;.:-_ "
@ -48,15 +48,17 @@ class SteamWorker(QRunnable):
def get_rating(app_name: str):
core = LegendaryCoreSingleton()
args = ArgumentsSingleton()
if os.path.exists(p := os.path.join(data_dir, "steam_ids.json")):
grades = json.load(open(p))
else:
grades = {}
if not grades.get(app_name):
if shared.args.offline:
if args.offline:
return "pending"
game = shared.core.get_game(app_name)
game = core.get_game(app_name)
steam_id = get_steam_id(game.app_title)
grade = get_grade(steam_id)

View file

@ -33,7 +33,7 @@ if platform.system() == "Windows":
# noinspection PyUnresolvedReferences
from win32com.client import Dispatch # pylint: disable=E0401
from rare import shared
from rare.shared import LegendaryCoreSingleton, ApiResultsSingleton
from rare.utils.paths import image_dir, resources_path
# Mac not supported
@ -63,7 +63,7 @@ def download_images(progress: pyqtSignal, results: pyqtSignal, core: LegendaryCo
for i, game in enumerate(game_list):
if game.app_title == "Unreal Engine":
game.app_title += f" {game.app_name.split('_')[-1]}"
shared.core.lgd.set_game_meta(game.app_name, game)
core.lgd.set_game_meta(game.app_name, game)
try:
download_image(game)
except json.decoder.JSONDecodeError:
@ -453,8 +453,8 @@ class WineResolverSignals(QObject):
class WineResolver(QRunnable):
def __init__(self, path: str, app_name: str, core: LegendaryCore):
super(WineResolver, self).__init__()
self.setAutoDelete(True)
self.signals = WineResolverSignals()
self.setAutoDelete(True)
self.wine_env = os.environ.copy()
self.wine_env.update(core.get_app_environment(app_name))
self.wine_env["WINEDLLOVERRIDES"] = "winemenubuilder=d;mscoree=d;mshtml=d;"
@ -514,19 +514,20 @@ class WineResolver(QRunnable):
return
class CloudResultSignal(QObject):
class CloudSignals(QObject):
result_ready = pyqtSignal(list) # List[SaveGameFile]
class CloudWorker(QRunnable):
def __init__(self):
super(CloudWorker, self).__init__()
self.signals = CloudResultSignal()
self.signals = CloudSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
def run(self) -> None:
try:
result = shared.core.get_save_games()
result = self.core.get_save_games()
except HTTPError:
result = None
self.signals.result_ready.emit(result)
@ -542,7 +543,8 @@ def get_raw_save_path(game: Game):
def get_default_platform(app_name):
if platform.system() != "Darwin" or app_name not in shared.api_results.mac_games:
api_results = ApiResultsSingleton()
if platform.system() != "Darwin" or app_name not in api_results.mac_games:
return "Windows"
else:
return "Mac"