@@ 2,7 2,7 @@ import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
-from gi.repository import Gtk, Adw, Gio, GLib
+from gi.repository import Gtk, Adw, Gio, GLib, Gdk
from melon.widgets.feeditem import AdaptiveFeedItem
from melon.widgets.iconbutton import IconButton
@@ 6,6 6,8 @@ from gi.repository import Gtk, Adw, GLib, Gdk
from melon.servers import Resource,Video,Playlist,Channel,Preference,PreferenceType
from melon.servers.utils import pixbuf_from_url
from melon.widgets.iconbutton import IconButton
+from melon.widgets.simpledialog import SimpleDialog
+from copy import deepcopy as copy
class PreferenceRow():
def __init__(self, pref: Preference, *args, **kwargs):
@@ 62,49 64,8 @@ class PreferenceRow():
lambda a: self.pass_to_callback(self.widget.get_value())
)
elif pref.type is PreferenceType.MULTI:
- self.widget = Adw.PreferencesRow()
- self.inner = Adw.PreferencesGroup()
- padding = 12
- self.inner.set_margin_top(padding)
- self.inner.set_margin_bottom(padding)
- self.inner.set_margin_start(padding)
- self.inner.set_margin_end(padding)
- self.widget.set_child(self.inner)
- self.inner.set_title(pref.name)
- self.inner.set_description(pref.description)
- self.children = []
- # TODO: implement functionality
- self.adder = IconButton("Add", "list-add-symbolic")
- self.inner.set_header_suffix(self.adder)
- counter = 0
- length = len(self.pref.value)
- for item in self.pref.value:
- row = Adw.ActionRow()
- row.set_title(item)
- actions = Gtk.Box()
- # move up button
- if counter > 0:
- # TODO: implement functionality
- move_up = IconButton("","go-up-symbolic")
- move_up.set_tooltip_text("Move up")
- move_up.add_css_class("circular")
- actions.append(move_up)
- if counter < length-1:
- # TODO: implement functionality
- move_down = IconButton("", "go-down-symbolic")
- move_down.set_tooltip_text("Move down")
- move_down.add_css_class("circular")
- actions.append(move_down)
- counter += 1
- # TODO: implement functionality
- remove = IconButton("", "list-remove-symbolic")
- remove.set_tooltip_text("Remove from list")
- remove.add_css_class("circular")
- actions.append(remove)
- row.add_suffix(actions)
- # store rows in seperate list to make removing them possible
- self.children.append(row)
- self.inner.add(row)
+ self.widget = MultiRow(pref)
+ self.widget.connect(lambda v: self.pass_to_callback(v))
else:
# shouldn't be reachable
self.widget = Adw.ActionRow()
@@ 117,7 78,7 @@ class PreferenceRow():
# that the callback would be called multiple times,
# because the "notify" signal might be called more than once
return
- self.current_value = value
+ self.current_value = copy(value)
if not self.callback is None:
self.callback(value)
def get_widget(self):
@@ 127,3 88,169 @@ class PreferenceRow():
def on_active(self):
if not self.callback is None:
self.callback(self.get_active())
+
+class MultiRow(Adw.PreferencesRow):
+ callback = None
+ values = []
+ def __init__(self, pref, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.pref = pref
+ self.values = copy(pref.value)
+ self.update()
+ def connect(self, cb):
+ self.callback = cb
+ def update(self):
+ self.inner = Adw.PreferencesGroup()
+ padding = 12
+ self.inner.set_margin_top(padding)
+ self.inner.set_margin_bottom(padding)
+ self.inner.set_margin_start(padding)
+ self.inner.set_margin_end(padding)
+ self.set_child(self.inner)
+ self.inner.set_title(self.pref.name)
+ self.inner.set_description(self.pref.description)
+ self.adder = IconButton("Add", "list-add-symbolic")
+ self.adder.connect("clicked", lambda x: self.open_add())
+ self.inner.set_header_suffix(self.adder)
+ counter = 0
+ length = len(self.values)
+ # create items list
+ for item in self.values:
+ row = Adw.ActionRow()
+ row.set_title(item)
+ actions = Gtk.Box()
+ # move up button
+ # not shown for first element
+ if counter > 0:
+ move_up = IconButton("","go-up-symbolic")
+ move_up.set_tooltip_text("Move up")
+ move_up.add_css_class("circular")
+ move_up.connect(
+ "clicked",
+ pass_me(self.move_up, item, counter)
+ )
+ actions.append(move_up)
+ # move down button
+ # not shown for last element
+ if counter < length-1:
+ move_down = IconButton("", "go-down-symbolic")
+ move_down.set_tooltip_text("Move down")
+ move_down.add_css_class("circular")
+ move_down.connect(
+ "clicked",
+ pass_me(self.move_down, item, counter)
+ )
+ actions.append(move_down)
+ # remove button
+ remove = IconButton("", "list-remove-symbolic")
+ remove.set_tooltip_text("Remove from list")
+ remove.add_css_class("circular")
+ remove.connect("clicked", pass_me(self.confirm_delete, item, counter))
+ actions.append(remove)
+ row.add_suffix(actions)
+ self.inner.add(row)
+ counter += 1
+ def notify(self):
+ if not self.callback is None:
+ self.callback(copy(self.values))
+ self.update()
+ def open_add(self):
+ diag = SimpleDialog()
+ diag.set_title("Add Item")
+ # preview prferences group
+ box = Adw.PreferencesGroup();
+ box.set_title("Create a new list entry")
+ box.set_description("Enter the new value here")
+ # text input
+ inp = Adw.EntryRow()
+ inp.set_title("Value")
+ box.add(inp)
+ diag.set_widget(box)
+ # place button bar in toolbar
+ bottom_bar = Gtk.Box()
+ btn_cancel = IconButton("Cancel", "process-stop-symbolic", tooltip="Do not create a new item")
+ btn_confirm = IconButton("Create", "list-add-symbolic", tooltip="Add entry to list")
+ btn_confirm.connect(
+ "clicked",
+ lambda _: many(
+ self.values.append(inp.get_text()),
+ self.notify(),
+ diag.hide())
+ )
+ btn_cancel.connect(
+ "clicked",
+ lambda x: diag.hide())
+ padding = 12
+ btn_confirm.set_vexpand(True)
+ btn_confirm.set_hexpand(True)
+ btn_confirm.set_margin_end(padding)
+ btn_confirm.set_margin_start(padding/2)
+ btn_confirm.set_margin_top(padding)
+ btn_confirm.set_margin_bottom(padding)
+ btn_cancel.set_vexpand(True)
+ btn_cancel.set_hexpand(True)
+ btn_cancel.set_margin_start(padding)
+ btn_cancel.set_margin_end(padding/2)
+ btn_cancel.set_margin_top(padding)
+ btn_cancel.set_margin_bottom(padding)
+ bottom_bar.append(btn_cancel)
+ bottom_bar.append(btn_confirm)
+ diag.toolbar_view.add_bottom_bar(bottom_bar)
+
+ diag.show()
+ def confirm_delete(self, _, item:str, counter:int):
+ diag = SimpleDialog()
+ diag.set_title("Delete")
+ # preview prferences group
+ preview = Adw.PreferencesGroup();
+ preview.set_title("Do you really want to delete this item?")
+ preview.set_description("You won't be able to restore it afterwards")
+ row = Adw.ActionRow()
+ row.set_title(item)
+ preview.add(row)
+ diag.set_widget(preview)
+ # place button bar in toolbar
+ bottom_bar = Gtk.Box()
+ btn_cancel = IconButton("Cancel", "process-stop-symbolic", tooltip="Do not remove item")
+ btn_confirm = IconButton("Delete", "list-add-symbolic", tooltip="Remove item from list")
+ btn_confirm.connect(
+ "clicked",
+ lambda _: many(
+ self.values.pop(counter),
+ self.notify(),
+ diag.hide())
+ )
+ btn_cancel.connect(
+ "clicked",
+ lambda x: diag.hide())
+ padding = 12
+ btn_confirm.set_vexpand(True)
+ btn_confirm.set_hexpand(True)
+ btn_confirm.set_margin_end(padding)
+ btn_confirm.set_margin_start(padding/2)
+ btn_confirm.set_margin_top(padding)
+ btn_confirm.set_margin_bottom(padding)
+ btn_cancel.set_vexpand(True)
+ btn_cancel.set_hexpand(True)
+ btn_cancel.set_margin_start(padding)
+ btn_cancel.set_margin_end(padding/2)
+ btn_cancel.set_margin_top(padding)
+ btn_cancel.set_margin_bottom(padding)
+ bottom_bar.append(btn_cancel)
+ bottom_bar.append(btn_confirm)
+ diag.toolbar_view.add_bottom_bar(bottom_bar)
+ diag.show()
+ pass
+ def move_up(self, _, item:str, counter:int):
+ val = self.values.pop(counter)
+ self.values.insert(counter-1, val)
+ self.notify()
+ def move_down(self, _, item:str, counter:int):
+ val = self.values.pop(counter)
+ self.values.insert(counter+1, val)
+ self.notify()
+
+def pass_me(func, *args):
+ return lambda *a: func(*a, *args)
+def many(*funcs):
+ return [funcs]