1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* e-tree-model-generator.c - Model wrapper that permutes underlying rows.
5 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * Authors: Hans Petter Jansson <hpj@novell.com>
28 #include <glib/gi18n-lib.h>
29 #include "e-tree-model-generator.h"
33 #define ITER_IS_VALID(tree_model_generator, iter) \
34 ((iter)->stamp == (tree_model_generator)->priv->stamp)
35 #define ITER_GET(iter, group, index) \
37 *(group) = (iter)->user_data; \
38 *(index) = GPOINTER_TO_INT ((iter)->user_data2); \
41 #define ITER_SET(tree_model_generator, iter, group, index) \
43 (iter)->stamp = (tree_model_generator)->priv->stamp; \
44 (iter)->user_data = group; \
45 (iter)->user_data2 = GINT_TO_POINTER (index); \
48 #define E_TREE_MODEL_GENERATOR_GET_PRIVATE(obj) \
49 (G_TYPE_INSTANCE_GET_PRIVATE \
50 ((obj), E_TYPE_TREE_MODEL_GENERATOR, ETreeModelGeneratorPrivate))
52 struct _ETreeModelGeneratorPrivate {
53 GtkTreeModel *child_model;
57 ETreeModelGeneratorGenerateFunc generate_func;
58 gpointer generate_func_data;
60 ETreeModelGeneratorModifyFunc modify_func;
61 gpointer modify_func_data;
64 static void e_tree_model_generator_tree_model_init (GtkTreeModelIface *iface);
66 G_DEFINE_TYPE_WITH_CODE (
67 ETreeModelGenerator, e_tree_model_generator, G_TYPE_OBJECT,
68 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, e_tree_model_generator_tree_model_init))
70 static GtkTreeModelFlags e_tree_model_generator_get_flags (GtkTreeModel *tree_model);
71 static gint e_tree_model_generator_get_n_columns (GtkTreeModel *tree_model);
72 static GType e_tree_model_generator_get_column_type (GtkTreeModel *tree_model,
74 static gboolean e_tree_model_generator_get_iter (GtkTreeModel *tree_model,
77 static GtkTreePath *e_tree_model_generator_get_path (GtkTreeModel *tree_model,
79 static void e_tree_model_generator_get_value (GtkTreeModel *tree_model,
83 static gboolean e_tree_model_generator_iter_next (GtkTreeModel *tree_model,
85 static gboolean e_tree_model_generator_iter_children (GtkTreeModel *tree_model,
88 static gboolean e_tree_model_generator_iter_has_child (GtkTreeModel *tree_model,
90 static gint e_tree_model_generator_iter_n_children (GtkTreeModel *tree_model,
92 static gboolean e_tree_model_generator_iter_nth_child (GtkTreeModel *tree_model,
96 static gboolean e_tree_model_generator_iter_parent (GtkTreeModel *tree_model,
100 static GArray *build_node_map (ETreeModelGenerator *tree_model_generator, GtkTreeIter *parent_iter,
101 GArray *parent_group, gint parent_index);
102 static void release_node_map (GArray *group);
104 static void child_row_changed (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
105 static void child_row_inserted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
106 static void child_row_deleted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path);
109 GArray *parent_group;
122 /* ------------------ *
123 * Class/object setup *
124 * ------------------ */
127 tree_model_generator_set_property (GObject *object,
132 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
136 case PROP_CHILD_MODEL:
137 tree_model_generator->priv->child_model = g_value_get_object (value);
138 g_object_ref (tree_model_generator->priv->child_model);
140 if (tree_model_generator->priv->root_nodes)
141 release_node_map (tree_model_generator->priv->root_nodes);
142 tree_model_generator->priv->root_nodes =
143 build_node_map (tree_model_generator, NULL, NULL, -1);
145 g_signal_connect_swapped (
146 tree_model_generator->priv->child_model, "row-changed",
147 G_CALLBACK (child_row_changed), tree_model_generator);
148 g_signal_connect_swapped (
149 tree_model_generator->priv->child_model, "row-deleted",
150 G_CALLBACK (child_row_deleted), tree_model_generator);
151 g_signal_connect_swapped (
152 tree_model_generator->priv->child_model, "row-inserted",
153 G_CALLBACK (child_row_inserted), tree_model_generator);
157 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163 tree_model_generator_get_property (GObject *object,
168 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
172 case PROP_CHILD_MODEL:
173 g_value_set_object (value, tree_model_generator->priv->child_model);
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
183 tree_model_generator_finalize (GObject *object)
185 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
187 if (tree_model_generator->priv->child_model) {
188 g_signal_handlers_disconnect_matched (
189 tree_model_generator->priv->child_model,
190 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
191 tree_model_generator);
192 g_object_unref (tree_model_generator->priv->child_model);
195 if (tree_model_generator->priv->root_nodes)
196 release_node_map (tree_model_generator->priv->root_nodes);
198 /* Chain up to parent's finalize() method. */
199 G_OBJECT_CLASS (e_tree_model_generator_parent_class)->finalize (object);
203 e_tree_model_generator_class_init (ETreeModelGeneratorClass *class)
205 GObjectClass *object_class;
207 g_type_class_add_private (class, sizeof (ETreeModelGeneratorPrivate));
209 object_class = G_OBJECT_CLASS (class);
210 object_class->get_property = tree_model_generator_get_property;
211 object_class->set_property = tree_model_generator_set_property;
212 object_class->finalize = tree_model_generator_finalize;
214 g_object_class_install_property (
217 g_param_spec_object (
220 "The child model to extend",
223 G_PARAM_CONSTRUCT_ONLY));
227 e_tree_model_generator_tree_model_init (GtkTreeModelIface *iface)
229 iface->get_flags = e_tree_model_generator_get_flags;
230 iface->get_n_columns = e_tree_model_generator_get_n_columns;
231 iface->get_column_type = e_tree_model_generator_get_column_type;
232 iface->get_iter = e_tree_model_generator_get_iter;
233 iface->get_path = e_tree_model_generator_get_path;
234 iface->get_value = e_tree_model_generator_get_value;
235 iface->iter_next = e_tree_model_generator_iter_next;
236 iface->iter_children = e_tree_model_generator_iter_children;
237 iface->iter_has_child = e_tree_model_generator_iter_has_child;
238 iface->iter_n_children = e_tree_model_generator_iter_n_children;
239 iface->iter_nth_child = e_tree_model_generator_iter_nth_child;
240 iface->iter_parent = e_tree_model_generator_iter_parent;
244 e_tree_model_generator_init (ETreeModelGenerator *tree_model_generator)
246 tree_model_generator->priv =
247 E_TREE_MODEL_GENERATOR_GET_PRIVATE (tree_model_generator);
249 tree_model_generator->priv->stamp = g_random_int ();
250 tree_model_generator->priv->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
253 /* ------------------ *
254 * Row update helpers *
255 * ------------------ */
258 row_deleted (ETreeModelGenerator *tree_model_generator,
263 ETMG_DEBUG (g_print ("row_deleted emitting\n"));
264 gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_model_generator), path);
268 row_inserted (ETreeModelGenerator *tree_model_generator,
275 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
276 ETMG_DEBUG (g_print ("row_inserted emitting\n"));
277 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_model_generator), path, &iter);
279 ETMG_DEBUG (g_print ("row_inserted could not get iter!\n"));
284 row_changed (ETreeModelGenerator *tree_model_generator,
291 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
292 ETMG_DEBUG (g_print ("row_changed emitting\n"));
293 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model_generator), path, &iter);
295 ETMG_DEBUG (g_print ("row_changed could not get iter!\n"));
299 /* -------------------- *
300 * Node map translation *
301 * -------------------- */
304 generated_offset_to_child_offset (GArray *group,
306 gint *internal_offset)
308 gboolean success = FALSE;
309 gint accum_offset = 0;
312 for (i = 0; i < group->len; i++) {
313 Node *node = &g_array_index (group, Node, i);
315 accum_offset += node->n_generated;
316 if (accum_offset > offset) {
317 accum_offset -= node->n_generated;
327 *internal_offset = offset - accum_offset;
333 child_offset_to_generated_offset (GArray *group,
336 gint accum_offset = 0;
339 g_return_val_if_fail (group != NULL, -1);
341 for (i = 0; i < group->len && i < offset; i++) {
342 Node *node = &g_array_index (group, Node, i);
344 accum_offset += node->n_generated;
351 count_generated_nodes (GArray *group)
353 gint accum_offset = 0;
356 for (i = 0; i < group->len; i++) {
357 Node *node = &g_array_index (group, Node, i);
359 accum_offset += node->n_generated;
365 /* ------------------- *
366 * Node map management *
367 * ------------------- */
370 release_node_map (GArray *group)
374 for (i = 0; i < group->len; i++) {
375 Node *node = &g_array_index (group, Node, i);
377 if (node->child_nodes)
378 release_node_map (node->child_nodes);
381 g_array_free (group, TRUE);
385 append_node (GArray *group)
387 g_array_set_size (group, group->len + 1);
388 return group->len - 1;
392 build_node_map (ETreeModelGenerator *tree_model_generator,
393 GtkTreeIter *parent_iter,
394 GArray *parent_group,
402 result = gtk_tree_model_iter_children (tree_model_generator->priv->child_model, &iter, parent_iter);
404 result = gtk_tree_model_get_iter_first (tree_model_generator->priv->child_model, &iter);
409 group = g_array_new (FALSE, FALSE, sizeof (Node));
415 i = append_node (group);
416 node = &g_array_index (group, Node, i);
418 node->parent_group = parent_group;
419 node->parent_index = parent_index;
421 if (tree_model_generator->priv->generate_func)
423 tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
424 &iter, tree_model_generator->priv->generate_func_data);
426 node->n_generated = 1;
428 node->child_nodes = build_node_map (tree_model_generator, &iter, group, i);
429 } while (gtk_tree_model_iter_next (tree_model_generator->priv->child_model, &iter));
435 get_first_visible_index_from (GArray *group,
440 for (i = index; i < group->len; i++) {
441 Node *node = &g_array_index (group, Node, i);
443 if (node->n_generated)
454 get_node_by_child_path (ETreeModelGenerator *tree_model_generator,
462 group = tree_model_generator->priv->root_nodes;
464 for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
468 g_warning ("ETreeModelGenerator got unknown child element!");
472 index = gtk_tree_path_get_indices (path)[depth];
473 node = &g_array_index (group, Node, index);
475 if (depth + 1 < gtk_tree_path_get_depth (path))
476 group = node->child_nodes;
489 create_node_at_child_path (ETreeModelGenerator *tree_model_generator,
492 GtkTreePath *parent_path;
494 GArray *parent_group;
499 parent_path = gtk_tree_path_copy (path);
500 gtk_tree_path_up (parent_path);
501 node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
504 if (!node->child_nodes)
505 node->child_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
507 group = node->child_nodes;
508 parent_index = gtk_tree_path_get_indices (parent_path)[gtk_tree_path_get_depth (parent_path) - 1];
510 if (!tree_model_generator->priv->root_nodes)
511 tree_model_generator->priv->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
513 group = tree_model_generator->priv->root_nodes;
517 gtk_tree_path_free (parent_path);
519 index = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path) - 1];
520 ETMG_DEBUG (g_print ("Inserting index %d into group of length %d\n", index, group->len));
521 index = MIN (index, group->len);
525 if (group->len - 1 - index > 0) {
529 (Node *) group->data + index + 1,
530 (Node *) group->data + index,
531 (group->len - 1 - index) * sizeof (Node));
533 /* Update parent pointers */
534 for (i = index + 1; i < group->len; i++) {
535 Node *pnode = &g_array_index (group, Node, i);
539 child_group = pnode->child_nodes;
543 for (j = 0; j < child_group->len; j++) {
544 Node *child_node = &g_array_index (child_group, Node, j);
545 child_node->parent_index = i;
550 node = &g_array_index (group, Node, index);
551 node->parent_group = parent_group;
552 node->parent_index = parent_index;
553 node->n_generated = 0;
554 node->child_nodes = NULL;
557 g_print ("Created node at offset %d, parent_group = %p, parent_index = %d\n",
558 index, node->parent_group, node->parent_index));
566 dump_group (GArray *group)
570 g_print ("\nGroup %p:\n", group);
572 for (i = 0; i < group->len; i++) {
573 Node *node = &g_array_index (group, Node, i);
575 " %04d: pgroup=%p, pindex=%d, n_generated=%d, child_nodes=%p\n",
576 i, node->parent_group, node->parent_index, node->n_generated, node->child_nodes);
583 delete_node_at_child_path (ETreeModelGenerator *tree_model_generator,
586 GtkTreePath *parent_path;
587 GArray *parent_group;
593 parent_path = gtk_tree_path_copy (path);
594 gtk_tree_path_up (parent_path);
595 node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
598 group = node->child_nodes;
600 group = tree_model_generator->priv->root_nodes;
603 gtk_tree_path_free (parent_path);
608 index = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path) - 1];
609 if (index >= group->len)
612 node = &g_array_index (group, Node, index);
613 if (node->child_nodes)
614 release_node_map (node->child_nodes);
615 g_array_remove_index (group, index);
617 /* Update parent pointers */
618 for (i = index; i < group->len; i++) {
619 Node *pnode = &g_array_index (group, Node, i);
623 child_group = pnode->child_nodes;
627 for (j = 0; j < child_group->len; j++) {
628 Node *child_node = &g_array_index (child_group, Node, j);
629 child_node->parent_index = i;
635 child_row_changed (ETreeModelGenerator *tree_model_generator,
639 GtkTreePath *generated_path;
644 if (tree_model_generator->priv->generate_func)
646 tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
647 iter, tree_model_generator->priv->generate_func_data);
651 node = get_node_by_child_path (tree_model_generator, path, NULL);
655 generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
657 /* FIXME: Converting the path to an iter every time is inefficient */
659 for (i = 0; i < n_generated && i < node->n_generated; i++) {
660 row_changed (tree_model_generator, generated_path);
661 gtk_tree_path_next (generated_path);
664 for (; i < node->n_generated; ) {
666 row_deleted (tree_model_generator, generated_path);
669 for (; i < n_generated; i++) {
671 row_inserted (tree_model_generator, generated_path);
672 gtk_tree_path_next (generated_path);
675 gtk_tree_path_free (generated_path);
679 child_row_inserted (ETreeModelGenerator *tree_model_generator,
683 GtkTreePath *generated_path;
687 if (tree_model_generator->priv->generate_func)
689 tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
690 iter, tree_model_generator->priv->generate_func_data);
694 node = create_node_at_child_path (tree_model_generator, path);
698 generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
700 /* FIXME: Converting the path to an iter every time is inefficient */
702 for (node->n_generated = 0; node->n_generated < n_generated; ) {
704 row_inserted (tree_model_generator, generated_path);
705 gtk_tree_path_next (generated_path);
708 gtk_tree_path_free (generated_path);
712 child_row_deleted (ETreeModelGenerator *tree_model_generator,
715 GtkTreePath *generated_path;
718 node = get_node_by_child_path (tree_model_generator, path, NULL);
722 generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
724 /* FIXME: Converting the path to an iter every time is inefficient */
726 for (; node->n_generated; ) {
728 row_deleted (tree_model_generator, generated_path);
731 delete_node_at_child_path (tree_model_generator, path);
732 gtk_tree_path_free (generated_path);
735 /* ----------------------- *
736 * ETreeModelGenerator API *
737 * ----------------------- */
740 * e_tree_model_generator_new:
741 * @child_model: a #GtkTreeModel
743 * Creates a new #ETreeModelGenerator wrapping @child_model.
745 * Returns: A new #ETreeModelGenerator.
747 ETreeModelGenerator *
748 e_tree_model_generator_new (GtkTreeModel *child_model)
750 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
752 return E_TREE_MODEL_GENERATOR (
753 g_object_new (E_TYPE_TREE_MODEL_GENERATOR,
754 "child-model", child_model, NULL));
758 * e_tree_model_generator_get_model:
759 * @tree_model_generator: an #ETreeModelGenerator
761 * Gets the child model being wrapped by @tree_model_generator.
763 * Returns: A #GtkTreeModel being wrapped.
766 e_tree_model_generator_get_model (ETreeModelGenerator *tree_model_generator)
768 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
770 return tree_model_generator->priv->child_model;
774 * e_tree_model_generator_set_generate_func:
775 * @tree_model_generator: an #ETreeModelGenerator
776 * @func: an #ETreeModelGeneratorGenerateFunc, or %NULL
777 * @data: user data to pass to @func
780 * Sets the callback function used to filter or generate additional rows
781 * based on the child model's data. This function is called for each child
782 * row, and returns a value indicating the number of rows that will be
783 * used to represent the child row - 0 or more.
785 * If @func is %NULL, a filtering/generating function will not be applied.
788 e_tree_model_generator_set_generate_func (ETreeModelGenerator *tree_model_generator,
789 ETreeModelGeneratorGenerateFunc func,
791 GDestroyNotify destroy)
793 g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
795 tree_model_generator->priv->generate_func = func;
796 tree_model_generator->priv->generate_func_data = data;
800 * e_tree_model_generator_set_modify_func:
801 * @tree_model_generator: an #ETreeModelGenerator
802 * @func: an @ETreeModelGeneratorModifyFunc, or %NULL
803 * @data: user data to pass to @func
806 * Sets the callback function used to override values for the child row's
807 * columns and specify values for generated rows' columns.
809 * If @func is %NULL, the child model's values will always be used.
812 e_tree_model_generator_set_modify_func (ETreeModelGenerator *tree_model_generator,
813 ETreeModelGeneratorModifyFunc func,
815 GDestroyNotify destroy)
817 g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
819 tree_model_generator->priv->modify_func = func;
820 tree_model_generator->priv->modify_func_data = data;
824 * e_tree_model_generator_convert_child_path_to_path:
825 * @tree_model_generator: an #ETreeModelGenerator
826 * @child_path: a #GtkTreePath
828 * Convert a path to a child row to a path to a @tree_model_generator row.
830 * Returns: A new GtkTreePath, owned by the caller.
833 e_tree_model_generator_convert_child_path_to_path (ETreeModelGenerator *tree_model_generator,
834 GtkTreePath *child_path)
840 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
841 g_return_val_if_fail (child_path != NULL, NULL);
843 path = gtk_tree_path_new ();
845 group = tree_model_generator->priv->root_nodes;
847 for (depth = 0; depth < gtk_tree_path_get_depth (child_path); depth++) {
850 gint generated_index;
853 g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
857 index = gtk_tree_path_get_indices (child_path)[depth];
858 generated_index = child_offset_to_generated_offset (group, index);
859 node = &g_array_index (group, Node, index);
860 group = node->child_nodes;
862 gtk_tree_path_append_index (path, generated_index);
869 * e_tree_model_generator_convert_child_iter_to_iter:
870 * @tree_model_generator: an #ETreeModelGenerator
871 * @generator_iter: a #GtkTreeIter to set
872 * @child_iter: a #GtkTreeIter to convert
874 * Convert @child_iter to a corresponding #GtkTreeIter for @tree_model_generator,
875 * storing the result in @generator_iter.
878 e_tree_model_generator_convert_child_iter_to_iter (ETreeModelGenerator *tree_model_generator,
879 GtkTreeIter *generator_iter,
880 GtkTreeIter *child_iter)
887 g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
889 path = gtk_tree_model_get_path (tree_model_generator->priv->child_model, child_iter);
893 group = tree_model_generator->priv->root_nodes;
895 for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
898 index = gtk_tree_path_get_indices (path)[depth];
899 node = &g_array_index (group, Node, index);
901 if (depth + 1 < gtk_tree_path_get_depth (path))
902 group = node->child_nodes;
905 g_warning ("ETreeModelGenerator was asked for iter to unknown child element!");
910 g_return_if_fail (group != NULL);
912 index = child_offset_to_generated_offset (group, index);
913 ITER_SET (tree_model_generator, generator_iter, group, index);
914 gtk_tree_path_free (path);
918 * e_tree_model_generator_convert_path_to_child_path:
919 * @tree_model_generator: an #ETreeModelGenerator
920 * @generator_path: a #GtkTreePath to a @tree_model_generator row
922 * Converts @generator_path to a corresponding #GtkTreePath in the child model.
924 * Returns: A new #GtkTreePath, owned by the caller.
927 e_tree_model_generator_convert_path_to_child_path (ETreeModelGenerator *tree_model_generator,
928 GtkTreePath *generator_path)
934 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
935 g_return_val_if_fail (generator_path != NULL, NULL);
937 path = gtk_tree_path_new ();
939 group = tree_model_generator->priv->root_nodes;
941 for (depth = 0; depth < gtk_tree_path_get_depth (generator_path); depth++) {
947 g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
951 index = gtk_tree_path_get_indices (generator_path)[depth];
952 child_index = generated_offset_to_child_offset (group, index, NULL);
953 node = &g_array_index (group, Node, child_index);
954 group = node->child_nodes;
956 gtk_tree_path_append_index (path, child_index);
963 * e_tree_model_generator_convert_iter_to_child_iter:
964 * @tree_model_generator: an #ETreeModelGenerator
965 * @child_iter: a #GtkTreeIter to set
966 * @permutation_n: a permutation index to set
967 * @generator_iter: a #GtkTreeIter indicating the row to convert
969 * Converts a @tree_model_generator row into a child row and permutation index.
970 * The permutation index is the index of the generated row based on this
971 * child row, with the first generated row based on this child row being 0.
974 e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_model_generator,
975 GtkTreeIter *child_iter,
977 GtkTreeIter *generator_iter)
982 gint internal_offset = 0;
984 g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
985 g_return_if_fail (ITER_IS_VALID (tree_model_generator, generator_iter));
987 path = gtk_tree_path_new ();
988 ITER_GET (generator_iter, &group, &index);
990 index = generated_offset_to_child_offset (group, index, &internal_offset);
991 gtk_tree_path_prepend_index (path, index);
994 Node *node = &g_array_index (group, Node, index);
996 group = node->parent_group;
997 index = node->parent_index;
1000 gtk_tree_path_prepend_index (path, index);
1004 gtk_tree_model_get_iter (tree_model_generator->priv->child_model, child_iter, path);
1006 *permutation_n = internal_offset;
1008 gtk_tree_path_free (path);
1011 /* ---------------- *
1012 * GtkTreeModel API *
1013 * ---------------- */
1015 static GtkTreeModelFlags
1016 e_tree_model_generator_get_flags (GtkTreeModel *tree_model)
1018 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1020 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
1022 return gtk_tree_model_get_flags (tree_model_generator->priv->child_model);
1026 e_tree_model_generator_get_n_columns (GtkTreeModel *tree_model)
1028 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1030 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
1032 return gtk_tree_model_get_n_columns (tree_model_generator->priv->child_model);
1036 e_tree_model_generator_get_column_type (GtkTreeModel *tree_model,
1039 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1041 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), G_TYPE_INVALID);
1043 return gtk_tree_model_get_column_type (tree_model_generator->priv->child_model, index);
1047 e_tree_model_generator_get_iter (GtkTreeModel *tree_model,
1051 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1056 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1057 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
1059 group = tree_model_generator->priv->root_nodes;
1063 for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
1067 index = gtk_tree_path_get_indices (path)[depth];
1068 child_index = generated_offset_to_child_offset (group, index, NULL);
1069 if (child_index < 0)
1072 node = &g_array_index (group, Node, child_index);
1074 if (depth + 1 < gtk_tree_path_get_depth (path)) {
1075 group = node->child_nodes;
1081 ITER_SET (tree_model_generator, iter, group, index);
1085 static GtkTreePath *
1086 e_tree_model_generator_get_path (GtkTreeModel *tree_model,
1089 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1094 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), NULL);
1095 g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), NULL);
1097 ITER_GET (iter, &group, &index);
1098 path = gtk_tree_path_new ();
1100 /* FIXME: Converting a path to an iter is a destructive operation, because
1101 * we don't store a node for each generated entry... Doesn't matter for
1102 * lists, not sure about trees. */
1104 gtk_tree_path_prepend_index (path, index);
1105 index = generated_offset_to_child_offset (group, index, NULL);
1108 Node *node = &g_array_index (group, Node, index);
1109 gint generated_index;
1111 group = node->parent_group;
1112 index = node->parent_index;
1114 generated_index = child_offset_to_generated_offset (group, index);
1115 gtk_tree_path_prepend_index (path, generated_index);
1123 e_tree_model_generator_iter_next (GtkTreeModel *tree_model,
1126 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1131 gint internal_offset = 0;
1133 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1134 g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
1136 ITER_GET (iter, &group, &index);
1137 child_index = generated_offset_to_child_offset (group, index, &internal_offset);
1138 node = &g_array_index (group, Node, child_index);
1140 if (internal_offset + 1 < node->n_generated ||
1141 get_first_visible_index_from (group, child_index + 1) >= 0) {
1142 ITER_SET (tree_model_generator, iter, group, index + 1);
1150 e_tree_model_generator_iter_children (GtkTreeModel *tree_model,
1152 GtkTreeIter *parent)
1154 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1159 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1162 if (!tree_model_generator->priv->root_nodes ||
1163 !count_generated_nodes (tree_model_generator->priv->root_nodes))
1166 ITER_SET (tree_model_generator, iter, tree_model_generator->priv->root_nodes, 0);
1170 ITER_GET (parent, &group, &index);
1171 index = generated_offset_to_child_offset (group, index, NULL);
1175 node = &g_array_index (group, Node, index);
1177 if (!node->child_nodes)
1180 if (!count_generated_nodes (node->child_nodes))
1183 ITER_SET (tree_model_generator, iter, node->child_nodes, 0);
1188 e_tree_model_generator_iter_has_child (GtkTreeModel *tree_model,
1191 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1196 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1199 if (!tree_model_generator->priv->root_nodes ||
1200 !count_generated_nodes (tree_model_generator->priv->root_nodes))
1206 ITER_GET (iter, &group, &index);
1207 index = generated_offset_to_child_offset (group, index, NULL);
1211 node = &g_array_index (group, Node, index);
1213 if (!node->child_nodes)
1216 if (!count_generated_nodes (node->child_nodes))
1223 e_tree_model_generator_iter_n_children (GtkTreeModel *tree_model,
1226 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1231 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
1234 return tree_model_generator->priv->root_nodes ?
1235 count_generated_nodes (tree_model_generator->priv->root_nodes) : 0;
1237 ITER_GET (iter, &group, &index);
1238 index = generated_offset_to_child_offset (group, index, NULL);
1242 node = &g_array_index (group, Node, index);
1244 if (!node->child_nodes)
1247 return count_generated_nodes (node->child_nodes);
1251 e_tree_model_generator_iter_nth_child (GtkTreeModel *tree_model,
1253 GtkTreeIter *parent,
1256 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1261 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1264 if (!tree_model_generator->priv->root_nodes)
1267 if (n >= count_generated_nodes (tree_model_generator->priv->root_nodes))
1270 ITER_SET (tree_model_generator, iter, tree_model_generator->priv->root_nodes, n);
1274 ITER_GET (parent, &group, &index);
1275 index = generated_offset_to_child_offset (group, index, NULL);
1279 node = &g_array_index (group, Node, index);
1281 if (!node->child_nodes)
1284 if (n >= count_generated_nodes (node->child_nodes))
1287 ITER_SET (tree_model_generator, iter, node->child_nodes, n);
1292 e_tree_model_generator_iter_parent (GtkTreeModel *tree_model,
1296 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1301 g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1302 g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
1304 ITER_GET (child, &group, &index);
1305 index = generated_offset_to_child_offset (group, index, NULL);
1309 node = &g_array_index (group, Node, index);
1311 group = node->parent_group;
1315 ITER_SET (tree_model_generator, iter, group, node->parent_index);
1320 e_tree_model_generator_get_value (GtkTreeModel *tree_model,
1325 ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1326 GtkTreeIter child_iter;
1329 g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model));
1330 g_return_if_fail (ITER_IS_VALID (tree_model_generator, iter));
1332 e_tree_model_generator_convert_iter_to_child_iter (
1333 tree_model_generator, &child_iter,
1334 &permutation_n, iter);
1336 if (tree_model_generator->priv->modify_func) {
1337 tree_model_generator->priv->modify_func (tree_model_generator->priv->child_model,
1338 &child_iter, permutation_n,
1340 tree_model_generator->priv->modify_func_data);
1344 gtk_tree_model_get_value (tree_model_generator->priv->child_model, &child_iter, column, value);