123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- ########################################################################
- # Wiizard - A Wii games manager
- # Copyright (C) 2023 CYBERDEViL
- #
- # This file is part of Wiizard.
- #
- # Wiizard is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # Wiizard is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- #
- ########################################################################
- import os
- from PyQt5.QtCore import pyqtSignal
- import pywwt
- from wiizard.thread import AbstractThread, THREAD_FLAG_IS_CANCELLABLE
- from wiizard.models.source import SOURCE_TYPE_LOCAL
- GAME_OP_DELETE = 1
- GAME_OP_ADD = 2
- GAME_OP_MOVE = GAME_OP_ADD | GAME_OP_DELETE
- class GameOperationsThread(AbstractThread):
- progress = pyqtSignal(int, str) # operation index, error message
- def __init__(self, operations):
- AbstractThread.__init__(self, flags=THREAD_FLAG_IS_CANCELLABLE)
- self.__operations = operations
- def execAdd(self, op):
- error = ""
- fromModel = op.game.sourceModel
- toModel = op.target
- if op.game.fileSize > toModel.getFree():
- error = "Not enough free space!"
- return error
- if fromModel.type == SOURCE_TYPE_LOCAL:
- # Local to local (regular file copy)
- if toModel.type == SOURCE_TYPE_LOCAL:
- frompath = os.path.join(op.game.sourcePath, op.game.filename)
- topath = os.path.join(toModel.location, op.game.filename)
- opStr = f"copy {frompath} to {topath}."
- print(f"Try to {opStr}")
- error = f"Failed to {opStr}"
- error += "\nFIXME copy local to local not implemented yet."
- # Local to WBFS partition
- else:
- filepath = os.path.join(op.game.sourcePath, op.game.filename)
- opStr = f"add '{filepath}' to '{toModel.location}'."
- result = None
- print(f"Try to {opStr}")
- try:
- result = pywwt.add_to_wbfs(toModel.location, filepath, testMode=False)
- except pywwt.error as err:
- error = f"Failed to {opStr}"
- error += f"\npywwt.error: '{err}'"
- else:
- if not result:
- error = f"Failed to {opStr}"
- else:
- # WBFS partition to local
- if toModel.type == SOURCE_TYPE_LOCAL:
- # TODO check file type
- # TODO check if file exists
- frompath = f"{fromModel.location}:{op.game.id6}"
- topath = os.path.join(toModel.location, f"{op.game.id6}.wbfs")
- opStr = f"export {frompath} to {topath}."
- result = None
- print(f"Try to {opStr}")
- try:
- result = pywwt.extract_from_wbfs(op.game.sourceModel.location,
- op.game.id6,
- topath,
- testMode=False)
- except pywwt.error as err:
- error = f"Failed to {opStr}"
- error += f"\npywwt.error: '{err}'"
- else:
- if not result:
- error = f"Failed to {opStr}"
- # WBFS partition to WBFS partition
- else:
- frompath = f"{fromModel.location}:{op.game.id6}"
- topath = f"{toModel.location}:{op.game.id6}"
- opStr = f"copy {frompath} to {topath}."
- result = None
- print(f"Try to {opStr}")
- try:
- result = pywwt.wbfs_to_wbfs(fromModel.location, toModel.location,
- op.game.id6)
- except pywwt.error as err:
- error = f"Failed to {opStr}"
- error += f"\npywwt.error: '{err}'"
- return error
- def execDelete(self, op):
- fromModel = op.game.sourceModel
- error = ""
- if fromModel.type == SOURCE_TYPE_LOCAL:
- # Delete local file
- filepath = os.path.join(op.game.sourcePath, op.game.filename)
- opStr = f"delete {filepath}."
- print(f"Try to {opStr}")
- error = f"Failed to {opStr}"
- error += "\nFIXME Delete local file not implemented yet."
- else:
- # Delete game from WBFS partition
- filepath = f"{fromModel.location}:{op.game.id6}"
- opStr = f"delete {filepath}."
- result = None
- print(f"Try to {opStr}")
- try:
- result = pywwt.remove_from_wbfs(fromModel.location, op.game.id6,
- testMode=False)
- except pywwt.error as err:
- error = f"Failed to {opStr}"
- error += f"\npywwt.error: '{err}'"
- else:
- if not result:
- error = f"Failed to {opStr}"
- return error
- def run(self):
- progress = 0
- for index in range(0, len(self.__operations)):
- error = ""
- op = self.__operations[index]
- # ADD game
- if op.operation == GAME_OP_ADD:
- error = self.execAdd(op)
- # DELETE game
- elif op.operation == GAME_OP_DELETE:
- error = self.execDelete(op)
- # MOVE game (First ADD and then DELETE)
- elif op.operation == GAME_OP_MOVE:
- error = self.execAdd(op)
- if not error:
- error = self.execDelete(op)
- progress += 1
- self.progress.emit(progress, error)
- if self.cancelled is True:
- break
- self.completed.emit()
- class GameOperation:
- def __init__(self, game, targetModel, operation):
- self.__game = game
- self.__targetModel = targetModel
- self.__operation = operation
- @property
- def operation(self):
- return self.__operation
- @property
- def game(self):
- return self.__game
- @property
- def target(self):
- return self.__targetModel
|