]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreemodelsort.c
Have the unit test check if the filter model emits the right signals
[~andy/gtk] / gtk / gtktreemodelsort.c
index 8376369c5eb7ef7cfbd4efdaa5aed4284737f6d5..4525bca8b1a7617bbabcdc9956cdc9ac707ecf14 100644 (file)
@@ -37,7 +37,7 @@
  * we warned you and we're not liable for any head injuries.
  */
 
-#include <config.h>
+#include "config.h"
 #include <string.h>
 
 #include "gtktreemodelsort.h"
@@ -45,6 +45,7 @@
 #include "gtktreestore.h"
 #include "gtktreedatalist.h"
 #include "gtkintl.h"
+#include "gtkprivate.h"
 #include "gtktreednd.h"
 #include "gtkalias.h"
 
@@ -100,15 +101,13 @@ enum {
 #define SORT_ELT(sort_elt) ((SortElt *)sort_elt)
 #define SORT_LEVEL(sort_level) ((SortLevel *)sort_level)
 
-#define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT (tree_model_sort), ch_iter, so_iter);
+#define GET_CHILD_ITER(tree_model_sort,ch_iter,so_iter) gtk_tree_model_sort_convert_iter_to_child_iter((GtkTreeModelSort*)(tree_model_sort), (ch_iter), (so_iter));
 
 #define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
 
-#define VALID_ITER(iter, tree_model_sort) (iter != NULL && iter->user_data != NULL && iter->user_data2 != NULL && tree_model_sort->stamp == iter->stamp)
+#define VALID_ITER(iter, tree_model_sort) ((iter) != NULL && (iter)->user_data != NULL && (iter)->user_data2 != NULL && (tree_model_sort)->stamp == (iter)->stamp)
 
 /* general (object/interface init, etc) */
-static void gtk_tree_model_sort_init                  (GtkTreeModelSort      *tree_model_sort);
-static void gtk_tree_model_sort_class_init            (GtkTreeModelSortClass *tree_model_sort_class);
 static void gtk_tree_model_sort_tree_model_init       (GtkTreeModelIface     *iface);
 static void gtk_tree_model_sort_tree_sortable_init    (GtkTreeSortableIface  *iface);
 static void gtk_tree_model_sort_drag_source_init      (GtkTreeDragSourceIface*iface);
@@ -202,11 +201,11 @@ static void         gtk_tree_model_sort_set_sort_func         (GtkTreeSortable
                                                               gint                    sort_column_id,
                                                               GtkTreeIterCompareFunc  func,
                                                               gpointer                data,
-                                                              GtkDestroyNotify        destroy);
+                                                              GDestroyNotify          destroy);
 static void         gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable        *sortable,
                                                               GtkTreeIterCompareFunc  func,
                                                               gpointer                data,
-                                                              GtkDestroyNotify        destroy);
+                                                              GDestroyNotify          destroy);
 static gboolean     gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable     *sortable);
 
 /* Private functions (sort funcs, level handling and other utils) */
@@ -237,68 +236,14 @@ static GtkTreePath *gtk_real_tree_model_sort_convert_child_path_to_path (GtkTree
                                                                         GtkTreePath      *child_path,
                                                                         gboolean          build_levels);
 
-static GObjectClass *parent_class = NULL;
 
-GType
-gtk_tree_model_sort_get_type (void)
-{
-  static GType tree_model_sort_type = 0;
-
-  if (!tree_model_sort_type)
-    {
-      static const GTypeInfo tree_model_sort_info =
-      {
-        sizeof (GtkTreeModelSortClass),
-        NULL,           /* base_init */
-        NULL,           /* base_finalize */
-        (GClassInitFunc) gtk_tree_model_sort_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GtkTreeModelSort),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) gtk_tree_model_sort_init
-      };
-
-      static const GInterfaceInfo tree_model_info =
-      {
-        (GInterfaceInitFunc) gtk_tree_model_sort_tree_model_init,
-        NULL,
-        NULL
-      };
-
-      static const GInterfaceInfo sortable_info =
-      {
-        (GInterfaceInitFunc) gtk_tree_model_sort_tree_sortable_init,
-        NULL,
-        NULL
-      };
-
-      static const GInterfaceInfo drag_source_info =
-      {
-        (GInterfaceInitFunc) gtk_tree_model_sort_drag_source_init,
-        NULL,
-        NULL
-      };
-
-      tree_model_sort_type =
-       g_type_register_static (G_TYPE_OBJECT, "GtkTreeModelSort",
-                               &tree_model_sort_info, 0);
-
-      g_type_add_interface_static (tree_model_sort_type,
-                                   GTK_TYPE_TREE_MODEL,
-                                   &tree_model_info);
-
-      g_type_add_interface_static (tree_model_sort_type,
-                                   GTK_TYPE_TREE_SORTABLE,
-                                   &sortable_info);
-
-      g_type_add_interface_static (tree_model_sort_type,
-                                   GTK_TYPE_TREE_DRAG_SOURCE,
-                                   &drag_source_info);
-    }
-
-  return tree_model_sort_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GtkTreeModelSort, gtk_tree_model_sort, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+                                               gtk_tree_model_sort_tree_model_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
+                                               gtk_tree_model_sort_tree_sortable_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+                                               gtk_tree_model_sort_drag_source_init))
 
 static void
 gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort)
@@ -316,7 +261,6 @@ gtk_tree_model_sort_class_init (GtkTreeModelSortClass *class)
   GObjectClass *object_class;
 
   object_class = (GObjectClass *) class;
-  parent_class = g_type_class_peek_parent (class);
 
   object_class->set_property = gtk_tree_model_sort_set_property;
   object_class->get_property = gtk_tree_model_sort_get_property;
@@ -330,7 +274,7 @@ gtk_tree_model_sort_class_init (GtkTreeModelSortClass *class)
                                                        P_("TreeModelSort Model"),
                                                        P_("The model for the TreeModelSort to sort"),
                                                        GTK_TYPE_TREE_MODEL,
-                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
@@ -374,7 +318,7 @@ gtk_tree_model_sort_drag_source_init (GtkTreeDragSourceIface *iface)
  * gtk_tree_model_sort_new_with_model:
  * @child_model: A #GtkTreeModel
  *
- * Creates a new #GtkTreeModel, with @child_model as the child_model.
+ * Creates a new #GtkTreeModel, with @child_model as the child model.
  *
  * Return value: A new #GtkTreeModel.
  */
@@ -409,8 +353,16 @@ gtk_tree_model_sort_finalize (GObject *object)
       tree_model_sort->sort_list = NULL;
     }
 
+  if (tree_model_sort->default_sort_destroy)
+    {
+      tree_model_sort->default_sort_destroy (tree_model_sort->default_sort_data);
+      tree_model_sort->default_sort_destroy = NULL;
+      tree_model_sort->default_sort_data = NULL;
+    }
+
+
   /* must chain up */
-  parent_class->finalize (object);
+  G_OBJECT_CLASS (gtk_tree_model_sort_parent_class)->finalize (object);
 }
 
 static void
@@ -489,6 +441,7 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
     }
 
   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
+  gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (data), &iter);
 
   level = iter.user_data;
   elt = iter.user_data2;
@@ -501,12 +454,13 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
        gtk_tree_path_free (start_s_path);
 
       gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
+      gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
 
       gtk_tree_path_free (path);
 
       return;
     }
-
+  
   if (!GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
     {
       gtk_tree_model_get_iter (tree_model_sort->child_model,
@@ -612,6 +566,7 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
   /* emit row_changed signal (at new location) */
   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
   gtk_tree_model_row_changed (GTK_TREE_MODEL (data), path, &iter);
+  gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
 
   gtk_tree_path_free (path);
   if (free_s_path)
@@ -675,9 +630,10 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
 
       if (level->array->len < gtk_tree_path_get_indices (s_path)[i])
        {
-         g_warning ("A node was inserted with a parent that's not in the tree.\n"
+         g_warning ("%s: A node was inserted with a parent that's not in the tree.\n"
                     "This possibly means that a GtkTreeModel inserted a child node\n"
-                    "before the parent was inserted.");
+                    "before the parent was inserted.",
+                    G_STRLOC);
          goto done;
        }
 
@@ -693,22 +649,6 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
 
       if (!elt->children)
        {
-         GtkTreePath *tmppath;
-         GtkTreeIter  tmpiter;
-
-         tmpiter.stamp = tree_model_sort->stamp;
-         tmpiter.user_data = level;
-         tmpiter.user_data2 = elt;
-
-         tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &tmpiter);
-         if (tmppath)
-           {
-             gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data),
-                                                   tmppath,
-                                                   &tmpiter);
-             gtk_tree_path_free (tmppath);
-           }
-
          /* not covering this signal */
          goto done;
        }
@@ -721,6 +661,12 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
   if (!parent_level)
     goto done;
 
+  if (level->ref_count == 0 && level != tree_model_sort->root)
+    {
+      gtk_tree_model_sort_free_level (tree_model_sort, level);
+      goto done;
+    }
+
   if (!gtk_tree_model_sort_insert_value (tree_model_sort,
                                         parent_level,
                                         s_path,
@@ -770,7 +716,6 @@ gtk_tree_model_sort_row_has_child_toggled (GtkTreeModel *s_model,
   gtk_tree_path_free (path);
 }
 
-/* FIXME: I still have doubts if this works */
 static void
 gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
                                 GtkTreePath  *s_path,
@@ -809,12 +754,18 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
 
   if (level->ref_count == 0)
     {
-      /* This will prune the level, so I can just emit the signal and not worry
-       * about cleaning this level up. */
+      /* This will prune the level, so I can just emit the signal and 
+       * not worry about cleaning this level up. 
+       * Careful, root level is not cleaned up in increment stamp.
+       */
       gtk_tree_model_sort_increment_stamp (tree_model_sort);
       gtk_tree_path_free (path);
       if (level == tree_model_sort->root)
-       tree_model_sort->root = NULL;
+       {
+         gtk_tree_model_sort_free_level (tree_model_sort, 
+                                         tree_model_sort->root);
+         tree_model_sort->root = NULL;
+       }
       return;
     }
 
@@ -857,7 +808,7 @@ gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
 
   g_return_if_fail (new_order != NULL);
 
-  if (s_path == NULL || gtk_tree_path_get_indices (s_path) == NULL)
+  if (s_path == NULL || gtk_tree_path_get_depth (s_path) == 0)
     {
       if (tree_model_sort->root == NULL)
        return;
@@ -933,12 +884,12 @@ gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
 static GtkTreeModelFlags
 gtk_tree_model_sort_get_flags (GtkTreeModel *tree_model)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeModelFlags flags;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, 0);
 
-  flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_SORT (tree_model)->child_model);
+  flags = gtk_tree_model_get_flags (tree_model_sort->child_model);
 
   if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
     return GTK_TREE_MODEL_LIST_ONLY;
@@ -951,8 +902,6 @@ gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
-
   if (tree_model_sort->child_model == 0)
     return 0;
 
@@ -963,10 +912,11 @@ static GType
 gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
                                      gint          index)
 {
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), G_TYPE_INVALID);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, G_TYPE_INVALID);
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
 
-  return gtk_tree_model_get_column_type (GTK_TREE_MODEL_SORT (tree_model)->child_model, index);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, G_TYPE_INVALID);
+
+  return gtk_tree_model_get_column_type (tree_model_sort->child_model, index);
 }
 
 static gboolean
@@ -974,15 +924,13 @@ gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
                              GtkTreeIter  *iter,
                              GtkTreePath  *path)
 {
-  GtkTreeModelSort *tree_model_sort;
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   gint *indices;
   SortLevel *level;
   gint depth, i;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
 
-  tree_model_sort = (GtkTreeModelSort *) tree_model;
   indices = gtk_tree_path_get_indices (path);
 
   if (tree_model_sort->root == NULL)
@@ -1021,13 +969,13 @@ static GtkTreePath *
 gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
                              GtkTreeIter  *iter)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreePath *retval;
   SortLevel *level;
   SortElt *elt;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, NULL);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, NULL);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
+  g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, NULL);
 
   retval = gtk_tree_path_new ();
   level = iter->user_data;
@@ -1049,14 +997,14 @@ gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
                               gint          column,
                               GValue       *value)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeIter child_iter;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
+  g_return_if_fail (tree_model_sort->child_model != NULL);
+  g_return_if_fail (VALID_ITER (iter, tree_model_sort));
 
-  GET_CHILD_ITER (tree_model, &child_iter, iter);
-  gtk_tree_model_get_value (GTK_TREE_MODEL_SORT (tree_model)->child_model,
+  GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
+  gtk_tree_model_get_value (tree_model_sort->child_model,
                            &child_iter, column, value);
 }
 
@@ -1064,12 +1012,12 @@ static gboolean
 gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
                               GtkTreeIter  *iter)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   SortLevel *level;
   SortElt *elt;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+  g_return_val_if_fail (tree_model_sort->stamp == iter->stamp, FALSE);
 
   level = iter->user_data;
   elt = iter->user_data2;
@@ -1093,9 +1041,9 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
   SortLevel *level;
 
   iter->stamp = 0;
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
   g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
-  if (parent) g_return_val_if_fail (tree_model_sort->stamp == parent->stamp, FALSE);
+  if (parent) 
+    g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
 
   if (parent == NULL)
     {
@@ -1129,33 +1077,34 @@ static gboolean
 gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
                                    GtkTreeIter  *iter)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeIter child_iter;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+  g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), FALSE);
 
-  GET_CHILD_ITER (tree_model, &child_iter, iter);
+  GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
 
-  return gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+  return gtk_tree_model_iter_has_child (tree_model_sort->child_model, &child_iter);
 }
 
 static gint
 gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
                                     GtkTreeIter  *iter)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeIter child_iter;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
-  if (iter) g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, 0);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, 0);
+  if (iter) 
+    g_return_val_if_fail (VALID_ITER (iter, tree_model_sort), 0);
 
   if (iter == NULL)
-    return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, NULL);
+    return gtk_tree_model_iter_n_children (tree_model_sort->child_model, NULL);
 
-  GET_CHILD_ITER (tree_model, &child_iter, iter);
+  GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
 
-  return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+  return gtk_tree_model_iter_n_children (tree_model_sort->child_model, &child_iter);
 }
 
 static gboolean
@@ -1164,12 +1113,13 @@ gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
                                    GtkTreeIter  *parent,
                                    gint          n)
 {
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   SortLevel *level;
   /* We have this for the iter == parent case */
   GtkTreeIter children;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
-  if (parent) g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
+  if (parent) 
+    g_return_val_if_fail (VALID_ITER (parent, tree_model_sort), FALSE);
 
   /* Use this instead of has_child to force us to build the level, if needed */
   if (gtk_tree_model_sort_iter_children (tree_model, &children, parent) == FALSE)
@@ -1185,7 +1135,7 @@ gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
       return FALSE;
     }
 
-  iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
+  iter->stamp = tree_model_sort->stamp;
   iter->user_data = level;
   iter->user_data2 = &g_array_index (level->array, SortElt, n);
 
@@ -1196,19 +1146,19 @@ static gboolean
 gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
                                 GtkTreeIter  *iter,
                                 GtkTreeIter  *child)
-{
+{ 
+  GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   SortLevel *level;
 
   iter->stamp = 0;
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
-  g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == child->stamp, FALSE);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+  g_return_val_if_fail (VALID_ITER (child, tree_model_sort), FALSE);
 
   level = child->user_data;
 
   if (level->parent_level)
     {
-      iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
+      iter->stamp = tree_model_sort->stamp;
       iter->user_data = level->parent_level;
       iter->user_data2 = level->parent_elt;
 
@@ -1223,41 +1173,53 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
   GtkTreeIter child_iter;
+  GtkTreeIter tmp_iter;
   SortLevel *level;
   SortElt *elt;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
+  g_return_if_fail (tree_model_sort->child_model != NULL);
+  g_return_if_fail (VALID_ITER (iter, tree_model_sort));
 
-  GET_CHILD_ITER (tree_model, &child_iter, iter);
+  GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
 
-  gtk_tree_model_ref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+  /* Reference the node in the child model */
+  gtk_tree_model_ref_node (tree_model_sort->child_model, &child_iter);
 
+  /* Increase the reference count of this element and its level */
   level = iter->user_data;
   elt = iter->user_data2;
 
   elt->ref_count++;
   level->ref_count++;
+
+  /* Increase the reference count of all parent elements */
+  tmp_iter.stamp = tree_model_sort->stamp;
+  tmp_iter.user_data = level->parent_level;
+  tmp_iter.user_data2 = level->parent_elt;;
+
+  while (tmp_iter.user_data2)
+    {
+      gtk_tree_model_sort_ref_node (tree_model, &tmp_iter);
+
+      tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
+      tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+    }
+
   if (level->ref_count == 1)
     {
       SortLevel *parent_level = level->parent_level;
       SortElt *parent_elt = level->parent_elt;
       /* We were at zero -- time to decrement the zero_ref_count val */
-      do
+      while (parent_level)
        {
-         if (parent_elt)
-           parent_elt->zero_ref_count--;
-         else
-           tree_model_sort->zero_ref_count--;
+         parent_elt->zero_ref_count--;
 
-         if (parent_level)
-           {
-             parent_elt = parent_level->parent_elt;
-             parent_level = parent_level->parent_level;
-           }
+         parent_elt = parent_level->parent_elt;
+         parent_level = parent_level->parent_level;
        }
-      while (parent_level);
+
+      if (tree_model_sort->root != level)
+       tree_model_sort->zero_ref_count--;
     }
 }
 
@@ -1267,18 +1229,20 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
                                     gboolean      propagate_unref)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
-  GtkTreeIter child_iter;
+  GtkTreeIter tmp_iter;
   SortLevel *level;
   SortElt *elt;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
-  g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
-
-  GET_CHILD_ITER (tree_model, &child_iter, iter);
+  g_return_if_fail (tree_model_sort->child_model != NULL);
+  g_return_if_fail (VALID_ITER (iter, tree_model_sort));
 
   if (propagate_unref)
-    gtk_tree_model_unref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+    {
+      GtkTreeIter child_iter;
+
+      GET_CHILD_ITER (tree_model_sort, &child_iter, iter);
+      gtk_tree_model_unref_node (tree_model_sort->child_model, &child_iter);
+    }
 
   level = iter->user_data;
   elt = iter->user_data2;
@@ -1288,6 +1252,19 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
   elt->ref_count--;
   level->ref_count--;
 
+  /* Decrease the reference count of all parent elements */
+  tmp_iter.stamp = tree_model_sort->stamp;
+  tmp_iter.user_data = level->parent_level;
+  tmp_iter.user_data2 = level->parent_elt;;
+
+  while (tmp_iter.user_data2)
+    {
+      gtk_tree_model_sort_real_unref_node (tree_model, &tmp_iter, FALSE);
+
+      tmp_iter.user_data2 = SORT_LEVEL (tmp_iter.user_data)->parent_elt;
+      tmp_iter.user_data = SORT_LEVEL (tmp_iter.user_data)->parent_level;
+    }
+
   if (level->ref_count == 0)
     {
       SortLevel *parent_level = level->parent_level;
@@ -1301,7 +1278,9 @@ gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
          parent_elt = parent_level->parent_elt;
          parent_level = parent_level->parent_level;
        }
-      tree_model_sort->zero_ref_count++;
+
+      if (tree_model_sort->root != level)
+       tree_model_sort->zero_ref_count++;
     }
 }
 
@@ -1320,8 +1299,6 @@ gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (sortable), FALSE);
-
   if (sort_column_id)
     *sort_column_id = tree_model_sort->sort_column_id;
   if (order)
@@ -1341,31 +1318,32 @@ gtk_tree_model_sort_set_sort_column_id (GtkTreeSortable *sortable,
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
-
-  if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+  if (sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
     {
-      GtkTreeDataSortHeader *header = NULL;
+      if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+        {
+          GtkTreeDataSortHeader *header = NULL;
 
-      header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
-                                              sort_column_id);
+          header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
+                                                  sort_column_id);
 
-      /* we want to make sure that we have a function */
-      g_return_if_fail (header != NULL);
-      g_return_if_fail (header->func != NULL);
-    }
-  else
-    g_return_if_fail (tree_model_sort->default_sort_func != NULL);
+          /* we want to make sure that we have a function */
+          g_return_if_fail (header != NULL);
+          g_return_if_fail (header->func != NULL);
+        }
+      else
+        g_return_if_fail (tree_model_sort->default_sort_func != NULL);
 
-  if (tree_model_sort->sort_column_id == sort_column_id)
-    {
-      if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
-       {
-         if (tree_model_sort->order == order)
+      if (tree_model_sort->sort_column_id == sort_column_id)
+        {
+          if (sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+           {
+             if (tree_model_sort->order == order)
+               return;
+           }
+          else
            return;
-       }
-      else
-       return;
+        }
     }
 
   tree_model_sort->sort_column_id = sort_column_id;
@@ -1381,46 +1359,13 @@ gtk_tree_model_sort_set_sort_func (GtkTreeSortable        *sortable,
                                   gint                    sort_column_id,
                                   GtkTreeIterCompareFunc  func,
                                   gpointer                data,
-                                  GtkDestroyNotify        destroy)
+                                  GDestroyNotify          destroy)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) sortable;
-  GtkTreeDataSortHeader *header = NULL;
-  GList *list;
-
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
-  g_return_if_fail (func != NULL);
-
-  for (list = tree_model_sort->sort_list; list; list = list->next)
-    {
-      GtkTreeDataSortHeader *list_header;
-
-      list_header = (GtkTreeDataSortHeader*) list->data;
-      if (list_header->sort_column_id == sort_column_id)
-       {
-         header = list_header;
-         break;
-       }
-    }
-
-  if (header == NULL)
-    {
-      header = g_new0 (GtkTreeDataSortHeader, 1);
-      header->sort_column_id = sort_column_id;
-      tree_model_sort->sort_list = g_list_append (tree_model_sort->sort_list,
-                                                 header);
-    }
-
-  if (header->destroy)
-    {
-      GtkDestroyNotify d = header->destroy;
-
-      header->destroy = NULL;
-      d (header->data);
-    }
 
-  header->func = func;
-  header->data = data;
-  header->destroy = destroy;
+  tree_model_sort->sort_list = _gtk_tree_data_list_set_header (tree_model_sort->sort_list,
+                                                              sort_column_id,
+                                                              func, data, destroy);
 
   if (tree_model_sort->sort_column_id == sort_column_id)
     gtk_tree_model_sort_sort (tree_model_sort);
@@ -1430,15 +1375,13 @@ static void
 gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable        *sortable,
                                           GtkTreeIterCompareFunc  func,
                                           gpointer                data,
-                                          GtkDestroyNotify        destroy)
+                                          GDestroyNotify          destroy)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
-
   if (tree_model_sort->default_sort_destroy)
     {
-      GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+      GDestroyNotify d = tree_model_sort->default_sort_destroy;
 
       tree_model_sort->default_sort_destroy = NULL;
       d (tree_model_sort->default_sort_data);
@@ -1457,8 +1400,6 @@ gtk_tree_model_sort_has_default_sort_func (GtkTreeSortable *sortable)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *)sortable;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (sortable), FALSE);
-
   return (tree_model_sort->default_sort_func != NULL);
 }
 
@@ -1471,9 +1412,6 @@ gtk_tree_model_sort_row_draggable (GtkTreeDragSource *drag_source,
   GtkTreePath *child_path;
   gboolean draggable;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
-  g_return_val_if_fail (path != NULL, FALSE);
-
   child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
                                                                path);
   draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path);
@@ -1491,11 +1429,7 @@ gtk_tree_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
   GtkTreePath *child_path;
   gboolean gotten;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
-  g_return_val_if_fail (path != NULL, FALSE);
-
-  child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
-                                                               path);
+  child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
   gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path, selection_data);
   gtk_tree_path_free (child_path);
 
@@ -1510,11 +1444,7 @@ gtk_tree_model_sort_drag_data_delete (GtkTreeDragSource *drag_source,
   GtkTreePath *child_path;
   gboolean deleted;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (drag_source), FALSE);
-  g_return_val_if_fail (path != NULL, FALSE);
-
-  child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort,
-                                                               path);
+  child_path = gtk_tree_model_sort_convert_path_to_child_path (tree_model_sort, path);
   deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_sort->child_model), child_path);
   gtk_tree_path_free (child_path);
 
@@ -1604,6 +1534,7 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
                                gboolean          emit_reordered)
 {
   gint i;
+  gint ref_offset;
   GArray *sort_array;
   GArray *new_array;
   gint *new_order;
@@ -1613,12 +1544,18 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
 
   SortData data;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
   g_return_if_fail (level != NULL);
 
   if (level->array->len < 1 && !((SortElt *)level->array->data)->children)
     return;
 
+  iter.stamp = tree_model_sort->stamp;
+  iter.user_data = level;
+  iter.user_data2 = &g_array_index (level->array, SortElt, 0);
+
+  gtk_tree_model_sort_ref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
+  ref_offset = g_array_index (level->array, SortElt, 0).offset;
+
   /* Set up data */
   data.tree_model_sort = tree_model_sort;
   if (level->parent_elt)
@@ -1740,12 +1677,30 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
     }
 
   g_free (new_order);
+
+  /* get the iter we referenced at the beginning of this function and
+   * unref it again
+   */
+  iter.stamp = tree_model_sort->stamp;
+  iter.user_data = level;
+
+  for (i = 0; i < level->array->len; i++)
+    {
+      if (g_array_index (level->array, SortElt, i).offset == ref_offset)
+        {
+         iter.user_data2 = &g_array_index (level->array, SortElt, i);
+         break;
+       }
+    }
+
+  gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort), &iter);
 }
 
 static void
 gtk_tree_model_sort_sort (GtkTreeModelSort *tree_model_sort)
 {
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
+  if (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
+    return;
 
   if (!tree_model_sort->root)
     return;
@@ -1924,18 +1879,17 @@ gtk_tree_model_sort_elt_get_path (SortLevel *level,
 /**
  * gtk_tree_model_sort_set_model:
  * @tree_model_sort: The #GtkTreeModelSort.
- * @child_model: A #GtkTreeModel, or NULL.
+ * @child_model: A #GtkTreeModel, or %NULL.
  *
- * Sets the model of @tree_model_sort to be @model.  If @model is NULL, then the
- * old model is unset.  The sort function is unset as a result of this call.
- * The model will be in an unsorted state until a sort function is set.
+ * Sets the model of @tree_model_sort to be @model.  If @model is %NULL, 
+ * then the old model is unset.  The sort function is unset as a result 
+ * of this call. The model will be in an unsorted state until a sort 
+ * function is set.
  **/
 static void
 gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
                                GtkTreeModel     *child_model)
 {
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
-
   if (child_model)
     g_object_ref (child_model);
 
@@ -1969,23 +1923,23 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
       gint i, n_columns;
 
       tree_model_sort->changed_id =
-        g_signal_connect (child_model, "row_changed",
+        g_signal_connect (child_model, "row-changed",
                           G_CALLBACK (gtk_tree_model_sort_row_changed),
                           tree_model_sort);
       tree_model_sort->inserted_id =
-        g_signal_connect (child_model, "row_inserted",
+        g_signal_connect (child_model, "row-inserted",
                           G_CALLBACK (gtk_tree_model_sort_row_inserted),
                           tree_model_sort);
       tree_model_sort->has_child_toggled_id =
-        g_signal_connect (child_model, "row_has_child_toggled",
+        g_signal_connect (child_model, "row-has-child-toggled",
                           G_CALLBACK (gtk_tree_model_sort_row_has_child_toggled),
                           tree_model_sort);
       tree_model_sort->deleted_id =
-        g_signal_connect (child_model, "row_deleted",
+        g_signal_connect (child_model, "row-deleted",
                           G_CALLBACK (gtk_tree_model_sort_row_deleted),
                           tree_model_sort);
       tree_model_sort->reordered_id =
-       g_signal_connect (child_model, "rows_reordered",
+       g_signal_connect (child_model, "rows-reordered",
                          G_CALLBACK (gtk_tree_model_sort_rows_reordered),
                          tree_model_sort);
 
@@ -2013,7 +1967,7 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
  * Return value: the "child model" being sorted
  **/
 GtkTreeModel *
-gtk_tree_model_sort_get_model (GtkTreeModelSort  *tree_model)
+gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
 {
   g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
 
@@ -2031,7 +1985,6 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
   SortLevel *level;
   gint i;
 
-  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
   g_return_val_if_fail (tree_model_sort->child_model != NULL, NULL);
   g_return_val_if_fail (child_path != NULL, NULL);
 
@@ -2090,8 +2043,8 @@ gtk_real_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_mode
  * 
  * Converts @child_path to a path relative to @tree_model_sort.  That is,
  * @child_path points to a path in the child model.  The returned path will
- * point to the same row in the sorted model.  If @child_path isn't a valid path
- * on the child model, then %NULL is returned.
+ * point to the same row in the sorted model.  If @child_path isn't a valid 
+ * path on the child model, then %NULL is returned.
  * 
  * Return value: A newly allocated #GtkTreePath, or %NULL
  **/
@@ -2113,31 +2066,45 @@ gtk_tree_model_sort_convert_child_path_to_path (GtkTreeModelSort *tree_model_sor
  * @child_iter: A valid #GtkTreeIter pointing to a row on the child model
  * 
  * Sets @sort_iter to point to the row in @tree_model_sort that corresponds to
- * the row pointed at by @child_iter.
+ * the row pointed at by @child_iter.  If @sort_iter was not set, %FALSE
+ * is returned.  Note: a boolean is only returned since 2.14.
+ *
+ * Return value: %TRUE, if @sort_iter was set, i.e. if @sort_iter is a
+ * valid iterator pointer to a visible row in the child model.
  **/
-void
+gboolean
 gtk_tree_model_sort_convert_child_iter_to_iter (GtkTreeModelSort *tree_model_sort,
                                                GtkTreeIter      *sort_iter,
                                                GtkTreeIter      *child_iter)
 {
+  gboolean ret;
   GtkTreePath *child_path, *path;
 
-  g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
-  g_return_if_fail (tree_model_sort->child_model != NULL);
-  g_return_if_fail (sort_iter != NULL);
-  g_return_if_fail (child_iter != NULL);
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), FALSE);
+  g_return_val_if_fail (tree_model_sort->child_model != NULL, FALSE);
+  g_return_val_if_fail (sort_iter != NULL, FALSE);
+  g_return_val_if_fail (child_iter != NULL, FALSE);
+  g_return_val_if_fail (sort_iter != child_iter, FALSE);
 
   sort_iter->stamp = 0;
 
   child_path = gtk_tree_model_get_path (tree_model_sort->child_model, child_iter);
-  g_return_if_fail (child_path != NULL);
+  g_return_val_if_fail (child_path != NULL, FALSE);
 
   path = gtk_tree_model_sort_convert_child_path_to_path (tree_model_sort, child_path);
   gtk_tree_path_free (child_path);
-  g_return_if_fail (path != NULL);
 
-  gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort), sort_iter, path);
+  if (!path)
+    {
+      g_warning ("%s: The conversion of the child path to a GtkTreeModel sort path failed", G_STRLOC);
+      return FALSE;
+    }
+
+  ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort),
+                                 sort_iter, path);
   gtk_tree_path_free (path);
+
+  return ret;
 }
 
 /**
@@ -2145,10 +2112,11 @@ gtk_tree_model_sort_convert_child_iter_to_iter (GtkTreeModelSort *tree_model_sor
  * @tree_model_sort: A #GtkTreeModelSort
  * @sorted_path: A #GtkTreePath to convert
  * 
- * Converts @sorted_path to a path on the child model of @tree_model_sort.  That
- * is, @sorted_path points to a location in @tree_model_sort.  The returned path
- * will point to the same location in the model not being sorted.  If @sorted_path 
- * does not point to a location in the child model, %NULL is returned.
+ * Converts @sorted_path to a path on the child model of @tree_model_sort.  
+ * That is, @sorted_path points to a location in @tree_model_sort.  The 
+ * returned path will point to the same location in the model not being 
+ * sorted.  If @sorted_path does not point to a location in the child model, 
+ * %NULL is returned.
  * 
  * Return value: A newly allocated #GtkTreePath, or %NULL
  **/
@@ -2214,8 +2182,8 @@ gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sor
   g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
   g_return_if_fail (tree_model_sort->child_model != NULL);
   g_return_if_fail (child_iter != NULL);
-  g_return_if_fail (sorted_iter != NULL);
-  g_return_if_fail (sorted_iter->stamp == tree_model_sort->stamp);
+  g_return_if_fail (VALID_ITER (sorted_iter, tree_model_sort));
+  g_return_if_fail (sorted_iter != child_iter);
 
   if (GTK_TREE_MODEL_SORT_CACHE_CHILD_ITERS (tree_model_sort))
     {
@@ -2313,7 +2281,30 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
          if (gtk_tree_model_iter_next (tree_model_sort->child_model, &iter) == FALSE &&
              i < length - 1)
            {
-             g_warning ("There is a discrepency between the sort model and the child model.");
+             if (parent_level)
+               {
+                 GtkTreePath *level;
+                 gchar *str;
+
+                 level = gtk_tree_model_sort_elt_get_path (parent_level,
+                                                           parent_elt);
+                 str = gtk_tree_path_to_string (level);
+                 gtk_tree_path_free (level);
+
+                 g_warning ("%s: There is a discrepancy between the sort model "
+                            "and the child model.  The child model is "
+                            "advertising a wrong length for level %s:.",
+                            G_STRLOC, str);
+                 g_free (str);
+               }
+             else
+               {
+                 g_warning ("%s: There is a discrepancy between the sort model "
+                            "and the child model.  The child model is "
+                            "advertising a wrong length for the root level.",
+                            G_STRLOC);
+               }
+
              return;
            }
        }
@@ -2333,32 +2324,28 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
 
   g_assert (sort_level);
 
+  for (i = 0; i < sort_level->array->len; i++)
+    {
+      if (g_array_index (sort_level->array, SortElt, i).children)
+       gtk_tree_model_sort_free_level (tree_model_sort,
+                                       SORT_LEVEL (g_array_index (sort_level->array, SortElt, i).children));
+    }
+
   if (sort_level->ref_count == 0)
     {
       SortLevel *parent_level = sort_level->parent_level;
       SortElt *parent_elt = sort_level->parent_elt;
 
-      do
+      while (parent_level)
        {
-         if (parent_elt)
-           parent_elt->zero_ref_count--;
-         else
-           tree_model_sort->zero_ref_count--;
+         parent_elt->zero_ref_count--;
 
-         if (parent_level)
-           {
-             parent_elt = parent_level->parent_elt;
-             parent_level = parent_level->parent_level;
-           }
+         parent_elt = parent_level->parent_elt;
+         parent_level = parent_level->parent_level;
        }
-      while (parent_level);
-    }
 
-  for (i = 0; i < sort_level->array->len; i++)
-    {
-      if (g_array_index (sort_level->array, SortElt, i).children)
-       gtk_tree_model_sort_free_level (tree_model_sort, 
-                                       SORT_LEVEL(g_array_index (sort_level->array, SortElt, i).children));
+      if (sort_level != tree_model_sort->root)
+       tree_model_sort->zero_ref_count--;
     }
 
   if (sort_level->parent_elt)
@@ -2419,7 +2406,7 @@ gtk_tree_model_sort_reset_default_sort_func (GtkTreeModelSort *tree_model_sort)
 
   if (tree_model_sort->default_sort_destroy)
     {
-      GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+      GDestroyNotify d = tree_model_sort->default_sort_destroy;
 
       tree_model_sort->default_sort_destroy = NULL;
       d (tree_model_sort->default_sort_data);
@@ -2450,7 +2437,7 @@ gtk_tree_model_sort_clear_cache (GtkTreeModelSort *tree_model_sort)
 {
   g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
 
-  if (tree_model_sort->zero_ref_count)
+  if (tree_model_sort->zero_ref_count > 0)
     gtk_tree_model_sort_clear_cache_helper (tree_model_sort, (SortLevel *)tree_model_sort->root);
 }
 
@@ -2480,8 +2467,9 @@ gtk_tree_model_sort_iter_is_valid_helper (GtkTreeIter *iter,
  * @tree_model_sort: A #GtkTreeModelSort.
  * @iter: A #GtkTreeIter.
  *
- * WARNING: This function is slow. Only use it for debugging and/or testing
- * purposes.
+ * <warning><para>
+ * This function is slow. Only use it for debugging and/or testing purposes.
+ * </para></warning>
  *
  * Checks if the given iter is a valid iter for this #GtkTreeModelSort.
  *