db: Give Decades knowledge about their Tracks & Properties
I expand on the decades_view to include additional playlist properties, and configure the default sort order to sort by year first. I then set up the decade_tracks_view to make it easy to select tracks that belong to a specific decade. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
0524085602
commit
99eb4abee3
|
@ -5,6 +5,7 @@ from gi.repository import GObject
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
from .years import Year
|
from .years import Year
|
||||||
from . import playlist
|
from . import playlist
|
||||||
|
from . import tracks
|
||||||
|
|
||||||
|
|
||||||
class Decade(playlist.Playlist):
|
class Decade(playlist.Playlist):
|
||||||
|
@ -34,6 +35,15 @@ class Decade(playlist.Playlist):
|
||||||
class Table(playlist.Table):
|
class Table(playlist.Table):
|
||||||
"""Our Decade Table."""
|
"""Our Decade Table."""
|
||||||
|
|
||||||
|
def __init__(self, sql: GObject.TYPE_PYOBJECT, **kwargs):
|
||||||
|
"""Initialize the Decade table."""
|
||||||
|
super().__init__(sql=sql, autodelete=True,
|
||||||
|
system_tracks=False, **kwargs)
|
||||||
|
|
||||||
|
def do_add_track(self, decade: Decade, track: tracks.Track) -> bool:
|
||||||
|
"""Verify adding a Track to the Decade playlist."""
|
||||||
|
return (track.year // 10 * 10) == decade.decade
|
||||||
|
|
||||||
def do_construct(self, **kwargs) -> Decade:
|
def do_construct(self, **kwargs) -> Decade:
|
||||||
"""Construct a new Decade playlist."""
|
"""Construct a new Decade playlist."""
|
||||||
return Decade(**kwargs)
|
return Decade(**kwargs)
|
||||||
|
@ -42,6 +52,10 @@ class Table(playlist.Table):
|
||||||
"""Get the sort key for the requested decade."""
|
"""Get the sort key for the requested decade."""
|
||||||
return decade.decade
|
return decade.decade
|
||||||
|
|
||||||
|
def do_remove_track(self, decade: Decade, track: tracks.Track) -> bool:
|
||||||
|
"""Verify removing a Track from the Decade playlist."""
|
||||||
|
return True
|
||||||
|
|
||||||
def do_sql_delete(self, decade: Decade) -> sqlite3.Cursor:
|
def do_sql_delete(self, decade: Decade) -> sqlite3.Cursor:
|
||||||
"""Delete a decade."""
|
"""Delete a decade."""
|
||||||
for year in decade.get_years():
|
for year in decade.get_years():
|
||||||
|
@ -71,6 +85,11 @@ class Table(playlist.Table):
|
||||||
return self.sql("SELECT decade FROM decades WHERE decade=?",
|
return self.sql("SELECT decade FROM decades WHERE decade=?",
|
||||||
year // 10 * 10)
|
year // 10 * 10)
|
||||||
|
|
||||||
|
def do_sql_select_trackids(self, decade: Decade) -> sqlite3.Cursor:
|
||||||
|
"""Load a Decade's Tracks from the database."""
|
||||||
|
return self.sql("""SELECT trackid FROM decade_tracks_view
|
||||||
|
WHERE decade=?""", decade.decade)
|
||||||
|
|
||||||
def get_years(self, decade: Decade) -> list[Year]:
|
def get_years(self, decade: Decade) -> list[Year]:
|
||||||
"""Get the list of years for this decade."""
|
"""Get the list of years for this decade."""
|
||||||
rows = self.sql("SELECT year FROM years WHERE (year / 10 * 10)=?",
|
rows = self.sql("SELECT year FROM years WHERE (year / 10 * 10)=?",
|
||||||
|
|
|
@ -317,13 +317,15 @@ CREATE TABLE decades (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE VIEW decades_view AS
|
CREATE VIEW decades_view AS
|
||||||
SELECT decade, propertyid, FORMAT("The %ds", decade) as name, active
|
SELECT decade, propertyid, FORMAT("The %ds", decade) as name,
|
||||||
|
active, loop, shuffle, sort_order, current_trackid
|
||||||
FROM decades
|
FROM decades
|
||||||
JOIN playlist_properties USING (propertyid);
|
JOIN playlist_properties USING (propertyid);
|
||||||
|
|
||||||
CREATE TRIGGER decades_insert_trigger AFTER INSERT ON decades
|
CREATE TRIGGER decades_insert_trigger AFTER INSERT ON decades
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO playlist_properties (active) VALUES (False);
|
INSERT INTO playlist_properties (active, sort_order)
|
||||||
|
VALUES (False, "release, albumartist, album, mediumno, number");
|
||||||
UPDATE decades SET propertyid = last_insert_rowid()
|
UPDATE decades SET propertyid = last_insert_rowid()
|
||||||
WHERE decade = NEW.decade;
|
WHERE decade = NEW.decade;
|
||||||
END;
|
END;
|
||||||
|
@ -555,6 +557,13 @@ CREATE VIEW genre_tracks_view AS
|
||||||
JOIN libraries USING (libraryid)
|
JOIN libraries USING (libraryid)
|
||||||
WHERE libraries.deleting = False;
|
WHERE libraries.deleting = False;
|
||||||
|
|
||||||
|
CREATE VIEW decade_tracks_view AS
|
||||||
|
SELECT tracks.trackid, decades.decade
|
||||||
|
FROM tracks
|
||||||
|
JOIN decades ON (tracks.year / 10 * 10) = decades.decade
|
||||||
|
JOIN libraries USING (libraryid)
|
||||||
|
WHERE libraries.deleting = False;
|
||||||
|
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* *
|
* *
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2022 (c) Anna Schumaker
|
# Copyright 2022 (c) Anna Schumaker
|
||||||
"""Tests our decade Gio.ListModel."""
|
"""Tests our decade Gio.ListModel."""
|
||||||
|
import pathlib
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
import emmental.db
|
import emmental.db
|
||||||
import tests.util
|
import tests.util
|
||||||
|
@ -57,10 +58,27 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
self.table = self.sql.decades
|
self.table = self.sql.decades
|
||||||
self.sql.years.load()
|
self.sql.years.load()
|
||||||
|
|
||||||
|
self.album = self.sql.albums.create("Test Album", "Test Artist", "123")
|
||||||
|
self.medium = self.sql.media.create(self.album, "", number=1)
|
||||||
|
self.library = self.sql.libraries.create(pathlib.Path("/a/b"))
|
||||||
|
self.year = self.sql.years.create(2023)
|
||||||
|
self.track = self.sql.tracks.create(self.library,
|
||||||
|
pathlib.Path("/a/b/c/1.ogg"),
|
||||||
|
self.medium, self.year)
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
"""Test that the decade table is configured correctly."""
|
"""Test that the decade table is configured correctly."""
|
||||||
self.assertIsInstance(self.table, emmental.db.playlist.Table)
|
self.assertIsInstance(self.table, emmental.db.playlist.Table)
|
||||||
self.assertEqual(len(self.table), 0)
|
self.assertEqual(len(self.table), 0)
|
||||||
|
self.assertTrue(self.table.autodelete)
|
||||||
|
self.assertFalse(self.table.system_tracks)
|
||||||
|
|
||||||
|
def test_add_track(self):
|
||||||
|
"""Test adding a Track to a Decade playlist."""
|
||||||
|
decade = self.table.create(2020)
|
||||||
|
self.assertTrue(self.table.add_track(decade, self.track))
|
||||||
|
decade2 = self.table.create(1990)
|
||||||
|
self.assertFalse(self.table.add_track(decade2, self.track))
|
||||||
|
|
||||||
def test_construct(self):
|
def test_construct(self):
|
||||||
"""Test constructing a decade playlist."""
|
"""Test constructing a decade playlist."""
|
||||||
|
@ -72,6 +90,7 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
self.assertEqual(decade.decade, 1980)
|
self.assertEqual(decade.decade, 1980)
|
||||||
self.assertEqual(decade.name, "The 1980s")
|
self.assertEqual(decade.name, "The 1980s")
|
||||||
self.assertFalse(decade.active)
|
self.assertFalse(decade.active)
|
||||||
|
self.assertFalse(decade.tracks_movable)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
"""Test creating a decade playlist."""
|
"""Test creating a decade playlist."""
|
||||||
|
@ -79,6 +98,8 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
self.assertIsInstance(decade, emmental.db.decades.Decade)
|
self.assertIsInstance(decade, emmental.db.decades.Decade)
|
||||||
self.assertEqual(decade.decade, 1980)
|
self.assertEqual(decade.decade, 1980)
|
||||||
self.assertEqual(decade.name, "The 1980s")
|
self.assertEqual(decade.name, "The 1980s")
|
||||||
|
self.assertEqual(decade.sort_order,
|
||||||
|
"release, albumartist, album, mediumno, number")
|
||||||
|
|
||||||
cur = self.sql("SELECT COUNT(decade) FROM decades")
|
cur = self.sql("SELECT COUNT(decade) FROM decades")
|
||||||
self.assertEqual(cur.fetchone()["COUNT(decade)"], 1)
|
self.assertEqual(cur.fetchone()["COUNT(decade)"], 1)
|
||||||
|
@ -91,6 +112,7 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
"""Test deleting a decade playlist."""
|
"""Test deleting a decade playlist."""
|
||||||
|
self.year.delete()
|
||||||
decade = self.table.create(1980)
|
decade = self.table.create(1980)
|
||||||
self.sql.years.create(1988)
|
self.sql.years.create(1988)
|
||||||
self.assertTrue(decade.delete())
|
self.assertTrue(decade.delete())
|
||||||
|
@ -131,6 +153,15 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
decade = self.table.create(1980)
|
decade = self.table.create(1980)
|
||||||
self.assertEqual(self.table.get_sort_key(decade), 1980)
|
self.assertEqual(self.table.get_sort_key(decade), 1980)
|
||||||
|
|
||||||
|
def test_get_trackids(self):
|
||||||
|
"""Test loading decade tracks from the database."""
|
||||||
|
decade = self.table.create(2020)
|
||||||
|
track2 = self.sql.tracks.create(self.library,
|
||||||
|
pathlib.Path("/a/b/c/2.ogg"),
|
||||||
|
self.medium, self.year)
|
||||||
|
self.assertSetEqual(self.table.get_trackids(decade),
|
||||||
|
{self.track.trackid, track2.trackid})
|
||||||
|
|
||||||
def test_load(self):
|
def test_load(self):
|
||||||
"""Load the decade table from the database."""
|
"""Load the decade table from the database."""
|
||||||
self.table.create(1980)
|
self.table.create(1980)
|
||||||
|
@ -154,14 +185,28 @@ class TestDecadeTable(tests.util.TestCase):
|
||||||
self.assertEqual(self.table.lookup(1988), decade)
|
self.assertEqual(self.table.lookup(1988), decade)
|
||||||
self.assertIsNone(self.table.lookup(1990))
|
self.assertIsNone(self.table.lookup(1990))
|
||||||
|
|
||||||
|
def test_remove_track(self):
|
||||||
|
"""Test removing a Track from the Decade."""
|
||||||
|
decade = self.table.create(2023)
|
||||||
|
self.assertTrue(self.table.remove_track(decade, unittest.mock.Mock()))
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
"""Test updating decade attributes."""
|
"""Test updating decade attributes."""
|
||||||
decade = self.table.create(1980)
|
decade = self.table.create(1980)
|
||||||
decade.active = True
|
decade.active = True
|
||||||
|
decade.loop = "Track"
|
||||||
|
decade.shuffle = True
|
||||||
|
decade.sort_order = "trackid"
|
||||||
|
|
||||||
row = self.sql("""SELECT active FROM playlist_properties
|
row = self.sql("""SELECT active, loop, shuffle,
|
||||||
WHERE propertyid=?""", decade.propertyid).fetchone()
|
sort_order, current_trackid
|
||||||
self.assertEqual(row["active"], True)
|
FROM decades_view WHERE decade=?""",
|
||||||
|
decade.decade).fetchone()
|
||||||
|
self.assertTrue(row["active"])
|
||||||
|
self.assertEqual(row["loop"], "Track")
|
||||||
|
self.assertTrue(row["shuffle"])
|
||||||
|
self.assertEqual(row["sort_order"], "trackid")
|
||||||
|
self.assertIsNone(row["current_trackid"])
|
||||||
|
|
||||||
def test_get_years(self):
|
def test_get_years(self):
|
||||||
"""Test getting the list of years for a decade."""
|
"""Test getting the list of years for a decade."""
|
||||||
|
|
Loading…
Reference in New Issue