Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / libedataserverui / e-tree-model-generator.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* e-tree-model-generator.c - Model wrapper that permutes underlying rows.
4  *
5  * Copyright (C) 2005 Novell, Inc.
6  *
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.
10  *
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.
15  *
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.
19  *
20  * Authors: Hans Petter Jansson <hpj@novell.com>
21  */
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <glib/gi18n-lib.h>
29 #include <gtk/gtktreemodel.h>
30 #include <gtk/gtksignal.h>
31 #include "e-tree-model-generator.h"
32
33 #define ETMG_DEBUG(x)
34
35 #define ITER_IS_VALID(tree_model_generator, iter) ((iter)->stamp == (tree_model_generator)->stamp)
36 #define ITER_GET(iter, group, index)                        \
37 G_STMT_START {                                              \
38         *(group) = (iter)->user_data;                       \
39         *(index) = GPOINTER_TO_INT ((iter)->user_data2);    \
40 } G_STMT_END
41
42 #define ITER_SET(tree_model_generator, iter, group, index)  \
43 G_STMT_START {                                              \
44         (iter)->stamp = (tree_model_generator)->stamp;      \
45         (iter)->user_data = group;                          \
46         (iter)->user_data2 = GINT_TO_POINTER (index);       \
47 } G_STMT_END
48
49 static void         e_tree_model_generator_init            (ETreeModelGenerator      *tree_model_generator);
50 static void         e_tree_model_generator_class_init      (ETreeModelGeneratorClass *class);
51 static void         e_tree_model_generator_tree_model_init (GtkTreeModelIface  *iface);
52 static void         e_tree_model_generator_finalize        (GObject            *object);
53 static GtkTreeModelFlags e_tree_model_generator_get_flags       (GtkTreeModel       *tree_model);
54 static gint         e_tree_model_generator_get_n_columns   (GtkTreeModel       *tree_model);
55 static GType        e_tree_model_generator_get_column_type (GtkTreeModel       *tree_model,
56                                                             gint                index);
57 static gboolean     e_tree_model_generator_get_iter        (GtkTreeModel       *tree_model,
58                                                             GtkTreeIter        *iter,
59                                                             GtkTreePath        *path);
60 static GtkTreePath *e_tree_model_generator_get_path        (GtkTreeModel       *tree_model,
61                                                             GtkTreeIter        *iter);
62 static void         e_tree_model_generator_get_value       (GtkTreeModel       *tree_model,
63                                                             GtkTreeIter        *iter,
64                                                             gint                column,
65                                                             GValue             *value);
66 static gboolean     e_tree_model_generator_iter_next       (GtkTreeModel       *tree_model,
67                                                             GtkTreeIter        *iter);
68 static gboolean     e_tree_model_generator_iter_children   (GtkTreeModel       *tree_model,
69                                                             GtkTreeIter        *iter,
70                                                             GtkTreeIter        *parent);
71 static gboolean     e_tree_model_generator_iter_has_child  (GtkTreeModel       *tree_model,
72                                                             GtkTreeIter        *iter);
73 static gint         e_tree_model_generator_iter_n_children (GtkTreeModel       *tree_model,
74                                                             GtkTreeIter        *iter);
75 static gboolean     e_tree_model_generator_iter_nth_child  (GtkTreeModel       *tree_model,
76                                                             GtkTreeIter        *iter,
77                                                             GtkTreeIter        *parent,
78                                                             gint                n);
79 static gboolean     e_tree_model_generator_iter_parent     (GtkTreeModel       *tree_model,
80                                                             GtkTreeIter        *iter,
81                                                             GtkTreeIter        *child);
82
83 static GArray *build_node_map     (ETreeModelGenerator *tree_model_generator, GtkTreeIter *parent_iter,
84                                    GArray *parent_group, gint parent_index);
85 static void    release_node_map   (GArray *group);
86
87 static void    child_row_changed  (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
88 static void    child_row_inserted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
89 static void    child_row_deleted  (ETreeModelGenerator *tree_model_generator, GtkTreePath *path);
90
91 typedef struct {
92         GArray *parent_group;
93         gint    parent_index;
94
95         gint    n_generated;
96         GArray *child_nodes;
97 }
98 Node;
99
100 enum {
101         PROP_0,
102         PROP_CHILD_MODEL
103 };
104
105 /* ------------------ *
106  * Class/object setup *
107  * ------------------ */
108
109 static GObjectClass *parent_class = NULL;
110
111 static void
112 e_tree_model_generator_get_property (GObject *object, guint prop_id,
113                                      GValue *value, GParamSpec *pspec)
114 {
115         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
116
117         switch (prop_id)
118         {
119                 case PROP_CHILD_MODEL:
120                         g_value_set_object (value, tree_model_generator->child_model);
121                         break;
122
123                 default:
124                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
125                         break;
126         }
127 }
128
129 static void
130 e_tree_model_generator_set_property (GObject *object, guint prop_id,
131                                      const GValue *value, GParamSpec *pspec)
132 {
133         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
134
135         switch (prop_id)
136         {
137                 case PROP_CHILD_MODEL:
138                         tree_model_generator->child_model = g_value_get_object (value);
139                         g_object_ref (tree_model_generator->child_model);
140
141                         if (tree_model_generator->root_nodes)
142                                 release_node_map (tree_model_generator->root_nodes);
143                         tree_model_generator->root_nodes =
144                                 build_node_map (tree_model_generator, NULL, NULL, -1);
145
146                         g_signal_connect_swapped (tree_model_generator->child_model, "row-changed",
147                                                   G_CALLBACK (child_row_changed), tree_model_generator);
148                         g_signal_connect_swapped (tree_model_generator->child_model, "row-deleted",
149                                                   G_CALLBACK (child_row_deleted), tree_model_generator);
150                         g_signal_connect_swapped (tree_model_generator->child_model, "row-inserted",
151                                                   G_CALLBACK (child_row_inserted), tree_model_generator);
152                         break;
153
154                 default:
155                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156                         break;
157         }
158 }
159
160 GType
161 e_tree_model_generator_get_type (void)
162 {
163         static GType tree_model_generator_type = 0;
164
165         if (!tree_model_generator_type) {
166                 static const GTypeInfo tree_model_generator_info =
167                 {
168                         sizeof (ETreeModelGeneratorClass),
169                         NULL,           /* base_init */
170                         NULL,           /* base_finalize */
171                         (GClassInitFunc) e_tree_model_generator_class_init,
172                         NULL,           /* class_finalize */
173                         NULL,           /* class_data */
174                         sizeof (ETreeModelGenerator),
175                         0,
176                         (GInstanceInitFunc) e_tree_model_generator_init,
177                 };
178
179                 static const GInterfaceInfo tree_model_info =
180                 {
181                         (GInterfaceInitFunc) e_tree_model_generator_tree_model_init,
182                         NULL,
183                         NULL
184                 };
185
186                 tree_model_generator_type = g_type_register_static (G_TYPE_OBJECT, "ETreeModelGenerator",
187                                                                     &tree_model_generator_info, 0);
188                 g_type_add_interface_static (tree_model_generator_type,
189                                              GTK_TYPE_TREE_MODEL,
190                                              &tree_model_info);
191         }
192
193         return tree_model_generator_type;
194 }
195
196 static void
197 e_tree_model_generator_class_init (ETreeModelGeneratorClass *class)
198 {
199         GObjectClass *object_class;
200
201         parent_class = g_type_class_peek_parent (class);
202         object_class = (GObjectClass *) class;
203
204         object_class->get_property = e_tree_model_generator_get_property;
205         object_class->set_property = e_tree_model_generator_set_property;
206         object_class->finalize     = e_tree_model_generator_finalize;
207
208         g_object_class_install_property (object_class, PROP_CHILD_MODEL,
209                                          g_param_spec_object ("child-model",
210                                                               "Child Model",
211                                                               "The child model to extend",
212                                                               G_TYPE_OBJECT,
213                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
214 }
215
216 static void
217 e_tree_model_generator_tree_model_init (GtkTreeModelIface *iface)
218 {
219         iface->get_flags       = e_tree_model_generator_get_flags;
220         iface->get_n_columns   = e_tree_model_generator_get_n_columns;
221         iface->get_column_type = e_tree_model_generator_get_column_type;
222         iface->get_iter        = e_tree_model_generator_get_iter;
223         iface->get_path        = e_tree_model_generator_get_path;
224         iface->get_value       = e_tree_model_generator_get_value;
225         iface->iter_next       = e_tree_model_generator_iter_next;
226         iface->iter_children   = e_tree_model_generator_iter_children;
227         iface->iter_has_child  = e_tree_model_generator_iter_has_child;
228         iface->iter_n_children = e_tree_model_generator_iter_n_children;
229         iface->iter_nth_child  = e_tree_model_generator_iter_nth_child;
230         iface->iter_parent     = e_tree_model_generator_iter_parent;
231 }
232
233 static void
234 e_tree_model_generator_init (ETreeModelGenerator *tree_model_generator)
235 {
236         tree_model_generator->stamp      = g_random_int ();
237         tree_model_generator->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
238 }
239
240 static void
241 e_tree_model_generator_finalize (GObject *object)
242 {
243         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
244
245         if (tree_model_generator->child_model) {
246                 g_signal_handlers_disconnect_matched (tree_model_generator->child_model,
247                                                       G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
248                                                       tree_model_generator);
249                 g_object_unref (tree_model_generator->child_model);
250         }
251
252         if (tree_model_generator->root_nodes)
253                 release_node_map (tree_model_generator->root_nodes);
254
255         if (G_OBJECT_CLASS (parent_class)->finalize)
256                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
257 }
258
259 /* ------------------ *
260  * Row update helpers *
261  * ------------------ */
262
263 static void
264 row_deleted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
265 {
266         g_assert (path);
267
268         ETMG_DEBUG (g_print ("row_deleted emitting\n"));
269         gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_model_generator), path);
270 }
271
272 static void
273 row_inserted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
274 {
275         GtkTreeIter iter;
276
277         g_assert (path);
278
279         if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
280                 ETMG_DEBUG (g_print ("row_inserted emitting\n"));
281                 gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_model_generator), path, &iter);
282         } else {
283                 ETMG_DEBUG (g_print ("row_inserted could not get iter!\n"));
284         }
285 }
286
287 static void
288 row_changed (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
289 {
290         GtkTreeIter iter;
291
292         g_assert (path);
293
294         if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
295                 ETMG_DEBUG (g_print ("row_changed emitting\n"));
296                 gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model_generator), path, &iter);
297         } else {
298                 ETMG_DEBUG (g_print ("row_changed could not get iter!\n"));
299         }
300 }
301
302 /* -------------------- *
303  * Node map translation *
304  * -------------------- */
305
306 static gint
307 generated_offset_to_child_offset (GArray *group, gint offset, gint *internal_offset)
308 {
309         gboolean success      = FALSE;
310         gint     accum_offset = 0;
311         gint     i;
312
313         for (i = 0; i < group->len; i++) {
314                 Node *node = &g_array_index (group, Node, i);
315
316                 accum_offset += node->n_generated;
317                 if (accum_offset > offset) {
318                         accum_offset -= node->n_generated;
319                         success = TRUE;
320                         break;
321                 }
322         }
323
324         if (!success)
325                 return -1;
326
327         if (internal_offset)
328                 *internal_offset = offset - accum_offset;
329
330         return i;
331 }
332
333 static gint
334 child_offset_to_generated_offset (GArray *group, gint offset)
335 {
336         gint accum_offset = 0;
337         gint i;
338
339         for (i = 0; i < group->len && i < offset; i++) {
340                 Node *node = &g_array_index (group, Node, i);
341
342                 accum_offset += node->n_generated;
343         }
344
345         return accum_offset;
346 }
347
348 static gint
349 count_generated_nodes (GArray *group)
350 {
351         gint accum_offset = 0;
352         gint i;
353
354         for (i = 0; i < group->len; i++) {
355                 Node *node = &g_array_index (group, Node, i);
356
357                 accum_offset += node->n_generated;
358         }
359
360         return accum_offset;
361 }
362
363 /* ------------------- *
364  * Node map management *
365  * ------------------- */
366
367 static void
368 release_node_map (GArray *group)
369 {
370         gint i;
371
372         for (i = 0; i < group->len; i++) {
373                 Node *node = &g_array_index (group, Node, i);
374
375                 if (node->child_nodes)
376                         release_node_map (node->child_nodes);
377         }
378
379         g_array_free (group, TRUE);
380 }
381
382 static gint
383 append_node (GArray *group)
384 {
385         g_array_set_size (group, group->len + 1);
386         return group->len - 1;
387 }
388
389 static GArray *
390 build_node_map (ETreeModelGenerator *tree_model_generator, GtkTreeIter *parent_iter,
391                 GArray *parent_group, gint parent_index)
392 {
393         GArray      *group;
394         GtkTreeIter  iter;
395         gboolean     result;
396
397         if (parent_iter)
398                 result = gtk_tree_model_iter_children (tree_model_generator->child_model, &iter, parent_iter);
399         else
400                 result = gtk_tree_model_get_iter_first (tree_model_generator->child_model, &iter);
401
402         if (!result)
403                 return NULL;
404
405         group = g_array_new (FALSE, FALSE, sizeof (Node));
406
407         do {
408                 Node *node;
409                 gint  i;
410
411                 i = append_node (group);
412                 node = &g_array_index (group, Node, i);
413
414                 node->parent_group = parent_group;
415                 node->parent_index = parent_index;
416
417                 if (tree_model_generator->generate_func)
418                         node->n_generated =
419                                 tree_model_generator->generate_func (tree_model_generator->child_model,
420                                                                      &iter, tree_model_generator->generate_func_data);
421                 else
422                         node->n_generated = 1;
423
424                 node->child_nodes = build_node_map (tree_model_generator, &iter, group, i);
425         } while (gtk_tree_model_iter_next (tree_model_generator->child_model, &iter));
426
427         return group;
428 }
429
430 static gint
431 get_first_visible_index_from (GArray *group, gint index)
432 {
433         gint i;
434
435         for (i = index; i < group->len; i++) {
436                 Node *node = &g_array_index (group, Node, i);
437
438                 if (node->n_generated)
439                         break;
440         }
441
442         if (i >= group->len)
443                 i = -1;
444
445         return i;
446 }
447
448 static Node *
449 get_node_by_child_path (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GArray **node_group)
450 {
451         Node   *node = NULL;
452         GArray *group;
453         gint    depth;
454
455         group = tree_model_generator->root_nodes;
456
457         for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
458                 gint  index;
459
460                 if (!group) {
461                         g_warning ("ETreeModelGenerator got unknown child element!");
462                         break;
463                 }
464
465                 index = gtk_tree_path_get_indices (path) [depth];
466                 node = &g_array_index (group, Node, index);
467
468                 if (depth + 1 < gtk_tree_path_get_depth (path))
469                     group = node->child_nodes;
470         }
471
472         if (!node)
473                 group = NULL;
474
475         if (node_group)
476                 *node_group = group;
477
478         return node;
479 }
480
481 static Node *
482 create_node_at_child_path (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
483 {
484         GtkTreePath *parent_path;
485         gint         parent_index;
486         GArray      *parent_group;
487         GArray      *group;
488         gint         index;
489         Node        *node;
490
491         parent_path = gtk_tree_path_copy (path);
492         gtk_tree_path_up (parent_path);
493         node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
494
495         if (node) {
496                 if (!node->child_nodes)
497                         node->child_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
498
499                 group = node->child_nodes;
500                 parent_index = gtk_tree_path_get_indices (parent_path) [gtk_tree_path_get_depth (parent_path) - 1];
501         } else {
502                 if (!tree_model_generator->root_nodes)
503                         tree_model_generator->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
504
505                 group = tree_model_generator->root_nodes;
506                 parent_index = -1;
507         }
508
509         gtk_tree_path_free (parent_path);
510
511         index = gtk_tree_path_get_indices (path) [gtk_tree_path_get_depth (path) - 1];
512         ETMG_DEBUG (g_print ("Inserting index %d into group of length %d\n", index, group->len));
513         index = MIN (index, group->len);
514
515         append_node (group);
516
517         if (group->len - 1 - index > 0) {
518                 gint i;
519
520                 memmove ((Node *) group->data + index + 1,
521                          (Node *) group->data + index,
522                          (group->len - 1 - index) * sizeof (Node));
523
524                 /* Update parent pointers */
525                 for (i = index + 1; i < group->len; i++) {
526                         Node   *pnode = &g_array_index (group, Node, i);
527                         GArray *child_group;
528                         gint    j;
529
530                         child_group = pnode->child_nodes;
531                         if (!child_group)
532                                 continue;
533
534                         for (j = 0; j < child_group->len; j++) {
535                                 Node *child_node = &g_array_index (child_group, Node, j);
536                                 child_node->parent_index = i;
537                         }
538                 }
539         }
540
541         node = &g_array_index (group, Node, index);
542         node->parent_group = parent_group;
543         node->parent_index = parent_index;
544         node->n_generated  = 0;
545         node->child_nodes  = NULL;
546
547         ETMG_DEBUG (g_print ("Created node at offset %d, parent_group = %p, parent_index = %d\n",
548                              index, node->parent_group, node->parent_index));
549
550         return node;
551 }
552
553 ETMG_DEBUG (
554
555 static void
556 dump_group (GArray *group)
557 {
558         gint i;
559
560         g_print ("\nGroup %p:\n", group);
561
562         for (i = 0; i < group->len; i++) {
563                 Node *node = &g_array_index (group, Node, i);
564                 g_print ("  %04d: pgroup=%p, pindex=%d, n_generated=%d, child_nodes=%p\n",
565                          i, node->parent_group, node->parent_index, node->n_generated, node->child_nodes);
566         }
567 }
568
569 )
570
571 static void
572 delete_node_at_child_path (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
573 {
574         GtkTreePath *parent_path;
575         gint         parent_index;
576         GArray      *parent_group;
577         GArray      *group;
578         gint         index;
579         Node        *node;
580         gint         i;
581
582         parent_path = gtk_tree_path_copy (path);
583         gtk_tree_path_up (parent_path);
584         node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
585
586         if (node) {
587                 group = node->child_nodes;
588                 parent_index = gtk_tree_path_get_indices (parent_path) [gtk_tree_path_get_depth (parent_path) - 1];
589         } else {
590                 group = tree_model_generator->root_nodes;
591                 parent_index = -1;
592         }
593
594         gtk_tree_path_free (parent_path);
595
596         if (!group)
597                 return;
598
599         index = gtk_tree_path_get_indices (path) [gtk_tree_path_get_depth (path) - 1];
600         if (index >= group->len)
601                 return;
602
603         node = &g_array_index (group, Node, index);
604         if (node->child_nodes)
605                 release_node_map (node->child_nodes);
606         g_array_remove_index (group, index);
607
608         /* Update parent pointers */
609         for (i = index; i < group->len; i++) {
610                 Node   *pnode = &g_array_index (group, Node, i);
611                 GArray *child_group;
612                 gint    j;
613
614                 child_group = pnode->child_nodes;
615                 if (!child_group)
616                         continue;
617
618                 for (j = 0; j < child_group->len; j++) {
619                         Node *child_node = &g_array_index (child_group, Node, j);
620                         child_node->parent_index = i;
621                 }
622         }
623 }
624
625 static void
626 child_row_changed (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter)
627 {
628         GtkTreePath *generated_path;
629         Node        *node;
630         gint         n_generated;
631         gint         i;
632
633         if (tree_model_generator->generate_func)
634                 n_generated =
635                         tree_model_generator->generate_func (tree_model_generator->child_model,
636                                                              iter, tree_model_generator->generate_func_data);
637         else
638                 n_generated = 1;
639
640         node = get_node_by_child_path (tree_model_generator, path, NULL);
641         if (!node)
642                 return;
643
644         generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
645
646         /* FIXME: Converting the path to an iter every time is inefficient */
647
648         for (i = 0; i < n_generated && i < node->n_generated; i++) {
649                 row_changed (tree_model_generator, generated_path);
650                 gtk_tree_path_next (generated_path);
651         }
652
653         for ( ; i < node->n_generated; ) {
654                 node->n_generated--;
655                 row_deleted (tree_model_generator, generated_path);
656         }
657
658         for ( ; i < n_generated; i++) {
659                 node->n_generated++;
660                 row_inserted (tree_model_generator, generated_path);
661                 gtk_tree_path_next (generated_path);
662         }
663
664         gtk_tree_path_free (generated_path);
665 }
666
667 static void
668 child_row_inserted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter)
669 {
670         GtkTreePath *generated_path;
671         Node        *node;
672         gint         n_generated;
673
674         if (tree_model_generator->generate_func)
675                 n_generated =
676                         tree_model_generator->generate_func (tree_model_generator->child_model,
677                                                              iter, tree_model_generator->generate_func_data);
678         else
679                 n_generated = 1;
680
681         node = create_node_at_child_path (tree_model_generator, path);
682         if (!node)
683                 return;
684
685         generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
686
687         /* FIXME: Converting the path to an iter every time is inefficient */
688
689         for (node->n_generated = 0; node->n_generated < n_generated; ) {
690                 node->n_generated++;
691                 row_inserted (tree_model_generator, generated_path);
692                 gtk_tree_path_next (generated_path);
693         }
694
695         gtk_tree_path_free (generated_path);
696 }
697
698 static void
699 child_row_deleted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path)
700 {
701         GtkTreePath *generated_path;
702         Node        *node;
703
704         node = get_node_by_child_path (tree_model_generator, path, NULL);
705         if (!node)
706                 return;
707
708         generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
709
710         /* FIXME: Converting the path to an iter every time is inefficient */
711
712         for ( ; node->n_generated; ) {
713                 node->n_generated--;
714                 row_deleted (tree_model_generator, generated_path);
715         }
716
717         delete_node_at_child_path (tree_model_generator, path);
718         gtk_tree_path_free (generated_path);
719 }
720
721 /* ----------------------- *
722  * ETreeModelGenerator API *
723  * ----------------------- */
724
725 /**
726  * e_tree_model_generator_new:
727  * @child_model: a #GtkTreeModel
728  *
729  * Creates a new #ETreeModelGenerator wrapping @child_model.
730  *
731  * Return value: A new #ETreeModelGenerator.
732  **/
733 ETreeModelGenerator *
734 e_tree_model_generator_new (GtkTreeModel *child_model)
735 {
736         g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
737
738         return E_TREE_MODEL_GENERATOR (g_object_new (E_TYPE_TREE_MODEL_GENERATOR,
739                                                      "child-model", child_model, NULL));
740 }
741
742 /**
743  * e_tree_model_generator_get_model:
744  * @tree_model_generator: an #ETreeModelGenerator
745  *
746  * Gets the child model being wrapped by @tree_model_generator.
747  *
748  * Return value: A #GtkTreeModel being wrapped.
749  **/
750 GtkTreeModel *
751 e_tree_model_generator_get_model (ETreeModelGenerator *tree_model_generator)
752 {
753         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
754
755         return tree_model_generator->child_model;
756 }
757
758 /**
759  * e_tree_model_generator_set_generate_func:
760  * @tree_model_generator: an #ETreeModelGenerator
761  * @func: an #ETreeModelGeneratorGenerateFunc, or %NULL
762  * @data: user data to pass to @func
763  * @destroy:
764  *
765  * Sets the callback function used to filter or generate additional rows
766  * based on the child model's data. This function is called for each child
767  * row, and returns a value indicating the number of rows that will be
768  * used to represent the child row - 0 or more.
769  *
770  * If @func is %NULL, a filtering/generating function will not be applied.
771  **/
772 void
773 e_tree_model_generator_set_generate_func (ETreeModelGenerator *tree_model_generator,
774                                           ETreeModelGeneratorGenerateFunc func,
775                                           gpointer data, GtkDestroyNotify destroy)
776 {
777         g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
778
779         tree_model_generator->generate_func      = func;
780         tree_model_generator->generate_func_data = data;
781 }
782
783 /**
784  * e_tree_model_generator_set_modify_func:
785  * @tree_model_generator: an #ETreeModelGenerator
786  * @func: an @ETreeModelGeneratorModifyFunc, or %NULL
787  * @data: user data to pass to @func
788  * @destroy:
789  *
790  * Sets the callback function used to override values for the child row's
791  * columns and specify values for generated rows' columns.
792  *
793  * If @func is %NULL, the child model's values will always be used.
794  **/
795 void
796 e_tree_model_generator_set_modify_func (ETreeModelGenerator *tree_model_generator,
797                                         ETreeModelGeneratorModifyFunc func,
798                                         gpointer data, GtkDestroyNotify destroy)
799 {
800         g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
801
802         tree_model_generator->modify_func      = func;
803         tree_model_generator->modify_func_data = data;
804 }
805
806 /**
807  * e_tree_model_generator_convert_child_path_to_path:
808  * @tree_model_generator: an #ETreeModelGenerator
809  * @child_path: a #GtkTreePath
810  *
811  * Convert a path to a child row to a path to a @tree_model_generator row.
812  *
813  * Return value: A new GtkTreePath, owned by the caller.
814  **/
815 GtkTreePath *
816 e_tree_model_generator_convert_child_path_to_path (ETreeModelGenerator *tree_model_generator,
817                                                    GtkTreePath *child_path)
818 {
819         GtkTreePath *path;
820         GArray      *group;
821         gint         depth;
822
823         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
824         g_return_val_if_fail (child_path != NULL, NULL);
825
826         path = gtk_tree_path_new ();
827
828         group = tree_model_generator->root_nodes;
829
830         for (depth = 0; depth < gtk_tree_path_get_depth (child_path); depth++) {
831                 Node *node;
832                 gint  index;
833                 gint  generated_index;
834
835                 if (!group) {
836                         g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
837                         break;
838                 }
839
840                 index = gtk_tree_path_get_indices (child_path) [depth];
841                 generated_index = child_offset_to_generated_offset (group, index);
842                 node = &g_array_index (group, Node, index);
843                 group = node->child_nodes;
844
845                 gtk_tree_path_append_index (path, generated_index);
846         }
847
848         return path;
849 }
850
851 /**
852  * e_tree_model_generator_convert_child_iter_to_iter:
853  * @tree_model_generator: an #ETreeModelGenerator
854  * @generator_iter: a #GtkTreeIter to set
855  * @child_iter: a #GtkTreeIter to convert
856  *
857  * Convert @child_iter to a corresponding #GtkTreeIter for @tree_model_generator,
858  * storing the result in @generator_iter.
859  **/
860 void
861 e_tree_model_generator_convert_child_iter_to_iter (ETreeModelGenerator *tree_model_generator,
862                                                    GtkTreeIter *generator_iter,
863                                                    GtkTreeIter *child_iter)
864 {
865         GtkTreePath *path;
866         GArray      *group;
867         gint         depth;
868         gint         index = 0;
869
870         g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
871
872         path = gtk_tree_model_get_path (tree_model_generator->child_model, child_iter);
873         if (!path)
874                 return;
875
876         group = tree_model_generator->root_nodes;
877
878         for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
879                 Node *node;
880
881                 index = gtk_tree_path_get_indices (path) [depth];
882                 node = &g_array_index (group, Node, index);
883
884                 if (depth + 1 < gtk_tree_path_get_depth (path))
885                         group = node->child_nodes;
886
887                 if (!group) {
888                         g_warning ("ETreeModelGenerator was asked for iter to unknown child element!");
889                         break;
890                 }
891         }
892
893         index = child_offset_to_generated_offset (group, index);
894         ITER_SET (tree_model_generator, generator_iter, group, index);
895         gtk_tree_path_free (path);
896 }
897
898 /**
899  * e_tree_model_generator_convert_path_to_child_path:
900  * @tree_model_generator: an #ETreeModelGenerator
901  * @generator_path: a #GtkTreePath to a @tree_model_generator row
902  *
903  * Converts @generator_path to a corresponding #GtkTreePath in the child model.
904  *
905  * Return value: A new #GtkTreePath, owned by the caller.
906  **/
907 GtkTreePath *
908 e_tree_model_generator_convert_path_to_child_path (ETreeModelGenerator *tree_model_generator,
909                                                    GtkTreePath *generator_path)
910 {
911         GtkTreePath *path;
912         GArray      *group;
913         gint         depth;
914
915         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
916         g_return_val_if_fail (generator_path != NULL, NULL);
917
918         path = gtk_tree_path_new ();
919
920         group = tree_model_generator->root_nodes;
921
922         for (depth = 0; depth < gtk_tree_path_get_depth (generator_path); depth++) {
923                 Node *node;
924                 gint  index;
925                 gint  child_index;
926
927                 if (!group) {
928                         g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
929                         break;
930                 }
931
932                 index = gtk_tree_path_get_indices (generator_path) [depth];
933                 child_index = generated_offset_to_child_offset (group, index, NULL);
934                 node = &g_array_index (group, Node, child_index);
935                 group = node->child_nodes;
936
937                 gtk_tree_path_append_index (path, child_index);
938         }
939
940         return path;
941 }
942
943 /**
944  * e_tree_model_generator_convert_iter_to_child_iter:
945  * @tree_model_generator: an #ETreeModelGenerator
946  * @child_iter: a #GtkTreeIter to set
947  * @permutation_n: a permutation index to set
948  * @generator_iter: a #GtkTreeIter indicating the row to convert
949  * 
950  * Converts a @tree_model_generator row into a child row and permutation index.
951  * The permutation index is the index of the generated row based on this
952  * child row, with the first generated row based on this child row being 0.
953  **/
954 void
955 e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_model_generator,
956                                                    GtkTreeIter *child_iter,
957                                                    gint *permutation_n,
958                                                    GtkTreeIter *generator_iter)
959 {
960         GtkTreePath *path;
961         GArray      *group;
962         gint         generator_index;
963         gint         index;
964         gint         internal_offset;
965
966         g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
967         g_return_if_fail (ITER_IS_VALID (tree_model_generator, generator_iter));
968
969         path = gtk_tree_path_new ();
970         ITER_GET (generator_iter, &group, &index);
971
972         generator_index = index;
973         index = generated_offset_to_child_offset (group, index, &internal_offset);
974         gtk_tree_path_prepend_index (path, index);
975
976         ETMG_DEBUG (g_print ("iter_to_child_iter: %d -> %d (%d)\n", generator_index, index, internal_offset));
977
978         while (group) {
979                 Node *node = &g_array_index (group, Node, index);
980
981                 group = node->parent_group;
982                 index = node->parent_index;
983
984                 if (group)
985                         gtk_tree_path_prepend_index (path, index);
986         }
987
988         if (child_iter)
989                 gtk_tree_model_get_iter (tree_model_generator->child_model, child_iter, path);
990         if (permutation_n)
991                 *permutation_n = internal_offset;
992
993         gtk_tree_path_free (path);
994 }
995
996 /* ---------------- *
997  * GtkTreeModel API *
998  * ---------------- */
999
1000 static GtkTreeModelFlags
1001 e_tree_model_generator_get_flags (GtkTreeModel *tree_model)
1002 {
1003         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1004
1005         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
1006
1007         return gtk_tree_model_get_flags (tree_model_generator->child_model);
1008 }
1009
1010 static gint
1011 e_tree_model_generator_get_n_columns (GtkTreeModel *tree_model)
1012 {
1013         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1014
1015         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
1016
1017         return gtk_tree_model_get_n_columns (tree_model_generator->child_model);
1018 }
1019
1020 static GType
1021 e_tree_model_generator_get_column_type (GtkTreeModel *tree_model,
1022                                         gint          index)
1023 {
1024         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1025
1026         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), G_TYPE_INVALID);
1027
1028         return gtk_tree_model_get_column_type (tree_model_generator->child_model, index);
1029 }
1030
1031 static gboolean
1032 e_tree_model_generator_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
1033 {
1034         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1035         GArray              *group;
1036         gint                 depth;
1037         gint                 index = 0;
1038
1039         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1040         g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
1041
1042         group = tree_model_generator->root_nodes;
1043         if (!group)
1044                 return FALSE;
1045
1046         for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
1047                 Node *node;
1048                 gint  child_index;
1049
1050                 index = gtk_tree_path_get_indices (path) [depth];
1051                 child_index = generated_offset_to_child_offset (group, index, NULL);
1052                 if (child_index < 0)
1053                         return FALSE;
1054
1055                 node = &g_array_index (group, Node, child_index);
1056
1057                 if (depth + 1 < gtk_tree_path_get_depth (path)) {
1058                         group = node->child_nodes;
1059                         if (!group)
1060                                 return FALSE;
1061                 }
1062         }
1063
1064         ITER_SET (tree_model_generator, iter, group, index);
1065         return TRUE;
1066 }
1067
1068 static GtkTreePath *
1069 e_tree_model_generator_get_path (GtkTreeModel *tree_model,
1070                                  GtkTreeIter  *iter)
1071 {
1072         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1073         GtkTreePath         *path;
1074         GArray              *group;
1075         gint                 index;
1076
1077         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), NULL);
1078         g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), NULL);
1079
1080         ITER_GET (iter, &group, &index);
1081         path = gtk_tree_path_new ();
1082
1083         /* FIXME: Converting a path to an iter is a destructive operation, because
1084          * we don't store a node for each generated entry... Doesn't matter for
1085          * lists, not sure about trees. */
1086
1087         gtk_tree_path_prepend_index (path, index);
1088         index = generated_offset_to_child_offset (group, index, NULL);
1089
1090         while (group) {
1091                 Node *node = &g_array_index (group, Node, index);
1092                 gint  generated_index;
1093
1094                 group = node->parent_group;
1095                 index = node->parent_index;
1096                 generated_index = child_offset_to_generated_offset (group, index);
1097
1098                 if (group)
1099                         gtk_tree_path_prepend_index (path, generated_index);
1100         }
1101
1102         return path;
1103 }
1104
1105 static gboolean
1106 e_tree_model_generator_iter_next (GtkTreeModel  *tree_model,
1107                                   GtkTreeIter   *iter)
1108 {
1109         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1110         Node                *node;
1111         GArray              *group;
1112         gint                 index;
1113         gint                 child_index;
1114         gint                 internal_offset;
1115
1116         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1117         g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
1118
1119         ITER_GET (iter, &group, &index);
1120         child_index = generated_offset_to_child_offset (group, index, &internal_offset);
1121         node = &g_array_index (group, Node, child_index);
1122
1123         if (internal_offset + 1 < node->n_generated ||
1124             get_first_visible_index_from (group, child_index + 1) >= 0) {
1125                 ITER_SET (tree_model_generator, iter, group, index + 1);
1126                 return TRUE;
1127         }
1128
1129         return FALSE;
1130 }
1131
1132 static gboolean
1133 e_tree_model_generator_iter_children (GtkTreeModel *tree_model,
1134                                       GtkTreeIter  *iter,
1135                                       GtkTreeIter  *parent)
1136 {
1137         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1138         Node                *node;
1139         GArray              *group;
1140         gint                 index;
1141
1142         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1143
1144         if (!parent) {
1145                 if (!tree_model_generator->root_nodes ||
1146                     !count_generated_nodes (tree_model_generator->root_nodes))
1147                         return FALSE;
1148
1149                 ITER_SET (tree_model_generator, iter, tree_model_generator->root_nodes, 0);
1150                 return TRUE;
1151         }
1152
1153         ITER_GET (parent, &group, &index);
1154         index = generated_offset_to_child_offset (group, index, NULL);
1155         if (index < 0)
1156                 return FALSE;
1157
1158         node = &g_array_index (group, Node, index);
1159
1160         if (!node->child_nodes)
1161                 return FALSE;
1162
1163         if (!count_generated_nodes (node->child_nodes))
1164                 return FALSE;
1165
1166         ITER_SET (tree_model_generator, iter, node->child_nodes, 0);
1167         return TRUE;
1168 }
1169
1170 static gboolean
1171 e_tree_model_generator_iter_has_child (GtkTreeModel *tree_model,
1172                                        GtkTreeIter  *iter)
1173 {
1174         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1175         Node                *node;
1176         GArray              *group;
1177         gint                 index;
1178
1179         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1180
1181         if (iter == NULL) {
1182                 if (!tree_model_generator->root_nodes ||
1183                     !count_generated_nodes (tree_model_generator->root_nodes))
1184                         return FALSE;
1185
1186                 return TRUE;
1187         }
1188
1189         ITER_GET (iter, &group, &index);
1190         index = generated_offset_to_child_offset (group, index, NULL);
1191         if (!index < 0)
1192                 return FALSE;
1193
1194         node = &g_array_index (group, Node, index);
1195
1196         if (!node->child_nodes)
1197                 return FALSE;
1198
1199         if (!count_generated_nodes (node->child_nodes))
1200                 return FALSE;
1201
1202         return TRUE;
1203 }
1204
1205 static gint
1206 e_tree_model_generator_iter_n_children (GtkTreeModel *tree_model,
1207                                         GtkTreeIter  *iter)
1208 {
1209         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1210         Node                *node;
1211         GArray              *group;
1212         gint                 index;
1213
1214         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1215
1216         if (iter == NULL)
1217                 return tree_model_generator->root_nodes ?
1218                         count_generated_nodes (tree_model_generator->root_nodes) : 0;
1219
1220         ITER_GET (iter, &group, &index);
1221         index = generated_offset_to_child_offset (group, index, NULL);
1222         if (index < 0)
1223                 return 0;
1224
1225         node = &g_array_index (group, Node, index);
1226
1227         if (!node->child_nodes)
1228                 return 0;
1229
1230         return count_generated_nodes (node->child_nodes);
1231 }
1232
1233 static gboolean
1234 e_tree_model_generator_iter_nth_child (GtkTreeModel *tree_model,
1235                                        GtkTreeIter  *iter,
1236                                        GtkTreeIter  *parent,
1237                                        gint          n)
1238 {
1239         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1240         Node                *node;
1241         GArray              *group;
1242         gint                 index;
1243
1244         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1245
1246         if (!parent) {
1247                 if (!tree_model_generator->root_nodes)
1248                         return FALSE;
1249
1250                 if (n >= count_generated_nodes (tree_model_generator->root_nodes))
1251                         return FALSE;
1252
1253                 ITER_SET (tree_model_generator, iter, tree_model_generator->root_nodes, n);
1254                 return TRUE;
1255         }
1256
1257         ITER_GET (parent, &group, &index);
1258         index = generated_offset_to_child_offset (group, index, NULL);
1259         if (index < 0)
1260                 return FALSE;
1261
1262         node = &g_array_index (group, Node, index);
1263
1264         if (!node->child_nodes)
1265                 return FALSE;
1266
1267         if (n >= count_generated_nodes (node->child_nodes))
1268                 return FALSE;
1269
1270         ITER_SET (tree_model_generator, iter, node->child_nodes, n);
1271         return TRUE;
1272 }
1273
1274 static gboolean
1275 e_tree_model_generator_iter_parent (GtkTreeModel *tree_model,
1276                                     GtkTreeIter  *iter,
1277                                     GtkTreeIter  *child)
1278 {
1279         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1280         Node                *node;
1281         GArray              *group;
1282         gint                 index;
1283
1284         g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
1285         g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
1286
1287         ITER_GET (child, &group, &index);
1288         index = generated_offset_to_child_offset (group, index, NULL);
1289         if (index < 0)
1290                 return FALSE;
1291
1292         node = &g_array_index (group, Node, index);
1293
1294         group = node->parent_group;
1295         if (!group)
1296                 return FALSE;
1297
1298         ITER_SET (tree_model_generator, iter, group, node->parent_index);
1299         return TRUE;
1300 }
1301
1302 static void
1303 e_tree_model_generator_get_value (GtkTreeModel *tree_model,
1304                                   GtkTreeIter  *iter,
1305                                   gint          column,
1306                                   GValue       *value)
1307 {
1308         ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
1309         GtkTreeIter          child_iter;
1310         gint                 permutation_n;
1311
1312         g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model));
1313         g_return_if_fail (ITER_IS_VALID (tree_model_generator, iter));
1314
1315         e_tree_model_generator_convert_iter_to_child_iter (tree_model_generator, &child_iter,
1316                                                            &permutation_n, iter);
1317
1318         if (tree_model_generator->modify_func) {
1319                 tree_model_generator->modify_func (tree_model_generator->child_model,
1320                                                    &child_iter, permutation_n,
1321                                                    column, value,
1322                                                    tree_model_generator->modify_func_data);
1323                 return;
1324         }
1325
1326         gtk_tree_model_get_value (tree_model_generator->child_model, &child_iter, column, value);
1327 }