SQLA2.0 playlist column headers display
This commit is contained in:
parent
bef4507ef6
commit
ab47bb0ab4
2
.envrc
2
.envrc
@ -5,5 +5,5 @@ if on_git_branch master; then
|
||||
export MM_DB="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
|
||||
else MYSQL_DATABASE="musicmuster_dev"
|
||||
export MM_ENV="DEVELOPMENT"
|
||||
export MM_DB="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_dev"
|
||||
export MM_DB="mysql+mysqldb://musicmusterv3:musicmusterv3@localhost/musicmuster_dev_v3"
|
||||
fi
|
||||
|
||||
@ -28,6 +28,7 @@ class Config(object):
|
||||
COLUMN_NAME_LAST_PLAYED = "Last played"
|
||||
COLUMN_NAME_LEADING_SILENCE = "Gap"
|
||||
COLUMN_NAME_LENGTH = "Length"
|
||||
COLUMN_NAME_NOTES = "Notes"
|
||||
COLUMN_NAME_START_TIME = "Start"
|
||||
COLUMN_NAME_TITLE = "Title"
|
||||
DBFS_FADE = -12
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
from config import Config
|
||||
|
||||
103
app/models.py
103
app/models.py
@ -3,25 +3,26 @@
|
||||
# import os.path
|
||||
# import re
|
||||
#
|
||||
# from dbconfig import Session
|
||||
from dbconfig import Session
|
||||
#
|
||||
# from datetime import datetime
|
||||
# from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
#
|
||||
# from pydub import AudioSegment
|
||||
# from sqlalchemy.ext.associationproxy import association_proxy
|
||||
# from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
|
||||
# from sqlalchemy import (
|
||||
# Boolean,
|
||||
# Column,
|
||||
# DateTime,
|
||||
# Float,
|
||||
# ForeignKey,
|
||||
# func,
|
||||
# Integer,
|
||||
# String,
|
||||
# UniqueConstraint,
|
||||
# )
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
Column,
|
||||
DateTime,
|
||||
# Float,
|
||||
# ForeignKey,
|
||||
# func,
|
||||
Integer,
|
||||
String,
|
||||
# UniqueConstraint,
|
||||
select,
|
||||
)
|
||||
# from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import (
|
||||
# backref,
|
||||
@ -253,19 +254,19 @@ Base = declarative_base()
|
||||
# session.query(Playdates).filter(
|
||||
# Playdates.track_id == track_id).delete()
|
||||
# session.flush()
|
||||
#
|
||||
#
|
||||
# class Playlists(Base):
|
||||
# """
|
||||
# Manage playlists
|
||||
# """
|
||||
#
|
||||
# __tablename__ = "playlists"
|
||||
#
|
||||
# id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
# name: str = Column(String(32), nullable=False, unique=True)
|
||||
# last_used: datetime = Column(DateTime, default=None, nullable=True)
|
||||
# loaded: bool = Column(Boolean, default=True, nullable=False)
|
||||
|
||||
|
||||
class Playlists(Base):
|
||||
"""
|
||||
Manage playlists
|
||||
"""
|
||||
|
||||
__tablename__ = "playlists"
|
||||
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(32), nullable=False, unique=True)
|
||||
last_used: datetime = Column(DateTime, default=None, nullable=True)
|
||||
loaded: bool = Column(Boolean, default=True, nullable=False)
|
||||
# notes = relationship(
|
||||
# "Notes", order_by="Notes.row",
|
||||
# back_populates="playlist", lazy="select"
|
||||
@ -278,9 +279,9 @@ Base = declarative_base()
|
||||
# self.name = name
|
||||
# session.add(self)
|
||||
# session.flush()
|
||||
#
|
||||
# def __repr__(self) -> str:
|
||||
# return f"<Playlists(id={self.id}, name={self.name}>"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Playlists(id={self.id}, name={self.name}>"
|
||||
#
|
||||
# def add_track(
|
||||
# self, session: Session, track_id: int,
|
||||
@ -323,25 +324,29 @@ Base = declarative_base()
|
||||
# .filter(cls.loaded.is_(False))
|
||||
# .order_by(cls.last_used.desc())
|
||||
# ).all()
|
||||
#
|
||||
# @classmethod
|
||||
# def get_open(cls, session: Session) -> List["Playlists"]:
|
||||
# """
|
||||
# Return a list of playlists marked "loaded", ordered by loaded date.
|
||||
# """
|
||||
#
|
||||
# return (
|
||||
# session.query(cls)
|
||||
# .filter(cls.loaded.is_(True))
|
||||
# .order_by(cls.last_used.desc())
|
||||
# ).all()
|
||||
#
|
||||
# def mark_open(self, session: Session) -> None:
|
||||
# """Mark playlist as loaded and used now"""
|
||||
#
|
||||
# self.loaded = True
|
||||
# self.last_used = datetime.now()
|
||||
# session.flush()
|
||||
|
||||
@classmethod
|
||||
def get_open(cls, session: Session) -> List[Optional["Playlists"]]:
|
||||
"""
|
||||
Return a list of playlists marked "loaded", ordered by loaded date.
|
||||
"""
|
||||
|
||||
return (
|
||||
session.execute(
|
||||
select(cls)
|
||||
.where(cls.loaded.is_(True))
|
||||
.order_by(cls.last_used.desc())
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
|
||||
def mark_open(self, session: Session) -> None:
|
||||
"""Mark playlist as loaded and used now"""
|
||||
|
||||
self.loaded = True
|
||||
self.last_used = datetime.now()
|
||||
# session.flush()
|
||||
#
|
||||
# @staticmethod
|
||||
# def next_free_row(session: Session, playlist_id: int) -> int:
|
||||
|
||||
@ -27,8 +27,7 @@ from PyQt5.QtWidgets import (
|
||||
# QMessageBox,
|
||||
)
|
||||
#
|
||||
import dbconfig
|
||||
# from dbconfig import Session
|
||||
from dbconfig import engine, Session
|
||||
# import helpers
|
||||
# import music
|
||||
#
|
||||
@ -36,11 +35,11 @@ import dbconfig
|
||||
from models import (
|
||||
Base,
|
||||
# Playdates,
|
||||
# Playlists,
|
||||
Playlists,
|
||||
# Settings,
|
||||
# Tracks
|
||||
)
|
||||
# from playlists import PlaylistTab
|
||||
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
|
||||
@ -95,7 +94,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
# self.visible_playlist_tab: Callable[[], PlaylistTab] = \
|
||||
# self.tabPlaylist.currentWidget
|
||||
#
|
||||
#self.load_last_playlists()
|
||||
self._load_last_playlists()
|
||||
# self.enable_play_next_controls()
|
||||
# self.check_audacity()
|
||||
# self.timer.start(Config.TIMER_MS)
|
||||
@ -270,18 +269,18 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
# except AttributeError:
|
||||
# # Just return if there's no visible playlist tab
|
||||
# return
|
||||
#
|
||||
# def create_playlist_tab(self, session: Session,
|
||||
# playlist: Playlists) -> None:
|
||||
# """
|
||||
# Take the passed playlist database object, create a playlist tab and
|
||||
# add tab to display.
|
||||
# """
|
||||
#
|
||||
# playlist_tab: PlaylistTab = PlaylistTab(
|
||||
# musicmuster=self, session=session, playlist_id=playlist.id)
|
||||
# idx: int = self.tabPlaylist.addTab(playlist_tab, playlist.name)
|
||||
# self.tabPlaylist.setCurrentIndex(idx)
|
||||
|
||||
def create_playlist_tab(self, session: Session,
|
||||
playlist: Playlists) -> None:
|
||||
"""
|
||||
Take the passed playlist database object, create a playlist tab and
|
||||
add tab to display.
|
||||
"""
|
||||
|
||||
playlist_tab: PlaylistTab = PlaylistTab(
|
||||
musicmuster=self, session=session, playlist_id=playlist.id)
|
||||
idx: int = self.tabPlaylist.addTab(playlist_tab, playlist.name)
|
||||
self.tabPlaylist.setCurrentIndex(idx)
|
||||
#
|
||||
# def disable_play_next_controls(self) -> None:
|
||||
# """
|
||||
@ -494,14 +493,14 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
# # If we don't specify "repaint=False", playlist will
|
||||
# # also be saved to database
|
||||
# self.visible_playlist_tab().insert_track(session, track)
|
||||
#
|
||||
# def load_last_playlists(self):
|
||||
# """Load the playlists that were loaded at end of last session"""
|
||||
#
|
||||
# with Session() as session:
|
||||
# for playlist in Playlists.get_open(session):
|
||||
# self.create_playlist_tab(session, playlist)
|
||||
# playlist.mark_open(session)
|
||||
|
||||
def _load_last_playlists(self):
|
||||
"""Load the playlists that were open when the last session closed"""
|
||||
|
||||
with Session() as session:
|
||||
for playlist in Playlists.get_open(session):
|
||||
self.create_playlist_tab(session, playlist)
|
||||
playlist.mark_open(session)
|
||||
#
|
||||
# def move_selected(self) -> None:
|
||||
# """Move selected rows to another playlist"""
|
||||
@ -1168,7 +1167,7 @@ if __name__ == "__main__":
|
||||
# else:
|
||||
# # Normal run
|
||||
try:
|
||||
Base.metadata.create_all(dbconfig.engine)
|
||||
Base.metadata.create_all(engine)
|
||||
app = QApplication(sys.argv)
|
||||
win = Window()
|
||||
win.show()
|
||||
|
||||
160
app/playlists.py
160
app/playlists.py
@ -1,3 +1,5 @@
|
||||
from collections import namedtuple
|
||||
|
||||
# from enum import Enum, auto
|
||||
# from typing import Dict, List, Optional, Set, Tuple, Union
|
||||
#
|
||||
@ -6,18 +8,18 @@
|
||||
# from PyQt5.Qt import QFont
|
||||
# from PyQt5.QtGui import QColor, QDropEvent
|
||||
# from PyQt5 import QtWidgets
|
||||
# from PyQt5.QtWidgets import (
|
||||
# QAbstractItemView,
|
||||
# QApplication,
|
||||
# QInputDialog,
|
||||
# QLineEdit,
|
||||
# QMainWindow,
|
||||
# QMenu,
|
||||
# QStyledItemDelegate,
|
||||
# QMessageBox,
|
||||
# QTableWidget,
|
||||
# QTableWidgetItem,
|
||||
# )
|
||||
from PyQt5.QtWidgets import (
|
||||
# QAbstractItemView,
|
||||
# QApplication,
|
||||
# QInputDialog,
|
||||
# QLineEdit,
|
||||
QMainWindow,
|
||||
# QMenu,
|
||||
# QStyledItemDelegate,
|
||||
# QMessageBox,
|
||||
QTableWidget,
|
||||
QTableWidgetItem,
|
||||
)
|
||||
#
|
||||
# import helpers
|
||||
# import os
|
||||
@ -25,7 +27,7 @@
|
||||
# import subprocess
|
||||
# import threading
|
||||
#
|
||||
# from config import Config
|
||||
from config import Config
|
||||
# from datetime import datetime, timedelta
|
||||
# from helpers import get_relative_date, open_in_audacity
|
||||
# from log import log.debug, log.error
|
||||
@ -38,8 +40,8 @@
|
||||
# Tracks,
|
||||
# NoteColours
|
||||
# )
|
||||
# from dbconfig import Session
|
||||
#
|
||||
from dbconfig import Session
|
||||
#from collections import namedtuple
|
||||
# start_time_re = re.compile(r"@\d\d:\d\d:\d\d")
|
||||
#
|
||||
#
|
||||
@ -50,20 +52,19 @@
|
||||
# NEXT = 3
|
||||
# CURRENT = 4
|
||||
# PLAYED = 5
|
||||
#
|
||||
#
|
||||
# class Columns(Enum):
|
||||
# AUTOPLAY = COL_USERDATA = auto()
|
||||
# MSS = auto()
|
||||
# NOTE = TITLE = auto()
|
||||
# ARTIST = auto()
|
||||
# DURATION = auto()
|
||||
# START_TIME = auto()
|
||||
# END_TIME = auto()
|
||||
# LAST_PLAYED = auto()
|
||||
# ROW_NOTES = auto()
|
||||
# LAST = ROW_NOTES
|
||||
#
|
||||
|
||||
# Columns
|
||||
Column = namedtuple("Column", ['idx', 'heading'])
|
||||
columns = {}
|
||||
columns["userdata"] = Column(idx=0, heading=Config.COLUMN_NAME_AUTOPLAY),
|
||||
columns["mss"] = Column(idx=1, heading=Config.COLUMN_NAME_LEADING_SILENCE),
|
||||
columns["title"] = Column(idx=2, heading=Config.COLUMN_NAME_TITLE),
|
||||
columns["artist"] = Column(idx=3, heading=Config.COLUMN_NAME_ARTIST),
|
||||
columns["duration"] = Column(idx=4, heading=Config.COLUMN_NAME_LENGTH),
|
||||
columns["start_time"] = Column(idx=5, heading=Config.COLUMN_NAME_START_TIME),
|
||||
columns["end_time"] = Column(idx=6, heading=Config.COLUMN_NAME_END_TIME),
|
||||
columns["last_played"] = Column(idx=7, heading=Config.COLUMN_NAME_LAST_PLAYED),
|
||||
columns["row_notes"] = Column(idx=8, heading=Config.COLUMN_NAME_NOTES),
|
||||
#
|
||||
# class NoSelectDelegate(QStyledItemDelegate):
|
||||
# """https://stackoverflow.com/questions/72790705/dont-select-text-in-qtablewidget-cell-when-editing/72792962#72792962"""
|
||||
@ -79,84 +80,49 @@
|
||||
# editor.deselect()
|
||||
# editor.selectionChanged.connect(deselect)
|
||||
# return editor
|
||||
#
|
||||
# class PlaylistTab(QTableWidget):
|
||||
# cellEditingStarted = QtCore.pyqtSignal(int, int)
|
||||
# cellEditingEnded = QtCore.pyqtSignal()
|
||||
#
|
||||
# # Column names
|
||||
# COL_AUTOPLAY = COL_USERDATA = 0
|
||||
# COL_MSS = 1
|
||||
# COL_NOTE = COL_TITLE = 2
|
||||
# COL_ARTIST = 3
|
||||
# COL_DURATION = 4
|
||||
# COL_START_TIME = 5
|
||||
# COL_END_TIME = 6
|
||||
# COL_LAST_PLAYED = 7
|
||||
# COL_ROW_NOTES = 8
|
||||
# COL_LAST = COL_ROW_NOTES
|
||||
#
|
||||
# NOTE_COL_SPAN = COL_LAST - COL_NOTE + 1
|
||||
# NOTE_ROW_SPAN = 1
|
||||
#
|
||||
# # Qt.UserRoles
|
||||
# ROW_METADATA = Qt.UserRole
|
||||
# CONTENT_OBJECT = Qt.UserRole + 1
|
||||
# ROW_DURATION = Qt.UserRole + 2
|
||||
#
|
||||
# def __init__(self, musicmuster: QMainWindow, session: Session,
|
||||
# playlist_id: int, *args, **kwargs):
|
||||
# super().__init__(*args, **kwargs)
|
||||
#
|
||||
# self.musicmuster: QMainWindow = musicmuster
|
||||
# self.playlist_id: int = playlist_id
|
||||
|
||||
|
||||
class PlaylistTab(QTableWidget):
|
||||
# cellEditingStarted = QtCore.pyqtSignal(int, int)
|
||||
# cellEditingEnded = QtCore.pyqtSignal()
|
||||
|
||||
# # Qt.UserRoles
|
||||
# ROW_METADATA = Qt.UserRole
|
||||
# CONTENT_OBJECT = Qt.UserRole + 1
|
||||
# ROW_DURATION = Qt.UserRole + 2
|
||||
|
||||
def __init__(self, musicmuster: QMainWindow, session: Session,
|
||||
playlist_id: int, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.musicmuster: QMainWindow = musicmuster
|
||||
self.playlist_id: int = playlist_id
|
||||
# self.menu: Optional[QMenu] = None
|
||||
# self.current_track_start_time: Optional[datetime] = None
|
||||
#
|
||||
# # Don't select text on edit
|
||||
# self.setItemDelegate(NoSelectDelegate(self))
|
||||
#
|
||||
# # Set up widget
|
||||
# Set up widget
|
||||
# self.setEditTriggers(QtWidgets.QAbstractItemView.AllEditTriggers)
|
||||
# self.setAlternatingRowColors(True)
|
||||
self.setAlternatingRowColors(True)
|
||||
# self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
# self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
# self.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
||||
# self.setRowCount(0)
|
||||
# self.setColumnCount(9)
|
||||
# # Add header row
|
||||
# item: QTableWidgetItem = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(0, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(1, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(2, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(3, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(4, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(5, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(6, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(7, item)
|
||||
# item = QtWidgets.QTableWidgetItem()
|
||||
# self.setHorizontalHeaderItem(8, item)
|
||||
# self.horizontalHeader().setMinimumSectionSize(0)
|
||||
#
|
||||
# self._set_column_widths(session)
|
||||
# self.setHorizontalHeaderLabels([
|
||||
# Config.COLUMN_NAME_AUTOPLAY,
|
||||
# Config.COLUMN_NAME_LEADING_SILENCE,
|
||||
# Config.COLUMN_NAME_TITLE,
|
||||
# Config.COLUMN_NAME_ARTIST,
|
||||
# Config.COLUMN_NAME_LENGTH,
|
||||
# Config.COLUMN_NAME_START_TIME,
|
||||
# Config.COLUMN_NAME_END_TIME,
|
||||
# Config.COLUMN_NAME_LAST_PLAYED,
|
||||
# "Row notes",
|
||||
# ])
|
||||
self.setRowCount(0)
|
||||
self.setColumnCount(len(columns))
|
||||
# Add header row
|
||||
for idx in [a for a in range(len(columns))]:
|
||||
item: QTableWidgetItem = QTableWidgetItem()
|
||||
self.setHorizontalHeaderItem(idx, item)
|
||||
|
||||
self.horizontalHeader().setMinimumSectionSize(0)
|
||||
# self._set_column_widths(session)
|
||||
# Set column headings sorted by idx
|
||||
self.setHorizontalHeaderLabels(
|
||||
[a[0].heading for a in list(sorted(columns.values(),
|
||||
key=lambda item: item[0][0]))]
|
||||
)
|
||||
#
|
||||
# self.setDragEnabled(True)
|
||||
# self.setAcceptDrops(True)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user