diff --git a/Modules/submenu.py b/Modules/submenu.py deleted file mode 100644 index 82882f4..0000000 --- a/Modules/submenu.py +++ /dev/null @@ -1,185 +0,0 @@ -import sys # For exiting the program -from Modules.common_ui import * -from Modules.wrappers import * - - -# Global action status to persist across all submenus and their nested submenus -GLOBAL_ACTION_STATUS = {} -GLOBAL_TOTAL_PROGRESS = {"completed": 0, "total": 0} # Tracks progress across all sections -GLOBAL_HIGHLIGHTS = {} # Tracks highlighted actions - - -def build_submenu(menu_title, actions=None, module=None): - """ - Builds a submenu dynamically by extracting functions from the given module, - or using a provided `actions` dictionary for pre-defined submenus. - Includes an `[ALL]` option to execute all functions or submenus on the page. - Allows actions to be unmarked and highlighted. - """ - if not actions and not module: - raise ValueError("No module or actions provided to extract submenu items.") - - # If actions are not provided, dynamically extract from the module - if not actions: - actions = { - str(idx + 1): { - "description": func.__name__.replace("_", " ").title(), - "function": func, - } - for idx, (name, func) in enumerate(module.items()) - if ( - callable(func) - and func.__module__ == module["__name__"] # Ensure the function is from this module - and "submenu" not in func.__name__ # Exclude functions with 'submenu' in their name - ) - } - - # Reassign sequential numbering starting at 1 - numbered_actions = {str(idx + 1): action for idx, action in enumerate(actions.values())} - - # Add the ALL option with key "ALL" - numbered_actions["ALL"] = { - "description": f"Run All {menu_title}", - "function": lambda: run_all_actions(numbered_actions, module, GLOBAL_ACTION_STATUS[menu_title]), - } - - # Initialize global action status and highlights for this submenu - if menu_title not in GLOBAL_ACTION_STATUS: - GLOBAL_ACTION_STATUS[menu_title] = {key: False for key in numbered_actions} - GLOBAL_TOTAL_PROGRESS["total"] += len(numbered_actions) - 1 # Exclude the ALL option from the progress count - - if menu_title not in GLOBAL_HIGHLIGHTS: - GLOBAL_HIGHLIGHTS[menu_title] = {key: False for key in numbered_actions} - - action_status = GLOBAL_ACTION_STATUS[menu_title] - highlight_status = GLOBAL_HIGHLIGHTS[menu_title] - - while True: - # Check if all individual actions are complete; if so, mark "ALL" as complete - action_status["ALL"] = all(status for key, status in action_status.items() if key != "ALL") - - clear_screen() - header() # Display global app header - - print("=" * 70) - print(f" {menu_title} Menu ") - print("=" * 70, "\n") - - for key, action in numbered_actions.items(): - # Determine the status symbol with color - status = f"{Fore.GREEN}✔️ " if action_status[key] else f"❌" - # Highlight the key and description based on highlight status - if key == "ALL": - print(f"{Fore.BLUE}[{key}]{Style.RESET_ALL} {status} {action['description']}{Style.RESET_ALL}") - elif highlight_status[key]: - print(f"{Style.RESET_ALL}[{key}] {Fore.YELLOW}💡 {action['description']}{Style.RESET_ALL}") - else: - print(f"{Style.RESET_ALL}[{key}] {status} {action['description']}") - - print("[0] Return to Previous Menu") - print("[q] EXIT\n") - - - # Get user choice - choice = input("Enter your choice: ").strip().upper() - - # Handle global commands - if choice in ["NOTE", "ABOUT"]: - global_command_handler(choice) - continue - - # Handle highlighting (toggle with "!") - if choice.endswith("!") and choice[:-1] in numbered_actions: - key_to_toggle = choice[:-1] - highlight_status[key_to_toggle] = not highlight_status[key_to_toggle] - if highlight_status[key_to_toggle]: - print(f"{Fore.YELLOW}Action [{key_to_toggle}] has been highlighted.") - else: - print(f"{Fore.YELLOW}Highlight removed from action [{key_to_toggle}].") - input("Press Enter to continue...") - continue - - # Handle unchecking of actions (with "-") - if choice.startswith("-") and choice[1:] in numbered_actions: - key_to_uncheck = choice[1:] - if action_status[key_to_uncheck]: - action_status[key_to_uncheck] = False - GLOBAL_TOTAL_PROGRESS["completed"] -= 1 - print(f"{Fore.RED}Unchecked action [{key_to_uncheck}].") - else: - print(f"{Fore.RED}Action [{key_to_uncheck}] was already unchecked.") - input("Press Enter to continue...") - continue - - if choice in numbered_actions: - if "function" in numbered_actions[choice]: - # Call the action function - numbered_actions[choice]["function"]() - if choice != "ALL" and not action_status[choice]: # Exclude ALL from progress tracking here - action_status[choice] = True - GLOBAL_TOTAL_PROGRESS["completed"] += 1 - elif "submenu" in numbered_actions[choice]: - # Call the nested submenu - numbered_actions[choice]["submenu"]() - if is_submenu_complete(numbered_actions[choice]["submenu"]): - if not action_status[choice]: - action_status[choice] = True - GLOBAL_TOTAL_PROGRESS["completed"] += 1 - elif choice == "0": - break - elif choice in ["Q", "EXIT", "QUIT"]: - sys.exit() - else: - print(f"{Fore.RED}Invalid choice. Press Enter to continue...") - input() - - - - -def run_all_actions(actions, module, action_status): - """ - Executes all actions in the submenu sequentially, excluding the "ALL" option itself. - """ - for key, action in actions.items(): - if action["description"].startswith("Run All"): # Skip the "ALL" option - continue - - if "function" in action: - if not action_status[key]: - action["function"]() - action_status[key] = True - GLOBAL_TOTAL_PROGRESS["completed"] += 1 - elif "submenu" in action: # Recursively handle submenus - actions[key]["submenu"]() - if is_submenu_complete(actions[key]["submenu"]): - if not action_status[key]: - action_status[key] = True - GLOBAL_TOTAL_PROGRESS["completed"] += 1 - - -def is_submenu_complete(submenu_function): - """ - Check if all actions in a submenu are complete. - """ - submenu_title = get_submenu_title(submenu_function) - if submenu_title in GLOBAL_ACTION_STATUS: - return all(GLOBAL_ACTION_STATUS[submenu_title].values()) - return False - - -def propagate_status_to_parent(menu_title): - """ - Propagates the status to the parent menu when all submenu items are completed. - """ - for parent_title, statuses in GLOBAL_ACTION_STATUS.items(): - if menu_title in statuses: - statuses[menu_title] = all( - GLOBAL_ACTION_STATUS[menu_title].values() - ) # Mark parent complete if all are done - - -def get_submenu_title(submenu_function): - """ - Converts a submenu function name to a readable submenu title. - """ - return submenu_function.__name__.replace("_submenu", "").replace("_", " ").title() \ No newline at end of file