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:
|
with open("menu.yaml", "r") as file:
|
||||||
menu_data = yaml.safe_load(file)
|
menu_data = yaml.safe_load(file)
|
||||||
|
|
||||||
# Store references for enabling/disabling actions later
|
self.menu_actions = {} # Store reference for enabling/disabling actions
|
||||||
self.menu_actions = {}
|
self.dynamic_submenus = {} # Store submenus for dynamic population
|
||||||
|
|
||||||
for menu_item in menu_data["menus"]:
|
for menu_item in menu_data["menus"]:
|
||||||
menu = menu_bar.addMenu(menu_item["title"])
|
menu = menu_bar.addMenu(menu_item["title"])
|
||||||
@ -495,60 +495,68 @@ class Window(QMainWindow):
|
|||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Handle external function calls via lambda
|
# Check whether this is a submenu first
|
||||||
if action_item.get("use_lambda"):
|
if action_item.get("submenu"):
|
||||||
handler = lambda: self.active_tab().select_duplicate_rows() # ✅ Keeps lambda logic
|
submenu = QMenu(action_item["text"], self)
|
||||||
else:
|
menu.addMenu(submenu)
|
||||||
handler = getattr(self, action_item["handler"], None)
|
|
||||||
|
|
||||||
|
# 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:
|
if handler is None:
|
||||||
print(f"Warning: No handler found for {action_item['text']}")
|
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 = self.create_action(
|
||||||
action_item["text"], handler, action_item.get("shortcut")
|
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"):
|
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)
|
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):
|
def populate_dynamic_submenu(self):
|
||||||
"""Dynamically populates the submenu when selected."""
|
"""Dynamically populates submenus when they are selected."""
|
||||||
submenu = self.dynamic_submenus["populate_dynamic_submenu"]
|
submenu = self.sender() # Get the submenu that triggered the event
|
||||||
submenu.clear() # Remove previous items
|
|
||||||
|
|
||||||
# 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:
|
for item in items:
|
||||||
action = QAction(item["text"], self)
|
action = QAction(item["text"], self)
|
||||||
action.triggered.connect(lambda _, i=item["handler"]: getattr(self, i)())
|
action.triggered.connect(
|
||||||
|
lambda _, i=item["handler"]: getattr(self, i)()
|
||||||
|
)
|
||||||
submenu.addAction(action)
|
submenu.addAction(action)
|
||||||
|
break
|
||||||
|
|
||||||
def get_dynamic_menu_items(self):
|
def get_new_playlist_dynamic_submenu_items(self):
|
||||||
"""Returns dynamically generated menu items (replace with real logic)."""
|
"""Returns dynamically generated menu items for Submenu 1."""
|
||||||
return [
|
return [
|
||||||
{"text": "Dynamic Option 1", "handler": "dynamic_option_1"},
|
{"text": "Option A", "handler": "option_a_handler"},
|
||||||
{"text": "Dynamic Option 2", "handler": "dynamic_option_2"},
|
{"text": "Option B", "handler": "option_b_handler"},
|
||||||
{"text": "Dynamic Option 3", "handler": "dynamic_option_3"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
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:
|
def about(self) -> None:
|
||||||
"""Get git tag and database name"""
|
"""Get git tag and database name"""
|
||||||
|
|
||||||
@ -838,7 +846,8 @@ class Window(QMainWindow):
|
|||||||
|
|
||||||
log.debug(f"enable_escape({enabled=})")
|
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:
|
def end_of_track_actions(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -364,7 +364,7 @@ class PlaylistTab(QTableView):
|
|||||||
Override closeEditor to enable play controls and update display.
|
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)
|
super(PlaylistTab, self).closeEditor(editor, hint)
|
||||||
|
|
||||||
|
|||||||
40
menu.yaml
40
menu.yaml
@ -1,11 +1,23 @@
|
|||||||
menus:
|
menus:
|
||||||
- title: "&File"
|
- 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:
|
actions:
|
||||||
- text: "Open Playlist"
|
- text: "Open Playlist"
|
||||||
handler: "open_playlist"
|
handler: "open_playlist"
|
||||||
shortcut: "Ctrl+O"
|
shortcut: "Ctrl+O"
|
||||||
- text: "New Playlist"
|
- text: "New Playlist"
|
||||||
handler: "new_playlist"
|
handler: "new_playlist_dynamic_submenu"
|
||||||
|
submenu: true
|
||||||
- text: "Close Playlist"
|
- text: "Close Playlist"
|
||||||
handler: "close_playlist_tab"
|
handler: "close_playlist_tab"
|
||||||
- text: "Rename Playlist"
|
- text: "Rename Playlist"
|
||||||
@ -13,31 +25,18 @@ menus:
|
|||||||
- text: "Delete Playlist"
|
- text: "Delete Playlist"
|
||||||
handler: "delete_playlist"
|
handler: "delete_playlist"
|
||||||
- separator: true
|
- 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"
|
- text: "Insert Track"
|
||||||
handler: "insert_track"
|
handler: "insert_track"
|
||||||
shortcut: "Ctrl+T"
|
shortcut: "Ctrl+T"
|
||||||
|
- text: "Select Track from Query"
|
||||||
|
handler: "query_dynamic_submenu"
|
||||||
|
submenu: true
|
||||||
- text: "Insert Section Header"
|
- text: "Insert Section Header"
|
||||||
handler: "insert_header"
|
handler: "insert_header"
|
||||||
shortcut: "Ctrl+H"
|
shortcut: "Ctrl+H"
|
||||||
|
- text: "Import Files"
|
||||||
|
handler: "import_files_wrapper"
|
||||||
|
shortcut: "Ctrl+Shift+I"
|
||||||
- separator: true
|
- separator: true
|
||||||
- text: "Mark for Moving"
|
- text: "Mark for Moving"
|
||||||
handler: "mark_rows_for_moving"
|
handler: "mark_rows_for_moving"
|
||||||
@ -53,7 +52,6 @@ menus:
|
|||||||
- separator: true
|
- separator: true
|
||||||
- text: "Select Duplicate Rows"
|
- text: "Select Duplicate Rows"
|
||||||
handler: "select_duplicate_rows"
|
handler: "select_duplicate_rows"
|
||||||
use_lambda: true
|
|
||||||
- text: "Move Selected"
|
- text: "Move Selected"
|
||||||
handler: "move_selected"
|
handler: "move_selected"
|
||||||
- text: "Move Unplayed"
|
- text: "Move Unplayed"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user