Remove rows from playlist works and db updates

This commit is contained in:
Keith Edmunds 2022-12-23 20:15:07 +00:00
parent 35b101a538
commit 444c3e4fb4
2 changed files with 91 additions and 82 deletions

View File

@ -457,7 +457,7 @@ class PlaylistRows(Base):
-> None:
"""
Delete rows in given playlist that have a higher row number
than 'row'
than 'maxrow'
"""
# Log the rows to be deleted
@ -470,9 +470,7 @@ class PlaylistRows(Base):
return
for row in rows_to_go:
log.debug(f"Should delete: {row}")
# If needed later:
# session.delete(row)
session.delete(row)
@staticmethod
def delete_rows(session: Session, ids: List[int]) -> None:
@ -617,23 +615,22 @@ class PlaylistRows(Base):
)
@staticmethod
def indexed_by_row(session: Session, playlist_id: int) -> dict:
def indexed_by_id(session: Session, plr_ids: List[int]) -> dict:
"""
Return a dictionary of playlist_rows indexed by row number for
the passed playlist_id.
Return a dictionary of playlist_rows indexed by their plr id from
the passed plr_id list.
"""
plrs = session.execute(
select(PlaylistRows)
.where(
PlaylistRows.playlist_id == playlist_id,
PlaylistRows.id.in_(plr_ids)
)
.order_by(PlaylistRows.row_number)
).scalars().all()
result = {}
for plr in plrs:
result[plr.row_number] = plr
result[plr.id] = plr
return result

View File

@ -822,22 +822,39 @@ class PlaylistTab(QTableWidget):
def save_playlist(self, session: Session) -> None:
"""
All playlist rows have a PlaylistRows id. Check that that id points
to this playlist (in case track has been moved from other) and that
the row number is correct (in case tracks have been reordered).
Get the PlaylistRow objects for each row in the display. Correct
the row_number and playlist_id if necessary. Remove any row
numbers in the database that are higher than the last row in
the display.
"""
plr_dict = PlaylistRows.indexed_by_row(session, self.playlist_id)
# Build a dictionary of
# {display_row_number: display_row_plr_id}
display_plr_ids = {row_number: self._get_playlistrow_id(row_number)
for row_number in range(self.rowCount())}
# Now build a dictionary of
# {display_row_number: display_row_plr}
plr_dict_by_id = PlaylistRows.indexed_by_id(session,
display_plr_ids.values())
# Finally a dictionary of
# {display_row_number: plr}
row_plr = {row_number: plr_dict_by_id[display_plr_ids[row_number]]
for row_number in range(self.rowCount())}
# Ensure all row plrs have correct row number and playlist_id
for row in range(self.rowCount()):
# Set the row number and playlist id (even if correct)
plr_dict[row].row_number = row
plr_dict[row].playlist_id = self.playlist_id
row_plr[row].row_number = row
row_plr[row].playlist_id = self.playlist_id
# Any rows in the database with a row_number higher that the
# current value of 'row' should not be there. Commit session
# first to ensure any changes made above are committed.
session.commit()
PlaylistRows.delete_higher_rows(session, self.playlist_id, row)
PlaylistRows.delete_higher_rows(session, self.playlist_id,
self.rowCount() - 1)
session.commit()
def scroll_current_to_top(self) -> None:
"""Scroll currently-playing row to top"""
@ -860,65 +877,6 @@ class PlaylistTab(QTableWidget):
return
self._search(next=True)
def _search(self, next: bool = True) -> None:
"""
Select next/previous row containg self.search_string. Start from
top selected row if there is one, else from top.
Wrap at last/first row.
"""
if not self.search_text:
return
selected_row = self._get_selected_row()
if next:
if selected_row is not None and selected_row < self.rowCount() - 1:
starting_row = selected_row + 1
else:
starting_row = 0
else:
if selected_row is not None and selected_row > 0:
starting_row = selected_row - 1
else:
starting_row = self.rowCount() - 1
wrapped = False
match_row = None
row = starting_row
needle = self.search_text.lower()
while True:
# Check for match in title, artist or notes
title = self._get_row_title(row)
if title and needle in title.lower():
match_row = row
break
artist = self._get_row_artist(row)
if artist and needle in artist.lower():
match_row = row
break
note = self._get_row_note(row)
if note and needle in note.lower():
match_row = row
break
if next:
row += 1
if wrapped and row >= starting_row:
break
if row >= self.rowCount():
row = 0
wrapped = True
else:
row -= 1
if wrapped and row <= starting_row:
break
if row < 0:
row = self.rowCount() - 1
wrapped = True
if match_row is not None:
self.selectRow(row)
def search_next(self) -> None:
"""
Select next row containg self.search_string.
@ -1541,11 +1499,6 @@ class PlaylistTab(QTableWidget):
return self._meta_search(RowMeta.UNREADABLE, one=False)
# def _header_click(self, index: int) -> None:
# """Handle playlist header click"""
# print(f"_header_click({index=})")
def _info_row(self, track_id: int) -> None:
"""Display popup with info re row"""
@ -1765,6 +1718,65 @@ class PlaylistTab(QTableWidget):
scroll_item = self.item(top_row, 0)
self.scrollToItem(scroll_item, QAbstractItemView.PositionAtTop)
def _search(self, next: bool = True) -> None:
"""
Select next/previous row containg self.search_string. Start from
top selected row if there is one, else from top.
Wrap at last/first row.
"""
if not self.search_text:
return
selected_row = self._get_selected_row()
if next:
if selected_row is not None and selected_row < self.rowCount() - 1:
starting_row = selected_row + 1
else:
starting_row = 0
else:
if selected_row is not None and selected_row > 0:
starting_row = selected_row - 1
else:
starting_row = self.rowCount() - 1
wrapped = False
match_row = None
row = starting_row
needle = self.search_text.lower()
while True:
# Check for match in title, artist or notes
title = self._get_row_title(row)
if title and needle in title.lower():
match_row = row
break
artist = self._get_row_artist(row)
if artist and needle in artist.lower():
match_row = row
break
note = self._get_row_note(row)
if note and needle in note.lower():
match_row = row
break
if next:
row += 1
if wrapped and row >= starting_row:
break
if row >= self.rowCount():
row = 0
wrapped = True
else:
row -= 1
if wrapped and row <= starting_row:
break
if row < 0:
row = self.rowCount() - 1
wrapped = True
if match_row is not None:
self.selectRow(row)
def _select_event(self) -> None:
"""
Called when item selection changes.