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("
Loading Cloud Saves
"))
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"" + self.tr("Cloud Saves") + "
\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"" + self.tr("Cloud Saves") + "
\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()