WIP: Implement move rows to playlist
This commit is contained in:
parent
12541e1ff7
commit
c8194fad80
@ -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"]]:
|
||||
|
||||
@ -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__":
|
||||
|
||||
@ -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:
|
||||
# """
|
||||
|
||||
Loading…
Reference in New Issue
Block a user