Move menu definitions to YAML file
This commit is contained in:
parent
aef8cb5cb5
commit
afd3be608c
@ -10,6 +10,7 @@ import subprocess
|
||||
import sys
|
||||
import urllib.parse
|
||||
import webbrowser
|
||||
import yaml
|
||||
|
||||
# PyQt imports
|
||||
from PyQt6.QtCore import (
|
||||
@ -38,6 +39,7 @@ from PyQt6.QtWidgets import (
|
||||
QLineEdit,
|
||||
QListWidgetItem,
|
||||
QMainWindow,
|
||||
QMenu,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
@ -475,104 +477,77 @@ class Window(QMainWindow):
|
||||
return action
|
||||
|
||||
def create_menu_bar(self):
|
||||
"""Dynamically creates the menu bar from a YAML file."""
|
||||
menu_bar = self.menuBar()
|
||||
|
||||
# File Menu
|
||||
file_menu = menu_bar.addMenu("&File")
|
||||
file_menu.addAction(
|
||||
self.create_action("Open Playlist", self.open_playlist, "Ctrl+O")
|
||||
)
|
||||
file_menu.addAction(self.create_action("New Playlist", self.new_playlist))
|
||||
file_menu.addAction(
|
||||
self.create_action("Close Playlist", self.close_playlist_tab)
|
||||
)
|
||||
file_menu.addAction(self.create_action("Rename Playlist", self.rename_playlist))
|
||||
file_menu.addAction(self.create_action("Delete Playlist", self.delete_playlist))
|
||||
file_menu.addSeparator()
|
||||
file_menu.addAction(
|
||||
self.create_action("Save as Template", self.save_as_template)
|
||||
)
|
||||
file_menu.addAction(
|
||||
self.create_action("Manage Templates", self.manage_templates)
|
||||
)
|
||||
file_menu.addSeparator()
|
||||
file_menu.addAction(
|
||||
self.create_action(
|
||||
"Import Files", self.import_files_wrapper, "Ctrl+Shift+I"
|
||||
)
|
||||
)
|
||||
file_menu.addSeparator()
|
||||
file_menu.addAction(self.create_action("Exit", self.close))
|
||||
# Load menu structure from YAML file
|
||||
with open("menu.yaml", "r") as file:
|
||||
menu_data = yaml.safe_load(file)
|
||||
|
||||
# Playlist Menu
|
||||
playlist_menu = menu_bar.addMenu("&Playlist")
|
||||
playlist_menu.addSeparator()
|
||||
playlist_menu.addAction(
|
||||
self.create_action("Insert Track", self.insert_track, "Ctrl+T")
|
||||
)
|
||||
playlist_menu.addAction(
|
||||
self.create_action("Insert Section Header", self.insert_header, "Ctrl+H")
|
||||
)
|
||||
playlist_menu.addSeparator()
|
||||
playlist_menu.addAction(
|
||||
self.create_action("Mark for Moving", self.mark_rows_for_moving, "Ctrl+C")
|
||||
)
|
||||
playlist_menu.addAction(self.create_action("Paste", self.paste_rows, "Ctrl+V"))
|
||||
playlist_menu.addSeparator()
|
||||
playlist_menu.addAction(
|
||||
self.create_action("Export Playlist", self.export_playlist_tab)
|
||||
)
|
||||
playlist_menu.addAction(
|
||||
self.create_action(
|
||||
"Download CSV of Played Tracks", self.download_played_tracks
|
||||
)
|
||||
)
|
||||
playlist_menu.addSeparator()
|
||||
playlist_menu.addAction(
|
||||
self.create_action(
|
||||
"Select Duplicate Rows",
|
||||
lambda: self.active_tab().select_duplicate_rows(),
|
||||
)
|
||||
)
|
||||
playlist_menu.addAction(self.create_action("Move Selected", self.move_selected))
|
||||
playlist_menu.addAction(self.create_action("Move Unplayed", self.move_unplayed))
|
||||
# Store references for enabling/disabling actions later
|
||||
self.menu_actions = {}
|
||||
|
||||
# Clear Selection with Escape key. Save in module so we can
|
||||
# enable/disable it later
|
||||
self.action_Clear_selection = self.create_action(
|
||||
"Clear Selection", self.clear_selection, "Esc"
|
||||
)
|
||||
playlist_menu.addAction(self.action_Clear_selection)
|
||||
for menu_item in menu_data["menus"]:
|
||||
menu = menu_bar.addMenu(menu_item["title"])
|
||||
|
||||
# Music Menu
|
||||
music_menu = menu_bar.addMenu("&Music")
|
||||
music_menu.addAction(
|
||||
self.create_action("Set Next", self.set_selected_track_next, "Ctrl+N")
|
||||
)
|
||||
music_menu.addAction(self.create_action("Play Next", self.play_next, "Return"))
|
||||
music_menu.addAction(self.create_action("Fade", self.fade, "Ctrl+Z"))
|
||||
music_menu.addAction(self.create_action("Stop", self.stop, "Ctrl+Alt+S"))
|
||||
music_menu.addAction(self.create_action("Resume", self.resume, "Ctrl+R"))
|
||||
music_menu.addAction(
|
||||
self.create_action("Skip to Next", self.play_next, "Ctrl+Alt+Return")
|
||||
)
|
||||
music_menu.addSeparator()
|
||||
music_menu.addAction(self.create_action("Search", self.search_playlist, "/"))
|
||||
music_menu.addAction(
|
||||
self.create_action(
|
||||
"Search Title in Wikipedia", self.lookup_row_in_wikipedia, "Ctrl+W"
|
||||
)
|
||||
)
|
||||
music_menu.addAction(
|
||||
self.create_action(
|
||||
"Search Title in Songfacts", self.lookup_row_in_songfacts, "Ctrl+S"
|
||||
)
|
||||
)
|
||||
for action_item in menu_item["actions"]:
|
||||
if "separator" in action_item and action_item["separator"]:
|
||||
menu.addSeparator()
|
||||
continue
|
||||
|
||||
# Help Menu
|
||||
help_menu = menu_bar.addMenu("Help")
|
||||
help_menu.addAction(self.create_action("About", self.about))
|
||||
help_menu.addAction(self.create_action("Debug", self.debug))
|
||||
# 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)
|
||||
|
||||
if handler is None:
|
||||
print(f"Warning: No handler found for {action_item['text']}")
|
||||
continue # Skip adding the action if the handler is missing
|
||||
|
||||
action = self.create_action(
|
||||
action_item["text"], handler, action_item.get("shortcut")
|
||||
)
|
||||
|
||||
if action_item.get("store_reference"):
|
||||
self.menu_actions[action_item["handler"]] = action # Store reference
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Example: Populate submenu with dynamically generated items
|
||||
items = self.get_dynamic_menu_items() # Assume this method provides a list of items
|
||||
|
||||
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)."""
|
||||
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"},
|
||||
]
|
||||
|
||||
def about(self) -> None:
|
||||
"""Get git tag and database name"""
|
||||
|
||||
104
menu.yaml
Normal file
104
menu.yaml
Normal file
@ -0,0 +1,104 @@
|
||||
menus:
|
||||
- title: "&File"
|
||||
actions:
|
||||
- text: "Open Playlist"
|
||||
handler: "open_playlist"
|
||||
shortcut: "Ctrl+O"
|
||||
- text: "New Playlist"
|
||||
handler: "new_playlist"
|
||||
- text: "Close Playlist"
|
||||
handler: "close_playlist_tab"
|
||||
- text: "Rename Playlist"
|
||||
handler: "rename_playlist"
|
||||
- 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: "Insert Section Header"
|
||||
handler: "insert_header"
|
||||
shortcut: "Ctrl+H"
|
||||
- separator: true
|
||||
- text: "Mark for Moving"
|
||||
handler: "mark_rows_for_moving"
|
||||
shortcut: "Ctrl+C"
|
||||
- text: "Paste"
|
||||
handler: "paste_rows"
|
||||
shortcut: "Ctrl+V"
|
||||
- separator: true
|
||||
- text: "Export Playlist"
|
||||
handler: "export_playlist_tab"
|
||||
- text: "Download CSV of Played Tracks"
|
||||
handler: "download_played_tracks"
|
||||
- separator: true
|
||||
- text: "Select Duplicate Rows"
|
||||
handler: "select_duplicate_rows"
|
||||
use_lambda: true
|
||||
- text: "Move Selected"
|
||||
handler: "move_selected"
|
||||
- text: "Move Unplayed"
|
||||
handler: "move_unplayed"
|
||||
- separator: true
|
||||
- text: "Clear Selection"
|
||||
handler: "clear_selection"
|
||||
shortcut: "Esc"
|
||||
store_reference: true # So we can enable/disable later
|
||||
|
||||
- title: "&Music"
|
||||
actions:
|
||||
- text: "Set Next"
|
||||
handler: "set_selected_track_next"
|
||||
shortcut: "Ctrl+N"
|
||||
- text: "Play Next"
|
||||
handler: "play_next"
|
||||
shortcut: "Return"
|
||||
- text: "Fade"
|
||||
handler: "fade"
|
||||
shortcut: "Ctrl+Z"
|
||||
- text: "Stop"
|
||||
handler: "stop"
|
||||
shortcut: "Ctrl+Alt+S"
|
||||
- text: "Resume"
|
||||
handler: "resume"
|
||||
shortcut: "Ctrl+R"
|
||||
- text: "Skip to Next"
|
||||
handler: "play_next"
|
||||
shortcut: "Ctrl+Alt+Return"
|
||||
- separator: true
|
||||
- text: "Search"
|
||||
handler: "search_playlist"
|
||||
shortcut: "/"
|
||||
- text: "Search Title in Wikipedia"
|
||||
handler: "lookup_row_in_wikipedia"
|
||||
shortcut: "Ctrl+W"
|
||||
- text: "Search Title in Songfacts"
|
||||
handler: "lookup_row_in_songfacts"
|
||||
shortcut: "Ctrl+S"
|
||||
|
||||
- title: "Help"
|
||||
actions:
|
||||
- text: "About"
|
||||
handler: "about"
|
||||
- text: "Debug"
|
||||
handler: "debug"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user