1
0
Fork 0
mirror of synced 2024-06-02 10:44:40 +12:00

Many fixes

This commit is contained in:
Dummerle 2021-11-16 22:54:23 +01:00
parent 825f055387
commit 3acc13e9b6
No known key found for this signature in database
GPG key ID: AB68CC59CA39F2F1
13 changed files with 152 additions and 55 deletions

View file

@ -83,13 +83,22 @@ jobs:
run: |
appimage-builder --skip-test
mv Rare-*.AppImage Rare.AppImage
mv Rare-*.AppImage.zsync Rare.AppImage.zsync
- name: Upload to GitHub
uses: svenstaro/upload-release-action@2.2.1
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: Rare.AppImage
asset_name: Rare.AppImage
asset_name: Rare-${{github.ref}}.AppImage
tag: ${{ github.ref }}
overwrite: true
- name: Upload to GitHub
uses: svenstaro/upload-release-action@2.2.1
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: Rare.AppImage
asset_name: Rare-${{github.ref}}.AppImage.zsync
tag: ${{ github.ref }}
overwrite: true
@ -119,6 +128,6 @@ jobs:
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/Rare.msi
asset_name: Rare.msi
asset_name: Rare-${{github.ref}}.msi
tag: ${{ github.ref }}
overwrite: true

View file

@ -32,8 +32,8 @@ class TabWidget(QTabWidget):
" (" + str(len(self.games_tab.updates)) + ")" if len(self.games_tab.updates) != 0 else ""))
self.store = Shop(self.core)
self.addTab(self.store, self.tr("Store (Beta)"))
self.settings = SettingsTab(self)
self.settings = SettingsTab(self)
if shared.args.debug:
self.settings.addTab(DebugSettings(), "Debug")

View file

@ -41,9 +41,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.core = shared.core
self.signals = shared.signals
self.settings = QSettings()
self.game_utils = GameUtils(parent=self)
self.before_launch_sync = dict()
shared.api_results.saves = []
self.game_list = shared.api_results.game_list
self.dlcs = shared.api_results.dlcs
@ -51,6 +48,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.mac_games = shared.api_results.mac_games
self.no_assets = shared.api_results.no_asset_games
self.game_utils = GameUtils(parent=self)
self.head_bar = GameListHeadBar(self)
self.head_bar.import_clicked.connect(self.show_import)
self.head_bar.egl_sync_clicked.connect(self.show_egl_sync)
@ -61,6 +60,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.addWidget(self.game_info_tabs)
self.game_info_tabs.info.verification_finished.connect(self.verification_finished)
self.game_info_tabs.info.uninstalled.connect(lambda x: self.setCurrentIndex(0))
self.import_sync_tabs = ImportSyncTabs(self)
self.import_sync_tabs.back_clicked.connect(lambda: self.setCurrentIndex(0))
@ -79,7 +79,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.no_asset_names.append(game.app_name)
else:
self.no_assets = []
self.setup_game_list()
if not self.settings.value("icon_view", True, bool):
@ -104,6 +103,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
self.signals.installation_finished.connect(lambda x: self.installing_widget.setVisible(False))
self.signals.uninstall_game.connect(self.uninstall_game)
self.game_utils.update_list.connect(self.update_list)
self.game_list_scroll_area.horizontalScrollBar().setDisabled(True)
def installation_started(self, app_name: str):

View file

@ -134,17 +134,43 @@ class CloudSaveUtils(QObject):
latest_saves[s.app_name] = s
return latest_saves
def sync_before_launch_game(self, app_name, ignore_settings=False) -> bool:
def sync_before_launch_game(self, app_name, ignore_settings=False) -> int:
if not ignore_settings:
default = self.settings.value("auto_sync_cloud", True, bool)
if not self.settings.value(f"{app_name}/auto_sync_cloud", default, bool):
return False
igame = self.core.get_installed_game(app_name)
if not igame.save_path:
try:
savepath = self.core.get_save_path(app_name)
except Exception as e:
logger.error(e)
savepath = ""
if savepath:
igame.save_path = savepath
self.core.lgd.set_installed_game(app_name, igame)
logger.info(f"Set save path of {igame.title} to {savepath}")
elif not ignore_settings: # sync on startup
if QMessageBox.question(None, "Warning", self.tr(
"Could not compute cloud save path. Please set it in Game settings manually. \nDo you want to launch {} anyway?").format(
igame.title, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes):
return False
else:
raise ValueError("No savepath detected")
else:
QMessageBox.warning(None, "Warning",
self.tr("No savepath found. Please set it in Game Settings manually"))
return False
res, (dt_local, dt_remote) = self.core.check_savegame_state(igame.save_path, self.latest_saves.get(app_name))
if res == SaveGameStatus.NO_SAVE:
return False
if res != SaveGameStatus.SAME_AGE:
newer = None
newer = ""
if res == SaveGameStatus.REMOTE_NEWER:
newer = "remote"
elif res == SaveGameStatus.LOCAL_NEWER:
@ -164,12 +190,12 @@ class CloudSaveUtils(QObject):
elif result == CloudSaveDialog.DOWNLOAD:
self.download_saves(igame)
elif result == CloudSaveDialog.CANCEL:
return False
raise AssertionError()
return True
return False
def game_finished(self, app_name, ignore_settings=False):
def game_finished(self, app_name, ignore_settings=False, always_ask: bool = False):
if not ignore_settings:
default = self.settings.value("auto_sync_cloud", True, bool)
if not self.settings.value(f"{app_name}/auto_sync_cloud", default, bool):
@ -177,26 +203,43 @@ class CloudSaveUtils(QObject):
return
igame = self.core.get_installed_game(app_name)
if not igame.save_path:
try:
savepath = self.core.get_save_path(app_name)
except Exception as e:
logger.error(e)
savepath = ""
if savepath:
igame.save_path = savepath
self.core.lgd.set_installed_game(app_name, igame)
logger.info(f"Set save path of {igame.title} to {savepath}")
else:
logger.warning(None, "Warning", self.tr("No savepath set. Skip syncing with cloud"))
return False
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 res == SaveGameStatus.LOCAL_NEWER and not always_ask:
self.upload_saves(igame, dt_local)
return
elif res == SaveGameStatus.NO_SAVE:
elif res == SaveGameStatus.NO_SAVE and not always_ask:
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))
self.sync_finished.emit(app_name)
return
elif res == SaveGameStatus.SAME_AGE:
elif res == SaveGameStatus.SAME_AGE and not always_ask:
self.sync_finished.emit(app_name)
return
# Remote newer
newer = None
newer = ""
if res == SaveGameStatus.REMOTE_NEWER:
newer = "remote"
elif res == SaveGameStatus.LOCAL_NEWER:
newer = "local"
result = CloudSaveDialog(igame, dt_local, dt_remote, newer).get_action()
if result == CloudSaveDialog.UPLOAD:
self.upload_saves(igame, dt_local)

View file

@ -16,7 +16,7 @@ class GameInfoTabs(SideTabWidget):
self.core = shared.core
self.signals = shared.signals
self.info = GameInfo(self)
self.info = GameInfo(self, game_utils)
self.addTab(self.info, self.tr("Information"))
self.settings = GameSettings(self.core, self)

View file

@ -1,5 +1,6 @@
import os
import platform
from logging import getLogger
from PyQt5.QtCore import pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QWidget, QMessageBox
@ -12,19 +13,22 @@ from rare.utils.models import InstallOptionsModel
from rare.utils.steam_grades import SteamWorker
from rare.utils.utils import get_size, get_pixmap
logger = getLogger("GameInfo")
class GameInfo(QWidget, Ui_GameInfo):
igame: InstalledGame
game: Game = None
verify_threads = dict()
verification_finished = pyqtSignal(InstalledGame)
uninstalled = pyqtSignal(Game)
uninstalled = pyqtSignal(str)
def __init__(self, parent):
def __init__(self, parent, game_utils):
super(GameInfo, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.signals = shared.signals
self.game_utils = game_utils
if platform.system() == "Windows":
self.lbl_grade.setVisible(False)
@ -38,13 +42,18 @@ class GameInfo(QWidget, Ui_GameInfo):
self.install_button.setText(self.tr("Link to Origin/Launch"))
self.game_actions_stack.resize(self.game_actions_stack.minimumSize())
self.uninstall_button.clicked.connect(lambda: self.signals.uninstall_game.emit(self.game))
self.uninstall_button.clicked.connect(self.uninstall)
self.verify_button.clicked.connect(self.verify)
self.repair_button.clicked.connect(self.repair)
self.verify_pool = QThreadPool()
self.verify_pool.setMaxThreadCount(2)
def uninstall(self):
if self.game_utils.uninstall_game(self.game.app_name):
self.game_utils.update_list.emit(self.game.app_name)
self.uninstalled.emit(self.game.app_name)
def repair(self):
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair')
if not os.path.exists(repair_file):
@ -55,11 +64,16 @@ class GameInfo(QWidget, Ui_GameInfo):
update=True))
def verify(self):
if not os.path.exists(self.igame.install_path):
logger.error("Path does not exist")
QMessageBox.warning(self, "Warning",
self.tr("Installation path of {} does not exist. Cannot verify").format(
self.igame.title))
return
self.verify_widget.setCurrentIndex(1)
verify_worker = VerifyWorker(self.core, self.game.app_name)
verify_worker.signals.status.connect(self.verify_staistics)
verify_worker.signals.summary.connect(self.finish_verify)
self.verify_pool.start(verify_worker)
self.verify_progress.setValue(0)
self.verify_threads[self.game.app_name] = verify_worker

View file

@ -118,26 +118,32 @@ class GameSettings(QWidget, Ui_GameSettings):
self.cloud_save_path_edit.setDisabled(True)
self.compute_save_path_button.setDisabled(True)
resolver = WineResolver(get_raw_save_path(self.game), self.game.app_name, self.core)
resolver.signals.result_ready.connect(self.wine_resolver_finished)
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
self.cloud_save_path_edit.setText(new_path)
def wine_resolver_finished(self, path):
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))
def wine_resolver_finished(self, path, app_name):
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:
return
if not path:
return
self.cloud_save_path_edit.setText(path)
self.cloud_save_path_edit.setText(path)
else:
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:

View file

@ -30,14 +30,16 @@ class GameProcess(QProcess):
class RunningGameModel:
process: GameProcess
app_name: str
always_ask_sync: bool = False
class GameUtils(QObject):
running_games = dict()
finished = pyqtSignal(str, str)
finished = pyqtSignal(str, str) # app_name, error
cloud_save_finished = pyqtSignal(str)
launch_queue = dict()
game_launched = pyqtSignal(str)
update_list = pyqtSignal(str)
def __init__(self, parent=None):
super(GameUtils, self).__init__(parent=parent)
@ -48,7 +50,19 @@ class GameUtils(QObject):
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
def uninstall_game(self, app_name) -> bool:
# returns if uninstalled
game = self.core.get_game(app_name)
igame = self.core.get_installed_game(app_name)
if not os.path.exists(igame.install_path):
if QMessageBox.Yes == QMessageBox.question(None, "Uninstall", self.tr(
"Game files of {} do not exist. Remove it from installed games?").format(igame.title),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes):
self.core.lgd.remove_installed_game(app_name)
return True
else:
return False
infos = UninstallDialog(game).get_information()
if infos == 0:
return False
@ -57,17 +71,26 @@ class GameUtils(QObject):
def prepare_launch(self, app_name, offline: bool = False, skip_update_check: bool = False):
game = self.core.get_game(app_name)
if game.supports_cloud_saves and self.cloud_save_utils.sync_before_launch_game(app_name):
self.launch_queue[app_name] = (app_name, skip_update_check, offline)
return
elif game.supports_cloud_saves:
dont_sync_after_finish = False
if game.supports_cloud_saves:
try:
sync = self.cloud_save_utils.sync_before_launch_game(app_name)
except ValueError:
logger.info("Cancel startup")
self.sync_finished(app_name)
except AssertionError:
dont_sync_after_finish = True
else:
if sync:
self.launch_queue[app_name] = (app_name, skip_update_check, offline)
return
self.sync_finished(app_name)
self.launch_game(app_name, offline, skip_update_check)
return
self.launch_game(app_name, offline, skip_update_check, ask_always_sync=dont_sync_after_finish)
def launch_game(self, app_name: str, offline: bool = False, skip_update_check: bool = False, wine_bin: str = None,
wine_pfx: str = None):
wine_pfx: str = None, ask_always_sync: bool = False):
game = self.core.get_game(app_name)
igame = self.core.get_installed_game(app_name)
@ -90,7 +113,8 @@ class GameUtils(QObject):
return
if not os.path.exists(igame.install_path):
logger.error("Game doesn't exist")
self.finished.emit(app_name, self.tr("Game files of {} do not exist. Please install game"))
self.finished.emit(app_name,
self.tr("Game files of {} do not exist. Please install game").format(game.app_title))
return
process = GameProcess(app_name)
@ -145,7 +169,7 @@ class GameUtils(QObject):
process.setProcessEnvironment(environment)
process.game_finished.connect(self.game_finished)
running_game = RunningGameModel(process=process, app_name=app_name)
running_game = RunningGameModel(process=process, app_name=app_name, always_ask_sync=ask_always_sync)
process.start(full_params[0], full_params[1:])
self.game_launched.emit(app_name)
@ -202,6 +226,7 @@ class GameUtils(QObject):
if resp == 0:
webbrowser.open("https://www.dm.origin.com/download")
game: RunningGameModel = self.running_games.get(app_name, None)
self.running_games.pop(app_name)
self.finished.emit(app_name, "")
@ -216,7 +241,7 @@ class GameUtils(QObject):
buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.Yes)
if r != QMessageBox.Yes:
return
self.cloud_save_utils.game_finished(app_name)
self.cloud_save_utils.game_finished(app_name, game.always_ask_sync)
def sync_finished(self, app_name):
if app_name in self.launch_queue.keys():

View file

@ -154,6 +154,7 @@ class BaseInstalledWidget(QGroupBox):
self.syncing_cloud_saves = False
def sync_game(self):
if self.game_utils.cloud_save_utils.sync_before_launch_game(self.game.app_name, True):
self.syncing_cloud_saves = True

View file

@ -112,8 +112,7 @@ class InstalledIconWidget(BaseInstalledWidget):
def game_finished(self, app_name, error):
if app_name != self.game.app_name:
return
super().game_finished(app_name, error)
self.game_running = False
self.leaveEvent(None)
def game_started(self, app_name):

View file

@ -9,7 +9,6 @@ class ImportSyncTabs(SideTabWidget):
def __init__(self, parent=None):
super(ImportSyncTabs, self).__init__(show_back=True, parent=parent)
self.import_widget = ImportSyncWidget(
ImportGroup(self),
self.tr('Import Game'),

View file

@ -3,9 +3,9 @@ import os
from logging import getLogger
from typing import List, Tuple
from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal, QObject, QEvent
from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QListView, QTreeView, QHeaderView
from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QTreeView, QHeaderView
import rare.shared as shared
from rare.ui.components.tabs.games.import_sync.import_group import Ui_ImportGroup
@ -65,10 +65,10 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
super(ImportGroup, self).__init__(parent=parent)
self.setupUi(self)
self.core = shared.core
self.app_name_list = [game.app_name for game in self.core.get_game_list()]
self.app_name_list = [game.app_name for game in shared.api_results.game_list]
self.install_dir_list = [
game.metadata.get('customAttributes', {}).get('FolderName', {}).get('value', game.app_name)
for game in self.core.get_game_list(False) if not game.is_dlc]
for game in shared.api_results.game_list if not game.is_dlc]
self.path_edit = PathEdit(
self.core.get_default_install_dir(),

View file

@ -90,9 +90,9 @@ class VerifyWorker(QRunnable):
if not self.core.is_installed(self.app_name):
logger.error(f'Game "{self.app_name}" is not installed')
return
logger.info(f'Loading installed manifest for "{self.app_name}"')
igame = self.core.get_installed_game(self.app_name)
logger.info(f'Loading installed manifest for "{igame.title}"')
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
if not manifest_data:
update_manifest(self.app_name, self.core)