tobias47n9e
tobias47n9e

Reputation: 2231

Gtk TreeView paste after and below a selected item

Is there a good way of pasting items after or below an item in a Gtk TreeView. Is it even possible to do that with one function? I made this self-contained example, but I am not sure what best-practices for this behavior should be. Is there maybe a way to deselect the TreeView and then paste at the end if nothing is selected?

from gi.repository import Gtk, Gdk
import json

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_border_width(10)
        self.set_default_size(400, 300)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(vbox)

        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        button = Gtk.Button("Cut")
        button.connect("clicked", self.on_cut_clicked)
        hbox.pack_start(button, True, True, 0)

        button = Gtk.Button(stock=Gtk.STOCK_COPY)
        button.connect("clicked", self.on_copy_clicked)
        hbox.pack_start(button, True, True, 0)

        button = Gtk.Button(stock=Gtk.STOCK_PASTE)
        button.connect("clicked", self.on_paste_clicked)
        hbox.pack_start(button, True, True, 0)
        vbox.add(hbox)

        self.store = Gtk.TreeStore(bool, str)
        self.view = Gtk.TreeView(model=self.store)
        vbox.add(self.view)

        renderer_toggle = Gtk.CellRendererToggle()
        column_toggle = Gtk.TreeViewColumn("", renderer_toggle, active=0)
        renderer_toggle.connect("toggled", self.on_toggled)
        self.view.append_column(column_toggle)

        renderer_name = Gtk.CellRendererText()
        column_name = Gtk.TreeViewColumn("Name", renderer_name, text=1)
        self.view.append_column(column_name)

        self.add_test_data()

    def add_test_data(self):
        parent = self.store.append(None, [True, "Item 1"])
        self.store.append(parent, [True, "Item 2"])
        self.store.append(None, [True, "Item 3"])
        self.store.append(None, [True, "Item 4"])

    def on_toggled(self, cellrenderer, path):
        self.store[path][0] = not self.store[path][0]

    def on_cut_clicked(self, button):
        """Ignores children of selection"""
        self.on_copy_clicked(None)
        selection = self.view.get_selection()
        model, row_list = selection.get_selected_rows()
        itr = model.get_iter(row_list[0])
        model.remove(itr)

    def on_copy_clicked(self, button):
        """Ignores children of selection"""
        selection = self.view.get_selection()
        model, row_list = selection.get_selected_rows()
        if len(row_list) == 0:
            return

        liste = []
        liste.append("TreeViewRow")
        for row in row_list:
            path = model[row]
            liste.append([path[0], path[1]])

        data = json.dumps(liste)
        self.clipboard.set_text(data, -1)

    def on_paste_clicked(self, button):
        """Ignores children of selection"""
        text = self.clipboard.wait_for_text()
        try:
            parse = json.loads(text)
            json_str = True
        except:
            print("Not JSON")
            json_str = False
        if text != None and json_str == True:

            if parse[0] == "TreeViewRow":
                selection = self.view.get_selection()
                model, row_list = selection.get_selected_rows()
                itr = model.get_iter(row_list[0])
                self.store.append(itr, parse[1])
        else:
            print("Could not paste.")

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

Upvotes: 0

Views: 132

Answers (1)

jcoppens
jcoppens

Reputation: 5440

Is there a good way of pasting items after or below an item in a Gtk TreeView. Is it even possible to do that with one function?

Not with a single function. Also, it doesn't work well if you have multiple selection enabled, because then you normally don't want to insert after the first of multiple selected rows.

Is there maybe a way to deselect the TreeView and then paste at the end if nothing is selected?

'Behaviour' of a program isn't really a question of best practices, but of how you want a program to behave. To accept several different 'styles', the functions are subdivided in several steps. I think the intuitive steps would be:

  • self.view.get_selection()
  • selection.get_selected()
  • insert_after

If get_selected returns itr == None, then you can just use append(None...), so the new row will be appended at the very end.

Upvotes: 1

Related Questions