Move selected / move unplayed working

This commit is contained in:
Keith Edmunds 2022-08-15 12:29:36 +01:00
parent eff80d684e
commit d5950ab29a
5 changed files with 125 additions and 105 deletions

View File

@ -556,29 +556,33 @@ class PlaylistRows(Base):
return plrs
@staticmethod
def move_to_playlist(session: Session,
playlistrow_ids: List[int],
destination_playlist_id: int) -> None:
"""
Move the list of playlistrow_ids to the end of destination_playlist
"""
def get_last_used_row(session: Session, playlist_id: int) -> Optional[int]:
"""Return the last used row for playlist, or None if no rows"""
# Find last row of destination playlist
last_row = session.execute(
return session.execute(
select(func.max(PlaylistRows.row_number))
.where(PlaylistRows.playlist_id == destination_playlist_id)
.where(PlaylistRows.playlist_id == playlist_id)
).scalar_one()
if last_row is None:
last_row = 0
# Update the PlaylistRows entries
for plr_id in playlistrow_ids:
last_row += 1
plr = session.get(PlaylistRows, plr_id)
plr.row_number = last_row
plr.playlist_id = destination_playlist_id
@classmethod
def get_unplayed_rows(cls, session: Session,
playlist_id: int) -> List[int]:
"""
For passed playlist, return a list of track rows that
have not been played.
"""
session.commit()
plrs = session.execute(
select(cls)
.where(
cls.playlist_id == playlist_id,
cls.track_id.is_not(None),
cls.played.is_(False)
)
.order_by(cls.row_number)
).scalars().all()
return plrs
# @classmethod
# def get_playlist_rows(cls, playlist_id: int) -> \

View File

@ -7,6 +7,7 @@ import sys
from datetime import datetime, timedelta
# from typing import Callable, Dict, List, Optional, Tuple
from typing import List
from PyQt5.QtCore import QDate, QEvent, Qt, QTime, QTimer
from PyQt5.QtGui import QColor
@ -175,8 +176,7 @@ class Window(QMainWindow, Ui_MainWindow):
# self.actionSelect_played_tracks.triggered.connect(self.select_played)
self.actionSelect_previous_track.triggered.connect(
self.select_previous_row)
# self.actionSelect_unplayed_tracks.triggered.connect(
# self.select_unplayed)
self.actionMoveUnplayed.triggered.connect(self.move_unplayed)
self.actionSetNext.triggered.connect(
lambda: self.tabPlaylist.currentWidget().set_selected_as_next())
self.actionSkipToNext.triggered.connect(self.play_next)
@ -485,9 +485,10 @@ class Window(QMainWindow, Ui_MainWindow):
self.create_playlist_tab(session, playlist)
playlist.mark_open(session)
def move_selected(self) -> None:
def move_playlist_rows(self, session: Session,
playlistrows: List[PlaylistRows]) -> None:
"""
Move selected rows to another playlist
Move passed playlist rows to another playlist
Actions required:
- identify destination playlist
@ -496,43 +497,74 @@ class Window(QMainWindow, Ui_MainWindow):
- update destination playlist display if loaded
"""
if not playlistrows:
log.debug(f"musicmuster.move_playlist_rows({playlistrows=}")
# Identify destination playlist
visible_tab = self.visible_playlist_tab()
source_playlist = visible_tab.playlist_id
playlists = []
for playlist in Playlists.get_all(session):
if playlist.id == source_playlist:
continue
else:
playlists.append(playlist)
# Get destination playlist id
dlg = SelectPlaylistDialog(self, playlists=playlists, session=session)
dlg.exec()
if not dlg.playlist:
return
destination_playlist_id = dlg.playlist.id
# Remove moved rows from display
visible_tab.remove_rows([plr.row_number for plr in playlistrows])
# Update playlist for the rows in the database
last_row = PlaylistRows.get_last_used_row(session,
destination_playlist_id)
if last_row is not None:
next_row = last_row + 1
else:
next_row = 0
for plr in playlistrows:
plr.row_number = next_row
plr.playlist_id = destination_playlist_id
# Reset played as it's not been played on this playlist
plr.played = False
# Update destination playlist_tab if visible (if not visible, it
# will be re-populated when it is opened)
destionation_playlist_tab = None
for tab in range(self.tabPlaylist.count()):
if self.tabPlaylist.widget(tab).playlist_id == dlg.playlist.id:
destionation_playlist_tab = self.tabPlaylist.widget(tab)
break
if destionation_playlist_tab:
destionation_playlist_tab.populate(session, dlg.playlist.id)
def move_selected(self) -> None:
"""
Move selected rows to another playlist
"""
with Session() as session:
visible_tab = self.visible_playlist_tab()
source_playlist = visible_tab.playlist_id
playlists = []
for playlist in Playlists.get_all(session):
if playlist.id == source_playlist:
continue
else:
playlists.append(playlist)
# Get destination playlist id
dlg = SelectPlaylistDialog(self, playlists=playlists,
session=session)
dlg.exec()
if not dlg.playlist:
return
destination_playlist = dlg.playlist
# Update playlist for the rows in the database
plr_ids = visible_tab.get_selected_playlistrow_ids()
PlaylistRows.move_to_playlist(
session, plr_ids, destination_playlist.id
self.move_playlist_rows(
session,
self.visible_playlist_tab().get_selected_playlistrows(session)
)
# Remove moved rows from display
visible_tab.remove_selected_rows()
def move_unplayed(self) -> None:
"""
Move unplayed rows to another playlist
"""
# Update destination playlist_tab if visible (if not visible, it
# will be re-populated when it is opened)
destionation_playlist_tab = None
for tab in range(self.tabPlaylist.count()):
if self.tabPlaylist.widget(tab).playlist_id == dlg.playlist.id:
destionation_playlist_tab = self.tabPlaylist.widget(tab)
break
if destionation_playlist_tab:
destionation_playlist_tab.populate(session, dlg.playlist.id)
playlist_id = self.visible_playlist_tab().playlist_id
with Session() as session:
unplayed_playlist_rows = PlaylistRows.get_unplayed_rows(
session, playlist_id)
self.move_playlist_rows(session, unplayed_playlist_rows)
def play_next(self) -> None:
"""
@ -640,7 +672,7 @@ class Window(QMainWindow, Ui_MainWindow):
"""Tidy up and reset search bar"""
# Clear the search text
self.visible_playlist_tab().search("")
self.visible_playlist_tab().set_search("")
# Clean up search bar
self.txtSearch.setText("")
self.txtSearch.setHidden(True)
@ -681,11 +713,6 @@ class Window(QMainWindow, Ui_MainWindow):
"""Select previous or first row in playlist"""
self.visible_playlist_tab().select_previous_row()
#
# def select_unplayed(self) -> None:
# """Select all unplayed tracks in playlist"""
#
# self.visible_playlist_tab().select_unplayed_tracks()
def set_main_window_size(self) -> None:
"""Set size of window from database"""

View File

@ -156,7 +156,7 @@ class PlaylistTab(QTableWidget):
self.populate(session, self.playlist_id)
def __repr__(self) -> str:
return f"<PlaylistTab(id={self.playlist_id}"
return f"<PlaylistTab(id={self.playlist_id}>"
# ########## Events other than cell editing ##########
@ -472,7 +472,15 @@ class PlaylistTab(QTableWidget):
Return a list of PlaylistRow ids of the selected rows
"""
return [self._get_playlistrow_id(a) for a in self._selected_rows()]
return [self._get_playlistrow_id(a) for a in self._get_selected_rows()]
def get_selected_playlistrows(self, session: Session) -> Optional[List]:
"""
Return a list of PlaylistRows of the selected rows
"""
plr_ids = self.get_selected_playlistrow_ids()
return [session.get(PlaylistRows, a) for a in plr_ids]
def insert_header(self, session: Session, note: str,
repaint: bool = True) -> None:
@ -497,12 +505,6 @@ class PlaylistTab(QTableWidget):
if repaint:
self.update_display(session)
#
# def _get_selected_rows(self) -> List[int]:
# """Return a sorted list of selected row numbers"""
#
# rows = self.selectionModel().selectedRows()
# return sorted([row.row() for row in rows])
#
# def get_selected_title(self) -> Optional[str]:
# """Return title of selected row or None"""
#
@ -747,13 +749,18 @@ class PlaylistTab(QTableWidget):
# self.save_playlist(session)
self.update_display(session)
def remove_selected_rows(self) -> None:
"""Remove selected rows from display"""
def remove_rows(self, row_numbers: List[int]) -> None:
"""Remove passed rows from display"""
# Remove rows from display. Do so in reverse order so that
# row numbers remain valid.
for row in sorted(self._selected_rows(), reverse=True):
for row in sorted(row_numbers, reverse=True):
self.removeRow(row)
def remove_selected_rows(self) -> None:
"""Remove selected rows from display"""
self.remove_rows(self._get_selected_rows())
# Reset drag mode
self.setDragEnabled(False)
@ -868,7 +875,7 @@ class PlaylistTab(QTableWidget):
row: int
selected_rows: List[int]
selected_rows = self._selected_rows()
selected_rows = self._get_selected_rows()
# we will only handle zero or one selected rows
if len(selected_rows) > 1:
return
@ -915,7 +922,7 @@ class PlaylistTab(QTableWidget):
row: int
selected_rows: List[int]
selected_rows = self._selected_rows()
selected_rows = self._get_selected_rows()
# we will only handle zero or one selected rows
if len(selected_rows) > 1:
return
@ -943,16 +950,6 @@ class PlaylistTab(QTableWidget):
track_id = self._get_row_track_id(row)
self.selectRow(row)
#
# def select_unplayed_tracks(self) -> None:
# """Select all unplayed tracks in playlist"""
#
# try:
# self.selecting_in_progress = True
# self._select_tracks(played=False)
# finally:
# self.selecting_in_progress = False
# self._select_event()
def set_searchtext(self, text: Optional[str]) -> None:
"""Set the search text and find first match"""
@ -1393,14 +1390,6 @@ class PlaylistTab(QTableWidget):
return track_id
# def _get_unplayed_track_rows(self) -> Optional[List[int]]:
# """Return rows marked as unplayed, or None"""
#
# unplayed_rows: Set[int] = set(self._meta_notset(RowMeta.PLAYED))
# notes_rows: Set[int] = set(self._get_notes_rows())
#
# return list(unplayed_rows - notes_rows)
def _get_selected_row(self) -> Optional[int]:
"""Return row number of first selected row, or None if none selected"""
@ -1409,6 +1398,13 @@ class PlaylistTab(QTableWidget):
else:
return self.selectionModel().selectedRows()[0].row()
def _get_selected_rows(self) -> List[int]:
"""Return a list of selected row numbers"""
# Use a set to deduplicate result (a selected row will have all
# items in that row selected)
return [row for row in set([a.row() for a in self.selectedItems()])]
def _get_unreadable_track_rows(self) -> List[int]:
"""Return rows marked as unreadable, or None"""
@ -1680,7 +1676,7 @@ class PlaylistTab(QTableWidget):
if self.selecting_in_progress:
return
selected_rows = self._selected_rows()
selected_rows = self._get_selected_rows()
# If no rows are selected, we have nothing to do
if len(selected_rows) == 0:
self.musicmuster.lblSumPlaytime.setText("")
@ -1697,13 +1693,6 @@ class PlaylistTab(QTableWidget):
else:
self.musicmuster.lblSumPlaytime.setText("")
def _selected_rows(self) -> List[int]:
"""Return a list of selected row numbers"""
# Use a set to deduplicate result (a selected row will have all
# items in that row selected)
return [row for row in set([a.row() for a in self.selectedItems()])]
def _set_column_widths(self, session: Session) -> None:
"""Column widths from settings"""

View File

@ -763,7 +763,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<addaction name="actionDeletePlaylist"/>
<addaction name="separator"/>
<addaction name="actionMoveSelected"/>
<addaction name="actionMove_unplayed"/>
<addaction name="actionMoveUnplayed"/>
<addaction name="actionDownload_CSV_of_played_tracks"/>
<addaction name="separator"/>
<addaction name="actionE_xit"/>
@ -1000,7 +1000,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<string>Select played tracks</string>
</property>
</action>
<action name="actionMove_unplayed">
<action name="actionMoveUnplayed">
<property name="text">
<string>Move &amp;unplayed tracks to...</string>
</property>

View File

@ -430,8 +430,8 @@ class Ui_MainWindow(object):
self.actionSelect_previous_track.setObjectName("actionSelect_previous_track")
self.actionSelect_played_tracks = QtWidgets.QAction(MainWindow)
self.actionSelect_played_tracks.setObjectName("actionSelect_played_tracks")
self.actionMove_unplayed = QtWidgets.QAction(MainWindow)
self.actionMove_unplayed.setObjectName("actionMove_unplayed")
self.actionMoveUnplayed = QtWidgets.QAction(MainWindow)
self.actionMoveUnplayed.setObjectName("actionMoveUnplayed")
self.actionAdd_note = QtWidgets.QAction(MainWindow)
self.actionAdd_note.setObjectName("actionAdd_note")
self.actionEnable_controls = QtWidgets.QAction(MainWindow)
@ -458,7 +458,7 @@ class Ui_MainWindow(object):
self.menuFile.addAction(self.actionDeletePlaylist)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionMoveSelected)
self.menuFile.addAction(self.actionMove_unplayed)
self.menuFile.addAction(self.actionMoveUnplayed)
self.menuFile.addAction(self.actionDownload_CSV_of_played_tracks)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionE_xit)
@ -559,7 +559,7 @@ class Ui_MainWindow(object):
self.actionSelect_previous_track.setText(_translate("MainWindow", "Select previous track"))
self.actionSelect_previous_track.setShortcut(_translate("MainWindow", "K"))
self.actionSelect_played_tracks.setText(_translate("MainWindow", "Select played tracks"))
self.actionMove_unplayed.setText(_translate("MainWindow", "Move &unplayed tracks to..."))
self.actionMoveUnplayed.setText(_translate("MainWindow", "Move &unplayed tracks to..."))
self.actionAdd_note.setText(_translate("MainWindow", "Add note..."))
self.actionAdd_note.setShortcut(_translate("MainWindow", "Ctrl+T"))
self.actionEnable_controls.setText(_translate("MainWindow", "Enable controls"))