190 lines
6.2 KiB
Python
190 lines
6.2 KiB
Python
# Standard library imports
|
|
from typing import Optional
|
|
import datetime as dt
|
|
|
|
# PyQt imports
|
|
|
|
# Third party imports
|
|
from alchemical import Model # type: ignore
|
|
from sqlalchemy import (
|
|
Boolean,
|
|
DateTime,
|
|
ForeignKey,
|
|
String,
|
|
)
|
|
from sqlalchemy.ext.associationproxy import association_proxy
|
|
from sqlalchemy.orm import (
|
|
Mapped,
|
|
mapped_column,
|
|
relationship,
|
|
)
|
|
|
|
# App imports
|
|
|
|
|
|
# Database classes
|
|
class NoteColoursTable(Model):
|
|
__tablename__ = "notecolours"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
substring: Mapped[str] = mapped_column(String(256), index=True)
|
|
colour: Mapped[str] = mapped_column(String(21), index=False)
|
|
enabled: Mapped[bool] = mapped_column(default=True, index=True)
|
|
foreground: Mapped[Optional[str]] = mapped_column(String(21), index=False)
|
|
is_regex: Mapped[bool] = mapped_column(default=False, index=False)
|
|
is_casesensitive: Mapped[bool] = mapped_column(default=False, index=False)
|
|
order: Mapped[Optional[int]] = mapped_column(index=True)
|
|
strip_substring: Mapped[bool] = mapped_column(default=True, index=False)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<NoteColours(id={self.id}, substring={self.substring}, "
|
|
f"colour={self.colour}>"
|
|
)
|
|
|
|
|
|
class PlaydatesTable(Model):
|
|
__tablename__ = "playdates"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
lastplayed: Mapped[dt.datetime] = mapped_column(index=True)
|
|
track_id: Mapped[int] = mapped_column(ForeignKey("tracks.id"))
|
|
track: Mapped["TracksTable"] = relationship(
|
|
"TracksTable",
|
|
back_populates="playdates",
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Playdates(id={self.id}, track_id={self.track_id} "
|
|
f"lastplayed={self.lastplayed}>"
|
|
)
|
|
|
|
|
|
class PlaylistsTable(Model):
|
|
"""
|
|
Manage playlists
|
|
"""
|
|
|
|
__tablename__ = "playlists"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
name: Mapped[str] = mapped_column(String(32), unique=True)
|
|
last_used: Mapped[Optional[dt.datetime]] = mapped_column(DateTime, default=None)
|
|
tab: Mapped[Optional[int]] = mapped_column(default=None)
|
|
open: Mapped[bool] = mapped_column(default=False)
|
|
is_template: Mapped[bool] = mapped_column(default=False)
|
|
rows: Mapped[list["PlaylistRowsTable"]] = relationship(
|
|
"PlaylistRowsTable",
|
|
back_populates="playlist",
|
|
cascade="all, delete-orphan",
|
|
order_by="PlaylistRowsTable.row_number",
|
|
)
|
|
favourite: Mapped[bool] = mapped_column(
|
|
Boolean, nullable=False, index=False, default=False
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Playlists(id={self.id}, name={self.name}, "
|
|
f"is_templatee={self.is_template}, open={self.open}>"
|
|
)
|
|
|
|
|
|
class PlaylistRowsTable(Model):
|
|
__tablename__ = "playlist_rows"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
row_number: Mapped[int] = mapped_column(index=True)
|
|
note: Mapped[str] = mapped_column(
|
|
String(2048), index=False, default="", nullable=False
|
|
)
|
|
playlist_id: Mapped[int] = mapped_column(
|
|
ForeignKey("playlists.id", ondelete="CASCADE"), index=True
|
|
)
|
|
|
|
playlist: Mapped[PlaylistsTable] = relationship(back_populates="rows")
|
|
track_id: Mapped[Optional[int]] = mapped_column(ForeignKey("tracks.id", ondelete="CASCADE"))
|
|
track: Mapped["TracksTable"] = relationship(
|
|
"TracksTable",
|
|
back_populates="playlistrows",
|
|
)
|
|
played: Mapped[bool] = mapped_column(
|
|
Boolean, nullable=False, index=False, default=False
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<PlaylistRows(id={self.id}, playlist_id={self.playlist_id}, "
|
|
f"track_id={self.track_id}, "
|
|
f"note={self.note}, row_number={self.row_number}>"
|
|
)
|
|
|
|
|
|
class QueriesTable(Model):
|
|
__tablename__ = "queries"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
sql: Mapped[str] = mapped_column(
|
|
String(2048), index=False, default="", nullable=False
|
|
)
|
|
favourite: Mapped[bool] = mapped_column(
|
|
Boolean, nullable=False, index=False, default=False
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Queries(id={self.id}, name={self.name}, sql={self.sql}>"
|
|
|
|
|
|
class SettingsTable(Model):
|
|
"""Manage settings"""
|
|
|
|
__tablename__ = "settings"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
name: Mapped[str] = mapped_column(String(64), unique=True)
|
|
f_datetime: Mapped[Optional[dt.datetime]] = mapped_column(default=None)
|
|
f_int: Mapped[Optional[int]] = mapped_column(default=None)
|
|
f_string: Mapped[Optional[str]] = mapped_column(String(128), default=None)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Settings(id={self.id}, name={self.name}, "
|
|
f"f_datetime={self.f_datetime}, f_int={self.f_int}, f_string={self.f_string}>"
|
|
)
|
|
|
|
|
|
class TracksTable(Model):
|
|
__tablename__ = "tracks"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
|
artist: Mapped[str] = mapped_column(String(256), index=True)
|
|
bitrate: Mapped[Optional[int]] = mapped_column(default=None)
|
|
duration: Mapped[int] = mapped_column(index=True)
|
|
fade_at: Mapped[int] = mapped_column(index=False)
|
|
intro: Mapped[Optional[int]] = mapped_column(default=None)
|
|
path: Mapped[str] = mapped_column(String(2048), index=False, unique=True)
|
|
silence_at: Mapped[int] = mapped_column(index=False)
|
|
start_gap: Mapped[int] = mapped_column(index=False)
|
|
title: Mapped[str] = mapped_column(String(256), index=True)
|
|
|
|
playlistrows: Mapped[list[PlaylistRowsTable]] = relationship(
|
|
"PlaylistRowsTable",
|
|
back_populates="track",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
playlists = association_proxy("playlistrows", "playlist")
|
|
playdates: Mapped[list[PlaydatesTable]] = relationship(
|
|
"PlaydatesTable",
|
|
back_populates="track",
|
|
cascade="all, delete-orphan",
|
|
lazy="joined",
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Track(id={self.id}, title={self.title}, "
|
|
f"artist={self.artist}, path={self.path}>"
|
|
)
|