WIP V3: select next track works with caveats

Peformance isn't great
Selecting a non-existent track isn't caught
This commit is contained in:
Keith Edmunds 2023-11-01 22:53:25 +00:00
parent d9ad001c75
commit e137045812
4 changed files with 93 additions and 56 deletions

View File

@ -80,7 +80,7 @@ class MusicMusterSignals(QObject):
add_track_to_header_signal = pyqtSignal(int, int, int) add_track_to_header_signal = pyqtSignal(int, int, int)
add_track_to_playlist_signal = pyqtSignal(int, int, int, str) add_track_to_playlist_signal = pyqtSignal(int, int, int, str)
enable_escape_signal = pyqtSignal(bool) 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) span_cells_signal = pyqtSignal(int, int, int, int)
def __post_init__(self): def __post_init__(self):
@ -111,6 +111,7 @@ class PlaylistTrack:
self.path: Optional[str] = None self.path: Optional[str] = None
self.playlist_id: Optional[int] = None self.playlist_id: Optional[int] = None
self.plr_id: Optional[int] = None self.plr_id: Optional[int] = None
self.plr_rownum: Optional[int] = None
self.silence_at: Optional[int] = None self.silence_at: Optional[int] = None
self.start_gap: Optional[int] = None self.start_gap: Optional[int] = None
self.start_time: Optional[datetime] = None self.start_time: Optional[datetime] = None
@ -120,7 +121,7 @@ class PlaylistTrack:
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
f"<PlaylistTrack(title={self.title}, artist={self.artist}, " f"<PlaylistTrack(title={self.title}, artist={self.artist}, "
f"playlist_id={self.playlist_id}>" f"plr_rownum={self.plr_rownum}, playlist_id={self.playlist_id}>"
) )
def set_plr(self, session: scoped_session, plr: PlaylistRows) -> None: def set_plr(self, session: scoped_session, plr: PlaylistRows) -> None:
@ -142,6 +143,7 @@ class PlaylistTrack:
self.path = track.path self.path = track.path
self.playlist_id = plr.playlist_id self.playlist_id = plr.playlist_id
self.plr_id = plr.id self.plr_id = plr.id
self.plr_rownum = plr.plr_rownum
self.silence_at = track.silence_at self.silence_at = track.silence_at
self.start_gap = track.start_gap self.start_gap = track.start_gap
self.start_time = None self.start_time = None

View File

@ -553,6 +553,7 @@ class Window(QMainWindow, Ui_MainWindow):
self.txtSearch.returnPressed.connect(self.search_playlist_return) self.txtSearch.returnPressed.connect(self.search_playlist_return)
self.signals.enable_escape_signal.connect(self.enable_escape) 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.timer10.timeout.connect(self.tick_10ms)
self.timer500.timeout.connect(self.tick_500ms) self.timer500.timeout.connect(self.tick_500ms)
@ -1422,6 +1423,15 @@ class Window(QMainWindow, Ui_MainWindow):
self.splitter.setSizes([splitter_top, splitter_bottom]) self.splitter.setSizes([splitter_top, splitter_bottom])
return 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: def set_tab_colour(self, widget: PlaylistTab, colour: QColor) -> None:
""" """
Find the tab containing the widget and set the text colour 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 # May also be called when last tab is closed
pass 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( def set_next_plr_id(
self, next_plr_id: Optional[int], playlist_tab: PlaylistTab self, next_plr_id: Optional[int], playlist_tab: PlaylistTab
) -> None: ) -> None:
@ -1541,37 +1538,33 @@ class Window(QMainWindow, Ui_MainWindow):
- Populate info tabs - Populate info tabs
""" """
with Session() as session: return
# Update self.next_track PlaylistTrack structure # with Session() as session:
old_next_track = self.next_track # # Update self.next_track PlaylistTrack structure
self.next_track = NextTrack() # self.next_track = NextTrack()
if next_plr_id: # if next_plr_id:
next_plr = session.get(PlaylistRows, next_plr_id) # next_plr = session.get(PlaylistRows, next_plr_id)
if next_plr: # if next_plr:
self.next_track.set_plr(session, 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 # # Update headers
# Args must both be ints, so use zero for no next track # self.update_headers()
self.signals.set_next_track_signal.emit(
old_next_track.plr_id, next_plr_id or 0
)
# Update headers # TODO: reimlement
self.update_headers() # # Set playlist tab colours
# self._set_next_track_playlist_tab_colours(old_next_track)
# Set playlist tab colours # if next_plr_id:
self._set_next_track_playlist_tab_colours(old_next_track) # # Populate 'info' tabs with Wikipedia info, but queue it
# # because it isn't quick
if next_plr_id: # if self.next_track.title:
# Populate 'info' tabs with Wikipedia info, but queue it # QTimer.singleShot(
# because it isn't quick # 0,
if self.next_track.title: # lambda: self.tabInfolist.open_in_wikipedia(
QTimer.singleShot( # self.next_track.title
0, # ),
lambda: self.tabInfolist.open_in_wikipedia( # )
self.next_track.title
),
)
def _set_next_track_playlist_tab_colours( def _set_next_track_playlist_tab_colours(
self, old_next_track: Optional[PlaylistTrack] self, old_next_track: Optional[PlaylistTrack]

View File

@ -101,8 +101,11 @@ class PlaylistModel(QAbstractTableModel):
self.playlist_rows: dict[int, PlaylistRowData] = {} self.playlist_rows: dict[int, PlaylistRowData] = {}
self.signals = MusicMusterSignals() 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_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: with Session() as session:
self.refresh_data(session) self.refresh_data(session)
@ -190,6 +193,12 @@ class PlaylistModel(QAbstractTableModel):
# Unreadable track file # Unreadable track file
if file_is_unreadable(prd.path): if file_is_unreadable(prd.path):
return QBrush(QColor(Config.COLOUR_UNREADABLE)) 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 # Individual cell colouring
if column == Col.START_GAP.value: if column == Col.START_GAP.value:
@ -514,6 +523,28 @@ class PlaylistModel(QAbstractTableModel):
return len(self.playlist_rows) 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( def setData(
self, index: QModelIndex, value: QVariant, role: int = Qt.ItemDataRole.EditRole self, index: QModelIndex, value: QVariant, role: int = Qt.ItemDataRole.EditRole
) -> bool: ) -> bool:

View File

@ -543,12 +543,12 @@ class PlaylistTab(QTableView):
# else: # else:
# return self.rowCount() # return self.rowCount()
# def get_selected_playlistrow_ids(self) -> list: def get_selected_playlistrow_ids(self) -> list:
# """ """
# Return a list of PlaylistRow ids of the selected rows 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]: # def get_selected_playlistrows(self, session: scoped_session) -> List[PlaylistRows]:
# """ # """
@ -1019,6 +1019,18 @@ class PlaylistTab(QTableView):
# # Reset selection mode # # Reset selection mode
# self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) # 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: # def tab_visible(self) -> None:
# """Called when tab becomes visible""" # """Called when tab becomes visible"""
@ -1475,19 +1487,18 @@ class PlaylistTab(QTableView):
or None if none selected or None if none selected
""" """
if not self.selectionModel().hasSelection(): sm = self.selectionModel()
if sm:
if sm.hasSelection():
return sm.selectedIndexes()[0].row()
return None return None
else:
return self.selectionModel().selectedRows()[0].row()
def _get_selected_rows(self) -> List[int]: def _get_selected_rows(self) -> List[int]:
"""Return a list of selected row numbers sorted by row""" """Return a list of selected row numbers sorted by row"""
# Use a set to deduplicate result (a selected row will have all # Use a set to deduplicate result (a selected row will have all
# items in that row selected) # items in that row selected)
return sorted( return sorted(list(set([a.row() for a in self.selectedIndexes()])))
[row_number for row_number in set([a.row() for a in self.selectedItems()])]
)
def _info_row(self, track_id: int) -> None: def _info_row(self, track_id: int) -> None:
"""Display popup with info re row""" """Display popup with info re row"""