sidebar: Use the Texture Cache for album art and user icons

I make sure to clear an existing texture before setting a new one in
case the user downloads a new file with the same path. Otherwise we'll
end up using a stale texture in the list.

Implements: #54 ("Convert the SideBar to use the Texture Cache")
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2023-06-27 16:57:03 -04:00
parent 51b290e1f0
commit a4f30d87e6
2 changed files with 16 additions and 18 deletions

View File

@ -4,9 +4,9 @@ import pathlib
from gi.repository import GObject from gi.repository import GObject
from gi.repository import GLib from gi.repository import GLib
from gi.repository import Gio from gi.repository import Gio
from gi.repository import Gdk
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Adw from gi.repository import Adw
from .. import texture
IMAGE_FILTERS = Gio.ListStore() IMAGE_FILTERS = Gio.ListStore()
@ -37,11 +37,7 @@ class Icon(Adw.Bin):
self.set_child(self._icon) self.set_child(self._icon)
def __notify_filepath(self, icon: Adw.Bin, param) -> None: def __notify_filepath(self, icon: Adw.Bin, param) -> None:
if self.filepath is None: self._icon.set_custom_image(texture.CACHE[self.filepath])
texture = None
else:
texture = Gdk.Texture.new_from_filename(str(self.filepath))
self._icon.set_custom_image(texture)
class Settable(Icon): class Settable(Icon):
@ -61,7 +57,9 @@ class Settable(Icon):
def __async_ready(self, dialog: Gtk.FileDialog, task: Gio.Task) -> None: def __async_ready(self, dialog: Gtk.FileDialog, task: Gio.Task) -> None:
try: try:
file = dialog.open_finish(task) file = dialog.open_finish(task)
self.filepath = pathlib.Path(file.get_path()) path = pathlib.Path(file.get_path())
texture.CACHE.drop(path)
self.filepath = path
except GLib.Error: except GLib.Error:
self.filepath = None self.filepath = None

View File

@ -69,18 +69,14 @@ class TestIcon(unittest.TestCase):
"""Test the filepath property.""" """Test the filepath property."""
self.assertIsNone(self.icon.filepath) self.assertIsNone(self.icon.filepath)
with unittest.mock.patch("gi.repository.Gdk.Texture.new_from_filename", self.icon.filepath = tests.util.COVER_JPG
wraps=Gdk.Texture.new_from_filename) \ texture = self.icon._icon.get_custom_image()
as mock_new: self.assertIsInstance(texture, Gdk.Texture)
self.icon.filepath = tests.util.COVER_JPG self.assertDictEqual(emmental.texture.CACHE,
mock_new.assert_called_with(str(tests.util.COVER_JPG)) {tests.util.COVER_JPG: texture})
self.assertIsInstance(self.icon._icon.get_custom_image(),
Gdk.Texture)
mock_new.reset_mock() self.icon.filepath = None
self.icon.filepath = None self.assertIsNone(self.icon._icon.get_custom_image())
self.assertIsNone(self.icon._icon.get_custom_image())
mock_new.assert_not_called()
class TestSettable(unittest.TestCase): class TestSettable(unittest.TestCase):
@ -123,11 +119,15 @@ class TestSettable(unittest.TestCase):
task = Gio.Task() task = Gio.Task()
cover_path = str(tests.util.COVER_JPG) cover_path = str(tests.util.COVER_JPG)
mock_finish.return_value = Gio.File.new_for_path(cover_path) mock_finish.return_value = Gio.File.new_for_path(cover_path)
emmental.texture.CACHE[tests.util.COVER_JPG] = "abcde"
self.icon._Settable__async_ready(self.icon._dialog, task) self.icon._Settable__async_ready(self.icon._dialog, task)
mock_finish.assert_called_with(task) mock_finish.assert_called_with(task)
self.assertEqual(self.icon.filepath, tests.util.COVER_JPG) self.assertEqual(self.icon.filepath, tests.util.COVER_JPG)
texture = emmental.texture.CACHE[tests.util.COVER_JPG]
self.assertIsInstance(texture, Gdk.Texture)
def test_clearing(self): def test_clearing(self):
"""Test clearing the icon by canceling the FileDialog.""" """Test clearing the icon by canceling the FileDialog."""
mock_set_initial_file = unittest.mock.Mock() mock_set_initial_file = unittest.mock.Mock()