Make manage queries and manage templates into classes
This commit is contained in:
parent
90d72464cb
commit
aa6ab03555
@ -80,6 +80,7 @@ class FileErrors(NamedTuple):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Filter:
|
class Filter:
|
||||||
|
version: int = 1
|
||||||
path_type: str = "contains"
|
path_type: str = "contains"
|
||||||
path: Optional[str] = None
|
path: Optional[str] = None
|
||||||
last_played_number: Optional[int] = None
|
last_played_number: Optional[int] = None
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import ssl
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
# PyQt imports
|
# PyQt imports
|
||||||
from PyQt6.QtWidgets import QMainWindow, QMessageBox, QWidget
|
from PyQt6.QtWidgets import QInputDialog, QMainWindow, QMessageBox, QWidget
|
||||||
|
|
||||||
# Third party imports
|
# Third party imports
|
||||||
from mutagen.flac import FLAC # type: ignore
|
from mutagen.flac import FLAC # type: ignore
|
||||||
@ -150,6 +150,23 @@ def get_audio_metadata(filepath: str) -> AudioMetadata:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_name(prompt: str, default: str = "") -> str | None:
|
||||||
|
"""Get a name from the user"""
|
||||||
|
|
||||||
|
dlg = QInputDialog()
|
||||||
|
dlg.setInputMode(QInputDialog.InputMode.TextInput)
|
||||||
|
dlg.setLabelText(prompt)
|
||||||
|
while True:
|
||||||
|
if default:
|
||||||
|
dlg.setTextValue(default)
|
||||||
|
dlg.resize(500, 100)
|
||||||
|
ok = dlg.exec()
|
||||||
|
if ok:
|
||||||
|
return dlg.textValue()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_relative_date(
|
def get_relative_date(
|
||||||
past_date: Optional[dt.datetime], reference_date: Optional[dt.datetime] = None
|
past_date: Optional[dt.datetime], reference_date: Optional[dt.datetime] = None
|
||||||
) -> str:
|
) -> str:
|
||||||
|
|||||||
@ -4,10 +4,10 @@ menus:
|
|||||||
- text: "Save as Template"
|
- text: "Save as Template"
|
||||||
handler: "save_as_template"
|
handler: "save_as_template"
|
||||||
- text: "Manage Templates"
|
- text: "Manage Templates"
|
||||||
handler: "manage_templates"
|
handler: "manage_templates_wrapper"
|
||||||
- separator: true
|
- separator: true
|
||||||
- text: "Manage Queries"
|
- text: "Manage Queries"
|
||||||
handler: "manage_queries"
|
handler: "manage_queries_wrapper"
|
||||||
- separator: true
|
- separator: true
|
||||||
- text: "Exit"
|
- text: "Exit"
|
||||||
handler: "close"
|
handler: "close"
|
||||||
|
|||||||
@ -68,7 +68,7 @@ from classes import (
|
|||||||
from config import Config
|
from config import Config
|
||||||
from dialogs import TrackSelectDialog
|
from dialogs import TrackSelectDialog
|
||||||
from file_importer import FileImporter
|
from file_importer import FileImporter
|
||||||
from helpers import file_is_unreadable
|
from helpers import file_is_unreadable, get_name
|
||||||
from log import log
|
from log import log
|
||||||
from models import db, Playdates, PlaylistRows, Playlists, Queries, Settings, Tracks
|
from models import db, Playdates, PlaylistRows, Playlists, Queries, Settings, Tracks
|
||||||
from music_manager import RowAndTrack, track_sequence
|
from music_manager import RowAndTrack, track_sequence
|
||||||
@ -270,7 +270,7 @@ class FilterDialog(QDialog):
|
|||||||
self.ok_button = QPushButton("OK")
|
self.ok_button = QPushButton("OK")
|
||||||
self.cancel_button = QPushButton("Cancel")
|
self.cancel_button = QPushButton("Cancel")
|
||||||
self.cancel_button.clicked.connect(self.reject)
|
self.cancel_button.clicked.connect(self.reject)
|
||||||
self.ok_button.clicked.connect(self.accept)
|
self.ok_button.clicked.connect(self.ok_clicked)
|
||||||
button_layout.addWidget(self.ok_button)
|
button_layout.addWidget(self.ok_button)
|
||||||
button_layout.addWidget(self.cancel_button)
|
button_layout.addWidget(self.cancel_button)
|
||||||
layout.addLayout(button_layout)
|
layout.addLayout(button_layout)
|
||||||
@ -278,7 +278,9 @@ class FilterDialog(QDialog):
|
|||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
# Connect signals
|
# Connect signals
|
||||||
self.last_played_combo.currentIndexChanged.connect(self.toggle_last_played_controls)
|
self.last_played_combo.currentIndexChanged.connect(
|
||||||
|
self.toggle_last_played_controls
|
||||||
|
)
|
||||||
|
|
||||||
self.toggle_last_played_controls()
|
self.toggle_last_played_controls()
|
||||||
|
|
||||||
@ -287,6 +289,21 @@ class FilterDialog(QDialog):
|
|||||||
self.last_played_spinbox.setDisabled(disabled)
|
self.last_played_spinbox.setDisabled(disabled)
|
||||||
self.last_played_unit.setDisabled(disabled)
|
self.last_played_unit.setDisabled(disabled)
|
||||||
|
|
||||||
|
def ok_clicked(self) -> None:
|
||||||
|
"""
|
||||||
|
Update filter to match selections
|
||||||
|
"""
|
||||||
|
self.filter.path_type = self.path_combo.currentText()
|
||||||
|
self.filter.path = self.path_text.text()
|
||||||
|
self.filter.last_played_number = self.last_played_spinbox.value()
|
||||||
|
self.filter.last_played_type = self.last_played_combo.currentText()
|
||||||
|
self.filter.last_played_unit = self.last_played_unit.currentText()
|
||||||
|
self.filter.duration_type = self.duration_combo.currentText()
|
||||||
|
self.filter.duration_number = self.duration_spinbox.value()
|
||||||
|
self.filter.duration_unit = self.duration_unit.currentText()
|
||||||
|
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ItemlistItem:
|
class ItemlistItem:
|
||||||
@ -296,18 +313,14 @@ class ItemlistItem:
|
|||||||
|
|
||||||
|
|
||||||
class ItemlistManager(QDialog):
|
class ItemlistManager(QDialog):
|
||||||
def __init__(
|
def __init__(self) -> None:
|
||||||
self, items: list[ItemlistItem], callbacks: ItemlistManagerCallbacks
|
|
||||||
) -> None:
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setWindowTitle("Item Manager")
|
self.setWindowTitle("Item Manager")
|
||||||
self.setMinimumSize(600, 400)
|
self.setMinimumSize(600, 400)
|
||||||
|
|
||||||
self.items = items
|
|
||||||
self.callbacks = callbacks
|
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
self.table = QTableWidget(len(items), 2, self)
|
self.table = QTableWidget(self)
|
||||||
|
self.table.setColumnCount(2)
|
||||||
self.table.setHorizontalHeaderLabels(["Item", "Actions"])
|
self.table.setHorizontalHeaderLabels(["Item", "Actions"])
|
||||||
hh = self.table.horizontalHeader()
|
hh = self.table.horizontalHeader()
|
||||||
if not hh:
|
if not hh:
|
||||||
@ -316,8 +329,6 @@ class ItemlistManager(QDialog):
|
|||||||
self.table.setColumnWidth(0, 288)
|
self.table.setColumnWidth(0, 288)
|
||||||
self.table.setColumnWidth(1, 300)
|
self.table.setColumnWidth(1, 300)
|
||||||
|
|
||||||
self.populate_table()
|
|
||||||
|
|
||||||
layout.addWidget(self.table)
|
layout.addWidget(self.table)
|
||||||
|
|
||||||
button_layout = QHBoxLayout()
|
button_layout = QHBoxLayout()
|
||||||
@ -331,8 +342,10 @@ class ItemlistManager(QDialog):
|
|||||||
|
|
||||||
layout.addLayout(button_layout)
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
def populate_table(self) -> None:
|
def populate_table(self, items: list[ItemlistItem]) -> None:
|
||||||
"""Populates the table with items and action buttons."""
|
"""Populates the table with items and action buttons."""
|
||||||
|
|
||||||
|
self.items = items
|
||||||
self.table.setRowCount(len(self.items))
|
self.table.setRowCount(len(self.items))
|
||||||
|
|
||||||
for row, item in enumerate(self.items):
|
for row, item in enumerate(self.items):
|
||||||
@ -371,25 +384,35 @@ class ItemlistManager(QDialog):
|
|||||||
self.table.setCellWidget(row, 1, widget)
|
self.table.setCellWidget(row, 1, widget)
|
||||||
|
|
||||||
def delete_item(self, item_id: int) -> None:
|
def delete_item(self, item_id: int) -> None:
|
||||||
self.callbacks.delete(item_id)
|
"""Subclass must implement this method"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def edit_item(self, item_id: int) -> None:
|
def edit_item(self, item_id: int) -> None:
|
||||||
self.callbacks.edit(item_id)
|
"""Subclass must implement this method"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def new_item(self) -> None:
|
||||||
|
"""Subclass must implement this method"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def rename_item(self, item_id: int) -> None:
|
def rename_item(self, item_id: int) -> None:
|
||||||
new_name = self.callbacks.rename(item_id)
|
"""Subclass must implement this method"""
|
||||||
if not new_name:
|
raise NotImplementedError
|
||||||
return
|
|
||||||
# Rename item in list
|
def change_text(self, item_id: int, new_text: str) -> None:
|
||||||
|
"""
|
||||||
|
Update text for one row
|
||||||
|
"""
|
||||||
|
|
||||||
for row in range(self.table.rowCount()):
|
for row in range(self.table.rowCount()):
|
||||||
item = self.table.item(row, 0)
|
item = self.table.item(row, 0)
|
||||||
if item and self.items[row].id == item_id:
|
if item and self.items[row].id == item_id:
|
||||||
item.setText(new_name)
|
item.setText(new_text)
|
||||||
self.items[row].name = new_name
|
self.items[row].name = new_text
|
||||||
break
|
break
|
||||||
|
|
||||||
def toggle_favourite(self, item_id: int, checked: bool) -> None:
|
def toggle_favourite(self, item_id: int, checked: bool) -> None:
|
||||||
self.callbacks.favourite(item_id, checked)
|
"""Subclass must udpate database if required"""
|
||||||
|
|
||||||
for row in range(self.table.rowCount()):
|
for row in range(self.table.rowCount()):
|
||||||
item = self.table.item(row, 0)
|
item = self.table.item(row, 0)
|
||||||
@ -402,8 +425,230 @@ class ItemlistManager(QDialog):
|
|||||||
self.items[row].favourite = checked
|
self.items[row].favourite = checked
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
class ManageQueries(ItemlistManager):
|
||||||
|
"""
|
||||||
|
Delete / edit queries
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, session: Session, musicmuster: Window) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.session = session
|
||||||
|
self.musicmuster = musicmuster
|
||||||
|
self.refresh_table()
|
||||||
|
self.exec()
|
||||||
|
|
||||||
|
def refresh_table(self) -> None:
|
||||||
|
"""
|
||||||
|
Update table in widget
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Build a list of queries
|
||||||
|
query_list: list[ItemlistItem] = []
|
||||||
|
|
||||||
|
for query in Queries.get_all_queries(self.session):
|
||||||
|
query_list.append(
|
||||||
|
ItemlistItem(name=query.name, id=query.id, favourite=query.favourite)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.populate_table(query_list)
|
||||||
|
|
||||||
|
def delete_item(self, query_id: int) -> None:
|
||||||
|
"""delete query"""
|
||||||
|
|
||||||
|
query = self.session.get(Queries, query_id)
|
||||||
|
if not query:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.delete({query_id=}) can't load query"
|
||||||
|
)
|
||||||
|
if helpers.ask_yes_no(
|
||||||
|
"Delete query",
|
||||||
|
f"Delete query '{query.name}': " "Are you sure?",
|
||||||
|
):
|
||||||
|
log.debug(f"manage_queries: delete {query=}")
|
||||||
|
self.session.delete(query)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
self.refresh_table()
|
||||||
|
|
||||||
|
def _edit_item(self, query: Queries) -> None:
|
||||||
|
"""Edit query"""
|
||||||
|
|
||||||
|
dlg = FilterDialog(query.name, query.filter)
|
||||||
|
if dlg.exec():
|
||||||
|
query.filter = dlg.filter
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
def edit_item(self, query_id: int) -> None:
|
||||||
|
"""Edit query"""
|
||||||
|
|
||||||
|
query = self.session.get(Queries, query_id)
|
||||||
|
if not query:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.edit_item({query_id=}) can't load query"
|
||||||
|
)
|
||||||
|
return self._edit_item(query)
|
||||||
|
|
||||||
|
def toggle_favourite(self, query_id: int, favourite: bool) -> None:
|
||||||
|
"""Mark query as (not) favourite"""
|
||||||
|
|
||||||
|
query = self.session.get(Queries, query_id)
|
||||||
|
if not query:
|
||||||
|
return
|
||||||
|
query.favourite = favourite
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
def new_item(self) -> None:
|
def new_item(self) -> None:
|
||||||
self.callbacks.new_item()
|
"""Create new query"""
|
||||||
|
|
||||||
|
query_name = get_name(prompt="New query name:")
|
||||||
|
if not query_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
query = Queries(self.session, query_name, Filter())
|
||||||
|
self._edit_item(query)
|
||||||
|
self.refresh_table()
|
||||||
|
|
||||||
|
def rename_item(self, query_id: int) -> None:
|
||||||
|
"""rename query"""
|
||||||
|
|
||||||
|
query = self.session.get(Queries, query_id)
|
||||||
|
if not query:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.delete({query_id=}) can't load query"
|
||||||
|
)
|
||||||
|
new_name = get_name(prompt="New query name", default=query.name)
|
||||||
|
if not new_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
query.name = new_name
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
self.change_text(query_id, new_name)
|
||||||
|
|
||||||
|
|
||||||
|
class ManageTemplates(ItemlistManager):
|
||||||
|
"""
|
||||||
|
Delete / edit templates
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, session: Session, musicmuster: Window) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.session = session
|
||||||
|
self.musicmuster = musicmuster
|
||||||
|
self.refresh_table()
|
||||||
|
self.exec()
|
||||||
|
|
||||||
|
def refresh_table(self) -> None:
|
||||||
|
"""
|
||||||
|
Update table in widget
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Build a list of templates
|
||||||
|
template_list: list[ItemlistItem] = []
|
||||||
|
|
||||||
|
for template in Playlists.get_all_templates(self.session):
|
||||||
|
template_list.append(
|
||||||
|
ItemlistItem(
|
||||||
|
name=template.name, id=template.id, favourite=template.favourite
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.populate_table(template_list)
|
||||||
|
|
||||||
|
def delete_item(self, template_id: int) -> None:
|
||||||
|
"""delete template"""
|
||||||
|
|
||||||
|
template = self.session.get(Playlists, template_id)
|
||||||
|
if not template:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.delete({template_id=}) can't load template"
|
||||||
|
)
|
||||||
|
if helpers.ask_yes_no(
|
||||||
|
"Delete template",
|
||||||
|
f"Delete template '{template.name}': Are you sure?",
|
||||||
|
):
|
||||||
|
# If template is currently open, re-check
|
||||||
|
open_idx = self.musicmuster.get_tab_index_for_playlist(template_id)
|
||||||
|
if open_idx:
|
||||||
|
if not helpers.ask_yes_no(
|
||||||
|
"Delete open template",
|
||||||
|
f"Template '{template.name}' is currently open. Really delete?",
|
||||||
|
):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.musicmuster.playlist_section.tabPlaylist.removeTab(open_idx)
|
||||||
|
|
||||||
|
log.debug(f"manage_templates: delete {template=}")
|
||||||
|
self.session.delete(template)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
def edit_item(self, template_id: int) -> None:
|
||||||
|
"""Edit template"""
|
||||||
|
|
||||||
|
template = self.session.get(Playlists, template_id)
|
||||||
|
if not template:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.edit({template_id=}) can't load template"
|
||||||
|
)
|
||||||
|
# Simply load the template as a playlist. Any changes
|
||||||
|
# made will persist
|
||||||
|
self.musicmuster._open_playlist(template, is_template=True)
|
||||||
|
|
||||||
|
def toggle_favourite(self, template_id: int, favourite: bool) -> None:
|
||||||
|
"""Mark template as (not) favourite"""
|
||||||
|
|
||||||
|
template = self.session.get(Playlists, template_id)
|
||||||
|
if not template:
|
||||||
|
return
|
||||||
|
template.favourite = favourite
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
def new_item(
|
||||||
|
self,
|
||||||
|
) -> None:
|
||||||
|
"""Create new template"""
|
||||||
|
|
||||||
|
# Get base template
|
||||||
|
template_id = self.musicmuster.solicit_template_to_use(
|
||||||
|
self.session, template_prompt="New template based upon:"
|
||||||
|
)
|
||||||
|
if template_id is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get new template name
|
||||||
|
name = self.musicmuster.get_playlist_name(
|
||||||
|
self.session, default="", prompt="New template name:"
|
||||||
|
)
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create playlist for template and mark is as a template
|
||||||
|
template = self.musicmuster._create_playlist(self.session, name, template_id)
|
||||||
|
template.is_template = True
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
# Open it for editing
|
||||||
|
self.musicmuster._open_playlist(template, is_template=True)
|
||||||
|
|
||||||
|
def rename_item(self, template_id: int) -> None:
|
||||||
|
"""rename template"""
|
||||||
|
|
||||||
|
template = self.session.get(Playlists, template_id)
|
||||||
|
if not template:
|
||||||
|
raise ApplicationError(
|
||||||
|
f"manage_template.delete({template_id=}) can't load template"
|
||||||
|
)
|
||||||
|
new_name = self.musicmuster.get_playlist_name(self.session, template.name)
|
||||||
|
if not new_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
template.name = new_name
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
self.change_text(template_id, new_name)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -884,7 +1129,7 @@ class Window(QMainWindow):
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"separator": True,
|
"separator": True,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
templates = Playlists.get_favourite_templates(session)
|
templates = Playlists.get_favourite_templates(session)
|
||||||
for template in templates:
|
for template in templates:
|
||||||
@ -965,7 +1210,7 @@ class Window(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
template_id = selected_template_id
|
template_id = selected_template_id
|
||||||
|
|
||||||
playlist_name = self.solicit_name(session)
|
playlist_name = self.get_playlist_name(session)
|
||||||
if not playlist_name:
|
if not playlist_name:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1030,10 +1275,10 @@ class Window(QMainWindow):
|
|||||||
session.commit()
|
session.commit()
|
||||||
helpers.show_OK("Template", "Template saved", self)
|
helpers.show_OK("Template", "Template saved", self)
|
||||||
|
|
||||||
def solicit_name(
|
def get_playlist_name(
|
||||||
self, session: Session, default: str = "", prompt: str = "Playlist name:"
|
self, session: Session, default: str = "", prompt: str = "Playlist name:"
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
"""Get name of new playlist from user"""
|
"""Get a name from the user"""
|
||||||
|
|
||||||
dlg = QInputDialog(self)
|
dlg = QInputDialog(self)
|
||||||
dlg.setInputMode(QInputDialog.InputMode.TextInput)
|
dlg.setInputMode(QInputDialog.InputMode.TextInput)
|
||||||
@ -1080,213 +1325,21 @@ class Window(QMainWindow):
|
|||||||
|
|
||||||
# # # # # # # # # # Manage templates and queries # # # # # # # # # #
|
# # # # # # # # # # Manage templates and queries # # # # # # # # # #
|
||||||
|
|
||||||
def manage_queries(self) -> None:
|
def manage_queries_wrapper(self):
|
||||||
"""
|
"""
|
||||||
Delete / edit queries
|
Simply instantiate the manage_queries class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Define callbacks to handle management options
|
|
||||||
def delete(query_id: int) -> None:
|
|
||||||
"""delete query"""
|
|
||||||
|
|
||||||
query = session.get(Queries, query_id)
|
|
||||||
if not query:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.delete({query_id=}) can't load query"
|
|
||||||
)
|
|
||||||
if helpers.ask_yes_no(
|
|
||||||
"Delete query",
|
|
||||||
f"Delete query '{query.name}': " "Are you sure?",
|
|
||||||
):
|
|
||||||
log.info(f"manage_queries: delete {query=}")
|
|
||||||
session.delete(query)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
def edit(query_id: int) -> None:
|
|
||||||
"""Edit query"""
|
|
||||||
|
|
||||||
query = session.get(Queries, query_id)
|
|
||||||
if not query:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.edit({query_id=}) can't load query"
|
|
||||||
)
|
|
||||||
import pdb; pdb.set_trace()
|
|
||||||
dlg = FilterDialog(query.name, query.filter)
|
|
||||||
dlg.show()
|
|
||||||
|
|
||||||
def favourite(query_id: int, favourite: bool) -> None:
|
|
||||||
"""Mark query as (not) favourite"""
|
|
||||||
|
|
||||||
query = session.get(Queries, query_id)
|
|
||||||
query.favourite = favourite
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
def new_item() -> None:
|
|
||||||
"""Create new query"""
|
|
||||||
|
|
||||||
# TODO: create query
|
|
||||||
print("create query")
|
|
||||||
|
|
||||||
def rename(query_id: int) -> Optional[str]:
|
|
||||||
"""rename query"""
|
|
||||||
|
|
||||||
query = session.get(Queries, query_id)
|
|
||||||
if not query:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.delete({query_id=}) can't load query"
|
|
||||||
)
|
|
||||||
new_name = self.solicit_name(session, query.name, prompt="New query name")
|
|
||||||
if new_name:
|
|
||||||
query.rename(session, new_name)
|
|
||||||
idx = self.tabBar.currentIndex()
|
|
||||||
self.tabBar.setTabText(idx, new_name)
|
|
||||||
session.commit()
|
|
||||||
return new_name
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Call listitem management dialog to manage queries
|
|
||||||
callbacks = ItemlistManagerCallbacks(
|
|
||||||
delete=delete,
|
|
||||||
edit=edit,
|
|
||||||
favourite=favourite,
|
|
||||||
new_item=new_item,
|
|
||||||
rename=rename,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Build a list of queries
|
|
||||||
query_list: list[ItemlistItem] = []
|
|
||||||
|
|
||||||
with db.Session() as session:
|
with db.Session() as session:
|
||||||
for query in Queries.get_all_queries(session):
|
_ = ManageQueries(session, self)
|
||||||
query_list.append(
|
|
||||||
ItemlistItem(
|
|
||||||
name=query.name, id=query.id, favourite=query.favourite
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# We need to retain a reference to the dialog box to stop it
|
|
||||||
# going out of scope and being garbage-collected.
|
|
||||||
self.dlg = ItemlistManager(query_list, callbacks)
|
|
||||||
self.dlg.show()
|
|
||||||
|
|
||||||
def manage_templates(self) -> None:
|
def manage_templates_wrapper(self):
|
||||||
"""
|
"""
|
||||||
Delete / edit templates
|
Simply instantiate the manage_queries class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Define callbacks to handle management options
|
|
||||||
def delete(template_id: int) -> None:
|
|
||||||
"""delete template"""
|
|
||||||
|
|
||||||
template = session.get(Playlists, template_id)
|
|
||||||
if not template:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.delete({template_id=}) can't load template"
|
|
||||||
)
|
|
||||||
if helpers.ask_yes_no(
|
|
||||||
"Delete template",
|
|
||||||
f"Delete template '{template.name}': " "Are you sure?",
|
|
||||||
):
|
|
||||||
# If template is currently open, re-check
|
|
||||||
open_idx = self.get_tab_index_for_playlist(template_id)
|
|
||||||
if open_idx:
|
|
||||||
if not helpers.ask_yes_no(
|
|
||||||
"Delete open template",
|
|
||||||
f"Template '{template.name}' is currently open. Really delete?",
|
|
||||||
):
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
self.playlist_section.tabPlaylist.removeTab(open_idx)
|
|
||||||
|
|
||||||
log.info(f"manage_templates: delete {template=}")
|
|
||||||
session.delete(template)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
def edit(template_id: int) -> None:
|
|
||||||
"""Edit template"""
|
|
||||||
|
|
||||||
template = session.get(Playlists, template_id)
|
|
||||||
if not template:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.edit({template_id=}) can't load template"
|
|
||||||
)
|
|
||||||
# Simply load the template as a playlist. Any changes
|
|
||||||
# made will persist
|
|
||||||
self._open_playlist(template, is_template=True)
|
|
||||||
|
|
||||||
def favourite(template_id: int, favourite: bool) -> None:
|
|
||||||
"""Mark template as (not) favourite"""
|
|
||||||
|
|
||||||
template = session.get(Playlists, template_id)
|
|
||||||
template.favourite = favourite
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
def new_item() -> None:
|
|
||||||
"""Create new template"""
|
|
||||||
|
|
||||||
# Get base template
|
|
||||||
template_id = self.solicit_template_to_use(
|
|
||||||
session, template_prompt="New template based upon:"
|
|
||||||
)
|
|
||||||
if template_id is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Get new template name
|
|
||||||
name = self.solicit_name(
|
|
||||||
session, default="", prompt="New template name:"
|
|
||||||
)
|
|
||||||
if not name:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Create playlist for template and mark is as a template
|
|
||||||
template = self._create_playlist(session, name, template_id)
|
|
||||||
template.is_template = True
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
# Open it for editing
|
|
||||||
self._open_playlist(template, is_template=True)
|
|
||||||
|
|
||||||
def rename(template_id: int) -> Optional[str]:
|
|
||||||
"""rename template"""
|
|
||||||
|
|
||||||
template = session.get(Playlists, template_id)
|
|
||||||
if not template:
|
|
||||||
raise ApplicationError(
|
|
||||||
f"manage_template.delete({template_id=}) can't load template"
|
|
||||||
)
|
|
||||||
new_name = self.solicit_name(session, template.name)
|
|
||||||
if new_name:
|
|
||||||
template.rename(session, new_name)
|
|
||||||
idx = self.tabBar.currentIndex()
|
|
||||||
self.tabBar.setTabText(idx, new_name)
|
|
||||||
session.commit()
|
|
||||||
return new_name
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Call listitem management dialog to manage templates
|
|
||||||
callbacks = ItemlistManagerCallbacks(
|
|
||||||
delete=delete,
|
|
||||||
edit=edit,
|
|
||||||
favourite=favourite,
|
|
||||||
new_item=new_item,
|
|
||||||
rename=rename,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Build a list of templates
|
|
||||||
template_list: list[ItemlistItem] = []
|
|
||||||
|
|
||||||
with db.Session() as session:
|
with db.Session() as session:
|
||||||
for template in Playlists.get_all_templates(session):
|
_ = ManageTemplates(session, self)
|
||||||
template_list.append(
|
|
||||||
ItemlistItem(
|
|
||||||
name=template.name, id=template.id, favourite=template.favourite
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# We need to retain a reference to the dialog box to stop it
|
|
||||||
# going out of scope and being garbage-collected.
|
|
||||||
self.dlg = ItemlistManager(template_list, callbacks)
|
|
||||||
self.dlg.show()
|
|
||||||
|
|
||||||
# # # # # # # # # # Miscellaneous functions # # # # # # # # # #
|
# # # # # # # # # # Miscellaneous functions # # # # # # # # # #
|
||||||
|
|
||||||
@ -1999,7 +2052,7 @@ class Window(QMainWindow):
|
|||||||
playlist_id = self.current.playlist_id
|
playlist_id = self.current.playlist_id
|
||||||
playlist = session.get(Playlists, playlist_id)
|
playlist = session.get(Playlists, playlist_id)
|
||||||
if playlist:
|
if playlist:
|
||||||
new_name = self.solicit_name(session, playlist.name)
|
new_name = self.get_playlist_name(session, playlist.name)
|
||||||
if new_name:
|
if new_name:
|
||||||
playlist.rename(session, new_name)
|
playlist.rename(session, new_name)
|
||||||
idx = self.tabBar.currentIndex()
|
idx = self.tabBar.currentIndex()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user