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:
parent
92346e11d0
commit
a66600efa3
|
@ -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)
|
||||
|
|
177
rare/components/tabs/games/game_info/cloud_saves.py
Normal file
177
rare/components/tabs/games/game_info/cloud_saves.py
Normal 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
|
|
@ -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="")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
44
rare/ui/components/tabs/games/game_info/cloud_widget.py
Normal file
44
rare/ui/components/tabs/games/game_info/cloud_widget.py
Normal 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_())
|
38
rare/ui/components/tabs/games/game_info/cloud_widget.ui
Normal file
38
rare/ui/components/tabs/games/game_info/cloud_widget.ui
Normal 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>
|
|
@ -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__":
|
||||
|
|
|
@ -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>
|
||||
|
|
92
rare/ui/components/tabs/games/game_info/sync_widget.py
Normal file
92
rare/ui/components/tabs/games/game_info/sync_widget.py
Normal 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_())
|
124
rare/ui/components/tabs/games/game_info/sync_widget.ui
Normal file
124
rare/ui/components/tabs/games/game_info/sync_widget.ui
Normal 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>
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue