python-gtk-pygobject icon indicating copy to clipboard operation
python-gtk-pygobject copied to clipboard

Drag and drop widgets

Open swanux opened this issue 3 years ago • 2 comments

I came across your repo recently, and finally found an example drag and drop implementation in GTK4 - also, the whole repo is impressive.

Though, I tried to modify the example, so it supports dragging and dropping the widgets (for example to reorder the labels) but no luck so far. Do you have any idea for this scenario?

swanux avatar May 19 '22 17:05 swanux

Hello @swanux.

Thank you very much!

Over the weekend I will try to recreate the scenario you described.

The only reference I could find was an example in C in the Gtk 4 demo, I'll try to recreate it in Python:

gtk4-drag-and-drop

If you have any tips or tutorials, be sure to share them here 😁.

natorsc avatar May 19 '22 22:05 natorsc

Hello @natorsc

Thank you for the response.

I took a look into the demo app, and translated the part of the code I thought may be relevant (not a proper translation, just a quick overview). Here it is:

C:

static void
canvas_item_init (CanvasItem *item)
{
  char *text;
  char *id;
  GdkRGBA rgba;
  GtkDropTarget *dest;
  GtkGesture *gesture;
  GType types[2] = { GDK_TYPE_RGBA, G_TYPE_STRING };

  n_items++;

  text = g_strdup_printf ("Item %d", n_items);
  item->label = gtk_label_new (text);
  gtk_widget_add_css_class (item->label, "canvasitem");
  g_free (text);

  item->fixed = gtk_fixed_new ();
  gtk_widget_set_parent (item->fixed, GTK_WIDGET (item));
  gtk_fixed_put (GTK_FIXED (item->fixed), item->label, 0, 0);

  gtk_widget_add_css_class (item->label, "frame");

  id = g_strdup_printf ("item%d", n_items);
  gtk_widget_set_name (item->label, id);
  g_free (id);

  if (theme_is_dark ())
    gdk_rgba_parse (&rgba, "blue");
  else
    gdk_rgba_parse (&rgba, "yellow");

  set_color (item, &rgba);

  item->angle = 0;

  dest = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_COPY);
  gtk_drop_target_set_gtypes (dest, types, G_N_ELEMENTS (types));
  g_signal_connect (dest, "drop", G_CALLBACK (item_drag_drop), NULL);
  gtk_widget_add_controller (GTK_WIDGET (item->label), GTK_EVENT_CONTROLLER (dest));

  gesture = gtk_gesture_rotate_new ();
  g_signal_connect (gesture, "angle-changed", G_CALLBACK (angle_changed), NULL);
  g_signal_connect (gesture, "end", G_CALLBACK (rotate_done), NULL);
  gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));

  gesture = gtk_gesture_click_new ();
  g_signal_connect (gesture, "released", G_CALLBACK (click_done), NULL);
  gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));
}

Python:

def canvas_item_init(item):
    text = "Item %d" % n_items
    item.label = Gtk.Label(text)
    item.label.get_style_context().add_class("canvasitem")
    item.fixed = Gtk.Fixed()
    item.fixed.set_parent(item)
    item.fixed.put(item.label, 0, 0)
    item.label.get_style_context().add_class("frame")
    id = "item%d" % n_items
    item.label.set_name(id)
    if theme_is_dark():
        rgba = Gdk.RGBA()
        rgba.parse("blue")
    else:
        rgba = Gdk.RGBA()
        rgba.parse("yellow")
    set_color(item, rgba)
    item.angle = 0
    dest = Gtk.DropTarget.new(GObject.TYPE_INVALID, Gdk.DragAction.COPY)
    dest.set_gtypes([Gdk.RGBA, GObject.TYPE_STRING])
    dest.connect("drop", item_drag_drop)
    item.label.add_controller(dest)
    gesture = Gtk.GestureRotate.new()
    gesture.connect("angle-changed", angle_changed)
    gesture.connect("end", rotate_done)
    item.add_controller(gesture)
    gesture = Gtk.GestureClick.new()
    gesture.connect("released", click_done)
    item.add_controller(gesture)

Also, here's an auto-generated API documentation (I find it useful overall): https://amolenaar.github.io/pgi-docgen/

Currently I believe the issue is with the Gtk.DropTarget and what type it accepts - as tested with your code I get every signal emitted, except tha drop which would be the point. Also the usual dnd highlight doesn't appear.

Edit: Here are some other resources concerning dnd in GTK4 and Python https://stackoverflow.com/questions/70921068/drag-and-drop-with-gtk4-connecting-dragsource-and-droptarget-via-contentprovide

This one for the types maybe (based on the API doc): https://stackoverflow.com/questions/24795405/gdk-type-pixbuf-in-gtk-3

swanux avatar May 20 '22 09:05 swanux