In Gtk, when using Drag and Drop in a TreeView, how do I keep from dropping between rows?
-
18-09-2019 - |
Question
I'm testing a window that looks something like this:
Dragging a Tag to a Card links the Tag to the Card. So does dragging a Card to a Tag.
It's meaningless to drop a tag between two cards, or a card between two tags. I can ignore these outcomes in the Handle...DataReceived
function like this:
if (dropPos != TreeViewDropPosition.IntoOrAfter &&
dropPos != TreeViewDropPosition.IntoOrBefore)
return;
However, when dragging, the user still sees the option to insert:
How do I prevent this from happening?
Solution
You need to connect to the drag-motion
signal and change the default behaviour so it never indicates a before/after drop:
def _drag_motion(self, widget, context, x, y, etime):
drag_info = widget.get_dest_row_at_pos(x, y)
if not drag_info:
return False
path, pos = drag_info
if pos == gtk.TREE_VIEW_DROP_BEFORE:
widget.set_drag_dest_row(path, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE)
elif pos == gtk.TREE_VIEW_DROP_AFTER:
widget.set_drag_dest_row(path, gtk.TREE_VIEW_DROP_INTO_OR_AFTER)
context.drag_status(context.suggested_action, etime)
return True
OTHER TIPS
You can define different targets for tags and cards, and on the left widget accept only the target that represents the tags. Use Gtk.Drag.DestSet
method. Maybe something like:
Gtk.Drag.DestSet (widget, DestDefaults.All,
new TargetEntry[1] { new TargetEntry ("MYAPP_TAGS", TargetFlags.App, 1) },
DragAction.Default);
I tried to make the destination emit Motion events with:
Gtk.Drag.DestSet (widget, DestDefaults.Motion,
new TargetEntry[1] { new TargetEntry ("MYAPP_TAGS", TargetFlags.App, 1) },
DragAction.Default);
theoretically, if I understand it correctly, it should work. But I couldn't make it fire motion events :(