From 3ba46db064037f81b75849b91f231b5c90ec5bba Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Wed, 31 Aug 2022 11:25:23 -0400 Subject: [PATCH] sidebar: Create a Section for Decades This section shows a tree of Decade and Year playlists. I use the year-alt icon from the gnome icon-library as the section header. Signed-off-by: Anna Schumaker --- emmental/sidebar/decade.py | 49 +++++++++++++++ icons/scalable/actions/year-alt-symbolic.svg | 2 + tests/sidebar/test_decade.py | 63 ++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 emmental/sidebar/decade.py create mode 100644 icons/scalable/actions/year-alt-symbolic.svg create mode 100644 tests/sidebar/test_decade.py diff --git a/emmental/sidebar/decade.py b/emmental/sidebar/decade.py new file mode 100644 index 0000000..80e7a92 --- /dev/null +++ b/emmental/sidebar/decade.py @@ -0,0 +1,49 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Displays our decade and year tree.""" +from gi.repository import GObject +from .. import db +from . import row +from . import section + + +class DecadeRow(row.TreeRow): + """A TreeRow for setting Decade & Year icons properly.""" + + def __init__(self, *args, **kwargs): + """Initialize a GenreRow.""" + super().__init__(*args, **kwargs) + self.child = row.Row() + + def do_bind(self) -> None: + """Bind the decade and year number to the row year property.""" + super().do_bind() + if isinstance(self.item, db.decades.Decade): + self.bind_and_set_property("decade", "year") + else: + self.bind_and_set_property("year", "year") + + +class Section(section.Section): + """A sidebar Section for the decade and year playlist tree.""" + + year_table = GObject.Property(type=db.years.Table) + + def __init__(self, decade_table: db.decades.Table, + year_table: db.years.Table): + """Initialize our decade & year section.""" + super().__init__(decade_table, DecadeRow, title="Decades & Years", + subtitle="0 decades, 0 years", + icon_name="year-alt", year_table=year_table) + self.year_table.connect("items-changed", self.__update_subtitle) + + def __update_subtitle(self, table: db.years.Table, position: int, + removed: int, added: int) -> None: + self.subtitle = self.do_get_subtitle(0) + + def do_get_subtitle(self, n_items: int) -> str: + """Return a subtitle for this section.""" + n_decades = len(self.table) + s_decades = "s" if n_decades != 1 else "" + n_years = len(self.year_table) + s_years = "s" if n_years != 1 else "" + return f"{n_decades} decade{s_decades}, {n_years} year{s_years}" diff --git a/icons/scalable/actions/year-alt-symbolic.svg b/icons/scalable/actions/year-alt-symbolic.svg new file mode 100644 index 0000000..e574bb5 --- /dev/null +++ b/icons/scalable/actions/year-alt-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/tests/sidebar/test_decade.py b/tests/sidebar/test_decade.py new file mode 100644 index 0000000..cd5c8be --- /dev/null +++ b/tests/sidebar/test_decade.py @@ -0,0 +1,63 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Tests our decade / year section and tree.""" +import emmental.sidebar.decade +import tests.util +import unittest.mock +from gi.repository import Gtk + + +class TestDecade(tests.util.TestCase): + """Test our Decade section.""" + + def setUp(self): + """Set up common variables.""" + super().setUp() + self.decades = emmental.sidebar.decade.Section(self.sql.decades, + self.sql.years) + + def test_init(self): + """Test that the decade section is set up correctly.""" + self.assertIsInstance(self.decades, emmental.sidebar.section.Section) + self.assertEqual(self.decades._factory.row_type, + emmental.sidebar.decade.DecadeRow) + + self.assertEqual(self.decades.table, self.sql.decades) + self.assertEqual(self.decades.year_table, self.sql.years) + self.assertEqual(self.decades.icon_name, "year-alt") + self.assertEqual(self.decades.title, "Decades & Years") + + def test_subtitle(self): + """Test that the subtitle property is set properly.""" + self.assertEqual(self.decades.subtitle, "0 decades, 0 years") + self.sql.decades.create(1980) + self.assertEqual(self.decades.subtitle, "1 decade, 0 years") + self.sql.years.create(1985) + self.assertEqual(self.decades.subtitle, "1 decade, 1 year") + self.sql.years.create(1988) + self.assertEqual(self.decades.subtitle, "1 decade, 2 years") + self.sql.decades.create(1990) + self.assertEqual(self.decades.subtitle, "2 decades, 2 years") + + def test_decade_row(self): + """Test the decaderow widget.""" + treeitem = Gtk.TreeListRow() + treeitem.get_item = unittest.mock.Mock() + listitem = Gtk.ListItem() + listitem.get_item = unittest.mock.Mock(return_value=treeitem) + + treeitem.get_item.return_value = self.sql.decades.create(1980) + row = emmental.sidebar.decade.DecadeRow(listitem) + self.assertIsInstance(row, emmental.sidebar.row.TreeRow) + self.assertIsInstance(row.child, emmental.sidebar.row.Row) + self.assertTrue(row.indented) + + row.bind() + self.assertEqual(row.child.name, "The 1980s") + self.assertEqual(row.child.year, 1980) + row.unbind() + + treeitem.get_item.return_value = self.sql.years.create(1988) + row.bind() + self.assertEqual(row.child.name, "1988") + self.assertEqual(row.child.year, 1988) + row.unbind()