from logging import getLogger
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtWidgets import *
from legendary.core import LegendaryCore
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
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, core: LegendaryCore, parent):
super(SyncSaves, self).__init__(parent=parent)
self.core = core
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], self.core)
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()