How to temporarily suspend sorting in a sorted liststore?

Hi all,

Please consider the following testcode consisting of a simple window with a listview widget. In the code I fill the corresponding liststore with 20000 entries. In one glade file (testwsort.glade) I put a TreeModelSort between the liststore and the listview.

#include <gtk/gtk.h>
int main(int argc, char **argv) {
   gtk_init(&argc, &argv);
#ifdef _WSORT
   GtkBuilder *builder = gtk_builder_new_from_file("testwsort.glade");
#else
   GtkBuilder *builder = gtk_builder_new_from_file("test.glade");
#endif
   GtkWindow *main_window = NULL;
   main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main_window"));
   GtkListStore *liststore = GTK_LIST_STORE(gtk_builder_get_object(builder, "liststore"));
   GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "column"));
   GtkCellRenderer *textrenderer = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "textrenderer"));
   gtk_tree_view_column_add_attribute(column, textrenderer, "text", 0); 
   for (unsigned int i=0; i<=20000; i++) {
      GtkTreeIter iter;
      gtk_list_store_append(liststore, &iter);
      gtk_list_store_set(liststore, &iter, 0, i, -1);
   }   
   gtk_builder_connect_signals(builder, NULL);
   gtk_widget_show(GTK_WIDGET(main_window));
   gtk_main();
   return 0;
}
void on_main_window_destroy(GtkWidget window, gpointer user_data) {
   gtk_main_quit();
}

As well the the two glade files:
test.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkListStore" id="liststore">
    <columns>
      <!-- column-name column -->
      <column type="guint"/>
    </columns>
  </object>
  <object class="GtkWindow" id="main_window">
    <property name="can_focus">False</property>
    <property name="default_width">100</property>
    <property name="default_height">100</property>
    <signal name="destroy" handler="on_main_window_destroy" swapped="no"/>
    <child type="titlebar">
      <placeholder/>
    </child>
    <child>
      <object class="GtkScrolledWindow">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="shadow_type">in</property>
        <child>
          <object class="GtkTreeView" id="treeview">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="model">liststore</property>
            <child internal-child="selection">
              <object class="GtkTreeSelection"/>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="column">
                <property name="title" translatable="yes">Whatever</property>
                <child>
                  <object class="GtkCellRendererText" id="textrenderer"/>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

testwsort.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkListStore" id="liststore">
    <columns>
      <!-- column-name column -->
      <column type="guint"/>
    </columns>
  </object>
  <object class="GtkTreeModelSort" id="treemodelsort">
    <property name="model">liststore</property>
  </object>
  <object class="GtkWindow" id="main_window">
    <property name="can_focus">False</property>
    <property name="default_width">100</property>
    <property name="default_height">100</property>
    <signal name="destroy" handler="on_main_window_destroy" swapped="no"/>
    <child type="titlebar">
      <placeholder/>
    </child>
    <child>
      <object class="GtkScrolledWindow">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="shadow_type">in</property>
        <child>
          <object class="GtkTreeView" id="treeview">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="model">treemodelsort</property>
            <child internal-child="selection">
              <object class="GtkTreeSelection"/>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="column">
                <property name="title" translatable="yes">Whatever</property>
                <child>
                  <object class="GtkCellRendererText" id="textrenderer"/>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

I compiled the c-code in two ways, such that each glade file gets used once:

gcc `pkg-config --cflags gtk+-3.0` -o test.x test.c `pkg-config --libs gtk+-3.0` -rdynamic
gcc -D_WSORT `pkg-config --cflags gtk+-3.0` -o testwsort.x test.c `pkg-config --libs gtk+-3.0` -rdynamic

When executing the programs you will find that the test.x starts up in under a second, while the testwsort.x needs about 20s (on my arguably slow setup).
If I understood it correctly the one with the ModelSort resorts the entire list, after any entry is added to the list. Since I am adding all Items at the same time, and only need them sorted after all items are added, I was wondering whether there was a way to temporarily suspend the sorting.
The idea is, to make the listview behave like without the ModelSort, then add all the elements, and after that to reactivate the ModelSort.
Any help would be appreciated.

Thanks a lot,
Felix

I might have found a solution, but it feels more like a dirty hack. It would be nice, if somebody could review it.
I reconnect the view directly to the list-store and delete the ModelSort with a g_object_unref(treemodelsort). Then I add all the elements, then I create a new Model sort and restore the connection from the beginning.
Here is the code (The glade files are unchanged):

#include <gtk/gtk.h>
int main(int argc, char **argv) {
   gtk_init(&argc, &argv);
#ifdef _WSORT
   GtkBuilder *builder = gtk_builder_new_from_file("testwsort.glade");
#else
   GtkBuilder *builder = gtk_builder_new_from_file("test.glade");
#endif
   GtkWindow *main_window = NULL;
   main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main_window"));
   GtkListStore *liststore = GTK_LIST_STORE(gtk_builder_get_object(builder, "liststore"));
   GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "column"));
   GtkTreeView *treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
#ifdef _WSORT
   GtkTreeModelSort *treemodelsort = GTK_TREE_MODEL_SORT(gtk_builder_get_object(builder, "treemodelsort"));
#endif
   GtkCellRenderer *textrenderer = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "textrenderer"));
   gtk_tree_view_column_add_attribute(column, textrenderer, "text", 0); 
#ifdef _WSORT
   gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(liststore));
   g_object_unref(treemodelsort);
#endif
   for (unsigned int i=0; i<=20000; i++) {
      GtkTreeIter iter;
      gtk_list_store_append(liststore, &iter);
      gtk_list_store_set(liststore, &iter, 0, i, -1);
   }   
#ifdef _WSORT
   treemodelsort = GTK_TREE_MODEL_SORT(gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(liststore)));
   gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(treemodelsort));
#endif
   gtk_builder_connect_signals(builder, NULL);
   gtk_widget_show(GTK_WIDGET(main_window));
   gtk_main();
   return 0;
}
void on_main_window_destroy(GtkWidget window, gpointer user_data) {
   gtk_main_quit();
}

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