1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Refine QueueWorker and implement worker_info for VerifyWorker and MoveWorker

This commit is contained in:
loathingKernel 2023-02-03 10:55:56 +02:00
parent 38710a0af1
commit 6b3a841378
7 changed files with 102 additions and 93 deletions

View file

@ -61,10 +61,6 @@ class GameInfo(QWidget):
if platform.system() == "Windows":
self.ui.lbl_grade.setVisible(False)
self.ui.grade.setVisible(False)
else:
self.steam_worker: SteamWorker = SteamWorker(self.core)
self.steam_worker.signals.rating.connect(self.ui.grade.setText)
self.steam_worker.setAutoDelete(False)
self.ui.game_actions_stack.setCurrentWidget(self.ui.installed_page)
@ -151,18 +147,18 @@ class GameInfo(QWidget):
self.verify_game(self.rgame)
def verify_game(self, rgame: RareGame):
worker = VerifyWorker(self.core, self.args, rgame)
worker.signals.progress.connect(self.__on_verify_progress)
worker.signals.result.connect(self.__on_verify_result)
worker.signals.error.connect(self.__on_verify_error)
self.ui.verify_stack.setCurrentWidget(self.ui.verify_progress_page)
verify_worker = VerifyWorker(self.core, self.args, rgame)
verify_worker.signals.progress.connect(self.__on_verify_progress)
verify_worker.signals.result.connect(self.__on_verify_result)
verify_worker.signals.error.connect(self.__on_verify_error)
self.ui.verify_progress.setValue(0)
self.rgame.__worker = verify_worker
self.verify_pool.start(verify_worker)
self.ui.move_button.setEnabled(False)
self.rcore.enqueue_worker(rgame, worker)
def verify_cleanup(self, rgame: RareGame):
rgame.__worker = None
if rgame is not self.rgame:
return
self.ui.verify_stack.setCurrentWidget(self.ui.verify_button_page)
self.ui.move_button.setEnabled(True)
self.ui.verify_button.setEnabled(True)
@ -257,7 +253,7 @@ class GameInfo(QWidget):
self.ui.move_progress.setValue(progress_int)
def start_copy_diff_drive(self):
copy_worker = MoveWorker(
worker = MoveWorker(
self.core,
install_path=self.rgame.igame.install_path,
dest_path=self.dest_path_with_suffix,
@ -265,10 +261,10 @@ class GameInfo(QWidget):
igame=self.rgame.igame,
)
copy_worker.signals.progress.connect(self.__on_move_progress)
copy_worker.signals.result.connect(self.set_new_game)
copy_worker.signals.error.connect(self.warn_no_space_left)
QThreadPool.globalInstance().start(copy_worker)
worker.signals.progress.connect(self.__on_move_progress)
worker.signals.result.connect(self.set_new_game)
worker.signals.error.connect(self.warn_no_space_left)
self.rcore.enqueue_worker(self.rgame, worker)
def move_helper_clean_up(self):
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
@ -310,67 +306,69 @@ class GameInfo(QWidget):
rgame = self.rcore.get_game(rgame)
if self.rgame is not None:
if (worker := self.rgame.worker) is not None:
if (worker := self.rgame.worker()) is not None:
if isinstance(worker, VerifyWorker):
try:
worker.signals.progress.disconnect(self.__on_verify_progress)
self.ui.verify_stack.setCurrentWidget(self.ui.verify_button_page)
except TypeError as e:
logger.warning(f"{self.rgame.app_name} verify worker: {e}")
if isinstance(worker, MoveWorker):
try:
worker.signals.progress.disconnect(self.__on_move_progress)
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
except TypeError as e:
logger.warning(f"{self.rgame.app_name} move worker: {e}")
self.rgame.signals.widget.update.disconnect(self.__update_ui)
self.rgame.signals.game.installed.disconnect(self.update_game)
self.rgame.signals.game.uninstalled.disconnect(self.update_game)
self.rgame = rgame
self.rgame = None
self.rgame.signals.widget.update.disconnect(self.__update_ui)
self.rgame.signals.game.installed.connect(self.update_game)
self.rgame.signals.game.uninstalled.connect(self.update_game)
if (worker := self.rgame.worker) is not None:
rgame.signals.widget.update.connect(self.__update_ui)
rgame.signals.game.installed.connect(self.update_game)
rgame.signals.game.uninstalled.connect(self.update_game)
if (worker := rgame.worker()) is not None:
if isinstance(worker, VerifyWorker):
self.ui.verify_stack.setCurrentWidget(self.ui.verify_progress_page)
self.ui.verify_progress.setValue(self.rgame.progress)
self.ui.verify_progress.setValue(rgame.progress)
worker.signals.progress.connect(self.__on_verify_progress)
else:
self.ui.verify_stack.setCurrentWidget(self.ui.verify_button_page)
if isinstance(worker, MoveWorker):
self.ui.move_stack.setCurrentWidget(self.ui.move_progress_page)
self.ui.move_progress.setValue(self.rgame.progress)
self.ui.move_progress.setValue(rgame.progress)
worker.signals.progress.connect(self.__on_move_progress)
else:
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
self.title.setTitle(self.rgame.app_title)
self.title.setTitle(rgame.app_title)
self.image.setPixmap(rgame.pixmap)
self.ui.app_name.setText(self.rgame.app_name)
self.ui.version.setText(self.rgame.version)
self.ui.dev.setText(self.rgame.developer)
self.ui.app_name.setText(rgame.app_name)
self.ui.version.setText(rgame.version)
self.ui.dev.setText(rgame.developer)
if self.rgame.igame:
self.ui.install_size.setText(get_size(self.rgame.igame.install_size))
self.ui.install_path.setText(self.rgame.igame.install_path)
self.ui.platform.setText(self.rgame.igame.platform)
if rgame.igame:
self.ui.install_size.setText(get_size(rgame.igame.install_size))
self.ui.install_path.setText(rgame.igame.install_path)
self.ui.platform.setText(rgame.igame.platform)
else:
self.ui.install_size.setText("N/A")
self.ui.install_path.setText("N/A")
self.ui.platform.setText("Windows")
self.ui.install_size.setEnabled(bool(self.rgame.igame))
self.ui.lbl_install_size.setEnabled(bool(self.rgame.igame))
self.ui.install_path.setEnabled(bool(self.rgame.igame))
self.ui.lbl_install_path.setEnabled(bool(self.rgame.igame))
self.ui.install_size.setEnabled(bool(rgame.igame))
self.ui.lbl_install_size.setEnabled(bool(rgame.igame))
self.ui.install_path.setEnabled(bool(rgame.igame))
self.ui.lbl_install_path.setEnabled(bool(rgame.igame))
self.ui.uninstall_button.setEnabled(bool(self.rgame.igame))
self.ui.verify_button.setEnabled(bool(self.rgame.igame))
self.ui.repair_button.setEnabled(bool(self.rgame.igame))
self.ui.uninstall_button.setEnabled(bool(rgame.igame))
self.ui.verify_button.setEnabled(bool(rgame.igame))
self.ui.repair_button.setEnabled(bool(rgame.igame))
if not self.rgame.is_installed or self.rgame.is_origin:
if not rgame.is_installed or rgame.is_origin:
self.ui.game_actions_stack.setCurrentWidget(self.ui.uninstalled_page)
if self.rgame.is_origin:
if rgame.is_origin:
self.ui.version.setText("N/A")
self.ui.version.setEnabled(False)
self.ui.install_button.setText(self.tr("Link to Origin/Launch"))
@ -379,34 +377,26 @@ class GameInfo(QWidget):
else:
if not self.args.offline:
self.ui.repair_button.setDisabled(
not os.path.exists(os.path.join(self.core.lgd.get_tmp_path(), f"{self.rgame.app_name}.repair"))
not os.path.exists(os.path.join(self.core.lgd.get_tmp_path(), f"{rgame.app_name}.repair"))
)
self.ui.game_actions_stack.setCurrentWidget(self.ui.installed_page)
grade_visible = not self.rgame.is_unreal and platform.system() != "Windows"
grade_visible = not rgame.is_unreal and platform.system() != "Windows"
self.ui.grade.setVisible(grade_visible)
self.ui.lbl_grade.setVisible(grade_visible)
if platform.system() != "Windows" and not self.rgame.is_unreal:
if platform.system() != "Windows" and not rgame.is_unreal:
self.ui.grade.setText(self.tr("Loading"))
self.steam_worker.set_app_name(self.rgame.app_name)
QThreadPool.globalInstance().start(self.steam_worker)
# TODO: Handle result emitted after quickly changing between game information
steam_worker: SteamWorker = SteamWorker(self.core, rgame.app_name)
steam_worker.signals.rating.connect(self.ui.grade.setText)
QThreadPool.globalInstance().start(steam_worker)
# If the game that is currently moving matches with the current app_name, we show the progressbar.
# Otherwhise, we show the move tool button.
if self.rgame.igame is not None:
if self.game_moving == self.rgame.app_name:
self.ui.move_stack.setCurrentWidget(self.ui.move_progress_page)
else:
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
# If a game is verifying or moving, disable both verify and moving buttons.
if rgame.worker is not None:
self.ui.verify_button.setEnabled(False)
self.ui.move_button.setEnabled(False)
if self.is_moving:
self.ui.move_button.setEnabled(False)
self.ui.verify_button.setEnabled(False)
self.ui.verify_button.setEnabled(rgame.is_idle)
self.ui.move_button.setEnabled(rgame.is_idle)
self.move_game_pop_up.update_game(rgame.app_name)
self.rgame = rgame

View file

@ -132,13 +132,13 @@ class RareGame(QObject):
def __on_progress_update(self, progress: int):
self.progress = progress
@property
def worker(self) -> Optional[QRunnable]:
return self.__worker
@worker.setter
def worker(self, worker: Optional[QRunnable]):
def set_worker(self, worker: Optional[QRunnable]):
self.__worker = worker
if worker is None:
self.state = RareGame.State.IDLE
@property
def state(self) -> 'RareGame.State':

View file

@ -15,6 +15,7 @@ from rare.models.game import RareGame, RareEosOverlay
from rare.models.signals import GlobalSignals
from .workers import QueueWorker, VerifyWorker, MoveWorker
from .image_manager import ImageManager
from .workers.worker import QueueWorkerInfo
logger = getLogger("RareCore")
@ -52,13 +53,16 @@ class RareCore(QObject):
rgame.state = RareGame.State.VERIFYING
if isinstance(worker, MoveWorker):
rgame.state = RareGame.State.MOVING
rgame.worker = worker
worker.feedback.started.connect(self.__signals.application.update_statubar)
rgame.set_worker(worker)
worker.feedback.started.connect(self.__signals.application.update_statusbar)
worker.feedback.finished.connect(lambda: rgame.set_worker(None))
worker.feedback.finished.connect(lambda: self.queue_workers.remove(worker))
worker.feedback.finished.connect(self.__signals.application.update_statusbar)
self.queue_workers.append(worker)
self.queue_threadpool.start(worker, 0)
self.queue_threadpool.start(worker, priority=0)
self.__signals.application.update_statusbar.emit()
def queue_info(self) -> List:
def queue_info(self) -> List[QueueWorkerInfo]:
return [w.worker_info() for w in self.queue_workers]
@staticmethod

View file

@ -7,7 +7,7 @@ from legendary.lfs.utils import validate_files
from legendary.models.game import VerifyResult, InstalledGame
from rare.lgndr.core import LegendaryCore
from .worker import QueueWorker
from .worker import QueueWorker, QueueWorkerInfo
# noinspection PyUnresolvedReferences
@ -37,8 +37,10 @@ class MoveWorker(QueueWorker):
self.file_list = None
self.total: int = 0
def worker_info(self):
return None
def worker_info(self) -> QueueWorkerInfo:
return QueueWorkerInfo(
app_name=self.rgame.app_name, app_title=self.rgame.app_title, worker_type="Move", state=self.state
)
def run_real(self):
root_directory = Path(self.install_path)

View file

@ -1,5 +1,6 @@
import os
import sys
import time
from argparse import Namespace
from logging import getLogger
@ -10,7 +11,7 @@ from rare.lgndr.core import LegendaryCore
from rare.lgndr.glue.arguments import LgndrVerifyGameArgs
from rare.lgndr.glue.monkeys import LgndrIndirectStatus
from rare.models.game import RareGame
from .worker import QueueWorker
from .worker import QueueWorker, QueueWorkerInfo
logger = getLogger("VerifyWorker")
@ -21,8 +22,8 @@ class VerifyWorker(QueueWorker):
result = pyqtSignal(RareGame, bool, int, int)
error = pyqtSignal(RareGame, str)
num: int = 0
total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
# num: int = 0
# total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
def __init__(self, core: LegendaryCore, args: Namespace, rgame: RareGame):
super(VerifyWorker, self).__init__()
@ -35,8 +36,10 @@ class VerifyWorker(QueueWorker):
self.rgame.signals.progress.update.emit(num * 100 // total)
self.signals.progress.emit(self.rgame, num, total, percentage, speed)
def worker_info(self):
return None
def worker_info(self) -> QueueWorkerInfo:
return QueueWorkerInfo(
app_name=self.rgame.app_name, app_title=self.rgame.app_title, worker_type="Verify", state=self.state
)
def run_real(self):
self.rgame.signals.progress.start.emit()

View file

@ -1,5 +1,6 @@
import sys
from abc import abstractmethod
from dataclasses import dataclass
from enum import IntEnum
from typing import Optional
@ -42,6 +43,21 @@ class Worker(QRunnable):
self.signals.deleteLater()
class QueueWorkerState(IntEnum):
UNDEFINED = 0
QUEUED = 1
ACTIVE = 2
@dataclass
class QueueWorkerInfo:
app_name: str
app_title: str
worker_type: str
state: QueueWorkerState
progress: int = 0
class QueueWorker(Worker):
"""
Base queueable worker class
@ -53,11 +69,6 @@ class QueueWorker(Worker):
to the `QueueWorker.signals` attribute, implement `QueueWorker.run_real()` and `QueueWorker.worker_info()`
"""
class State(IntEnum):
UNDEFINED = 0
QUEUED = 1
ACTIVE = 2
class Signals(QObject):
started = pyqtSignal()
finished = pyqtSignal()
@ -65,16 +76,18 @@ class QueueWorker(Worker):
def __init__(self):
super(QueueWorker, self).__init__()
self.feedback = QueueWorker.Signals()
self.state = QueueWorker.State.QUEUED
self.state = QueueWorkerState.QUEUED
@pyqtSlot()
def run(self):
self.state = QueueWorker.State.ACTIVE
self.state = QueueWorkerState.ACTIVE
self.feedback.started.emit()
super(QueueWorker, self).run()
self.feedback.finished.emit()
self.feedback.deleteLater()
@abstractmethod
def worker_info(self):
pass
def worker_info(self) -> QueueWorkerInfo:
pass

View file

@ -8,22 +8,22 @@ from PyQt5.QtCore import pyqtSignal, QRunnable, QObject, QCoreApplication
from rare.lgndr.core import LegendaryCore
from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton
from rare.shared.workers import Worker
from rare.utils.paths import data_dir, cache_dir
replace_chars = ",;.:-_ "
url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"
class SteamWorker(QRunnable):
class SteamWorker(Worker):
class Signals(QObject):
rating = pyqtSignal(str)
app_name: str = ""
def __init__(self, core: LegendaryCore):
def __init__(self, core: LegendaryCore, app_name: str):
super(SteamWorker, self).__init__()
self.signals = SteamWorker.Signals()
self.core = core
self.app_name = app_name
_tr = QCoreApplication.translate
self.ratings = {
"platinum": _tr("SteamWorker", "Platinum"),
@ -35,10 +35,7 @@ class SteamWorker(QRunnable):
"pending": _tr("SteamWorker", "Could not get grade"),
}
def set_app_name(self, app_name: str):
self.app_name = app_name
def run(self) -> None:
def run_real(self) -> None:
self.signals.rating.emit(
self.ratings.get(get_rating(self.app_name), self.ratings["fail"])
)