diff --git a/app/musicmuster.py b/app/musicmuster.py index e8969bb..a502b79 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -484,8 +484,8 @@ class Window(QMainWindow): with open("menu.yaml", "r") as file: menu_data = yaml.safe_load(file) - # Store references for enabling/disabling actions later - self.menu_actions = {} + self.menu_actions = {} # Store reference for enabling/disabling actions + self.dynamic_submenus = {} # Store submenus for dynamic population for menu_item in menu_data["menus"]: menu = menu_bar.addMenu(menu_item["title"]) @@ -495,60 +495,68 @@ class Window(QMainWindow): menu.addSeparator() continue - # Handle external function calls via lambda - if action_item.get("use_lambda"): - handler = lambda: self.active_tab().select_duplicate_rows() # ✅ Keeps lambda logic - else: - handler = getattr(self, action_item["handler"], None) + # Check whether this is a submenu first + if action_item.get("submenu"): + submenu = QMenu(action_item["text"], self) + menu.addMenu(submenu) + # Store submenu reference for dynamic population + self.dynamic_submenus[action_item["handler"]] = submenu + submenu.aboutToShow.connect(self.populate_dynamic_submenu) + continue # Skip the rest of the loop (no handler needed) + + # Now check for a normal menu action + handler = getattr(self, action_item["handler"], None) if handler is None: print(f"Warning: No handler found for {action_item['text']}") - continue # Skip adding the action if the handler is missing + continue action = self.create_action( action_item["text"], handler, action_item.get("shortcut") ) - + # Store reference to "Clear Selection" so we can enable/disable it if action_item.get("store_reference"): - self.menu_actions[action_item["handler"]] = action # Store reference - + self.menu_actions[action_item["handler"]] = action menu.addAction(action) - # Handle dynamic submenu - if action_item.get("submenu"): - submenu = QMenu(action_item["text"], self) - action.setMenu(submenu) - menu.addMenu(submenu) - - # Store submenu reference for dynamic population - self.dynamic_submenus = getattr(self, "dynamic_submenus", {}) - self.dynamic_submenus[action_item["handler"]] = submenu - - # Connect submenu aboutToShow signal to population function - submenu.aboutToShow.connect(self.populate_dynamic_submenu) - def populate_dynamic_submenu(self): - """Dynamically populates the submenu when selected.""" - submenu = self.dynamic_submenus["populate_dynamic_submenu"] - submenu.clear() # Remove previous items + """Dynamically populates submenus when they are selected.""" + submenu = self.sender() # Get the submenu that triggered the event - # Example: Populate submenu with dynamically generated items - items = self.get_dynamic_menu_items() # Assume this method provides a list of items + # Find which submenu it is + for key, stored_submenu in self.dynamic_submenus.items(): + if submenu == stored_submenu: + submenu.clear() + # Dynamically call the correct function + items = getattr(self, f"get_{key}_items")() + for item in items: + action = QAction(item["text"], self) + action.triggered.connect( + lambda _, i=item["handler"]: getattr(self, i)() + ) + submenu.addAction(action) + break - for item in items: - action = QAction(item["text"], self) - action.triggered.connect(lambda _, i=item["handler"]: getattr(self, i)()) - submenu.addAction(action) - - def get_dynamic_menu_items(self): - """Returns dynamically generated menu items (replace with real logic).""" + def get_new_playlist_dynamic_submenu_items(self): + """Returns dynamically generated menu items for Submenu 1.""" return [ - {"text": "Dynamic Option 1", "handler": "dynamic_option_1"}, - {"text": "Dynamic Option 2", "handler": "dynamic_option_2"}, - {"text": "Dynamic Option 3", "handler": "dynamic_option_3"}, + {"text": "Option A", "handler": "option_a_handler"}, + {"text": "Option B", "handler": "option_b_handler"}, ] + def get_query_dynamic_submenu_items(self): + """Returns dynamically generated menu items for Submenu 2.""" + return [ + {"text": "Action X", "handler": "action_x_handler"}, + {"text": "Action Y", "handler": "action_y_handler"}, + ] + + def select_duplicate_rows(self) -> None: + """Call playlist to select duplicate rows""" + + self.active_tab().select_duplicate_rows() + def about(self) -> None: """Get git tag and database name""" @@ -838,7 +846,8 @@ class Window(QMainWindow): log.debug(f"enable_escape({enabled=})") - self.action_Clear_selection.setEnabled(enabled) + if "clear_selection" in self.menu_actions: + self.menu_actions["clear_selection"].setEnabled(enabled) def end_of_track_actions(self) -> None: """ diff --git a/app/playlists.py b/app/playlists.py index 6b32213..f87d974 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -364,7 +364,7 @@ class PlaylistTab(QTableView): Override closeEditor to enable play controls and update display. """ - self.musicmuster.action_Clear_selection.setEnabled(True) + self.musicmuster.enable_escape(True) super(PlaylistTab, self).closeEditor(editor, hint) diff --git a/menu.yaml b/menu.yaml index 20e73c4..62fc331 100644 --- a/menu.yaml +++ b/menu.yaml @@ -1,11 +1,23 @@ menus: - title: "&File" + actions: + - text: "Save as Template" + handler: "save_as_template" + - text: "Manage Templates" + handler: "manage_templates" + - separator: true + - separator: true + - text: "Exit" + handler: "close" + + - title: "&Playlist" actions: - text: "Open Playlist" handler: "open_playlist" shortcut: "Ctrl+O" - text: "New Playlist" - handler: "new_playlist" + handler: "new_playlist_dynamic_submenu" + submenu: true - text: "Close Playlist" handler: "close_playlist_tab" - text: "Rename Playlist" @@ -13,31 +25,18 @@ menus: - text: "Delete Playlist" handler: "delete_playlist" - separator: true - - text: "Save as Template" - handler: "save_as_template" - - text: "Manage Templates" - handler: "manage_templates" - - separator: true - - text: "Import Files" - handler: "import_files_wrapper" - shortcut: "Ctrl+Shift+I" - - separator: true - - text: "Dynamic Submenu" - handler: "populate_dynamic_submenu" - submenu: true - - separator: true - - text: "Exit" - handler: "close" - - - title: "&Playlist" - actions: - - separator: true - text: "Insert Track" handler: "insert_track" shortcut: "Ctrl+T" + - text: "Select Track from Query" + handler: "query_dynamic_submenu" + submenu: true - text: "Insert Section Header" handler: "insert_header" shortcut: "Ctrl+H" + - text: "Import Files" + handler: "import_files_wrapper" + shortcut: "Ctrl+Shift+I" - separator: true - text: "Mark for Moving" handler: "mark_rows_for_moving" @@ -53,7 +52,6 @@ menus: - separator: true - text: "Select Duplicate Rows" handler: "select_duplicate_rows" - use_lambda: true - text: "Move Selected" handler: "move_selected" - text: "Move Unplayed"