Skip to content

Commit

Permalink
Merge pull request #175 from loathingKernel/singletons
Browse files Browse the repository at this point in the history
Implement global objects as functions that return a single instance
  • Loading branch information
Dummerle authored Feb 25, 2022
2 parents f12686e + 6b2e8ee commit 6d356da
Show file tree
Hide file tree
Showing 37 changed files with 328 additions and 273 deletions.
43 changes: 23 additions & 20 deletions rare/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@
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

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
Expand All @@ -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
Expand All @@ -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"):
Expand All @@ -71,7 +75,7 @@ def __init__(self):
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()
Expand All @@ -95,7 +99,7 @@ def __init__(self):
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(
Expand Down Expand Up @@ -159,7 +163,7 @@ def show_mainwindow(self):
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():
Expand All @@ -184,32 +188,32 @@ def start_app(self):
)

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):
Expand All @@ -220,7 +224,7 @@ def tray(self, reason):
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"),
Expand Down Expand Up @@ -255,7 +259,6 @@ def exit_app(self, exit_code=0):
def start(args):
# set excepthook to show dialog with exception
sys.excepthook = excepthook
shared.init_args(args)

# configure logging
if args.debug:
Expand All @@ -281,7 +284,7 @@ def start(args):
)

while True:
app = App()
app = App(args)
exit_code = app.exec_()
# if not restart
# restart app
Expand Down
17 changes: 9 additions & 8 deletions rare/components/dialogs/install_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
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
Expand All @@ -29,7 +29,8 @@ def __init__(
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
Expand All @@ -55,8 +56,8 @@ def __init__(
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,
Expand All @@ -77,9 +78,9 @@ def __init__(
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(
Expand Down Expand Up @@ -296,7 +297,7 @@ def keyPressEvent(self, e: QKeyEvent) -> None:
self.cancel_clicked()


class InstallInfoWorkerSignals(QObject):
class InstallInfoSignals(QObject):
result = pyqtSignal(InstallDownloadModel)
failed = pyqtSignal(str)
finished = pyqtSignal()
Expand All @@ -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
Expand Down
40 changes: 20 additions & 20 deletions rare/components/dialogs/launch_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
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
Expand All @@ -17,40 +17,41 @@
logger = getLogger("Login")


class ApiSignals(QObject):
class LaunchDialogSignals(QObject):
image_progress = pyqtSignal(int)
result = pyqtSignal(object, str)


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")
Expand All @@ -68,16 +69,16 @@ def __init__(self, parent=None):
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()

def login(self):
do_launch = True
try:
if self.offline:
if self.args.offline:
pass
else:
QApplication.processEvents()
Expand All @@ -90,10 +91,10 @@ def login(self):
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:
Expand All @@ -104,11 +105,11 @@ def launch(self):
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
Expand Down Expand Up @@ -179,8 +180,7 @@ def finish(self):
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
5 changes: 3 additions & 2 deletions rare/components/dialogs/login/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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
Expand All @@ -32,6 +32,7 @@ def __init__(self, core: LegendaryCore, parent=None):
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)
Expand Down Expand Up @@ -85,7 +86,7 @@ def next_clicked(self):
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
Expand Down
Loading

0 comments on commit 6d356da

Please sign in to comment.