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

Rebasing cloud_save_update with main

This commit is contained in:
Dummerle 2021-10-24 01:47:49 +02:00
parent 9f638ce16c
commit 8b8c3a1f64
No known key found for this signature in database
GPG key ID: AB68CC59CA39F2F1
17 changed files with 620 additions and 328 deletions

View file

@ -105,7 +105,8 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
["32bit", self.core.get_game_and_dlc_list, (True, "Win32")],
["mac", self.core.get_game_and_dlc_list, (True, "Mac")],
["assets", self.core.egs.get_game_assets, ()],
["no_assets", self.core.get_non_asset_library_items, ()]
["no_assets", self.core.get_non_asset_library_items, ()],
["saves", self.core.get_save_games, ()]
]
for r in api_requests:
worker = ApiRequestWorker(*r)
@ -138,6 +139,9 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
elif text == "no_assets":
self.api_results.no_asset_games = result[0] if result else []
elif text == "saves":
self.api_results.saves = result
if self.api_results:
self.finish()

View file

@ -39,7 +39,7 @@ class MainWindow(QMainWindow):
if shared.args.subparser == "launch":
if shared.args.app_name in [i.app_name for i in self.tab_widget.games_tab.installed]:
logger.info("Launching " + self.core.get_installed_game(shared.args.app_name).title)
self.tab_widget.games_tab.widgets[shared.args.app_name][1].launch()
self.tab_widget.games_tab.widgets[shared.args.app_name][1].prepare_launch()
else:
logger.info(
f"Could not find {shared.args.app_name} in Games or it is not installed")
@ -56,8 +56,8 @@ class MainWindow(QMainWindow):
file.close()
if action.startswith("launch"):
game = action.replace("launch ", "").replace("\n", "")
if self.core.is_installed(game):
self.tab_widget.games_tab.widgets[game][1].launch()
if game in [i.app_name for i in self.tab_widget.games_tab.game_list] and self.core.is_installed(game):
self.tab_widget.games_tab.game_utils.prepare_launch(game, offline=shared.args.offline)
else:
logger.info(f"Could not find {game} in Games")

View file

@ -5,6 +5,7 @@ from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget
import rare.shared as shared
from .cloud_save_utils import CloudSaveUtils
from legendary.models.game import Game, InstalledGame
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.ui.components.tabs.games.games_tab import Ui_GamesTab
@ -38,6 +39,9 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.core = shared.core
self.signals = shared.signals
self.settings = QSettings()
self.cloud_save_utils = CloudSaveUtils()
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
self.before_launch_sync = dict()
self.game_list = shared.api_results.game_list
self.dlcs = shared.api_results.dlcs
@ -129,7 +133,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.import_sync_tabs.show_egl_sync()
def show_game_info(self, game):
self.game_info_tabs.update_game(game, self.dlcs)
self.game_info_tabs.update_game(game)
self.setCurrentIndex(1)
def show_uninstalled_info(self, game):
@ -137,7 +141,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.setCurrentIndex(3)
def setup_game_list(self):
self.icon_view = QWidget()
self.icon_view.setLayout(FlowLayout())
self.list_view = QWidget()
@ -153,12 +156,12 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
# add installed games
for igame in self.installed:
icon_widget, list_widget = self.add_installed_widget(self.core.get_game(igame.app_name, update_meta=False))
icon_widget, list_widget = self.add_installed_widget(igame.app_name)
self.icon_view.layout().addWidget(icon_widget)
self.list_view.layout().addWidget(list_widget)
for game in self.no_assets:
icon_widget, list_widget = self.add_installed_widget(game, is_origin=True)
icon_widget, list_widget = self.add_installed_widget(game.app_name)
self.icon_view.layout().addWidget(icon_widget)
self.list_view.layout().addWidget(list_widget)
@ -175,35 +178,44 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
len(self.core.get_installed_list()),
len(self.game_list)))
def add_installed_widget(self, game, is_origin=False):
pixmap = get_pixmap(game.app_name)
def sync_finished(self, app_name):
self.widgets[app_name][0].info_text = ""
self.widgets[app_name][0].info_label.setText("")
self.widgets[app_name][1].info_label.setText("")
if app_name in self.before_launch_sync.keys():
self.launch(*self.before_launch_sync[app_name])
self.before_launch_sync.pop(app_name)
def add_installed_widget(self, app_name):
pixmap = get_pixmap(app_name)
if pixmap.isNull():
logger.info(game.app_title + " has a corrupt image.")
download_image(self.core.get_game(game.app_name), force=True)
pixmap = get_pixmap(game.app_name)
logger.info(app_name + " has a corrupt image.")
download_image(self.core.get_game(app_name), force=True)
pixmap = get_pixmap(app_name)
if game.app_name in self.no_asset_names:
igame = None
else:
igame = self.core.get_installed_game(game.app_name)
icon_widget = InstalledIconWidget(app_name, pixmap)
icon_widget = InstalledIconWidget(igame, pixmap, is_origin, game)
list_widget = InstalledListWidget(app_name, pixmap)
list_widget = InstalledListWidget(igame, pixmap, is_origin, game)
self.widgets[game.app_name] = (icon_widget, list_widget)
self.widgets[app_name] = (icon_widget, list_widget)
icon_widget.show_info.connect(self.show_game_info)
list_widget.show_info.connect(self.show_game_info)
icon_widget.launch_signal.connect(self.launch)
icon_widget.launch_signal.connect(self.prepare_launch)
icon_widget.finish_signal.connect(self.finished)
list_widget.launch_signal.connect(self.launch)
list_widget.launch_signal.connect(self.prepare_launch)
list_widget.finish_signal.connect(self.finished)
game = self.core.get_game(app_name)
if game.supports_cloud_saves:
icon_widget.sync_game.connect(self.cloud_save_utils.sync_before_launch_game)
list_widget.sync_game.connect(self.cloud_save_utils.sync_before_launch_game)
if icon_widget.update_available:
self.updates.add(igame.app_name)
self.updates.add(app_name)
return icon_widget, list_widget
@ -230,33 +242,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
return icon_widget, list_widget
def finished(self, app_name):
self.running_games.remove(app_name)
self.widgets[app_name][0].info_text = ""
self.widgets[app_name][0].info_label.setText("")
self.widgets[app_name][1].launch_button.setDisabled(False)
self.widgets[app_name][1].launch_button.setText(self.tr("Launch"))
if self.widgets[app_name][0].game.supports_cloud_saves:
if not self.settings.value(f"{app_name}/auto_sync_cloud", True, bool) \
and not self.settings.value("auto_sync_cloud", True, bool):
logger.info("Auto saves disabled")
return
self.widgets[app_name][0].info_text = self.tr("Sync CLoud saves")
self.widgets[app_name][0].info_label.setText(self.tr("Sync CLoud saves"))
self.widgets[app_name][1].info_label.setText(self.tr("Sync CLoud saves"))
self.signals.set_discord_rpc.emit(None)
def launch(self, app_name):
self.running_games.append(app_name)
# self.game_started.emit(app_name)
self.widgets[app_name][0].info_text = self.tr("Game running")
self.widgets[app_name][0].info_label.setText(self.tr("Game running"))
self.widgets[app_name][1].launch_button.setDisabled(True)
self.widgets[app_name][1].launch_button.setText(self.tr("Game running"))
self.signals.set_discord_rpc.emit(app_name)
def filter_games(self, filter_name="all", search_text: str = ""):
if not search_text and (t := self.head_bar.search_bar.text()):
search_text = t
@ -315,7 +300,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.widgets[app_name][1].deleteLater()
self.widgets.pop(app_name)
self.add_installed_widget(self.core.get_game(app_name))
self.add_installed_widget(app_name)
update_list = True
# uninstalled
@ -330,6 +315,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
game = self.core.get_game(app_name, False)
self.add_uninstalled_widget(game)
update_list = True
# do not update, if only update finished
if update_list:
self._update_games()
@ -356,7 +342,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.widgets.pop(name)
igame = self.core.get_installed_game(name)
self.add_installed_widget(self.core.get_game(igame.app_name))
self.add_installed_widget(igame.app_name)
for name in new_uninstalled_games:
self.icon_view.layout().removeWidget(self.widgets[name][0])

View file

@ -0,0 +1,208 @@
import datetime
from dataclasses import dataclass
from logging import getLogger
from typing import Union
from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool, Qt
from PyQt5.QtWidgets import QDialog, QMessageBox, QSizePolicy, QLayout
from qtawesome import icon
from legendary.models.game import SaveGameStatus, InstalledGame, SaveGameFile
from rare import shared
from rare.ui.components.dialogs.sync_save_dialog import Ui_SyncSaveDialog
logger = getLogger("Cloud Saves")
@dataclass
class UploadModel:
app_name: str
date_time: datetime.datetime
path: str
@dataclass
class DownloadModel:
app_name: str
latest_save: SaveGameFile
path: str
class WorkerSignals(QObject):
finished = pyqtSignal(str, str)
class SaveWorker(QRunnable):
signals = WorkerSignals()
def __init__(self, model: Union[UploadModel, DownloadModel]):
super(SaveWorker, self).__init__()
self.model = model
self.setAutoDelete(True)
def run(self) -> None:
try:
if isinstance(self.model, DownloadModel):
shared.core.download_saves(self.model.app_name, self.model.latest_save.manifest_name, self.model.path)
else:
shared.core.upload_save(self.model.app_name, self.model.path, self.model.date_time)
except Exception as e:
self.signals.finished.emit(str(e), self.model.app_name)
logger.error(str(e))
return
self.signals.finished.emit("", self.model.app_name)
class CloudSaveDialog(QDialog, Ui_SyncSaveDialog):
DOWNLOAD = 2
UPLOAD = 1
CANCEL = 0
def __init__(self, igame: InstalledGame, dt_local: datetime.datetime, dt_remote: datetime.datetime, newer: str):
super(CloudSaveDialog, self).__init__()
self.setupUi(self)
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
self.status = self.CANCEL
self.title_label.setText(self.title_label.text() + igame.title)
self.date_info_local.setText(dt_local.strftime("%A, %d. %B %Y %I:%M%p"))
self.date_info_remote.setText(dt_remote.strftime("%A, %d. %B %Y %I:%M%p"))
new_text = self.tr(" (newer)")
if newer == "remote":
self.cloud_gb.setTitle(self.cloud_gb.title() + new_text)
elif newer == "local":
self.local_gb.setTitle(self.local_gb.title() + new_text)
self.icon_local.setPixmap(icon("mdi.harddisk").pixmap(128, 128))
self.icon_remote.setPixmap(icon("mdi.cloud-outline").pixmap(128, 128))
self.upload_button.clicked.connect(lambda: self.btn_clicked(self.UPLOAD))
self.download_button.clicked.connect(lambda: self.btn_clicked(self.DOWNLOAD))
self.cancel_button.clicked.connect(self.close)
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
self.layout().setSizeConstraint(QLayout.SetFixedSize)
def get_action(self):
self.exec_()
return self.status
def btn_clicked(self, status):
self.status = status
self.close()
class CloudSaveUtils(QObject):
sync_finished = pyqtSignal(str)
def __init__(self):
super(CloudSaveUtils, self).__init__()
self.core = shared.core
saves = shared.api_results.saves
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)
self.latest_saves = dict()
for s in sorted(saves, key=lambda a: a.datetime):
if s.app_name in save_games:
self.latest_saves[s.app_name] = s
self.thread_pool = QThreadPool.globalInstance()
def sync_before_launch_game(self, app_name):
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:
newer = "remote"
elif res == SaveGameStatus.LOCAL_NEWER:
newer = "local"
if res == SaveGameStatus.REMOTE_NEWER and not dt_local:
self.download_saves(igame)
return True
elif res == SaveGameStatus.LOCAL_NEWER and not dt_remote:
self.upload_saves(igame, dt_local)
return True
result = CloudSaveDialog(igame, dt_local, dt_remote, newer).get_action()
if result == CloudSaveDialog.UPLOAD:
self.upload_saves(igame, dt_local)
return
elif result == CloudSaveDialog.DOWNLOAD:
self.download_saves(igame)
elif result == CloudSaveDialog.CANCEL:
return False
return True
return False
def game_finished(self, app_name, exit_code):
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))
if res == SaveGameStatus.LOCAL_NEWER:
if exit_code != 0:
reply = QMessageBox.question(None, "Cloud Saves", self.tr(
"Game could crashed. Do you want to upload save files? The save files could be corrupt"),
buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.Yes)
if reply == QMessageBox.No:
self.sync_finished.emit(app_name)
return
self.upload_saves(igame, dt_local)
return
elif res == SaveGameStatus.NO_SAVE:
QMessageBox.warning(None, "No saves", self.tr(
"There are no saves local and online. Maybe you have to change save path of {}").format(igame.title))
return
elif res == SaveGameStatus.SAME_AGE:
return
# Remote newer
newer = None
if res == SaveGameStatus.REMOTE_NEWER:
newer = "remote"
result = CloudSaveDialog(igame, dt_local, dt_remote, newer).get_action()
if result == CloudSaveDialog.UPLOAD:
self.upload_saves(igame, dt_local)
elif result == CloudSaveDialog.DOWNLOAD:
self.download_saves(igame)
def upload_saves(self, igame: InstalledGame, dt_local):
logger.info("Uploading saves for " + igame.title)
w = SaveWorker(UploadModel(igame.app_name, dt_local, igame.save_path))
w.signals.finished.connect(self.worker_finished)
self.thread_pool.start(w)
def download_saves(self, igame):
logger.info("Downloading saves for " + igame.title)
w = SaveWorker(DownloadModel(igame.app_name, self.latest_saves.get(igame.app_name), igame.save_path))
w.signals.finished.connect(self.worker_finished)
self.thread_pool.start(w)
def worker_finished(self, error_message: str, app_name: str):
if not error_message:
self.sync_finished.emit(app_name)
else:
QMessageBox.warning(None, "Warning", self.tr("Syncing with cloud failed: \n ") + error_message)
self.sync_finished.emit(app_name)

View file

@ -27,7 +27,7 @@ class GameInfoTabs(SideTabWidget):
self.tabBar().setCurrentIndex(1)
def update_game(self, game: Game, dlcs: list):
def update_game(self, game: Game):
self.setCurrentIndex(1)
self.info.update_game(game)
self.settings.update_game(game)

View file

@ -3,7 +3,7 @@ import platform
from typing import Tuple
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QWidget, QFileDialog
from PyQt5.QtWidgets import QWidget, QFileDialog, QLabel
from legendary.core import LegendaryCore
from legendary.models.game import InstalledGame, Game
@ -47,6 +47,13 @@ class GameSettings(QWidget, Ui_GameSettings):
self.core = core
self.settings = QSettings()
self.cloud_save_path_edit = PathEdit("", file_type=QFileDialog.DirectoryOnly,
ph_text=self.tr("Cloud save path"),
edit_func=lambda text: (os.path.exists(text), text),
save_func=self.save_save_path)
self.cloud_gb.layout().addRow(QLabel(self.tr("Save path")), self.cloud_save_path_edit)
self.offline.currentIndexChanged.connect(
lambda x: self.update_combobox(x, "offline")
)
@ -85,7 +92,12 @@ class GameSettings(QWidget, Ui_GameSettings):
else:
self.proton_groupbox.setVisible(False)
# startparams, skip_update_check
# skip_update_check
def save_save_path(self, text):
if self.game.supports_cloud_saves and not 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:
@ -211,7 +223,7 @@ class GameSettings(QWidget, Ui_GameSettings):
self.game_title.setText(f"<h2>{self.game.app_title}</h2>")
if platform.system() != "Windows":
self.linux_settings.update_game(app_name)
self.linux_settings.dxvk.update_settings(app_name)
proton = self.core.lgd.config.get(f"{app_name}", "wrapper", fallback="").replace('"', "")
if proton != "":
self.proton_prefix.setEnabled(True)
@ -227,11 +239,16 @@ class GameSettings(QWidget, Ui_GameSettings):
self.wrapper_widget.setEnabled(True)
if not self.game.supports_cloud_saves:
self.cloud_sync.setEnabled(False)
self.cloud_gb.setEnabled(False)
self.cloud_save_path_edit.setText("")
else:
self.cloud_sync.setEnabled(True)
self.cloud_gb.setEnabled(True)
sync_cloud = self.settings.value(f"{self.game.app_name}/auto_sync_cloud", True, bool)
self.cloud_sync.setChecked(sync_cloud)
if 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.change = True
@ -245,5 +262,6 @@ class LinuxAppSettings(LinuxSettings):
self.name = app_name
self.wine_prefix.setText(self.core.lgd.config.get(self.name, "wine_prefix", fallback=""))
self.wine_exec.setText(self.core.lgd.config.get(self.name, "wine_executable", fallback=""))
self.dxvk.name = app_name
self.dxvk.more_settings_widget.name = app_name
self.dxvk.load_settings()

View file

@ -7,7 +7,7 @@ from PyQt5.QtCore import pyqtSignal, QProcess, QSettings, Qt, QByteArray, QProce
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QGroupBox, QMessageBox, QAction, QLabel, QPushButton
from legendary.models.game import InstalledGame, Game
from legendary.models.game import Game
from rare import shared
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.extra.console import ConsoleWindow
@ -18,29 +18,32 @@ logger = getLogger("Game")
class BaseInstalledWidget(QGroupBox):
launch_signal = pyqtSignal(str)
launch_signal = pyqtSignal(str, QProcess, list)
show_info = pyqtSignal(Game)
finish_signal = pyqtSignal(str)
finish_signal = pyqtSignal(str, int)
update_list = pyqtSignal()
proc: QProcess()
sync_game = pyqtSignal(str)
def __init__(self, igame: InstalledGame, pixmap: QPixmap, is_origin: bool = False, game: Game = None):
def __init__(self, app_name, pixmap: QPixmap):
super(BaseInstalledWidget, self).__init__()
self.igame = igame
self.is_origin = is_origin
self.core = shared.core
if not game:
self.game = self.core.get_game(self.igame.app_name)
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.game = game
self.is_origin = True
self.image = QLabel()
self.image.setPixmap(pixmap.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation))
self.game_running = False
self.offline = shared.args.offline
if is_origin:
if self.game.third_party_store == "Origin":
self.update_available = False
else:
self.update_available = self.core.get_asset(self.game.app_name, False).build_version != igame.version
self.update_available = self.core.get_asset(self.game.app_name, False).build_version != self.igame.version
self.data = QByteArray()
self.setContentsMargins(0, 0, 0, 0)
self.settings = QSettings()
@ -50,12 +53,17 @@ class BaseInstalledWidget(QGroupBox):
launch.triggered.connect(self.launch)
self.addAction(launch)
if self.game.supports_cloud_saves:
sync = QAction(self.tr("Sync with cloud"), self)
sync.triggered.connect(lambda: self.sync_game.emit(self.game.app_name))
self.addAction(sync)
if os.path.exists(os.path.expanduser(f"~/Desktop/{self.game.app_title}.desktop")) \
or os.path.exists(os.path.expanduser(f"~/Desktop/{self.game.app_title}.lnk")):
self.create_desktop = QAction(self.tr("Remove Desktop link"))
else:
self.create_desktop = QAction(self.tr("Create Desktop link"))
if not is_origin:
if not self.is_origin:
self.create_desktop.triggered.connect(lambda: self.create_desktop_link("desktop"))
self.addAction(self.create_desktop)
@ -69,7 +77,7 @@ class BaseInstalledWidget(QGroupBox):
self.create_start_menu = QAction(self.tr("Remove start menu link"))
else:
self.create_start_menu = QAction(self.tr("Create start menu link"))
if not is_origin:
if not self.is_origin:
self.create_start_menu.triggered.connect(lambda: self.create_desktop_link("start_menu"))
self.addAction(self.create_start_menu)
@ -185,9 +193,8 @@ class BaseInstalledWidget(QGroupBox):
self.proc.readyReadStandardOutput.connect(self.stdout)
self.proc.readyReadStandardError.connect(self.stderr)
self.proc.start(params[0], params[1:])
self.launch_signal.emit(self.game.app_name)
self.game_running = True
self.launch_signal.emit(self.game.app_name, self.proc, params)
# self.game_running = True
return 0
@ -214,7 +221,7 @@ class BaseInstalledWidget(QGroupBox):
if resp == 0:
webbrowser.open("https://www.dm.origin.com/download")
self.finish_signal.emit(self.game.app_name)
self.finish_signal.emit(self.game.app_name, exit_code)
self.game_running = False
if self.settings.value("show_console", False, bool):
self.console.log(f"Game exited with code: {exit_code}")

View file

@ -5,7 +5,6 @@ from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton, QLabel
from qtawesome import icon
from legendary.models.game import InstalledGame, Game
from rare import shared
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
@ -15,9 +14,8 @@ logger = getLogger("GameWidgetInstalled")
class InstalledIconWidget(BaseInstalledWidget):
update_game = pyqtSignal()
def __init__(self, igame: InstalledGame, pixmap, is_origin: bool = False,
game: Game = None):
super(InstalledIconWidget, self).__init__(igame, pixmap, is_origin, game)
def __init__(self, app_name, pixmap):
super(InstalledIconWidget, self).__init__(app_name, pixmap)
self.setObjectName("game_widget_icon")
self.setContextMenuPolicy(Qt.ActionsContextMenu)
@ -32,7 +30,7 @@ class InstalledIconWidget(BaseInstalledWidget):
self.layout.addWidget(self.image)
self.title_label = QLabel(f"<h4>{game.app_title}</h4>")
self.title_label = QLabel(f"<h4>{self.game.app_title}</h4>")
self.title_label.setAutoFillBackground(False)
self.title_label.setWordWrap(True)
self.title_label.setFixedWidth(175)

View file

@ -4,7 +4,6 @@ from PyQt5.QtCore import QProcess, pyqtSignal
from PyQt5.QtWidgets import QHBoxLayout, QLabel, QPushButton, QVBoxLayout
from qtawesome import icon
from legendary.models.game import InstalledGame, Game
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget
logger = getLogger("GameWidget")
@ -15,12 +14,12 @@ class InstalledListWidget(BaseInstalledWidget):
signal = pyqtSignal(str)
update_game = pyqtSignal()
def __init__(self, igame: InstalledGame, pixmap, is_origin: bool = False, game: Game = None):
super(InstalledListWidget, self).__init__(igame, pixmap, is_origin, game)
def __init__(self, app_name, pixmap):
super(InstalledListWidget, self).__init__(app_name, pixmap)
self.dev = self.game.metadata["developer"]
if not is_origin:
self.size = igame.install_size
self.launch_params = igame.launch_parameters
if self.game.third_party_store != "Origin":
self.size = self.igame.install_size
self.launch_params = self.igame.launch_parameters
else:
self.size = 0
self.launch_params = ""

View file

@ -1,10 +1,7 @@
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QGroupBox
from PyQt5.QtWidgets import QWidget, QCheckBox, QVBoxLayout, QWidgetAction, QMenu, QToolButton, QHBoxLayout
from legendary.core import LegendaryCore
from rare import shared
from rare.ui.components.tabs.settings.dxvk import Ui_DxvkSettings
@ -65,7 +62,6 @@ class DxvkSettings(QGroupBox, Ui_DxvkSettings):
show_dxvk_index = self.show_dxvk.currentIndex()
if show_dxvk_index:
if f"{self.name}.env" not in self.core.lgd.config.sections():
print("add section dxvk")
self.core.lgd.config.add_section(f"{self.name}.env")
if show_dxvk_index == 1:
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = "0"
@ -93,139 +89,3 @@ class DxvkSettings(QGroupBox, Ui_DxvkSettings):
self.core.lgd.config.remove_section(f"{self.name}.env")
self.core.lgd.save_config()
self.load_settings()
class DxvkWidget(QGroupBox):
def __init__(self, name=None):
super(DxvkWidget, self).__init__()
self.core = shared.core
self.setObjectName("settings_widget")
self.dxvk_settings = {
"fps": [False, "Fps"],
"gpuload": [False, self.tr("GPU usage")],
"memory": [False, self.tr("Used Memory")],
"devinfo": [False, self.tr("Device info")],
"version": [False, self.tr("DXVK version")],
"api": [False, self.tr("D3D Level of application")],
"frametime": [False, self.tr("Frame time graph")]
}
self.name = name
self.layout = QVBoxLayout()
self.child_layout = QHBoxLayout()
self.setTitle(self.tr("dxvk settings"))
self.show_dxvk = QCheckBox("Show Dxvk HUD")
self.more_settings = QToolButton()
dxvk_hud = self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback="")
self.more_settings.setDisabled(not dxvk_hud == "")
if dxvk_hud:
for s in dxvk_hud.split(","):
self.dxvk_settings[s][0] = True
self.more_settings.setPopupMode(QToolButton.InstantPopup)
self.more_settings.setMenu(QMenu())
self.more_settings.setText("More DXVK settings")
action = QWidgetAction(self)
self.more_settings_widget = DxvkMoreSettingsWidget(self.dxvk_settings, self.core)
self.more_settings_widget.show_dxvk.connect(lambda x: self.show_dxvk.setChecked(x))
action.setDefaultWidget(self.more_settings_widget)
self.more_settings.menu().addAction(action)
self.show_dxvk.stateChanged.connect(self.update_dxvk_active)
self.show_dxvk.setChecked(not dxvk_hud == "")
self.child_layout.addWidget(self.show_dxvk)
self.child_layout.addWidget(self.more_settings)
self.layout.addLayout(self.child_layout)
self.setLayout(self.layout)
def update_settings(self, app_name):
self.name = app_name
dxvk_hud = self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback="")
if dxvk_hud:
self.more_settings.setDisabled(False)
for s in dxvk_hud.split(","):
self.dxvk_settings[s][0] = True
else:
self.show_dxvk.setChecked(False)
self.more_settings.setDisabled(True)
def update_dxvk_active(self):
if self.show_dxvk.isChecked():
if not f"{self.name}.env" in self.core.lgd.config.sections():
print("add section dxvk")
self.core.lgd.config.add_section(f"{self.name}.env")
self.more_settings.setDisabled(False)
for i in self.more_settings_widget.settings:
if i in ["fps", "gpuload"]:
self.more_settings_widget.settings[i][0] = True
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = "fps,gpuload"
for w in self.more_settings_widget.widgets:
if w.tag == "fps" or w.tag == "gpuload":
w.setChecked(True)
else:
w.setChecked(False)
else:
self.more_settings.setDisabled(True)
if not self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback="") == "":
self.core.lgd.config.remove_option(f"{self.name}.env", "DXVK_HUD")
if not self.core.lgd.config[f"{self.name}.env"]:
self.core.lgd.config.remove_section(f"{self.name}.env")
self.core.lgd.save_config()
class DxvkMoreSettingsWidget(QWidget):
show_dxvk = pyqtSignal(bool)
def __init__(self, settings: dict, core: LegendaryCore):
super(DxvkMoreSettingsWidget, self).__init__()
self.layout = QVBoxLayout()
self.name = "default"
self.widgets = []
self.core = core
self.settings = settings
for i in settings:
widget = CheckBox(i, settings[i])
widget.signal.connect(self.change)
self.layout.addWidget(widget)
self.widgets.append(widget)
self.setLayout(self.layout)
def change(self, signal: list):
tag, checked = signal
self.settings[tag][0] = checked
sett = []
logger.debug(self.settings)
for i in self.settings:
check, _ = self.settings[i]
if check:
sett.append(i)
if len(sett) > 0:
self.core.lgd.config.set(f"{self.name}.env", "DXVK_HUD", ",".join(sett))
else:
self.core.lgd.config.remove_option(f"{self.name}.env", "DXVK_HUD")
self.show_dxvk.emit(False)
if not self.core.lgd.config.options(f"{self.name}.env"):
self.core.lgd.config.remove_section(f"{self.name}.env")
self.core.lgd.save_config()
class CheckBox(QCheckBox):
signal = pyqtSignal(tuple)
def __init__(self, tag, settings):
checked, text = settings
super(CheckBox, self).__init__(text)
self.setChecked(checked)
self.tag = tag
self.clicked.connect(lambda: self.signal.emit((self.tag, self.isChecked())))

View file

@ -3,7 +3,7 @@ from logging import getLogger
from PyQt5.QtWidgets import QFileDialog, QWidget
from rare import shared
from rare.components.tabs.settings.dxvk import DxvkSettings, DxvkWidget
from rare.components.tabs.settings.dxvk import DxvkSettings
from rare.ui.components.tabs.settings.linux import Ui_LinuxSettings
from rare.utils.extra_widgets import PathEdit
@ -32,11 +32,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
self.exec_layout.addWidget(self.wine_exec)
# dxvk
# FIXME: Remove this check when done with per game settings
if name is None:
self.dxvk = DxvkSettings(self.name)
else:
self.dxvk = DxvkWidget()
self.dxvk = DxvkSettings(self.name)
self.dxvk_layout.addWidget(self.dxvk)
def save_setting(self, text: str, setting_name: str):

View file

@ -4,14 +4,12 @@ from qtawesome import icon
from rare import shared
from rare.components.tabs.account import MiniWidget
from rare.components.tabs.cloud_saves import SyncSaves
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
from rare.utils.models import InstallOptionsModel
class TabWidget(QTabWidget):
@ -19,7 +17,7 @@ class TabWidget(QTabWidget):
def __init__(self, parent):
super(TabWidget, self).__init__(parent=parent)
disabled_tab = 4 if not shared.args.offline else 1
disabled_tab = 3 if not shared.args.offline else 1
self.core = shared.core
self.signals = shared.signals
self.setTabBar(TabBar(disabled_tab))
@ -31,8 +29,6 @@ class TabWidget(QTabWidget):
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.cloud_saves = SyncSaves()
self.addTab(self.cloud_saves, "Cloud Saves")
self.store = Shop(self.core)
self.addTab(self.store, self.tr("Store (Beta)"))
self.settings = SettingsTab(self)
@ -65,19 +61,6 @@ class TabWidget(QTabWidget):
# update dl tab text
self.signals.update_download_tab_text.connect(self.update_dl_tab_text)
# imported
# shared.signals.update_gamelist.connect(self.game_imported)
if not shared.args.offline:
# install dlc
self.games_tab.game_info_tabs.dlc.install_dlc.connect(
lambda app_name, update: self.install_game(
InstallOptionsModel(app_name=app_name),
update=update))
# Finished sync
self.cloud_saves.finished.connect(self.finished_sync)
# Game finished
# Open game list on click on Games tab button
self.tabBarClicked.connect(self.mouse_clicked)

View file

@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/sync_save_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.5
#
# 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, QtWidgets
class Ui_SyncSaveDialog(object):
def setupUi(self, SyncSaveDialog):
SyncSaveDialog.setObjectName("SyncSaveDialog")
SyncSaveDialog.resize(648, 394)
self.verticalLayout = QtWidgets.QVBoxLayout(SyncSaveDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.title_label = QtWidgets.QLabel(SyncSaveDialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.title_label.sizePolicy().hasHeightForWidth())
self.title_label.setSizePolicy(sizePolicy)
self.title_label.setObjectName("title_label")
self.verticalLayout.addWidget(self.title_label)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.local_gb = QtWidgets.QGroupBox(SyncSaveDialog)
self.local_gb.setObjectName("local_gb")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.local_gb)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.date_info_local = QtWidgets.QLabel(self.local_gb)
self.date_info_local.setText("TextLabel")
self.date_info_local.setObjectName("date_info_local")
self.verticalLayout_2.addWidget(self.date_info_local)
self.icon_local = QtWidgets.QLabel(self.local_gb)
self.icon_local.setText("")
self.icon_local.setObjectName("icon_local")
self.verticalLayout_2.addWidget(self.icon_local)
self.upload_button = QtWidgets.QPushButton(self.local_gb)
self.upload_button.setObjectName("upload_button")
self.verticalLayout_2.addWidget(self.upload_button)
self.horizontalLayout.addWidget(self.local_gb)
self.cloud_gb = QtWidgets.QGroupBox(SyncSaveDialog)
self.cloud_gb.setObjectName("cloud_gb")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.cloud_gb)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.date_info_remote = QtWidgets.QLabel(self.cloud_gb)
self.date_info_remote.setText("TextLabel")
self.date_info_remote.setObjectName("date_info_remote")
self.verticalLayout_3.addWidget(self.date_info_remote)
self.icon_remote = QtWidgets.QLabel(self.cloud_gb)
self.icon_remote.setText("")
self.icon_remote.setObjectName("icon_remote")
self.verticalLayout_3.addWidget(self.icon_remote)
self.download_button = QtWidgets.QPushButton(self.cloud_gb)
self.download_button.setObjectName("download_button")
self.verticalLayout_3.addWidget(self.download_button)
self.horizontalLayout.addWidget(self.cloud_gb)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.cancel_button = QtWidgets.QPushButton(SyncSaveDialog)
self.cancel_button.setObjectName("cancel_button")
self.horizontalLayout_2.addWidget(self.cancel_button)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.retranslateUi(SyncSaveDialog)
QtCore.QMetaObject.connectSlotsByName(SyncSaveDialog)
def retranslateUi(self, SyncSaveDialog):
_translate = QtCore.QCoreApplication.translate
SyncSaveDialog.setWindowTitle(_translate("SyncSaveDialog", "Sync saves with cloud"))
self.title_label.setText(_translate("SyncSaveDialog", "Select save, you want to use for "))
self.local_gb.setTitle(_translate("SyncSaveDialog", "Local"))
self.upload_button.setText(_translate("SyncSaveDialog", "Upload"))
self.cloud_gb.setTitle(_translate("SyncSaveDialog", "Cloud"))
self.download_button.setText(_translate("SyncSaveDialog", "Download"))
self.cancel_button.setText(_translate("SyncSaveDialog", "Cancel"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
SyncSaveDialog = QtWidgets.QDialog()
ui = Ui_SyncSaveDialog()
ui.setupUi(SyncSaveDialog)
SyncSaveDialog.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SyncSaveDialog</class>
<widget class="QDialog" name="SyncSaveDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>648</width>
<height>394</height>
</rect>
</property>
<property name="windowTitle">
<string>Sync saves with cloud</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="title_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Select save, you want to use for</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="local_gb">
<property name="title">
<string>Local</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="date_info_local">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="icon_local">
<property name="text">
<string notr="true"/>
</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="verticalLayout_3">
<item>
<widget class="QLabel" name="date_info_remote">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="icon_remote">
<property name="text">
<string notr="true"/>
</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="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancel_button">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -2,13 +2,13 @@
# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/game_info/game_settings.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
# Created by: PyQt5 UI code generator 5.15.5
#
# 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
from PyQt5 import QtCore, QtWidgets
class Ui_GameSettings(object):
@ -55,16 +55,9 @@ class Ui_GameSettings(object):
self.offline.addItem("")
self.offline.addItem("")
self.launch_settings_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.offline)
self.cloud_sync_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.cloud_sync_label.setObjectName("cloud_sync_label")
self.launch_settings_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.cloud_sync_label)
self.cloud_sync = QtWidgets.QCheckBox(self.launch_settings_groupbox)
self.cloud_sync.setText("")
self.cloud_sync.setObjectName("cloud_sync")
self.launch_settings_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.cloud_sync)
self.launch_params_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.launch_params_label.setObjectName("launch_params_label")
self.launch_settings_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.launch_params_label)
self.launch_settings_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.launch_params_label)
self.launch_params_widget = QtWidgets.QWidget(self.launch_settings_groupbox)
self.launch_params_widget.setObjectName("launch_params_widget")
self.launch_params_layout = QtWidgets.QHBoxLayout(self.launch_params_widget)
@ -77,10 +70,10 @@ class Ui_GameSettings(object):
self.launch_params_button = QtWidgets.QPushButton(self.launch_params_widget)
self.launch_params_button.setObjectName("launch_params_button")
self.launch_params_layout.addWidget(self.launch_params_button)
self.launch_settings_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.launch_params_widget)
self.launch_settings_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.launch_params_widget)
self.wrapper_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.wrapper_label.setObjectName("wrapper_label")
self.launch_settings_layout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.wrapper_label)
self.launch_settings_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.wrapper_label)
self.wrapper_widget = QtWidgets.QWidget(self.launch_settings_groupbox)
self.wrapper_widget.setObjectName("wrapper_widget")
self.wrapper_layout = QtWidgets.QHBoxLayout(self.wrapper_widget)
@ -93,7 +86,7 @@ class Ui_GameSettings(object):
self.wrapper_button = QtWidgets.QPushButton(self.wrapper_widget)
self.wrapper_button.setObjectName("wrapper_button")
self.wrapper_layout.addWidget(self.wrapper_button)
self.launch_settings_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.wrapper_widget)
self.launch_settings_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.wrapper_widget)
self.game_settings_layout.addWidget(self.launch_settings_groupbox, 0, QtCore.Qt.AlignTop)
self.proton_groupbox = QtWidgets.QGroupBox(GameSettings)
self.proton_groupbox.setObjectName("proton_groupbox")
@ -123,6 +116,18 @@ class Ui_GameSettings(object):
self.linux_layout.setObjectName("linux_layout")
self.proton_layout.setLayout(3, QtWidgets.QFormLayout.SpanningRole, self.linux_layout)
self.game_settings_layout.addWidget(self.proton_groupbox, 0, QtCore.Qt.AlignTop)
self.cloud_gb = QtWidgets.QGroupBox(GameSettings)
self.cloud_gb.setObjectName("cloud_gb")
self.formLayout = QtWidgets.QFormLayout(self.cloud_gb)
self.formLayout.setObjectName("formLayout")
self.cloud_sync_label = QtWidgets.QLabel(self.cloud_gb)
self.cloud_sync_label.setObjectName("cloud_sync_label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.cloud_sync_label)
self.cloud_sync = QtWidgets.QCheckBox(self.cloud_gb)
self.cloud_sync.setText("")
self.cloud_sync.setObjectName("cloud_sync")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cloud_sync)
self.game_settings_layout.addWidget(self.cloud_gb)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.game_settings_layout.addItem(spacerItem)
@ -141,7 +146,6 @@ class Ui_GameSettings(object):
self.offline.setItemText(0, _translate("GameSettings", "Default"))
self.offline.setItemText(1, _translate("GameSettings", "Yes"))
self.offline.setItemText(2, _translate("GameSettings", "No"))
self.cloud_sync_label.setText(_translate("GameSettings", "Sync with cloud"))
self.launch_params_label.setText(_translate("GameSettings", "Launch parameters"))
self.launch_params.setPlaceholderText(_translate("GameSettings", "parameters"))
self.launch_params_button.setText(_translate("GameSettings", "Save"))
@ -152,6 +156,8 @@ class Ui_GameSettings(object):
self.proton_wrapper_label.setText(_translate("GameSettings", "Proton"))
self.proton_wrapper.setItemText(0, _translate("GameSettings", "Don\'t use Proton"))
self.proton_prefix_label.setText(_translate("GameSettings", "Prefix"))
self.cloud_gb.setTitle(_translate("GameSettings", "Cloud Saves"))
self.cloud_sync_label.setText(_translate("GameSettings", "Sync with cloud"))
if __name__ == "__main__":

View file

@ -98,37 +98,23 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="cloud_sync_label">
<property name="text">
<string>Sync with cloud</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="cloud_sync">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="launch_params_label">
<property name="text">
<string>Launch parameters</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QWidget" name="launch_params_widget" native="true">
<layout class="QHBoxLayout" name="launch_params_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
<item row="2" column="1">
<widget class="QWidget" name="launch_params_widget" native="true">
<layout class="QHBoxLayout" name="launch_params_layout">
<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>
@ -156,24 +142,24 @@
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="wrapper_label">
<property name="text">
<string>Wrapper</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="wrapper_widget" native="true">
<layout class="QHBoxLayout" name="wrapper_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
<item row="3" column="0">
<widget class="QLabel" name="wrapper_label">
<property name="text">
<string>Wrapper</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QWidget" name="wrapper_widget" native="true">
<layout class="QHBoxLayout" name="wrapper_layout">
<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>
@ -246,28 +232,51 @@
<layout class="QVBoxLayout" name="proton_prefix_layout"/>
</item>
<item row="3" column="0" colspan="2">
<layout class="QVBoxLayout" name="linux_layout">
<property name="spacing">
<number>0</number>
</property>
</layout>
<layout class="QVBoxLayout" name="linux_layout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="game_settings_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="cloud_gb">
<property name="title">
<string>Cloud Saves</string>
</property>
<layout class="QFormLayout" name="formLayout">
<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>
<spacer name="game_settings_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>

View file

@ -100,6 +100,7 @@ class ApiResults:
mac_games: list = None
assets: list = None
no_asset_games: list = None
saves: list = None
def __bool__(self):
return self.game_list is not None \
@ -107,7 +108,8 @@ class ApiResults:
and self.bit32_games is not None \
and self.mac_games is not None \
and self.assets is not None \
and self.no_asset_games is not None
and self.no_asset_games is not None \
and self.saves is not None
class Signals(QObject):