import sys # For exiting the program 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, module=None): """ Builds a submenu and tracks progress across all nested submenus. Automatically adds an 'All' option to execute all actions. """ # Initialize global action status for this submenu if not already set if menu_title not in GLOBAL_ACTION_STATUS: GLOBAL_ACTION_STATUS[menu_title] = {key: False for key in actions} # False means not completed GLOBAL_HIGHLIGHTS[menu_title] = {key: False for key in actions} # False means not highlighted # Update global total progress for tracking across all menus GLOBAL_TOTAL_PROGRESS["total"] += len(actions) # Access the action status and highlight status for this specific submenu action_status = GLOBAL_ACTION_STATUS[menu_title] highlight_status = GLOBAL_HIGHLIGHTS[menu_title] # Dynamically add "All" option actions["all"] = { "description": "Run All", "function": lambda: run_all_actions(actions, module, action_status), } # Ensure the "all" option is in the dictionaries if "all" not in action_status: action_status["all"] = False if "all" not in highlight_status: highlight_status["all"] = False while True: clear_screen() header() # Call the header without arguments print("=====================================") print(f" {menu_title} Menu ") print("=====================================\n") # Display global progress only (not specific to this submenu) global_completed = GLOBAL_TOTAL_PROGRESS["completed"] global_total = GLOBAL_TOTAL_PROGRESS["total"] print(f"Global Progress: {global_completed}/{global_total} tasks completed\n") # Display menu options with status, progress, and highlighting for key, action in actions.items(): if key == "all": # Highlight the "All" option in blue print(f"\033[94m[{key.upper()}] {action['description']}\033[0m") else: # Check the status and highlight of the submenu or action if "submenu" in action: submenu_completed = is_submenu_complete(action["submenu"]) status = "✔️" if submenu_completed else "❌" else: status = "✔️ " if action_status[key] else "❌" if highlight_status[key]: # Highlight in yellow if flagged print(f"\033[93m[{key}] {status} {action['description']}\033[0m") else: print(f"[{key}] {status} {action['description']}") print("[0] Return to Main Menu") print("[q] EXIT\n") # Get user choice choice = input("Enter your choice: ").strip().lower() # Handle highlighting if choice.endswith("!") and choice[:-1] in 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"Action [{key_to_toggle}] has been highlighted.") else: print(f"Highlight removed from action [{key_to_toggle}].") input("Press Enter to continue...") continue # Handle unchecking of actions if choice.startswith("-") and choice[1:] in 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"Unchecked action [{key_to_uncheck}]") else: print(f"Action [{key_to_uncheck}] was not completed.") input("Press Enter to continue...") continue # Handle menu choices if choice in actions: if choice == "all": run_all_actions(actions, module, action_status) action_status["all"] = True # Mark the "All" option as completed elif "submenu" in actions[choice]: # Navigate to nested submenu actions[choice]["submenu"]() # After returning, check if all nested submenu items are done if is_submenu_complete(actions[choice]["submenu"]): if not action_status[choice]: action_status[choice] = True # Mark this submenu as complete GLOBAL_TOTAL_PROGRESS["completed"] += 1 elif "function" in actions[choice]: # Execute the associated function actions[choice]["function"]() if not action_status[choice]: action_status[choice] = True # Mark the action as completed GLOBAL_TOTAL_PROGRESS["completed"] += 1 # Propagate status updates to the parent menu propagate_status_to_parent(menu_title) elif choice == "0": print("Returning to main menu...") break elif choice in ["q", "exit", "quit"]: print("Logging out...") sys.exit() else: print("Invalid choice. Please try again.") input("Press Enter to continue...") # Propagate parent status again after menu completion propagate_status_to_parent(menu_title) def run_all_actions(actions, module, action_status): """ Executes all actions in the submenu sequentially. """ for key, action in actions.items(): if key != "all": # Skip the "All" option itself 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()