From b2fe5f6f38bb98439a977749e54272d1750a1c4e Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Sun, 25 Apr 2021 00:04:01 +0100 Subject: [PATCH] Maintain track headers when changing playlists --- app/musicmuster.py | 6 ++-- app/playlists.py | 85 ++++++++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/app/musicmuster.py b/app/musicmuster.py index b469850..5ca6578 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -50,9 +50,9 @@ class Window(QMainWindow, Ui_MainWindow): # Hard code to the first playlist for now # TODO - if self.playlist.load_playlist(1): - self.update_headers() - self.enable_play_next_controls() + self.playlist.load_playlist(1) + self.update_headers() + self.enable_play_next_controls() self.plLabel = QLabel(f"Playlist: {self.playlist.playlist_name}") self.statusbar.addPermanentWidget(self.plLabel) diff --git a/app/playlists.py b/app/playlists.py index d6ea416..f3ab5b5 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -17,6 +17,7 @@ from PyQt5.QtWidgets import ( import helpers import music +import os from config import Config from datetime import datetime, timedelta @@ -25,7 +26,6 @@ from model import Notes, Playdates, Playlists, PlaylistTracks, Settings, Tracks from ui.dlg_search_database_ui import Ui_Dialog from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist - class Playlist(QTableWidget): # Column names COL_INDEX = 0 @@ -364,6 +364,12 @@ class Playlist(QTableWidget): def calculate_next_start_time(self, row, start): "Return this row's end time given its start time" + if start is None: + return None + if row is None: + DEBUG("calculate_next_start_time() called with row=None") + return None + duration = Tracks.get_duration( int(self.item(row, self.COL_INDEX).text())) return start + timedelta(milliseconds=duration) @@ -387,8 +393,6 @@ class Playlist(QTableWidget): Load tracks and notes from playlist id. Set first track as next track to play. - - Return True if successful else False. """ DEBUG(f"load_playlist(plid={plid})") @@ -416,22 +420,36 @@ class Playlist(QTableWidget): for item in sorted(data, key=lambda x: x[0]): self.add_to_playlist(item[1], repaint=False) - # Set the first non-notes row as next track to play - notes_rows = self.meta_get_notes() - for row in range(self.rowCount()): - if row in notes_rows: - continue - self.meta_set_next(row) - self.tracks_changed() - return True + # If this is not the first playlist loaded, we may already have + # a next track set in which case don't change it. Otherwise, set + # the first non-notes row as next track to play. + if not self.next_track: + notes_rows = self.meta_get_notes() + for row in range(self.rowCount()): + if row in notes_rows: + continue + self.cue_next_track(row) + break - return False + # Scroll to top + scroll_to = self.item(0, self.COL_INDEX) + self.scrollToItem(scroll_to, QAbstractItemView.PositionAtTop) def meta_clear(self, row): "Clear metadata for row" self.meta_set(row, None) + def meta_clear_current(self): + """ + Clear current row if there is one. There may not be if + we've changed playlists + """ + + current_row = self.meta_get_current() + if current_row: + self.meta_clear(current_row) + def meta_find(self, metadata, one=True): """ Search rows for metadata. @@ -568,7 +586,7 @@ class Playlist(QTableWidget): if row in notes_rows: continue if self.item(row, self.COL_INDEX): - self.meta_set_next(row) + self.cue_next_track(row) break # Tell database to record it as played @@ -579,7 +597,7 @@ class Playlist(QTableWidget): self.played_tracks.append(self.current_track.id) # Update display - self.tracks_changed() + self.repaint() def search_database(self): dlg = DbDialog(self) @@ -609,8 +627,7 @@ class Playlist(QTableWidget): return False if self.item(row, self.COL_INDEX): - self.meta_set_next(row) - self.tracks_changed() + self.cue_next_track(row) return True return False @@ -626,8 +643,8 @@ class Playlist(QTableWidget): self.previous_track = self.current_track self.previous_track_position = 0 - self.meta_clear(self.meta_get_current()) - self.tracks_changed() + self.meta_clear_current() + self.repaint() def repaint(self, clear_selection=True): "Set row colours, fonts, etc, and save playlist" @@ -850,31 +867,21 @@ class Playlist(QTableWidget): item = QTableWidgetItem(time_str) self.setItem(row, self.COL_START_TIME, item) - def tracks_changed(self): + def cue_next_track(self, next_row): """ - One or more of current or next track has changed. - - The row metadata is definitive because the same track may appear - more than once in the playlist, but only one track may be marked - as current or next. - - Update self.current_track and self.next_track. + Set the passed row as the next track to play """ - # Update instance variables - current_row = self.meta_get_current() - if current_row is not None: - track_id = int(self.item(current_row, self.COL_INDEX).text()) - if not self.current_track or self.current_track.id != track_id: - self.current_track = Tracks.get_track(track_id) - else: - self.current_track = None - - next_row = self.meta_get_next() if next_row is not None: + self.meta_set_next(next_row) track_id = int(self.item(next_row, self.COL_INDEX).text()) if not self.next_track or self.next_track.id != track_id: self.next_track = Tracks.get_track(track_id) + # Check we can read it + if not self.can_read_track(self.next_track): + self.parent().parent().show_warning( + "Can't read next track", + self.next_track.path) else: self.next_track = None @@ -937,13 +944,11 @@ class DbDialog(QDialog): def double_click(self, entry): track_id = entry.data(Qt.UserRole) self.add_track(track_id) + # Select search text to make it easier for next search + self.select_searchtext() def add_track(self, track_id): track = Tracks.track_from_id(track_id) - # Store in current playlist in database - db_playlist = Playlists.get_playlist_by_id(self.parent().playlist_id) - db_playlist.add_track(track) - # Add to on-screen playlist self.parent().add_to_playlist(track) # Select search text to make it easier for next search self.select_searchtext()