175 lines
6.5 KiB
Python
175 lines
6.5 KiB
Python
# Copyright 2022 (c) Anna Schumaker.
|
|
"""Widgets for sidebar rows."""
|
|
from gi.repository import GObject
|
|
from gi.repository import Gtk
|
|
from .title import PlaylistTitle
|
|
from .title import EditableTitle
|
|
from .icon import Icon
|
|
from .icon import Settable
|
|
from .. import db
|
|
from .. import factory
|
|
|
|
|
|
class BaseRow(Gtk.Box):
|
|
"""Base class for Row widgets."""
|
|
|
|
playlist = GObject.Property(type=db.playlist.Playlist)
|
|
name = GObject.Property(type=str)
|
|
count = GObject.Property(type=int)
|
|
|
|
|
|
class Row(BaseRow):
|
|
"""A basic row representing a playlist without extra actions."""
|
|
|
|
image = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize a sidebar Row."""
|
|
super().__init__(spacing=12, **kwargs)
|
|
self._icon = Icon(text=self.name, show_initials=True)
|
|
self._title = PlaylistTitle(title=self.name, count=self.count)
|
|
self._year = None
|
|
|
|
self.bind_property("image", self._icon, "filepath")
|
|
self.bind_property("name", self._icon, "text")
|
|
self.bind_property("name", self._title, "title")
|
|
self.bind_property("count", self._title, "count")
|
|
|
|
self.append(self._icon)
|
|
self.append(self._title)
|
|
|
|
@GObject.Property(type=int)
|
|
def year(self) -> int | None:
|
|
"""Set the year displayed in the icon."""
|
|
return self._year
|
|
|
|
@year.setter
|
|
def year(self, year: int) -> None:
|
|
digits = str(year)
|
|
self._year = year
|
|
self._icon.text = f"{digits[-2]} {digits[-1]}"
|
|
|
|
|
|
class PlaylistRow(BaseRow):
|
|
"""An advanced playlist row with extra actions for users."""
|
|
|
|
icon_name = GObject.Property(type=str)
|
|
filepath = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
|
modifiable = GObject.Property(type=bool, default=False)
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize a PlaylistRow."""
|
|
super().__init__(**kwargs)
|
|
self._icon = Settable()
|
|
self._title = EditableTitle(margin_start=12, margin_end=12)
|
|
self._delete = Gtk.Button(icon_name="big-x-symbolic",
|
|
valign=Gtk.Align.CENTER,
|
|
has_frame=False, visible=False)
|
|
|
|
self.bind_property("name", self._icon, "text")
|
|
self.bind_property("icon-name", self._icon, "icon-name")
|
|
self.bind_property("filepath", self._icon, "filepath",
|
|
GObject.BindingFlags.BIDIRECTIONAL)
|
|
self.bind_property("modifiable", self._icon, "settable")
|
|
|
|
self.bind_property("name", self._title, "title")
|
|
self.bind_property("count", self._title, "count")
|
|
self.bind_property("modifiable", self._title, "editable")
|
|
|
|
self.bind_property("modifiable", self._delete, "visible")
|
|
|
|
self._title.connect("request-rename", self.__on_rename)
|
|
self._delete.connect("clicked", self.__on_delete)
|
|
|
|
self._delete.add_css_class("emmental-delete")
|
|
|
|
self.append(self._icon)
|
|
self.append(self._title)
|
|
self.append(self._delete)
|
|
|
|
def __on_rename(self, title: EditableTitle, new_name: str) -> None:
|
|
if self.playlist is not None:
|
|
self.playlist.rename(new_name)
|
|
|
|
def __on_delete(self, button: Gtk.Button) -> None:
|
|
if self.playlist is not None:
|
|
self.playlist.delete()
|
|
|
|
|
|
class LibraryRow(BaseRow):
|
|
"""An advaced playlist row with extra actions for library management."""
|
|
|
|
enabled = GObject.Property(type=bool, default=True)
|
|
online = GObject.Property(type=bool, default=True)
|
|
scanning = GObject.Property(type=bool, default=False)
|
|
progress = GObject.Property(type=float)
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize a LibraryRow."""
|
|
super().__init__(**kwargs)
|
|
self._box = Gtk.Box()
|
|
self._overlay = Gtk.Overlay(child=self._box)
|
|
self._switch = Gtk.Switch(active=self.enabled, valign=Gtk.Align.CENTER)
|
|
self._title = PlaylistTitle(margin_start=12, margin_end=12)
|
|
self._scan = Gtk.Button(icon_name="update", has_frame=False,
|
|
valign=Gtk.Align.CENTER)
|
|
self._stop = Gtk.Button(icon_name="stop-sign-large", has_frame=False,
|
|
valign=Gtk.Align.CENTER, visible=False)
|
|
self._delete = Gtk.Button(icon_name="big-x-symbolic",
|
|
valign=Gtk.Align.CENTER, has_frame=False)
|
|
self._progress = Gtk.ProgressBar(valign=Gtk.Align.END, visible=False)
|
|
|
|
self.bind_property("enabled", self._switch, "active",
|
|
GObject.BindingFlags.BIDIRECTIONAL)
|
|
self.bind_property("online", self._switch, "sensitive")
|
|
|
|
self.bind_property("name", self._title, "title")
|
|
self.bind_property("count", self._title, "count")
|
|
self.bind_property("online", self._title, "sensitive")
|
|
self.bind_property("enabled", self._title, "sensitive")
|
|
|
|
self.bind_property("scanning", self._stop, "visible")
|
|
self.bind_property("scanning", self._scan, "visible",
|
|
GObject.BindingFlags.INVERT_BOOLEAN)
|
|
self.bind_property("scanning", self._progress, "visible")
|
|
self.bind_property("progress", self._progress, "fraction")
|
|
|
|
self._delete.connect("clicked", self.__on_button_press, "delete")
|
|
self._scan.connect("clicked", self.__on_button_press, "scan")
|
|
self._stop.connect("clicked", self.__on_button_press, "stop")
|
|
|
|
self._delete.add_css_class("emmental-delete")
|
|
self._stop.add_css_class("emmental-stop")
|
|
self._progress.add_css_class("osd")
|
|
|
|
self._box.append(self._switch)
|
|
self._box.append(self._title)
|
|
self._box.append(self._scan)
|
|
self._box.append(self._stop)
|
|
self._box.append(self._delete)
|
|
self._overlay.add_overlay(self._progress)
|
|
self.append(self._overlay)
|
|
|
|
def __on_button_press(self, button: Gtk.Button, action: str) -> None:
|
|
if self.playlist is not None:
|
|
match action:
|
|
case "delete": self.playlist.delete()
|
|
case "scan": self.playlist.scan()
|
|
case "stop": self.playlist.stop()
|
|
|
|
|
|
class TreeRow(factory.TreeRow):
|
|
"""A factory Row used for displaying individual playlists."""
|
|
|
|
def do_bind(self) -> None:
|
|
"""Bind a Playlist to this Row."""
|
|
self.child.playlist = self.item
|
|
self.bind_and_set_property("name", "name")
|
|
self.bind_and_set_property("n-tracks", "count")
|
|
self.bind_n_children(self.item.children)
|
|
self.bind_active("active")
|
|
|
|
def do_unbind(self) -> None:
|
|
"""Unbind a Playlist from this Row."""
|
|
self.child.playlist = None
|