sidebar: Create a Section Group

This group manages a list of sections so only one is active at a time.
Additionally, it adjusts the animation property of each section to match
the direction the header moves when activated.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2022-08-30 10:58:46 -04:00
parent b316184bf1
commit eb0b005c75
2 changed files with 143 additions and 0 deletions

View File

@ -97,3 +97,54 @@ class Section(header.Header):
@GObject.Signal(arg_types=(db.playlist.Playlist,))
def playlist_selected(self, playlist: db.playlist.Playlist):
"""Signal that the selected playlist has changed."""
class Group(GObject.GObject):
"""A group of sections."""
sql = GObject.Property(type=db.Connection)
current = GObject.Property(type=Section)
selected_section = GObject.Property(type=Section)
selected_playlist = GObject.Property(type=db.playlist.Playlist)
def __init__(self, sql: db.Connection):
"""Initialize a Section Group."""
super().__init__(sql=sql)
self._sections = []
def __on_active(self, section: Section, param: GObject.ParamSpec) -> None:
if section.active:
new = self._sections.index(section)
prev = len(self._sections)
if self.current and self.current is not section:
prev = self._sections.index(self.current)
self.current.active = False
self.current = section
if new < prev:
section.animation = Gtk.RevealerTransitionType.SLIDE_DOWN
else:
section.animation = Gtk.RevealerTransitionType.SLIDE_UP
if section is self.selected_section:
section.select_playlist(self.selected_playlist)
def __playlist_activated(self, section: Section,
playlist: db.playlist.Playlist) -> None:
self.sql.set_active_playlist(playlist)
def __playlist_selected(self, section: Section,
playlist: db.playlist.Playlist) -> None:
if self.selected_section and self.selected_section is not section:
self.selected_section.clear_selection()
self.selected_section = section
self.selected_playlist = playlist
def add(self, section: Section) -> None:
"""Add a section to the group."""
self._sections.append(section)
section.connect("notify::active", self.__on_active)
section.connect("playlist-activated", self.__playlist_activated)
section.connect("playlist-selected", self.__playlist_selected)

View File

@ -4,6 +4,7 @@ import emmental.db
import emmental.sidebar.section
import tests.util
import unittest.mock
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gtk
@ -141,3 +142,94 @@ class TestSection(tests.util.TestCase):
playlist = self.table.create("Test Playlist")
self.section._listview.emit("activate", 0)
playlist_activated.assert_called_with(self.section, playlist)
class TestGroup(tests.util.TestCase):
"""Test our sidebar section group."""
def setUp(self):
"""Set up common variables."""
super().setUp()
self.group = emmental.sidebar.section.Group(self.sql)
self.row_type = emmental.sidebar.row.TreeRow
self.section1 = emmental.sidebar.section.Section(self.sql.playlists,
self.row_type)
self.section2 = emmental.sidebar.section.Section(self.sql.genres,
self.row_type)
self.section1.do_get_subtitle = unittest.mock.Mock(return_value="")
self.section2.do_get_subtitle = unittest.mock.Mock(return_value="")
def test_init(self):
"""Test that the Group is set up properly."""
self.assertIsInstance(self.group, GObject.GObject)
self.assertListEqual(self.group._sections, [])
self.assertEqual(self.group.sql, self.sql)
def test_add(self):
"""Test adding sections to the Group."""
self.group.add(self.section1)
self.assertListEqual(self.group._sections, [self.section1])
self.group.add(self.section2)
self.assertListEqual(self.group._sections,
[self.section1, self.section2])
def test_current(self):
"""Test the current section property."""
self.group.add(self.section1)
self.group.add(self.section2)
self.assertIsNone(self.group.current)
self.section1.active = True
self.assertEqual(self.group.current, self.section1)
self.section2.active = True
self.assertEqual(self.group.current, self.section2)
self.assertFalse(self.section1.active)
def test_animation(self):
"""Test setting the section animation style."""
self.group.add(self.section1)
self.group.add(self.section2)
self.section1.active = True
self.assertEqual(self.section1.animation,
Gtk.RevealerTransitionType.SLIDE_DOWN)
self.section2.active = True
self.assertEqual(self.section2.animation,
Gtk.RevealerTransitionType.SLIDE_UP)
def test_playlist_activated(self):
"""Test responding to the section playlist-activated signal."""
self.group.add(self.section1)
self.group.add(self.section2)
self.assertIsNone(self.sql.active_playlist)
playlist = self.sql.playlists.create("Test Playlist")
self.section1.emit("playlist-activated", playlist)
self.assertEqual(self.sql.active_playlist, playlist)
genre = self.sql.genres.create("Test Genre")
self.section2.emit("playlist-activated", genre)
self.assertEqual(self.sql.active_playlist, genre)
def test_selections(self):
"""Test the selected section & playlist properties."""
self.group.add(self.section1)
self.group.add(self.section2)
self.assertIsNone(self.group.selected_section)
self.assertIsNone(self.group.selected_playlist)
genre = self.sql.genres.create("Test Genre")
self.section2.emit("playlist-selected", genre)
self.assertEqual(self.group.selected_section, self.section2)
self.assertEqual(self.group.selected_playlist, genre)
self.section2.active = True
treerow = self.section2._selection.get_selected_item()
self.assertEqual(treerow.get_item(), genre)
playlist = self.sql.playlists.create("Test Playlist")
self.section1.emit("playlist-selected", playlist)
self.assertIsNone(self.section2._selection.get_selected_item())