170 lines
6.0 KiB
Python
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())
|