tracklist: Create a TrackView
The TrackView sets up a scrollable Gtk.ColumnView inside a nice looking frame. It also creates a FilterListModel for filtering tracks in a separate layer from the Playlist so we don't affect choosing the next track. Finally, I add the TrackView to the TrackList Card. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
2c2462c3d6
commit
999a3eb523
|
@ -5,6 +5,7 @@ from gi.repository import Gtk
|
|||
from .. import db
|
||||
from .. import entry
|
||||
from .. import playlist
|
||||
from . import trackview
|
||||
|
||||
|
||||
class Card(Gtk.Box):
|
||||
|
@ -21,9 +22,14 @@ class Card(Gtk.Box):
|
|||
margin_end=6)
|
||||
self._filter = entry.Filter("tracks", hexpand=True,
|
||||
margin_start=100, margin_end=100)
|
||||
self._trackview = trackview.TrackView(sql, margin_start=6,
|
||||
margin_end=6)
|
||||
|
||||
self._top_box.set_center_widget(self._filter)
|
||||
self.append(self._top_box)
|
||||
self.append(self._trackview)
|
||||
|
||||
self.bind_property("playlist", self._trackview, "playlist")
|
||||
|
||||
self._filter.connect("search-changed", self.__search_changed)
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2022 (c) Anna Schumaker.
|
||||
"""A Gtk.ColumnView for displaying Tracks."""
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from .. import db
|
||||
from .. import playlist
|
||||
|
||||
|
||||
class TrackView(Gtk.Frame):
|
||||
"""A Gtk.ColumnView that has been configured to show Tracks."""
|
||||
|
||||
playlist = GObject.Property(type=playlist.playlist.Playlist)
|
||||
n_tracks = GObject.Property(type=int)
|
||||
runtime = GObject.Property(type=float)
|
||||
|
||||
def __init__(self, sql: db.Connection, **kwargs):
|
||||
"""Initialize a TrackView."""
|
||||
super().__init__(**kwargs)
|
||||
self._filtermodel = Gtk.FilterListModel(filter=sql.tracks.get_filter(),
|
||||
incremental=True)
|
||||
self._selection = Gtk.MultiSelection(model=self._filtermodel)
|
||||
self._columnview = Gtk.ColumnView(hexpand=True, vexpand=True,
|
||||
show_row_separators=True,
|
||||
enable_rubberband=True,
|
||||
model=self._selection)
|
||||
self._scrollwin = Gtk.ScrolledWindow(child=self._columnview)
|
||||
|
||||
self.bind_property("playlist", self._filtermodel, "model")
|
||||
self._selection.bind_property("n-items", self, "n-tracks")
|
||||
|
||||
self._selection.connect("items-changed", self.__runtime_changed)
|
||||
self._columnview.add_css_class("emmental-track-list")
|
||||
|
||||
self.set_child(self._scrollwin)
|
||||
|
||||
def __runtime_changed(self, selection: Gtk.MultiSelection,
|
||||
position: int, removed: int, added: int) -> None:
|
||||
self.runtime = sum(t.length for t in self._selection)
|
|
@ -56,9 +56,20 @@ class TestTracklist(tests.util.TestCase):
|
|||
self.tracklist._filter.emit("search-changed")
|
||||
mock_filter.assert_called_with("*test text*")
|
||||
|
||||
def test_trackview(self):
|
||||
"""Test the Trackview widget."""
|
||||
self.assertIsInstance(self.tracklist._trackview,
|
||||
emmental.tracklist.trackview.TrackView)
|
||||
self.assertEqual(self.tracklist._top_box.get_next_sibling(),
|
||||
self.tracklist._trackview)
|
||||
|
||||
self.assertEqual(self.tracklist._trackview.get_margin_start(), 6)
|
||||
self.assertEqual(self.tracklist._trackview.get_margin_end(), 6)
|
||||
|
||||
def test_playlist(self):
|
||||
"""Test the playlist property."""
|
||||
self.assertIsNone(self.tracklist.playlist)
|
||||
|
||||
self.tracklist.playlist = self.playlist
|
||||
self.assertEqual(self.tracklist.playlist, self.playlist)
|
||||
self.assertEqual(self.tracklist._trackview.playlist, self.playlist)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright 2022 (c) Anna Schumaker.
|
||||
"""Tests our Track ColumnView."""
|
||||
import pathlib
|
||||
import emmental.tracklist.trackview
|
||||
import tests.util
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
class TestTrackView(tests.util.TestCase):
|
||||
"""Tests the TrackView widget."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up common variables."""
|
||||
super().setUp()
|
||||
self.db_plist = self.sql.playlists.create("Test Playlist")
|
||||
self.playlist = emmental.playlist.playlist.Playlist(self.sql,
|
||||
self.db_plist)
|
||||
self.trackview = emmental.tracklist.trackview.TrackView(self.sql)
|
||||
|
||||
self.library = self.sql.libraries.create(pathlib.Path("/a/b/"))
|
||||
self.album = self.sql.albums.create("Test Album", "Artist", "2023")
|
||||
self.medium = self.sql.media.create(self.album, "", number=1)
|
||||
self.year = self.sql.years.create(2023)
|
||||
self.track = self.sql.tracks.create(self.library,
|
||||
pathlib.Path("/a/b/1.ogg"),
|
||||
self.medium, self.year, length=10)
|
||||
|
||||
def test_init(self):
|
||||
"""Test that the TrackView is initialized properly."""
|
||||
self.assertIsInstance(self.trackview, Gtk.Frame)
|
||||
self.assertIsInstance(self.trackview._scrollwin, Gtk.ScrolledWindow)
|
||||
|
||||
self.assertEqual(self.trackview.get_child(), self.trackview._scrollwin)
|
||||
self.assertEqual(self.trackview._scrollwin.get_child(),
|
||||
self.trackview._columnview)
|
||||
|
||||
def test_list_models(self):
|
||||
"""Test our filter and selection list models."""
|
||||
self.assertIsInstance(self.trackview._filtermodel, Gtk.FilterListModel)
|
||||
self.assertIsInstance(self.trackview._selection, Gtk.MultiSelection)
|
||||
|
||||
self.assertEqual(self.trackview._filtermodel.get_filter(),
|
||||
self.sql.tracks.get_filter())
|
||||
self.assertTrue(self.trackview._filtermodel.get_incremental())
|
||||
|
||||
self.assertEqual(self.trackview._selection.get_model(),
|
||||
self.trackview._filtermodel)
|
||||
|
||||
def test_columnview(self):
|
||||
"""Test the columnview."""
|
||||
self.assertIsInstance(self.trackview._columnview, Gtk.ColumnView)
|
||||
self.assertEqual(self.trackview._columnview.get_model(),
|
||||
self.trackview._selection)
|
||||
|
||||
self.assertTrue(self.trackview._columnview.get_hexpand())
|
||||
self.assertTrue(self.trackview._columnview.get_vexpand())
|
||||
self.assertTrue(self.trackview._columnview.get_show_row_separators())
|
||||
self.assertTrue(self.trackview._columnview.get_enable_rubberband())
|
||||
self.assertTrue(self.trackview._columnview.has_css_class(
|
||||
"emmental-track-list"))
|
||||
|
||||
def test_playlist(self):
|
||||
"""Test the playlist property."""
|
||||
self.assertIsNone(self.trackview.playlist)
|
||||
self.trackview.playlist = self.playlist
|
||||
self.assertEqual(self.trackview._filtermodel.get_model(),
|
||||
self.playlist)
|
||||
|
||||
def test_n_tracks(self):
|
||||
"""Test the n-tracks property."""
|
||||
self.assertEqual(self.trackview.n_tracks, 0)
|
||||
self.trackview._selection.set_model(self.playlist)
|
||||
self.db_plist.add_track(self.track)
|
||||
self.assertEqual(self.trackview.n_tracks, 1)
|
||||
|
||||
def test_runtime(self):
|
||||
"""Test the runtime property."""
|
||||
self.assertEqual(self.trackview.runtime, 0)
|
||||
self.trackview._selection.set_model(self.playlist)
|
||||
self.db_plist.add_track(self.track)
|
||||
self.assertEqual(self.trackview.runtime, 10.0)
|
Loading…
Reference in New Issue