Framework for dynamic submenus
This commit is contained in:
parent
afd3be608c
commit
b0f6e4e819
@ -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:
|
||||
"""
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
40
menu.yaml
40
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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user