db: Give playlists an add_track() function

And emit a "track-added" signal to notify higher layers

Implements: Issue #15 (Convert Playlists into Gio.ListModels)
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2021-10-18 17:25:20 -04:00
parent 32dcd83865
commit 9b4153737b
10 changed files with 105 additions and 14 deletions

View File

@ -45,6 +45,9 @@ class Playlist(GObject.GObject):
f"WHERE trackid=?", [ track.rowid ])
return cur.fetchone()[1] - 1
def add_track(self, track):
self.emit("track-added", track)
@GObject.Property
def name(self): raise NotImplementedError
@ -60,6 +63,9 @@ class Playlist(GObject.GObject):
@GObject.Property
def rowkey(self): return self._rowkey
@GObject.Signal(arg_types=(GObject.TYPE_PYOBJECT,))
def track_added(self, track): pass
class MappedPlaylist(Playlist):
def __init__(self, row, icon_name, map_table):
@ -70,9 +76,12 @@ class MappedPlaylist(Playlist):
def map_table(self): return self._map_table
def add_track(self, track):
return sql.execute(f"INSERT OR IGNORE INTO {self.map_table} "
res = sql.execute(f"INSERT OR IGNORE INTO {self.map_table} "
f"({self.rowkey}, trackid) VALUES (?, ?)",
[ self.rowid, track.rowid ]).rowcount == 1
if res:
super().add_track(track)
return res
def clear(self):
sql.execute(f"DELETE FROM {self.map_table} "
@ -98,7 +107,7 @@ class MappedPlaylist(Playlist):
def get_track_index(self, track):
order = ', '.join(self.plist_state.sort)
cur = sql.execute(f"SELECT * FROM (SELECT trackid,{self._rowkey},ROW_NUMBER() "
row = sql.execute(f"SELECT * FROM (SELECT trackid,{self._rowkey},ROW_NUMBER() "
f"OVER (ORDER BY {order}) "
f"FROM tracks "
f"INNER JOIN {self.map_table} USING (trackid) "
@ -107,8 +116,8 @@ class MappedPlaylist(Playlist):
f"INNER JOIN discs USING(discid) "
f"INNER JOIN years USING(yearid)) "
f"WHERE {self._rowkey}=? AND trackid=?",
[ self.rowid, track.rowid ])
return cur.fetchone()[2] - 1
[ self.rowid, track.rowid ]).fetchone()
return row[2] - 1 if row else None
def remove_track(self, track):
return sql.execute(f"DELETE FROM {self.map_table} "

View File

@ -5,6 +5,9 @@ import unittest
from gi.repository import GObject
class TestAlbum(unittest.TestCase):
def track_added(self, album, added):
self.added = added
def setUp(self):
db.reset()
@ -28,14 +31,17 @@ class TestAlbum(unittest.TestCase):
disc = album.find_disc(1, None)
self.assertIsInstance(disc, db.disc.Disc)
def test_n_tracks(self):
def test_tracks(self):
artist = db.artist.Table.find("Test Artist", "Test Sort")
album = artist.find_album("Test Album")
album.connect("track-added", self.track_added)
self.assertEqual(album.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(album.get_n_tracks(), 1)
self.assertEqual(album.get_track(0), track)
self.assertEqual(album.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestAlbumTable(unittest.TestCase):

View File

@ -5,6 +5,9 @@ import unittest
from gi.repository import GObject
class TestArtist(unittest.TestCase):
def track_added(self, artist, added):
self.added = added
def setUp(self):
db.reset()
@ -25,13 +28,16 @@ class TestArtist(unittest.TestCase):
album = artist.find_album("Test Album")
self.assertIsInstance(album, db.album.Album)
def test_n_tracks(self):
def test_tracks(self):
artist = db.artist.Table.find("Test Artist", "Test Sort")
artist.connect("track-added", self.track_added)
self.assertEqual(artist.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(artist.get_n_tracks(), 1)
self.assertEqual(artist.get_track(0), track)
self.assertEqual(artist.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestArtistTable(unittest.TestCase):

View File

@ -8,6 +8,9 @@ class TestDecade(unittest.TestCase):
def children_changed(self, decade, pos, rm, add):
self.changed = (pos, rm, add)
def track_added(self, decade, added):
self.added = added
def setUp(self):
db.reset()
@ -36,13 +39,16 @@ class TestDecade(unittest.TestCase):
self.assertIsInstance(year, db.year.Year)
self.assertEqual(self.changed, (0, 0, 1))
def test_n_tracks(self):
def test_tracks(self):
decade = db.decade.Table.insert(2020)
decade.connect("track-added", self.track_added)
self.assertEqual(decade.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(decade.get_n_tracks(), 1)
self.assertEqual(decade.get_track(0), track)
self.assertEqual(decade.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestDecadeTable(unittest.TestCase):

View File

@ -5,6 +5,9 @@ import unittest
from gi.repository import GObject
class TestDisc(unittest.TestCase):
def track_added(self, disc, added):
self.added = added
def setUp(self):
db.reset()
@ -43,13 +46,16 @@ class TestDisc(unittest.TestCase):
self.assertEqual(disc.get_property("subtitle"), "")
self.assertEqual(disc.get_property("name"), "Disc 1")
def test_n_tracks(self):
def test_tracks(self):
disc = self.make_disc("Test Artist", "Test Album", 1, "Test Subtitle")
disc.connect("track-added", self.track_added)
self.assertEqual(disc.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(disc.get_n_tracks(), 1)
self.assertEqual(disc.get_track(0), track)
self.assertEqual(disc.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestDiscTable(unittest.TestCase):

View File

@ -7,6 +7,9 @@ from . import sql
class TestGenre(unittest.TestCase):
def track_added(self, genre, added):
self.added = added
def setUp(self):
db.reset()
@ -28,13 +31,15 @@ class TestGenre(unittest.TestCase):
def test_add_remove_track(self):
genre = db.genre.Table.find("Test Genre")
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
genre.connect("track-added", self.track_added)
self.assertEqual(genre.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertTrue(genre.add_track(track))
self.assertEqual(genre.get_n_tracks(), 1)
self.assertEqual(genre.get_track(0), track)
self.assertEqual(genre.get_track_index(track), 0)
self.assertEqual(self.added, track)
self.assertTrue(genre.remove_track(track))
self.assertFalse(genre.remove_track(track))

View File

@ -7,6 +7,9 @@ from gi.repository import GObject
class TestLibrary(unittest.TestCase):
def track_added(self, library, added):
self.added = added
def setUp(self):
db.reset()
@ -34,13 +37,16 @@ class TestLibrary(unittest.TestCase):
library.enabled = False
self.assertFalse(library._enabled)
def test_n_tracks(self):
def test_tracks(self):
library = db.library.Table.insert(pathlib.Path("/a/b/c"))
library.connect("track-added", self.track_added)
self.assertEqual(library.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(library.get_n_tracks(), 1)
self.assertEqual(library.get_track(0), track)
self.assertEqual(library.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestLibraryTable(unittest.TestCase):

View File

@ -6,6 +6,9 @@ from gi.repository import GObject
from . import sql
class TestCollection(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -16,18 +19,25 @@ class TestCollection(unittest.TestCase):
self.assertEqual(collection.icon_name, "media-playback-start")
self.assertTrue(collection.plist_state.loop)
def test_n_tracks(self):
def test_tracks(self):
collection = db.user.Table.find("Collection")
collection.connect("track-added", self.track_added)
self.assertEqual(collection.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(collection.get_n_tracks(), 1)
self.assertEqual(collection.get_track(0), track)
self.assertEqual(collection.get_track_index(track), 0)
self.assertEqual(self.added, track)
track.library.enabled = False
self.assertEqual(collection.get_n_tracks(), 0)
class TestFavorites(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -42,6 +52,7 @@ class TestFavorites(unittest.TestCase):
def test_add_remove_track(self):
favorites = db.user.Table.find("Favorites")
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
favorites.connect("track-added", self.track_added)
self.assertEqual(favorites.get_n_tracks(), 0)
self.assertTrue(favorites.add_track(track))
@ -49,6 +60,7 @@ class TestFavorites(unittest.TestCase):
self.assertEqual(favorites.get_n_tracks(), 1)
self.assertEqual(favorites.get_track(0), track)
self.assertEqual(favorites.get_track_index(track), 0)
self.assertEqual(self.added, track)
self.assertTrue(favorites.remove_track(track))
self.assertFalse(favorites.remove_track(track))
@ -56,6 +68,9 @@ class TestFavorites(unittest.TestCase):
class TestNewTracks(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -69,12 +84,14 @@ class TestNewTracks(unittest.TestCase):
def test_add_remove_track(self):
new = db.user.Table.find("New Tracks")
new.connect("track-added", self.track_added)
self.assertEqual(new.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(new.get_n_tracks(), 1)
self.assertEqual(new.get_track(0), track)
self.assertEqual(new.get_track_index(track), 0)
self.added = track
self.assertTrue(new.remove_track(track))
self.assertFalse(new.remove_track(track))
@ -82,6 +99,9 @@ class TestNewTracks(unittest.TestCase):
class TestPrevious(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -98,12 +118,14 @@ class TestPrevious(unittest.TestCase):
previous = db.user.Table.find("Previous")
track1 = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
track2 = db.make_fake_track(2, 2, "Test Track 2", "/a/b/c/2.ogg")
previous.connect("track-added", self.track_added)
self.assertEqual(previous.get_n_tracks(), 0)
self.assertTrue(previous.add_track(track1))
self.assertEqual(previous.get_n_tracks(), 1)
self.assertEqual(previous.get_track(0), track1)
self.assertEqual(previous.get_track_index(track1), 0)
self.assertEqual(self.added, track1)
self.assertTrue(previous.add_track(track2))
self.assertEqual(previous.get_n_tracks(), 2)
@ -111,6 +133,7 @@ class TestPrevious(unittest.TestCase):
self.assertEqual(previous.get_track(1), track1)
self.assertEqual(previous.get_track_index(track2), 0)
self.assertEqual(previous.get_track_index(track1), 1)
self.assertEqual(self.added, track2)
self.assertTrue(previous.add_track(track1))
self.assertEqual(previous.get_n_tracks(), 2)
@ -118,6 +141,7 @@ class TestPrevious(unittest.TestCase):
self.assertEqual(previous.get_track(1), track2)
self.assertEqual(previous.get_track_index(track1), 0)
self.assertEqual(previous.get_track_index(track2), 1)
self.assertEqual(self.added, track1)
self.assertTrue(previous.remove_track(track1))
self.assertFalse(previous.remove_track(track1))
@ -126,6 +150,9 @@ class TestPrevious(unittest.TestCase):
class TestQueuedTracks(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -141,6 +168,7 @@ class TestQueuedTracks(unittest.TestCase):
def test_add_remove_track(self):
queued = db.user.Table.find("Queued Tracks")
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
queued.connect("track-added", self.track_added)
self.assertEqual(queued.get_n_tracks(), 0)
self.assertTrue(queued.add_track(track))
@ -148,6 +176,7 @@ class TestQueuedTracks(unittest.TestCase):
self.assertEqual(queued.get_n_tracks(), 1)
self.assertEqual(queued.get_track(0), track)
self.assertEqual(queued.get_track_index(track), 0)
self.assertEqual(self.added, track)
self.assertTrue(queued.remove_track(track))
self.assertFalse(queued.remove_track(track))
@ -155,6 +184,9 @@ class TestQueuedTracks(unittest.TestCase):
class TestUserPlaylist(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self): db.reset()
def test_init(self):
@ -177,6 +209,7 @@ class TestUserPlaylist(unittest.TestCase):
def test_add_remove_track(self):
plist = db.user.Table.find("Test Playlist")
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
plist.connect("track-added", self.track_added)
self.assertEqual(plist.get_n_tracks(), 0)
self.assertTrue(plist.add_track(track))
@ -184,6 +217,7 @@ class TestUserPlaylist(unittest.TestCase):
self.assertEqual(plist.get_n_tracks(), 1)
self.assertEqual(plist.get_track(0), track)
self.assertEqual(plist.get_track_index(track), 0)
self.assertEqual(self.added, track)
self.assertTrue(plist.remove_track(track))
self.assertFalse(plist.remove_track(track))

View File

@ -5,6 +5,9 @@ import unittest
from gi.repository import GObject
class TestYear(unittest.TestCase):
def track_added(self, plist, added):
self.added = added
def setUp(self):
db.reset()
@ -22,14 +25,17 @@ class TestYear(unittest.TestCase):
year.delete()
self.assertIsNone(db.year.Table.lookup(2021))
def test_n_tracks(self):
def test_tracks(self):
decade = db.decade.Table.find(2020)
year = decade.find_year(2021)
year.connect("track-added", self.track_added)
self.assertEqual(year.get_n_tracks(), 0)
track = db.make_fake_track(1, 1, "Test Track", "/a/b/c/1.ogg")
self.assertEqual(year.get_n_tracks(), 1)
self.assertEqual(year.get_track(0), track)
self.assertEqual(year.get_track_index(track), 0)
self.assertEqual(self.added, track)
class TestYearTable(unittest.TestCase):

View File

@ -149,9 +149,16 @@ class TrackTable(table.Table):
def find(self, *args):
raise NotImplementedError
def insert(self, *args):
track = super().insert(*args)
def insert(self, library, artist, album, disc, decade,
year, number, length, title, path):
track = super().insert(library, artist, album, disc, decade,
year, number, length, title, path)
user.Table.find("New Tracks").add_track(track)
for plist in [ artist, album, disc, decade, year, library,
user.Table.find("Collection") ]:
plist.add_track(track)
return track