WIP: Implement move rows to playlist

This commit is contained in:
Keith Edmunds 2022-08-09 20:33:06 +01:00
parent 12541e1ff7
commit c8194fad80
3 changed files with 171 additions and 122 deletions

View File

@ -18,7 +18,7 @@ from sqlalchemy import (
delete,
Float,
ForeignKey,
# func,
func,
Integer,
select,
String,
@ -317,15 +317,15 @@ class Playlists(Base):
# self.loaded = False
# session.add(self)
# session.flush()
#
# @classmethod
# def get_all(cls, session: Session) -> List["Playlists"]:
# """Returns a list of all playlists ordered by last use"""
#
# return (
# session.query(cls).order_by(
# cls.loaded.desc(), cls.last_used.desc())
# ).all()
@classmethod
def get_all(cls, session: Session) -> List["Playlists"]:
"""Returns a list of all playlists ordered by last use"""
return (
session.query(cls).order_by(
cls.loaded.desc(), cls.last_used.desc())
).all()
#
# @classmethod
# def get_closed(cls, session: Session) -> List["Playlists"]:
@ -508,6 +508,31 @@ class PlaylistRows(Base):
# Ensure new row numbers are available to the caller
session.commit()
@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
"""
# Find last row of destination playlist
last_row = session.execute(
select(func.max(PlaylistRows.row_number))
.where(PlaylistRows.playlist_id == destination_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
session.commit()
# @classmethod
# def get_playlist_rows(cls, playlist_id: int) -> \
# Optional[List["PlaylistRows"]]:

View File

@ -13,16 +13,17 @@ import sys
# from typing import Callable, Dict, List, Optional, Tuple
#
# from PyQt5.QtCore import QDate, QEvent, QProcess, Qt, QTime, QTimer, QUrl
from PyQt5.QtCore import Qt
# from PyQt5.QtGui import QColor
# from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView
from PyQt5.QtWidgets import (
QApplication,
# QDialog,
QDialog,
# QFileDialog,
# QInputDialog,
QLabel,
# QLineEdit,
# QListWidgetItem,
QListWidgetItem,
QMainWindow,
# QMessageBox,
)
@ -35,14 +36,15 @@ from dbconfig import engine, Session
from models import (
Base,
# Playdates,
PlaylistRows,
Playlists,
# Settings,
Settings,
Tracks
)
from playlists import PlaylistTab
# from sqlalchemy.orm.exc import DetachedInstanceError
# from ui.dlg_search_database_ui import Ui_Dialog
# from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
# from ui.downloadcsv_ui import Ui_DateSelect
from config import Config
from ui.main_window_ui import Ui_MainWindow
@ -503,51 +505,58 @@ class Window(QMainWindow, Ui_MainWindow):
playlist.mark_open(session)
def move_selected(self) -> None:
"""Move selected rows to another playlist"""
"""
Move selected rows to another playlist
# ***KAE
pass
Actions required:
- identify destination playlist
- update playlist for the rows in the database
- remove them from the display
- update destination playlist display if loaded
"""
# with Session() as session:
# visible_tab = self.visible_playlist_tab()
# visible_tab_id = visible_tab.playlist_id
#
# source_playlist = None
# playlists = []
# for playlist in Playlists.get_all(session):
# if playlist.id == visible_tab_id:
# source_playlist = playlist
# 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
#
# self.visible_playlist_tab().move_selected_to_playlist(
# session, destination_playlist.id)
#
# # Update destination playlist_tab if visible (if not visible, it
# # will be re-populated when it is opened)
# destination_visible_playlist_tab = None
# for tab in range(self.tabPlaylist.count()):
# # Non-playlist tabs won't have a 'playlist_id' attribute
# if not hasattr(self.tabPlaylist.widget(tab), 'playlist_id'):
# continue
# if self.tabPlaylist.widget(tab).playlist_id == dlg.playlist.id:
# destination_visible_playlist_tab = (
# self.tabPlaylist.widget(tab))
# break
#
# if destination_visible_playlist_tab:
# # We need to commit to database for populate to work
# session.commit()
# destination_visible_playlist_tab.populate(
# session, dlg.playlist.id)
# Identify destination 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
)
# Remove moved rows from display
visible_tab.remove_selected_rows()
# Update destination playlist_tab if visible (if not visible, it
# will be re-populated when it is opened)
destination_visible_playlist_tab = None
for tab in range(self.tabPlaylist.count()):
# Non-playlist tabs won't have a 'playlist_id' attribute
if not hasattr(self.tabPlaylist.widget(tab), 'playlist_id'):
continue
if self.tabPlaylist.widget(tab).playlist_id == dlg.playlist.id:
destination_visible_playlist_tab = (
self.tabPlaylist.widget(tab))
break
if destination_visible_playlist_tab:
destination_visible_playlist_tab.populate(
session, dlg.playlist.id)
#
# def open_info_tabs(self) -> None:
# """
@ -1095,57 +1104,57 @@ class Window(QMainWindow, Ui_MainWindow):
# self.ui.dateTimeEdit.setTime(QTime(19, 59, 0))
# self.ui.buttonBox.accepted.connect(self.accept)
# self.ui.buttonBox.rejected.connect(self.reject)
#
#
# class SelectPlaylistDialog(QDialog):
# def __init__(self, parent=None, playlists=None, session=None):
# super().__init__(parent)
#
# if playlists is None:
# return
# self.ui = Ui_dlgSelectPlaylist()
# self.ui.setupUi(self)
# self.ui.lstPlaylists.itemDoubleClicked.connect(self.list_doubleclick)
# self.ui.buttonBox.accepted.connect(self.open)
# self.ui.buttonBox.rejected.connect(self.close)
# self.session = session
# self.playlist = None
# self.plid = None
#
# record = Settings.get_int_settings(
# self.session, "select_playlist_dialog_width")
# width = record.f_int or 800
# record = Settings.get_int_settings(
# self.session, "select_playlist_dialog_height")
# height = record.f_int or 600
# self.resize(width, height)
#
# for playlist in playlists:
# p = QListWidgetItem()
# p.setText(playlist.name)
# p.setData(Qt.UserRole, playlist)
# self.ui.lstPlaylists.addItem(p)
#
# def __del__(self): # review
# record = Settings.get_int_settings(
# self.session, "select_playlist_dialog_height")
# if record.f_int != self.height():
# record.update(self.session, {'f_int': self.height()})
#
# record = Settings.get_int_settings(
# self.session, "select_playlist_dialog_width")
# if record.f_int != self.width():
# record.update(self.session, {'f_int': self.width()})
#
# def list_doubleclick(self, entry): # review
# self.playlist = entry.data(Qt.UserRole)
# self.accept()
#
# def open(self): # review
# if self.ui.lstPlaylists.selectedItems():
# item = self.ui.lstPlaylists.currentItem()
# self.playlist = item.data(Qt.UserRole)
# self.accept()
class SelectPlaylistDialog(QDialog):
def __init__(self, parent=None, playlists=None, session=None):
super().__init__(parent)
if playlists is None:
return
self.ui = Ui_dlgSelectPlaylist()
self.ui.setupUi(self)
self.ui.lstPlaylists.itemDoubleClicked.connect(self.list_doubleclick)
self.ui.buttonBox.accepted.connect(self.open)
self.ui.buttonBox.rejected.connect(self.close)
self.session = session
self.playlist = None
self.plid = None
record = Settings.get_int_settings(
self.session, "select_playlist_dialog_width")
width = record.f_int or 800
record = Settings.get_int_settings(
self.session, "select_playlist_dialog_height")
height = record.f_int or 600
self.resize(width, height)
for playlist in playlists:
p = QListWidgetItem()
p.setText(playlist.name)
p.setData(Qt.UserRole, playlist)
self.ui.lstPlaylists.addItem(p)
def __del__(self): # review
record = Settings.get_int_settings(
self.session, "select_playlist_dialog_height")
if record.f_int != self.height():
record.update(self.session, {'f_int': self.height()})
record = Settings.get_int_settings(
self.session, "select_playlist_dialog_width")
if record.f_int != self.width():
record.update(self.session, {'f_int': self.width()})
def list_doubleclick(self, entry): # review
self.playlist = entry.data(Qt.UserRole)
self.accept()
def open(self): # review
if self.ui.lstPlaylists.selectedItems():
item = self.ui.lstPlaylists.currentItem()
self.playlist = item.data(Qt.UserRole)
self.accept()
if __name__ == "__main__":

View File

@ -340,6 +340,13 @@ class PlaylistTab(QTableWidget):
self.clearSelection()
self.setDragEnabled(False)
def get_selected_playlistrow_ids(self) -> Optional[List]:
"""
Return a list of PlaylistRow ids of the selected rows
"""
return [self._get_playlistrow_id(a) for a in self._selected_rows()]
# def closeEvent(self, event) -> None:
# """Save column widths"""
#
@ -697,6 +704,16 @@ class PlaylistTab(QTableWidget):
# KAE self.save_playlist(session)
self.update_display(session)
def remove_selected_rows(self) -> None:
"""Remove selected 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):
self.removeRow(row)
# Reset drag mode
self.setDragEnabled(False)
def save_playlist(self, session: Session) -> None:
"""
Save playlist to database
@ -1254,22 +1271,14 @@ class PlaylistTab(QTableWidget):
"""
# Delete rows from database
# Each item in a row will be returned from selectedItems(), so
# make a set to remove duplicate row numbers
selected_rows = sorted(
set(item.row() for item in self.selectedItems())
)
plr_ids = [self._get_playlistrow_id(a) for a in selected_rows]
plr_ids = self.get_selected_playlistrow_ids()
with Session() as session:
PlaylistRows.delete_rows(session, plr_ids)
# Fix up row numbers left in this playlist
PlaylistRows.fixup_rownumbers(session, self.playlist_id)
# Remove rows from display. Do so in reverse order so that
# row numbers remain valid.
for row in sorted(selected_rows, reverse=True):
self.removeRow(row)
#Remove selected rows from display
self.remove_selected_rows()
def _drop_on(self, event):
"""
@ -1736,9 +1745,7 @@ class PlaylistTab(QTableWidget):
if self.selecting_in_progress:
return
# Get the row number of all selected items and put into a set
# to deduplicate
selected_rows = set([item.row() for item in self.selectedItems()])
selected_rows = self._selected_rows()
# If no rows are selected, we have nothing to do
if len(selected_rows) == 0:
self.musicmuster.lblSumPlaytime.setText("")
@ -1754,6 +1761,14 @@ class PlaylistTab(QTableWidget):
f"Selected duration: {helpers.ms_to_mmss(ms)}")
else:
self.musicmuster.lblSumPlaytime.setText("")
def _selected_rows(self) -> Optional[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 _select_tracks(self, played: bool) -> None:
# """