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_convert_path:
326 * @tree_model_sort: The #GtkTreeModelSort.
327 * @child_path: A #GtkTreePath, relative to the child model.
329 * Converts the @child_path to a new path, relative to the sorted position. In other
330 * words, the value found in the @tree_model_sort ->child_model at the @child_path, is
331 * identical to that found in the @tree_model_sort and the return value.
333 * Return value: A new path, or NULL if @child_path does not exist in @tree_model_sort
337 gtk_tree_model_sort_convert_path (GtkTreeModelSort *tree_model_sort,
338 GtkTreePath *child_path)
340 g_return_val_if_fail (tree_model_sort != NULL, NULL);
341 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
342 g_return_val_if_fail (child_path != NULL, NULL);
344 return gtk_tree_model_sort_convert_path_real (tree_model_sort, child_path, TRUE);
348 gtk_tree_model_sort_finalize (GObject *object)
350 GtkTreeModelSort *tree_model_sort = (GtkTreeModelSort *) object;
352 if (tree_model_sort->root)
353 gtk_tree_model_sort_free_level (tree_model_sort->root);
355 if (tree_model_sort->child_model)
357 g_object_unref (G_OBJECT (tree_model_sort->child_model));
358 tree_model_sort->child_model = NULL;
363 gtk_tree_model_sort_changed (GtkTreeModel *s_model,
368 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
373 gboolean free_s_path = FALSE;
376 g_return_if_fail (s_path != NULL || s_iter != NULL);
381 s_path = gtk_tree_model_get_path (s_model, s_iter);
384 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
388 gtk_tree_path_free (s_path);
392 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
393 elt = (SortElt *) iter.user_data;
394 array = get_array (elt, tree_model_sort);
396 /* FIXME: as an optimization for when the column other then the one we're
397 * sorting is changed, we can check the prev and next element to see if
401 /* Now we need to resort things. */
402 index = gtk_tree_model_sort_array_find_insert (tree_model_sort,
406 g_print ("index is %d\n", index);
407 gtk_signal_emit_by_name (GTK_OBJECT (data), "changed", path, &iter);
409 gtk_tree_path_free (path);
411 gtk_tree_path_free (s_path);
414 /* FALSE if the value was inserted, TRUE otherwise */
416 gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
420 GtkTreePath *tmp_path;
428 offset = gtk_tree_path_get_indices (s_path)[gtk_tree_path_get_depth (s_path) - 1];
435 tmp_path = gtk_tree_path_copy (s_path);
437 if (gtk_tree_path_up (tmp_path))
439 GtkTreePath *parent_path;
441 parent_path = gtk_tree_model_sort_convert_path_real (sort, tmp_path, FALSE);
442 if (parent_path == NULL)
444 gtk_tree_path_free (tmp_path);
447 gtk_tree_model_get_iter (GTK_TREE_MODEL (sort), &iter, parent_path);
448 elt.parent = ((SortElt *) iter.user_data);
449 array = ((SortElt *) iter.user_data)->children;
450 gtk_tree_path_free (parent_path);
453 gtk_tree_path_free (tmp_path);
459 if (sort->root == NULL)
460 sort->root = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), 1);
464 gtk_tree_path_free (tmp_path);
466 index = gtk_tree_model_sort_array_find_insert (sort, array, (GtkTreeIter *) &elt, FALSE);
468 g_array_insert_vals (array, index, &elt, 1);
470 /* update all the larger offsets */
471 tmp_elt = (SortElt *) array->data;
472 for (j = 0; j < array->len; j++, tmp_elt++)
474 if ((tmp_elt->offset >= offset) &&
483 gtk_tree_model_sort_inserted (GtkTreeModel *s_model,
488 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
492 g_return_if_fail (s_path != NULL || s_iter != NULL);
495 s_path = gtk_tree_model_get_path (s_model, s_iter);
497 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
499 gtk_tree_model_sort_free_level ((GArray *) tree_model_sort->root);
500 tree_model_sort->root = NULL;
504 GtkTreeIter real_s_iter;
507 gtk_tree_model_get_iter (s_model, &real_s_iter, s_path);
509 real_s_iter = (* s_iter);
511 if (!gtk_tree_model_sort_insert_value (tree_model_sort, s_path, &real_s_iter))
515 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
519 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
520 gtk_signal_emit_by_name (GTK_OBJECT (data), "inserted", path, &iter);
521 gtk_tree_path_free (path);
525 gtk_tree_model_sort_child_toggled (GtkTreeModel *s_model,
530 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
533 gboolean free_s_path = FALSE;
535 g_return_if_fail (s_path != NULL || s_iter != NULL);
537 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
539 gtk_tree_model_sort_free_level ((GArray *)tree_model_sort->root);
540 tree_model_sort->root = NULL;
545 s_path = gtk_tree_model_get_path (s_model, s_iter);
549 path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
552 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
553 gtk_signal_emit_by_name (GTK_OBJECT (data),
556 gtk_tree_path_free (path);
558 gtk_tree_path_free (s_path);
562 gtk_tree_model_sort_deleted (GtkTreeModel *s_model,
566 GtkTreeModelSort *tree_model_sort = GTK_TREE_MODEL_SORT (data);
569 g_return_if_fail (s_path != NULL);
570 path = gtk_tree_model_sort_convert_path (tree_model_sort, s_path);
571 g_return_if_fail (path != NULL);
573 if (!(tree_model_sort->flags & GTK_TREE_MODEL_ITERS_PERSIST))
575 gtk_tree_model_sort_free_level ((GArray *)tree_model_sort->root);
576 tree_model_sort->root = NULL;
586 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_sort), &iter, path);
587 elt = (SortElt *) iter.user_data;
588 offset = elt->offset;
589 array = get_array (elt, tree_model_sort);
592 if (((SortElt *)array->data)->parent == NULL)
593 tree_model_sort->root = NULL;
595 (((SortElt *)array->data)->parent)->children = NULL;
596 gtk_tree_model_sort_free_level (array);
600 g_array_remove_index (array, elt - ((SortElt *) array->data));
602 for (i = 0; i < array->len; i++)
604 elt = & (g_array_index (array, SortElt, i));
605 if (elt->offset > offset)
611 tree_model_sort->stamp++;
612 gtk_signal_emit_by_name (GTK_OBJECT (data), "deleted", path);
613 gtk_tree_path_free (path);
617 gtk_tree_model_sort_get_n_columns (GtkTreeModel *tree_model)
619 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
620 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
622 return gtk_tree_model_get_n_columns (GTK_TREE_MODEL_SORT (tree_model)->child_model);
626 gtk_tree_model_sort_get_column_type (GtkTreeModel *tree_model,
629 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), G_TYPE_INVALID);
630 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, G_TYPE_INVALID);
632 return gtk_tree_model_get_column_type (GTK_TREE_MODEL_SORT (tree_model)->child_model, index);
636 gtk_tree_model_sort_get_iter_helper (GtkTreeModelSort *tree_model_sort,
647 if (gtk_tree_path_get_indices (path)[depth] > array->len)
650 elt = & (g_array_index (array, SortElt, gtk_tree_path_get_indices (path)[depth]));
652 if (depth == gtk_tree_path_get_depth (path) - 1)
654 iter->stamp = tree_model_sort->stamp;
655 iter->user_data = elt;
659 if (elt->children != NULL)
660 return gtk_tree_model_sort_get_iter_helper (tree_model_sort,
666 if (gtk_tree_model_iter_has_child (tree_model_sort->child_model,
669 gtk_tree_model_sort_build_level (tree_model_sort, elt);
671 return gtk_tree_model_sort_get_iter_helper (tree_model_sort,
679 gtk_tree_model_sort_get_iter (GtkTreeModel *tree_model,
683 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
684 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
686 if (GTK_TREE_MODEL_SORT (tree_model)->root == NULL)
687 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), NULL);
689 return gtk_tree_model_sort_get_iter_helper (GTK_TREE_MODEL_SORT (tree_model),
690 GTK_TREE_MODEL_SORT (tree_model)->root,
695 gtk_tree_model_sort_get_path (GtkTreeModel *tree_model,
698 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), NULL);
699 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, NULL);
701 return gtk_tree_model_get_path (GTK_TREE_MODEL_SORT (tree_model)->child_model, iter);
705 gtk_tree_model_sort_get_value (GtkTreeModel *tree_model,
712 g_return_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model));
713 g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL);
714 g_return_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp);
716 elt = iter->user_data;
718 gtk_tree_model_get_value (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt, column, value);
722 gtk_tree_model_sort_iter_next (GtkTreeModel *tree_model,
728 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
729 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
730 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
732 elt = iter->user_data;
733 array = get_array (elt, tree_model);
735 if (elt - ((SortElt*) array->data) >= array->len - 1)
740 iter->user_data = elt + 1;
745 gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
751 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
752 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
755 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
758 elt = parent->user_data;
760 elt = (SortElt *) ((GArray *)GTK_TREE_MODEL_SORT (tree_model)->root)->data;
765 if (elt->children == NULL &&
766 gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt))
767 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), elt);
769 if (elt->children == NULL)
772 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
773 iter->user_data = elt->children->data;
779 gtk_tree_model_sort_iter_has_child (GtkTreeModel *tree_model,
784 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
785 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
786 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, FALSE);
788 elt = iter->user_data;
792 return gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *) elt);
796 gtk_tree_model_sort_iter_n_children (GtkTreeModel *tree_model,
801 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), 0);
802 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, 0);
803 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == iter->stamp, 0);
805 elt = iter->user_data;
807 return elt->children->len;
809 return gtk_tree_model_iter_n_children (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *) elt);
814 gtk_tree_model_sort_iter_nth_child (GtkTreeModel *tree_model,
821 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
822 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
824 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
826 elt = iter->user_data;
829 if (elt->children == NULL)
831 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL_SORT (tree_model)->child_model, (GtkTreeIter *)elt))
832 gtk_tree_model_sort_build_level (GTK_TREE_MODEL_SORT (tree_model), elt);
837 if (elt->children == NULL)
840 if (n >= elt->children->len)
843 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
844 iter->user_data = &g_array_index (elt->children, SortElt, n);
850 gtk_tree_model_sort_iter_parent (GtkTreeModel *tree_model,
856 g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
857 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
858 g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == child->stamp, FALSE);
860 elt = iter->user_data;
863 iter->stamp = GTK_TREE_MODEL_SORT (tree_model)->stamp;
864 iter->user_data = elt->parent;
872 gtk_tree_model_sort_ref_iter (GtkTreeModel *tree_model,
878 gtk_tree_model_sort_unref_iter (GtkTreeModel *tree_model,
884 /* Internal functions */
887 gtk_tree_model_sort_array_find_insert (GtkTreeModelSort *tree_model_sort,
890 gboolean skip_sort_elt)
894 GValueCompareFunc func;
895 GValue value = {0, };
896 GValue tmp_value = {0, };
899 func = (GValueCompareFunc) gtk_tree_model_sort_get_func (tree_model_sort);
901 g_return_val_if_fail (func != NULL, 0);
903 gtk_tree_model_get_value (tree_model_sort->child_model, iter, tree_model_sort->sort_col, &value);
905 for (middle = 0; middle < array->len; middle++)
907 tmp_elt = &(g_array_index (array, SortElt, middle));
908 if (!skip_sort_elt &&
909 (SortElt *) iter == tmp_elt)
911 gtk_tree_model_get_value (tree_model_sort->child_model,
912 (GtkTreeIter *) tmp_elt,
913 tree_model_sort->sort_col,
916 cmp = ((func) (&value, &tmp_value));
917 g_value_unset (&tmp_value);
927 gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
928 GtkTreePath *child_path,
929 gboolean build_children)
936 if (tree_model_sort->root == NULL)
939 gtk_tree_model_sort_build_level (tree_model_sort, NULL);
944 retval = gtk_tree_path_new ();
945 array = (GArray *) tree_model_sort->root;
946 indices = gtk_tree_path_get_indices (child_path);
951 gboolean found = FALSE;
954 if ((array->len < indices[i]) || (array == NULL))
956 gtk_tree_path_free (retval);
960 elt = (SortElt *) array->data;
961 for (j = 0; j < array->len; j++, elt++)
963 if (elt->offset == indices[i])
971 gtk_tree_path_free (retval);
975 gtk_tree_path_prepend_index (retval, j);
979 if (i == gtk_tree_path_get_depth (child_path))
982 if (elt->children == NULL)
986 gtk_tree_path_prepend_index (retval, j);
987 gtk_tree_model_sort_build_level (tree_model_sort, elt);
991 gtk_tree_path_free (retval);
1002 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
1007 GtkTreeIter *parent_iter = NULL;
1013 parent_iter = & (place->iter);
1016 n = gtk_tree_model_iter_n_children (tree_model_sort->child_model, parent_iter);
1021 children = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), n);
1024 place->children = children;
1026 tree_model_sort->root = children;
1028 gtk_tree_model_iter_children (tree_model_sort->child_model,
1036 elt.children = NULL;
1040 g_array_append_vals (children, &elt, 1);
1043 while (gtk_tree_model_iter_next (tree_model_sort->child_model, &iter));
1045 sort_data.func = (GValueCompareFunc) gtk_tree_model_sort_get_func (tree_model_sort);
1046 sort_data.model = tree_model_sort->child_model;
1047 sort_data.sort_col = tree_model_sort->sort_col;
1049 g_array_sort_with_data (children, gtk_tree_model_sort_func, &sort_data);
1053 gtk_tree_model_sort_free_level (GArray *array)
1060 for (i = 0; i < array->len; i++)
1064 elt = &g_array_index (array, SortElt, i);
1066 gtk_tree_model_sort_free_level (array);
1069 g_array_free (array, TRUE);
1073 gtk_tree_model_sort_get_func (GtkTreeModelSort *tree_model_sort)
1075 GValueCompareFunc func;
1076 if (tree_model_sort->func)
1077 func = tree_model_sort->func;
1080 switch (gtk_tree_model_get_column_type (tree_model_sort->child_model,
1081 tree_model_sort->sort_col))
1084 func = &g_value_string_compare_func;
1087 func = &g_value_int_compare_func;
1090 g_warning ("No comparison function for row %d (Type %s)\n",
1091 tree_model_sort->sort_col,
1092 g_type_name (gtk_tree_model_get_column_type (tree_model_sort->child_model,
1093 tree_model_sort->sort_col)));
1098 return (GFunc) func;
1102 gtk_tree_model_sort_func (gconstpointer a,
1106 GValue value_a = {0, };
1107 GValue value_b = {0, };
1108 SortData *sort_data = user_data;
1111 gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) a, sort_data->sort_col, &value_a);
1112 gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) b, sort_data->sort_col, &value_b);
1114 retval = (sort_data->func) (&value_a, &value_b);
1116 g_value_unset (&value_a);
1117 g_value_unset (&value_b);
1124 g_value_string_compare_func (const GValue *a,
1127 gchar *a_str = g_value_get_string (a);
1128 gchar *b_str = g_value_get_string (b);
1131 return a_str == NULL;
1135 return strcmp (a_str, b_str);
1139 g_value_int_compare_func (const GValue *a,
1142 gint a_int = g_value_get_int (a);
1143 gint b_int = g_value_get_int (b);
1147 else if (a_int > b_int)
1157 /* FIXME: we can, as we are an array, do binary search to find the correct
1158 * location to insert the element. However, I'd rather get it working. The
1159 * below is quite wrong, but a step in the right direction.
1163 middle = (low + high)/2;
1165 /* Insert the value into the array */
1169 tmp_elt = &(g_array_index (array, SortElt, middle));
1170 gtk_tree_model_get_value (sort->child_model,
1171 (GtkTreeIter *) tmp_elt,
1175 cmp = ((func) (&tmp_value, &s_value));
1176 g_value_unset (&tmp_value);
1184 middle = (low + high)/2;