GtkTreeView insert / update performance through sorting

I'm having performance issues when inserting many lines into the GTK tree view (using PyGTK) - or when changing many lines. The problem is that the model seems to resort after each change (insert / modify). This causes the GUI to freeze within seconds. Exiting a model unsorted by commenting on model.set_sort_column_id(SOME_ROW_INDEX, gtk.SORT_ASCENDING) fixes these problems.

Therefore, I would like to turn off sorting while I insert or modify a model and turn it on again. Unfortunately, sorting cannot be disabled using model.set_sort_column_id(-1, gtk.SORT_ASCENDING) . Using the freeze / thaw functions also does not work:

 treeview.freeze_child_notify() try: for row in model: # ... change something in row ... finally: treeview.thaw_child_notify() 

So how can I turn off sorting? Or is there a better method for bulk inserts / modifications?


Decision

Thanks to the bobince info and links provided in his answer, I checked out some of the alternatives:

1) Dummy sorting

  tv.freeze_child_notify() sortSettings = model.get_sort_column_id() model.set_default_sort_func(lambda *unused: 0) # <-- can also use None but that is slower! # model.set_default_sort_func(lambda *unused: 1) <-- slow # model.set_default_sort_func(lambda *unused: -1) <-- crash (access violation in gtk_tree_store_move_after?!) model.set_sort_column_id(-1, gtk.SORT_ASCENDING) # change rows model.set_sort_column_id(*sortSettings) tv.thaw_child_notify() 

This reduced the time from 11 seconds to 2 seconds. Wow! But it could be better, it was only for 1000 lines.

2) Deleting a model when updating

 tv.set_model(None) # change rows tv.set_model(model) 

No noticeable difference, 11 seconds.

3) Dummy sorting and cooling generator trick from PyGTK FAQ

  def gen(): tv.freeze_child_notify() sortSettings = model.get_sort_column_id() model.set_default_sort_func(lambda *unused: 0) model.set_sort_column_id(-1, gtk.SORT_ASCENDING) i = 0 for row in rowsToChange: i += 1 # change something if i % 200 == 0: # freeze/thaw not really necessary here as sorting is wrong because of the # default sort function yield True model.set_sort_column_id(*sortSettings) tv.thaw_child_notify() yield False g = gen() if g.next(): # run once now, remaining iterations when idle gobject.idle_add(g.next) 

Result: the same estimated 2 seconds as in solution 1), but the GUI responds during this time. I prefer this method. The modulo 200 module can be modified to make the GUI more or less reactive, if necessary.

Maybe it's even possible to subclass gtk.TreeStore to get better results? I have not tried it yet, but option 3) is still good enough.

+6
bulkinsert gtk pygtk gtktreeview
source share
1 answer

Looks like you're almost there. See the FAQ for more details. In particular, you should also set default_sort_order (now you can use None , as well as dummy compare lambda in this example for better performance) to make sure that there is no sorting, and remove the model from the tree for the duration of operations.

If you have a lot of changes, you might be better off creating and installing a complete new model.

+2
source share

All Articles