sidebar: Create an Icon widget

This is mostly a wrapper around an Adw.Avatar to make it easier to load
images from a file.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2022-08-17 13:57:45 -04:00
parent 673c6910e9
commit 0584a2398a
2 changed files with 96 additions and 0 deletions

34
emmental/sidebar/icon.py Normal file
View File

@ -0,0 +1,34 @@
# Copyright 2022 (c) Anna Schumaker.
"""Custom icon widgets for playlist rows."""
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Adw
class Icon(Adw.Bin):
"""A custom Adw.Avatar that can load images from a file path."""
text = GObject.Property(type=str)
filepath = GObject.Property(type=GObject.TYPE_PYOBJECT)
icon_name = GObject.Property(type=str)
show_initials = GObject.Property(type=bool, default=False)
def __init__(self, **kwargs):
"""Initialize our Playlist icon."""
super().__init__(**kwargs)
self._icon = Adw.Avatar(size=40, show_initials=self.show_initials)
self.bind_property("text", self._icon, "text")
self.bind_property("icon-name", self._icon, "icon-name")
self.bind_property("show-initials", self._icon, "show-initials")
self.connect("notify::filepath", self.__notify_filepath)
self.set_child(self._icon)
def __notify_filepath(self, icon: Adw.Bin, param) -> None:
if self.filepath is None:
texture = None
else:
texture = Gdk.Texture.new_from_filename(str(self.filepath))
self._icon.set_custom_image(texture)

View File

@ -0,0 +1,62 @@
# Copyright 2022 (c) Anna Schumaker.
"""Tests our custom icon widgets."""
import unittest
import emmental.sidebar.icon
import tests.util
from gi.repository import Gdk
from gi.repository import Adw
class TestIcon(unittest.TestCase):
"""Test our icon that can also be set from filepath."""
def setUp(self):
"""Set up common variables."""
self.icon = emmental.sidebar.icon.Icon()
def test_init(self):
"""Test that the icon is set up properly."""
self.assertIsInstance(self.icon, Adw.Bin)
self.assertIsInstance(self.icon._icon, Adw.Avatar)
self.assertEqual(self.icon._icon.get_size(), 40)
self.assertEqual(self.icon.get_child(), self.icon._icon)
def test_icon_name(self):
"""Test setting an icon name to the inner icon widget."""
self.assertEqual(self.icon.icon_name, "")
self.icon.icon_name = "audio-x-generic"
self.assertEqual(self.icon._icon.get_icon_name(), "audio-x-generic")
def test_text(self):
"""Test the text property."""
self.assertEqual(self.icon.text, "")
self.icon.text = "Test Playlist"
self.assertEqual(self.icon._icon.get_text(), "Test Playlist")
def test_show_initials(self):
"""Test the show initials property."""
self.assertFalse(self.icon.show_initials)
self.icon.show_initials = True
self.assertTrue(self.icon._icon.get_show_initials())
icon2 = emmental.sidebar.icon.Icon(show_initials=True)
self.assertTrue(icon2._icon.get_show_initials())
def test_filepath(self):
"""Test the filepath property."""
self.assertIsNone(self.icon.filepath)
with unittest.mock.patch("gi.repository.Gdk.Texture.new_from_filename",
wraps=Gdk.Texture.new_from_filename) \
as mock_new:
self.icon.filepath = tests.util.COVER_JPG
mock_new.assert_called_with(str(tests.util.COVER_JPG))
self.assertIsInstance(self.icon._icon.get_custom_image(),
Gdk.Texture)
mock_new.reset_mock()
self.icon.filepath = None
self.assertIsNone(self.icon._icon.get_custom_image())
mock_new.assert_not_called()