Add a new signal system
This commit is contained in:
parent
0f3b492ae4
commit
4b5a0b0084
42
rare/app.py
42
rare/app.py
|
@ -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()
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue