115 lines
4.2 KiB
Python
115 lines
4.2 KiB
Python
# Copyright 2022 (c) Anna Schumaker.
|
|
"""Helper widgets for sidebar rows titles."""
|
|
from gi.repository import GObject
|
|
from gi.repository import Pango
|
|
from gi.repository import Gtk
|
|
|
|
|
|
class Title(Gtk.Box):
|
|
"""Row Title and Subtitle."""
|
|
|
|
title = GObject.Property(type=str)
|
|
subtitle = GObject.Property(type=str)
|
|
|
|
def __init__(self, title: str = "", subtitle: str = "", **kwargs):
|
|
"""Initialize a row Title widget."""
|
|
super().__init__(orientation=Gtk.Orientation.VERTICAL,
|
|
title=title, subtitle=subtitle, tooltip_text=title,
|
|
hexpand=True, valign=Gtk.Align.CENTER,
|
|
margin_top=6, margin_bottom=6, **kwargs)
|
|
self._title = Gtk.Label(label=self.title, xalign=0,
|
|
ellipsize=Pango.EllipsizeMode.END)
|
|
self._subtitle = Gtk.Label(label=self.subtitle, xalign=0,
|
|
ellipsize=Pango.EllipsizeMode.END)
|
|
|
|
self._title.add_css_class("header")
|
|
self._subtitle.add_css_class("caption")
|
|
|
|
self.bind_property("title", self, "tooltip-text")
|
|
self.bind_property("title", self._title, "label")
|
|
self.bind_property("subtitle", self._subtitle, "label")
|
|
|
|
self.append(self._title)
|
|
self.append(self._subtitle)
|
|
|
|
|
|
class PlaylistTitle(Title):
|
|
"""A title widget for displaying playlist size."""
|
|
|
|
count = GObject.Property(type=int)
|
|
|
|
def __init__(self, title: str = "", **kwargs):
|
|
"""Initialize a Playlist Title widget."""
|
|
super().__init__(title=title, subtitle="-- tracks", **kwargs)
|
|
self.connect("notify::count", self.__update_subtitle)
|
|
|
|
def __update_subtitle(self, title: Title, param) -> None:
|
|
s_count = "s" if self.count != 1 else ""
|
|
self.subtitle = f"{self.count} track{s_count}"
|
|
|
|
|
|
class EditableTitle(Gtk.Stack):
|
|
"""A Title widget and an Entry for handling renames."""
|
|
|
|
title = GObject.Property(type=str)
|
|
count = GObject.Property(type=int)
|
|
editable = GObject.Property(type=bool, default=False)
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize a row EditableTitle widget."""
|
|
super().__init__(**kwargs)
|
|
self._title = PlaylistTitle(title=self.title, count=self.count)
|
|
self._entry = Gtk.Text(text=self.title)
|
|
self._long_press = Gtk.GestureLongPress()
|
|
self._trigger = Gtk.ShortcutTrigger.parse_string("Escape")
|
|
self._action = Gtk.CallbackAction.new(self.__cancel_editing)
|
|
self._cancel = Gtk.Shortcut.new(self._trigger, self._action)
|
|
self._shortcut = Gtk.ShortcutController()
|
|
|
|
self._shortcut.add_shortcut(self._cancel)
|
|
|
|
self.bind_property("title", self._title, "title")
|
|
self.bind_property("title", self._entry, "text")
|
|
self.bind_property("count", self._title, "count")
|
|
|
|
self._long_press.connect("pressed", self.__long_press)
|
|
self._entry.connect("activate", self.__entry_activated)
|
|
self._entry.connect("notify::has-focus", self.__focus_change)
|
|
|
|
self.add_child(self._title)
|
|
self.add_child(self._entry)
|
|
self.add_controller(self._long_press)
|
|
self.add_controller(self._shortcut)
|
|
self.add_css_class("linked")
|
|
|
|
def __long_press(self, gesture: Gtk.GestureLongPress,
|
|
x: float, y: float) -> None:
|
|
self.editing = True
|
|
|
|
def __entry_activated(self, entry: Gtk.Text) -> None:
|
|
self.emit("request-rename", entry.get_text())
|
|
|
|
def __focus_change(self, text: Gtk.Text, param) -> None:
|
|
self.editing = text.has_focus()
|
|
|
|
def __cancel_editing(self, title, *args) -> None:
|
|
self.editing = False
|
|
|
|
@GObject.Property
|
|
def editing(self) -> bool:
|
|
"""Get if we are currently editing the label."""
|
|
return self.get_visible_child() == self._entry
|
|
|
|
@editing.setter
|
|
def editing(self, newval: bool) -> None:
|
|
if self.editable and newval:
|
|
self.set_visible_child(self._entry)
|
|
self._entry.grab_focus()
|
|
else:
|
|
self.set_visible_child(self._title)
|
|
|
|
@GObject.Signal(arg_types=(str,))
|
|
def request_rename(self, new_name: str):
|
|
"""Signal that the user has entered new text."""
|
|
self.editing = False
|