tracklist: Scroll to the requested Track
And wire this up to not only the Now Playing "jump" signal, but also the next track pickers so we scroll when tracks are changed. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
481c4856c7
commit
a485a3806b
|
@ -64,12 +64,17 @@ class Application(Adw.Application):
|
||||||
else:
|
else:
|
||||||
track.start()
|
track.start()
|
||||||
self.__set_replaygain(rg_auto=rg_auto)
|
self.__set_replaygain(rg_auto=rg_auto)
|
||||||
|
self.__on_jump()
|
||||||
|
|
||||||
def __pick_next_track(self, *, user: bool, gapless: bool = False) -> None:
|
def __pick_next_track(self, *, user: bool, gapless: bool = False) -> None:
|
||||||
(track, rg_auto, restart) = self.factory.next_track(user=user)
|
(track, rg_auto, restart) = self.factory.next_track(user=user)
|
||||||
self.__load_track(track, gapless=gapless,
|
self.__load_track(track, gapless=gapless,
|
||||||
rg_auto=rg_auto, restart=restart)
|
rg_auto=rg_auto, restart=restart)
|
||||||
|
|
||||||
|
def __on_jump(self, nowplay: nowplaying.Card | None = None) -> None:
|
||||||
|
"""Handle a jump event."""
|
||||||
|
self.win.tracklist.scroll_to_track(self.db.tracks.current_track)
|
||||||
|
|
||||||
def __on_seek(self, nowplay: nowplaying.Card, newpos: float) -> None:
|
def __on_seek(self, nowplay: nowplaying.Card, newpos: float) -> None:
|
||||||
"""Handle a seek event."""
|
"""Handle a seek event."""
|
||||||
self.player.seek(newpos)
|
self.player.seek(newpos)
|
||||||
|
@ -114,6 +119,7 @@ class Application(Adw.Application):
|
||||||
self.player.file = track_table.current_track.path
|
self.player.file = track_table.current_track.path
|
||||||
self.player.pause()
|
self.player.pause()
|
||||||
track_table.current_track.start()
|
track_table.current_track.start()
|
||||||
|
self.__on_jump()
|
||||||
|
|
||||||
def build_header(self) -> header.Header:
|
def build_header(self) -> header.Header:
|
||||||
"""Build a new header instance."""
|
"""Build a new header instance."""
|
||||||
|
@ -147,6 +153,7 @@ class Application(Adw.Application):
|
||||||
self.db.settings.bind_setting("now-playing.prefer-artist",
|
self.db.settings.bind_setting("now-playing.prefer-artist",
|
||||||
playing, "prefer-artist")
|
playing, "prefer-artist")
|
||||||
|
|
||||||
|
playing.connect("jump", self.__on_jump)
|
||||||
playing.connect("play", self.player.play)
|
playing.connect("play", self.player.play)
|
||||||
playing.connect("pause", self.player.pause)
|
playing.connect("pause", self.player.pause)
|
||||||
playing.connect("seek", self.__on_seek)
|
playing.connect("seek", self.__on_seek)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2022 (c) Anna Schumaker.
|
# Copyright 2022 (c) Anna Schumaker.
|
||||||
"""A card for displaying a list of tracks."""
|
"""A card for displaying a list of tracks."""
|
||||||
from gi.repository import GObject
|
from gi.repository import GObject
|
||||||
|
from gi.repository import GLib
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
from .. import db
|
from .. import db
|
||||||
|
@ -39,6 +40,15 @@ class Card(Gtk.Box):
|
||||||
def __search_changed(self, filter: entry.Filter) -> None:
|
def __search_changed(self, filter: entry.Filter) -> None:
|
||||||
self.sql.tracks.filter(filter.get_query())
|
self.sql.tracks.filter(filter.get_query())
|
||||||
|
|
||||||
|
def __scroll_idle(self, track: db.tracks.Track) -> bool:
|
||||||
|
self._trackview.scroll_to_track(track)
|
||||||
|
return GLib.SOURCE_REMOVE
|
||||||
|
|
||||||
|
def scroll_to_track(self, track: db.tracks.Track) -> None:
|
||||||
|
"""Scroll to the requested Track."""
|
||||||
|
if self.playlist is not None:
|
||||||
|
GLib.idle_add(self.__scroll_idle, track)
|
||||||
|
|
||||||
@GObject.Property(type=Gio.ListModel)
|
@GObject.Property(type=Gio.ListModel)
|
||||||
def columns(self) -> Gio.ListModel:
|
def columns(self) -> Gio.ListModel:
|
||||||
"""Get the columns displayed in the Tracklist."""
|
"""Get the columns displayed in the Tracklist."""
|
||||||
|
|
|
@ -77,6 +77,16 @@ class TrackView(Gtk.Frame):
|
||||||
self.playlist.request_track(self._selection[position])
|
self.playlist.request_track(self._selection[position])
|
||||||
self._selection.unselect_all()
|
self._selection.unselect_all()
|
||||||
|
|
||||||
|
def scroll_to_track(self, track: db.tracks.Track) -> None:
|
||||||
|
"""Scroll to the requested Track."""
|
||||||
|
# This is a workaround until the ColumnView has better scrolling
|
||||||
|
# support, which seems to be targeted for Gtk 4.10.
|
||||||
|
adjustment = self._scrollwin.get_vadjustment()
|
||||||
|
for (i, t) in enumerate(self._selection):
|
||||||
|
if t == track:
|
||||||
|
pos = max(i - 3, 0) * adjustment.get_upper()
|
||||||
|
adjustment.set_value(pos / self._selection.get_n_items())
|
||||||
|
|
||||||
@GObject.Property(type=Gio.ListModel)
|
@GObject.Property(type=Gio.ListModel)
|
||||||
def columns(self) -> Gio.ListModel:
|
def columns(self) -> Gio.ListModel:
|
||||||
"""Get the ListModel for the columns."""
|
"""Get the ListModel for the columns."""
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
import emmental.tracklist
|
import emmental.tracklist
|
||||||
import tests.util
|
import tests.util
|
||||||
|
from gi.repository import GLib
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,3 +76,20 @@ class TestTracklist(tests.util.TestCase):
|
||||||
self.tracklist.playlist = self.playlist
|
self.tracklist.playlist = self.playlist
|
||||||
self.assertEqual(self.tracklist.playlist, self.playlist)
|
self.assertEqual(self.tracklist.playlist, self.playlist)
|
||||||
self.assertEqual(self.tracklist._trackview.playlist, self.playlist)
|
self.assertEqual(self.tracklist._trackview.playlist, self.playlist)
|
||||||
|
|
||||||
|
@unittest.mock.patch("gi.repository.GLib.idle_add")
|
||||||
|
def test_scroll_to_track(self, mock_idle_add: unittest.mock.Mock):
|
||||||
|
"""Test the scroll_to_track() function."""
|
||||||
|
self.tracklist.scroll_to_track(None)
|
||||||
|
mock_idle_add.assert_not_called()
|
||||||
|
|
||||||
|
self.tracklist.playlist = self.playlist
|
||||||
|
self.tracklist.scroll_to_track(None)
|
||||||
|
mock_idle_add.assert_called_with(self.tracklist._Card__scroll_idle,
|
||||||
|
None)
|
||||||
|
|
||||||
|
with unittest.mock.patch.object(self.tracklist._trackview,
|
||||||
|
"scroll_to_track") as mock_scroll:
|
||||||
|
self.assertEqual(self.tracklist._Card__scroll_idle(None),
|
||||||
|
GLib.SOURCE_REMOVE)
|
||||||
|
mock_scroll.assert_called_with(None)
|
||||||
|
|
Loading…
Reference in New Issue