]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreemodelsort.c
gtk/gtktreemodelsort.c typo in docs for
[~andy/gtk] / gtk / gtktreemodelsort.c
index 80243090ef902d543cc5541103f83fdf6f28a3b4..6ae397e68340386ca3dc360f03943840d95f85b1 100644 (file)
@@ -99,6 +99,8 @@ enum {
 
 #define GET_CHILD_ITER(tree_model_sort,child_iter,sort_iter) gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT (tree_model_sort), child_iter, sort_iter);
 
+#define NO_SORT_FUNC ((GtkTreeIterCompareFunc) 0x1)
+
 /* 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);
@@ -168,6 +170,9 @@ static gboolean     gtk_tree_model_sort_iter_parent        (GtkTreeModel
                                                             GtkTreeIter           *child);
 static void         gtk_tree_model_sort_ref_node           (GtkTreeModel          *tree_model,
                                                             GtkTreeIter           *iter);
+static void         gtk_tree_model_sort_real_unref_node    (GtkTreeModel          *tree_model,
+                                                            GtkTreeIter           *iter,
+                                                           gboolean               propagate_unref);
 static void         gtk_tree_model_sort_unref_node         (GtkTreeModel          *tree_model,
                                                             GtkTreeIter           *iter);
 
@@ -432,10 +437,6 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
 
   g_return_if_fail (start_s_path != NULL || start_s_iter != NULL);
 
-#ifdef VERBOSE
-  g_print ("::row_changed run\n");
-#endif
-
   if (!start_s_path)
     {
       free_s_path = TRUE;
@@ -457,7 +458,9 @@ gtk_tree_model_sort_row_changed (GtkTreeModel *s_model,
   level = iter.user_data;
   elt = iter.user_data2;
 
-  if (level->array->len < 2 || tree_model_sort->sort_column_id == -1)
+  if (level->array->len < 2 ||
+      (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
+       tree_model_sort->default_sort_func == NO_SORT_FUNC))
     {
       if (free_s_path)
        gtk_tree_path_free (start_s_path);
@@ -535,10 +538,6 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
 
   parent_level = level = SORT_LEVEL (tree_model_sort->root);
 
-#ifdef VERBOSE
-  g_print ("::row_inserted\n");
-#endif
-
   g_return_if_fail (s_path != NULL || s_iter != NULL);
 
   if (!s_path)
@@ -684,10 +683,6 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
 
   g_return_if_fail (s_path != NULL);
 
-#ifdef VERBOSE
-  g_print ("::row_deleted\n");
-#endif
-
   path = gtk_real_tree_model_sort_convert_child_path_to_path (tree_model_sort, s_path, FALSE);
   if (path == NULL)
     return;
@@ -698,24 +693,28 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
   elt = SORT_ELT (iter.user_data2);
   offset = elt->offset;
 
-  gtk_tree_model_sort_increment_stamp (tree_model_sort);
+  /* we _need_ to emit ::row_deleted before we start unreffing the node
+   * itself. This is because of the row refs, which start unreffing nodes
+   * when we emit ::row_deleted
+   */
   gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
 
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
+
   while (elt->ref_count > 0)
-    gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (data), &iter);
+    gtk_tree_model_sort_real_unref_node (GTK_TREE_MODEL (data), &iter, FALSE);
 
   if (level->ref_count == 0 && level != tree_model_sort->root)
     {
       /* This will prune the level, so I can just emit the signal and not worry
        * about cleaning this level up. */
-#ifdef VERBOSE
-      g_print ("ref_count == 0, prune level\n");
-#endif
-
+      gtk_tree_model_sort_increment_stamp (tree_model_sort);
       gtk_tree_path_free (path);
       return;
     }
 
+  gtk_tree_model_sort_increment_stamp (tree_model_sort);
+
   /* Remove the row */
   for (i = 0; i < level->array->len; i++)
     if (elt->offset == g_array_index (level->array, SortElt, i).offset)
@@ -799,8 +798,8 @@ gtk_tree_model_sort_rows_reordered (GtkTreeModel *s_model,
     g_array_index (level->array, SortElt, i).offset = tmp_array[i];
   g_free (tmp_array);
 
-  if (tree_model_sort->sort_column_id == -1 &&
-      tree_model_sort->default_sort_func == (GtkTreeIterCompareFunc) 0x1)
+  if (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
+      tree_model_sort->default_sort_func == NO_SORT_FUNC)
     {
 
       gtk_tree_model_sort_sort_level (tree_model_sort, level,
@@ -1106,6 +1105,7 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
                              GtkTreeIter  *iter)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
+  GtkTreeIter child_iter;
   SortLevel *level;
   SortElt *elt;
 
@@ -1113,6 +1113,10 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *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);
+
+  gtk_tree_model_ref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+
   level = iter->user_data;
   elt = iter->user_data2;
 
@@ -1141,10 +1145,12 @@ gtk_tree_model_sort_ref_node (GtkTreeModel *tree_model,
 }
 
 static void
-gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
-                               GtkTreeIter  *iter)
+gtk_tree_model_sort_real_unref_node (GtkTreeModel *tree_model,
+                                    GtkTreeIter  *iter,
+                                    gboolean      propagate_unref)
 {
   GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) tree_model;
+  GtkTreeIter child_iter;
   SortLevel *level;
   SortElt *elt;
 
@@ -1152,6 +1158,11 @@ gtk_tree_model_sort_unref_node (GtkTreeModel *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);
+
+  if (propagate_unref)
+    gtk_tree_model_unref_node (GTK_TREE_MODEL_SORT (tree_model)->child_model, &child_iter);
+
   level = iter->user_data;
   elt = iter->user_data2;
 
@@ -1176,6 +1187,13 @@ gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
     }
 }
 
+static void
+gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
+                               GtkTreeIter  *iter)
+{
+  gtk_tree_model_sort_real_unref_node (tree_model, iter, TRUE);
+}
+
 /* Sortable interface */
 static gboolean
 gtk_tree_model_sort_get_sort_column_id (GtkTreeSortable *sortable,
@@ -1269,7 +1287,12 @@ gtk_tree_model_sort_set_sort_func (GtkTreeSortable        *sortable,
     }
 
   if (header->destroy)
-    (* header->destroy) (header->data);
+    {
+      GtkDestroyNotify d = header->destroy;
+
+      header->destroy = NULL;
+      d (header->data);
+    }
 
   header->func = func;
   header->data = data;
@@ -1287,7 +1310,12 @@ gtk_tree_model_sort_set_default_sort_func (GtkTreeSortable        *sortable,
   g_return_if_fail (GTK_IS_TREE_MODEL_SORT (sortable));
 
   if (tree_model_sort->default_sort_destroy)
-    (* tree_model_sort->default_sort_destroy) (tree_model_sort->default_sort_data);
+    {
+      GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+
+      tree_model_sort->default_sort_destroy = NULL;
+      d (tree_model_sort->default_sort_data);
+    }
 
   tree_model_sort->default_sort_func = func;
   tree_model_sort->default_sort_data = data;
@@ -1412,7 +1440,7 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
     }
   else
     {
-      data.parent_path = gtk_tree_path_new_root ();
+      data.parent_path = gtk_tree_path_new_first ();
     }
   data.parent_path_depth = gtk_tree_path_get_depth (data.parent_path);
   data.parent_path_indices = gtk_tree_path_get_indices (data.parent_path);
@@ -1451,28 +1479,20 @@ gtk_tree_model_sort_sort_level (GtkTreeModelSort *tree_model_sort,
        data.sort_data = tree_model_sort->default_sort_data;
       }
 
-  if (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
-      tree_model_sort->default_sort_func == (GtkTreeIterCompareFunc) 0x1)
-    {
-      g_array_sort_with_data (sort_array,
-                             gtk_tree_model_sort_offset_compare_func,
-                             &data);
-    }
+  if (data.sort_func == NO_SORT_FUNC)
+    g_array_sort_with_data (sort_array,
+                           gtk_tree_model_sort_offset_compare_func,
+                           &data);
   else
-    {
-      g_array_sort_with_data (sort_array,
-                             gtk_tree_model_sort_compare_func,
-                             &data);
-    }
+    g_array_sort_with_data (sort_array,
+                           gtk_tree_model_sort_compare_func,
+                           &data);
 
   gtk_tree_path_free (data.parent_path);
 
   new_array = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), level->array->len);
   new_order = g_new (gint, level->array->len);
 
-#ifdef VERBOSE
-  g_print ("---- sort\n");
-#endif
   for (i = 0; i < level->array->len; i++)
     {
       SortElt *elt;
@@ -1575,19 +1595,28 @@ gtk_tree_model_sort_level_find_insert (GtkTreeModelSort *tree_model_sort,
 
   GtkTreePath *path;
 
-  {
-    GtkTreeDataSortHeader *header;
-
-    header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
-                                            tree_model_sort->sort_column_id);
-
-    g_return_val_if_fail (header != NULL, 0);
-    g_return_val_if_fail (header->func != NULL, 0);
-
-    func = header->func;
-    data = header->data;
-  }
+  if (tree_model_sort->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID)
+    {
+      GtkTreeDataSortHeader *header;
+      
+      header = _gtk_tree_data_list_get_header (tree_model_sort->sort_list,
+                                              tree_model_sort->sort_column_id);
+      
+      g_return_val_if_fail (header != NULL, 0);
+      
+      func = header->func;
+      data = header->data;
+    }
+  else
+    {
+      func = tree_model_sort->default_sort_func;
+      data = tree_model_sort->default_sort_data;
+      
+      g_return_val_if_fail (func != NO_SORT_FUNC, 0);
+    }
 
+  g_return_val_if_fail (func != NULL, 0);
+      
   for (middle = 0; middle < level->array->len; middle++)
     {
       tmp_elt = &(g_array_index (level->array, SortElt, middle));
@@ -1634,22 +1663,25 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *tree_model_sort,
   elt.ref_count = 0;
   elt.children = NULL;
 
-  /* just insert it here, the ::row_changed signal will put the model
-   * back in a nice sort order
-   */
+  /* update all larger offsets */
+  tmp_elt = SORT_ELT (level->array->data);
+  for (i = 0; i < level->array->len; i++, tmp_elt++)
+    if (tmp_elt->offset >= offset)
+      tmp_elt->offset++;
 
-  index = gtk_tree_path_get_indices (s_path)[gtk_tree_path_get_depth (s_path)-1];
-  g_array_insert_vals (level->array, index, &elt, 1);
+  if (tree_model_sort->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
+      tree_model_sort->default_sort_func == NO_SORT_FUNC)
+    index = offset;
+  else
+    index = gtk_tree_model_sort_level_find_insert (tree_model_sort,
+                                                   level, s_iter,
+                                                   FALSE);
 
-  /* update all larger offsets */
+  g_array_insert_vals (level->array, index, &elt, 1);
   tmp_elt = SORT_ELT (level->array->data);
   for (i = 0; i < level->array->len; i++, tmp_elt++)
-    {
-      if ((tmp_elt->offset >= offset) && i != index)
-       tmp_elt->offset++;
-      if (tmp_elt->children)
-       tmp_elt->children->parent_elt = tmp_elt;
-    }
+    if (tmp_elt->children)
+      tmp_elt->children->parent_elt = tmp_elt;
 
   return TRUE;
 }
@@ -1758,7 +1790,7 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
       tree_model_sort->sort_list = _gtk_tree_data_list_header_new (n_columns, types);
       g_free (types);
 
-      tree_model_sort->default_sort_func = (GtkTreeIterCompareFunc)0x1;
+      tree_model_sort->default_sort_func = NO_SORT_FUNC;
       tree_model_sort->stamp = g_random_int ();
     }
 }
@@ -1953,7 +1985,7 @@ gtk_tree_model_sort_convert_path_to_child_path (GtkTreeModelSort *tree_model_sor
  * @child_iter: An uninitialized #GtkTreeIter
  * @sorted_iter: A valid #GtkTreeIter pointing to a row on @tree_model_sort.
  * 
- * Sets @child_iter to point to the row pointed to by *sorted_iter.
+ * Sets @child_iter to point to the row pointed to by @sorted_iter.
  **/
 void
 gtk_tree_model_sort_convert_iter_to_child_iter (GtkTreeModelSort *tree_model_sort,
@@ -1995,7 +2027,7 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
 
   if (parent_level == NULL)
     {
-      if (gtk_tree_model_get_iter_root (tree_model_sort->child_model, &iter) == FALSE)
+      if (gtk_tree_model_get_iter_first (tree_model_sort->child_model, &iter) == FALSE)
        return;
       length = gtk_tree_model_iter_n_children (tree_model_sort->child_model, NULL);
     }
@@ -2015,6 +2047,12 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
                                        &iter,
                                        &child_parent_iter) == FALSE)
        return;
+
+      /* stamp may have changed */
+      gtk_tree_model_sort_convert_iter_to_child_iter (tree_model_sort,
+                                                     &child_parent_iter,
+                                                     &parent_iter);
+
       length = gtk_tree_model_iter_n_children (tree_model_sort->child_model, &child_parent_iter);
     }
 
@@ -2063,10 +2101,6 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
       g_array_append_val (new_level->array, sort_elt);
     }
 
-#ifdef VERBOSE
-  g_print ("-- new level\n");
-#endif
-
   /* sort level */
   gtk_tree_model_sort_sort_level (tree_model_sort, new_level,
                                  FALSE, FALSE);
@@ -2078,19 +2112,8 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
 {
   gint i;
 
-#ifdef VERBOSE
-  g_print ("freeing level: %p, %p (ref = %d)\n", sort_level, 
-          sort_level->array, sort_level->ref_count);
-  g_print ("-- parents - elt: %p, level %p\n",
-          sort_level->parent_elt, sort_level->parent_level);
-#endif
-
   g_assert (sort_level);
 
-#ifdef VERBOSE  
-  g_print ("-- freeing current level (ref = %d)\n",sort_level->ref_count);
-#endif
-
   if (sort_level->ref_count == 0)
     {
       SortLevel *parent_level = sort_level->parent_level;
@@ -2112,10 +2135,6 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
       while (parent_level);
     }
 
-#ifdef VERBOSE
-  g_print ("-- freeing children\n");
-#endif
-
   for (i = 0; i < sort_level->array->len; i++)
     {
       if (g_array_index (sort_level->array, SortElt, i).children)
@@ -2124,37 +2143,25 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
     }
 
   if (sort_level->parent_elt)
-    {
-      sort_level->parent_elt->children = NULL;
-    }
+    sort_level->parent_elt->children = NULL;
   else
-    {
-      tree_model_sort->root = NULL;
-    }
-
-#ifdef VERBOSE  
-  g_print ("free %p\n", sort_level->array);
-#endif
+    tree_model_sort->root = NULL;
 
   g_array_free (sort_level->array, TRUE);
   sort_level->array = NULL;
 
-#ifdef VERBOSE
-  g_print ("free %p\n", sort_level);
-#endif
-
   g_free (sort_level);
   sort_level = NULL;
-
-#ifdef VERBOSE
-  g_print ("-------- done ---------\n");
-#endif
 }
 
 static void
 gtk_tree_model_sort_increment_stamp (GtkTreeModelSort *tree_model_sort)
 {
-  while (tree_model_sort->stamp == 0) tree_model_sort->stamp++;
+  do
+    {
+      tree_model_sort->stamp++;
+    }
+  while (tree_model_sort->stamp == 0);
 
   gtk_tree_model_sort_clear_cache (tree_model_sort);
 }
@@ -2174,10 +2181,7 @@ gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
     }
 
   if (level->ref_count == 0 && level != tree_model_sort->root)
-    {
-      gtk_tree_model_sort_free_level (tree_model_sort, level);
-      return;
-    }
+    gtk_tree_model_sort_free_level (tree_model_sort, level);
 }
 
 /**
@@ -2193,9 +2197,14 @@ gtk_tree_model_sort_reset_default_sort_func (GtkTreeModelSort *tree_model_sort)
   g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
 
   if (tree_model_sort->default_sort_destroy)
-    (* tree_model_sort->default_sort_destroy) (tree_model_sort->default_sort_data);
+    {
+      GtkDestroyNotify d = tree_model_sort->default_sort_destroy;
+
+      tree_model_sort->default_sort_destroy = NULL;
+      d (tree_model_sort->default_sort_data);
+    }
 
-  tree_model_sort->default_sort_func = (GtkTreeIterCompareFunc) 0x1;
+  tree_model_sort->default_sort_func = NO_SORT_FUNC;
   tree_model_sort->default_sort_data = NULL;
   tree_model_sort->default_sort_destroy = NULL;
   tree_model_sort->sort_column_id = GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID;