WIP: template management: new, rename, delete working
This commit is contained in:
parent
e10c2adafe
commit
5f396a0993
@ -203,12 +203,12 @@ class Playlists(dbtables.PlaylistsTable):
|
||||
|
||||
@classmethod
|
||||
def create_playlist_from_template(
|
||||
cls, session: Session, template: "Playlists", playlist_name: str
|
||||
cls, session: Session, template_id: int, playlist_name: str
|
||||
) -> Optional["Playlists"]:
|
||||
"""Create a new playlist from template"""
|
||||
|
||||
# Sanity check
|
||||
if not template.id:
|
||||
if not template_id:
|
||||
return None
|
||||
|
||||
playlist = cls(session, playlist_name)
|
||||
@ -217,7 +217,7 @@ class Playlists(dbtables.PlaylistsTable):
|
||||
if not playlist or not playlist.id:
|
||||
return None
|
||||
|
||||
PlaylistRows.copy_playlist(session, template.id, playlist.id)
|
||||
PlaylistRows.copy_playlist(session, template_id, playlist.id)
|
||||
|
||||
return playlist
|
||||
|
||||
|
||||
@ -83,18 +83,6 @@ from utilities import check_db, update_bitrates
|
||||
import helpers
|
||||
|
||||
|
||||
class DownloadCSV(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__()
|
||||
|
||||
self.ui = Ui_DateSelect()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.dateTimeEdit.setDate(QDate.currentDate())
|
||||
self.ui.dateTimeEdit.setTime(QTime(19, 59, 0))
|
||||
self.ui.buttonBox.accepted.connect(self.accept)
|
||||
self.ui.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
|
||||
class Current:
|
||||
base_model: PlaylistModel
|
||||
proxy_model: PlaylistProxyModel
|
||||
@ -267,7 +255,16 @@ class ItemlistManager(QDialog):
|
||||
self.callbacks.edit(item_id)
|
||||
|
||||
def rename_item(self, item_id: int) -> None:
|
||||
print(f"Rename item {item_id}")
|
||||
new_name = self.callbacks.rename(item_id)
|
||||
if not new_name:
|
||||
return
|
||||
# Rename item in list
|
||||
for row in range(self.table.rowCount()):
|
||||
item = self.table.item(row, 0)
|
||||
if item and self.items[row].id == item_id:
|
||||
item.setText(new_name)
|
||||
self.items[row].name = new_name
|
||||
break
|
||||
|
||||
def toggle_favourite(self, item_id: int, checked: bool) -> None:
|
||||
print(f"Toggle favourite for item {item_id}: {checked}")
|
||||
@ -294,7 +291,7 @@ class ItemlistManagerCallbacks:
|
||||
edit: Callable[[int], None]
|
||||
favourite: Callable[[int, bool], None]
|
||||
new_item: Callable[[], None]
|
||||
rename: Callable[[int], None]
|
||||
rename: Callable[[int], Optional[str]]
|
||||
|
||||
|
||||
class PreviewManager:
|
||||
@ -459,16 +456,21 @@ class TemplateSelectorDialog(QDialog):
|
||||
Class to manage user selection of template
|
||||
"""
|
||||
|
||||
def __init__(self, templates: list[tuple[str, int]]) -> None:
|
||||
def __init__(
|
||||
self, templates: list[tuple[str, int]], template_prompt: Optional[str]
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.templates = templates
|
||||
self.template_prompt = template_prompt
|
||||
self.selected_id = None
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
# Create label
|
||||
label = QLabel("Select template:")
|
||||
if not self.template_prompt:
|
||||
self.template_prompt = "Select template:"
|
||||
label = QLabel(self.template_prompt)
|
||||
|
||||
# Create combo box
|
||||
self.combo_box = QComboBox()
|
||||
@ -868,14 +870,22 @@ class Window(QMainWindow):
|
||||
self.signals.search_songfacts_signal.connect(self.open_songfacts_browser)
|
||||
self.signals.search_wikipedia_signal.connect(self.open_wikipedia_browser)
|
||||
|
||||
def create_playlist(
|
||||
self, session: Session, playlist_name: str
|
||||
) -> Optional[Playlists]:
|
||||
def create_playlist(self, session: Session, template_id: int) -> Optional[Playlists]:
|
||||
"""Create new playlist"""
|
||||
|
||||
log.debug(f"create_playlist({playlist_name=}")
|
||||
# Get a name for this new playlist
|
||||
playlist_name = self.solicit_playlist_name(session)
|
||||
if not playlist_name:
|
||||
return None
|
||||
|
||||
# If template.id == 0, user doesn't want a template
|
||||
playlist: Optional[Playlists]
|
||||
if template_id == 0:
|
||||
playlist = Playlists(session, playlist_name)
|
||||
else:
|
||||
playlist = Playlists.create_playlist_from_template(
|
||||
session, template_id, playlist_name
|
||||
)
|
||||
|
||||
if playlist:
|
||||
return playlist
|
||||
@ -1072,6 +1082,18 @@ class Window(QMainWindow):
|
||||
if track_sequence.current:
|
||||
track_sequence.current.fade()
|
||||
|
||||
def get_tab_index_for_playlist(self, playlist_id: int) -> Optional[int]:
|
||||
"""
|
||||
Return the tab index for the passed playlist_id if it is displayed,
|
||||
else return None.
|
||||
"""
|
||||
|
||||
for idx in range(self.playlist_section.tabPlaylist.count()):
|
||||
if self.playlist_section.tabPlaylist.widget(idx).playlist_id == playlist_id:
|
||||
return idx
|
||||
|
||||
return None
|
||||
|
||||
def hide_played(self):
|
||||
"""Toggle hide played tracks"""
|
||||
|
||||
@ -1178,6 +1200,7 @@ class Window(QMainWindow):
|
||||
Delete / edit templates
|
||||
"""
|
||||
|
||||
# Define callbacks to handle management options
|
||||
def delete(template_id: int) -> None:
|
||||
"""delete template"""
|
||||
|
||||
@ -1191,19 +1214,15 @@ class Window(QMainWindow):
|
||||
f"Delete template '{template.name}': " "Are you sure?",
|
||||
):
|
||||
# If template is currently open, re-check
|
||||
for idx in range(self.playlist_section.tabPlaylist.count()):
|
||||
if (
|
||||
self.playlist_section.tabPlaylist.widget(idx).playlist_id
|
||||
== template_id
|
||||
):
|
||||
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?"
|
||||
f"Template '{template.name}' is currently open. Really delete?",
|
||||
):
|
||||
return
|
||||
else:
|
||||
self.playlist_section.tabPlaylist.removeTab(idx)
|
||||
break
|
||||
self.playlist_section.tabPlaylist.removeTab(open_idx)
|
||||
|
||||
log.info(f"manage_templates: delete {template=}")
|
||||
template.delete(session)
|
||||
@ -1223,25 +1242,50 @@ class Window(QMainWindow):
|
||||
self.playlist_section.tabPlaylist.setCurrentIndex(idx)
|
||||
|
||||
def favourite(template_id: int, favourite: bool) -> None:
|
||||
"""favourite template"""
|
||||
"""Mark template as (not) favourite"""
|
||||
|
||||
print(f"manage_templates.favourite({template_id=}")
|
||||
print(f"{session=}")
|
||||
|
||||
def new_item() -> None:
|
||||
"""new item"""
|
||||
"""Create new template"""
|
||||
|
||||
print("manage_templates.new()")
|
||||
print(f"{session=}")
|
||||
# Get base template
|
||||
template_id = self.solicit_template_to_use(
|
||||
session, template_prmompt="New template based upon:"
|
||||
)
|
||||
if template_id is None:
|
||||
return
|
||||
|
||||
def rename(template_id: int) -> None:
|
||||
new_template = self.create_playlist(session, template_id)
|
||||
if new_template:
|
||||
self.open_playlist(session, new_template)
|
||||
|
||||
def rename(template_id: int) -> Optional[str]:
|
||||
"""rename template"""
|
||||
|
||||
print(f"manage_templates.rename({template_id=}")
|
||||
print(f"{session=}")
|
||||
template = session.get(Playlists, template_id)
|
||||
if not template:
|
||||
raise ApplicationError(
|
||||
f"manage_templeate.delete({template_id=}) can't load template"
|
||||
)
|
||||
new_name = self.solicit_playlist_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
|
||||
delete=delete,
|
||||
edit=edit,
|
||||
favourite=favourite,
|
||||
new_item=new_item,
|
||||
rename=rename,
|
||||
)
|
||||
|
||||
# Build a list of templates
|
||||
@ -1251,8 +1295,10 @@ class Window(QMainWindow):
|
||||
for template in Playlists.get_all_templates(session):
|
||||
# TODO: need to add in favourites
|
||||
template_list.append(ItemlistItem(name=template.name, id=template.id))
|
||||
x = ItemlistManager(template_list, callbacks)
|
||||
x.show()
|
||||
# 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()
|
||||
|
||||
def mark_rows_for_moving(self) -> None:
|
||||
"""
|
||||
@ -1337,37 +1383,17 @@ class Window(QMainWindow):
|
||||
self.move_playlist_rows(unplayed_rows)
|
||||
self.disable_selection_timing = False
|
||||
|
||||
def new_playlist(self) -> None:
|
||||
def new_playlist(self) -> Optional[Playlists]:
|
||||
"""
|
||||
Create new playlist, optionally from template
|
||||
"""
|
||||
|
||||
# Build a list of (template-name, playlist-id) tuples starting
|
||||
# with the "no template" entry
|
||||
template_list: list[tuple[str, int]] = []
|
||||
template_list.append((Config.NO_TEMPLATE_NAME, 0))
|
||||
|
||||
with db.Session() as session:
|
||||
for template in Playlists.get_all_templates(session):
|
||||
template_list.append((template.name, template.id))
|
||||
template_id = self.solicit_template_to_use(session)
|
||||
if not template_id:
|
||||
return None # User cancelled
|
||||
|
||||
dlg = TemplateSelectorDialog(template_list)
|
||||
if not dlg.exec():
|
||||
return # User cancelled
|
||||
template_id = dlg.selected_id
|
||||
|
||||
# Get a name for this new playlist
|
||||
playlist_name = self.solicit_playlist_name(session)
|
||||
if not playlist_name:
|
||||
return
|
||||
|
||||
# If template_id == 0, user doesn't want a template
|
||||
if template_id == 0:
|
||||
playlist = self.create_playlist(session, playlist_name)
|
||||
else:
|
||||
playlist = Playlists.create_playlist_from_template(
|
||||
session, template, playlist_name
|
||||
)
|
||||
playlist = self.create_playlist(session, template_id)
|
||||
|
||||
if playlist:
|
||||
playlist.mark_open()
|
||||
@ -1376,10 +1402,13 @@ class Window(QMainWindow):
|
||||
session.commit()
|
||||
idx = self.create_playlist_tab(playlist)
|
||||
self.playlist_section.tabPlaylist.setCurrentIndex(idx)
|
||||
return playlist
|
||||
else:
|
||||
log.error("Playlist failed to create")
|
||||
ApplicationError("new_playlist: Playlist failed to create")
|
||||
|
||||
def open_playlist(self) -> None:
|
||||
return None
|
||||
|
||||
def open_existing_playlist(self) -> None:
|
||||
"""Open existing playlist"""
|
||||
|
||||
with db.Session() as session:
|
||||
@ -1388,6 +1417,11 @@ class Window(QMainWindow):
|
||||
dlg.exec()
|
||||
playlist = dlg.playlist
|
||||
if playlist:
|
||||
self.open_playlist(session, playlist)
|
||||
|
||||
def open_playlist(self, session: Session, playlist: Playlists) -> None:
|
||||
"""Open passed playlist"""
|
||||
|
||||
idx = self.create_playlist_tab(playlist)
|
||||
playlist.mark_open()
|
||||
session.commit()
|
||||
@ -1859,24 +1893,45 @@ class Window(QMainWindow):
|
||||
|
||||
# Switch to correct tab
|
||||
if playlist_id != self.current.playlist_id:
|
||||
for idx in range(self.playlist_section.tabPlaylist.count()):
|
||||
if (
|
||||
self.playlist_section.tabPlaylist.widget(idx).playlist_id
|
||||
== playlist_id
|
||||
):
|
||||
self.playlist_section.tabPlaylist.setCurrentIndex(idx)
|
||||
break
|
||||
open_idx = self.get_tab_index_for_playlist(playlist_id)
|
||||
if open_idx:
|
||||
self.playlist_section.tabPlaylist.setCurrentIndex(open_idx)
|
||||
else:
|
||||
raise ApplicationError(
|
||||
f"show_track() can't find current playlist tab {playlist_id=}"
|
||||
)
|
||||
|
||||
self.active_tab().scroll_to_top(playlist_track.row_number)
|
||||
|
||||
def solicit_template_to_use(
|
||||
self, session: Session, template_prmompt: Optional[str] = None
|
||||
) -> Optional[int]:
|
||||
"""
|
||||
Have user select a template. Return the template.id, or None if they cancel.
|
||||
template_id of zero means don't use a template.
|
||||
"""
|
||||
|
||||
template_name_id_list: list[tuple[str, int]] = []
|
||||
template_name_id_list.append((Config.NO_TEMPLATE_NAME, 0))
|
||||
|
||||
with db.Session() as session:
|
||||
for template in Playlists.get_all_templates(session):
|
||||
template_name_id_list.append((template.name, template.id))
|
||||
|
||||
dlg = TemplateSelectorDialog(template_name_id_list, template_prmompt)
|
||||
if not dlg.exec() or dlg.selected_id is None:
|
||||
return None # User cancelled
|
||||
|
||||
return dlg.selected_id
|
||||
|
||||
def solicit_playlist_name(
|
||||
self, session: Session, default: str = ""
|
||||
self, session: Session, default: str = "", prompt: str = "Playlist name:"
|
||||
) -> Optional[str]:
|
||||
"""Get name of new playlist from user"""
|
||||
|
||||
dlg = QInputDialog(self)
|
||||
dlg.setInputMode(QInputDialog.InputMode.TextInput)
|
||||
dlg.setLabelText("Playlist name:")
|
||||
dlg.setLabelText(prompt)
|
||||
while True:
|
||||
if default:
|
||||
dlg.setTextValue(default)
|
||||
|
||||
@ -26,6 +26,7 @@ from PyQt6.QtGui import (
|
||||
)
|
||||
|
||||
# Third party imports
|
||||
from sqlalchemy.orm.session import Session
|
||||
import obswebsocket # type: ignore
|
||||
|
||||
# import snoop # type: ignore
|
||||
@ -772,7 +773,7 @@ class PlaylistModel(QAbstractTableModel):
|
||||
|
||||
return None
|
||||
|
||||
def load_data(self, session: db.session) -> None:
|
||||
def load_data(self, session: Session) -> None:
|
||||
"""
|
||||
Same as refresh data, but only used when creating playslit.
|
||||
Distinguishes profile time between initial load and other
|
||||
@ -1061,7 +1062,7 @@ class PlaylistModel(QAbstractTableModel):
|
||||
# Update display
|
||||
self.invalidate_row(track_sequence.previous.row_number)
|
||||
|
||||
def refresh_data(self, session: db.session) -> None:
|
||||
def refresh_data(self, session: Session) -> None:
|
||||
"""
|
||||
Populate self.playlist_rows with playlist data
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user