diff --git a/gui/move_roms_section.py b/gui/move_roms_section.py index f6480bb..11660fb 100644 --- a/gui/move_roms_section.py +++ b/gui/move_roms_section.py @@ -35,14 +35,11 @@ def create_move_roms_section(): global_variables.ui_move_roms_use_same_folder_for_multidisc_switch = ui.switch("Use the same folder for multidisc roms?") with ui.row().classes('w-full items-center').bind_visibility(globals(), 'show_move_roms_to_folder_elements'): global_variables.ui_move_roms_use_different_folder_switch = ui.switch("Use as destination folder a custom folder?") - global_variables.ui_move_roms_destination_path_input = ui.input(label='Destination file location', - validation={ - 'Path not valid': lambda value: Path(value).is_dir() - }, - ).classes('w-full') + global_variables.ui_move_roms_destination_path_input = ui.input(label='Destination file location').classes('w-full') with ui.row().classes('w-full items-center'): global_variables.ui_move_roms_preview_button = ui.button('Preview', on_click=generate_preview) global_variables.ui_move_roms_run_button = ui.button('Run!', on_click=run) + global_variables.ui_move_roms_delete_empty_folders_switch = ui.switch("Delete empty folders at the end?") with ui.row().classes('w-full items-center').bind_visibility_from(globals(), 'show_preview'): add_table_to_ui() @@ -72,6 +69,9 @@ def apply_bindings(): global_variables.ui_move_roms_run_button.bind_enabled_from(globals(), 'enable_ui_elements') global_variables.ui_move_roms_run_button.bind_visibility_from(globals(), 'show_preview') + global_variables.ui_move_roms_delete_empty_folders_switch.bind_value(global_variables.user_data.move_roms, 'delete_empty_folders') + global_variables.ui_move_roms_delete_empty_folders_switch.bind_enabled_from(globals(), 'enable_ui_elements') + def check_move_roms_choice(): global show_move_roms_to_subfolder_elements global show_move_roms_to_folder_elements @@ -86,8 +86,9 @@ def check_move_roms_choice(): def add_table_to_ui(): columns = [ - {'name': 'source', 'label': 'Source', 'field': 'source', 'required': True, 'align': 'left', 'sortable': True}, - {'name': 'destination', 'label': 'Destination', 'field': 'destination', 'required': True, 'align': 'left', 'sortable': True}, + {'name': 'file', 'label': 'File', 'field': 'file', 'required': True, 'align': 'left', 'sortable': True}, + {'name': 'source_folder', 'label': 'Source', 'field': 'source_folder', 'required': True, 'align': 'left', 'sortable': True}, + {'name': 'destination_folder', 'label': 'Destination', 'field': 'destination_folder', 'required': True, 'align': 'left', 'sortable': True}, ] rows = [] global_variables.ui_move_roms_preview_table = ui.table(columns=columns, rows=rows).classes('w-full') @@ -99,8 +100,9 @@ def add_rows_to_table(): item: Move_Tracing global_variables.ui_move_roms_preview_table.rows.append({ - 'source': item.source, - 'destination': item.destination, + 'file': item.file, + 'source_folder': item.source_folder, + 'destination_folder': item.destination_folder, }) global_variables.ui_move_roms_preview_table.update() @@ -128,7 +130,11 @@ async def generate_preview(): spinner = ui.spinner('dots', size='xl') await asyncio.to_thread(move_roms_worker.generate_preview) - if len(global_variables.move_roms_tracing_list) > 0: + if len(global_variables.move_roms_tracing_list) == 0: + message = 'No moves to do' + ui.notify(message) + global_variables.logger.info(message) + else: global_variables.ui_move_roms_preview_table.rows.clear() global_variables.ui_move_roms_preview_table.selected.clear() @@ -155,11 +161,6 @@ def check_for_preview(): global_variables.logger.info(message) ui.notify(message) return False - if global_variables.ui_move_roms_destination_path_input.error != None: - message = 'Cannot generate preview. Destination path not valid' - global_variables.logger.info(message) - ui.notify(message) - return False return True @@ -176,7 +177,7 @@ async def run(): # add the spinner to apply the ui enable change from enable_ui_elements and show the loading animation spinner = ui.spinner('dots', size='xl') - moved_roms = await asyncio.to_thread(move_roms_worker.generate_M3U) + moved_roms = await asyncio.to_thread(move_roms_worker.move_roms) if moved_roms > 0: message = 'Moved ' + str(moved_roms) + ' roms. Check log for details' diff --git a/obj/move_tracing.py b/obj/move_tracing.py index c40ddd3..799ffa6 100644 --- a/obj/move_tracing.py +++ b/obj/move_tracing.py @@ -1,5 +1,6 @@ class Move_Tracing(): - def __init__(self, source, destination): - self.source = source - self.destination = destination + def __init__(self, file, source_folder, destination_folder): + self.file = file + self.source_folder = source_folder + self.destination_folder = destination_folder diff --git a/obj/user_data.py b/obj/user_data.py index bddb456..a57fdd6 100644 --- a/obj/user_data.py +++ b/obj/user_data.py @@ -15,12 +15,14 @@ def __init__(self, use_same_folder_for_multidisc, use_different_folder, destination_path, + delete_empty_folders, ): self.choice = choice self.source_path = source_path self.use_same_folder_for_multidisc = use_same_folder_for_multidisc self.use_different_folder = use_different_folder self.destination_path = destination_path + self.delete_empty_folders = delete_empty_folders class Create_M3U(): def __init__(self, @@ -42,6 +44,7 @@ def return_default_user_data(): use_same_folder_for_multidisc=False, use_different_folder= False, destination_path= '', + delete_empty_folders=False, ), create_m3u= Create_M3U( source_path=str(Path.cwd()), diff --git a/src/global_variables.py b/src/global_variables.py index 27e7448..6d58ce6 100644 --- a/src/global_variables.py +++ b/src/global_variables.py @@ -45,6 +45,7 @@ ui_move_roms_destination_path_input: ui.input ui_move_roms_preview_button: ui.button ui_move_roms_run_button: ui.button +ui_move_roms_delete_empty_folders_switch: ui.switch ui_move_roms_preview_table: ui.table move_roms_tracing_list = [] @@ -58,7 +59,7 @@ m3u_tracing_list = [] # regex string to find if a file refer to a multidisc format -regex_multi_disc = r"(\(Disc .+?\)|\(Disk .+?\)|\(Bonus Disc\))" +regex_multi_disc = r"( *\(Disc .+?\)| *\(Disk .+?\)| *\(Bonus Disc\))" # regex string to find part of filename to remove from the destination folder name -regex_string_to_remove_for_destination_folder = r"(\(Track .+?\))" +regex_string_to_remove_for_destination_folder = r" *\(Track .+?\)" diff --git a/src/pathManager.py b/src/path_manager.py similarity index 66% rename from src/pathManager.py rename to src/path_manager.py index fa2d1cf..4ad0474 100644 --- a/src/pathManager.py +++ b/src/path_manager.py @@ -6,14 +6,7 @@ # project libraries import src.global_variables as global_variables -def addLastSlashIfMissing(path): - global_variables.logger.debug(inspect.currentframe().f_code.co_name) - global_variables.logger.debug(' path: ' + path) - if not path.endswith('\\'): - path += '\\' - return path - -def deleteEmptyFolders(path): +def delete_empty_folders(path): global_variables.logger.debug(inspect.currentframe().f_code.co_name) global_variables.logger.debug(' path: ' + path) for root, folders, files in os.walk(path, topdown=False): diff --git a/src/user_data_manager.py b/src/user_data_manager.py index 53e89ac..beae2ec 100644 --- a/src/user_data_manager.py +++ b/src/user_data_manager.py @@ -9,8 +9,6 @@ # project libraries import obj.user_data as ud import src.global_variables as global_variables -import src.pathManager as pathManager -import src.log_manager as log_manager def read_user_data(): diff --git a/workers/move_roms_worker.py b/workers/move_roms_worker.py index 603879b..75c979f 100644 --- a/workers/move_roms_worker.py +++ b/workers/move_roms_worker.py @@ -2,12 +2,14 @@ import inspect import os import re +import shutil import time from nicegui import ui from pathlib import Path # project libraries import src.global_variables as global_variables +import src.path_manager as path_manager from obj.move_tracing import Move_Tracing def generate_preview(): @@ -54,9 +56,6 @@ def generate_preview_to_subfolder_multidisc(file, root): regexResult = re.split(global_variables.regex_multi_disc, cleanedFileName, re.IGNORECASE) global_variables.logger.debug('Check multidisk regex result: ' + str(regexResult)) - # starts composing the destination folder - global_variables.logger.debug('Folder calculated before loop is: ' + destination_folder) - calculated_folder = '' for item in regexResult: @@ -75,8 +74,9 @@ def generate_preview_to_subfolder_multidisc(file, root): if (Path(root) != Path(destination_folder)): global_variables.move_roms_tracing_list.append( Move_Tracing( - source=os.path.join(root, file), - destination=destination_folder + file=file, + source_folder=root, + destination_folder=destination_folder, ) ) @@ -85,59 +85,86 @@ def generate_preview_to_subfolder_singledisc(file, root): cleanedFileName = clean_file_name(file) - start from here - regexResult = re.split(global_variables.regex_multi_disc, cleanedFileName, re.IGNORECASE) - global_variables.logger.debug('Check multidisk regex result: ' + str(regexResult)) - - # starts composing the destination folder - global_variables.logger.debug('Folder calculated before loop is: ' + destination_folder) + # splitext split file from extension giving and array. the [0] element is filename r:\Python\Rom Manager\test\rom folder\ + filename = os.path.splitext(cleanedFileName)[0] + global_variables.logger.debug('Name extracted: ' + filename) - calculated_folder = '' - for item in regexResult: - - if re.search(global_variables.regex_multi_disc, item, re.IGNORECASE): - global_variables.logger.debug('Multidisc pattern found in: ' + item + '. Breaking loop') - break - else: - global_variables.logger.debug('Multidisc pattern not found in: ' + item + '. Appending') - calculated_folder += item - - destination_folder = os.path.join(str(Path(global_variables.user_data.move_roms.source_path)), calculated_folder) - destination_folder = destination_folder.rstrip() + # starts composing the destination folder + destination_folder = os.path.join(str(Path(global_variables.user_data.move_roms.source_path)), filename) - global_variables.logger.debug('New folder calculated after loop is: ' + destination_folder) + global_variables.logger.debug('New folder calculated is: ' + destination_folder ) if (Path(root) != Path(destination_folder)): global_variables.move_roms_tracing_list.append( Move_Tracing( - source=os.path.join(root, file), - destination=destination_folder + file=file, + source_folder=root, + destination_folder=destination_folder, ) ) -def generate_M3U(): +def generate_preview_to_folder(): global_variables.logger.debug(inspect.currentframe().f_code.co_name) - created_m3u_files = 0 - for item in global_variables.m3u_tracing_list: - item: M3U_tracing - if Path(item.M3U_path).exists() and Path(item.M3U_path).is_file() and not global_variables.user_data.create_m3u.overwrite: - global_variables.logger.info('M3U file ' + Path(item.M3U_path).name + ' already created and overwrite not selected. Skipping') + global_variables.logger.debug('Generating preview moves to user choosen folder') + + # using the os.walk instead of rglob because return in an entry the folder and all it's files + for root, folders, files in os.walk(global_variables.user_data.move_roms.source_path): + if len(files) == 0: continue + + root = str(Path(root)) + global_variables.logger.debug('Working on folder ' + root) - with open(file=item.M3U_path, mode="w") as file: - count = 0 - for element in item.M3U_file_list: - if count != 0: - file.write("\n") - file.write(element) - count = count + 1 - file.close + for file in files: + global_variables.logger.debug('Working on file ' + str(file)) + + # check if the current file is allowed (extension) + if not check_extesion(file): + global_variables.logger.debug('Item is not ok [extension not allowed]') + continue - global_variables.logger.info('Created M3U file ' + str(Path(item.M3U_path)) + ' with this discs into: ' + str(item.M3U_file_list)) - created_m3u_files += 1 + # if checks are ok, add the file to the move list + if global_variables.user_data.move_roms.use_different_folder: + if (Path(root) != Path(global_variables.user_data.move_roms.destination_path)): + global_variables.move_roms_tracing_list.append( + Move_Tracing( + file=file, + source_folder=root, + destination_folder=global_variables.user_data.move_roms.destination_path, + ) + ) + else: + if (Path(root) != Path(global_variables.user_data.move_roms.source_path)): + global_variables.move_roms_tracing_list.append( + Move_Tracing( + file=file, + source_folder=root, + destination_folder=global_variables.user_data.move_roms.source_path, + ) + ) + +def move_roms(): + global_variables.logger.debug(inspect.currentframe().f_code.co_name) + + moved_roms = 0 + + for item in global_variables.move_roms_tracing_list: + item: Move_Tracing + + source = os.path.join(item.source_folder, item.file) + destination = os.path.join(item.destination_folder, item.file) + if not (Path(item.destination_folder).exists()) or not (Path(item.destination_folder).is_dir()): + Path(destination).parent.mkdir(exist_ok=True) - return created_m3u_files + shutil.move(source, destination) + global_variables.logger.info('Moved roms from ' + source + ' to ' + destination) + moved_roms = moved_roms + 1 + + if global_variables.user_data.move_roms.delete_empty_folders: + path_manager.delete_empty_folders(global_variables.user_data.move_roms.source_path) + + return moved_roms def check_extesion(file):