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:
parent
d9ad001c75
commit
e137045812
@ -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
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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"""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user