Refactor musicmuster and template management

This commit is contained in:
Keith Edmunds 2025-02-23 17:28:03 +00:00
parent 040020e7ed
commit 67bf926ed8
3 changed files with 72 additions and 101 deletions

View File

@ -233,6 +233,19 @@ class Playlists(dbtables.PlaylistsTable):
select(cls).where(cls.is_template.is_(True)).order_by(cls.name)
).all()
@classmethod
def get_favourite_templates(cls, session: Session) -> Sequence["Playlists"]:
"""Returns a list of favourite templates ordered by name"""
return session.scalars(
select(cls)
.where(
cls.is_template.is_(True),
cls.favourite.is_(True)
)
.order_by(cls.name)
).all()
@classmethod
def get_closed(cls, session: Session) -> Sequence["Playlists"]:
"""Returns a list of all closed playlists ordered by last use"""
@ -287,7 +300,7 @@ class Playlists(dbtables.PlaylistsTable):
) -> None:
"""Save passed playlist as new template"""
template = Playlists(session, template_name)
template = Playlists(session, template_name, template_id=0)
if not template or not template.id:
return
@ -582,7 +595,7 @@ class PlaylistRows(dbtables.PlaylistRowsTable):
class Settings(dbtables.SettingsTable):
def __init__(self, session: Session, name: str):
def __init__(self, session: Session, name: str) -> None:
self.name = name
session.add(self)
session.commit()
@ -610,7 +623,7 @@ class Tracks(dbtables.TracksTable):
fade_at: int,
silence_at: int,
bitrate: int,
):
) -> None:
self.path = path
self.title = title
self.artist = artist

View File

@ -601,6 +601,61 @@ class Window(QMainWindow):
self.load_last_playlists()
self.stop_autoplay = False
# # # # # # # # # # Overrides # # # # # # # # # #
def closeEvent(self, event: Optional[QCloseEvent]) -> None:
"""Handle attempt to close main window"""
if not event:
return
# Don't allow window to close when a track is playing
if track_sequence.current and track_sequence.current.is_playing():
event.ignore()
helpers.show_warning(
self, "Track playing", "Can't close application while track is playing"
)
else:
with db.Session() as session:
# Save tab number of open playlists
open_playlist_ids: dict[int, int] = {}
for idx in range(self.playlist_section.tabPlaylist.count()):
open_playlist_ids[
self.playlist_section.tabPlaylist.widget(idx).playlist_id
] = idx
Playlists.clear_tabs(session, list(open_playlist_ids.keys()))
for playlist_id, idx in open_playlist_ids.items():
playlist = session.get(Playlists, playlist_id)
if playlist:
log.debug(f"Set {playlist=} tab to {idx=}")
playlist.tab = idx
# Save window attributes
attributes_to_save = dict(
mainwindow_height=self.height(),
mainwindow_width=self.width(),
mainwindow_x=self.x(),
mainwindow_y=self.y(),
active_tab=self.playlist_section.tabPlaylist.currentIndex(),
)
for name, value in attributes_to_save.items():
record = Settings.get_setting(session, name)
record.f_int = value
session.commit()
event.accept()
# # # # # # # # # # Internal utility functions # # # # # # # # # #
def active_base_model(self) -> PlaylistModel:
return self.current.base_model
def active_tab(self) -> PlaylistTab:
return self.playlist_section.tabPlaylist.currentWidget()
# # # # # # # # # # Menu functions # # # # # # # # # #
def create_action(
self, text: str, handler: Callable, shortcut: Optional[str] = None
) -> QAction:
@ -921,12 +976,6 @@ class Window(QMainWindow):
QMessageBox.StandardButton.Ok,
)
def active_base_model(self) -> PlaylistModel:
return self.current.base_model
def active_tab(self) -> PlaylistTab:
return self.playlist_section.tabPlaylist.currentWidget()
def clear_next(self) -> None:
"""
Clear next track
@ -945,49 +994,6 @@ class Window(QMainWindow):
# Clear the search bar
self.search_playlist_clear()
def closeEvent(self, event: Optional[QCloseEvent]) -> None:
"""Handle attempt to close main window"""
if not event:
return
# Don't allow window to close when a track is playing
if track_sequence.current and track_sequence.current.is_playing():
event.ignore()
helpers.show_warning(
self, "Track playing", "Can't close application while track is playing"
)
else:
with db.Session() as session:
# Save tab number of open playlists
open_playlist_ids: dict[int, int] = {}
for idx in range(self.playlist_section.tabPlaylist.count()):
open_playlist_ids[
self.playlist_section.tabPlaylist.widget(idx).playlist_id
] = idx
Playlists.clear_tabs(session, list(open_playlist_ids.keys()))
for playlist_id, idx in open_playlist_ids.items():
playlist = session.get(Playlists, playlist_id)
if playlist:
log.debug(f"Set {playlist=} tab to {idx=}")
playlist.tab = idx
# Save window attributes
attributes_to_save = dict(
mainwindow_height=self.height(),
mainwindow_width=self.width(),
mainwindow_x=self.x(),
mainwindow_y=self.y(),
active_tab=self.playlist_section.tabPlaylist.currentIndex(),
)
for name, value in attributes_to_save.items():
record = Settings.get_setting(session, name)
record.f_int = value
session.commit()
event.accept()
def close_playlist_tab(self) -> bool:
"""
Close active playlist tab, called by menu item
@ -1985,54 +1991,6 @@ class Window(QMainWindow):
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 = "", prompt: str = "Playlist name:"
) -> Optional[str]:
"""Get name of new playlist from user"""
dlg = QInputDialog(self)
dlg.setInputMode(QInputDialog.InputMode.TextInput)
dlg.setLabelText(prompt)
while True:
if default:
dlg.setTextValue(default)
dlg.resize(500, 100)
ok = dlg.exec()
if ok:
proposed_name = dlg.textValue()
if Playlists.name_is_available(session, proposed_name):
return proposed_name
else:
helpers.show_warning(
self,
"Name in use",
f"There's already a playlist called '{proposed_name}'",
)
continue
else:
return None
def stop(self) -> None:
"""Stop playing immediately"""

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>1249</width>
<height>499</height>
<height>538</height>
</rect>
</property>
<property name="windowTitle">