Workers: Implement wrapper QueueWorker class prototype for queueable workers
RareCore: Impelement base worker queue
This commit is contained in:
parent
07ef43b13e
commit
6800b7e9ab
8 changed files with 135 additions and 45 deletions
|
@ -27,8 +27,7 @@ from rare.shared import (
|
||||||
ImageManagerSingleton,
|
ImageManagerSingleton,
|
||||||
)
|
)
|
||||||
from rare.shared.image_manager import ImageSize
|
from rare.shared.image_manager import ImageSize
|
||||||
from rare.shared.workers.verify import VerifyWorker
|
from rare.shared.workers import VerifyWorker, MoveWorker
|
||||||
from rare.shared.workers.move import MoveWorker
|
|
||||||
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
|
||||||
from rare.utils.misc import get_size
|
from rare.utils.misc import get_size
|
||||||
from rare.utils.steam_grades import SteamWorker
|
from rare.utils.steam_grades import SteamWorker
|
||||||
|
@ -267,8 +266,8 @@ class GameInfo(QWidget):
|
||||||
)
|
)
|
||||||
|
|
||||||
copy_worker.signals.progress.connect(self.__on_move_progress)
|
copy_worker.signals.progress.connect(self.__on_move_progress)
|
||||||
copy_worker.signals.finished.connect(self.set_new_game)
|
copy_worker.signals.result.connect(self.set_new_game)
|
||||||
copy_worker.signals.no_space_left.connect(self.warn_no_space_left)
|
copy_worker.signals.error.connect(self.warn_no_space_left)
|
||||||
QThreadPool.globalInstance().start(copy_worker)
|
QThreadPool.globalInstance().start(copy_worker)
|
||||||
|
|
||||||
def move_helper_clean_up(self):
|
def move_helper_clean_up(self):
|
||||||
|
@ -300,6 +299,10 @@ class GameInfo(QWidget):
|
||||||
def show_menu_after_browse(self):
|
def show_menu_after_browse(self):
|
||||||
self.ui.move_button.showMenu()
|
self.ui.move_button.showMenu()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def __update_ui(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
@pyqtSlot(RareGame)
|
@pyqtSlot(RareGame)
|
||||||
def update_game(self, rgame: Union[RareGame, str]):
|
def update_game(self, rgame: Union[RareGame, str]):
|
||||||
|
@ -307,24 +310,39 @@ class GameInfo(QWidget):
|
||||||
rgame = self.rcore.get_game(rgame)
|
rgame = self.rcore.get_game(rgame)
|
||||||
|
|
||||||
if self.rgame is not None:
|
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):
|
if isinstance(worker, VerifyWorker):
|
||||||
try:
|
try:
|
||||||
worker.signals.progress.disconnect(self.__on_verify_progress)
|
worker.signals.progress.disconnect(self.__on_verify_progress)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
logger.warning(f"{self.rgame.app_title} verify worker: {e}")
|
logger.warning(f"{self.rgame.app_name} verify worker: {e}")
|
||||||
|
if isinstance(worker, MoveWorker):
|
||||||
|
try:
|
||||||
|
worker.signals.progress.disconnect(self.__on_move_progress)
|
||||||
|
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.installed.disconnect(self.update_game)
|
||||||
self.rgame.signals.game.uninstalled.disconnect(self.update_game)
|
self.rgame.signals.game.uninstalled.disconnect(self.update_game)
|
||||||
|
|
||||||
self.rgame = rgame
|
self.rgame = rgame
|
||||||
|
|
||||||
|
self.rgame.signals.widget.update.disconnect(self.__update_ui)
|
||||||
self.rgame.signals.game.installed.connect(self.update_game)
|
self.rgame.signals.game.installed.connect(self.update_game)
|
||||||
self.rgame.signals.game.uninstalled.connect(self.update_game)
|
self.rgame.signals.game.uninstalled.connect(self.update_game)
|
||||||
if (worker := self.rgame.__worker) is not None:
|
if (worker := self.rgame.worker) is not None:
|
||||||
if isinstance(worker, VerifyWorker):
|
if isinstance(worker, VerifyWorker):
|
||||||
self.ui.verify_stack.setCurrentWidget(self.ui.verify_progress_page)
|
self.ui.verify_stack.setCurrentWidget(self.ui.verify_progress_page)
|
||||||
self.ui.verify_progress.setValue(self.rgame.progress)
|
self.ui.verify_progress.setValue(self.rgame.progress)
|
||||||
worker.signals.progress.connect(self.__on_verify_progress)
|
worker.signals.progress.connect(self.__on_verify_progress)
|
||||||
else:
|
else:
|
||||||
self.ui.verify_stack.setCurrentWidget(self.ui.verify_button_page)
|
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)
|
||||||
|
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(self.rgame.app_title)
|
||||||
self.image.setPixmap(rgame.pixmap)
|
self.image.setPixmap(rgame.pixmap)
|
||||||
|
@ -383,7 +401,7 @@ class GameInfo(QWidget):
|
||||||
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
|
self.ui.move_stack.setCurrentWidget(self.ui.move_button_page)
|
||||||
|
|
||||||
# If a game is verifying or moving, disable both verify and moving buttons.
|
# If a game is verifying or moving, disable both verify and moving buttons.
|
||||||
if rgame.__worker is not None:
|
if rgame.worker is not None:
|
||||||
self.ui.verify_button.setEnabled(False)
|
self.ui.verify_button.setEnabled(False)
|
||||||
self.ui.move_button.setEnabled(False)
|
self.ui.move_button.setEnabled(False)
|
||||||
if self.is_moving:
|
if self.is_moving:
|
||||||
|
|
|
@ -14,8 +14,6 @@ from rare.lgndr.core import LegendaryCore
|
||||||
from rare.models.install import InstallOptionsModel, UninstallOptionsModel
|
from rare.models.install import InstallOptionsModel, UninstallOptionsModel
|
||||||
from rare.shared.game_process import GameProcess
|
from rare.shared.game_process import GameProcess
|
||||||
from rare.shared.image_manager import ImageManager
|
from rare.shared.image_manager import ImageManager
|
||||||
from rare.shared.workers.move import MoveWorker
|
|
||||||
from rare.shared.workers.verify import VerifyWorker
|
|
||||||
from rare.utils.misc import get_rare_executable
|
from rare.utils.misc import get_rare_executable
|
||||||
from rare.utils.paths import data_dir
|
from rare.utils.paths import data_dir
|
||||||
|
|
||||||
|
@ -118,10 +116,11 @@ class RareGame(QObject):
|
||||||
if self.has_update:
|
if self.has_update:
|
||||||
logger.info(f"Update available for game: {self.app_name} ({self.app_title})")
|
logger.info(f"Update available for game: {self.app_name} ({self.app_title})")
|
||||||
|
|
||||||
self.progress: int = 0
|
|
||||||
self.__worker: Optional[QRunnable] = None
|
self.__worker: Optional[QRunnable] = None
|
||||||
|
|
||||||
self.__state = RareGame.State.IDLE
|
self.__state = RareGame.State.IDLE
|
||||||
|
self.progress: int = 0
|
||||||
|
self.signals.progress.start.connect(lambda: self.__on_progress_update(0))
|
||||||
|
self.signals.progress.update.connect(self.__on_progress_update)
|
||||||
|
|
||||||
self.game_process = GameProcess(self.game)
|
self.game_process = GameProcess(self.game)
|
||||||
self.game_process.launched.connect(self.__game_launched)
|
self.game_process.launched.connect(self.__game_launched)
|
||||||
|
@ -130,18 +129,15 @@ class RareGame(QObject):
|
||||||
self.game_process.connect_to_server(on_startup=True)
|
self.game_process.connect_to_server(on_startup=True)
|
||||||
# self.grant_date(True)
|
# self.grant_date(True)
|
||||||
|
|
||||||
|
def __on_progress_update(self, progress: int):
|
||||||
|
self.progress = progress
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def worker(self) -> Optional[QRunnable]:
|
def worker(self) -> Optional[QRunnable]:
|
||||||
return self.__worker
|
return self.__worker
|
||||||
|
|
||||||
@worker.setter
|
@worker.setter
|
||||||
def worker(self, worker: Optional[QRunnable]):
|
def worker(self, worker: Optional[QRunnable]):
|
||||||
if worker is None:
|
|
||||||
self.state = RareGame.State.IDLE
|
|
||||||
if isinstance(worker, VerifyWorker):
|
|
||||||
self.state = RareGame.State.VERIFYING
|
|
||||||
if isinstance(worker, MoveWorker):
|
|
||||||
self.state = RareGame.State.MOVING
|
|
||||||
self.__worker = worker
|
self.__worker = worker
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -497,21 +493,13 @@ class RareGame(QObject):
|
||||||
def refresh_pixmap(self):
|
def refresh_pixmap(self):
|
||||||
self.image_manager.download_image(self.game, self.set_pixmap, 0, True)
|
self.image_manager.download_image(self.game, self.set_pixmap, 0, True)
|
||||||
|
|
||||||
def start_progress(self):
|
def install(self) -> bool:
|
||||||
self.signals.progress.start.emit()
|
if not self.is_idle:
|
||||||
|
return False
|
||||||
def update_progress(self, progress: int):
|
|
||||||
self.progress = progress
|
|
||||||
self.signals.progress.update.emit(progress)
|
|
||||||
|
|
||||||
def finish_progress(self, fail: bool, miss: int, app: str):
|
|
||||||
self.set_installed(True)
|
|
||||||
self.signals.progress.finish.emit(fail)
|
|
||||||
|
|
||||||
def install(self):
|
|
||||||
self.signals.game.install.emit(
|
self.signals.game.install.emit(
|
||||||
InstallOptionsModel(app_name=self.app_name)
|
InstallOptionsModel(app_name=self.app_name)
|
||||||
)
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
def repair(self, repair_and_update):
|
def repair(self, repair_and_update):
|
||||||
self.signals.game.install.emit(
|
self.signals.game.install.emit(
|
||||||
|
@ -520,10 +508,13 @@ class RareGame(QObject):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def uninstall(self):
|
def uninstall(self) -> bool:
|
||||||
|
if not self.is_idle:
|
||||||
|
return False
|
||||||
self.signals.game.uninstall.emit(
|
self.signals.game.uninstall.emit(
|
||||||
UninstallOptionsModel(app_name=self.app_name)
|
UninstallOptionsModel(app_name=self.app_name)
|
||||||
)
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
def launch(
|
def launch(
|
||||||
self,
|
self,
|
||||||
|
@ -532,9 +523,9 @@ class RareGame(QObject):
|
||||||
wine_bin: Optional[str] = None,
|
wine_bin: Optional[str] = None,
|
||||||
wine_pfx: Optional[str] = None,
|
wine_pfx: Optional[str] = None,
|
||||||
ask_sync_saves: bool = False,
|
ask_sync_saves: bool = False,
|
||||||
):
|
) -> bool:
|
||||||
if not self.can_launch:
|
if not self.can_launch:
|
||||||
return
|
return False
|
||||||
|
|
||||||
cmd_line = get_rare_executable()
|
cmd_line = get_rare_executable()
|
||||||
executable, args = cmd_line[0], cmd_line[1:]
|
executable, args = cmd_line[0], cmd_line[1:]
|
||||||
|
@ -554,6 +545,7 @@ class RareGame(QObject):
|
||||||
QProcess.startDetached(executable, args)
|
QProcess.startDetached(executable, args)
|
||||||
logger.info(f"Start new Process: ({executable} {' '.join(args)})")
|
logger.info(f"Start new Process: ({executable} {' '.join(args)})")
|
||||||
self.game_process.connect_to_server(on_startup=False)
|
self.game_process.connect_to_server(on_startup=False)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class RareEosOverlay(QObject):
|
class RareEosOverlay(QObject):
|
||||||
|
|
|
@ -19,6 +19,8 @@ class GlobalSignals:
|
||||||
overlay_installed = pyqtSignal()
|
overlay_installed = pyqtSignal()
|
||||||
# none
|
# none
|
||||||
update_tray = pyqtSignal()
|
update_tray = pyqtSignal()
|
||||||
|
# none
|
||||||
|
update_statusbar = pyqtSignal()
|
||||||
|
|
||||||
class GameSignals(QObject):
|
class GameSignals(QObject):
|
||||||
# model
|
# model
|
||||||
|
|
|
@ -3,9 +3,9 @@ import os
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from typing import Optional, Dict, Iterator, Callable
|
from typing import Optional, Dict, Iterator, Callable, List
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject
|
from PyQt5.QtCore import QObject, QThreadPool
|
||||||
from legendary.lfs.eos import EOSOverlayApp
|
from legendary.lfs.eos import EOSOverlayApp
|
||||||
from legendary.models.game import Game, SaveGameFile
|
from legendary.models.game import Game, SaveGameFile
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ from rare.lgndr.core import LegendaryCore
|
||||||
from rare.models.apiresults import ApiResults
|
from rare.models.apiresults import ApiResults
|
||||||
from rare.models.game import RareGame, RareEosOverlay
|
from rare.models.game import RareGame, RareEosOverlay
|
||||||
from rare.models.signals import GlobalSignals
|
from rare.models.signals import GlobalSignals
|
||||||
|
from .workers import QueueWorker, VerifyWorker, MoveWorker
|
||||||
from .image_manager import ImageManager
|
from .image_manager import ImageManager
|
||||||
|
|
||||||
logger = getLogger("RareCore")
|
logger = getLogger("RareCore")
|
||||||
|
@ -36,12 +37,30 @@ class RareCore(QObject):
|
||||||
self.core(init=True)
|
self.core(init=True)
|
||||||
self.image_manager(init=True)
|
self.image_manager(init=True)
|
||||||
|
|
||||||
|
self.queue_workers: List[QueueWorker] = []
|
||||||
|
self.queue_threadpool = QThreadPool()
|
||||||
|
self.queue_threadpool.setMaxThreadCount(2)
|
||||||
|
|
||||||
self.__games: Dict[str, RareGame] = {}
|
self.__games: Dict[str, RareGame] = {}
|
||||||
|
|
||||||
self.__eos_overlay_rgame = RareEosOverlay(self.__core, self.__image_manager, EOSOverlayApp)
|
self.__eos_overlay_rgame = RareEosOverlay(self.__core, self.__image_manager, EOSOverlayApp)
|
||||||
|
|
||||||
RareCore._instance = self
|
RareCore._instance = self
|
||||||
|
|
||||||
|
def enqueue_worker(self, rgame: RareGame, worker: QueueWorker):
|
||||||
|
if isinstance(worker, VerifyWorker):
|
||||||
|
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)
|
||||||
|
worker.feedback.finished.connect(lambda: self.queue_workers.remove(worker))
|
||||||
|
self.queue_workers.append(worker)
|
||||||
|
self.queue_threadpool.start(worker, 0)
|
||||||
|
|
||||||
|
def queue_info(self) -> List:
|
||||||
|
return [w.worker_info() for w in self.queue_workers]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def instance() -> 'RareCore':
|
def instance() -> 'RareCore':
|
||||||
if RareCore._instance is None:
|
if RareCore._instance is None:
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
from .install_info import InstallInfoWorker
|
||||||
|
from .move import MoveWorker
|
||||||
|
from .uninstall import UninstallWorker
|
||||||
|
from .verify import VerifyWorker
|
||||||
|
from .worker import Worker, QueueWorker
|
|
@ -2,20 +2,20 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QRunnable, QObject
|
from PyQt5.QtCore import pyqtSignal, QObject
|
||||||
from legendary.lfs.utils import validate_files
|
from legendary.lfs.utils import validate_files
|
||||||
from legendary.models.game import VerifyResult, InstalledGame
|
from legendary.models.game import VerifyResult, InstalledGame
|
||||||
|
|
||||||
from rare.lgndr.core import LegendaryCore
|
from rare.lgndr.core import LegendaryCore
|
||||||
from .worker import Worker
|
from .worker import QueueWorker
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
class MoveWorker(Worker):
|
class MoveWorker(QueueWorker):
|
||||||
class Signals(QObject):
|
class Signals(QObject):
|
||||||
progress = pyqtSignal(int)
|
progress = pyqtSignal(int)
|
||||||
finished = pyqtSignal(str)
|
result = pyqtSignal(str)
|
||||||
no_space_left = pyqtSignal()
|
error = pyqtSignal()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -37,6 +37,9 @@ class MoveWorker(Worker):
|
||||||
self.file_list = None
|
self.file_list = None
|
||||||
self.total: int = 0
|
self.total: int = 0
|
||||||
|
|
||||||
|
def worker_info(self):
|
||||||
|
return None
|
||||||
|
|
||||||
def run_real(self):
|
def run_real(self):
|
||||||
root_directory = Path(self.install_path)
|
root_directory = Path(self.install_path)
|
||||||
self.source_size = sum(f.stat().st_size for f in root_directory.glob("**/*") if f.is_file())
|
self.source_size = sum(f.stat().st_size for f in root_directory.glob("**/*") if f.is_file())
|
||||||
|
|
|
@ -10,12 +10,12 @@ from rare.lgndr.core import LegendaryCore
|
||||||
from rare.lgndr.glue.arguments import LgndrVerifyGameArgs
|
from rare.lgndr.glue.arguments import LgndrVerifyGameArgs
|
||||||
from rare.lgndr.glue.monkeys import LgndrIndirectStatus
|
from rare.lgndr.glue.monkeys import LgndrIndirectStatus
|
||||||
from rare.models.game import RareGame
|
from rare.models.game import RareGame
|
||||||
from .worker import Worker
|
from .worker import QueueWorker
|
||||||
|
|
||||||
logger = getLogger("VerifyWorker")
|
logger = getLogger("VerifyWorker")
|
||||||
|
|
||||||
|
|
||||||
class VerifyWorker(Worker):
|
class VerifyWorker(QueueWorker):
|
||||||
class Signals(QObject):
|
class Signals(QObject):
|
||||||
progress = pyqtSignal(RareGame, int, int, float, float)
|
progress = pyqtSignal(RareGame, int, int, float, float)
|
||||||
result = pyqtSignal(RareGame, bool, int, int)
|
result = pyqtSignal(RareGame, bool, int, int)
|
||||||
|
@ -35,6 +35,9 @@ class VerifyWorker(Worker):
|
||||||
self.rgame.signals.progress.update.emit(num * 100 // total)
|
self.rgame.signals.progress.update.emit(num * 100 // total)
|
||||||
self.signals.progress.emit(self.rgame, num, total, percentage, speed)
|
self.signals.progress.emit(self.rgame, num, total, percentage, speed)
|
||||||
|
|
||||||
|
def worker_info(self):
|
||||||
|
return None
|
||||||
|
|
||||||
def run_real(self):
|
def run_real(self):
|
||||||
self.rgame.signals.progress.start.emit()
|
self.rgame.signals.progress.start.emit()
|
||||||
cli = LegendaryCLI(self.core)
|
cli = LegendaryCLI(self.core)
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
import sys
|
import sys
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
|
from enum import IntEnum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from PyQt5.QtCore import QRunnable, QObject, pyqtSlot
|
from PyQt5.QtCore import QRunnable, QObject, pyqtSlot, pyqtSignal
|
||||||
|
|
||||||
|
|
||||||
class Worker(QRunnable):
|
class Worker(QRunnable):
|
||||||
|
"""
|
||||||
|
Base QRunnable class.
|
||||||
|
|
||||||
|
This class provides a base for QRunnables with signals that are automatically deleted.
|
||||||
|
|
||||||
|
To use this class you have to assign the signals object of your concrete implementation
|
||||||
|
to the `Worker.signals` attribute and implement `Worker.run_real()`
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
sys.excepthook = sys.__excepthook__
|
sys.excepthook = sys.__excepthook__
|
||||||
super(Worker, self).__init__()
|
super(Worker, self).__init__()
|
||||||
|
@ -30,3 +40,41 @@ class Worker(QRunnable):
|
||||||
def run(self):
|
def run(self):
|
||||||
self.run_real()
|
self.run_real()
|
||||||
self.signals.deleteLater()
|
self.signals.deleteLater()
|
||||||
|
|
||||||
|
|
||||||
|
class QueueWorker(Worker):
|
||||||
|
"""
|
||||||
|
Base queueable worker class
|
||||||
|
|
||||||
|
This class is a specialization of the `Worker` class. It provides feedback signals to know
|
||||||
|
if a worker has started or finished.
|
||||||
|
|
||||||
|
To use this class you have to assign the signals object of your concrete implementation
|
||||||
|
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()
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(QueueWorker, self).__init__()
|
||||||
|
self.feedback = QueueWorker.Signals()
|
||||||
|
self.state = QueueWorker.State.QUEUED
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def run(self):
|
||||||
|
self.state = QueueWorker.State.ACTIVE
|
||||||
|
self.feedback.started.emit()
|
||||||
|
super(QueueWorker, self).run()
|
||||||
|
self.feedback.finished.emit()
|
||||||
|
self.feedback.deleteLater()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def worker_info(self):
|
||||||
|
pass
|
Loading…
Reference in a new issue