[PyGObject] Drag & Drop in a TreeView

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[PyGObject] Drag & Drop in a TreeView

Gtk+ - Apps Dev mailing list
I am totally confused about this topic. I think I miss some fundamental
understanding on how PyGObject works here.

I want to drag & drop items of one TreeView inside itself. Not other
widgets or applications. I just want to drag item 2 and drop it between
item 4 and 5.

I found some resources about this topic

This states that DnD in a TreeView is different from the rest of
PyGObject concept.
https://python-gtk-3-tutorial.readthedocs.io/en/latest/drag_and_drop.html

Some incomplete, out-dated, not working or to complex examples
http://jcoppens.com/soft/howto/pygtk_dnd/index.en.php
https://stackoverflow.com/q/29673495/4865723
https://stackoverflow.com/q/13882076/4865723

I even don't know which one of the events I really need. There are to
much. I attached a minimal example with a two column (str, str)
treeview.

Can you give me a hint and a direction on which points I should focus
on?
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Gtk+ - Apps Dev mailing list
I see attachments are removed
This is the code


#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk


class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="TreeView Drag and Drop")
        self.connect("delete-event", Gtk.main_quit)
        self.set_default_size(400, 300)

        # "model" with dummy data
        self.store = Gtk.TreeStore(str, str)
        for i in range(5):
            self.store.append(None, ['Item {}'.format(i),
        '{}'.format(i*100)]) # treeview
        self.view = Gtk.TreeView(model=self.store)
        self.add(self.view)

        # build columsn
        colA = Gtk.TreeViewColumn('Col A', Gtk.CellRendererText(),
        text=0) self.view.append_column(colA)
        colB = Gtk.TreeViewColumn('Col B', Gtk.CellRendererText(),
        text=1) self.view.append_column(colB)

        # DnD events
        self.view.connect("drag-begin", self.drag_begin)
        self.view.connect("drag-data-get", self.drag_data_get)
        self.view.connect("drag-drop", self.drag_drop)
        self.view.connect("drag-data-delete", self.drag_data_delete)
        self.view.connect("drag-data-received", self.drag_data_received)
        self.view.connect("drag-end", self.drag_end)

        target_entry = Gtk.TargetEntry.new('text/uri-list', 2, 0)
        self.view.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
            [target_entry], Gdk.DragAction.DEFAULT|Gdk.DragAction.MOVE)
        self.view.enable_model_drag_dest([target_entry],
                Gdk.DragAction.DEFAULT|Gdk.DragAction.MOVE)

    def drag_begin(self, treeview, context):
        print('== Drag started')

    def drag_data_get(self, treeview, context, data, info, time):
        print('== Drag data requested by destination')

    def drag_drop(self, treeview, context, selection, info, time):
        print('== Drag data droped')

    def drag_data_received(self, treeview, context, x, y, selection,
    info, time): print('== Drag data received')

    def drag_end(self, treeview, context):
        print('== Drag data end')

    def drag_data_delete(self, treeview, context):
        print('== Drag data delete')

win = MainWindow()
win.show_all()
Gtk.main()
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Reuben Rissler
In reply to this post by Gtk+ - Apps Dev mailing list
On 07/22/2018 04:26 PM, c.buhtz--- via gtk-app-devel-list wrote:
> I am totally confused about this topic. I think I miss some fundamental
> understanding on how PyGObject works here.
>
> I want to drag & drop items of one TreeView inside itself. Not other
> widgets or applications. I just want to drag item 2 and drop it between
> item 4 and 5.
<snip>

This is how I have done it in the past. Note, I do not proclaim
spectacular or Pythonic code, and would humbly accept any corrections
and/or better ways to accomplish this. It seems to me there should be a
way to let the TreeView do this work itself, but alas, I have not found
it yet.



#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk


class MainWindow(Gtk.Window):

     def __init__(self):
         Gtk.Window.__init__(self, title="TreeView Drag and Drop")
         self.connect("delete-event", Gtk.main_quit)
         self.set_default_size(400, 300)

         # "model" with dummy data
         self.store = Gtk.TreeStore(str, str)
         for i in range(5):
             self.store.append(None, ['Item {}'.format(i),
'{}'.format(i*100)]) # treeview
         self.view = Gtk.TreeView(model=self.store)
         self.add(self.view)

         # build columsn
         colA = Gtk.TreeViewColumn('Col A', Gtk.CellRendererText(), text=0)
         self.view.append_column(colA)
         colB = Gtk.TreeViewColumn('Col B', Gtk.CellRendererText(), text=1)
         self.view.append_column(colB)

         # DnD events
         self.view.connect("drag-data-received", self.drag_data_received)
         self.view.connect("drag-data-get", self.drag_data_get)

         target_entry = Gtk.TargetEntry.new('text/plain', 2, 0)
self.view.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,[target_entry],
Gdk.DragAction.DEFAULT|Gdk.DragAction.MOVE)
self.view.enable_model_drag_dest([target_entry],Gdk.DragAction.DEFAULT|Gdk.DragAction.MOVE)

     def drag_data_get (self, treeview, drag_context, data, info, time):
         model, path = treeview.get_selection().get_selected_rows()
         data.set_text(str(path[0]), -1)

     def drag_data_received (self, treeview, drag_context, x,y,
data,info, time):
         store = treeview.get_model()
         source_path = data.get_text()
         source_iter = store.get_iter(source_path)
         dest_path = self.view.get_dest_row_at_pos(x, y)
         if dest_path != None:
             dest_iter = store.get_iter(dest_path[0])
             if dest_path[1] == Gtk.TreeViewDropPosition.BEFORE:
                 store.move_before(source_iter, dest_iter)
             else:
                 store.move_after(source_iter, dest_iter)
         treeview.emit_stop_by_name("drag-data-received")

win = MainWindow()
win.show_all()
Gtk.main()

_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Gtk+ - Apps Dev mailing list
Dear Reuben

On 2018-07-23 08:03 Reuben Rissler <[hidden email]> wrote:
> This is how I have done it in the past. Note, I do not proclaim
> spectacular or Pythonic code, and would humbly accept any corrections
> and/or better ways to accomplish this. It seems to me there should be
> a way to let the TreeView do this work itself, but alas, I have not
> found it yet.

Your code works for me - thank you very much. But I also have the
question if anyone here could improve it or show a more easier and
elegant way.
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Colomban Wendling-3
Le 27/07/2018 à 23:05, c.buhtz--- via gtk-app-devel-list a écrit :

> Dear Reuben
>
> On 2018-07-23 08:03 Reuben Rissler <[hidden email]> wrote:
>> This is how I have done it in the past. Note, I do not proclaim
>> spectacular or Pythonic code, and would humbly accept any corrections
>> and/or better ways to accomplish this. It seems to me there should be
>> a way to let the TreeView do this work itself, but alas, I have not
>> found it yet.
>
> Your code works for me - thank you very much. But I also have the
> question if anyone here could improve it or show a more easier and
> elegant way.

If it's only for reordering the elements in the tree view, you can use
the built-in Gtk.TreeView.set_reorderable() method [1], and you're all
set.  You get inserted/deleted signals for moved rows so you can know
when and how things changed if needed, and the underlying model is also
changing accordingly.

Regards,
Colomban

[1]
https://developer.gnome.org/gtk3/stable/GtkTreeView.html#gtk-tree-view-set-reorderable
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Reuben Rissler

> If it's only for reordering the elements in the tree view, you can use
> the built-in Gtk.TreeView.set_reorderable() method [1], and you're all
> set.  You get inserted/deleted signals for moved rows so you can know
> when and how things changed if needed, and the underlying model is also
> changing accordingly.
Of course. Thank you very much, Colomban. It is unbelievable how
complicated I can make simple things.

Cheers,
Reuben
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: [PyGObject] Drag & Drop in a TreeView

Gtk+ - Apps Dev mailing list
In reply to this post by Colomban Wendling-3
Dear Colomban,

thanks for your great hint.

> You get inserted/deleted signals for moved rows so you can know
> when and how things changed if needed

This signals are also emited when I manually insert and delete data in
the model. How do I know if a insert/delete signal was caused by a drag
and drop "event"?

One workaround in my mind would be to do
Gtk.TreeView.set_reordable(False) when manipulating the model manualy
(without drag and drop).

Do you see another more elegant way?
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list