2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 /* NOTE: There is a potential for confusion in this code as to whether an iter,
22 * path or value refers to the GtkTreeModelSort model, or the child model being
23 * sorted. As a convention, variables referencing the child model will have an
24 * s_ prefix before them (ie. s_iter, s_value, s_path);
27 #include "gtktreemodelsort.h"
28 #include "gtksignal.h"
39 typedef struct _SortElt SortElt;
49 typedef struct _SortData SortData;
54 GValueCompareFunc func;
57 static guint tree_model_sort_signals[LAST_SIGNAL] = { 0 };
60 #define get_array(e,t) ((GArray *)((e)->parent?(e)->parent->children:GTK_TREE_MODEL_SORT(t)->root))
63 static void gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort);
64 static void gtk_tree_model_sort_class_init (GtkTreeModelSortClass *tree_model_sort_class);
65 static void gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface);
66 static void gtk_tree_model_sort_finalize (GObject *object);
67 static void gtk_tree_model_sort_changed (GtkTreeModel *model,
71 static void gtk_tree_model_sort_inserted (GtkTreeModel *model,
75 static void gtk_tree_model_sort_child_toggled (GtkTreeModel *model,
79 static void gtk_tree_model_sort_deleted (GtkTreeModel *model,
82 static gint gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model);
83 static GType gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
85 static gboolean gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
88 static GtkTreePath *gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
90 static void gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
94 static gboolean gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
96 static gboolean gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
99 static gboolean gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
101 static gint gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
103 static gboolean gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
107 static gboolean gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
110 static void gtk_tree_model_sort_ref_iter (GtkTreeModel *tree_model,
112 static void gtk_tree_model_sort_unref_iter (GtkTreeModel *tree_model,
115 /* Internal functions */
116 static gint gtk_tree_model_sort_array_find_insert (GtkTreeModelSort *tree_model_sort,
119 gboolean skip_sort_elt);
120 static GtkTreePath *gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
121 GtkTreePath *child_path,
122 gboolean build_children);
123 static void gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
125 static void gtk_tree_model_sort_free_level (GArray *array);
126 static GFunc gtk_tree_model_sort_get_func (GtkTreeModelSort *tree_model_sort);
127 static gint gtk_tree_model_sort_func (gconstpointer a,
130 static gint g_value_string_compare_func (const GValue *a,
132 static gint g_value_int_compare_func (const GValue *a,
138 gtk_tree_model_sort_get_type (void)
140 static GtkType tree_model_sort_type = 0;
142 if (!tree_model_sort_type)
144 static const GTypeInfo tree_model_sort_info =
146 sizeof (GtkTreeModelSortClass),
147 NULL, /* base_init */
148 NULL, /* base_finalize */
149 (GClassInitFunc) gtk_tree_model_sort_class_init,
150 NULL, /* class_finalize */
151 NULL, /* class_data */
152 sizeof (GtkTreeModelSort),
154 (GInstanceInitFunc) gtk_tree_model_sort_init
157 static const GInterfaceInfo tree_model_info =
159 (GInterfaceInitFunc) gtk_tree_model_sort_tree_model_init,
164 tree_model_sort_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeModelSort", &tree_model_sort_info, 0);
165 g_type_add_interface_static (tree_model_sort_type,
170 return tree_model_sort_type;
174 gtk_tree_model_sort_class_init (GtkTreeModelSortClass *tree_model_sort_class)
176 GObjectClass *object_class;
178 object_class = (GObjectClass *) tree_model_sort_class;
180 object_class->finalize = gtk_tree_model_sort_finalize;
182 tree_model_sort_signals[CHANGED] =
183 gtk_signal_new ("changed",
185 GTK_CLASS_TYPE (object_class),
186 GTK_SIGNAL_OFFSET (GtkTreeModelSortClass, changed),
187 gtk_marshal_VOID__POINTER_POINTER,
191 tree_model_sort_signals[INSERTED] =
192 gtk_signal_new ("inserted",
194 GTK_CLASS_TYPE (object_class),
195 GTK_SIGNAL_OFFSET (GtkTreeModelSortClass, inserted),
196 gtk_marshal_VOID__POINTER_POINTER,
200 tree_model_sort_signals[CHILD_TOGGLED] =
201 gtk_signal_new ("child_toggled",
203 GTK_CLASS_TYPE (object_class),
204 GTK_SIGNAL_OFFSET (GtkTreeModelSortClass, child_toggled),
205 gtk_marshal_VOID__POINTER_POINTER,
209 tree_model_sort_signals[DELETED] =
210 gtk_signal_new ("deleted",
212 GTK_CLASS_TYPE (object_class),
213 GTK_SIGNAL_OFFSET (GtkTreeModelSortClass, deleted),
214 gtk_marshal_VOID__POINTER,
220 gtk_tree_model_sort_tree_model_init (GtkTreeModelIface *iface)
222 iface->get_n_columns = gtk_tree_model_sort_get_n_columns;
223 iface->get_column_type = gtk_tree_model_sort_get_column_type;
224 iface->get_iter = gtk_tree_model_sort_get_iter;
225 iface->get_path = gtk_tree_model_sort_get_path;
226 iface->get_value = gtk_tree_model_sort_get_value;
227 iface->iter_next = gtk_tree_model_sort_iter_next;
228 iface->iter_children = gtk_tree_model_sort_iter_children;
229 iface->iter_has_child = gtk_tree_model_sort_iter_has_child;
230 iface->iter_n_children = gtk_tree_model_sort_iter_n_children;
231 iface->iter_nth_child = gtk_tree_model_sort_iter_nth_child;
232 iface->iter_parent = gtk_tree_model_sort_iter_parent;
233 iface->ref_iter = gtk_tree_model_sort_ref_iter;
234 iface->unref_iter = gtk_tree_model_sort_unref_iter;
238 gtk_tree_model_sort_init (GtkTreeModelSort *tree_model_sort)
240 tree_model_sort->stamp = g_random_int ();
244 gtk_tree_model_sort_new (void)
246 return GTK_TREE_MODEL (gtk_type_new (gtk_tree_model_sort_get_type ()));
250 gtk_tree_model_sort_new_with_model (GtkTreeModel *child_model,
251 GValueCompareFunc func,
254 GtkTreeModel *retval;
256 retval = gtk_tree_model_sort_new ();
257 gtk_tree_model_sort_set_model (GTK_TREE_MODEL_SORT (retval), child_model);
259 GTK_TREE_MODEL_SORT (retval)->func = func;
260 GTK_TREE_MODEL_SORT (retval)->sort_col = sort_col;
265 * gtk_tree_model_sort_set_model:
266 * @tree_model_sort: The #GtkTreeModelSort.
267 * @child_model: A #GtkTreeModel, or NULL.
269 * Sets the model of @tree_model_sort to be @model. If @model is NULL, then the
270 * old model is unset.
273 gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
274 GtkTreeModel *child_model)
276 g_return_if_fail (tree_model_sort != NULL);
277 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort));
280 g_object_ref (G_OBJECT (child_model));
282 if (tree_model_sort->child_model)
284 gtk_signal_disconnect_by_func (GTK_OBJECT (tree_model_sort->child_model),
285 gtk_tree_model_sort_changed,
287 gtk_signal_disconnect_by_func (GTK_OBJECT (tree_model_sort->child_model),
288 gtk_tree_model_sort_inserted,
290 gtk_signal_disconnect_by_func (GTK_OBJECT (tree_model_sort->child_model),
291 gtk_tree_model_sort_child_toggled,
293 gtk_signal_disconnect_by_func (GTK_OBJECT (tree_model_sort->child_model),
294 gtk_tree_model_sort_deleted,
297 g_object_unref (G_OBJECT (tree_model_sort->child_model));
300 tree_model_sort->child_model = child_model;
304 gtk_signal_connect (GTK_OBJECT (child_model),
306 gtk_tree_model_sort_changed,
308 gtk_signal_connect (GTK_OBJECT (child_model),
310 gtk_tree_model_sort_inserted,
312 gtk_signal_connect (GTK_OBJECT (child_model),
314 gtk_tree_model_sort_child_toggled,
316 gtk_signal_connect (GTK_OBJECT (child_model),
318 gtk_tree_model_sort_deleted,
320 tree_model_sort->flags = gtk_tree_model_get_flags (child_model);
325 * gtk_tree_model_sort_get_model:
326 * @tree_model: a #GtkTreeModelSort
328 * Returns the model the #GtkTreeModelSort is sorting.
330 * Return value: the "child model" being sorted
333 gtk_tree_model_sort_get_model (GtkTreeModelSort *tree_model)
335 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
337 return tree_model->child_model;
341 * gtk_tree_model_sort_convert_path:
342 * @tree_model_sort: The #GtkTreeModelSort.
343 * @child_path: A #GtkTreePath, relative to the child model.
345 * Converts the @child_path to a new path, relative to the sorted position. In other
346 * words, the value found in the @tree_model_sort ->child_model at the @child_path, is
347 * identical to that found in the @tree_model_sort and the return value.
349 * Return value: A new path, or NULL if @child_path does not exist in @tree_model_sort
353 gtk_tree_model_sort_convert_path (GtkTreeModelSort *tree_model_sort,
354 GtkTreePath *child_path)
356 g_return_val_if_fail (tree_model_sort != NULL, NULL);
357 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
358 g_return_val_if_fail (child_path != NULL, NULL);
360 return gtk_tree_model_sort_convert_path_real (tree_model_sort, child_path, TRUE);
364 gtk_tree_model_sort_finalize (GObject *object)
366 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) object;
368 if (tree_model_sort->root)
369 gtk_tree_model_sort_free_level (tree_model_sort->root);
371 if (tree_model_sort->child_model)
373 g_object_unref (G_OBJECT (tree_model_sort->child_model));
374 tree_model_sort->child_model = NULL;
379 gtk_tree_model_sort_changed (GtkTreeModel *s_model,
384 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
389 gboolean free_s_path = FALSE;
392 g_return_if_fail (s_path != NULL || s_iter != NULL);
397 s_path = gtk_tree_model_get_path (s_model, s_iter);
400 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
404 gtk_tree_path_free (s_path);
408 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
409 elt = (SortElt *) iter.user_data;
410 array = get_array (elt, tree_model_sort);
412 /* FIXME: as an optimization for when the column other then the one we're
413 * sorting is changed, we can check the prev and next element to see if
417 /* Now we need to resort things. */
418 index = gtk_tree_model_sort_array_find_insert (tree_model_sort,
422 g_print ("index is %d\n", index);
423 gtk_signal_emit_by_name (GTK_OBJECT (data), "changed", path, &iter);
425 gtk_tree_path_free (path);
427 gtk_tree_path_free (s_path);
430 /* FALSE if the value was inserted, TRUE otherwise */
432 gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
436 GtkTreePath *tmp_path;
444 offset = gtk_tree_path_get_indices (s_path)[gtk_tree_path_get_depth (s_path) - 1];
451 tmp_path = gtk_tree_path_copy (s_path);
453 if (gtk_tree_path_up (tmp_path))
455 GtkTreePath *parent_path;
457 parent_path = gtk_tree_model_sort_convert_path_real (sort, tmp_path, FALSE);
458 if (parent_path == NULL)
460 gtk_tree_path_free (tmp_path);
463 gtk_tree_model_get_iter (GTK_TREE_MODEL (sort), &iter, parent_path);
464 elt.parent = ((SortElt *) iter.user_data);
465 array = ((SortElt *) iter.user_data)->children;
466 gtk_tree_path_free (parent_path);
469 gtk_tree_path_free (tmp_path);
475 if (sort->root == NULL)
476 sort->root = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), 1);
480 gtk_tree_path_free (tmp_path);
482 index = gtk_tree_model_sort_array_find_insert (sort, array, (GtkTreeIter *) &elt, FALSE);
484 g_array_insert_vals (array, index, &elt, 1);
486 /* update all the larger offsets */
487 tmp_elt = (SortElt *) array->data;
488 for (j = 0; j < array->len; j++, tmp_elt++)
490 if ((tmp_elt->offset >= offset) &&
499 gtk_tree_model_sort_inserted (GtkTreeModel *s_model,
504 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
508 g_return_if_fail (s_path != NULL || s_iter != NULL);
511 s_path = gtk_tree_model_get_path (s_model, s_iter);
513 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
515 gtk_tree_model_sort_free_level ((GArray *) tree_model_sort->root);
516 tree_model_sort->root = NULL;
520 GtkTreeIter real_s_iter;
523 gtk_tree_model_get_iter (s_model, &real_s_iter, s_path);
525 real_s_iter = (* s_iter);
527 if (!gtk_tree_model_sort_insert_value (tree_model_sort, s_path, &real_s_iter))
531 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
535 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
536 gtk_signal_emit_by_name (GTK_OBJECT (data), "inserted", path, &iter);
537 gtk_tree_path_free (path);
541 gtk_tree_model_sort_child_toggled (GtkTreeModel *s_model,
546 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
549 gboolean free_s_path = FALSE;
551 g_return_if_fail (s_path != NULL || s_iter != NULL);
553 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
555 gtk_tree_model_sort_free_level ((GArray *)tree_model_sort->root);
556 tree_model_sort->root = NULL;
561 s_path = gtk_tree_model_get_path (s_model, s_iter);
565 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
568 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
569 gtk_signal_emit_by_name (GTK_OBJECT (data),
572 gtk_tree_path_free (path);
574 gtk_tree_path_free (s_path);
578 gtk_tree_model_sort_deleted (GtkTreeModel *s_model,
582 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
585 g_return_if_fail (s_path != NULL);
586 path = gtk_tree_model_sort_convert_path (tree_model_sort, s_path);
587 g_return_if_fail (path != NULL);
589 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
591 gtk_tree_model_sort_free_level ((GArray *)tree_model_sort->root);
592 tree_model_sort->root = NULL;
602 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort), &iter, path);
603 elt = (SortElt *) iter.user_data;
604 offset = elt->offset;
605 array = get_array (elt, tree_model_sort);
608 if (((SortElt *)array->data)->parent == NULL)
609 tree_model_sort->root = NULL;
611 (((SortElt *)array->data)->parent)->children = NULL;
612 gtk_tree_model_sort_free_level (array);
616 g_array_remove_index (array, elt - ((SortElt *) array->data));
618 for (i = 0; i < array->len; i++)
620 elt = & (g_array_index (array, SortElt, i));
621 if (elt->offset > offset)
627 tree_model_sort->stamp++;
628 gtk_signal_emit_by_name (GTK_OBJECT (data), "deleted", path);
629 gtk_tree_path_free (path);
633 gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model)
635 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
636 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
638 return gtk_tree_model_get_n_columns (GTK_TREE_MODEL_SORT (tree_model)->child_model);
642 gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
645 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), G_TYPE_INVALID);
646 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, G_TYPE_INVALID);
648 return gtk_tree_model_get_column_type (GTK_TREE_MODEL_SORT (tree_model)->child_model, index);
652 gtk_tree_model_sort_get_iter_helper (GtkTreeModelSort *tree_model_sort,
663 if (gtk_tree_path_get_indices (path)[depth] > array->len)
666 elt = & (g_array_index (array, SortElt, gtk_tree_path_get_indices (path)[depth]));
668 if (depth == gtk_tree_path_get_depth (path) - 1)
670 iter->stamp = tree_model_sort->stamp;
671 iter->user_data = elt;
675 if (elt->children != NULL)
676 return gtk_tree_model_sort_get_iter_helper (tree_model_sort,
682 if (gtk_tree_model_iter_has_child (tree_model_sort->child_model,
685 gtk_tree_model_sort_build_level (tree_model_sort, elt);
687 return gtk_tree_model_sort_get_iter_helper (tree_model_sort,
695 gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
699 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
700 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
702 if (GTK_TREE_MODEL_SORT (tree_model)->root == NULL)
703 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), NULL);
705 return gtk_tree_model_sort_get_iter_helper (GTK_TREE_MODEL_SORT (tree_model),
706 GTK_TREE_MODEL_SORT (tree_model)->root,
711 gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
714 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
715 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, NULL);
717 return gtk_tree_model_get_path (GTK_TREE_MODEL_SORT (tree_model)->child_model, iter);
721 gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
728 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
729 g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
730 g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
732 elt = iter->user_data;
734 gtk_tree_model_get_value (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt, column, value);
738 gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
744 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
745 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
746 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
748 elt = iter->user_data;
749 array = get_array (elt, tree_model);
751 if (elt - ((SortElt*) array->data) >= array->len - 1)
756 iter->user_data = elt + 1;
761 gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
767 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
768 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
771 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
774 elt = parent->user_data;
776 elt = (SortElt *) ((GArray *)GTK_TREE_MODEL_SORT (tree_model)->root)->data;
781 if (elt->children == NULL &&
782 gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt))
783 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), elt);
785 if (elt->children == NULL)
788 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
789 iter->user_data = elt->children->data;
795 gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
800 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
801 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
802 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
804 elt = iter->user_data;
808 return gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *) elt);
812 gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
817 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
818 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
819 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, 0);
821 elt = iter->user_data;
823 return elt->children->len;
825 return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *) elt);
830 gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
837 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
838 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
840 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
842 elt = iter->user_data;
845 if (elt->children == NULL)
847 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt))
848 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), elt);
853 if (elt->children == NULL)
856 if (n >= elt->children->len)
859 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
860 iter->user_data = &g_array_index (elt->children, SortElt, n);
866 gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
872 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
873 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
874 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == child->stamp, FALSE);
876 elt = iter->user_data;
879 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
880 iter->user_data = elt->parent;
888 gtk_tree_model_sort_ref_iter (GtkTreeModel *tree_model,
894 gtk_tree_model_sort_unref_iter (GtkTreeModel *tree_model,
900 /* Internal functions */
903 gtk_tree_model_sort_array_find_insert (GtkTreeModelSort *tree_model_sort,
906 gboolean skip_sort_elt)
910 GValueCompareFunc func;
911 GValue value = {0, };
912 GValue tmp_value = {0, };
915 func = (GValueCompareFunc) gtk_tree_model_sort_get_func (tree_model_sort);
917 g_return_val_if_fail (func != NULL, 0);
919 gtk_tree_model_get_value (tree_model_sort->child_model, iter, tree_model_sort->sort_col, &value);
921 for (middle = 0; middle < array->len; middle++)
923 tmp_elt = &(g_array_index (array, SortElt, middle));
924 if (!skip_sort_elt &&
925 (SortElt *) iter == tmp_elt)
927 gtk_tree_model_get_value (tree_model_sort->child_model,
928 (GtkTreeIter *) tmp_elt,
929 tree_model_sort->sort_col,
932 cmp = ((func) (&value, &tmp_value));
933 g_value_unset (&tmp_value);
943 gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
944 GtkTreePath *child_path,
945 gboolean build_children)
952 if (tree_model_sort->root == NULL)
955 gtk_tree_model_sort_build_level (tree_model_sort, NULL);
960 retval = gtk_tree_path_new ();
961 array = (GArray *) tree_model_sort->root;
962 indices = gtk_tree_path_get_indices (child_path);
967 gboolean found = FALSE;
970 if ((array->len < indices[i]) || (array == NULL))
972 gtk_tree_path_free (retval);
976 elt = (SortElt *) array->data;
977 for (j = 0; j < array->len; j++, elt++)
979 if (elt->offset == indices[i])
987 gtk_tree_path_free (retval);
991 gtk_tree_path_prepend_index (retval, j);
995 if (i == gtk_tree_path_get_depth (child_path))
998 if (elt->children == NULL)
1002 gtk_tree_path_prepend_index (retval, j);
1003 gtk_tree_model_sort_build_level (tree_model_sort, elt);
1007 gtk_tree_path_free (retval);
1018 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
1023 GtkTreeIter *parent_iter = NULL;
1029 parent_iter = & (place->iter);
1032 n = gtk_tree_model_iter_n_children (tree_model_sort->child_model, parent_iter);
1037 children = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), n);
1040 place->children = children;
1042 tree_model_sort->root = children;
1044 gtk_tree_model_iter_children (tree_model_sort->child_model,
1052 elt.children = NULL;
1056 g_array_append_vals (children, &elt, 1);
1059 while (gtk_tree_model_iter_next (tree_model_sort->child_model, &iter));
1061 sort_data.func = (GValueCompareFunc) gtk_tree_model_sort_get_func (tree_model_sort);
1062 sort_data.model = tree_model_sort->child_model;
1063 sort_data.sort_col = tree_model_sort->sort_col;
1065 g_array_sort_with_data (children, gtk_tree_model_sort_func, &sort_data);
1069 gtk_tree_model_sort_free_level (GArray *array)
1076 for (i = 0; i < array->len; i++)
1080 elt = &g_array_index (array, SortElt, i);
1082 gtk_tree_model_sort_free_level (array);
1085 g_array_free (array, TRUE);
1089 gtk_tree_model_sort_get_func (GtkTreeModelSort *tree_model_sort)
1091 GValueCompareFunc func;
1092 if (tree_model_sort->func)
1093 func = tree_model_sort->func;
1096 switch (gtk_tree_model_get_column_type (tree_model_sort->child_model,
1097 tree_model_sort->sort_col))
1100 func = &g_value_string_compare_func;
1103 func = &g_value_int_compare_func;
1106 g_warning ("No comparison function for row %d (Type %s)\n",
1107 tree_model_sort->sort_col,
1108 g_type_name (gtk_tree_model_get_column_type (tree_model_sort->child_model,
1109 tree_model_sort->sort_col)));
1114 return (GFunc) func;
1118 gtk_tree_model_sort_func (gconstpointer a,
1122 GValue value_a = {0, };
1123 GValue value_b = {0, };
1124 SortData *sort_data = user_data;
1127 gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) a, sort_data->sort_col, &value_a);
1128 gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) b, sort_data->sort_col, &value_b);
1130 retval = (sort_data->func) (&value_a, &value_b);
1132 g_value_unset (&value_a);
1133 g_value_unset (&value_b);
1140 g_value_string_compare_func (const GValue *a,
1143 gchar *a_str = g_value_get_string (a);
1144 gchar *b_str = g_value_get_string (b);
1147 return a_str == NULL;
1151 return strcmp (a_str, b_str);
1155 g_value_int_compare_func (const GValue *a,
1158 gint a_int = g_value_get_int (a);
1159 gint b_int = g_value_get_int (b);
1163 else if (a_int > b_int)
1173 /* FIXME: we can, as we are an array, do binary search to find the correct
1174 * location to insert the element. However, I'd rather get it working. The
1175 * below is quite wrong, but a step in the right direction.
1179 middle = (low + high)/2;
1181 /* Insert the value into the array */
1185 tmp_elt = &(g_array_index (array, SortElt, middle));
1186 gtk_tree_model_get_value (sort->child_model,
1187 (GtkTreeIter *) tmp_elt,
1191 cmp = ((func) (&tmp_value, &s_value));
1192 g_value_unset (&tmp_value);
1200 middle = (low + high)/2;