Playlist creation and changing fragilely working

This commit is contained in:
Keith Edmunds 2021-04-07 22:07:53 +01:00
parent 15a540234e
commit 67b3b804e1
5 changed files with 248 additions and 91 deletions

View File

@ -147,13 +147,26 @@ class Playlists(Base):
def __repr__(self):
return (f"<Playlist(id={self.id}, name={self.name}>")
# Currently we only support one playlist, so make that obvious from
# function name
@classmethod
def get_playlist_by_name(cls, name):
"Returns a playlist object for named playlist"
@staticmethod
def new(name):
DEBUG(f"Playlists.new({name})")
pl = Playlists()
pl.name = name
session.add(pl)
session.commit()
return pl.id
return session.query(Playlists).filter(Playlists.name == name).one()
@staticmethod
def get_all_playlists():
"Returns a list of (id, name) of all playlists"
return session.query(Playlists).all()
@classmethod
def get_playlist_by_id(cls, plid):
"Returns a playlist object for playlist id"
return session.query(Playlists).filter(Playlists.id == plid).one()
def add_track(self, track, row):
glue = PlaylistTracks(row=row)
@ -178,14 +191,18 @@ class PlaylistTracks(Base):
playlists = relationship("Playlists", back_populates="tracks")
@staticmethod
def update_track_row(playlist_id, track_id, row):
DEBUG(f"update_track({id}, {row})")
def update_track_row(playlist_id, track_id, old_row, new_row):
DEBUG(
f"update_track_row({playlist_id}, "
f"{track_id}, {old_row}, {new_row})"
)
plt = session.query(PlaylistTracks).filter(
PlaylistTracks.playlist_id == playlist_id,
PlaylistTracks.track_id == track_id
PlaylistTracks.track_id == track_id,
PlaylistTracks.row == old_row
).one()
plt.row = row
plt.row = new_row
session.commit()
@staticmethod

View File

@ -7,21 +7,19 @@ import music
from datetime import datetime, timedelta
# from log import DEBUG
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import (
QApplication,
QDialog,
QFileDialog,
QInputDialog,
QListWidgetItem,
QLabel,
QMainWindow,
)
import helpers
from config import Config
from model import Playlists, Settings, Tracks
from ui.dlg_search_database_ui import Ui_Dialog
from model import Settings
from ui.main_window_ui import Ui_MainWindow
@ -47,11 +45,16 @@ class Window(QMainWindow, Ui_MainWindow):
height = record.f_int or 981
self.setGeometry(x, y, width, height)
# Hard code to the only playlist we have for now
if self.playlist.load_playlist("Default"):
# Hard code to the first playlist for now
# TODO
if self.playlist.load_playlist(1):
self.update_headers()
self.enable_play_next_controls()
self.timer.start(Config.TIMER_MS)
self.plLabel = QLabel(f"Playlist: {self.playlist.playlist_name}")
self.statusbar.addPermanentWidget(self.plLabel)
self.timer.start(Config.TIMER_MS)
def __del__(self):
record = Settings.get_int("mainwindow_height")
@ -90,6 +93,8 @@ class Window(QMainWindow, Ui_MainWindow):
def connect_signals_slots(self):
self.action_Clear_selection.triggered.connect(self.clear_selection)
self.actionFade.triggered.connect(self.fade)
self.actionNewPlaylist.triggered.connect(self.create_playlist)
self.actionSelectPlaylist.triggered.connect(self.select_playlist)
self.actionPlay_next.triggered.connect(self.play_next)
self.actionSearch_database.triggered.connect(self.search_database)
self.actionSkip_next.triggered.connect(self.play_next)
@ -102,6 +107,17 @@ class Window(QMainWindow, Ui_MainWindow):
self.timer.timeout.connect(self.tick)
def create_playlist(self):
"Create new playlist"
dlg = QInputDialog(self)
dlg.setInputMode(QInputDialog.TextInput)
dlg.setLabelText("Playlist name:")
dlg.resize(500, 100)
ok = dlg.exec()
if ok:
self.playlist.create_playlist(dlg.textValue())
def disable_play_next_controls(self):
self.actionPlay_next.setEnabled(False)
@ -143,8 +159,10 @@ class Window(QMainWindow, Ui_MainWindow):
pass
def search_database(self):
dlg = DbDialog(self)
dlg.exec()
self.playlist.search_database()
def select_playlist(self):
self.playlist.select_playlist()
def set_next_track(self):
"Set selected track as next"
@ -237,62 +255,8 @@ class Window(QMainWindow, Ui_MainWindow):
f"{self.playlist.get_next_artist()}"
)
class AddNoteDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_dlgAddNote()
self.ui.setupUi(self)
class DbDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.searchString.textEdited.connect(self.chars_typed)
self.ui.matchList.itemDoubleClicked.connect(self.listdclick)
record = Settings.get_int("dbdialog_width")
width = record.f_int or 800
record = Settings.get_int("dbdialog_height")
height = record.f_int or 600
self.resize(width, height)
def __del__(self):
record = Settings.get_int("dbdialog_height")
if record.f_int != self.height():
record.update({'f_int': self.height()})
record = Settings.get_int("dbdialog_width")
if record.f_int != self.width():
record.update({'f_int': self.width()})
def chars_typed(self, s):
if len(s) >= 3:
matches = Tracks.search_titles(s)
self.ui.matchList.clear()
if matches:
for track in matches:
t = QListWidgetItem()
t.setText(
f"{track.title} - {track.artist} "
f"[{helpers.ms_to_mmss(track.duration)}]"
)
t.setData(Qt.UserRole, track.id)
self.ui.matchList.addItem(t)
def listdclick(self, entry):
track_id = entry.data(Qt.UserRole)
track = Tracks.track_from_id(track_id)
# Store in current playlist in database
db_playlist = Playlists.get_only_playlist()
# TODO: hack position to be at end of list
db_playlist.add_track(track, 99999)
# Add to on-screen playlist
self.parent().add_to_playlist(track)
def update_statusbar(self):
pass
def main():

View File

@ -5,7 +5,9 @@ from PyQt5.QtGui import QColor, QDropEvent
from PyQt5.QtWidgets import (
QAbstractItemView,
QApplication,
QDialog,
QHBoxLayout,
QListWidgetItem,
QMenu,
QMessageBox,
QTableWidget,
@ -19,6 +21,8 @@ from config import Config
from datetime import datetime, timedelta
from log import DEBUG, ERROR
from model import Notes, Playdates, Playlists, PlaylistTracks, Settings, Tracks
from ui.dlg_search_database_ui import Ui_Dialog
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
class Playlist(QTableWidget):
@ -199,6 +203,12 @@ class Playlist(QTableWidget):
if repaint:
self.repaint()
def create_playlist(self, name):
"Create new playlist"
new_id = Playlists.new(name)
self.load_playlist(new_id)
def drop_on(self, event):
index = self.indexAt(event.pos())
if not index.isValid():
@ -327,21 +337,21 @@ class Playlist(QTableWidget):
and pos.y() >= rect.center().y() # noqa W503
)
def load_playlist(self, name):
def load_playlist(self, plid):
"""
Load tracks and notes from named playlist.
Load tracks and notes from playlist id.
Set first track as next track to play.
Return True if successful else False.
"""
DEBUG(f"load_playlist({name})")
DEBUG(f"load_playlist({plid})")
self.playlist_name = name
p = Playlists.get_playlist_by_name(name)
self.playlist_id = p.id
p = Playlists.get_playlist_by_id(plid)
self.playlist_id = plid
self.playlist_name = p.name
self.parent().parent().update_statusbar()
# We need to retrieve playlist tracks and playlist notes, then
# add them in row order. We don't mandate that an item will be
@ -354,6 +364,9 @@ class Playlist(QTableWidget):
for n in p.notes:
data.append(([n.row], n))
# Clear playlist
self.setRowCount(0)
# Now add data in row order
for item in sorted(data, key=lambda x: x[0]):
DEBUG(f"Adding {item}")
@ -516,6 +529,14 @@ class Playlist(QTableWidget):
# Update display
self.tracks_changed()
def search_database(self):
dlg = DbDialog(self)
dlg.exec()
def select_playlist(self):
dlg = SelectPlaylistDialog(self)
dlg.exec()
def set_selected_as_next(self):
"""
Sets the selected track as the next track.
@ -647,7 +668,7 @@ class Playlist(QTableWidget):
# Get tracks and notes from database
db_tracks = {}
db_notes = {}
p = Playlists.get_playlist_by_name(self.playlist_name)
p = Playlists.get_playlist_by_id(self.playlist_id)
for track in p.tracks:
db_tracks[track.track_id] = track.row
@ -682,7 +703,8 @@ class Playlist(QTableWidget):
if tracks[id] != db_tracks[id]:
DEBUG(f"Update db track.id={id} in database")
PlaylistTracks.update_track_row(
self.playlist_id, id, row=tracks[id]
self.playlist_id, track_id=id,
old_row=db_tracks[id], new_row=tracks[id]
)
def set_row_bold(self, row):
@ -749,6 +771,76 @@ class Playlist(QTableWidget):
self.repaint()
class DbDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.searchString.textEdited.connect(self.chars_typed)
self.ui.matchList.itemDoubleClicked.connect(self.listdclick)
record = Settings.get_int("dbdialog_width")
width = record.f_int or 800
record = Settings.get_int("dbdialog_height")
height = record.f_int or 600
self.resize(width, height)
def __del__(self):
record = Settings.get_int("dbdialog_height")
if record.f_int != self.height():
record.update({'f_int': self.height()})
record = Settings.get_int("dbdialog_width")
if record.f_int != self.width():
record.update({'f_int': self.width()})
def chars_typed(self, s):
if len(s) >= 3:
matches = Tracks.search_titles(s)
self.ui.matchList.clear()
if matches:
for track in matches:
t = QListWidgetItem()
t.setText(
f"{track.title} - {track.artist} "
f"[{helpers.ms_to_mmss(track.duration)}]"
)
t.setData(Qt.UserRole, track.id)
self.ui.matchList.addItem(t)
def listdclick(self, entry):
track_id = entry.data(Qt.UserRole)
track = Tracks.track_from_id(track_id)
# Store in current playlist in database
db_playlist = Playlists.get_playlist_by_id(self.parent().playlist_id)
# TODO: hack position to be at end of list
db_playlist.add_track(track, 99999)
# Add to on-screen playlist
self.parent().add_to_playlist(track)
class SelectPlaylistDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_dlgSelectPlaylist()
self.ui.setupUi(self)
self.ui.lstPlaylists.itemDoubleClicked.connect(self.listdclick)
for (plid, plname) in [
(a.id, a.name) for a in Playlists.get_all_playlists()
]:
p = QListWidgetItem()
p.setText(plname)
p.setData(Qt.UserRole, plid)
self.ui.lstPlaylists.addItem(p)
def listdclick(self, entry):
plid = entry.data(Qt.UserRole)
self.parent().load_playlist(plid)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>dlgSelectPlaylist</class>
<widget class="QDialog" name="dlgSelectPlaylist">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>276</width>
<height>150</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="lstPlaylists"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>dlgSelectPlaylist</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>dlgSelectPlaylist</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>768</width>
<width>931</width>
<height>600</height>
</rect>
</property>
@ -710,7 +710,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<rect>
<x>0</x>
<y>0</y>
<width>768</width>
<width>931</width>
<height>18</height>
</rect>
</property>
@ -724,19 +724,26 @@ border: 1px solid rgb(85, 87, 83);</string>
<property name="title">
<string>Pla&amp;ylist</string>
</property>
<addaction name="actionPlay_next"/>
<addaction name="actionSkip_next"/>
<addaction name="actionSearch_database"/>
<addaction name="actionAdd_file"/>
<addaction name="action_Clear_selection"/>
<addaction name="separator"/>
<addaction name="actionSelectPlaylist"/>
<addaction name="actionNewPlaylist"/>
</widget>
<widget class="QMenu" name="menu_Tracks">
<property name="title">
<string>&amp;Tracks</string>
</property>
<addaction name="actionPlay_next"/>
<addaction name="actionSkip_next"/>
<addaction name="actionFade"/>
<addaction name="actionS_top"/>
<addaction name="separator"/>
<addaction name="action_Resume_previous"/>
<addaction name="action_Clear_selection"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuPlaylist"/>
<addaction name="menu_Tracks"/>
</widget>
<widget class="QStatusBar" name="statusbar">
<property name="enabled">
@ -833,6 +840,16 @@ border: 1px solid rgb(85, 87, 83);</string>
<string>&amp;Test</string>
</property>
</action>
<action name="actionSelectPlaylist">
<property name="text">
<string>Select &amp;playlist</string>
</property>
</action>
<action name="actionNewPlaylist">
<property name="text">
<string>&amp;New playlist</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>