diff --git a/emmental/db/emmental.sql b/emmental/db/emmental.sql index 50d5873..caf6347 100644 --- a/emmental/db/emmental.sql +++ b/emmental/db/emmental.sql @@ -350,13 +350,15 @@ CREATE TABLE years ( ); CREATE VIEW years_view AS - SELECT year, propertyid, FORMAT("%s", year) as name, active + SELECT year, propertyid, FORMAT("%s", year) as name, + active, loop, shuffle, sort_order, current_trackid FROM years JOIN playlist_properties USING (propertyid); CREATE TRIGGER years_insert_trigger AFTER INSERT ON years BEGIN - INSERT INTO playlist_properties (active) VALUES (False); + INSERT INTO playlist_properties (active, sort_order) + VALUES (False, "release, albumartist, album, mediumno, number"); UPDATE years SET propertyid = last_insert_rowid() WHERE year = NEW.year; END; @@ -564,6 +566,13 @@ CREATE VIEW decade_tracks_view AS JOIN libraries USING (libraryid) WHERE libraries.deleting = False; +CREATE VIEW year_tracks_view AS + SELECT tracks.trackid, years.year + FROM tracks + JOIN years USING (year) + JOIN libraries USING (libraryid) + WHERE libraries.deleting = False; + /**************************************************** * * diff --git a/emmental/db/years.py b/emmental/db/years.py index d64e6ca..b65ebf9 100644 --- a/emmental/db/years.py +++ b/emmental/db/years.py @@ -3,6 +3,7 @@ import sqlite3 from gi.repository import GObject from . import playlist +from . import tracks class Year(playlist.Playlist): @@ -24,6 +25,15 @@ class Year(playlist.Playlist): class Table(playlist.Table): """Our Year Table.""" + def __init__(self, sql: GObject.TYPE_PYOBJECT, **kwargs): + """Initialize the Years table.""" + super().__init__(sql=sql, autodelete=True, + system_tracks=False, **kwargs) + + def do_add_track(self, year: Year, track: tracks.Track) -> bool: + """Verify adding a Track to the Year playlist.""" + return track.year == year.year + def do_construct(self, **kwargs) -> Year: """Construct a new Year playlist.""" return Year(**kwargs) @@ -32,6 +42,10 @@ class Table(playlist.Table): """Get the sort key for a specific year.""" return year.year + def do_remove_track(self, year: Year, track: tracks.Track) -> bool: + """Verify removing a Track from the Year playlist.""" + return True + def do_sql_delete(self, year: Year) -> sqlite3.Cursor: """Delete a year.""" return self.sql("DELETE FROM years WHERE year=?", year.year) @@ -52,3 +66,8 @@ class Table(playlist.Table): def do_sql_select_one(self, year: int) -> sqlite3.Cursor: """Look up a year.""" return self.sql("SELECT year FROM years WHERE year=?", year) + + def do_sql_select_trackids(self, year: Year) -> sqlite3.Cursor: + """Load a Year's Tracks from the database.""" + return self.sql("""SELECT trackid FROM year_tracks_view + WHERE year=?""", year.year) diff --git a/tests/db/test_years.py b/tests/db/test_years.py index cfbac6a..f876fa9 100644 --- a/tests/db/test_years.py +++ b/tests/db/test_years.py @@ -1,5 +1,7 @@ # Copyright 2022 (c) Anna Schumaker. """Tests our year Gio.ListModel.""" +import pathlib +import unittest import emmental.db import tests.util @@ -38,10 +40,27 @@ class TestYearTable(tests.util.TestCase): super().setUp() self.table = self.sql.years + 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")) + def test_init(self): """Test that the year model is configured correctly.""" self.assertIsInstance(self.table, emmental.db.playlist.Table) 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 Year playlist.""" + year = self.sql.years.create(2023) + track = self.sql.tracks.create(self.library, + pathlib.Path("/a/b/c/1.ogg"), + self.medium, year) + + self.assertTrue(self.table.add_track(year, track)) + year2 = self.sql.years.create(2013) + self.assertFalse(self.table.add_track(year2, track)) def test_construct(self): """Test constructing a year playlist.""" @@ -52,6 +71,7 @@ class TestYearTable(tests.util.TestCase): self.assertEqual(year.year, 1988) self.assertEqual(year.name, "1988") self.assertFalse(year.active) + self.assertFalse(year.tracks_movable) def test_create(self): """Test creating a year playlist.""" @@ -59,6 +79,8 @@ class TestYearTable(tests.util.TestCase): self.assertIsInstance(year, emmental.db.years.Year) self.assertEqual(year.year, 1988) self.assertEqual(year.name, "1988") + self.assertEqual(year.sort_order, + "release, albumartist, album, mediumno, number") cur = self.sql("SELECT COUNT(year) FROM years") self.assertEqual(cur.fetchone()["COUNT(year)"], 1) @@ -100,6 +122,18 @@ class TestYearTable(tests.util.TestCase): year = self.table.create(1988) self.assertEqual(self.table.get_sort_key(year), 1988) + def test_get_trackids(self): + """Test loading year tracks from the database.""" + year = self.sql.years.create(2023) + track1 = self.sql.tracks.create(self.library, + pathlib.Path("/a/b/c/1.ogg"), + self.medium, year) + track2 = self.sql.tracks.create(self.library, + pathlib.Path("/a/b/c/2.ogg"), + self.medium, year) + self.assertSetEqual(self.table.get_trackids(year), + {track1.trackid, track2.trackid}) + def test_load(self): """Test loading the year table from the database.""" self.table.create(1985) @@ -123,11 +157,25 @@ class TestYearTable(tests.util.TestCase): self.assertEqual(self.table.lookup(1988), year) self.assertIsNone(self.table.lookup(1985)) + def test_remove_track(self): + """Test removing a Track from the Year.""" + year = self.table.create(2023) + self.assertTrue(self.table.remove_track(year, unittest.mock.Mock())) + def test_update(self): """Test updating year attributes.""" year = self.table.create(1980) year.active = True + year.loop = "Track" + year.shuffle = True + year.sort_order = "trackid" - row = self.sql("""SELECT active FROM playlist_properties - WHERE propertyid=?""", year.propertyid).fetchone() - self.assertEqual(row["active"], True) + row = self.sql("""SELECT active, loop, shuffle, + sort_order, current_trackid + FROM years_view WHERE year=?""", + year.year).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"])