From 1ffc300edac1baf88bebc3071b24254c52b55732 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Fri, 13 Jan 2023 14:34:26 -0500 Subject: [PATCH] tracklist: Create a TracknoString TrackRow This is an InscriptionRow that combines a Track's number with its Medium's number. Signed-off-by: Anna Schumaker --- emmental/tracklist/row.py | 30 ++++++++++++++++++++++++++++++ emmental/tracklist/trackview.py | 2 ++ tests/test_settings.py | 4 ++++ tests/tracklist/test_row.py | 19 +++++++++++++++++++ tests/tracklist/test_trackview.py | 31 ++++++++++++++++++++++++------- 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/emmental/tracklist/row.py b/emmental/tracklist/row.py index 6187a85..9003466 100644 --- a/emmental/tracklist/row.py +++ b/emmental/tracklist/row.py @@ -13,6 +13,7 @@ class TrackRow(factory.ListRow): """Base class for Track Row widgets.""" property = GObject.Property(type=str) + mediumid = GObject.Property(type=int) def __init__(self, listitem: Gtk.ListItem, property: str): """Initialize a TrackRow.""" @@ -25,6 +26,10 @@ class TrackRow(factory.ListRow): self.bind_and_set(library, "online", self, "online") self.bind_active("active") + def bind_to_self(self, item_prop: str, child_prop: str) -> None: + """Bind an item property directly to a TrackRow property.""" + self.bind_and_set(self.item, item_prop, self, child_prop) + @GObject.Property(type=bool, default=False) def active(self) -> bool: """Get the active state of this Row.""" @@ -160,6 +165,31 @@ class PathString(InscriptionRow): self.child.set_text(str(newval)) +class TracknoString(InscriptionRow): + """A FormatString that combines medium and track numbers.""" + + number = GObject.Property(type=int) + + def __init__(self, *args, **kwargs): + """Initialize a TracknoString.""" + super().__init__(*args, **kwargs) + self.connect("notify", self.__update_trackno) + + def __update_trackno(self, row: InscriptionRow, param) -> None: + """Update the trackno string when properties change.""" + match param.name: + case "mediumid": self.notify("number") + case "number": + mediumno = self.item.get_medium().number + self.child.set_text("{}-{:02d}".format(mediumno, self.number)) + + def do_bind(self) -> None: + """Bind track and medium numbers to the Track Inscription.""" + super().do_bind() + self.bind_to_self("mediumid", "mediumid") + self.bind_to_self("number", "number") + + class FavoriteButton(TrackRow): """A TrackRow with an toggle to set Track favorite status.""" diff --git a/emmental/tracklist/trackview.py b/emmental/tracklist/trackview.py index e28727e..db92e83 100644 --- a/emmental/tracklist/trackview.py +++ b/emmental/tracklist/trackview.py @@ -30,6 +30,8 @@ class TrackView(Gtk.Frame): self.__append_column("Fav", "favorite", row.FavoriteButton, resizable=False) + self.__append_column("Track", "number", row.TracknoString, + width=55, xalign=1.0, numeric=True) self.__append_column("Title", "title", row.TrackString, width=300) self.__append_column("Length", "length", row.LengthString, xalign=1.0, numeric=True) diff --git a/tests/test_settings.py b/tests/test_settings.py index b4dc3fe..b136470 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -122,6 +122,7 @@ class TestSettings(unittest.TestCase): def test_save_tracklist_column_width(self, mock_stdout: io.StringIO): """Test saving tracklist column widths.""" self.assertEqual(self.settings["tracklist.fav.size"], -1) + self.assertEqual(self.settings["tracklist.track.size"], 55) self.assertEqual(self.settings["tracklist.title.size"], 300) self.assertEqual(self.settings["tracklist.length.size"], -1) self.assertEqual(self.settings["tracklist.artist.size"], 250) @@ -134,6 +135,7 @@ class TestSettings(unittest.TestCase): column.set_fixed_width(123) self.assertEqual(self.settings["tracklist.fav.size"], 123) + self.assertEqual(self.settings["tracklist.track.size"], 123) self.assertEqual(self.settings["tracklist.title.size"], 123) self.assertEqual(self.settings["tracklist.length.size"], 123) self.assertEqual(self.settings["tracklist.artist.size"], 123) @@ -145,6 +147,7 @@ class TestSettings(unittest.TestCase): def test_save_tracklist_column_visible(self, mock_stdout: io.StringIO): """Test saving tracklist column visibility.""" self.assertTrue(self.settings["tracklist.fav.visible"]) + self.assertTrue(self.settings["tracklist.track.visible"]) self.assertTrue(self.settings["tracklist.title.visible"]) self.assertTrue(self.settings["tracklist.length.visible"]) self.assertTrue(self.settings["tracklist.artist.visible"]) @@ -157,6 +160,7 @@ class TestSettings(unittest.TestCase): column.set_visible(not column.get_visible()) self.assertFalse(self.settings["tracklist.fav.visible"]) + self.assertFalse(self.settings["tracklist.track.visible"]) self.assertFalse(self.settings["tracklist.title.visible"]) self.assertFalse(self.settings["tracklist.length.visible"]) self.assertFalse(self.settings["tracklist.artist.visible"]) diff --git a/tests/tracklist/test_row.py b/tests/tracklist/test_row.py index 77a9eaf..e543eb7 100644 --- a/tests/tracklist/test_row.py +++ b/tests/tracklist/test_row.py @@ -38,6 +38,7 @@ class TestTrackRowWidgets(tests.util.TestCase): row = emmental.tracklist.row.TrackRow(self.listitem, "property") self.assertIsInstance(row, emmental.factory.ListRow) self.assertEqual(row.property, "property") + self.assertEqual(row.mediumid, 0) row.child = Gtk.Label() self.columnrow.set_child(row.child) @@ -129,6 +130,24 @@ class TestTrackRowWidgets(tests.util.TestCase): row.bind() self.assertEqual(row.child.get_text(), str(pathlib.Path("/a/b/1.ogg"))) + def test_trackno_label(self): + """Test the Track Number Label widget.""" + row = emmental.tracklist.row.TracknoString(self.listitem, "number") + self.assertIsInstance(row, emmental.tracklist.row.InscriptionRow) + self.assertEqual(row.property, "number") + self.assertEqual(row.number, 0) + + row.bind() + self.assertEqual(row.mediumid, self.medium.mediumid) + self.assertEqual(row.child.get_text(), "1-00") + + self.track.number = 3 + self.assertEqual(row.child.get_text(), "1-03") + + medium = self.sql.media.create(self.album, "", number=3) + self.track.mediumid = medium.mediumid + self.assertEqual(row.child.get_text(), "3-03") + def test_favorite_button(self): """Test the Favorite Button widget.""" row = emmental.tracklist.row.FavoriteButton(self.listitem, "favorite") diff --git a/tests/tracklist/test_trackview.py b/tests/tracklist/test_trackview.py index 6955ea1..e4aae9a 100644 --- a/tests/tracklist/test_trackview.py +++ b/tests/tracklist/test_trackview.py @@ -108,7 +108,24 @@ class TestTrackViewColumns(tests.util.TestCase): factory.emit("setup", self.listitem) self.assertEqual(self.listitem.listrow.property, "favorite") - def test_title_column(self, i: int = 1): + def test_trackno_column(self, i: int = 1): + """Test the track number column.""" + self.assertEqual(self.columns[i].get_title(), "Track") + self.assertEqual(self.columns[i].get_fixed_width(), 55) + self.assertTrue(self.columns[i].get_resizable()) + self.assertTrue(self.columns[i].get_visible()) + + factory = self.columns[i].get_factory() + self.assertIsInstance(factory, emmental.factory.Factory) + self.assertEqual(factory.row_type, + emmental.tracklist.row.TracknoString) + + factory.emit("setup", self.listitem) + self.assertEqual(self.listitem.listrow.property, "number") + self.assertEqual(self.listitem.listrow.child.get_xalign(), 1.0) + self.assertTrue(self.listitem.listrow.child.has_css_class("numeric")) + + def test_title_column(self, i: int = 2): """Test the title column.""" self.assertEqual(self.columns[i].get_title(), "Title") self.assertEqual(self.columns[i].get_fixed_width(), 300) @@ -124,7 +141,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 0.0) self.assertFalse(self.listitem.listrow.child.has_css_class("numeric")) - def test_length_column(self, i: int = 2): + def test_length_column(self, i: int = 3): """Test the length column.""" self.assertEqual(self.columns[i].get_title(), "Length") self.assertEqual(self.columns[i].get_fixed_width(), -1) @@ -140,7 +157,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 1.0) self.assertTrue(self.listitem.listrow.child.has_css_class("numeric")) - def test_artist_column(self, i: int = 3): + def test_artist_column(self, i: int = 4): """Test the artist column.""" self.assertEqual(self.columns[i].get_title(), "Artist") self.assertEqual(self.columns[i].get_fixed_width(), 250) @@ -156,7 +173,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 0.0) self.assertFalse(self.listitem.listrow.child.has_css_class("numeric")) - def test_playcount_column(self, i: int = 4): + def test_playcount_column(self, i: int = 5): """Test the play count column.""" self.assertEqual(self.columns[i].get_title(), "Play Count") self.assertEqual(self.columns[i].get_fixed_width(), 135) @@ -173,7 +190,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 0.0) self.assertTrue(self.listitem.listrow.child.has_css_class("numeric")) - def test_last_started_column(self, i: int = 5): + def test_last_started_column(self, i: int = 6): """Test the last started column.""" self.assertEqual(self.columns[i].get_title(), "Last Started") self.assertEqual(self.columns[i].get_fixed_width(), 250) @@ -190,7 +207,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 0.0) self.assertTrue(self.listitem.listrow.child.has_css_class("numeric")) - def test_last_played_column(self, i: int = 6): + def test_last_played_column(self, i: int = 7): """Test the last played column.""" self.assertEqual(self.columns[i].get_title(), "Last Played") self.assertEqual(self.columns[i].get_fixed_width(), 250) @@ -207,7 +224,7 @@ class TestTrackViewColumns(tests.util.TestCase): self.assertEqual(self.listitem.listrow.child.get_xalign(), 0.0) self.assertTrue(self.listitem.listrow.child.has_css_class("numeric")) - def test_filepath_column(self, i: int = 7): + def test_filepath_column(self, i: int = 8): """Test the last played column.""" self.assertEqual(self.columns[i].get_title(), "Filepath") self.assertEqual(self.columns[i].get_fixed_width(), -1)