Hi,
I have managed to implement this with GtkColumnView in python. It’s obviously not very pretty but I think it is enough to get an idea of how this could be implemented. I used this blog post for the initial concept: .
Here is the script:
#!/usr/bin/python3
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, Gio, Gdk, Pango, GObject, GLib
from random import randint as ran
import random, string
class Test(GObject.Object):
def __init__(self, track):
super().__init__()
self._track=track
self._string=''.join(random.choice(string.ascii_letters) for i in range(20)).strip().lower()
sec=str(ran(0,60))
minu=str(ran(2,10))
self._time=f"{minu.zfill(2)}:{sec.zfill(2)}"
def get_string(self):
return self._string
def get_time(self):
return self._time
def get_track(self):
return str(self._track)
class Scroll(Gtk.ScrolledWindow):
def __init__(self):
super().__init__()
self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
def drop(control, origin_pos, x, y, dest_pos):
height=control.get_widget().get_allocated_height()
obj=glist.get_item(origin_pos)
glist.remove(origin_pos)
if origin_pos < dest_pos:
pos=dest_pos-1
else:
pos=dest_pos
if y < height//2: # insert above
glist.insert(pos, obj)
else: # insert below
glist.insert(pos+1, obj)
def setup(factory, item, xalign, chars):
label=Gtk.Label(xalign=xalign, width_chars=chars, ellipsize=Pango.EllipsizeMode.END, valign=Gtk.Align.FILL, vexpand=True)
item.set_child(label)
def bind0(factory, item):
label=item.get_child()
label.set_label(item.get_item().get_track())
def bind1(factory, item):
label=item.get_child()
p=label.get_parent()
dt=Gtk.DropTarget()
ds=Gtk.DragSource()
p.add_controller(ds)
p.add_controller(dt)
dt.set_actions(Gdk.DragAction.COPY)
dt.set_gtypes((int,))
c=Gdk.ContentProvider.new_for_value(item.get_position())
ds.set_content(c)
dt.connect("drop", drop, item.get_position())
label.set_label(item.get_item().get_string())
def bind2(factory, item):
label=item.get_child()
label.set_label(item.get_item().get_time())
l=Gtk.ColumnView(hexpand=True, single_click_activate=True)
l.add_css_class("rich-list")
c0=Gtk.ColumnViewColumn(title="Nr.")
f0=Gtk.SignalListItemFactory()
f0.connect("setup", setup, 1, 3)
f0.connect("bind", bind0)
c0.set_factory(f0)
l.append_column(c0)
c1=Gtk.ColumnViewColumn(title="Titel", expand=True)
f1=Gtk.SignalListItemFactory()
f1.connect("setup", setup, 0, -1)
f1.connect("bind", bind1)
c1.set_factory(f1)
l.append_column(c1)
c2=Gtk.ColumnViewColumn(title="Länge")
f2=Gtk.SignalListItemFactory()
f2.connect("setup", setup, 1, -1)
f2.connect("bind", bind2)
c2.set_factory(f2)
l.append_column(c2)
def drop2(control, origin_pos, x, y):
obj=glist.get_item(origin_pos)
glist.remove(origin_pos)
glist.append(obj)
dt=Gtk.DropTarget()
l.add_controller(dt)
dt.set_actions(Gdk.DragAction.COPY)
dt.set_gtypes((int,))
dt.connect("drop", drop2)
glist=Gio.ListStore.new(Test)
for i in range(11):
glist.append(Test(i))
model=Gtk.SingleSelection(model=glist)
l.set_model(model)
self.set_child(l)
def on_activate(app):
s=Scroll()
win=Gtk.ApplicationWindow(application=app)
win.set_child(s)
win.present()
app=Gtk.Application(application_id="org.test.popover")
app.connect("activate", on_activate)
app.run(None)
I hope this helps.