Much optimization
- updating text in installed widgets - move tab_widget.py to __init__.py - errors at launching are now in a popup - remove old sync widget
This commit is contained in:
parent
65f85f9b3d
commit
0e88d3965f
11 changed files with 204 additions and 541 deletions
|
@ -6,7 +6,7 @@ from PyQt5.QtGui import QCloseEvent
|
|||
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QApplication
|
||||
|
||||
from rare import data_dir, shared
|
||||
from rare.components.tabs.tab_widget import TabWidget
|
||||
from rare.components.tabs import TabWidget
|
||||
from rare.utils.rpc import DiscordRPC
|
||||
|
||||
logger = getLogger("Window")
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
from PyQt5.QtCore import QSize, pyqtSignal
|
||||
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut
|
||||
from qtawesome import icon
|
||||
|
||||
from rare import shared
|
||||
from rare.components.tabs.account import MiniWidget
|
||||
from rare.components.tabs.downloads import DownloadTab
|
||||
from rare.components.tabs.games import GamesTab
|
||||
from rare.components.tabs.settings import SettingsTab
|
||||
from rare.components.tabs.settings.debug import DebugSettings
|
||||
from rare.components.tabs.shop import Shop
|
||||
from rare.components.tabs.tab_utils import TabBar, TabButtonWidget
|
||||
|
||||
|
||||
class TabWidget(QTabWidget):
|
||||
delete_presence = pyqtSignal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(TabWidget, self).__init__(parent=parent)
|
||||
disabled_tab = 3 if not shared.args.offline else 1
|
||||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
self.setTabBar(TabBar(disabled_tab))
|
||||
# Generate Tabs
|
||||
self.games_tab = GamesTab()
|
||||
self.addTab(self.games_tab, self.tr("Games"))
|
||||
|
||||
if not shared.args.offline:
|
||||
# updates = self.games_tab.default_widget.game_list.updates
|
||||
self.downloadTab = DownloadTab(self.games_tab.updates)
|
||||
self.addTab(self.downloadTab, "Downloads" + (
|
||||
" (" + str(len(self.games_tab.updates)) + ")" if len(self.games_tab.updates) != 0 else ""))
|
||||
self.store = Shop(self.core)
|
||||
self.addTab(self.store, self.tr("Store (Beta)"))
|
||||
self.settings = SettingsTab(self)
|
||||
|
||||
if shared.args.debug:
|
||||
self.settings.addTab(DebugSettings(), "Debug")
|
||||
|
||||
# Space Tab
|
||||
self.addTab(QWidget(), "")
|
||||
self.setTabEnabled(disabled_tab, False)
|
||||
# Button
|
||||
self.account = QWidget()
|
||||
self.addTab(self.account, "")
|
||||
self.setTabEnabled(disabled_tab + 1, False)
|
||||
|
||||
self.mini_widget = MiniWidget()
|
||||
account_action = QWidgetAction(self)
|
||||
account_action.setDefaultWidget(self.mini_widget)
|
||||
account_button = TabButtonWidget('mdi.account-circle', 'Account')
|
||||
account_button.setMenu(QMenu())
|
||||
account_button.menu().addAction(account_action)
|
||||
self.tabBar().setTabButton(disabled_tab + 1, self.tabBar().RightSide, account_button)
|
||||
|
||||
self.addTab(self.settings, icon("fa.gear"),
|
||||
"(!)" if self.settings.about.update_available else "")
|
||||
|
||||
# Signals
|
||||
# set current index
|
||||
self.signals.set_main_tab_index.connect(self.setCurrentIndex)
|
||||
|
||||
# update dl tab text
|
||||
self.signals.update_download_tab_text.connect(self.update_dl_tab_text)
|
||||
|
||||
# Open game list on click on Games tab button
|
||||
self.tabBarClicked.connect(self.mouse_clicked)
|
||||
self.setIconSize(QSize(25, 25))
|
||||
|
||||
# shortcuts
|
||||
QShortcut("Alt+1", self).activated.connect(lambda: self.setCurrentIndex(0))
|
||||
QShortcut("Alt+2", self).activated.connect(lambda: self.setCurrentIndex(1))
|
||||
QShortcut("Alt+3", self).activated.connect(lambda: self.setCurrentIndex(2))
|
||||
QShortcut("Alt+4", self).activated.connect(lambda: self.setCurrentIndex(5))
|
||||
|
||||
def update_dl_tab_text(self):
|
||||
num_downloads = len(set([i.options.app_name for i in self.downloadTab.dl_queue] + [i for i in
|
||||
self.downloadTab.update_widgets.keys()]))
|
||||
|
||||
if num_downloads != 0:
|
||||
self.setTabText(1, f"Downloads ({num_downloads})")
|
||||
else:
|
||||
self.setTabText(1, "Downloads")
|
||||
|
||||
def mouse_clicked(self, tab_num):
|
||||
if tab_num == 0:
|
||||
self.games_tab.layout().setCurrentIndex(0)
|
||||
|
||||
if not shared.args.offline and tab_num == 3:
|
||||
self.store.load()
|
||||
|
||||
def game_imported(self, app_name: str):
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
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 ""))
|
||||
self.games_tab.update_list(app_name)
|
||||
self.games_tab.setCurrentIndex(0)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
self.tabBar().setMinimumWidth(self.width())
|
||||
super(TabWidget, self).resizeEvent(event)
|
||||
|
||||
# Remove text "sync game"
|
||||
def finished_sync(self, app_name):
|
||||
if self.core.is_installed(app_name):
|
||||
self.games_tab.widgets[app_name][0].info_text = ""
|
||||
self.games_tab.widgets[app_name][0].info_label.setText("")
|
||||
self.games_tab.widgets[app_name][1].info_label.setText("")
|
|
@ -1,156 +0,0 @@
|
|||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
||||
from PyQt5.QtWidgets import QScrollArea, QWidget, QVBoxLayout, QLabel, QPushButton, QMessageBox
|
||||
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.models.game import SaveGameStatus
|
||||
from rare import shared
|
||||
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
|
||||
|
||||
logger = getLogger("Sync Saves")
|
||||
|
||||
|
||||
class LoadThread(QThread):
|
||||
signal = pyqtSignal(list)
|
||||
|
||||
def __init__(self, core: LegendaryCore):
|
||||
super(LoadThread, self).__init__()
|
||||
self.core = core
|
||||
|
||||
def run(self) -> None:
|
||||
saves = self.core.get_save_games()
|
||||
self.signal.emit(saves)
|
||||
|
||||
|
||||
class SyncSaves(QScrollArea):
|
||||
finished = pyqtSignal(str)
|
||||
|
||||
def __init__(self):
|
||||
super(SyncSaves, self).__init__()
|
||||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
self.load_saves()
|
||||
|
||||
def load_saves(self, app_name=None, auto=False):
|
||||
self.widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(WaitingSpinner())
|
||||
layout.addWidget(QLabel("<h4>Loading Cloud Saves</h4>"))
|
||||
layout.addStretch()
|
||||
self.widget.setLayout(layout)
|
||||
self.setWidget(self.widget)
|
||||
|
||||
self.start_thread = LoadThread(self.core)
|
||||
self.start_thread.signal.connect(lambda x: self.setup_ui(x, app_name, auto))
|
||||
self.start_thread.start()
|
||||
self.igames = self.core.get_installed_list()
|
||||
|
||||
def setup_ui(self, saves: list, app_name, auto=False):
|
||||
self.start_thread.disconnect()
|
||||
self.main_layout = QVBoxLayout()
|
||||
self.title = QLabel(
|
||||
f"<h1>" + self.tr("Cloud Saves") + "</h1>\n" + self.tr("Found Saves for folowing Games"))
|
||||
self.main_layout.addWidget(self.title)
|
||||
|
||||
saves_games = []
|
||||
for i in saves:
|
||||
if not i.app_name in saves_games and self.core.is_installed(i.app_name):
|
||||
saves_games.append(i.app_name)
|
||||
if len(saves_games) == 0:
|
||||
# QMessageBox.information(self.tr("No Games Found"), self.tr("Your games don't support cloud save"))
|
||||
self.title.setText(
|
||||
f"<h1>" + self.tr("Cloud Saves") + "</h1>\n" + self.tr("Your games does not support Cloud Saves"))
|
||||
self.setWidget(self.title)
|
||||
return
|
||||
|
||||
self.sync_all_button = QPushButton(self.tr("Sync all games"))
|
||||
self.sync_all_button.clicked.connect(self.sync_all)
|
||||
self.main_layout.addWidget(self.sync_all_button)
|
||||
|
||||
latest_save = {}
|
||||
for i in sorted(saves, key=lambda a: a.datetime):
|
||||
latest_save[i.app_name] = i
|
||||
|
||||
logger.info(f'Got {len(latest_save)} remote save game(s)')
|
||||
|
||||
self.widgets = []
|
||||
for igame in self.igames:
|
||||
game = self.core.get_game(igame.app_name)
|
||||
if not game.supports_cloud_saves:
|
||||
continue
|
||||
if latest_save.get(igame.app_name):
|
||||
sync_widget = SyncWidget(igame, latest_save[igame.app_name])
|
||||
else:
|
||||
continue
|
||||
sync_widget.reload.connect(self.reload)
|
||||
self.main_layout.addWidget(sync_widget)
|
||||
self.widgets.append(sync_widget)
|
||||
|
||||
self.widget = QWidget()
|
||||
self.main_layout.addStretch(1)
|
||||
self.widget.setLayout(self.main_layout)
|
||||
self.setWidgetResizable(True)
|
||||
self.setWidget(self.widget)
|
||||
|
||||
if auto:
|
||||
self.save(app_name, True)
|
||||
|
||||
def reload(self, app_name, auto=False):
|
||||
self.finished.emit(app_name)
|
||||
self.setWidget(QWidget())
|
||||
self.load_saves(auto)
|
||||
|
||||
def sync_game(self, app_name, from_game_finish_auto=True):
|
||||
self.setWidget(QWidget())
|
||||
self.load_saves(app_name, from_game_finish_auto)
|
||||
|
||||
def save(self, app_name, from_game_finish_auto=True):
|
||||
for w in self.widgets:
|
||||
if w.igame.app_name == app_name:
|
||||
widget = w
|
||||
break
|
||||
else:
|
||||
logger.warning("An Error occurred. Game does not support cloud saves")
|
||||
return
|
||||
|
||||
if widget.res == SaveGameStatus.SAME_AGE:
|
||||
logger.info("Game is up to date")
|
||||
elif widget.res == SaveGameStatus.LOCAL_NEWER:
|
||||
widget.upload()
|
||||
elif widget.res == SaveGameStatus.REMOTE_NEWER:
|
||||
if from_game_finish_auto:
|
||||
if QMessageBox.question(self, "Really", self.tr("You finished playing game, but Remote game is newer. "
|
||||
"Do you want to download anyway? This could remove "
|
||||
"your game progress. Please check your save path or "
|
||||
"make a backup"),
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
|
||||
widget.download()
|
||||
else:
|
||||
logger.info("Cancel Download")
|
||||
self.finished.emit(app_name)
|
||||
|
||||
def sync_all(self):
|
||||
logger.info("Sync all Games")
|
||||
for w in self.widgets:
|
||||
if not w.igame.save_path:
|
||||
save_path = self.core.get_save_path(w.igame.app_name)
|
||||
if '%' in save_path or '{' in save_path:
|
||||
self.logger.info_label("Could not find save_path")
|
||||
save_path = PathInputDialog(self.tr("Found no savepath"),
|
||||
self.tr("No save path was found. Please select path or skip"))
|
||||
if save_path == "":
|
||||
continue
|
||||
else:
|
||||
w.igame.save_path = save_path
|
||||
if w.res == SaveGameStatus.SAME_AGE:
|
||||
continue
|
||||
if w.res == SaveGameStatus.REMOTE_NEWER:
|
||||
logger.info("Download")
|
||||
w.download()
|
||||
elif w.res == SaveGameStatus.LOCAL_NEWER:
|
||||
logger.info("Upload")
|
||||
w.upload()
|
|
@ -1,231 +0,0 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QSettings
|
||||
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QGroupBox, QMessageBox
|
||||
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.models.game import InstalledGame, SaveGameStatus
|
||||
from rare import shared
|
||||
from rare.components.dialogs.path_input_dialog import PathInputDialog
|
||||
|
||||
logger = getLogger("Sync")
|
||||
|
||||
|
||||
def get_raw_save_path(app_name, core):
|
||||
game = core.lgd.get_game_meta(app_name)
|
||||
save_path = game.metadata['customAttributes'].get('CloudSaveFolder', {}).get('value')
|
||||
return save_path
|
||||
|
||||
|
||||
class _UploadThread(QThread):
|
||||
signal = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, app_name, date_time, save_path, core: LegendaryCore):
|
||||
super(_UploadThread, self).__init__()
|
||||
self.core = core
|
||||
self.app_name = app_name
|
||||
self.date_time = date_time
|
||||
self.save_path = save_path
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self.core.upload_save(self.app_name, self.save_path, self.date_time)
|
||||
self.signal.emit(True)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
self.signal.emit(False)
|
||||
|
||||
|
||||
class _DownloadThread(QThread):
|
||||
signal = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, app_name, latest_save, save_path, core: LegendaryCore):
|
||||
super(_DownloadThread, self).__init__()
|
||||
self.core = core
|
||||
self.app_name = app_name
|
||||
self.latest_save = latest_save
|
||||
self.save_path = save_path
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self.core.download_saves(self.app_name, self.latest_save.manifest_name, self.save_path, clean_dir=True)
|
||||
self.signal.emit(True)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
self.signal.emit(False)
|
||||
|
||||
|
||||
class SyncWidget(QGroupBox):
|
||||
reload = pyqtSignal(str)
|
||||
|
||||
def __init__(self, igame: InstalledGame, save):
|
||||
super(SyncWidget, self).__init__(igame.title)
|
||||
self.setObjectName("group")
|
||||
self.layout = QVBoxLayout()
|
||||
self.setContentsMargins(10, 20, 10, 20)
|
||||
self.thr = None
|
||||
self.core = shared.core
|
||||
self.save = save
|
||||
self.logger = getLogger("Sync " + igame.app_name)
|
||||
self.game = self.core.get_game(igame.app_name)
|
||||
self.igame = igame
|
||||
self.has_save_path = True
|
||||
if not igame.save_path or igame.save_path is None:
|
||||
try:
|
||||
save_path = self.core.get_save_path(igame.app_name)
|
||||
except Exception as e:
|
||||
self.logger.error(e)
|
||||
return
|
||||
if '%' in save_path or '{' in save_path:
|
||||
# status = self.tr("Path not found")
|
||||
self.logger.info("Could not find save path")
|
||||
igame.save_path = ""
|
||||
|
||||
else:
|
||||
igame.save_path = save_path
|
||||
|
||||
if not igame.save_path:
|
||||
igame.save_path = os.path.expanduser(f"~/{igame.app_name}/")
|
||||
QMessageBox.warning(self, "Savepath error",
|
||||
self.tr("Please edit save path of game {} manually in Cload saves tab").format(
|
||||
igame.title))
|
||||
if igame.save_path and not os.path.exists(igame.save_path):
|
||||
os.makedirs(igame.save_path)
|
||||
self.core.lgd.set_installed_game(self.igame.app_name, self.igame)
|
||||
|
||||
self.res, (self.dt_local, dt_remote) = self.core.check_savegame_state(igame.save_path, save)
|
||||
if self.res == SaveGameStatus.NO_SAVE:
|
||||
self.logger.debug('No cloud or local savegame found.')
|
||||
return
|
||||
|
||||
# game_title = QLabel(f"<h2>{igame.title}</h2>")
|
||||
|
||||
if self.dt_local:
|
||||
local_save_date = QLabel(
|
||||
self.tr("Local Save date: ") + str(self.dt_local.strftime('%Y-%m-%d %H:%M:%S')))
|
||||
else:
|
||||
local_save_date = QLabel(self.tr("No Local Save files"))
|
||||
if dt_remote:
|
||||
cloud_save_date = QLabel(self.tr("Cloud save date: ") + str(dt_remote.strftime('%Y-%m-%d %H:%M:%S')))
|
||||
else:
|
||||
cloud_save_date = QLabel(self.tr("No Cloud saves"))
|
||||
|
||||
if self.res == SaveGameStatus.SAME_AGE:
|
||||
self.logger.debug(f'Save game for "{igame.title}" is up to date')
|
||||
status = self.tr("Game is up to date")
|
||||
self.upload_button = QPushButton(self.tr("Upload anyway"))
|
||||
self.download_button = QPushButton(self.tr("Download anyway"))
|
||||
elif self.res == SaveGameStatus.REMOTE_NEWER:
|
||||
status = self.tr("Cloud save is newer")
|
||||
self.download_button = QPushButton(self.tr("Download Cloud saves"))
|
||||
self.download_button.setObjectName("success")
|
||||
self.upload_button = QPushButton(self.tr("Upload Saves"))
|
||||
self.logger.debug(f'Cloud save for "{igame.title}" is newer:')
|
||||
self.logger.debug(f'- Cloud save date: {dt_remote.strftime("%Y-%m-%d %H:%M:%S")}')
|
||||
if self.dt_local:
|
||||
self.logger.debug(f'- Local save date: {self.dt_local.strftime("%Y-%m-%d %H:%M:%S")}')
|
||||
else:
|
||||
self.logger.debug('- Local save date: N/A')
|
||||
self.upload_button.setDisabled(True)
|
||||
self.upload_button.setToolTip("No local save")
|
||||
|
||||
elif self.res == SaveGameStatus.LOCAL_NEWER:
|
||||
status = self.tr("Local save is newer")
|
||||
self.upload_button = QPushButton(self.tr("Upload saves"))
|
||||
self.upload_button.setObjectName("success")
|
||||
self.download_button = QPushButton(self.tr("Download saves"))
|
||||
self.logger.info(f'Local save for "{igame.title}" is newer')
|
||||
if dt_remote:
|
||||
self.logger.debug(f'- Cloud save date: {dt_remote.strftime("%Y-%m-%d %H:%M:%S")}')
|
||||
else:
|
||||
self.logger.debug('- Cloud save date: N/A')
|
||||
self.download_button.setDisabled(True)
|
||||
self.logger.debug(f'- Local save date: {self.dt_local.strftime("%Y-%m-%d %H:%M:%S")}')
|
||||
else:
|
||||
self.logger.error(self.res)
|
||||
return
|
||||
|
||||
self.upload_button.clicked.connect(self.upload)
|
||||
self.download_button.clicked.connect(self.download)
|
||||
self.info_text = QLabel(status)
|
||||
# self.layout.addWidget(game_title)
|
||||
self.layout.addWidget(local_save_date)
|
||||
self.layout.addWidget(cloud_save_date)
|
||||
|
||||
save_path_layout = QHBoxLayout()
|
||||
|
||||
self.raw_path = QLabel("Raw path: " + get_raw_save_path(self.game.app_name, self.core))
|
||||
self.raw_path.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||
self.layout.addWidget(self.raw_path)
|
||||
|
||||
self.save_path_text = QLabel(igame.save_path)
|
||||
self.save_path_text.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||
self.save_path_text.setWordWrap(True)
|
||||
self.change_save_path = QPushButton(self.tr("Change path"))
|
||||
self.change_save_path.setFixedWidth(100)
|
||||
self.change_save_path.clicked.connect(self.change_path)
|
||||
save_path_layout.addWidget(self.save_path_text)
|
||||
save_path_layout.addWidget(self.change_save_path)
|
||||
self.layout.addLayout(save_path_layout)
|
||||
self.layout.addWidget(self.info_text)
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addWidget(self.upload_button)
|
||||
button_layout.addWidget(self.download_button)
|
||||
self.layout.addLayout(button_layout)
|
||||
self.layout.addStretch(1)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
if self.res == SaveGameStatus.REMOTE_NEWER:
|
||||
settings = QSettings()
|
||||
if settings.value(f"{igame.app_name}/auto_sync_cloud", False, bool):
|
||||
self.download()
|
||||
|
||||
def change_path(self):
|
||||
path = PathInputDialog("Select directory", "Select savepath. Warning: Do not change if you are not sure",
|
||||
self.igame.save_path).get_path()
|
||||
if path != "":
|
||||
self.igame.save_path = path
|
||||
self.core.lgd.set_installed_game(self.igame.app_name, self.igame)
|
||||
self.save_path_text.setText(self.igame.save_path)
|
||||
self.reload.emit(self.game.app_name)
|
||||
|
||||
def upload(self):
|
||||
self.logger.info("Uploading Saves for game " + self.igame.title)
|
||||
self.info_text.setText(self.tr("Uploading..."))
|
||||
self.upload_button.setDisabled(True)
|
||||
self.download_button.setDisabled(True)
|
||||
self.thr = _UploadThread(self.igame.app_name, self.dt_local, self.igame.save_path, self.core)
|
||||
self.thr.signal.connect(self.uploaded)
|
||||
self.thr.start()
|
||||
|
||||
def uploaded(self, success: bool):
|
||||
if success:
|
||||
self.info_text.setText(self.tr("Upload finished"))
|
||||
|
||||
else:
|
||||
self.info_text.setText(self.tr("Upload failed"))
|
||||
self.upload_button.setDisabled(False)
|
||||
self.reload.emit(self.game.app_name)
|
||||
|
||||
def download(self):
|
||||
if not os.path.exists(self.igame.save_path):
|
||||
os.makedirs(self.igame.save_path)
|
||||
self.upload_button.setDisabled(True)
|
||||
self.download_button.setDisabled(True)
|
||||
self.logger.info("Downloading Saves for game " + self.igame.title)
|
||||
self.info_text.setText(self.tr("Downloading..."))
|
||||
self.thr = _DownloadThread(self.igame.app_name, self.save, self.igame.save_path, self.core)
|
||||
self.thr.signal.connect(self.downloaded)
|
||||
self.thr.start()
|
||||
|
||||
def downloaded(self, success: bool):
|
||||
if success:
|
||||
self.info_text.setText(self.tr("Download finished"))
|
||||
self.upload_button.setDisabled(True)
|
||||
self.download_button.setDisabled(True)
|
||||
self.download_button.setStyleSheet("QPushButton{background-color: black}")
|
||||
self.reload.emit(self.game.app_name)
|
||||
else:
|
||||
self.info_text.setText("Error while downloading save")
|
||||
self.download_button.setStyleSheet("QPushButton{background-color: black}")
|
|
@ -103,6 +103,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.signals.installation_finished.connect(lambda x: self.installing_widget.setVisible(False))
|
||||
self.signals.uninstall_game.connect(self.uninstall_game)
|
||||
|
||||
self.game_list_scroll_area.horizontalScrollBar().setDisabled(True)
|
||||
|
||||
def installation_started(self, app_name: str):
|
||||
game = self.core.get_game(app_name, False)
|
||||
if game.is_dlc:
|
||||
|
@ -115,7 +117,9 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
i_widget, l_widget = self.widgets[igame.app_name]
|
||||
i_widget.igame = igame
|
||||
l_widget.igame = igame
|
||||
i_widget.info_text = ""
|
||||
|
||||
i_widget.leaveEvent(None)
|
||||
l_widget.update_text()
|
||||
|
||||
def uninstall_game(self, game: Game):
|
||||
infos = UninstallDialog(game).get_information()
|
||||
|
@ -269,11 +273,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
igame = self.core.get_installed_game(app_name)
|
||||
for w in widgets:
|
||||
w.igame = igame
|
||||
w.update_available = self.core.get_asset(w.game.app_name,
|
||||
True).build_version != igame.version
|
||||
widgets[0].info_label.setText("")
|
||||
widgets[0].info_text = ""
|
||||
|
||||
w.update_available = self.core.get_asset(w.game.app_name, True).build_version != igame.version
|
||||
widgets[0].leaveEvent(None)
|
||||
# new installed
|
||||
elif self.core.is_installed(app_name) and isinstance(widgets[0], BaseUninstalledWidget):
|
||||
logger.debug("Update Gamelist: New installed " + app_name)
|
||||
|
@ -405,3 +406,5 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
else:
|
||||
self.scroll_widget.layout().replaceWidget(self.icon_view, self.list_view)
|
||||
self.icon_view.setParent(None)
|
||||
|
||||
self.game_list_scroll_area.verticalScrollBar().setValue(0)
|
||||
|
|
|
@ -123,9 +123,6 @@ class CloudSaveUtils(QObject):
|
|||
igame = self.core.get_installed_game(app_name)
|
||||
res, (dt_local, dt_remote) = self.core.check_savegame_state(igame.save_path, self.latest_saves.get(app_name))
|
||||
|
||||
# maybe i will add this
|
||||
# if res == SaveGameStatus.REMOTE_NEWER:
|
||||
# self.download_saves()
|
||||
if res != SaveGameStatus.SAME_AGE:
|
||||
newer = None
|
||||
if res == SaveGameStatus.REMOTE_NEWER:
|
||||
|
|
|
@ -34,7 +34,7 @@ class RunningGameModel:
|
|||
|
||||
class GameUtils(QObject):
|
||||
running_games = dict()
|
||||
finished = pyqtSignal(str)
|
||||
finished = pyqtSignal(str, str)
|
||||
cloud_save_finished = pyqtSignal(str)
|
||||
launch_queue = dict()
|
||||
|
||||
|
@ -78,12 +78,15 @@ class GameUtils(QObject):
|
|||
else:
|
||||
if not game:
|
||||
logger.error("Game not found")
|
||||
self.finished.emit(app_name, self.tr("Game not found in available games"))
|
||||
return
|
||||
if game.is_dlc:
|
||||
logger.error("Game is dlc")
|
||||
self.finished.emit(app_name, self.tr("Game is a DLC. Please launch base game instead"))
|
||||
return
|
||||
if not os.path.exists(igame.install_path):
|
||||
logger.error("Game doesn't exist")
|
||||
self.finished.emit(app_name, self.tr("Game files of {} do not exist. Please install game"))
|
||||
return
|
||||
|
||||
process = GameProcess(app_name)
|
||||
|
@ -96,11 +99,11 @@ class GameUtils(QObject):
|
|||
try:
|
||||
latest = self.core.get_asset(app_name, update=True)
|
||||
except ValueError:
|
||||
print("Metadata doesn't exist")
|
||||
return None
|
||||
self.finished.emit(app_name, self.tr("Metadata doesn't exist"))
|
||||
return
|
||||
if latest.build_version != igame.version:
|
||||
print("Please update game")
|
||||
return None
|
||||
self.finished.emit(app_name, self.tr("Please update game"))
|
||||
return
|
||||
|
||||
params: LaunchParameters = self.core.get_launch_parameters(app_name=app_name, offline=offline,
|
||||
wine_bin=wine_bin, wine_pfx=wine_pfx)
|
||||
|
@ -130,6 +133,7 @@ class GameUtils(QObject):
|
|||
logger.info("Launch Origin Game: ")
|
||||
if platform.system() == "Windows":
|
||||
webbrowser.open(origin_uri)
|
||||
self.finished.emit(app_name, "")
|
||||
return
|
||||
wine_pfx = self.core.lgd.config.get(self.game.app_name, 'wine_prefix',
|
||||
fallback=os.path.expanduser("~/.wine"))
|
||||
|
@ -137,9 +141,10 @@ class GameUtils(QObject):
|
|||
wine_bin = self.core.lgd.config.get(self.game.app_name, 'wine_executable', fallback="/usr/bin/wine")
|
||||
env = self.core.get_app_environment(self.game.app_name, wine_pfx=wine_pfx)
|
||||
|
||||
if not wine_bin or not env.get('WINEPREFIX'):
|
||||
if not wine_bin or not env.get('WINEPREFIX') and not os.path.exists("/usr/bin/wine"):
|
||||
logger.error(f'In order to launch Origin correctly you must specify the wine binary and prefix '
|
||||
f'to use in the configuration file or command line. See the README for details.')
|
||||
self.finished.emit(app_name, self.tr("No wine executable selected. Please set it in settings"))
|
||||
return
|
||||
|
||||
environment = QProcessEnvironment()
|
||||
|
@ -175,7 +180,7 @@ class GameUtils(QObject):
|
|||
webbrowser.open("https://www.dm.origin.com/download")
|
||||
|
||||
self.running_games.pop(app_name)
|
||||
self.finished.emit(app_name)
|
||||
self.finished.emit(app_name, "")
|
||||
|
||||
if QSettings().value("show_console", False, bool):
|
||||
self.console.log(f"Game exited with code: {exit_code}")
|
||||
|
|
|
@ -26,13 +26,29 @@ class BaseInstalledWidget(QGroupBox):
|
|||
self.core = shared.core
|
||||
self.game_utils = game_utils
|
||||
self.game_utils.cloud_save_finished.connect(self.sync_finished)
|
||||
self.sync_cloud_saves = False
|
||||
self.syncing_cloud_saves = False
|
||||
|
||||
self.texts = {
|
||||
"needs_verification": self.tr("Please verify game before playing"),
|
||||
"hover": {
|
||||
"update_available": self.tr("Start game without version check"),
|
||||
"launch": self.tr("Launch Game"),
|
||||
"launch_origin": self.tr("Launch/Link"),
|
||||
"running": self.tr("Game running")
|
||||
},
|
||||
"default": {
|
||||
"running": self.tr("Game running"),
|
||||
"syncing": self.tr("Syncing cloud saves"),
|
||||
"update_available": self.tr("Update available")
|
||||
}
|
||||
}
|
||||
|
||||
self.game = self.core.get_game(app_name)
|
||||
if self.game.third_party_store != "Origin":
|
||||
self.igame = self.core.get_installed_game(app_name)
|
||||
self.is_origin = False
|
||||
else:
|
||||
self.igame = None
|
||||
self.is_origin = True
|
||||
|
||||
self.image = QLabel()
|
||||
|
@ -129,13 +145,19 @@ class BaseInstalledWidget(QGroupBox):
|
|||
self.create_start_menu.setText(self.tr("Create Start menu link"))
|
||||
|
||||
def launch(self, offline=False, skip_version_check=False):
|
||||
if self.game.supports_cloud_saves:
|
||||
self.sync_cloud_saves = True
|
||||
self.game_utils.launch_game(self.game.app_name, offline=offline, skip_update_check=skip_version_check)
|
||||
if not self.game_running:
|
||||
if self.game.supports_cloud_saves:
|
||||
self.syncing_cloud_saves = True
|
||||
self.game_utils.prepare_launch(self.game.app_name, offline, skip_version_check)
|
||||
|
||||
def sync_finished(self, app_name):
|
||||
if app_name == self.game.app_name:
|
||||
self.sync_cloud_saves = False
|
||||
self.syncing_cloud_saves = False
|
||||
|
||||
def sync_game(self):
|
||||
self.game_utils.cloud_save_utils.sync_before_launch_game(self.game.app_name)
|
||||
if self.game_utils.cloud_save_utils.sync_before_launch_game(self.game.app_name):
|
||||
self.syncing_cloud_saves = True
|
||||
|
||||
def game_finished(self, app_name, error):
|
||||
if error:
|
||||
QMessageBox.warning(self, "Error", error)
|
||||
|
|
|
@ -21,12 +21,9 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
self.setContextMenuPolicy(Qt.ActionsContextMenu)
|
||||
self.layout = QVBoxLayout()
|
||||
self.core = shared.core
|
||||
self.running = False
|
||||
self.info_text = ""
|
||||
|
||||
if self.update_available:
|
||||
logger.info("Update available for game: " + self.game.app_name)
|
||||
self.info_text = self.tr("Update available")
|
||||
|
||||
self.layout.addWidget(self.image)
|
||||
|
||||
|
@ -45,9 +42,8 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
self.menu_btn.setIcon(icon("ei.info-circle"))
|
||||
# self.menu_btn.setObjectName("installed_menu_button")
|
||||
self.menu_btn.setIconSize(QSize(18, 18))
|
||||
self.menu_btn.enterEvent = lambda x: self.info_label.setText("Information")
|
||||
self.menu_btn.leaveEvent = lambda x: self.info_label.setText(
|
||||
"Please update Game") if self.update_available else self.info_label.setText("Start Game")
|
||||
self.menu_btn.enterEvent = lambda x: self.info_label.setText(self.tr("Information"))
|
||||
self.menu_btn.leaveEvent = lambda x: self.enterEvent(None)
|
||||
# remove Border
|
||||
|
||||
self.menu_btn.setObjectName("menu_button")
|
||||
|
@ -58,33 +54,37 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
minilayout.addStretch(1)
|
||||
self.layout.addLayout(minilayout)
|
||||
|
||||
self.info_label = QLabel(self.info_text)
|
||||
self.info_label = QLabel("")
|
||||
self.leaveEvent(None)
|
||||
self.info_label.setAutoFillBackground(False)
|
||||
self.info_label.setObjectName("info_label")
|
||||
self.layout.addWidget(self.info_label)
|
||||
|
||||
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.info_label.setText(self.texts["needs_verification"])
|
||||
|
||||
self.setLayout(self.layout)
|
||||
self.setFixedWidth(self.sizeHint().width())
|
||||
|
||||
def enterEvent(self, a0: QEvent) -> None:
|
||||
def enterEvent(self, a0: QEvent = None) -> None:
|
||||
if self.game_running:
|
||||
self.info_label.setText(self.tr("Game running"))
|
||||
self.info_label.setText(self.texts["hover"]["running"])
|
||||
elif not self.is_origin and self.igame.needs_verification:
|
||||
self.info_label.setText(self.tr("Please verify game before playing"))
|
||||
self.info_label.setText(self.texts["hover"]["needs_verification"])
|
||||
elif self.update_available:
|
||||
self.info_label.setText(self.tr("Start game without version check"))
|
||||
self.info_label.setText(self.texts["hover"]["update_available"])
|
||||
else:
|
||||
self.info_label.setText(self.tr("Start Game") if not self.is_origin else self.tr("Launch/Link"))
|
||||
self.info_label.setText(self.texts["hover"]["launch" if not self.is_origin else "launch_origin"])
|
||||
|
||||
def leaveEvent(self, a0: QEvent) -> None:
|
||||
if self.running:
|
||||
self.info_label.setText(self.tr("Game running"))
|
||||
def leaveEvent(self, a0: QEvent = None) -> None:
|
||||
if self.game_running:
|
||||
self.info_label.setText(self.texts["default"]["running"])
|
||||
elif self.syncing_cloud_saves:
|
||||
self.info_label.setText(self.texts["default"]["syncing"])
|
||||
elif self.update_available:
|
||||
self.info_label.setText(self.texts["default"]["update_available"])
|
||||
else:
|
||||
self.info_label.setText(self.info_text)
|
||||
self.info_label.setText("")
|
||||
|
||||
def mousePressEvent(self, e: QMouseEvent):
|
||||
# left button
|
||||
|
@ -100,9 +100,10 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
elif e.button() == 2:
|
||||
pass # self.showMenu(e)
|
||||
|
||||
def game_finished(self, app_name):
|
||||
def game_finished(self, app_name, error):
|
||||
if app_name != self.game.app_name:
|
||||
return
|
||||
|
||||
self.info_text = ""
|
||||
self.info_label.setText("")
|
||||
super().game_finished(app_name, error)
|
||||
|
||||
self.leaveEvent(None)
|
||||
|
|
|
@ -32,17 +32,22 @@ class InstalledListWidget(BaseInstalledWidget):
|
|||
self.layout.addWidget(self.image)
|
||||
|
||||
play_icon = icon("ei.play")
|
||||
self.title_widget = QLabel(f"<h1>{self.game.app_title}</h1>")
|
||||
self.title_label = QLabel(f"<h1>{self.game.app_title}</h1>")
|
||||
self.title_label.setWordWrap(True)
|
||||
self.childLayout.addWidget(self.title_label)
|
||||
self.app_name_label = QLabel(self.game.app_name)
|
||||
self.launch_button = QPushButton(play_icon, self.tr("Launch") if not self.is_origin else self.tr("Link/Play"))
|
||||
self.launch_button.setObjectName("launch_game_button")
|
||||
self.launch_button.setFixedWidth(120)
|
||||
self.launch_button.setFixedWidth(150)
|
||||
|
||||
self.info = QPushButton("Info")
|
||||
self.info.clicked.connect(lambda: self.show_info.emit(self.game))
|
||||
self.info.setFixedWidth(80)
|
||||
|
||||
self.childLayout.addWidget(self.title_widget)
|
||||
self.info_label = QLabel("")
|
||||
self.childLayout.addWidget(self.info_label)
|
||||
self.update_text()
|
||||
|
||||
self.launch_button.clicked.connect(self.launch)
|
||||
|
||||
self.childLayout.addWidget(self.launch_button)
|
||||
|
@ -57,15 +62,22 @@ class InstalledListWidget(BaseInstalledWidget):
|
|||
self.childLayout.addWidget(self.version_label)
|
||||
self.childLayout.addWidget(self.size_label)
|
||||
|
||||
self.info_label = QLabel("")
|
||||
self.childLayout.addWidget(self.info_label)
|
||||
# self.childLayout.addWidget(QPushButton("Settings"))
|
||||
# self.childLayout.addWidget(QPushButton("Uninstall"))
|
||||
self.childLayout.addStretch(1)
|
||||
self.layout.addLayout(self.childLayout)
|
||||
self.layout.addStretch(1)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
def launch(self):
|
||||
if not self.game_running:
|
||||
super(InstalledListWidget, self).launch(skip_version_check=self.update_available)
|
||||
self.game_utils.cloud_save_finished.connect(self.sync_finished)
|
||||
|
||||
self.leaveEvent = self.update_text
|
||||
self.enterEvent = self.update_text
|
||||
|
||||
def update_text(self, e=None):
|
||||
if self.update_available:
|
||||
self.info_label.setText(self.texts["default"]["update_available"])
|
||||
elif self.igame and self.igame.needs_verification:
|
||||
self.info_label.setText(self.texts["needs_verification"])
|
||||
elif self.syncing_cloud_saves:
|
||||
self.info_label.setText(self.texts["default"]["syncing"])
|
||||
else:
|
||||
self.info_label.setText("")
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
from PyQt5.QtCore import QSize, pyqtSignal
|
||||
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut
|
||||
from qtawesome import icon
|
||||
|
||||
from rare import shared
|
||||
from rare.components.tabs.account import MiniWidget
|
||||
from rare.components.tabs.downloads import DownloadTab
|
||||
from rare.components.tabs.games import GamesTab
|
||||
from rare.components.tabs.settings import SettingsTab
|
||||
from rare.components.tabs.settings.debug import DebugSettings
|
||||
from rare.components.tabs.shop import Shop
|
||||
from rare.components.tabs.tab_utils import TabBar, TabButtonWidget
|
||||
|
||||
|
||||
class TabWidget(QTabWidget):
|
||||
delete_presence = pyqtSignal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(TabWidget, self).__init__(parent=parent)
|
||||
disabled_tab = 3 if not shared.args.offline else 1
|
||||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
self.setTabBar(TabBar(disabled_tab))
|
||||
# Generate Tabs
|
||||
self.games_tab = GamesTab()
|
||||
self.addTab(self.games_tab, self.tr("Games"))
|
||||
if not shared.args.offline:
|
||||
# updates = self.games_tab.default_widget.game_list.updates
|
||||
self.downloadTab = DownloadTab(self.games_tab.updates)
|
||||
self.addTab(self.downloadTab, "Downloads" + (
|
||||
" (" + str(len(self.games_tab.updates)) + ")" if len(self.games_tab.updates) != 0 else ""))
|
||||
self.store = Shop(self.core)
|
||||
self.addTab(self.store, self.tr("Store (Beta)"))
|
||||
self.settings = SettingsTab(self)
|
||||
|
||||
if shared.args.debug:
|
||||
self.settings.addTab(DebugSettings(), "Debug")
|
||||
|
||||
# Space Tab
|
||||
self.addTab(QWidget(), "")
|
||||
self.setTabEnabled(disabled_tab, False)
|
||||
# Button
|
||||
self.account = QWidget()
|
||||
self.addTab(self.account, "")
|
||||
self.setTabEnabled(disabled_tab + 1, False)
|
||||
|
||||
self.mini_widget = MiniWidget()
|
||||
account_action = QWidgetAction(self)
|
||||
account_action.setDefaultWidget(self.mini_widget)
|
||||
account_button = TabButtonWidget('mdi.account-circle', 'Account')
|
||||
account_button.setMenu(QMenu())
|
||||
account_button.menu().addAction(account_action)
|
||||
self.tabBar().setTabButton(disabled_tab + 1, self.tabBar().RightSide, account_button)
|
||||
|
||||
self.addTab(self.settings, icon("fa.gear"),
|
||||
"(!)" if self.settings.about.update_available else "")
|
||||
|
||||
# Signals
|
||||
# set current index
|
||||
self.signals.set_main_tab_index.connect(self.setCurrentIndex)
|
||||
|
||||
# update dl tab text
|
||||
self.signals.update_download_tab_text.connect(self.update_dl_tab_text)
|
||||
|
||||
# Open game list on click on Games tab button
|
||||
self.tabBarClicked.connect(self.mouse_clicked)
|
||||
self.setIconSize(QSize(25, 25))
|
||||
|
||||
# shortcuts
|
||||
QShortcut("Alt+1", self).activated.connect(lambda: self.setCurrentIndex(0))
|
||||
QShortcut("Alt+2", self).activated.connect(lambda: self.setCurrentIndex(1))
|
||||
QShortcut("Alt+3", self).activated.connect(lambda: self.setCurrentIndex(2))
|
||||
QShortcut("Alt+4", self).activated.connect(lambda: self.setCurrentIndex(5))
|
||||
|
||||
def update_dl_tab_text(self):
|
||||
num_downloads = len(set([i.options.app_name for i in self.downloadTab.dl_queue] + [i for i in
|
||||
self.downloadTab.update_widgets.keys()]))
|
||||
|
||||
if num_downloads != 0:
|
||||
self.setTabText(1, f"Downloads ({num_downloads})")
|
||||
else:
|
||||
self.setTabText(1, "Downloads")
|
||||
|
||||
def mouse_clicked(self, tab_num):
|
||||
if tab_num == 0:
|
||||
self.games_tab.layout().setCurrentIndex(0)
|
||||
|
||||
if not shared.args.offline and tab_num == 3:
|
||||
self.store.load()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
self.tabBar().setMinimumWidth(self.width())
|
||||
super(TabWidget, self).resizeEvent(event)
|
||||
|
||||
# Remove text "sync game"
|
||||
def finished_sync(self, app_name):
|
||||
if self.core.is_installed(app_name):
|
||||
self.games_tab.widgets[app_name][0].info_text = ""
|
||||
self.games_tab.widgets[app_name][0].info_label.setText("")
|
||||
self.games_tab.widgets[app_name][1].info_label.setText("")
|
Loading…
Reference in a new issue