1
0
Fork 0
mirror of synced 2024-06-02 18:54:41 +12:00

Add a new signal system

This commit is contained in:
Dummerle 2021-09-29 23:22:47 +02:00
parent 0f3b492ae4
commit 4b5a0b0084
14 changed files with 212 additions and 187 deletions

View file

@ -15,6 +15,7 @@ from rare import languages_path, resources_path, cache_dir
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.components.tray_icon import TrayIcon
from rare.utils.models import Signals
from rare.utils.utils import load_color_scheme
start_time = time.strftime('%y-%m-%d--%H-%M') # year-month-day-hour-minute
@ -70,11 +71,14 @@ class App(QApplication):
self.launch_dialog = None
self.setApplicationName("Rare")
self.setOrganizationName("Rare")
settings = QSettings()
self.settings = QSettings()
self.signals = Signals()
self.signals.app.connect(lambda x: self.handle_signal(*x))
# Translator
self.translator = QTranslator()
lang = settings.value("language", self.core.language_code, type=str)
lang = self.settings.value("language", self.core.language_code, type=str)
if os.path.exists(p := os.path.join(languages_path, lang + ".qm")):
self.translator.load(p)
logger.info("Your language is supported: " + lang)
@ -84,18 +88,18 @@ class App(QApplication):
# Style
self.setStyle(QStyleFactory.create("Fusion"))
if settings.value("color_scheme", None) is None and settings.value("style_sheet", None) is None:
settings.setValue("color_scheme", "")
settings.setValue("style_sheet", "RareStyle")
if color := settings.value("color_scheme", False):
settings.setValue("style_sheet", "")
if self.settings.value("color_scheme", None) is None and self.settings.value("style_sheet", None) is None:
self.settings.setValue("color_scheme", "")
self.settings.setValue("style_sheet", "RareStyle")
if color := self.settings.value("color_scheme", False):
self.settings.setValue("style_sheet", "")
custom_palette = load_color_scheme(os.path.join(resources_path, "colors", color + ".scheme"))
if custom_palette is not None:
self.setPalette(custom_palette)
qtawesome.set_defaults(color=custom_palette.color(QPalette.Text))
elif style := settings.value("style_sheet", False):
settings.setValue("color_scheme", "")
elif style := self.settings.value("style_sheet", False):
self.settings.setValue("color_scheme", "")
stylesheet = open(os.path.join(resources_path, "stylesheets", style, "stylesheet.qss")).read()
style_resource_path = os.path.join(resources_path, "stylesheets", style, "")
if os.name == "nt":
@ -122,22 +126,26 @@ class App(QApplication):
def start_app(self, offline=False):
self.args.offline = offline
self.mainwindow = MainWindow(self.core, self.args)
self.mainwindow.quit_app.connect(self.exit_app)
self.mainwindow = MainWindow(self.core, self.args, self.signals)
self.tray_icon = TrayIcon(self)
self.tray_icon.exit_action.triggered.connect(self.exit_app)
self.tray_icon.start_rare.triggered.connect(self.mainwindow.show)
self.tray_icon.activated.connect(self.tray)
if not offline:
self.mainwindow.tab_widget.downloadTab.finished.connect(lambda x: self.tray_icon.showMessage(
self.tr("Download finished"),
self.tr("Download finished. {} is playable now").format(self.core.get_game(x[1]).app_title),
QSystemTrayIcon.Information, 4000) if (
x[0] and QSettings().value("notification", True, bool)) else None)
if not self.args.silent:
self.mainwindow.show()
def handle_signal(self, action, data):
if action == self.signals.actions.quit_app:
self.exit_app(data)
elif action == self.signals.actions.installation_finished:
# data: (notification, app_title)
if data[0] and self.settings.value("notification", True, bool):
self.tray_icon.showMessage(
self.tr("Download finished"),
self.tr("Download finished. {} is playable now").format(data[1]),
QSystemTrayIcon.Information, 4000)
def tray(self, reason):
if reason == QSystemTrayIcon.DoubleClick:
self.mainwindow.show()

View file

@ -1,26 +1,30 @@
import os
from logging import getLogger
from PyQt5.QtCore import Qt, QSettings, QTimer, pyqtSignal
from PyQt5.QtCore import Qt, QSettings, QTimer
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QApplication
from legendary.core import LegendaryCore
from rare import data_dir
from rare.components.tabs.tab_widget import TabWidget
from rare.utils.models import Signals
from rare.utils.rpc import DiscordRPC
logger = getLogger("Window")
class MainWindow(QMainWindow):
quit_app = pyqtSignal(int)
def __init__(self, core: LegendaryCore, args):
def __init__(self, core: LegendaryCore, args, signals: Signals):
super(MainWindow, self).__init__()
self.setAttribute(Qt.WA_DeleteOnClose)
self.settings = QSettings()
self.core = core
self.signals = signals
self.signals.main_window.connect(lambda x: self.handle_signal(*x))
self.offline = args.offline
width, height = 1200, 800
if self.settings.value("save_size", False):
@ -30,8 +34,7 @@ class MainWindow(QMainWindow):
self.setGeometry((desktop.width() - width) / 2, (desktop.height() - height) / 2, width, height)
self.setWindowTitle("Rare - GUI for legendary")
self.tab_widget = TabWidget(core, self, args)
self.tab_widget.quit_app.connect(self.quit_app.emit)
self.tab_widget = TabWidget(core, self.signals, self, args)
self.setCentralWidget(self.tab_widget)
if not args.offline:
self.rpc = DiscordRPC(core)
@ -59,6 +62,9 @@ class MainWindow(QMainWindow):
self.timer.timeout.connect(self.timer_finished)
self.timer.start(1000)
def handle_signal(self, action, data):
pass
def timer_finished(self):
file_path = os.path.join(data_dir, "lockfile")
if os.path.exists(file_path):

View file

@ -1,18 +1,17 @@
import webbrowser
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QLabel, QPushButton
from legendary.core import LegendaryCore
from rare.utils.models import Signals
class MiniWidget(QWidget):
quit_app = pyqtSignal(int)
def __init__(self, core: LegendaryCore):
def __init__(self, core: LegendaryCore, signals: Signals):
super(MiniWidget, self).__init__()
self.layout = QVBoxLayout()
self.core = core
self.signals = signals
self.layout.addWidget(QLabel("Account"))
username = self.core.lgd.userdata.get("display_name")
if not username:
@ -41,4 +40,4 @@ class MiniWidget(QWidget):
if reply == QMessageBox.Yes:
self.core.lgd.invalidate_userdata()
self.quit_app.emit(-133742) # restart exit code
self.signals.app.emit((self.signals.actions.quit_app, -133742)) # restart exit code

View file

@ -8,6 +8,7 @@ from legendary.models.game import SaveGameStatus
from rare.components.dialogs.path_input_dialog import PathInputDialog
from rare.components.tabs.cloud_saves.sync_widget import SyncWidget
from rare.utils.extra_widgets import WaitingSpinner
from rare.utils.models import Signals
logger = getLogger("Sync Saves")
@ -27,12 +28,17 @@ class LoadThread(QThread):
class SyncSaves(QScrollArea):
finished = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent):
super(SyncSaves, self).__init__(parent=parent)
def __init__(self, core: LegendaryCore, signals: Signals):
super(SyncSaves, self).__init__()
self.core = core
self.signals = signals
self.signals.cloud_saves.connect(self.signal_received)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.load_saves()
def signal_received(self, action, ):
pass
def load_saves(self, app_name=None, auto=False):
self.widget = QWidget()
layout = QVBoxLayout()

View file

@ -11,25 +11,25 @@ from legendary.models.game import Game, InstalledGame
from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.tabs.downloads.dl_queue_widget import DlQueueWidget
from rare.components.tabs.downloads.download_thread import DownloadThread
from rare.utils.models import InstallOptionsModel, InstallQueueItemModel
from rare.utils.models import InstallOptionsModel, InstallQueueItemModel, Signals
from rare.utils.utils import get_size
logger = getLogger("Download")
class DownloadTab(QWidget):
finished = pyqtSignal(tuple)
thread: QThread
dl_queue = []
dl_status = pyqtSignal(int)
def __init__(self, core: LegendaryCore, updates: list, parent):
super(DownloadTab, self).__init__(parent=parent)
def __init__(self, core: LegendaryCore, updates: list, signals: Signals):
super(DownloadTab, self).__init__()
self.core = core
self.layout = QVBoxLayout()
self.active_game: Game = None
self.analysis = None
self.signals = signals
self.signals.dl_tab.connect(lambda x: self.signal_received(*x))
self.info_layout = QGridLayout()
self.installing_game = QLabel(self.tr("No active Download"))
@ -81,13 +81,17 @@ class DownloadTab(QWidget):
self.setLayout(self.layout)
def signal_received(self, action, data):
if action == self.signals.actions.install_game:
self.get_install_options(data)
def add_update(self, igame: InstalledGame):
widget = UpdateWidget(self.core, igame, self)
self.update_layout.addWidget(widget)
self.update_widgets[igame.app_name] = widget
widget.update_signal.connect(self.update_game)
widget.update_signal.connect(self.get_install_options)
if QSettings().value("auto_update", False, bool):
self.update_game(igame.app_name, True)
self.get_install_options(InstallOptionsModel(app_name=igame.app_name, update=True, silent=True))
widget.update_button.setDisabled(True)
def update_dl_queue(self, dl_queue):
@ -116,6 +120,8 @@ class DownloadTab(QWidget):
self.analysis = queue_item.download.analysis
self.installing_game.setText(self.tr("Installing Game: ") + self.active_game.app_title)
self.signals.games_tab.emit((self.signals.actions.start_installation, self.active_game))
def status(self, text):
if text == "dl_finished":
pass
@ -124,22 +130,24 @@ class DownloadTab(QWidget):
# QMessageBox.information(self, "Info", "Download finished")
logger.info("Download finished: " + self.active_game.app_title)
app_name = self.active_game.app_name
game = self.active_game
self.active_game = None
if self.dl_queue:
if self.dl_queue[0].download.game.app_name == app_name:
if self.dl_queue[0].download.game.app_name == game.app_name:
self.dl_queue.pop(0)
self.queue_widget.update_queue(self.dl_queue)
if app_name in self.update_widgets.keys():
self.update_widgets[app_name].setVisible(False)
self.update_widgets.pop(app_name)
if game.app_name in self.update_widgets.keys():
self.update_widgets[game.app_name].setVisible(False)
self.update_widgets.pop(game.app_name)
if len(self.update_widgets) == 0:
self.update_text.setVisible(True)
self.finished.emit((True, app_name))
self.signals.app.emit((self.signals.actions.installation_finished, (True, game.app_title)))
self.signals.games_tab.emit((self.signals.actions.installation_finished, game.app_name))
self.signals.tab_widget.emit(
(self.signals.actions.set_dl_tab_text, len(self.dl_queue) + len(self.update_widgets.keys())))
self.reset_infos()
if len(self.dl_queue) != 0:
@ -152,8 +160,8 @@ class DownloadTab(QWidget):
elif text == "stop":
self.reset_infos()
self.signals.app.emit((self.signals.actions.installation_finished, (False, self.active_game.app_title)))
self.active_game = None
self.finished.emit((False, ""))
if self.dl_queue:
self.start_installation(self.dl_queue[0])
@ -175,29 +183,39 @@ class DownloadTab(QWidget):
self.downloaded.setText(
self.tr("Downloaded") + f": {get_size(ui_update.total_downloaded)} / {get_size(self.analysis.dl_size)}")
self.time_left.setText(self.tr("Time left: ") + self.get_time(ui_update.estimated_time_left))
self.dl_status.emit(int(100 * ui_update.total_downloaded / self.analysis.dl_size))
self.signals.games_tab.emit(
(self.signals.actions.dl_status, int(100 * ui_update.total_downloaded / self.analysis.dl_size)))
def get_time(self, seconds: int) -> str:
return str(datetime.timedelta(seconds=seconds))
def update_game(self, app_name: str, auto=False):
logger.info("Update " + app_name)
install_dialog = InstallDialog(self.core,
InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)),
update=True, silent=auto, parent=self)
install_dialog.result_ready.connect(self.on_install_dialog_closed)
install_dialog.execute()
def on_install_dialog_closed(self, download_item: InstallQueueItemModel):
if download_item:
self.install_game(download_item)
self.signals.tab_widget.emit((self.signals.actions.set_index, 1))
else:
self.update_widgets[download_item.options.app_name].update_button.setDisabled(False)
self.update_widgets[download_item.options.app_name].update_with_settings.setDisabled(False)
if w := self.update_widgets.get(download_item.options.app_name):
w.update_button.setDisabled(False)
w.update_with_settings.setDisabled(False)
def get_install_options(self, options: InstallOptionsModel):
install_dialog = InstallDialog(self.core,
InstallQueueItemModel(options=options),
update=options.update, silent=options.silent, parent=self)
install_dialog.result_ready.connect(self.on_install_dialog_closed)
install_dialog.execute()
def start_download(self, download_item: InstallQueueItemModel):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + 1
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.setCurrentIndex(1)
self.downloadTab.install_game(download_item)
self.games_tab.start_download(download_item.options.app_name)
class UpdateWidget(QWidget):
update_signal = pyqtSignal(str, bool)
update_signal = pyqtSignal(InstallOptionsModel)
def __init__(self, core: LegendaryCore, game: InstalledGame, parent):
super(UpdateWidget, self).__init__(parent=parent)
@ -223,4 +241,4 @@ class UpdateWidget(QWidget):
def update_game(self, auto: bool):
self.update_button.setDisabled(True)
self.update_with_settings.setDisabled(True)
self.update_signal.emit(self.game.app_name, auto) # True if settings
self.update_signal.emit(InstallOptionsModel(app_name=self.game.app_name, silent=auto)) # True if settings

View file

@ -5,6 +5,7 @@ from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget
from legendary.core import LegendaryCore
from legendary.models.game import GameAsset
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.tabs.games.game_info import InfoTabs
from rare.components.tabs.games.game_info.uninstalled_info import UninstalledTabInfo
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
@ -17,7 +18,9 @@ from rare.components.tabs.games.game_widgets.uninstalled_list_widget import List
from rare.components.tabs.games.head_bar import GameListHeadBar
from rare.components.tabs.games.import_widget import ImportWidget
from rare.ui.components.tabs.games.games_tab import Ui_GamesTab
from rare.utils import legendary_utils
from rare.utils.extra_widgets import FlowLayout
from rare.utils.models import Signals
from rare.utils.utils import get_pixmap, download_image, get_uninstalled_pixmap
logger = getLogger("GamesTab")
@ -28,27 +31,27 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
widgets = {}
running_games = []
game_exited = pyqtSignal(str)
game_started = pyqtSignal(str)
def __init__(self, core: LegendaryCore, offline):
def __init__(self, core: LegendaryCore, offline, signals: Signals):
super(GamesTab, self).__init__()
self.setupUi(self)
self.core = core
self.offline = offline
self.signals = signals
self.signals.games_tab.connect(lambda x: self.signal_received(*x))
self.settings = QSettings()
self.head_bar = GameListHeadBar()
self.games.layout().insertWidget(0, self.head_bar)
self.game_info = InfoTabs(self.core, self)
self.game_info.info.update_list.connect(self.update_list)
self.game_info = InfoTabs(self.core, self.signals, self)
self.addWidget(self.game_info)
self.import_widget = ImportWidget(core, self)
self.addWidget(self.import_widget)
self.uninstalled_info_widget = UninstalledTabInfo(core, self)
self.uninstalled_info_widget = UninstalledTabInfo(core, self.signals, self)
self.layout().addWidget(self.uninstalled_info_widget)
# navigation
@ -56,10 +59,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.import_widget.back_button.clicked.connect(lambda: self.setCurrentIndex(0))
self.uninstalled_info_widget.tabBarClicked.connect(lambda x: self.setCurrentIndex(0) if x == 0 else None)
self.game_info.info.update_list.connect(self.update_list)
self.setup_game_list()
if not self.settings.value("icon_view", True, bool):
@ -73,7 +72,26 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.head_bar.refresh_list.clicked.connect(self.update_list)
self.head_bar.view.toggled.connect(self.toggle_view)
self.filter(["", "installed", "offline", "32bit", "installable"][self.settings.value("filter", 0, int)])
self.filter(self.head_bar.available_filters[self.settings.value("filter", 0, int)])
def signal_received(self, action, data):
if action == self.signals.actions.dl_status:
self.installing_widget.set_status(data)
elif action == self.signals.actions.set_index:
self.setCurrentIndex(data)
elif action == self.signals.actions.start_installation:
self.installing_widget.set_game(data)
self.installing_widget.setVisible(True)
elif action == self.signals.actions.installation_finished:
self.update_list(data)
self.installing_widget.setVisible(False)
elif action == self.signals.actions.uninstall:
infos = UninstallDialog(data).get_information()
if infos == 0:
return
legendary_utils.uninstall(data.app_name, self.core, infos)
self.setCurrentIndex(0)
self.update_list(data.app_name)
def show_game_info(self, game):
self.game_info.update_game(game, self.dlcs)
@ -197,10 +215,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
return icon_widget, list_widget
def start_download(self, app_name):
self.installing_widget.set_game(self.core.get_game(app_name))
self.installing_widget.setVisible(True)
def finished(self, app_name):
self.running_games.remove(app_name)
self.active_game = ("", 0)

View file

@ -1,27 +1,29 @@
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWidgets import QWidget, QTabWidget
from legendary.models.game import Game
from qtawesome import icon
from legendary.models.game import Game
from rare.components.tabs.games.game_info.game_dlc import GameDlc
from rare.components.tabs.games.game_info.game_info import GameInfo
from rare.components.tabs.games.game_info.game_settings import GameSettings
from rare.utils.extra_widgets import SideTabBar
from rare.utils.models import Signals
class InfoTabs(QTabWidget):
def __init__(self, core, parent):
def __init__(self, core, signals: Signals, parent):
super(InfoTabs, self).__init__(parent=parent)
self.app_name = ""
self.core = core
self.signals = signals
self.setTabBar(SideTabBar())
self.setTabPosition(QTabWidget.West)
self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back"))
self.tabBarClicked.connect(lambda x: self.parent().setCurrentIndex(0) if x == 0 else None)
self.info = GameInfo(core, self)
self.info = GameInfo(self.core, self.signals, self)
self.addTab(self.info, self.tr("Information"))
self.settings = GameSettings(core, self)

View file

@ -1,29 +1,27 @@
import os
import platform
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QMessageBox
from legendary.core import LegendaryCore
from legendary.models.game import Game, InstalledGame
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
from rare.utils.legendary_utils import VerifyThread
from rare.utils.models import Signals, InstallOptionsModel
from rare.utils.steam_grades import SteamWorker
from rare.utils.utils import get_size, get_pixmap
class GameInfo(QWidget, Ui_GameInfo):
igame: InstalledGame
game: Game
uninstall_game = pyqtSignal(str)
update_list = pyqtSignal(str)
verify_game = pyqtSignal(str)
game: Game = None
verify_threads = dict()
def __init__(self, core: LegendaryCore, parent):
def __init__(self, core: LegendaryCore, signals: Signals, parent):
super(GameInfo, self).__init__(parent=parent)
self.setupUi(self)
self.core = core
self.signals = signals
if platform.system() == "Windows":
self.lbl_grade.setVisible(False)
@ -41,8 +39,11 @@ class GameInfo(QWidget, Ui_GameInfo):
self.repair_button.clicked.connect(self.repair)
def uninstall(self):
self.uninstall_game.emit(self.game.app_name)
self.update_list.emit(self.game.app_name)
# uninstall game
self.signals.games_tab.emit((self.signals.actions.uninstall, self.game))
# remove from update or dl_queue
self.signals.dl_tab.emit((self.signals.actions.uninstall, self.game))
def repair(self):
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair')
@ -50,19 +51,21 @@ class GameInfo(QWidget, Ui_GameInfo):
QMessageBox.warning(self, "Warning", self.tr(
"Repair file does not exist or game does not need a repair. Please verify game first"))
return
self.verify_game.emit(self.game.app_name)
self.signals.dl_tab.emit(
(self.signals.actions.install_game, InstallOptionsModel(app_name=self.game.app_name, repair=True,
base_path=self.igame.install_path)))
def verify(self):
self.verify_widget.setCurrentIndex(1)
verify_thread = VerifyThread(self.core, self.game.app_name)
verify_thread.status.connect(self.verify_satistics)
verify_thread.status.connect(self.verify_staistics)
verify_thread.summary.connect(self.finish_verify)
verify_thread.finished.connect(verify_thread.deleteLater)
verify_thread.start()
self.verify_progress.setValue(0)
self.verify_threads[self.game.app_name] = verify_thread
def verify_satistics(self, progress):
def verify_staistics(self, progress):
# checked, max, app_name
if progress[2] == self.game.app_name:
self.verify_progress.setValue(progress[0] * 100 / progress[1])
@ -72,12 +75,16 @@ class GameInfo(QWidget, Ui_GameInfo):
if failed == 0 and missing == 0:
QMessageBox.information(self, "Summary",
"Game was verified successfully. No missing or corrupt files found")
self.igame.needs_verification = False
self.core.lgd.set_installed_game(self.igame.app_name, self.igame)
else:
ans = QMessageBox.question(self, "Summary", self.tr(
'Verification failed, {} file(s) corrupted, {} file(s) are missing. Do you want to repair them?').format(
failed, missing), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if ans == QMessageBox.Yes:
self.verify_game.emit(self.game.app_name)
self.signals.dl_tab.emit(
(self.signals.actions.install_game, InstallOptionsModel(app_name=self.game.app_name, repair=True,
base_path=self.igame.install_path)))
self.verify_widget.setCurrentIndex(0)
self.verify_threads.pop(app_name)

View file

@ -1,8 +1,6 @@
import json
import os
import platform
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWidgets import QWidget, QTabWidget, QTreeView
from qtawesome import icon
@ -12,20 +10,22 @@ 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 SideTabBar
from rare.utils.json_formatter import QJsonModel
from rare.utils.models import Signals, InstallOptionsModel
from rare.utils.steam_grades import SteamWorker
from rare.utils.utils import get_pixmap
class UninstalledTabInfo(QTabWidget):
def __init__(self, core, parent):
def __init__(self, core, signals: Signals, parent):
super(UninstalledTabInfo, self).__init__(parent=parent)
self.app_name = ""
self.core = core
self.signals = signals
self.setTabBar(SideTabBar())
self.setTabPosition(QTabWidget.West)
self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back"))
self.info = UninstalledInfo(core, self)
self.info = UninstalledInfo(core, self.signals, self)
self.addTab(self.info, self.tr("Game Info"))
self.view = QTreeView()
@ -56,13 +56,13 @@ class UninstalledTabInfo(QTabWidget):
class UninstalledInfo(QWidget, Ui_GameInfo):
game: Game
install_game = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent=None):
def __init__(self, core: LegendaryCore, signals: Signals, parent=None):
super(UninstalledInfo, self).__init__(parent=parent)
self.setupUi(self)
self.core = core
self.signals = signals
self.install_button.clicked.connect(self.install_game)
if platform.system() != "Windows":
self.steam_worker = SteamWorker(self.core)
self.steam_worker.rating_signal.connect(self.grade.setText)
@ -79,11 +79,11 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
self.game_actions_stack.setCurrentIndex(1)
self.game_actions_stack.resize(self.game_actions_stack.minimumSize())
self.install_button.clicked.connect(lambda: self.install_game.emit(self.game.app_name))
def install_game(self):
self.signals.dl_tab.emit((self.signals.actions.install_game, InstallOptionsModel(app_name=self.game.app_name)))
def update_game(self, game: Game):
self.game = game
self.game_title.setText(f"<h2>{self.game.app_title}</h2>")
pixmap = get_pixmap(game.app_name)

View file

@ -64,9 +64,9 @@ class InstalledIconWidget(BaseInstalledWidget):
self.info_label.setObjectName("info_label")
self.layout.addWidget(self.info_label)
# p = self.palette()
# p.setColor(self.backgroundRole(), Qt.red)
# self.setPalette(p)
if not self.is_origin and self.igame.needs_verification:
self.info_text = self.tr("Game needs verification")
self.info_label.setText(self.info_text)
self.setLayout(self.layout)
self.setFixedWidth(self.sizeHint().width())
@ -74,6 +74,8 @@ class InstalledIconWidget(BaseInstalledWidget):
def enterEvent(self, a0: QEvent) -> None:
if self.game_running:
self.info_label.setText(self.tr("Game running"))
elif not self.is_origin and self.igame.needs_verification:
self.info_label.setText(self.tr("Please verify game before playing"))
elif self.update_available:
self.info_label.setText(self.tr("Start game without version check"))
else:
@ -87,7 +89,7 @@ class InstalledIconWidget(BaseInstalledWidget):
def mousePressEvent(self, e: QMouseEvent):
# left button
if e.button() == 1 and not self.game_running:
if e.button() == 1 and not self.game_running and not self.igame.needs_verification:
if self.update_available:
self.launch(skip_version_check=True)
else:

View file

@ -36,6 +36,10 @@ class InstallingGameWidget(QGroupBox):
self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation)
self.image_widget.set_game(self.pixmap, game.app_name)
def set_status(self, s: int):
self.image_widget.status = s
self.image_widget.repaint()
class PaintWidget(QWidget):
def __init__(self):
@ -74,7 +78,3 @@ class PaintWidget(QWidget):
painter.setFont(QFont(None, 16))
painter.drawText(a0.rect(), Qt.AlignCenter, str(self.status) + "%")
painter.end()
def set_status(self, s: int):
self.status = s
self.repaint()

View file

@ -24,6 +24,8 @@ class GameListHeadBar(QWidget):
self.tr("Exclude Origin")])
self.layout().addWidget(self.filter)
self.available_filters = ["", "installed", "offline", "32bit", "installable"]
try:
self.filter.setCurrentIndex(self.settings.value("filter", 0, int))
except TypeError:
@ -58,5 +60,5 @@ class GameListHeadBar(QWidget):
self.layout().addWidget(self.refresh_list)
def filter_changed(self, i):
self.filter_changed_signal.emit(["", "installed", "offline", "32bit", "installable"][i])
self.filter_changed_signal.emit(self.available_filters[i])
self.settings.setValue("filter", i)

View file

@ -1,40 +1,38 @@
from PyQt5.QtCore import QSize, pyqtSignal, QObject
from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut
from qtawesome import icon
from legendary.core import LegendaryCore
from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.tabs.games.__init__ import GamesTab
from rare.components.tabs.tab_utils import TabBar, TabButtonWidget
from rare.components.tabs.account import MiniWidget
from rare.components.tabs.cloud_saves import SyncSaves
from rare.components.tabs.downloads import DownloadTab
from rare.components.tabs.games.__init__ import GamesTab
from rare.components.tabs.settings import SettingsTab
from rare.components.tabs.settings.debug_settings import DebugSettings
from rare.components.tabs.shop import Shop
from rare.utils import legendary_utils
from rare.utils.models import InstallQueueItemModel, InstallOptionsModel
from rare.components.tabs.tab_utils import TabBar, TabButtonWidget
from rare.utils.models import InstallOptionsModel, Signals
class TabWidget(QTabWidget):
quit_app = pyqtSignal(int)
delete_presence = pyqtSignal()
def __init__(self, core: LegendaryCore, parent, args):
def __init__(self, core: LegendaryCore, signals: Signals, parent, args):
super(TabWidget, self).__init__(parent=parent)
offline = args.offline
disabled_tab = 4 if not offline else 1
self.core = core
self.signals = signals
self.setTabBar(TabBar(disabled_tab))
# Generate Tabs
self.games_tab = GamesTab(core, self)
self.games_tab = GamesTab(core, args.offline, self.signals)
self.addTab(self.games_tab, self.tr("Games"))
self.signals.tab_widget.connect(lambda x: self.handle_signal(*x))
if not offline:
# updates = self.games_tab.default_widget.game_list.updates
self.downloadTab = DownloadTab(core, [], self)
self.downloadTab = DownloadTab(core, [], self.signals)
self.addTab(self.downloadTab, "Downloads" + (" (" + str(len([])) + ")" if len([]) != 0 else ""))
self.cloud_saves = SyncSaves(core, self)
self.cloud_saves = SyncSaves(core, self.signals)
self.addTab(self.cloud_saves, "Cloud Saves")
self.store = Shop(self.core)
self.addTab(self.store, self.tr("Store (Beta)"))
@ -51,8 +49,7 @@ class TabWidget(QTabWidget):
self.addTab(self.account, "")
self.setTabEnabled(disabled_tab + 1, False)
self.mini_widget = MiniWidget(core)
self.mini_widget.quit_app.connect(self.quit_app.emit)
self.mini_widget = MiniWidget(core, self.signals)
account_action = QWidgetAction(self)
account_action.setDefaultWidget(self.mini_widget)
account_button = TabButtonWidget(core, 'mdi.account-circle', 'Account')
@ -64,37 +61,16 @@ class TabWidget(QTabWidget):
"(!)" if self.settings.about.update_available else "")
# Signals
# open download tab
# self.games_tab.update_game.connect(lambda: self.setCurrentIndex(1))
# uninstall
self.games_tab.game_info.info.uninstall_game.connect(self.uninstall_game)
# imported
self.games_tab.import_widget.update_list.connect(self.game_imported)
if not offline:
# Download finished
self.downloadTab.finished.connect(self.dl_finished)
# install dlc
self.games_tab.game_info.dlc.install_dlc.connect(
lambda app_name, update: self.install_game(
InstallOptionsModel(app_name=app_name),
update=update))
# install game
self.games_tab.uninstalled_info_widget.info.install_game.connect(
lambda app_name: self.install_game(
InstallOptionsModel(app_name=app_name)))
# repair game
self.games_tab.game_info.info.verify_game.connect(
lambda app_name: self.install_game(
InstallOptionsModel(app_name=app_name,
base_path=core.get_installed_game(app_name).install_path,
repair=True),
silent=True)
)
# Finished sync
self.cloud_saves.finished.connect(self.finished_sync)
# Game finished
@ -110,8 +86,11 @@ class TabWidget(QTabWidget):
QShortcut("Alt+3", self).activated.connect(lambda: self.setCurrentIndex(2))
QShortcut("Alt+4", self).activated.connect(lambda: self.setCurrentIndex(5))
self.downloadTab.dl_status.connect(
self.games_tab.installing_widget.image_widget.set_status)
def handle_signal(self, action, data):
if action == self.signals.actions.set_index:
self.setCurrentIndex(data)
if action == self.signals.actions.set_dl_tab_text:
self.setTabText(1, "Downloads" + ((" (" + str(data) + ")") if data != 0 else ""))
def mouse_clicked(self, tab_num):
if tab_num == 0:
@ -119,31 +98,9 @@ class TabWidget(QTabWidget):
if tab_num == 3:
self.store.load()
# TODO; maybe pass InstallOptionsModel only, not split arguments
def install_game(self, options: InstallOptionsModel, update=False, silent=False):
install_dialog = InstallDialog(self.core,
InstallQueueItemModel(options=options),
update=update, silent=silent, parent=self)
install_dialog.result_ready.connect(self.on_install_dialog_closed)
install_dialog.execute()
def on_install_dialog_closed(self, download_item: InstallQueueItemModel):
if download_item:
self.setCurrentIndex(1)
self.start_download(download_item)
def start_download(self, download_item: InstallQueueItemModel):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + 1
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.setCurrentIndex(1)
self.downloadTab.install_game(download_item)
self.games_tab.start_download(download_item.options.app_name)
def game_imported(self, app_name: str):
igame = self.core.get_installed_game(app_name)
if self.core.get_asset(app_name, True).build_version != igame.version:
if self.core.get_asset(app_name, False).build_version != igame.version:
self.downloadTab.add_update(igame)
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
@ -157,28 +114,6 @@ class TabWidget(QTabWidget):
if game and game.supports_cloud_saves:
self.cloud_saves.sync_game(app_name, True)
def uninstall_game(self, app_name):
game = self.core.get_game(app_name)
infos = UninstallDialog(game).get_information()
if infos == 0:
return
legendary_utils.uninstall(game.app_name, self.core, infos)
self.games_tab.setCurrentIndex(0)
if app_name in self.downloadTab.update_widgets.keys():
self.downloadTab.update_layout.removeWidget(self.downloadTab.update_widgets[app_name])
self.downloadTab.update_widgets.pop(app_name)
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.downloadTab.update_text.setVisible(len(self.downloadTab.update_widgets) == 0)
# Update gamelist and set text of Downloads to "Downloads"
def dl_finished(self, update_list):
if update_list[0]:
self.games_tab.update_list(update_list[1])
self.cloud_saves.reload(update_list[1])
self.games_tab.installing_widget.setVisible(False)
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
def resizeEvent(self, event):
self.tabBar().setMinimumWidth(self.width())

View file

@ -2,6 +2,8 @@ import os
from dataclasses import field, dataclass
from multiprocessing import Queue
from PyQt5.QtCore import QObject, pyqtSignal
from legendary.downloader.mp.manager import DLManager
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
from legendary.models.game import Game, InstalledGame
@ -17,6 +19,8 @@ class InstallOptionsModel:
ignore_space_req: bool = False
force: bool = False
sdl_list: list = field(default_factory=lambda: [''])
update: bool = False
silent: bool = False
@dataclass
@ -38,3 +42,25 @@ class InstallQueueItemModel:
def __bool__(self):
return (self.status_q is not None) and (self.download is not None) and (self.options is not None)
class SignalActions:
quit_app = "quit_app"
dl_status = "dl_status"
install_game = "install_game"
start_installation = "start_installation"
installation_finished = "installation_finished"
uninstall = "uninstall"
set_index = "set_index"
set_dl_tab_text = "set_dl_tab_text"
class Signals(QObject):
actions = SignalActions()
tab_widget = pyqtSignal(tuple)
games_tab = pyqtSignal(tuple)
cloud_saves = pyqtSignal(tuple)
dl_tab = pyqtSignal(tuple)
main_window = pyqtSignal(tuple)
app = pyqtSignal(tuple)