GameInfo: Offer to also update the game after a verification if there is one
This commit is contained in:
parent
785aaf648e
commit
e5c7b029ff
|
@ -25,7 +25,7 @@ from rare.utils import config_helper
|
|||
class InstallDialog(QDialog, Ui_InstallDialog):
|
||||
result_ready = pyqtSignal(InstallQueueItemModel)
|
||||
|
||||
def __init__(self, dl_item: InstallQueueItemModel, update=False, silent=False, parent=None):
|
||||
def __init__(self, dl_item: InstallQueueItemModel, update=False, repair=False, silent=False, parent=None):
|
||||
super(InstallDialog, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose, True)
|
||||
|
@ -44,6 +44,7 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
|||
self.game_path = self.game.metadata.get("customAttributes", {}).get("FolderName", {}).get("value", "")
|
||||
|
||||
self.update = update
|
||||
self.repair = repair
|
||||
self.silent = silent
|
||||
|
||||
self.options_changed = False
|
||||
|
|
|
@ -85,7 +85,7 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
if self.args.offline:
|
||||
self.repair_button.setDisabled(True)
|
||||
else:
|
||||
self.repair_button.clicked.connect(lambda: self.repair(self.igame))
|
||||
self.repair_button.clicked.connect(self.repair)
|
||||
|
||||
self.install_button.clicked.connect(lambda: self.game_utils.launch_game(self.game.app_name))
|
||||
|
||||
|
@ -117,46 +117,78 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
self.game_utils.update_list.emit(self.game.app_name)
|
||||
self.uninstalled.emit(self.game.app_name)
|
||||
|
||||
@pyqtSlot(InstalledGame)
|
||||
def repair(self, igame: InstalledGame):
|
||||
game = self.core.get_game(igame.app_name)
|
||||
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f"{igame.app_name}.repair")
|
||||
@pyqtSlot()
|
||||
def repair(self):
|
||||
""" This function is to be called from the button only """
|
||||
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f"{self.igame.app_name}.repair")
|
||||
if not os.path.exists(repair_file):
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Warning",
|
||||
self.tr("Error - {}").format(self.igame.title),
|
||||
self.tr(
|
||||
"Repair file does not exist or game does not need a repair. Please verify game first"
|
||||
),
|
||||
)
|
||||
return
|
||||
update = igame.version != game.app_version(igame.platform)
|
||||
self.repair_game(self.igame)
|
||||
|
||||
def repair_game(self, igame: InstalledGame):
|
||||
game = self.core.get_game(igame.app_name)
|
||||
ans = False
|
||||
if igame.version != game.app_version(igame.platform):
|
||||
ans = QMessageBox.question(
|
||||
self,
|
||||
self.tr("Repair and update?"),
|
||||
self.tr(
|
||||
"There is an update for <b>{}</b> from <b>{}</b> to <b>{}</b>."
|
||||
"Do you want to update the game while repairing it?"
|
||||
).format(igame.title, igame.version, game.app_version(igame.platform)),
|
||||
) == QMessageBox.Yes
|
||||
self.signals.install_game.emit(
|
||||
InstallOptionsModel(app_name=self.game.app_name, repair_mode=True, repair_and_update=update, update=True)
|
||||
InstallOptionsModel(
|
||||
app_name=igame.app_name, repair_mode=True, repair_and_update=ans, update=True
|
||||
)
|
||||
)
|
||||
|
||||
@pyqtSlot()
|
||||
def verify(self):
|
||||
""" This function is to be called from the button only """
|
||||
if not os.path.exists(self.igame.install_path):
|
||||
logger.error("Path does not exist")
|
||||
logger.error(f"Installation path {self.igame.install_path} for {self.igame.title} does not exist")
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Warning",
|
||||
self.tr("Installation path of {} does not exist. Cannot verify").format(self.igame.title),
|
||||
self.tr("Error - {}").format(self.igame.title),
|
||||
self.tr("Installation path for <b>{}</b> does not exist. Cannot continue.").format(self.igame.title),
|
||||
)
|
||||
return
|
||||
self.verify_game(self.igame)
|
||||
|
||||
def verify_game(self, igame: InstalledGame):
|
||||
self.verify_widget.setCurrentIndex(1)
|
||||
verify_worker = VerifyWorker(self.game.app_name)
|
||||
verify_worker = VerifyWorker(igame.app_name)
|
||||
verify_worker.signals.status.connect(self.verify_status)
|
||||
verify_worker.signals.result.connect(self.verify_result)
|
||||
verify_worker.signals.error.connect(self.verify_error)
|
||||
self.verify_progress.setValue(0)
|
||||
self.verify_threads[self.game.app_name] = verify_worker
|
||||
self.verify_threads[igame.app_name] = verify_worker
|
||||
self.verify_pool.start(verify_worker)
|
||||
self.move_button.setEnabled(False)
|
||||
|
||||
def verify_cleanup(self, app_name: str):
|
||||
self.verify_widget.setCurrentIndex(0)
|
||||
self.verify_threads.pop(app_name)
|
||||
self.move_button.setEnabled(True)
|
||||
self.verify_button.setEnabled(True)
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def verify_error(self, app_name, message):
|
||||
pass
|
||||
self.verify_cleanup(app_name)
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
self.tr("Error - {}").format(igame.title),
|
||||
message
|
||||
)
|
||||
|
||||
@pyqtSlot(str, int, int, float, float)
|
||||
def verify_status(self, app_name, num, total, percentage, speed):
|
||||
|
@ -166,36 +198,30 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
|
||||
@pyqtSlot(str, bool, int, int)
|
||||
def verify_result(self, app_name, success, failed, missing):
|
||||
self.verify_cleanup(app_name)
|
||||
self.repair_button.setDisabled(success)
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
if success:
|
||||
QMessageBox.information(
|
||||
self,
|
||||
self.tr("Summary - {}").format(igame.title),
|
||||
self.tr("Game has been verified successfully. No missing or corrupt files found").format(igame.title),
|
||||
self.tr("<b>{}</b> has been verified successfully. "
|
||||
"No missing or corrupt files found").format(igame.title),
|
||||
)
|
||||
if igame.needs_verification:
|
||||
igame.needs_verification = False
|
||||
self.core.lgd.set_installed_game(igame.app_name, igame)
|
||||
self.verification_finished.emit(igame)
|
||||
elif failed == missing == -1:
|
||||
QMessageBox.warning(self, self.tr("Warning - {}").format(igame.title), self.tr("Something went wrong"))
|
||||
|
||||
self.verification_finished.emit(igame)
|
||||
else:
|
||||
ans = QMessageBox.question(
|
||||
self,
|
||||
self.tr("Summary - {}").format(igame.title),
|
||||
self.tr(
|
||||
"Verification failed, {} file(s) corrupted, {} file(s) are missing. Do you want to repair them?"
|
||||
"Verification failed, <b>{}</b> file(s) corrupted, <b>{}</b> file(s) are missing. "
|
||||
"Do you want to repair them?"
|
||||
).format(failed, missing),
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes,
|
||||
)
|
||||
if ans == QMessageBox.Yes:
|
||||
self.repair(igame)
|
||||
self.verify_widget.setCurrentIndex(0)
|
||||
self.verify_threads.pop(app_name)
|
||||
self.move_button.setEnabled(True)
|
||||
self.verify_button.setEnabled(True)
|
||||
self.repair_game(igame)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def move_game(self, dest_path):
|
||||
|
@ -326,7 +352,9 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
self.uninstall_button.setDisabled(False)
|
||||
self.verify_button.setDisabled(False)
|
||||
if not self.args.offline:
|
||||
self.repair_button.setDisabled(False)
|
||||
self.repair_button.setDisabled(
|
||||
not os.path.exists(os.path.join(self.core.lgd.get_tmp_path(), f"{self.igame.app_name}.repair"))
|
||||
)
|
||||
self.game_actions_stack.setCurrentIndex(0)
|
||||
|
||||
try:
|
||||
|
|
|
@ -43,7 +43,7 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
minilayout.setSpacing(0)
|
||||
miniwidget.setLayout(minilayout)
|
||||
|
||||
self.title_label = ElideLabel(f"<h4>{self.game.app_title}</h4>", parent=miniwidget)
|
||||
self.title_label = ElideLabel(f"<b>{self.game.app_title}</b>", parent=miniwidget)
|
||||
self.title_label.setAlignment(Qt.AlignTop)
|
||||
self.title_label.setObjectName("game_widget")
|
||||
minilayout.addWidget(self.title_label, stretch=2)
|
||||
|
|
|
@ -29,7 +29,7 @@ class UninstalledIconWidget(BaseUninstalledWidget):
|
|||
minilayout.setSpacing(0)
|
||||
miniwidget.setLayout(minilayout)
|
||||
|
||||
self.title_label = ElideLabel(f"<h4>{game.app_title}</h4>", parent=miniwidget)
|
||||
self.title_label = ElideLabel(f"<b>{game.app_title}</b>", parent=miniwidget)
|
||||
self.title_label.setAlignment(Qt.AlignTop)
|
||||
self.title_label.setObjectName("game_widget")
|
||||
minilayout.addWidget(self.title_label, stretch=2)
|
||||
|
|
|
@ -8,7 +8,7 @@ from legendary.core import LegendaryCore
|
|||
from rare.lgndr.api_monkeys import LgndrIndirectStatus
|
||||
from rare.lgndr.api_arguments import LgndrVerifyGameArgs, LgndrUninstallGameArgs
|
||||
from rare.lgndr.api_exception import LgndrException
|
||||
from rare.shared import LegendaryCLISingleton, LegendaryCoreSingleton
|
||||
from rare.shared import LegendaryCLISingleton, LegendaryCoreSingleton, ArgumentsSingleton
|
||||
from rare.utils import config_helper
|
||||
|
||||
logger = getLogger("Legendary Utils")
|
||||
|
@ -90,6 +90,7 @@ class VerifyWorker(QRunnable):
|
|||
self.setAutoDelete(True)
|
||||
self.cli = LegendaryCLISingleton()
|
||||
self.core = LegendaryCoreSingleton()
|
||||
self.args = ArgumentsSingleton()
|
||||
self.app_name = app_name
|
||||
|
||||
def status_callback(self, num: int, total: int, percentage: float, speed: float):
|
||||
|
@ -100,15 +101,37 @@ class VerifyWorker(QRunnable):
|
|||
args = LgndrVerifyGameArgs(app_name=self.app_name,
|
||||
indirect_status=status,
|
||||
verify_stdout=self.status_callback)
|
||||
# TODO: offer this as an alternative when manifest doesn't exist
|
||||
# TODO: requires the client to be online. To do it this way, we need to
|
||||
# TODO: somehow detect the error and offer a dialog in which case `verify_games` is
|
||||
# TODO: re-run with `repair_mode` and `repair_online`
|
||||
# FIXME: This will crash in offline mode. Offline mode needs a re-thinking in general.
|
||||
|
||||
# lk: first pass, verify with the current manifest
|
||||
repair_mode = False
|
||||
result = self.cli.verify_game(
|
||||
args, print_command=False, repair_mode=True, repair_online=True)
|
||||
# success, failed, missing = self.cli.verify_game(args, print_command=False)
|
||||
if result:
|
||||
self.signals.result.emit(self.app_name, not any(result), *result)
|
||||
else:
|
||||
self.signals.error.emit(self.app_name, status.message)
|
||||
args, print_command=False, repair_mode=repair_mode, repair_online=not self.args.offline
|
||||
)
|
||||
if result is None:
|
||||
# lk: second pass with the latest manifest
|
||||
# lk: this happens if the manifest was not found and repair_mode was not requested
|
||||
# lk: we already have checked if the directory exists before starting the worker
|
||||
try:
|
||||
# lk: this try-except block handles the exception caused by a missing manifest
|
||||
# lk: and is raised only in the case we are offline
|
||||
repair_mode = True
|
||||
result = self.cli.verify_game(
|
||||
args, print_command=False, repair_mode=repair_mode, repair_online=not self.args.offline
|
||||
)
|
||||
if result is None:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
self.signals.error.emit(self.app_name, status.message)
|
||||
return
|
||||
|
||||
success = result is not None and not any(result)
|
||||
if success:
|
||||
# lk: if verification was successful we delete the repair file and run the clean procedure
|
||||
# lk: this could probably be cut down to what is relevant for this use-case and skip the `cli` call
|
||||
igame = self.core.get_installed_game(self.app_name)
|
||||
game = self.core.get_game(self.app_name, platform=igame.platform)
|
||||
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
|
||||
self.cli.clean_post_install(game=game, igame=igame, repair=True, repair_file=repair_file)
|
||||
|
||||
self.signals.result.emit(self.app_name, success, *result)
|
||||
|
||||
|
|
Loading…
Reference in a new issue