1
0
Fork 0
mirror of synced 2024-06-26 10:11:19 +12:00

Move cloud save ui to a new tab in game_info

Signed-off-by: loathingKernel <142770+loathingKernel@users.noreply.github.com>
This commit is contained in:
lennard 2023-02-04 17:43:52 +02:00 committed by loathingKernel
parent 92346e11d0
commit a66600efa3
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
13 changed files with 535 additions and 152 deletions

View file

@ -11,6 +11,7 @@ from rare.widgets.side_tab import SideTabWidget, SideTabContents
from .game_dlc import GameDlc
from .game_info import GameInfo
from .game_settings import GameSettings
from .cloud_saves import CloudSaves
class GameInfoTabs(SideTabWidget):
@ -26,6 +27,9 @@ class GameInfoTabs(SideTabWidget):
self.settings_tab = GameSettings(self)
self.settings_index = self.addTab(self.settings_tab, self.tr("Settings"))
self.cloud_saves_tab = CloudSaves(self)
self.cloud_saves_index = self.addTab(self.cloud_saves_tab, self.tr("Cloud Saves"))
self.dlc_tab = GameDlc(self)
self.dlc_index = self.addTab(self.dlc_tab, self.tr("Downloadable Content"))
@ -47,6 +51,9 @@ class GameInfoTabs(SideTabWidget):
self.dlc_tab.update_dlcs(rgame)
self.dlc_tab.setEnabled(rgame.is_installed and bool(rgame.owned_dlcs))
self.cloud_saves_tab.update_game(rgame)
# self.cloud_saves_tab.setEnabled(rgame.game.supports_cloud_saves or rgame.game.supports_mac_cloud_saves)
if self.args.debug:
self.game_meta_view.update_game(rgame, rgame.game)
self.igame_meta_view.update_game(rgame, rgame.igame)

View file

@ -0,0 +1,177 @@
import os
from logging import getLogger
from PyQt5.QtCore import QThreadPool, QSettings
from PyQt5.QtWidgets import (
QWidget,
QFileDialog,
QLabel,
QPushButton,
QSizePolicy,
QMessageBox,
QGroupBox,
QVBoxLayout,
QSpacerItem,
)
from rare.models.game import RareGame
from rare.shared import LegendaryCoreSingleton
from rare.shared.workers.wine_resolver import WineResolver
from rare.ui.components.tabs.games.game_info.cloud_widget import Ui_CloudWidget
from rare.ui.components.tabs.games.game_info.sync_widget import Ui_SyncWidget
from rare.utils.misc import icon
from rare.widgets.indicator_edit import PathEdit, IndicatorReasonsCommon
from rare.widgets.side_tab import SideTabContents
logger = getLogger("CloudWidget")
class CloudSaves(QWidget, SideTabContents):
def __init__(self, parent=None):
super(CloudSaves, self).__init__(parent=parent)
self.sync_widget = QWidget(self)
self.sync_ui = Ui_SyncWidget()
self.sync_ui.setupUi(self.sync_widget)
self.change = True
self.info_label = QLabel(self.tr("<b>This game doesn't support cloud saves</b>"))
self.core = LegendaryCoreSingleton()
self.settings = QSettings()
self.sync_ui.icon_local.setPixmap(icon("mdi.harddisk", "fa.desktop").pixmap(128, 128))
self.sync_ui.icon_remote.setPixmap(icon("mdi.cloud-outline", "ei.cloud").pixmap(128, 128))
self.sync_ui.upload_button.clicked.connect(self.upload)
self.sync_ui.download_button.clicked.connect(self.download)
self.rgame: RareGame = None
self.cloud_widget = QGroupBox(self)
self.cloud_ui = Ui_CloudWidget()
self.cloud_ui.setupUi(self.cloud_widget)
self.sync_widget.layout().addWidget(self.cloud_widget)
self.cloud_save_path_edit = PathEdit(
"",
file_type=QFileDialog.DirectoryOnly,
placeholder=self.tr("Cloud save path"),
edit_func=lambda text: (True, text, None)
if os.path.exists(text)
else (False, text, IndicatorReasonsCommon.DIR_NOT_EXISTS),
save_func=self.save_save_path,
)
self.cloud_ui.cloud_layout.addRow(QLabel(self.tr("Save path")), self.cloud_save_path_edit)
self.compute_save_path_button = QPushButton(icon("fa.magic"), self.tr("Auto compute save path"))
self.compute_save_path_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
self.compute_save_path_button.clicked.connect(self.compute_save_path)
self.cloud_ui.cloud_layout.addRow(None, self.compute_save_path_button)
self.cloud_ui.cloud_sync.stateChanged.connect(
lambda: self.settings.setValue(
f"{self.rgame.app_name}/auto_sync_cloud", self.cloud_ui.cloud_sync.isChecked()
)
)
layout = QVBoxLayout(self)
layout.addWidget(self.sync_widget)
layout.addWidget(self.cloud_widget)
layout.addWidget(self.info_label)
layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding))
def upload(self):
pass
def download(self):
pass
def compute_save_path(self):
if self.rgame.is_installed and self.rgame.game.supports_cloud_saves:
try:
new_path = self.core.get_save_path(self.rgame.app_name)
if not os.path.exists(new_path):
raise ValueError(f'Path "{new_path}" does not exist.')
except Exception as e:
logger.warning(str(e))
resolver = WineResolver(self.core, self.rgame.raw_save_path, self.rgame.app_name)
if not resolver.wine_env.get("WINEPREFIX"):
self.cloud_save_path_edit.setText("")
QMessageBox.warning(self, "Warning", "No wine prefix selected. Please set it in settings")
return
self.cloud_save_path_edit.setText(self.tr("Loading"))
self.cloud_save_path_edit.setDisabled(True)
self.compute_save_path_button.setDisabled(True)
app_name = self.rgame.app_name[:]
resolver.signals.result_ready.connect(lambda x: self.wine_resolver_finished(x, app_name))
QThreadPool.globalInstance().start(resolver)
return
else:
self.cloud_save_path_edit.setText(new_path)
def wine_resolver_finished(self, path, app_name):
logger.info(f"Wine resolver finished for {app_name}. Computed save path: {path}")
if app_name == self.rgame.app_name:
self.cloud_save_path_edit.setDisabled(False)
self.compute_save_path_button.setDisabled(False)
if path and not os.path.exists(path):
try:
os.makedirs(path)
except PermissionError:
self.cloud_save_path_edit.setText("")
QMessageBox.warning(
None,
"Error",
self.tr("Error while launching {}. No permission to create {}").format(
self.rgame.title, path
),
)
return
if not path:
self.cloud_save_path_edit.setText("")
return
self.cloud_save_path_edit.setText(path)
elif path:
igame = self.core.get_installed_game(app_name)
igame.save_path = path
self.core.lgd.set_installed_game(app_name, igame)
def save_save_path(self, text):
if self.rgame.game.supports_cloud_saves and self.change:
self.rgame.igame.save_path = text
self.core.lgd.set_installed_game(self.rgame.app_name, self.rgame.igame)
def update_game(self, rgame: RareGame):
self.rgame = rgame
self.set_title.emit(rgame.title)
supports_saves = rgame.game.supports_cloud_saves or rgame.game.supports_mac_cloud_saves
self.sync_widget.setEnabled(bool(supports_saves and rgame.save_path))
self.cloud_widget.setEnabled(supports_saves)
self.info_label.setVisible(not supports_saves)
if not supports_saves:
return
self.change = False
newer = "remote"
new_text = self.tr(" (newer)")
if newer == "remote":
self.sync_ui.cloud_gb.setTitle(self.sync_ui.cloud_gb.title() + new_text)
elif newer == "local":
self.sync_ui.local_gb.setTitle(self.sync_ui.local_gb.title() + new_text)
sync_cloud = self.settings.value(f"{self.rgame.app_name}/auto_sync_cloud", True, bool)
self.cloud_ui.cloud_sync.setChecked(sync_cloud)
if hasattr(self.rgame.igame, "save_path") and self.rgame.igame.save_path:
self.cloud_save_path_edit.setText(self.rgame.igame.save_path)
res, (dt_local, dt_remote) = self.core.check_savegame_state(
rgame.igame.save_path, self.rgame.latest_save
)
self.sync_ui.date_info_local.setText(dt_local.strftime("%A, %d. %B %Y %X") if dt_local else "None")
self.sync_ui.date_info_remote.setText(dt_remote.strftime("%A, %d. %B %Y %X") if dt_remote else "None")
else:
self.cloud_save_path_edit.setText("")
self.change = True

View file

@ -1,19 +1,15 @@
import os
import platform
from logging import getLogger
from PyQt5.QtCore import Qt, QThreadPool
from PyQt5.QtWidgets import QSizePolicy, QPushButton, QLabel, QFileDialog, QMessageBox
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLabel
from legendary.models.game import Game, InstalledGame
from rare.components.tabs.settings import DefaultGameSettings
from rare.components.tabs.settings.widgets.pre_launch import PreLaunchSettings
from rare.models.game import RareGame
from rare.shared.workers.wine_resolver import WineResolver
from rare.utils import config_helper
from rare.widgets.indicator_edit import PathEdit, IndicatorReasonsCommon
from rare.widgets.side_tab import SideTabContents
from rare.utils.misc import icon, get_raw_save_path
logger = getLogger("GameSettings")
@ -29,88 +25,14 @@ class GameSettings(DefaultGameSettings, SideTabContents):
QLabel(self.tr("Pre-launch command")), self.pre_launch_settings
)
self.cloud_save_path_edit = PathEdit(
"",
file_type=QFileDialog.DirectoryOnly,
placeholder=self.tr("Cloud save path"),
edit_func=lambda text: (True, text, IndicatorReasonsCommon.VALID)
if os.path.exists(text)
else (False, text, IndicatorReasonsCommon.DIR_NOT_EXISTS),
save_func=self.save_save_path,
)
self.cloud_layout.addRow(QLabel(self.tr("Save path")), self.cloud_save_path_edit)
self.compute_save_path_button = QPushButton(icon("fa.magic"), self.tr("Auto compute save path"))
self.compute_save_path_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
self.compute_save_path_button.clicked.connect(self.compute_save_path)
self.cloud_layout.addRow(None, self.compute_save_path_button)
self.offline.currentIndexChanged.connect(lambda x: self.update_combobox(x, "offline"))
self.skip_update.currentIndexChanged.connect(lambda x: self.update_combobox(x, "skip_update_check"))
self.cloud_sync.stateChanged.connect(
lambda: self.settings.setValue(
f"{self.game.app_name}/auto_sync_cloud", self.cloud_sync.isChecked()
)
)
self.override_exe_edit.textChanged.connect(lambda text: self.save_line_edit("override_exe", text))
self.launch_params.textChanged.connect(lambda x: self.save_line_edit("start_params", x))
self.game_settings_layout.setAlignment(Qt.AlignTop)
def compute_save_path(self):
if self.core.is_installed(self.game.app_name) and self.game.supports_cloud_saves:
try:
new_path = self.core.get_save_path(self.game.app_name)
except Exception as e:
logger.warning(str(e))
resolver = WineResolver(self.core, get_raw_save_path(self.game), self.game.app_name)
if not resolver.wine_env.get("WINEPREFIX"):
self.cloud_save_path_edit.setText("")
QMessageBox.warning(self, "Warning", "No wine prefix selected. Please set it in settings")
return
self.cloud_save_path_edit.setText(self.tr("Loading"))
self.cloud_save_path_edit.setDisabled(True)
self.compute_save_path_button.setDisabled(True)
app_name = self.game.app_name[:]
resolver.signals.result_ready.connect(lambda x: self.wine_resolver_finished(x, app_name))
QThreadPool.globalInstance().start(resolver)
return
else:
self.cloud_save_path_edit.setText(new_path)
def wine_resolver_finished(self, path, app_name):
logger.info(f"Wine resolver finished for {app_name}. Computed save path: {path}")
if app_name == self.game.app_name:
self.cloud_save_path_edit.setDisabled(False)
self.compute_save_path_button.setDisabled(False)
if path and not os.path.exists(path):
try:
os.makedirs(path)
except PermissionError:
self.cloud_save_path_edit.setText("")
QMessageBox.warning(
None,
"Error",
self.tr("Error while launching {}. No permission to create {}").format(
self.game.app_title, path
),
)
return
if not path:
self.cloud_save_path_edit.setText("")
return
self.cloud_save_path_edit.setText(path)
elif path:
igame = self.core.get_installed_game(app_name)
igame.save_path = path
self.core.lgd.set_installed_game(app_name, igame)
def save_save_path(self, text):
if self.game.supports_cloud_saves and self.change:
self.igame.save_path = text
self.core.lgd.set_installed_game(self.igame.app_name, self.igame)
def save_line_edit(self, option, value):
if value:
@ -119,10 +41,6 @@ class GameSettings(DefaultGameSettings, SideTabContents):
config_helper.remove_option(self.game.app_name, option)
config_helper.save_config()
if option == "wine_prefix":
if self.game.supports_cloud_saves:
self.compute_save_path()
def update_combobox(self, i, option):
if self.change:
# remove section
@ -173,18 +91,6 @@ class GameSettings(DefaultGameSettings, SideTabContents):
else:
self.linux_settings_widget.setVisible(True)
if not self.game.supports_cloud_saves:
self.cloud_group.setEnabled(False)
self.cloud_save_path_edit.setText("")
else:
self.cloud_group.setEnabled(True)
sync_cloud = self.settings.value(f"{self.game.app_name}/auto_sync_cloud", True, bool)
self.cloud_sync.setChecked(sync_cloud)
if hasattr(self.igame, "save_path") and self.igame.save_path:
self.cloud_save_path_edit.setText(self.igame.save_path)
else:
self.cloud_save_path_edit.setText("")
self.launch_params.setText(self.core.lgd.config.get(self.game.app_name, "start_params", fallback=""))
self.override_exe_edit.setText(
self.core.lgd.config.get(self.game.app_name, "override_exe", fallback="")

View file

@ -70,7 +70,6 @@ class DefaultGameSettings(QWidget, Ui_GameSettings):
for i in range(4): # remove some entries which are not supported by default
self.launch_settings_layout.removeRow(0)
self.cloud_group.deleteLater()
self.load_settings("default")
def save_line_edit(self, option, value):
@ -80,10 +79,6 @@ class DefaultGameSettings(QWidget, Ui_GameSettings):
config_helper.remove_option(self.game.app_name, option)
config_helper.save_config()
if option == "wine_prefix":
if self.game.supports_cloud_saves:
self.compute_save_path()
def update_combobox(self, i, option):
if self.change:
# remove section

View file

@ -31,6 +31,7 @@ class RareGameBase(QObject):
VERIFYING = 3
MOVING = 4
UNINSTALLING = 5
SYNCING = 6
class Signals:
class Progress(QObject):
@ -198,6 +199,7 @@ class RareGame(RareGameSlim):
self.__origin_install_path: Optional[str] = None
self.__origin_install_size: Optional[int] = None
self.__steam_grade: Optional[str] = None
self.__latest_save: Optional[SaveGameFile] = None
self.image_manager = image_manager
@ -236,6 +238,21 @@ class RareGame(RareGameSlim):
if worker is None:
self.state = RareGame.State.IDLE
@property
def latest_save(self) -> Optional[SaveGameFile]:
if self.saves:
self.saves.sort(key=lambda s: s.datetime, reverse=True)
return self.saves[0]
return None
@latest_save.setter
def latest_save(self, save: SaveGameFile):
self.__latest_save = save
def upload_saves(self):
if not self.game.supports_cloud_saves:
return
@pyqtSlot(int)
def __game_launched(self, code: int):
if code == GameProcess.Code.ON_STARTUP:
@ -543,9 +560,21 @@ class RareGame(RareGameSlim):
@property
def raw_save_path(self) -> str:
if self.game.supports_cloud_saves:
return self.game.metadata.get("customAttributes", {}).get("CloudSaveFolder", {}).get("value")
return self.game.metadata['customAttributes'].get("CloudSaveFolder", {}).get("value")
return ""
@property
def raw_save_path_mac(self) -> str:
if self.game.supports_mac_cloud_saves:
return self.game.metadata['customAttributes'].get('CloudSaveFolder_MAC', {}).get('value')
return ""
@property
def save_path(self) -> Optional[str]:
if self.igame is not None:
return self.igame.save_path
return None
def steam_grade(self) -> str:
if platform.system() == "Windows" or self.is_unreal:
return "na"

View file

@ -432,12 +432,12 @@ class RareCore(QObject):
"""!
SaveGameFiles across games
"""
return chain.from_iterable([game.saves for game in self.has_saves])
return chain.from_iterable([game.latest_save for game in self.has_saves])
@property
def has_saves(self) -> Iterator[RareGame]:
"""!
RareGames that have SaveGameFiles associated with them
"""
return self.__filter_games(lambda game: bool(game.saves))
return self.__filter_games(lambda game: bool(game.latest_save))

View file

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/game_info/cloud_widget.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_CloudWidget(object):
def setupUi(self, CloudWidget):
CloudWidget.setObjectName("CloudWidget")
CloudWidget.resize(251, 93)
CloudWidget.setWindowTitle("GroupBox")
self.cloud_layout = QtWidgets.QFormLayout(CloudWidget)
self.cloud_layout.setObjectName("cloud_layout")
self.cloud_sync_label = QtWidgets.QLabel(CloudWidget)
self.cloud_sync_label.setObjectName("cloud_sync_label")
self.cloud_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.cloud_sync_label)
self.cloud_sync = QtWidgets.QCheckBox(CloudWidget)
self.cloud_sync.setText("")
self.cloud_sync.setObjectName("cloud_sync")
self.cloud_layout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cloud_sync)
self.retranslateUi(CloudWidget)
def retranslateUi(self, CloudWidget):
_translate = QtCore.QCoreApplication.translate
CloudWidget.setTitle(_translate("CloudWidget", "Options"))
self.cloud_sync_label.setText(_translate("CloudWidget", "Sync with cloud"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
CloudWidget = QtWidgets.QGroupBox()
ui = Ui_CloudWidget()
ui.setupUi(CloudWidget)
CloudWidget.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CloudWidget</class>
<widget class="QGroupBox" name="CloudWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>251</width>
<height>93</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">GroupBox</string>
</property>
<property name="title">
<string>Options</string>
</property>
<layout class="QFormLayout" name="cloud_layout">
<item row="0" column="0">
<widget class="QLabel" name="cloud_sync_label">
<property name="text">
<string>Sync with cloud</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cloud_sync">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GameSettings(object):
def setupUi(self, GameSettings):
GameSettings.setObjectName("GameSettings")
GameSettings.resize(263, 258)
GameSettings.resize(263, 261)
self.game_settings_layout = QtWidgets.QVBoxLayout(GameSettings)
self.game_settings_layout.setObjectName("game_settings_layout")
self.launch_settings_group = QtWidgets.QGroupBox(GameSettings)
@ -68,19 +68,6 @@ class Ui_GameSettings(object):
self.override_exe_edit.setObjectName("override_exe_edit")
self.launch_settings_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.override_exe_edit)
self.game_settings_layout.addWidget(self.launch_settings_group)
self.cloud_group = QtWidgets.QGroupBox(GameSettings)
self.cloud_group.setObjectName("cloud_group")
self.cloud_layout = QtWidgets.QFormLayout(self.cloud_group)
self.cloud_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.cloud_layout.setObjectName("cloud_layout")
self.cloud_sync_label = QtWidgets.QLabel(self.cloud_group)
self.cloud_sync_label.setObjectName("cloud_sync_label")
self.cloud_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.cloud_sync_label)
self.cloud_sync = QtWidgets.QCheckBox(self.cloud_group)
self.cloud_sync.setText("")
self.cloud_sync.setObjectName("cloud_sync")
self.cloud_layout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cloud_sync)
self.game_settings_layout.addWidget(self.cloud_group)
self.proton_layout = QtWidgets.QVBoxLayout()
self.proton_layout.setObjectName("proton_layout")
self.game_settings_layout.addLayout(self.proton_layout)
@ -109,8 +96,6 @@ class Ui_GameSettings(object):
self.launch_params.setPlaceholderText(_translate("GameSettings", "parameters"))
self.override_exe_label.setText(_translate("GameSettings", "Override Exe"))
self.override_exe_edit.setPlaceholderText(_translate("GameSettings", "Relative path to launch executable"))
self.cloud_group.setTitle(_translate("GameSettings", "Cloud Saves"))
self.cloud_sync_label.setText(_translate("GameSettings", "Sync with cloud"))
if __name__ == "__main__":

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>263</width>
<height>258</height>
<height>261</height>
</rect>
</property>
<property name="windowTitle">
@ -124,32 +124,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="cloud_group">
<property name="title">
<string>Cloud Saves</string>
</property>
<layout class="QFormLayout" name="cloud_layout">
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="cloud_sync_label">
<property name="text">
<string>Sync with cloud</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cloud_sync">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="proton_layout"/>
</item>

View file

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/game_info/sync_widget.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_SyncWidget(object):
def setupUi(self, SyncWidget):
SyncWidget.setObjectName("SyncWidget")
SyncWidget.resize(400, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(SyncWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.local_gb = QtWidgets.QGroupBox(SyncWidget)
self.local_gb.setObjectName("local_gb")
self.local_layout = QtWidgets.QVBoxLayout(self.local_gb)
self.local_layout.setObjectName("local_layout")
self.date_info_local = QtWidgets.QLabel(self.local_gb)
self.date_info_local.setText("TextLabel")
self.date_info_local.setAlignment(QtCore.Qt.AlignCenter)
self.date_info_local.setObjectName("date_info_local")
self.local_layout.addWidget(self.date_info_local)
self.icon_local = QtWidgets.QLabel(self.local_gb)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.icon_local.sizePolicy().hasHeightForWidth())
self.icon_local.setSizePolicy(sizePolicy)
self.icon_local.setText("")
self.icon_local.setAlignment(QtCore.Qt.AlignCenter)
self.icon_local.setObjectName("icon_local")
self.local_layout.addWidget(self.icon_local)
self.upload_button = QtWidgets.QPushButton(self.local_gb)
self.upload_button.setObjectName("upload_button")
self.local_layout.addWidget(self.upload_button)
self.horizontalLayout.addWidget(self.local_gb)
self.cloud_gb = QtWidgets.QGroupBox(SyncWidget)
self.cloud_gb.setObjectName("cloud_gb")
self.cloud_layout = QtWidgets.QVBoxLayout(self.cloud_gb)
self.cloud_layout.setObjectName("cloud_layout")
self.date_info_remote = QtWidgets.QLabel(self.cloud_gb)
self.date_info_remote.setText("TextLabel")
self.date_info_remote.setAlignment(QtCore.Qt.AlignCenter)
self.date_info_remote.setObjectName("date_info_remote")
self.cloud_layout.addWidget(self.date_info_remote)
self.icon_remote = QtWidgets.QLabel(self.cloud_gb)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.icon_remote.sizePolicy().hasHeightForWidth())
self.icon_remote.setSizePolicy(sizePolicy)
self.icon_remote.setText("")
self.icon_remote.setAlignment(QtCore.Qt.AlignCenter)
self.icon_remote.setObjectName("icon_remote")
self.cloud_layout.addWidget(self.icon_remote)
self.download_button = QtWidgets.QPushButton(self.cloud_gb)
self.download_button.setObjectName("download_button")
self.cloud_layout.addWidget(self.download_button)
self.horizontalLayout.addWidget(self.cloud_gb)
self.verticalLayout.addLayout(self.horizontalLayout)
self.path_layout = QtWidgets.QFormLayout()
self.path_layout.setObjectName("path_layout")
self.verticalLayout.addLayout(self.path_layout)
self.retranslateUi(SyncWidget)
def retranslateUi(self, SyncWidget):
_translate = QtCore.QCoreApplication.translate
SyncWidget.setWindowTitle(_translate("SyncWidget", "Form"))
self.local_gb.setTitle(_translate("SyncWidget", "Local"))
self.upload_button.setText(_translate("SyncWidget", "Upload"))
self.cloud_gb.setTitle(_translate("SyncWidget", "Cloud"))
self.download_button.setText(_translate("SyncWidget", "Download"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
SyncWidget = QtWidgets.QWidget()
ui = Ui_SyncWidget()
ui.setupUi(SyncWidget)
SyncWidget.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SyncWidget</class>
<widget class="QWidget" name="SyncWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="local_gb">
<property name="title">
<string>Local</string>
</property>
<layout class="QVBoxLayout" name="local_layout">
<item>
<widget class="QLabel" name="date_info_local">
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="icon_local">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="upload_button">
<property name="text">
<string>Upload</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="cloud_gb">
<property name="title">
<string>Cloud</string>
</property>
<layout class="QVBoxLayout" name="cloud_layout">
<item>
<widget class="QLabel" name="date_info_remote">
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="icon_remote">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="download_button">
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="path_layout"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -188,7 +188,7 @@ def read_registry(registry: str, wine_pfx: str) -> ConfigParser:
class CloudWorker(QRunnable):
class Signals(QObject):
# List[SaveGameFile]
result_ready = pyqtSignal(list)
result_ready = pyqtSignal(dict)
def __init__(self, core: LegendaryCore):
super(CloudWorker, self).__init__()
@ -198,11 +198,23 @@ class CloudWorker(QRunnable):
def run(self) -> None:
try:
result = self.core.get_save_games()
saves = self.core.get_save_games()
except HTTPError:
result = None
self.signals.result_ready.emit(result)
self.signals.result_ready.emit(None)
return
save_games = set()
for igame in self.core.get_installed_list():
game = self.core.get_game(igame.app_name)
if self.core.is_installed(igame.app_name) and game.supports_cloud_saves:
save_games.add(igame.app_name)
latest_saves = dict()
for s in sorted(saves, key=lambda a: a.datetime):
if s.app_name in save_games:
latest_saves[s.app_name] = s
self.signals.result_ready.emit(latest_saves)
def get_raw_save_path(game: Game):
if game.supports_cloud_saves: