Compare commits

..

No commits in common. "9c663337295f0541a607d040fb0fd1888707c1cb" and "c9c47c3133a11c6693655b402601c154d18f07df" have entirely different histories.

2 changed files with 132 additions and 150 deletions

View File

@ -142,7 +142,7 @@ class CartButton(QPushButton):
class PlaylistTrack: class PlaylistTrack:
""" """
Used to provide a single reference point for specific playlist tracks, Used to provide a single reference point for specific playlist tracks,
typically the previous, current and next track. typicall the previous, current and next track.
""" """
def __init__(self) -> None: def __init__(self) -> None:
@ -257,7 +257,7 @@ class MusicMusterSignals(QObject):
emit-a-signal-from-another-class-to-main-class emit-a-signal-from-another-class-to-main-class
""" """
set_next_track_signal = pyqtSignal(int, int) update_row_note_signal = pyqtSignal(int)
class Window(QMainWindow, Ui_MainWindow): class Window(QMainWindow, Ui_MainWindow):
@ -579,7 +579,8 @@ class Window(QMainWindow, Ui_MainWindow):
self.actionSelect_previous_track.triggered.connect( self.actionSelect_previous_track.triggered.connect(
self.select_previous_row) self.select_previous_row)
self.actionMoveUnplayed.triggered.connect(self.move_unplayed) self.actionMoveUnplayed.triggered.connect(self.move_unplayed)
self.actionSetNext.triggered.connect(self.set_next_track_from_mm) self.actionSetNext.triggered.connect(
lambda: self.tabPlaylist.currentWidget().set_selected_as_next())
self.actionSkipToNext.triggered.connect(self.play_next) self.actionSkipToNext.triggered.connect(self.play_next)
self.actionStop.triggered.connect(self.stop) self.actionStop.triggered.connect(self.stop)
self.btnDrop3db.clicked.connect(self.drop3db) self.btnDrop3db.clicked.connect(self.drop3db)
@ -1284,47 +1285,43 @@ class Window(QMainWindow, Ui_MainWindow):
def resume(self) -> None: def resume(self) -> None:
""" """
Resume playing last track. We may be playing the next track Resume playing stopped track
or none; take care of both eventualities.
Actions required: Actions required:
- Return if no saved position - Return if no saved position
- Resume last track - Store saved position
- If a track is playing, make that the next track - Store next track
- Set previous track to be next track
- Call play_next() from saved position
- Reset next track
""" """
# Return if no saved position # Return if no saved position
if not self.previous_track_position: if not self.previous_track_position:
return return
# Note any playing track as this will become the next track # Note resume point
playing_track = None resume_from = self.previous_track_position
if self.current_track.track_id:
playing_track = self.current_track # Remember what was to have been the next track
original_next_plr_id = self.next_track.plr_id
original_next_plr_playlist_tab = self.next_track.playlist_tab
with Session() as session: with Session() as session:
# Set next plr to be track to resume # Set next track to be the last one played
plr_resume = session.get(PlaylistRows, self.previous_track.plr_id) self.next_track = self.previous_track
if not plr_resume: self.previous_track = PlaylistTrack()
return
plr_tab_resume = self.previous_track.playlist_tab
if not plr_tab_resume:
return
# Resume last track # Resume last track
self._set_next_plr(session, plr_resume, plr_tab_resume) self.play_next(resume_from)
self.play_next(self.previous_track_position)
# If a track was playing when we were called, get details to # Reset next track if there was one
# set it as the next track if original_next_plr_id:
if playing_track: next_plr = session.get(PlaylistRows, original_next_plr_id)
plr_next = session.get(PlaylistRows, playing_track.plr_id) if not next_plr or not original_next_plr_playlist_tab:
if not plr_next:
return return
plr_tab_next = playing_track.playlist_tab self.this_is_the_next_playlist_row(
if not plr_tab_next: session, next_plr, original_next_plr_playlist_tab)
return
self._set_next_plr(session, plr_next, plr_tab_next)
def save_as_template(self) -> None: def save_as_template(self) -> None:
"""Save current playlist as template""" """Save current playlist as template"""
@ -1497,58 +1494,57 @@ 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_next_track_from_playlist(self, playlist_tab: PlaylistTab, def this_is_the_next_playlist_row(
next_plr_id: int) -> None: self, session: scoped_session, plr: PlaylistRows,
next_track_playlist_tab: PlaylistTab) -> None:
""" """
Called from playlist tab to notify us of next track This is notification from a playlist tab that it holds the next
""" playlist row to be played.
with Session() as session:
next_plr = session.get(PlaylistRows, next_plr_id)
if not next_plr:
return
self._set_next_plr(session, next_plr, playlist_tab)
def set_next_track_from_mm(self) -> None:
"""
Set currently-selected row on visible playlist tab as next track
Actions required: Actions required:
- Update self.next_track PlaylistTrack structure - Clear next track if on other tab
- Set playlist tab colours - Reset tab colour if on other tab
- Tell playlist tabs to update their 'next track' highlighting - Note next playlist tab
- Set next next_track_playlist_tab tab colour
- Note next track
- Update headers - Update headers
- Populate info tabs - Populate info tabs
""" """
with Session() as session: if plr.track_id is None:
playlist_tab = self.visible_playlist_tab() return
selected_plrs = playlist_tab.get_selected_playlistrows(session)
if len(selected_plrs) != 1:
log.error(f"set_next_track:_from_mm {selected_plrs=}")
return
next_plr = selected_plrs[0]
self._set_next_plr(session, next_plr, playlist_tab)
def _set_next_plr(self, session: scoped_session, # If we already have a next tab lined up and it's neither
next_plr: PlaylistRows, # the "new" next tab nor the current track tab then we need
playlist_tab: PlaylistTab) -> None: # to reset the tab colour.
""" if (
Set next_plr as the next track to play self.next_track.playlist_tab and
""" self.next_track.playlist_tab != next_track_playlist_tab and
self.next_track.playlist_tab != self.current_track.playlist_tab
):
self.set_tab_colour(self.next_track.playlist_tab,
QColor(Config.COLOUR_NORMAL_TAB))
# Build PlaylistTrack structure for new next track # Discard now-incorrect next_track PlaylistTrack and tell
old_next_track = self.next_track # playlist_tab too
self.next_track = PlaylistTrack() self.next_track.playlist_tab.clear_next()
self.next_track.set_plr(session, next_plr, playlist_tab) self.clear_next()
# Set playlist tab colours # Populate self.next_track
self._set_next_track_playlist_tab_colours(old_next_track) self.next_track.set_plr(session, plr, next_track_playlist_tab)
if self.next_track.playlist_tab:
if self.current_track.playlist_tab != self.next_track.playlist_tab:
self.set_tab_colour(self.next_track.playlist_tab,
QColor(Config.COLOUR_NEXT_TAB))
# Tell playlist tabs to update themselves # Populate footer if we're not currently playing
self.signals.set_next_track_signal.emit(old_next_track.plr_id, if not self.playing and self.next_track.track_id:
next_plr.id) self.label_track_length.setText(
helpers.ms_to_mmss(self.next_track.duration)
)
self.label_fade_length.setText(helpers.ms_to_mmss(
self.next_track.fade_length))
# Update headers # Update headers
self.update_headers() self.update_headers()
@ -1560,40 +1556,6 @@ class Window(QMainWindow, Ui_MainWindow):
1, lambda: self.tabInfolist.open_in_wikipedia(track_title) 1, lambda: self.tabInfolist.open_in_wikipedia(track_title)
) )
def _set_next_track_playlist_tab_colours(
self, old_next_track: Optional[PlaylistTrack]) -> None:
"""
Set playlist tab colour for next track. self.next_track needs
to be set before calling.
"""
# If the original next playlist tab isn't the same as the
# new one or the current track, it needs its colour reset.
if (
old_next_track and
old_next_track.playlist_tab and
old_next_track.playlist_tab not in [
self.next_track.playlist_tab,
self.current_track.playlist_tab
]):
self.set_tab_colour(old_next_track.playlist_tab,
QColor(Config.COLOUR_NORMAL_TAB))
# If the new next playlist tab isn't the same as the
# old one or the current track, it needs its colour set.
if old_next_track:
old_tab = old_next_track.playlist_tab
else:
old_tab = None
if (
self.next_track and
self.next_track.playlist_tab and
self.next_track.playlist_tab not in [
old_tab,
self.current_track.playlist_tab
]):
self.set_tab_colour(self.next_track.playlist_tab,
QColor(Config.COLOUR_NEXT_TAB))
def tick(self) -> None: def tick(self) -> None:
""" """
Carry out clock tick actions. Carry out clock tick actions.

View File

@ -191,14 +191,13 @@ class PlaylistTab(QTableWidget):
# Call self.eventFilter() for events # Call self.eventFilter() for events
self.viewport().installEventFilter(self) self.viewport().installEventFilter(self)
self.itemSelectionChanged.connect(self._select_event)
self.search_text: str = "" self.search_text: str = ""
self.edit_cell_type: Optional[int] self.edit_cell_type: Optional[int]
self.selecting_in_progress = False self.selecting_in_progress = False
# Connect signals # Connect signals
self.horizontalHeader().sectionResized.connect(self._column_resize) self.horizontalHeader().sectionResized.connect(self._column_resize)
self.itemSelectionChanged.connect(self._select_event)
self.signals.set_next_track_signal.connect(self._reset_next)
# Load playlist rows # Load playlist rows
self.populate_display(session, self.playlist_id) self.populate_display(session, self.playlist_id)
@ -648,8 +647,7 @@ class PlaylistTab(QTableWidget):
# Set next track # Set next track
next_row = self._find_next_track_row(session, current_row + 1) next_row = self._find_next_track_row(session, current_row + 1)
if next_row: if next_row:
self.musicmuster.set_next_track_from_playlist( self._set_next(session, next_row)
self, self._get_row_plr_id(next_row))
# Display row as current track # Display row as current track
self._set_row_colour_current(current_row) self._set_row_colour_current(current_row)
@ -734,6 +732,7 @@ class PlaylistTab(QTableWidget):
row_number = self._get_next_track_row_number() row_number = self._get_next_track_row_number()
if not row_number: if not row_number:
return return
self.musicmuster.clear_next()
self._set_row_colour_default(row_number) self._set_row_colour_default(row_number)
self.clear_selection() self.clear_selection()
@ -869,6 +868,14 @@ class PlaylistTab(QTableWidget):
self.selectRow(row_number) self.selectRow(row_number)
def set_selected_as_next(self) -> None:
"""Sets the select track as next to play"""
row_number = self._get_selected_row()
if row_number is not None:
with Session() as session:
self._set_next(session, row_number)
def tab_visible(self) -> None: def tab_visible(self) -> None:
"""Called when tab becomes visible""" """Called when tab becomes visible"""
@ -883,6 +890,7 @@ class PlaylistTab(QTableWidget):
def _add_track(self, row_number: int) -> None: def _add_track(self, row_number: int) -> None:
"""Add a track to a section header making it a normal track row""" """Add a track to a section header making it a normal track row"""
print(f"_add_track({row_number=})")
with Session() as session: with Session() as session:
# Add track to playlist row # Add track to playlist row
plr = self._get_row_plr(session, row_number) plr = self._get_row_plr(session, row_number)
@ -976,7 +984,8 @@ class PlaylistTab(QTableWidget):
# Mark unplayed # Mark unplayed
if self._get_row_userdata(row_number, self.PLAYED): if self._get_row_userdata(row_number, self.PLAYED):
self._add_context_menu("Mark unplayed", self._mark_unplayed) self._add_context_menu("Mark unplayed",
lambda: self._mark_unplayed(row_number))
# Unmark as next # Unmark as next
if next_row: if next_row:
@ -1379,23 +1388,25 @@ class PlaylistTab(QTableWidget):
and pos.y() >= rect.center().y() # noqa W503 and pos.y() >= rect.center().y() # noqa W503
) )
def _mark_unplayed(self) -> None: def _mark_unplayed(self, row_number: int) -> None:
""" """
Mark selected rows as unplayed in this playlist Mark passed row as unplayed in this playlist
""" """
if row_number is None:
return
_ = self._set_row_userdata(row_number, self.PLAYED, False)
self._set_row_bold(row_number, True)
self.clear_selection()
with Session() as session: with Session() as session:
for row_number in self._get_selected_rows(): plr = self._get_row_plr(session, row_number)
_ = self._set_row_userdata(row_number, self.PLAYED, False) if not plr:
self._set_row_bold(row_number, True) return
plr.played = False
plr = self._get_row_plr(session, row_number)
if not plr:
continue
plr.played = False
self._update_start_end_times(session) self._update_start_end_times(session)
self.clear_selection() self.hide_or_show_played_tracks()
self.hide_or_show_played_tracks()
def _move_row(self, session: scoped_session, plr: PlaylistRows, def _move_row(self, session: scoped_session, plr: PlaylistRows,
new_row_number: int) -> None: new_row_number: int) -> None:
@ -1701,44 +1712,53 @@ class PlaylistTab(QTableWidget):
return item return item
def _reset_next(self, old_plrid: int, new_plrid: int) -> None: def _set_next(self, session: scoped_session, row_number: int) -> None:
""" """
Called when set_next_track_signal signal received. Set passed row as next playlist row to play.
Actions required: Actions required:
- If old_plrid points to this playlist: - Check row has a track
- Remove existing next track - Check track is readable
- If new_plrid points to this playlist: - Notify musicmuster
- Set track as next - Display row as next track
- Display row as next track - Update start/stop times
- Update start/stop times
""" """
with Session() as session: # Check row has a track
# Get plrs track_id = self._get_row_track_id(row_number)
old_plr = new_plr = None if not track_id:
if old_plrid: log.error(
old_plr = session.get(PlaylistRows, old_plrid) f"playlists._set_next({row_number=}) has no track associated"
if not new_plrid: )
log.error(f"_reset_next called with {new_plrid=}") return
return
new_plr = session.get(PlaylistRows, new_plrid)
if not new_plr:
log.error(f"_reset_next({new_plrid=}): plr not found")
return
# Unmark next track track = session.get(Tracks, track_id)
if old_plr and old_plr.playlist_id == self.playlist_id: if not track:
self._set_row_colour_default(old_plr.row_number) log.error(f"playlists._set_next({row_number=}): Track not found")
return
# Mark next track # Check track is readable
if new_plr and new_plr.playlist_id == self.playlist_id: if file_is_unreadable(track.path):
self._set_row_colour_next(new_plr.row_number) return None
# Update start/stop times # Clear any existing next track
self._update_start_end_times(session) next_track_row = self._get_next_track_row_number()
if next_track_row:
self._set_row_colour_default(next_track_row)
# Notify musicmuster
plr = self._get_row_plr(session, row_number)
if not plr:
log.debug(f"playists._set_next({row_number=}) can't retrieve plr")
else:
self.musicmuster.this_is_the_next_playlist_row(session, plr, self)
# Display row as next track
self._set_row_colour_next(row_number)
# Update start/stop times
self.clear_selection() self.clear_selection()
self._update_start_end_times(session)
def _set_played_row(self, session: scoped_session, def _set_played_row(self, session: scoped_session,
row_number: int) -> None: row_number: int) -> None: