emmental/playlist/sort.py

170 lines
6.0 KiB
Python

# Copyright 2021 (c) Anna Schumaker.
from gi.repository import GObject
from gi.repository import Gtk
class UpDownBox(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self)
self.append(Gtk.Button.new_from_icon_name("go-up-symbolic"))
self.append(Gtk.Button.new_from_icon_name("go-down-symbolic"))
self.add_css_class("linked")
self.get_first_child().connect("clicked", self.clicked, "move-up")
self.get_last_child().connect("clicked", self.clicked, "move-down")
self.get_first_child().set_sensitive(False)
self.get_last_child().set_sensitive(False)
def set_active(self, active, first, last):
self.get_first_child().set_sensitive(active and not first)
self.get_last_child().set_sensitive(active and not last)
def clicked(self, button, signal):
self.emit(signal)
@GObject.Signal
def move_up(self): pass
@GObject.Signal
def move_down(self): pass
class DirectionButton(Gtk.Button):
def __init__(self):
Gtk.Button.__init__(self, sensitive=False)
self.set_icon_name("view-sort-ascending")
def set_direction(self, direction, active):
sort = "ascending" if direction == "ASC" else "descending"
self.set_icon_name(f"view-sort-{sort}")
self.set_sensitive(active)
class FieldLabel(Gtk.Label):
def __init__(self):
Gtk.Label.__init__(self, sensitive=False, hexpand=True)
def set_field(self, field, active):
self.set_sensitive(active)
self.set_text({ "tracks.number" : "Track Number",
"tracks.title" : "Track Title",
"tracks.length" : "Track Length",
"artists.sort" : "Artist Name",
"albums.sort" : "Album Name",
"discs.subtitle" : "Disc Subtitle",
"albums.release" : "Release Date",
"tracks.playcount" : "Play Count",
"tracks.lastplayed" : "Last Played",
"playlist_map.rowid" : "Order Added"}.get(field, field))
def get_field(self):
text = self.get_text()
return { "Track Number" : "tracks.number",
"Track Title" : "tracks.title",
"Track Length" : "tracks.length",
"Artist Name" : "artists.sort",
"Album Name" : "albums.sort",
"Disc Subtitle" : "discs.subtitle",
"Release Date" : "albums.release",
"Play Count" : "tracks.playcount",
"Last Played" : "tracks.lastplayed",
"Order Added" : "playlist_map.rowid"}.get(text, text)
class SortRow(Gtk.Box):
def __init__(self):
Gtk.Box.__init__(self, spacing=5)
self.switch = Gtk.Switch(valign=Gtk.Align.CENTER)
self.label = FieldLabel()
self.direction = DirectionButton()
self.updown = UpDownBox()
self.append(self.switch)
self.append(self.label)
self.append(self.direction)
self.append(self.updown)
self.switch.connect("notify::active", self.switch_active)
self.direction.connect("clicked", self.reverse)
self.updown.connect("move-up", self.moved_up)
self.updown.connect("move-down", self.moved_down)
def set_item(self, text, index, n_active):
(field, direction) = text.split()
self.switch.set_active(index < n_active)
self.switch.set_sensitive("rowid" not in field)
self.label.set_field(field, index < n_active)
self.direction.set_direction(direction, index < n_active)
self.updown.set_active(index < n_active, index == 0,
index == n_active - 1)
def switch_active(self, switch, param): self.emit("switched", switch.get_active())
def reverse(self, button): self.emit("reversed")
def moved_up(self, button): self.emit("move-up")
def moved_down(self, button): self.emit("move-down")
@GObject.Signal(arg_types=(bool,))
def switched(self, switch): pass
@GObject.Signal
def reversed(self): pass
@GObject.Signal
def move_up(self): pass
@GObject.Signal
def move_down(self): pass
class Factory(Gtk.SignalListItemFactory):
def __init__(self, model):
self.model = model
Gtk.SignalListItemFactory.__init__(self)
self.connect("setup", self.setup)
self.connect("bind", self.bind)
self.connect("unbind", self.unbind)
self.connect("teardown", self.teardown)
def setup(self, factory, listitem):
listitem.set_child(SortRow())
def bind(self, factory, listitem):
child = listitem.get_child()
child.set_item(listitem.get_item().get_string(),
listitem.get_position(),
self.model.get_n_enabled())
child.connect("switched", self.row_switched)
child.connect("reversed", self.row_reversed)
child.connect("move-up", self.move_row_up)
child.connect("move-down", self.move_row_down)
def unbind(self, factory, listitem):
child = listitem.get_child()
child.disconnect_by_func(self.row_switched)
child.disconnect_by_func(self.row_reversed)
child.disconnect_by_func(self.move_row_up)
child.disconnect_by_func(self.move_row_down)
def teardown(self, factory, listitem):
listitem.set_child(None)
def row_switched(self, row, enabled):
field = row.label.get_field()
if enabled:
self.model.enable(field)
index = self.model.get_enabled_model().get_index(field)
else:
index = self.model.get_enabled_model().get_index(field)
self.model.disable(field)
if index > 0:
self.model.emit("items-changed", index - 1, 1, 1)
def row_reversed(self, row):
self.model.get_enabled_model().reverse(row.label.get_field())
def move_row_up(self, row):
self.model.get_enabled_model().move_up(row.label.get_field())
def move_row_down(self, row):
self.model.get_enabled_model().move_down(row.label.get_field())