emmental/emmental/sidebar/icon.py

75 lines
2.6 KiB
Python

# Copyright 2022 (c) Anna Schumaker.
"""Custom icon widgets for playlist rows."""
import pathlib
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
from gi.repository import Gtk
from gi.repository import Adw
from .. import texture
IMAGE_FILTERS = Gio.ListStore()
IMAGE_FILTERS.append(Gtk.FileFilter(name="Image Files",
mime_types=["inode/directory"]))
IMAGE_FILTERS[0].add_pixbuf_formats()
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:
self._icon.set_custom_image(texture.CACHE[self.filepath])
class Settable(Icon):
"""A custom Avatar with an attached popover for selecting an image."""
settable = GObject.Property(type=bool, default=False)
def __init__(self):
"""Initialize our settable icon."""
super().__init__()
self._dialog = Gtk.FileDialog(title="Pick an Image",
filters=IMAGE_FILTERS)
self._long_press = Gtk.GestureLongPress()
self._long_press.connect("pressed", self.__long_press)
self.add_controller(self._long_press)
def __async_ready(self, dialog: Gtk.FileDialog, task: Gio.Task) -> None:
try:
file = dialog.open_finish(task)
path = pathlib.Path(file.get_path())
texture.CACHE.drop(path)
self.filepath = path
except GLib.Error:
self.filepath = None
def __long_press(self, gesture: Gtk.GestureLongPress,
x: float, y: float) -> None:
"""Handle a click event."""
if self.settable:
if self.filepath is not None:
file = Gio.File.new_for_path(str(self.filepath))
self._dialog.set_initial_file(file)
self._dialog.open(self.get_ancestor(Gtk.Window), None,
self.__async_ready)