From 98c8cbb8a5323888db73c213200601c94405ca5c Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 17 Feb 2021 18:19:37 +0100 Subject: [PATCH] Login, launchdialog download features --- Rare/Components/Launch/LaunchDialog.py | 78 +++++++++++ Rare/Components/Launch/__init__.py | 0 Rare/Components/Tabs/Downloads/DownloadTab.py | 1 + Rare/Components/Tabs/Games/GameList.py | 7 +- .../Tabs/Games/GameWidgetInstalled.py | 1 + Rare/Main.py | 41 +----- Rare/utils/utils.py | 122 +++++++++--------- 7 files changed, 151 insertions(+), 99 deletions(-) create mode 100644 Rare/Components/Launch/LaunchDialog.py create mode 100644 Rare/Components/Launch/__init__.py diff --git a/Rare/Components/Launch/LaunchDialog.py b/Rare/Components/Launch/LaunchDialog.py new file mode 100644 index 00000000..1f15bfdf --- /dev/null +++ b/Rare/Components/Launch/LaunchDialog.py @@ -0,0 +1,78 @@ +from logging import getLogger + +from PyQt5.QtCore import QThread, pyqtSignal +from PyQt5.QtWidgets import QDialog, QLabel, QProgressBar, QVBoxLayout +from legendary.core import LegendaryCore + +from Rare.utils.Dialogs.Login.LoginDialog import LoginDialog +from Rare.utils.utils import download_images +logger = getLogger("Login") + +class LaunchThread(QThread): + download_progess = pyqtSignal(int) + action = pyqtSignal(str) + + def __init__(self, core: LegendaryCore, parent=None): + super(LaunchThread, self).__init__(parent) + self.core = core + + def run(self): + self.action.emit("Login") + self.action.emit("Downloading Images") + download_images(self.download_progess, self.core) + self.action.emit("finish") + +class LoginThread(QThread): + def __init__(self, core: LegendaryCore): + super(LoginThread, self).__init__() + self.core = core + + def run(self): + logger.info("Try if you are logged in") + try: + if self.core.login(): + logger.info("You are logged in") + else: + self.run() + except ValueError: + logger.info("You are not logged in. Open Login Window") + login_window = LoginDialog(self.core) + if not login_window.login(): + return + + +class LaunchDialog(QDialog): + def __init__(self, core: LegendaryCore): + super(LaunchDialog, self).__init__() + self.core = core + self.login_thread = LoginThread(core) + self.login_thread.finished.connect(self.launch) + self.login_thread.start() + + self.title = QLabel("

"+self.tr("Launching Rare")+"

") + self.info_pb = QProgressBar() + self.info_text = QLabel(self.tr("Logging in")) + self.layout = QVBoxLayout() + + self.layout.addWidget(self.title) + self.layout.addWidget(self.info_pb) + self.layout.addWidget(self.info_text) + + self.setLayout(self.layout) + + + def launch(self): + self.info_pb.setMaximum(len(self.core.get_game_list())) + self.info_text.setText("Downloading Images") + self.thread = LaunchThread(self.core, self) + self.thread.download_progess.connect(self.update_pb) + self.thread.action.connect(self.info) + self.thread.start() + + def update_pb(self, i: int): + self.info_pb.setValue(i) + + def info(self, text: str): + if text == "finish": + self.close() + self.info_text.setText(text) diff --git a/Rare/Components/Launch/__init__.py b/Rare/Components/Launch/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Rare/Components/Tabs/Downloads/DownloadTab.py b/Rare/Components/Tabs/Downloads/DownloadTab.py index 097aa2de..f1860d2a 100644 --- a/Rare/Components/Tabs/Downloads/DownloadTab.py +++ b/Rare/Components/Tabs/Downloads/DownloadTab.py @@ -108,6 +108,7 @@ class DownloadTab(QWidget): def install_game(self, options: {}): game = self.core.get_game(options["app_name"]) + dlm, analysis, igame = self.core.prepare_download( game=game, base_path=options["options"]["path"], diff --git a/Rare/Components/Tabs/Games/GameList.py b/Rare/Components/Tabs/Games/GameList.py index a41f92c9..c63b50f5 100644 --- a/Rare/Components/Tabs/Games/GameList.py +++ b/Rare/Components/Tabs/Games/GameList.py @@ -27,23 +27,19 @@ class GameList(QScrollArea): self.widgets=[] self.layout = FlowLayout() # Installed Games - for game in self.core.get_installed_list(): + for game in sorted(self.core.get_installed_list(), key=lambda x: x.title): # continue widget = GameWidgetInstalled(self.core, game) self.layout.addWidget(widget) widget.update_list.connect(self.update_list) uninstalled_games = [] - installed = [] installed = [i.app_name for i in self.core.get_installed_list()] - print(len(installed)) # get Uninstalled games - print(len(self.core.get_game_list())) for game in sorted(self.core.get_game_list(), key=lambda x: x.app_title): if not game.app_name in installed: uninstalled_games.append(game) # add uninstalled to gui - print(len(uninstalled_games)) for game in uninstalled_games: widget = GameWidgetUninstalled(self.core, game) widget.install_game.connect(lambda options: self.install_game.emit(options)) @@ -68,6 +64,5 @@ class GameList(QScrollArea): def update_list(self): print("Updating List") self.setWidget(QWidget()) - self.core.login() self.init_ui() self.update() \ No newline at end of file diff --git a/Rare/Components/Tabs/Games/GameWidgetInstalled.py b/Rare/Components/Tabs/Games/GameWidgetInstalled.py index ea3f0ec1..f2b84c5c 100644 --- a/Rare/Components/Tabs/Games/GameWidgetInstalled.py +++ b/Rare/Components/Tabs/Games/GameWidgetInstalled.py @@ -39,6 +39,7 @@ class GameWidgetInstalled(QWidget): else: logger.warning(f"No Image found: {self.game.title}") pixmap = None + if pixmap: w = 200 pixmap = pixmap.scaled(w, int(w * 4 / 3)) diff --git a/Rare/Main.py b/Rare/Main.py index 6a875cf0..c20ad0e0 100644 --- a/Rare/Main.py +++ b/Rare/Main.py @@ -2,20 +2,17 @@ import logging import os import sys -import requests -from PyQt5.QtCore import QTranslator, pyqtSignal -from PyQt5.QtWidgets import QApplication, QMessageBox - +from PyQt5.QtCore import QTranslator +from PyQt5.QtWidgets import QApplication from legendary.core import LegendaryCore from Rare import style_path, lang_path +from Rare.Components.Launch.LaunchDialog import LaunchDialog from Rare.Components.MainWindow import MainWindow - # from Rare.Start.Launch import LaunchDialog # from Rare.Start.Login import LoginWindow # from Rare.utils.RareUtils import get_lang -from Rare.utils.Dialogs.Login.LoginDialog import LoginDialog -from Rare.utils.utils import download_images, get_lang +from Rare.utils.utils import get_lang logging.basicConfig( format='[%(name)s] %(levelname)s: %(message)s', @@ -39,35 +36,9 @@ def main(): # Style app.setStyleSheet(open(style_path + "RareStyle.qss").read()) - # Offline mode (not completed) - offline = True - # Login - logger.info("Try if you are logged in") - try: - if core.login(): - logger.info("You are logged in") - offline = False - else: - logger.error("Login Failed") - main() - except ValueError: - # If not Logged in: Start Login window - logger.info("You are not logged in. Open Login Window") - login_window = LoginDialog(core) - if not login_window.login(): - return - - # Start Offline mode - except requests.exceptions.ConnectionError: - offline = True - QMessageBox.information(None, "Offline", "You are offline. Launching Rare in offline mode") - # Launch Offlienmode - if not offline: - # launch_dialog = LaunchDialog(core) - # launch_dialog.exec_() - pass - # mainwindow = MainWindow(core) + launch_dialog = LaunchDialog(core) + launch_dialog.exec_() mainwindow = MainWindow(core) app.exec_() diff --git a/Rare/utils/utils.py b/Rare/utils/utils.py index 5fdf81ab..0c4abd23 100644 --- a/Rare/utils/utils.py +++ b/Rare/utils/utils.py @@ -1,5 +1,6 @@ import json import os +import shutil from logging import getLogger import requests @@ -20,67 +21,72 @@ def download_images(signal: pyqtSignal, core: LegendaryCore): # Download Images for i, game in enumerate(sorted(core.get_game_list(), key=lambda x: x.app_title)): - - if not os.path.isdir(f"{IMAGE_DIR}/" + game.app_name): - os.mkdir(f"{IMAGE_DIR}/" + game.app_name) - - if not os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/image.json"): - json_data = {"DieselGameBoxTall": None, "DieselGameBoxLogo": None} - else: - json_data = json.load(open(f"{IMAGE_DIR}/{game.app_name}/image.json", "r")) - - for image in game.metadata["keyImages"]: - if image["type"] == "DieselGameBoxTall" or image["type"] == "DieselGameBoxLogo": - - if json_data[image["type"]] != image["md5"] or not os.path.isfile( - f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png"): - # Download - json_data[image["type"]] = image["md5"] - # os.remove(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png") - json.dump(json_data, open(f"{IMAGE_DIR}/{game.app_name}/image.json", "w")) - logger.info(f"Download Image for Game: {game.app_title}") - url = image["url"] - with open(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png", "wb") as f: - f.write(requests.get(url).content) - f.close() - - if not os.path.isfile(f'{IMAGE_DIR}/' + game.app_name + '/UninstalledArt.png'): - - if os.path.isfile(f'{IMAGE_DIR}/' + game.app_name + '/DieselGameBoxTall.png'): - # finalArt = Image.open(f'{IMAGE_DIR}/' + game.app_name + '/DieselGameBoxTall.png') - # finalArt.save(f'{IMAGE_DIR}/{game.app_name}/FinalArt.png') - # And same with the grayscale one - - bg = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png") - uninstalledArt = bg.convert('L') - uninstalledArt.save(f'{IMAGE_DIR}/{game.app_name}/UninstalledArt.png') - elif os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png"): - bg: Image.Image = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png") - bg = bg.resize((int(bg.size[1] * 3 / 4), bg.size[1])) - logo = Image.open(f'{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png').convert('RGBA') - wpercent = ((bg.size[0] * (3 / 4)) / float(logo.size[0])) - hsize = int((float(logo.size[1]) * float(wpercent))) - logo = logo.resize((int(bg.size[0] * (3 / 4)), hsize), Image.ANTIALIAS) - # Calculate where the image has to be placed - pasteX = int((bg.size[0] - logo.size[0]) / 2) - pasteY = int((bg.size[1] - logo.size[1]) / 2) - # And finally copy the background and paste in the image - # finalArt = bg.copy() - # finalArt.paste(logo, (pasteX, pasteY), logo) - # Write out the file - # finalArt.save(f'{IMAGE_DIR}/' + game.app_name + '/FinalArt.png') - logoCopy = logo.copy() - logoCopy.putalpha(int(256 * 3 / 4)) - logo.paste(logoCopy, logo) - uninstalledArt = bg.copy() - uninstalledArt.paste(logo, (pasteX, pasteY), logo) - uninstalledArt = uninstalledArt.convert('L') - uninstalledArt.save(f'{IMAGE_DIR}/' + game.app_name + '/UninstalledArt.png') - else: - logger.warning(f"File {IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png dowsn't exist") + download_image(game) signal.emit(i) +def download_image(game, force=False): + if force: + shutil.rmtree(f"{IMAGE_DIR}/{game.app_name}") + if not os.path.isdir(f"{IMAGE_DIR}/" + game.app_name): + os.mkdir(f"{IMAGE_DIR}/" + game.app_name) + + if not os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/image.json"): + json_data = {"DieselGameBoxTall": None, "DieselGameBoxLogo": None} + else: + json_data = json.load(open(f"{IMAGE_DIR}/{game.app_name}/image.json", "r")) + # Download + for image in game.metadata["keyImages"]: + if image["type"] == "DieselGameBoxTall" or image["type"] == "DieselGameBoxLogo": + + if json_data[image["type"]] != image["md5"] or not os.path.isfile( + f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png"): + # Download + json_data[image["type"]] = image["md5"] + # os.remove(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png") + json.dump(json_data, open(f"{IMAGE_DIR}/{game.app_name}/image.json", "w")) + logger.info(f"Download Image for Game: {game.app_title}") + url = image["url"] + with open(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png", "wb") as f: + f.write(requests.get(url).content) + f.close() + # scale and grey + if not os.path.isfile(f'{IMAGE_DIR}/' + game.app_name + '/UninstalledArt.png'): + + if os.path.isfile(f'{IMAGE_DIR}/' + game.app_name + '/DieselGameBoxTall.png'): + # finalArt = Image.open(f'{IMAGE_DIR}/' + game.app_name + '/DieselGameBoxTall.png') + # finalArt.save(f'{IMAGE_DIR}/{game.app_name}/FinalArt.png') + # And same with the grayscale one + + bg = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png") + uninstalledArt = bg.convert('L') + uninstalledArt.save(f'{IMAGE_DIR}/{game.app_name}/UninstalledArt.png') + elif os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png"): + bg: Image.Image = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png") + bg = bg.resize((int(bg.size[1] * 3 / 4), bg.size[1])) + logo = Image.open(f'{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png').convert('RGBA') + wpercent = ((bg.size[0] * (3 / 4)) / float(logo.size[0])) + hsize = int((float(logo.size[1]) * float(wpercent))) + logo = logo.resize((int(bg.size[0] * (3 / 4)), hsize), Image.ANTIALIAS) + # Calculate where the image has to be placed + pasteX = int((bg.size[0] - logo.size[0]) / 2) + pasteY = int((bg.size[1] - logo.size[1]) / 2) + # And finally copy the background and paste in the image + # finalArt = bg.copy() + # finalArt.paste(logo, (pasteX, pasteY), logo) + # Write out the file + # finalArt.save(f'{IMAGE_DIR}/' + game.app_name + '/FinalArt.png') + logoCopy = logo.copy() + logoCopy.putalpha(int(256 * 3 / 4)) + logo.paste(logoCopy, logo) + uninstalledArt = bg.copy() + uninstalledArt.paste(logo, (pasteX, pasteY), logo) + uninstalledArt = uninstalledArt.convert('L') + uninstalledArt.save(f'{IMAGE_DIR}/' + game.app_name + '/UninstalledArt.png') + else: + logger.warning(f"File {IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png dowsn't exist") + + def get_lang(): if "Legendary" in legendaryConfig.get_config() and "locale" in legendaryConfig.get_config()["Legendary"]: logger.info("Found locale in Legendary config: " + legendaryConfig.get_config()["Legendary"]["locale"])