tracklist: Move the OSD out of the TrackView
This simplifies the code a lot by letting the TrackList directly call OSD functions without going through the TrackView. I can also simplify the TrackView to just contain our columnview. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
5011db344e
commit
ddfd37130b
|
@ -70,6 +70,14 @@ button.emmental-stop>image {
|
|||
color: @red_3;
|
||||
}
|
||||
|
||||
columnview.emmental-track-list > header {
|
||||
background-color: @card_bg_color;
|
||||
}
|
||||
|
||||
columnview.emmental-track-list > listview {
|
||||
background-color: @card_bg_color;
|
||||
}
|
||||
|
||||
columnview.emmental-track-list > listview > row > cell {
|
||||
padding: 0px 2px;
|
||||
min-height: 40px;
|
||||
|
|
|
@ -10,6 +10,7 @@ from .. import db
|
|||
from .. import entry
|
||||
from . import buttons
|
||||
from . import footer
|
||||
from . import selection
|
||||
from . import trackview
|
||||
|
||||
|
||||
|
@ -27,8 +28,9 @@ class Card(Gtk.Box):
|
|||
self._top_box = Gtk.CenterBox(margin_start=6, 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._trackview = trackview.TrackView(sql)
|
||||
self._osd = selection.OSD(sql, self._trackview.selection_model,
|
||||
child=self._trackview)
|
||||
self._visible_cols = buttons.VisibleColumns(self._trackview.columns)
|
||||
self._unselect = Gtk.Button(icon_name="edit-select-none-symbolic",
|
||||
has_frame=False, sensitive=False)
|
||||
|
@ -50,9 +52,14 @@ class Card(Gtk.Box):
|
|||
self._top_box.set_end_widget(self._top_right)
|
||||
|
||||
self.append(self._top_box)
|
||||
self.append(self._trackview)
|
||||
self.append(Gtk.Separator())
|
||||
self.append(self._osd)
|
||||
self.append(Gtk.Separator())
|
||||
self.append(self._footer)
|
||||
|
||||
self._osd.bind_property("have-selected", self._trackview,
|
||||
"have-selected")
|
||||
self._osd.bind_property("n-selected", self._trackview, "n-selected")
|
||||
self._trackview.bind_property("n-tracks", self._footer, "count")
|
||||
self._trackview.bind_property("n-selected", self._footer, "selected")
|
||||
self._trackview.bind_property("runtime", self._footer, "runtime")
|
||||
|
@ -61,7 +68,7 @@ class Card(Gtk.Box):
|
|||
"sensitive")
|
||||
|
||||
self._filter.connect("search-changed", self.__search_changed)
|
||||
self._unselect.connect("clicked", self.__clear_selection)
|
||||
self._unselect.connect("clicked", self._osd.clear_selection)
|
||||
self._loop.connect("notify::state", self.__update_loop_state)
|
||||
self._shuffle.connect("notify::active", self.__update_shuffle_state)
|
||||
self._sort.connect("notify::sort-order", self.__update_sort_order)
|
||||
|
@ -69,9 +76,6 @@ class Card(Gtk.Box):
|
|||
self._top_box.add_css_class("toolbar")
|
||||
self.add_css_class("card")
|
||||
|
||||
def __clear_selection(self, unselect: Gtk.Button) -> None:
|
||||
self._trackview.clear_selected_tracks()
|
||||
|
||||
def __playlist_notify(self, playlist: Playlist, param) -> None:
|
||||
match param.name:
|
||||
case "loop":
|
||||
|
@ -89,7 +93,7 @@ class Card(Gtk.Box):
|
|||
self._loop.state = self.playlist.loop
|
||||
self._shuffle.active = self.playlist.shuffle
|
||||
self._sort.set_sort_order(self.playlist.sort_order)
|
||||
self._trackview.reset_osd()
|
||||
self._osd.reset()
|
||||
|
||||
def __update_loop_state(self, loop: buttons.LoopButton, param) -> None:
|
||||
if self.playlist.loop != loop.state:
|
||||
|
@ -132,6 +136,8 @@ class Card(Gtk.Box):
|
|||
self._trackview.playlist.disconnect_by_func(self.__playlist_notify)
|
||||
|
||||
self._trackview.playlist = newval
|
||||
self._osd.playlist = newval
|
||||
|
||||
if newval is not None:
|
||||
self._top_right.set_sensitive(not isinstance(newval, Previous))
|
||||
self.__set_button_state()
|
||||
|
|
|
@ -7,10 +7,9 @@ from .. import db
|
|||
from .. import factory
|
||||
from .. import playlist
|
||||
from . import row
|
||||
from . import selection
|
||||
|
||||
|
||||
class TrackView(Gtk.Frame):
|
||||
class TrackView(Gtk.ScrolledWindow):
|
||||
"""A Gtk.ColumnView that has been configured to show Tracks."""
|
||||
|
||||
playlist = GObject.Property(type=playlist.playlist.Playlist)
|
||||
|
@ -30,8 +29,6 @@ class TrackView(Gtk.Frame):
|
|||
show_row_separators=True,
|
||||
enable_rubberband=True,
|
||||
model=self._selection)
|
||||
self._scrollwin = Gtk.ScrolledWindow(child=self._columnview)
|
||||
self._osd = selection.OSD(sql, self._selection, child=self._scrollwin)
|
||||
|
||||
self.__append_column("Art", "cover", row.AlbumCover, resizable=False)
|
||||
self.__append_column("Fav", "favorite", row.FavoriteButton,
|
||||
|
@ -57,16 +54,13 @@ class TrackView(Gtk.Frame):
|
|||
self.__append_column("Filepath", "path", row.PathString, visible=False)
|
||||
|
||||
self.bind_property("playlist", self._filtermodel, "model")
|
||||
self.bind_property("playlist", self._osd, "playlist")
|
||||
self._osd.bind_property("have-selected", self, "have-selected")
|
||||
self._osd.bind_property("n-selected", self, "n-selected")
|
||||
self._selection.bind_property("n-items", self, "n-tracks")
|
||||
|
||||
self._selection.connect("items-changed", self.__runtime_changed)
|
||||
self._columnview.connect("activate", self.__track_activated)
|
||||
self._columnview.add_css_class("emmental-track-list")
|
||||
|
||||
self.set_child(self._osd)
|
||||
self.set_child(self._columnview)
|
||||
|
||||
def __append_column(self, title: str, property: str, row_type: type,
|
||||
*, width: int = -1, visible: bool = True,
|
||||
|
@ -95,15 +89,12 @@ class TrackView(Gtk.Frame):
|
|||
pos = max(i - 3, 0) * adjustment.get_upper()
|
||||
adjustment.set_value(pos / self._selection.get_n_items())
|
||||
|
||||
def clear_selected_tracks(self) -> None:
|
||||
"""Clear the currently selected tracks."""
|
||||
self._osd.clear_selection()
|
||||
|
||||
def reset_osd(self) -> None:
|
||||
"""Reset the OSD."""
|
||||
self._osd.reset()
|
||||
|
||||
@GObject.Property(type=Gio.ListModel)
|
||||
def columns(self) -> Gio.ListModel:
|
||||
"""Get the ListModel for the columns."""
|
||||
return self._columnview.get_columns()
|
||||
|
||||
@GObject.Property(type=Gio.ListModel)
|
||||
def selection_model(self) -> Gio.ListModel:
|
||||
"""Get the SelectionModel for the ColumnView."""
|
||||
return self._columnview.get_model()
|
||||
|
|
|
@ -66,8 +66,8 @@ class TestTracklist(tests.util.TestCase):
|
|||
self.tracklist._trackview.have_selected = True
|
||||
self.assertTrue(self.tracklist._unselect.get_sensitive())
|
||||
|
||||
with unittest.mock.patch.object(self.tracklist._trackview,
|
||||
"clear_selected_tracks") as mock_clear:
|
||||
with unittest.mock.patch.object(self.tracklist._osd.selection,
|
||||
"unselect_all") as mock_clear:
|
||||
self.tracklist._unselect.emit("clicked")
|
||||
mock_clear.assert_called()
|
||||
|
||||
|
@ -160,14 +160,32 @@ class TestTracklist(tests.util.TestCase):
|
|||
"""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)
|
||||
self.assertEqual(self.tracklist.columns,
|
||||
self.tracklist._trackview.columns)
|
||||
|
||||
sep = self.tracklist._top_box.get_next_sibling()
|
||||
self.assertIsInstance(sep, Gtk.Separator)
|
||||
self.assertEqual(sep.get_orientation(), Gtk.Orientation.HORIZONTAL)
|
||||
self.assertEqual(sep.get_next_sibling(), self.tracklist._osd)
|
||||
self.assertEqual(self.tracklist._osd.get_child(),
|
||||
self.tracklist._trackview)
|
||||
|
||||
def test_osd(self):
|
||||
"""Test the OSD widget."""
|
||||
self.assertIsInstance(self.tracklist._osd,
|
||||
emmental.tracklist.selection.OSD)
|
||||
self.assertEqual(self.tracklist._osd.sql, self.sql)
|
||||
self.assertEqual(self.tracklist._osd.selection,
|
||||
self.tracklist._trackview.selection_model)
|
||||
|
||||
self.assertFalse(self.tracklist._trackview.have_selected)
|
||||
self.tracklist._osd.have_selected = True
|
||||
self.assertTrue(self.tracklist._trackview.have_selected)
|
||||
|
||||
self.assertEqual(self.tracklist._trackview.n_selected, 0)
|
||||
self.tracklist._osd.n_selected = 4
|
||||
self.assertEqual(self.tracklist._trackview.n_selected, 4)
|
||||
|
||||
def test_footer(self):
|
||||
"""Test that the footer is wired up properly."""
|
||||
self.assertIsInstance(self.tracklist._footer,
|
||||
|
@ -176,8 +194,11 @@ class TestTracklist(tests.util.TestCase):
|
|||
self.assertEqual(self.tracklist._footer.get_margin_end(), 6)
|
||||
self.assertEqual(self.tracklist._footer.get_margin_top(), 6)
|
||||
self.assertEqual(self.tracklist._footer.get_margin_bottom(), 6)
|
||||
self.assertEqual(self.tracklist._trackview.get_next_sibling(),
|
||||
self.tracklist._footer)
|
||||
|
||||
sep = self.tracklist._osd.get_next_sibling()
|
||||
self.assertIsInstance(sep, Gtk.Separator)
|
||||
self.assertEqual(sep.get_orientation(), Gtk.Orientation.HORIZONTAL)
|
||||
self.assertEqual(sep.get_next_sibling(), self.tracklist._footer)
|
||||
|
||||
self.tracklist._trackview.n_tracks = 5
|
||||
self.tracklist._trackview.n_selected = 3
|
||||
|
@ -192,11 +213,12 @@ class TestTracklist(tests.util.TestCase):
|
|||
self.assertIsNone(self.tracklist.playlist)
|
||||
self.assertFalse(self.tracklist._top_right.get_sensitive())
|
||||
|
||||
with unittest.mock.patch.object(self.tracklist._trackview,
|
||||
"reset_osd") as mock_reset_osd:
|
||||
with unittest.mock.patch.object(self.tracklist._osd,
|
||||
"reset") as mock_reset_osd:
|
||||
self.tracklist.playlist = self.playlist
|
||||
self.assertEqual(self.tracklist.playlist, self.playlist)
|
||||
self.assertEqual(self.tracklist._trackview.playlist, self.playlist)
|
||||
self.assertEqual(self.tracklist._osd.playlist, self.playlist)
|
||||
self.assertTrue(self.tracklist._top_right.get_sensitive())
|
||||
mock_reset_osd.assert_called()
|
||||
|
||||
|
|
|
@ -28,15 +28,8 @@ class TestTrackView(tests.util.TestCase):
|
|||
|
||||
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.assertIsInstance(self.trackview._osd,
|
||||
emmental.tracklist.selection.OSD)
|
||||
|
||||
self.assertEqual(self.trackview.get_child(), self.trackview._osd)
|
||||
self.assertEqual(self.trackview._osd.get_child(),
|
||||
self.trackview._scrollwin)
|
||||
self.assertEqual(self.trackview._scrollwin.get_child(),
|
||||
self.assertIsInstance(self.trackview, Gtk.ScrolledWindow)
|
||||
self.assertEqual(self.trackview.get_child(),
|
||||
self.trackview._columnview)
|
||||
|
||||
def test_list_models(self):
|
||||
|
@ -50,6 +43,8 @@ class TestTrackView(tests.util.TestCase):
|
|||
|
||||
self.assertEqual(self.trackview._selection.get_model(),
|
||||
self.trackview._filtermodel)
|
||||
self.assertEqual(self.trackview.selection_model,
|
||||
self.trackview._selection)
|
||||
|
||||
def test_columnview(self):
|
||||
"""Test the columnview."""
|
||||
|
@ -80,27 +75,12 @@ class TestTrackView(tests.util.TestCase):
|
|||
requested.assert_called_with(self.playlist, self.track)
|
||||
mock_unselect.assert_called()
|
||||
|
||||
def test_clear_selected_tracks(self):
|
||||
"""Test the clear_selected_tracks() function."""
|
||||
with unittest.mock.patch.object(self.trackview._osd,
|
||||
"clear_selection") as mock_clear:
|
||||
self.trackview.clear_selected_tracks()
|
||||
mock_clear.assert_called()
|
||||
|
||||
def test_reset_osd(self):
|
||||
"""Test the reset_osd() function."""
|
||||
with unittest.mock.patch.object(self.trackview._osd,
|
||||
"reset") as mock_reset:
|
||||
self.trackview.reset_osd()
|
||||
mock_reset.assert_called()
|
||||
|
||||
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)
|
||||
self.assertEqual(self.trackview._osd.playlist, self.playlist)
|
||||
|
||||
def test_n_tracks(self):
|
||||
"""Test the n-tracks property."""
|
||||
|
@ -116,17 +96,6 @@ class TestTrackView(tests.util.TestCase):
|
|||
self.db_plist.add_track(self.track)
|
||||
self.assertEqual(self.trackview.runtime, 10.0)
|
||||
|
||||
def test_n_selected(self):
|
||||
"""Test the n-selected and have-selected properties."""
|
||||
self.assertEqual(self.trackview.n_selected, 0)
|
||||
self.assertFalse(self.trackview.have_selected)
|
||||
|
||||
self.trackview._osd.n_selected = 4
|
||||
self.trackview._osd.have_selected = True
|
||||
|
||||
self.assertEqual(self.trackview.n_selected, 4)
|
||||
self.assertTrue(self.trackview.have_selected)
|
||||
|
||||
|
||||
class TestTrackViewColumns(tests.util.TestCase):
|
||||
"""Test the TrackView Columns."""
|
||||
|
|
Loading…
Reference in New Issue