From 67bf926ed873055969f284c024985fe45db0b199 Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Sun, 23 Feb 2025 17:28:03 +0000 Subject: [PATCH] Refactor musicmuster and template management --- app/models.py | 19 ++++- app/musicmuster.py | 152 ++++++++++++--------------------- app/ui/main_window_playlist.ui | 2 +- 3 files changed, 72 insertions(+), 101 deletions(-) diff --git a/app/models.py b/app/models.py index e6a96ac..238e71a 100644 --- a/app/models.py +++ b/app/models.py @@ -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 diff --git a/app/musicmuster.py b/app/musicmuster.py index 95f094d..bdf0cdf 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -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""" diff --git a/app/ui/main_window_playlist.ui b/app/ui/main_window_playlist.ui index 6bcee88..4b8fb1a 100644 --- a/app/ui/main_window_playlist.ui +++ b/app/ui/main_window_playlist.ui @@ -7,7 +7,7 @@ 0 0 1249 - 499 + 538