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