WIP V3: playlist populates from database
This commit is contained in:
parent
51a827093a
commit
bec336d2a3
@ -67,7 +67,7 @@ import icons_rc # noqa F401
|
||||
import music
|
||||
from models import Base, Carts, Playdates, PlaylistRows, Playlists, Settings, Tracks
|
||||
from config import Config
|
||||
from playlists import PlaylistTab
|
||||
from playlists_v3 import PlaylistTab
|
||||
from ui.dlg_cart_ui import Ui_DialogCartEdit # type: ignore
|
||||
from ui.dlg_search_database_ui import Ui_Dialog # type: ignore
|
||||
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist # type: ignore
|
||||
|
||||
217
app/playlistmodel.py
Normal file
217
app/playlistmodel.py
Normal file
@ -0,0 +1,217 @@
|
||||
from datetime import datetime
|
||||
from enum import auto, Enum
|
||||
from typing import Optional
|
||||
|
||||
from PyQt6.QtCore import (
|
||||
QAbstractTableModel,
|
||||
QModelIndex,
|
||||
Qt,
|
||||
QVariant,
|
||||
)
|
||||
|
||||
from PyQt6.QtGui import (
|
||||
QColor,
|
||||
QFont,
|
||||
)
|
||||
|
||||
from config import Config
|
||||
|
||||
from dbconfig import Session
|
||||
|
||||
from helpers import (
|
||||
file_is_unreadable,
|
||||
)
|
||||
|
||||
from models import (
|
||||
PlaylistRows,
|
||||
)
|
||||
|
||||
|
||||
class Col(Enum):
|
||||
START_GAP = 0
|
||||
TITLE = auto()
|
||||
ARTIST = auto()
|
||||
DURATION = auto()
|
||||
START_TIME = auto()
|
||||
END_TIME = auto()
|
||||
LASTPLAYED = auto()
|
||||
BITRATE = auto()
|
||||
NOTE = auto()
|
||||
|
||||
|
||||
class PlaylistRowData:
|
||||
|
||||
def __init__(self, plr: PlaylistRows) -> None:
|
||||
"""
|
||||
Populate PlaylistRowData from database PlaylistRows record
|
||||
"""
|
||||
|
||||
self.start_gap: Optional[int] = None
|
||||
self.title: str = ""
|
||||
self.artist: str = ""
|
||||
self.duration: int = 0
|
||||
self.lastplayed: datetime = Config.EPOCH
|
||||
self.bitrate = 0
|
||||
self.path = ""
|
||||
|
||||
self.plrid: int = plr.id
|
||||
self.plr_rownum: int = plr.plr_rownum
|
||||
self.note: str = plr.note
|
||||
if plr.track:
|
||||
self.start_gap = plr.track.start_gap
|
||||
self.title = plr.track.title
|
||||
self.artist = plr.track.artist
|
||||
self.duration = plr.track.duration
|
||||
if plr.track.playdates:
|
||||
self.lastplayed = max([a.lastplayed for a in plr.track.playdates])
|
||||
else:
|
||||
self.lastplayed = Config.EPOCH
|
||||
self.bitrate = plr.track.bitrate or 0
|
||||
self.path = plr.track.path
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<PlaylistRowData: plrid={self.plrid}, plr_rownum={self.plr_rownum}, "
|
||||
f"note='{self.note}', title='{self.title}', artist='{self.artist}'>"
|
||||
)
|
||||
|
||||
|
||||
class PlaylistModel(QAbstractTableModel):
|
||||
def __init__(self, playlist_id: int, *args, **kwargs):
|
||||
self.playlist_id = playlist_id
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.playlist_rows: dict[int, PlaylistRowData] = {}
|
||||
# self.current_row = None
|
||||
# self.next_row = None
|
||||
self.previous_row = None
|
||||
self.current_row = 2
|
||||
self.next_row = 3
|
||||
|
||||
self.refresh_data()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<PlaylistModel: playlist_id={self.playlist_id}>"
|
||||
)
|
||||
|
||||
def columnCount(self, parent: QModelIndex) -> int:
|
||||
"""Standard function for view"""
|
||||
|
||||
return 9
|
||||
|
||||
def data(self, index: QModelIndex, role: Qt.ItemDataRole.DisplayRole):
|
||||
"""Return data to view"""
|
||||
|
||||
if not index.isValid() or not (
|
||||
0 <= index.row() < len(self.playlist_rows)):
|
||||
return QVariant()
|
||||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
# prd for playlist row data as it's used a lot
|
||||
prd = self.playlist_rows[row]
|
||||
|
||||
# Dispatch to role-specific functions
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
return self.display_role(row, column, prd)
|
||||
elif role == Qt.ItemDataRole.DecorationRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.EditRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.ToolTipRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.StatusTipRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.WhatsThisRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.SizeHintRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.FontRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.TextAlignmentRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.BackgroundRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.ForegroundRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.CheckStateRole:
|
||||
pass
|
||||
elif role == Qt.ItemDataRole.InitialSortOrderRole:
|
||||
pass
|
||||
|
||||
# Fall through to no-op
|
||||
return QVariant()
|
||||
|
||||
def display_role(self, row: int, column: int, prd: PlaylistRowData) -> QVariant:
|
||||
"""
|
||||
Return text for display
|
||||
"""
|
||||
|
||||
if column == Col.START_GAP.value:
|
||||
return QVariant(prd.start_gap)
|
||||
if column == Col.TITLE.value:
|
||||
return QVariant(prd.title)
|
||||
if column == Col.ARTIST.value:
|
||||
return QVariant(prd.artist)
|
||||
if column == Col.DURATION.value:
|
||||
return QVariant(prd.duration)
|
||||
if column == Col.START_TIME.value:
|
||||
return QVariant("FIXME")
|
||||
if column == Col.END_TIME.value:
|
||||
return QVariant("FIXME")
|
||||
if column == Col.LASTPLAYED.value:
|
||||
return QVariant(prd.lastplayed)
|
||||
if column == Col.BITRATE.value:
|
||||
return QVariant(prd.bitrate)
|
||||
if column == Col.NOTE.value:
|
||||
return QVariant(prd.note)
|
||||
|
||||
return QVariant()
|
||||
|
||||
|
||||
if role == Qt.ItemDataRole.BackgroundRole:
|
||||
if rowdata.path and file_is_unreadable(rowdata.path):
|
||||
return QVariant(QColor(Config.COLOUR_UNREADABLE))
|
||||
elif row == self.current_row:
|
||||
return QVariant(QColor(Config.COLOUR_CURRENT_PLAYLIST))
|
||||
elif row == self.next_row:
|
||||
return QVariant(QColor(Config.COLOUR_NEXT_PLAYLIST))
|
||||
elif column == BITRATE:
|
||||
if rowdata.bitrate:
|
||||
if rowdata.bitrate < Config.BITRATE_LOW_THRESHOLD:
|
||||
cell_colour = Config.COLOUR_BITRATE_LOW
|
||||
elif rowdata.bitrate < Config.BITRATE_OK_THRESHOLD:
|
||||
cell_colour = Config.COLOUR_BITRATE_MEDIUM
|
||||
else:
|
||||
cell_colour = Config.COLOUR_BITRATE_OK
|
||||
return QVariant(QColor(cell_colour))
|
||||
|
||||
# Return a QColor, QIcon or QPixmap. QColor puts a coloured
|
||||
# block to left of text
|
||||
|
||||
return QVariant()
|
||||
|
||||
# Text colour, not currently used
|
||||
return QVariant()
|
||||
|
||||
if not rowdata.played:
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
return QVariant(font)
|
||||
|
||||
return QVariant()
|
||||
|
||||
def refresh_data(self):
|
||||
"""Populate dicts for data calls"""
|
||||
|
||||
|
||||
# Populate self.playlist_rows with playlist data
|
||||
with Session() as session:
|
||||
for p in PlaylistRows.deep_rows(session, self.playlist_id):
|
||||
self.playlist_rows[p.plr_rownum] = PlaylistRowData(p)
|
||||
|
||||
def rowCount(self, index: QModelIndex) -> int:
|
||||
"""Standard function for view"""
|
||||
|
||||
return len(self.playlist_rows)
|
||||
2589
app/playlists_v3.py
Normal file
2589
app/playlists_v3.py
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user