Treeview selection and deletion in gtk3

Hi –

I’ve run into a strange situation and wonder if I’m doing something wrong. In a Gtk.TreeView that is displaying multiple lines, if I click on a line to select it and then delete the selected line (via a button that calls Gtk.TreeModel.remove) then the next line is automatically selected, and the callback connect to Gtk.TreeSelection’s “changed” signal is called twice. However, if instead I select a line via gtk.TreeSelection.select_path and then delete it, no new selection is made and the “changed” callback is called only once.

This seems odd. The only information available about the state of the system is which line is selected, but the behavior of the system depends on how that line was selected. This is making my program behave differently in situations that I think ought to be identical.

I’ve appended a simple example. Click a line in the middle of the list and then click “Delete line”, or click a line, click “Next line” to select a different one, and then click “Delete line” and you will see different output.

Am I doing something wrong? Expecting something wrong? Have I missed something that would make the two situations equivalent?

Thanks for any suggestions.

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GObject


def selectionChanged(selection):
    model, treeiter = selection.get_selected()
    if treeiter:
        print("selected treepath =", model.get_path(treeiter))
    else:
        print("selected nothing")
    
def delCB(button, treeview):
    print("delete")
    selection = treeview.get_selection()
    model, treeiter = selection.get_selected()
    if treeiter:
        model.remove(treeiter)

def nextCB(button, treeview):
    # Select the next row instead
    print("next")
    selection = treeview.get_selection()
    model, treeiter = selection.get_selected()
    if treeiter:
        path = model.get_path(treeiter).get_indices()
        path[0] = (path[0] + 1) % len(model)
        selection.select_path(Gtk.TreePath(path))
        

def run():
    window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL, title="treeview")
    vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4)
    window.add(vbox)
    window.connect("delete-event", Gtk.main_quit)

    treestore = Gtk.TreeStore(GObject.TYPE_STRING)
    treeview = Gtk.TreeView(model=treestore, headers_visible=False)
    tvcol = Gtk.TreeViewColumn()
    treeview.append_column(tvcol)
    cell = Gtk.CellRendererText()
    tvcol.pack_start(cell, expand=False)
    tvcol.set_attributes(cell, text=0)

    selection = treeview.get_selection()
    selection.connect("changed", selectionChanged)

    vbox.pack_start(treeview, expand=True, fill=True, padding=0)

    bbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=4,
                   homogeneous=True)
    vbox.pack_start(bbox, expand=False, fill=False, padding=0)

    nextbutton = Gtk.Button(label="Next line")
    nextbutton.connect("clicked", nextCB, treeview)
    bbox.pack_start(nextbutton, expand=True, fill=True, padding=0)

    delbutton = Gtk.Button(label="Delete line")
    delbutton.connect("clicked", delCB, treeview)
    bbox.pack_start(delbutton, expand=True, fill=True, padding=0)

    for x in range(10):
        treeiter = treestore.append(None)
        treestore.set_value(treeiter, 0, "Item number %d" % x)

    window.show_all()
    Gtk.main()

    
if __name__ == "__main__":
    run()

I think so.

The docs seem to match what you’re describing?

https://developer.gnome.org/gtk3/stable/GtkTreeSelection.html#GtkTreeSelection-changed

I saw that, but it doesn’t completely explain what’s happening. Whether or not the “changed” signal has been sent, the behavior of TreeModel.remove is different in the two cases. If a line is selected in a TreeView, and you delete that line from the model, what should happen to the selection in the TreeView? It seems to depend on the way in which that line was selected.

I think that relates to events that aren’t triggered when you select from code, similar to the situation you ran into with popovers? I think it was.

Anyway, maybe one of the devs could clear this up for sure. @ebassi would probably know for sure whether that’s all it is or there’s more to it.

I’ve just always accepted it and worked around it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.