[gtk+/filesystemmodel: 13/28] add the ability to freeze the model, to bundle updates for performance



commit 77d301493a9698405e1701e43be23bf618148f99
Author: Benjamin Otte <otte gnome org>
Date:   Sun Jun 21 20:01:59 2009 +0200

    add the ability to freeze the model, to bundle updates for performance

 gtk/gtkfilesystemmodel.c |  101 +++++++++++++++++++++++++++++++++++++++++++---
 gtk/gtkfilesystemmodel.h |    2 +
 2 files changed, 97 insertions(+), 6 deletions(-)
---
diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c
index 0e014e8..8e640f9 100644
--- a/gtk/gtkfilesystemmodel.c
+++ b/gtk/gtkfilesystemmodel.c
@@ -53,7 +53,7 @@ struct _FileModelNode
   guint                 index;          /* if valid, index in path - aka visible nodes before this one */
 
   guint                 visible :1;     /* if the file is currently visible */
-  guint                 values_set :1;  /* true if the set function has been called on this node */
+  guint                 frozen_add :1;  /* true if the model was frozen and the entry has not been added yet */
 
   GValue                values[1];      /* actually n_columns values */
 };
@@ -85,6 +85,11 @@ struct _GtkFileSystemModel
   gpointer              default_sort_data; /* data to pass to default sort func */
   GDestroyNotify        default_sort_destroy; /* function to call to destroy default_sort_data */
 
+  guint                 frozen;         /* number of times we're frozen */
+
+  gboolean              filter_on_thaw :1;/* set when filtering needs to happen upon thawing */
+  gboolean              sort_on_thaw :1;/* set when sorting needs to happen upon thawing */
+
   guint                 show_hidden :1; /* whether to show hidden files */
   guint                 show_folders :1;/* whether to show folders */
   guint                 show_files :1;  /* whether to show files */
@@ -179,7 +184,8 @@ node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible)
   GtkTreePath *path;
   GtkTreeIter iter;
 
-  if (node->visible == visible)
+  if (node->visible == visible ||
+      node->frozen_add)
     return;
 
   if (visible)
@@ -343,7 +349,7 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model,
   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
   FileModelNode *node;
   
-  g_return_if_fail (column < model->n_columns);
+  g_return_if_fail ((guint) column < model->n_columns);
   g_return_if_fail (ITER_IS_VALID (model, iter));
 
   node = get_node (model, ITER_INDEX (iter));
@@ -460,7 +466,15 @@ gtk_file_system_model_iface_init (GtkTreeModelIface *iface)
 static void
 gtk_file_system_model_sort (GtkFileSystemModel *model)
 {
+  if (model->frozen)
+    {
+      model->sort_on_thaw = TRUE;
+      return;
+    }
+
   g_warning ("sort not implemented");
+
+  model->sort_on_thaw = FALSE;
 }
 
 static gboolean
@@ -712,9 +726,14 @@ gtk_file_system_model_add_node (GtkFileSystemModel *model, GFile *file, GFileInf
 
   node->file = file;
   node->info = info;
+  node->frozen_add = model->frozen ? TRUE : FALSE;
 
   g_array_append_vals (model->files, node, 1);
   g_slice_free1 (NODE_SIZE (model), node);
+
+  if (!model->frozen)
+    node_set_visible (model, model->files->len -1,
+                      node_should_be_visible (model, model->files->len - 1));
 }
 
 static void
@@ -747,6 +766,7 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
 
   files = g_file_enumerator_next_files_finish (enumerator, res, &error);
 
+  _gtk_file_system_model_freeze_updates (model);
   for (walk = files; walk; walk = walk->next)
     {
       const char *name;
@@ -763,10 +783,9 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
         }
       file = g_file_get_child (model->dir, name);
       gtk_file_system_model_add_node (model, file, info);
-      node_set_visible (model, model->files->len - 1,
-                        node_should_be_visible (model, model->files->len - 1));
     }
   g_list_free (files);
+  _gtk_file_system_model_thaw_updates (model);
 
   if (files == NULL)
     {
@@ -923,11 +942,22 @@ gtk_file_system_model_refilter_all (GtkFileSystemModel *model)
 {
   guint i;
 
-  /* don't change the editable */
+  if (model->frozen)
+    {
+      model->filter_on_thaw = TRUE;
+      return;
+    }
+
+  _gtk_file_system_model_freeze_updates (model);
+
+  /* start at index 1, don't change the editable */
   for (i = 1; i < model->files->len; i++)
     {
       node_set_visible (model, i, node_should_be_visible (model, i));
     }
+
+  model->filter_on_thaw = FALSE;
+  _gtk_file_system_model_thaw_updates (model);
 }
 
 /**
@@ -1146,3 +1176,62 @@ _gtk_file_system_model_remove_editable (GtkFileSystemModel *model)
   node_set_visible (model, 0, FALSE);
 }
 
+/**
+ * _gtk_file_system_model_freeze_updates:
+ * @model: a #GtkFileSystemModel
+ *
+ * Freezes most updates on the model, so that performing multiple 
+ * operations on the files in the model do not cause any events.
+ * Use _gtk_file_system_model_thaw_updates() to resume proper 
+ * operations. It is fine to call this function multiple times as
+ * long as freeze and thaw calls are balanced.
+ **/
+void
+_gtk_file_system_model_freeze_updates (GtkFileSystemModel *model)
+{
+  g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
+
+  model->frozen++;
+}
+
+/**
+ * _gtk_file_system_model_thaw_updates:
+ * @model: a #GtkFileSystemModel
+ *
+ * Undoes the effect of a previous call to
+ * _gtk_file_system_model_freeze_updates() 
+ **/
+void
+_gtk_file_system_model_thaw_updates (GtkFileSystemModel *model)
+{
+  gboolean stuff_added;
+
+  g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
+  g_return_if_fail (model->frozen > 0);
+
+  model->frozen--;
+  if (model->frozen > 0)
+    return;
+
+  stuff_added = get_node (model, model->files->len - 1)->frozen_add;
+
+  if (model->filter_on_thaw)
+    gtk_file_system_model_refilter_all (model);
+  if (model->sort_on_thaw)
+    gtk_file_system_model_sort (model);
+  if (stuff_added)
+    {
+      guint i;
+
+      for (i = 0; i < model->files->len; i++)
+        {
+          FileModelNode *node = get_node (model, i);
+
+          if (!node->frozen_add)
+            continue;
+          node->frozen_add = FALSE;
+          node_set_visible (model, i, node_should_be_visible (model, i));
+        }
+    }
+}
+
diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h
index 89c6f6a..7df9077 100644
--- a/gtk/gtkfilesystemmodel.h
+++ b/gtk/gtkfilesystemmodel.h
@@ -61,6 +61,8 @@ void                _gtk_file_system_model_set_show_folders (GtkFileSystemModel
 							     gboolean            show_folders);
 void                _gtk_file_system_model_set_show_files   (GtkFileSystemModel *model,
 							     gboolean            show_files);
+void                _gtk_file_system_model_freeze_updates   (GtkFileSystemModel *model);
+void                _gtk_file_system_model_thaw_updates     (GtkFileSystemModel *model);
 
 typedef gboolean (*GtkFileSystemModelFilter) (GtkFileSystemModel *model,
 					      GFile              *file,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]