diff --git a/app/classes.py b/app/classes.py index 08ce0ae..9f211ec 100644 --- a/app/classes.py +++ b/app/classes.py @@ -80,7 +80,7 @@ class MusicMusterSignals(QObject): add_track_to_header_signal = pyqtSignal(int, int, int) add_track_to_playlist_signal = pyqtSignal(int, int, int, str) enable_escape_signal = pyqtSignal(bool) - set_next_track_signal = pyqtSignal(int, int) + next_track_changed_signal = pyqtSignal() span_cells_signal = pyqtSignal(int, int, int, int) def __post_init__(self): @@ -111,6 +111,7 @@ class PlaylistTrack: self.path: Optional[str] = None self.playlist_id: Optional[int] = None self.plr_id: Optional[int] = None + self.plr_rownum: Optional[int] = None self.silence_at: Optional[int] = None self.start_gap: Optional[int] = None self.start_time: Optional[datetime] = None @@ -120,7 +121,7 @@ class PlaylistTrack: def __repr__(self) -> str: return ( f"" + f"plr_rownum={self.plr_rownum}, playlist_id={self.playlist_id}>" ) def set_plr(self, session: scoped_session, plr: PlaylistRows) -> None: @@ -142,6 +143,7 @@ class PlaylistTrack: self.path = track.path self.playlist_id = plr.playlist_id self.plr_id = plr.id + self.plr_rownum = plr.plr_rownum self.silence_at = track.silence_at self.start_gap = track.start_gap self.start_time = None diff --git a/app/musicmuster.py b/app/musicmuster.py index a0158ef..7c8ef74 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -553,6 +553,7 @@ class Window(QMainWindow, Ui_MainWindow): self.txtSearch.returnPressed.connect(self.search_playlist_return) self.signals.enable_escape_signal.connect(self.enable_escape) + self.signals.next_track_changed_signal.connect(self.update_headers) self.timer10.timeout.connect(self.tick_10ms) self.timer500.timeout.connect(self.tick_500ms) @@ -1422,6 +1423,15 @@ class Window(QMainWindow, Ui_MainWindow): self.splitter.setSizes([splitter_top, splitter_bottom]) return + def set_selected_track_next(self) -> None: + """ + Set currently-selected row on visible playlist tab as next track + """ + + playlist_tab = self.active_tab() + if playlist_tab: + playlist_tab.set_row_as_next_track() + def set_tab_colour(self, widget: PlaylistTab, colour: QColor) -> None: """ Find the tab containing the widget and set the text colour @@ -1514,19 +1524,6 @@ class Window(QMainWindow, Ui_MainWindow): # May also be called when last tab is closed pass - def set_selected_track_next(self) -> None: - """ - Set currently-selected row on visible playlist tab as next track - """ - - playlist_tab = self.active_tab() - selected_plr_ids = playlist_tab.get_selected_playlistrow_ids() - if len(selected_plr_ids) != 1: - log.error(f"set_next_track:_from_mm {selected_plr_ids=}") - return - - self.set_next_plr_id(selected_plr_ids[0], playlist_tab) - def set_next_plr_id( self, next_plr_id: Optional[int], playlist_tab: PlaylistTab ) -> None: @@ -1541,37 +1538,33 @@ class Window(QMainWindow, Ui_MainWindow): - Populate ‘info’ tabs """ - with Session() as session: - # Update self.next_track PlaylistTrack structure - old_next_track = self.next_track - self.next_track = NextTrack() - if next_plr_id: - next_plr = session.get(PlaylistRows, next_plr_id) - if next_plr: - self.next_track.set_plr(session, next_plr) + return + # with Session() as session: + # # Update self.next_track PlaylistTrack structure + # self.next_track = NextTrack() + # if next_plr_id: + # next_plr = session.get(PlaylistRows, next_plr_id) + # if next_plr: + # self.next_track.set_plr(session, next_plr) + # self.signals.set_next_track_signal.emit(next_plr.playlist_id) - # Tell playlist tabs to update their 'next track' highlighting - # Args must both be ints, so use zero for no next track - self.signals.set_next_track_signal.emit( - old_next_track.plr_id, next_plr_id or 0 - ) + # # Update headers + # self.update_headers() - # Update headers - self.update_headers() + # TODO: reimlement + # # Set playlist tab colours + # self._set_next_track_playlist_tab_colours(old_next_track) - # Set playlist tab colours - self._set_next_track_playlist_tab_colours(old_next_track) - - if next_plr_id: - # Populate 'info' tabs with Wikipedia info, but queue it - # because it isn't quick - if self.next_track.title: - QTimer.singleShot( - 0, - lambda: self.tabInfolist.open_in_wikipedia( - self.next_track.title - ), - ) + # if next_plr_id: + # # Populate 'info' tabs with Wikipedia info, but queue it + # # because it isn't quick + # if self.next_track.title: + # QTimer.singleShot( + # 0, + # lambda: self.tabInfolist.open_in_wikipedia( + # self.next_track.title + # ), + # ) def _set_next_track_playlist_tab_colours( self, old_next_track: Optional[PlaylistTrack] diff --git a/app/playlistmodel.py b/app/playlistmodel.py index 60a9597..fd952d6 100644 --- a/app/playlistmodel.py +++ b/app/playlistmodel.py @@ -101,8 +101,11 @@ class PlaylistModel(QAbstractTableModel): self.playlist_rows: dict[int, PlaylistRowData] = {} self.signals = MusicMusterSignals() - self.signals.add_track_to_playlist_signal.connect(self.add_track) self.signals.add_track_to_header_signal.connect(self.add_track_to_header) + self.signals.add_track_to_playlist_signal.connect(self.add_track) + + self.current_track = CurrentTrack() + self.next_track = NextTrack() with Session() as session: self.refresh_data(session) @@ -190,6 +193,12 @@ class PlaylistModel(QAbstractTableModel): # Unreadable track file if file_is_unreadable(prd.path): return QBrush(QColor(Config.COLOUR_UNREADABLE)) + # Current track + if prd.plrid == self.current_track.plr_id: + return QBrush(QColor(Config.COLOUR_CURRENT_PLAYLIST)) + # Next track + if prd.plrid == self.next_track.plr_id: + return QBrush(QColor(Config.COLOUR_NEXT_PLAYLIST)) # Individual cell colouring if column == Col.START_GAP.value: @@ -514,6 +523,28 @@ class PlaylistModel(QAbstractTableModel): return len(self.playlist_rows) + def set_next_track(self, row_number: int) -> None: + """ + Update display if necessary + """ + + # Update self.next_track PlaylistTrack structure + with Session() as session: + self.next_track = NextTrack() + try: + plrid = self.playlist_rows[row_number].plrid + except IndexError: + log.error( + f"playlistmodel.set_next_track({row_number=}, " + f"{self.playlist_id=}" + ) + return + plr = session.get(PlaylistRows, plrid) + if plr: + self.next_track.set_plr(session, plr) + self.signals.next_track_changed_signal.emit() + self.invalidate_row(row_number) + def setData( self, index: QModelIndex, value: QVariant, role: int = Qt.ItemDataRole.EditRole ) -> bool: diff --git a/app/playlists.py b/app/playlists.py index b93c55d..a3fd28c 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -543,12 +543,12 @@ class PlaylistTab(QTableView): # else: # return self.rowCount() - # def get_selected_playlistrow_ids(self) -> list: - # """ - # Return a list of PlaylistRow ids of the selected rows - # """ + def get_selected_playlistrow_ids(self) -> list: + """ + Return a list of PlaylistRow ids of the selected rows + """ - # return [self._get_row_plr_id(a) for a in self._get_selected_rows()] + return [self._get_row_plr_id(a) for a in self._get_selected_rows()] # def get_selected_playlistrows(self, session: scoped_session) -> List[PlaylistRows]: # """ @@ -1019,6 +1019,18 @@ class PlaylistTab(QTableView): # # Reset selection mode # self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) + def set_row_as_next_track(self) -> None: + """ + Set selected row as next track + """ + + selected_row = self._get_selected_row() + if selected_row is None: + return + model = cast(PlaylistModel, self.model()) + model.set_next_track(selected_row) + self.clearSelection() + # def tab_visible(self) -> None: # """Called when tab becomes visible""" @@ -1475,19 +1487,18 @@ class PlaylistTab(QTableView): or None if none selected """ - if not self.selectionModel().hasSelection(): - return None - else: - return self.selectionModel().selectedRows()[0].row() + sm = self.selectionModel() + if sm: + if sm.hasSelection(): + return sm.selectedIndexes()[0].row() + return None def _get_selected_rows(self) -> List[int]: """Return a list of selected row numbers sorted by row""" # Use a set to deduplicate result (a selected row will have all # items in that row selected) - return sorted( - [row_number for row_number in set([a.row() for a in self.selectedItems()])] - ) + return sorted(list(set([a.row() for a in self.selectedIndexes()]))) def _info_row(self, track_id: int) -> None: """Display popup with info re row"""