1 /*
2  * e-tree-model.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 #include "e-tree-model.h"
19 
20 enum {
21 	PRE_CHANGE,
22 	NODE_CHANGED,
23 	NODE_DATA_CHANGED,
24 	NODE_INSERTED,
25 	NODE_REMOVED,
26 	NODE_DELETED,
27 	REBUILT,
28 	LAST_SIGNAL
29 };
30 
31 static guint signals[LAST_SIGNAL];
32 
G_DEFINE_INTERFACE(ETreeModel,e_tree_model,G_TYPE_OBJECT)33 G_DEFINE_INTERFACE (ETreeModel, e_tree_model, G_TYPE_OBJECT)
34 
35 static void
36 e_tree_model_default_init (ETreeModelInterface *iface)
37 {
38 	signals[PRE_CHANGE] = g_signal_new (
39 		"pre_change",
40 		G_TYPE_FROM_INTERFACE (iface),
41 		G_SIGNAL_RUN_LAST,
42 		G_STRUCT_OFFSET (ETreeModelInterface, pre_change),
43 		NULL, NULL, NULL,
44 		G_TYPE_NONE, 0);
45 
46 	signals[REBUILT] = g_signal_new (
47 		"rebuilt",
48 		G_TYPE_FROM_INTERFACE (iface),
49 		G_SIGNAL_RUN_LAST,
50 		G_STRUCT_OFFSET (ETreeModelInterface, rebuilt),
51 		NULL, NULL, NULL,
52 		G_TYPE_NONE, 0);
53 
54 	signals[NODE_CHANGED] = g_signal_new (
55 		"node_changed",
56 		G_TYPE_FROM_INTERFACE (iface),
57 		G_SIGNAL_RUN_LAST,
58 		G_STRUCT_OFFSET (ETreeModelInterface, node_changed),
59 		NULL, NULL, NULL,
60 		G_TYPE_NONE, 1,
61 		G_TYPE_POINTER);
62 
63 	signals[NODE_DATA_CHANGED] = g_signal_new (
64 		"node_data_changed",
65 		G_TYPE_FROM_INTERFACE (iface),
66 		G_SIGNAL_RUN_LAST,
67 		G_STRUCT_OFFSET (ETreeModelInterface, node_data_changed),
68 		NULL, NULL, NULL,
69 		G_TYPE_NONE, 1,
70 		G_TYPE_POINTER);
71 
72 	signals[NODE_INSERTED] = g_signal_new (
73 		"node_inserted",
74 		G_TYPE_FROM_INTERFACE (iface),
75 		G_SIGNAL_RUN_LAST,
76 		G_STRUCT_OFFSET (ETreeModelInterface, node_inserted),
77 		NULL, NULL, NULL,
78 		G_TYPE_NONE, 2,
79 		G_TYPE_POINTER,
80 		G_TYPE_POINTER);
81 
82 	signals[NODE_REMOVED] = g_signal_new (
83 		"node_removed",
84 		G_TYPE_FROM_INTERFACE (iface),
85 		G_SIGNAL_RUN_LAST,
86 		G_STRUCT_OFFSET (ETreeModelInterface, node_removed),
87 		NULL, NULL, NULL,
88 		G_TYPE_NONE, 3,
89 		G_TYPE_POINTER,
90 		G_TYPE_POINTER,
91 		G_TYPE_INT);
92 
93 	signals[NODE_DELETED] = g_signal_new (
94 		"node_deleted",
95 		G_TYPE_FROM_INTERFACE (iface),
96 		G_SIGNAL_RUN_LAST,
97 		G_STRUCT_OFFSET (ETreeModelInterface, node_deleted),
98 		NULL, NULL, NULL,
99 		G_TYPE_NONE, 1,
100 		G_TYPE_POINTER);
101 }
102 
103 /**
104  * e_tree_model_pre_change:
105  * @tree_model:
106  *
107  * Return value:
108  **/
109 void
e_tree_model_pre_change(ETreeModel * tree_model)110 e_tree_model_pre_change (ETreeModel *tree_model)
111 {
112 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
113 
114 	g_signal_emit (tree_model, signals[PRE_CHANGE], 0);
115 }
116 
117 /**
118  * e_tree_model_rebuilt:
119  * @tree_model:
120  *
121  * Return value:
122  **/
123 void
e_tree_model_rebuilt(ETreeModel * tree_model)124 e_tree_model_rebuilt (ETreeModel *tree_model)
125 {
126 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
127 
128 	g_signal_emit (tree_model, signals[REBUILT], 0);
129 }
130 /**
131  * e_tree_model_node_changed:
132  * @tree_model:
133  * @path:
134  *
135  *
136  *
137  * Return value:
138  **/
139 void
e_tree_model_node_changed(ETreeModel * tree_model,ETreePath path)140 e_tree_model_node_changed (ETreeModel *tree_model,
141                            ETreePath path)
142 {
143 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
144 
145 	g_signal_emit (tree_model, signals[NODE_CHANGED], 0, path);
146 }
147 
148 /**
149  * e_tree_model_node_data_changed:
150  * @tree_model:
151  * @path:
152  *
153  *
154  *
155  * Return value:
156  **/
157 void
e_tree_model_node_data_changed(ETreeModel * tree_model,ETreePath path)158 e_tree_model_node_data_changed (ETreeModel *tree_model,
159                                 ETreePath path)
160 {
161 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
162 
163 	g_signal_emit (tree_model, signals[NODE_DATA_CHANGED], 0, path);
164 }
165 
166 /**
167  * e_tree_model_node_inserted:
168  * @tree_model:
169  * @parent_path:
170  * @inserted_path:
171  *
172  *
173  **/
174 void
e_tree_model_node_inserted(ETreeModel * tree_model,ETreePath parent_path,ETreePath inserted_path)175 e_tree_model_node_inserted (ETreeModel *tree_model,
176                             ETreePath parent_path,
177                             ETreePath inserted_path)
178 {
179 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
180 
181 	g_signal_emit (
182 		tree_model, signals[NODE_INSERTED], 0,
183 		parent_path, inserted_path);
184 }
185 
186 /**
187  * e_tree_model_node_removed:
188  * @tree_model:
189  * @parent_path:
190  * @removed_path:
191  *
192  *
193  **/
194 void
e_tree_model_node_removed(ETreeModel * tree_model,ETreePath parent_path,ETreePath removed_path,gint old_position)195 e_tree_model_node_removed (ETreeModel *tree_model,
196                            ETreePath parent_path,
197                            ETreePath removed_path,
198                            gint old_position)
199 {
200 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
201 
202 	g_signal_emit (
203 		tree_model, signals[NODE_REMOVED], 0,
204 		parent_path, removed_path, old_position);
205 }
206 
207 /**
208  * e_tree_model_node_deleted:
209  * @tree_model:
210  * @deleted_path:
211  *
212  *
213  **/
214 void
e_tree_model_node_deleted(ETreeModel * tree_model,ETreePath deleted_path)215 e_tree_model_node_deleted (ETreeModel *tree_model,
216                            ETreePath deleted_path)
217 {
218 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
219 
220 	g_signal_emit (tree_model, signals[NODE_DELETED], 0, deleted_path);
221 }
222 
223 /**
224  * e_tree_model_get_root
225  * @tree_model: the ETreeModel of which we want the root node.
226  *
227  * Accessor for the root node of @tree_model.
228  *
229  * return values: the ETreePath corresponding to the root node.
230  */
231 ETreePath
e_tree_model_get_root(ETreeModel * tree_model)232 e_tree_model_get_root (ETreeModel *tree_model)
233 {
234 	ETreeModelInterface *iface;
235 
236 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
237 
238 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
239 	g_return_val_if_fail (iface->get_root != NULL, NULL);
240 
241 	return iface->get_root (tree_model);
242 }
243 
244 /**
245  * e_tree_model_node_get_parent:
246  * @tree_model:
247  * @path:
248  *
249  *
250  *
251  * Return value:
252  **/
253 ETreePath
e_tree_model_node_get_parent(ETreeModel * tree_model,ETreePath path)254 e_tree_model_node_get_parent (ETreeModel *tree_model,
255                               ETreePath path)
256 {
257 	ETreeModelInterface *iface;
258 
259 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
260 
261 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
262 	g_return_val_if_fail (iface->get_parent != NULL, NULL);
263 
264 	return iface->get_parent (tree_model, path);
265 }
266 
267 /**
268  * e_tree_model_node_get_first_child:
269  * @tree_model:
270  * @path:
271  *
272  *
273  *
274  * Return value:
275  **/
276 ETreePath
e_tree_model_node_get_first_child(ETreeModel * tree_model,ETreePath path)277 e_tree_model_node_get_first_child (ETreeModel *tree_model,
278                                    ETreePath path)
279 {
280 	ETreeModelInterface *iface;
281 
282 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
283 
284 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
285 	g_return_val_if_fail (iface->get_first_child != NULL, NULL);
286 
287 	return iface->get_first_child (tree_model, path);
288 }
289 
290 /**
291  * e_tree_model_node_get_next:
292  * @tree_model:
293  * @path:
294  *
295  *
296  *
297  * Return value:
298  **/
299 ETreePath
e_tree_model_node_get_next(ETreeModel * tree_model,ETreePath path)300 e_tree_model_node_get_next (ETreeModel *tree_model,
301                             ETreePath path)
302 {
303 	ETreeModelInterface *iface;
304 
305 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
306 
307 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
308 	g_return_val_if_fail (iface->get_next != NULL, NULL);
309 
310 	return iface->get_next (tree_model, path);
311 }
312 
313 /**
314  * e_tree_model_node_is_root:
315  * @tree_model:
316  * @path:
317  *
318  *
319  *
320  * Return value:
321  **/
322 gboolean
e_tree_model_node_is_root(ETreeModel * tree_model,ETreePath path)323 e_tree_model_node_is_root (ETreeModel *tree_model,
324                            ETreePath path)
325 {
326 	ETreeModelInterface *iface;
327 
328 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
329 
330 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
331 	g_return_val_if_fail (iface->is_root != NULL, FALSE);
332 
333 	return iface->is_root (tree_model, path);
334 }
335 
336 /**
337  * e_tree_model_node_is_expandable:
338  * @tree_model:
339  * @path:
340  *
341  *
342  *
343  * Return value:
344  **/
345 gboolean
e_tree_model_node_is_expandable(ETreeModel * tree_model,ETreePath path)346 e_tree_model_node_is_expandable (ETreeModel *tree_model,
347                                  ETreePath path)
348 {
349 	ETreeModelInterface *iface;
350 
351 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
352 	g_return_val_if_fail (path != NULL, FALSE);
353 
354 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
355 	g_return_val_if_fail (iface->is_expandable != NULL, FALSE);
356 
357 	return iface->is_expandable (tree_model, path);
358 }
359 
360 guint
e_tree_model_node_get_n_nodes(ETreeModel * tree_model)361 e_tree_model_node_get_n_nodes (ETreeModel *tree_model)
362 {
363 	ETreeModelInterface *iface;
364 
365 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
366 
367 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
368 	g_return_val_if_fail (iface->get_n_nodes != NULL, 0);
369 
370 	return iface->get_n_nodes (tree_model);
371 }
372 
373 guint
e_tree_model_node_get_n_children(ETreeModel * tree_model,ETreePath path)374 e_tree_model_node_get_n_children (ETreeModel *tree_model,
375                                   ETreePath path)
376 {
377 	ETreeModelInterface *iface;
378 
379 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
380 
381 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
382 	g_return_val_if_fail (iface->get_n_children != NULL, 0);
383 
384 	return iface->get_n_children (tree_model, path);
385 }
386 
387 /**
388  * e_tree_model_node_depth:
389  * @tree_model:
390  * @path:
391  *
392  *
393  *
394  * Return value:
395  **/
396 guint
e_tree_model_node_depth(ETreeModel * tree_model,ETreePath path)397 e_tree_model_node_depth (ETreeModel *tree_model,
398                          ETreePath path)
399 {
400 	ETreeModelInterface *iface;
401 
402 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
403 
404 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
405 	g_return_val_if_fail (iface->depth != NULL, 0);
406 
407 	return iface->depth (tree_model, path);
408 }
409 
410 /**
411  * e_tree_model_get_expanded_default
412  * @tree_model: The ETreeModel.
413  *
414  * XXX docs here.
415  *
416  * return values: Whether nodes should be expanded by default.
417  */
418 gboolean
e_tree_model_get_expanded_default(ETreeModel * tree_model)419 e_tree_model_get_expanded_default (ETreeModel *tree_model)
420 {
421 	ETreeModelInterface *iface;
422 
423 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
424 
425 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
426 	g_return_val_if_fail (iface->get_expanded_default != NULL, FALSE);
427 
428 	return iface->get_expanded_default (tree_model);
429 }
430 
431 /**
432  * e_tree_model_column_count
433  * @tree_model: The ETreeModel.
434  *
435  * XXX docs here.
436  *
437  * return values: The number of columns
438  */
439 gint
e_tree_model_column_count(ETreeModel * tree_model)440 e_tree_model_column_count (ETreeModel *tree_model)
441 {
442 	ETreeModelInterface *iface;
443 
444 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
445 
446 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
447 	g_return_val_if_fail (iface->column_count != NULL, 0);
448 
449 	return iface->column_count (tree_model);
450 }
451 
452 /**
453  * e_tree_model_get_save_id
454  * @tree_model: The ETreeModel.
455  * @path: The ETreePath.
456  *
457  * XXX docs here.
458  *
459  * return values: The save id for this path.
460  */
461 gchar *
e_tree_model_get_save_id(ETreeModel * tree_model,ETreePath path)462 e_tree_model_get_save_id (ETreeModel *tree_model,
463                           ETreePath path)
464 {
465 	ETreeModelInterface *iface;
466 
467 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
468 
469 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
470 	g_return_val_if_fail (iface->get_save_id != NULL, NULL);
471 
472 	return iface->get_save_id (tree_model, path);
473 }
474 
475 /**
476  * e_tree_model_get_node_by_id
477  * @tree_model: The ETreeModel.
478  * @save_id:
479  *
480  * get_node_by_id(get_save_id(node)) should be the original node.
481  * Likewise if get_node_by_id is not NULL, then
482  * get_save_id(get_node_by_id(string)) should be a copy of the
483  * original string.
484  *
485  * return values: The path for this save id.
486  */
487 ETreePath
e_tree_model_get_node_by_id(ETreeModel * tree_model,const gchar * save_id)488 e_tree_model_get_node_by_id (ETreeModel *tree_model,
489                              const gchar *save_id)
490 {
491 	ETreeModelInterface *iface;
492 
493 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
494 
495 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
496 	g_return_val_if_fail (iface->get_node_by_id != NULL, NULL);
497 
498 	return iface->get_node_by_id (tree_model, save_id);
499 }
500 
501 /**
502  * e_tree_model_sort_value_at:
503  * @tree_model: The ETreeModel.
504  * @path: The ETreePath to the node we're getting the data from.
505  * @col: the column to retrieve data from
506  *
507  * Return value: This function returns the value that is stored by the
508  * @tree_model in column @col and node @path.  The data returned can be a
509  * pointer or any data value that can be stored inside a pointer.
510  *
511  * The data returned is typically used by a sort renderer if it wants
512  * to proxy the data of cell value_at at a better sorting order.
513  *
514  * The data returned must be valid until the model sends a signal that
515  * affect that piece of data.  node_changed and node_deleted affect
516  * all data in tha t node and all nodes under that node.
517  * node_data_changed affects the data in that node.  node_col_changed
518  * affects the data in that node for that column.  node_inserted,
519  * node_removed, and no_change don't affect any data in this way.
520  **/
521 gpointer
e_tree_model_sort_value_at(ETreeModel * tree_model,ETreePath path,gint col)522 e_tree_model_sort_value_at (ETreeModel *tree_model,
523                             ETreePath path,
524                             gint col)
525 {
526 	ETreeModelInterface *iface;
527 
528 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
529 
530 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
531 	g_return_val_if_fail (iface->sort_value_at != NULL, NULL);
532 
533 	return iface->sort_value_at (tree_model, path, col);
534 }
535 
536 /**
537  * e_tree_model_value_at:
538  * @tree_model: The ETreeModel.
539  * @path: The ETreePath to the node we're getting the data from.
540  * @col: the column to retrieve data from
541  *
542  * Return value: This function returns the value that is stored by the
543  * @tree_model in column @col and node @path.  The data returned can be a
544  * pointer or any data value that can be stored inside a pointer.
545  *
546  * The data returned is typically used by an ECell renderer.
547  *
548  * The data returned must be valid until the model sends a signal that
549  * affect that piece of data.  node_changed and node_deleted affect
550  * all data in tha t node and all nodes under that node.
551  * node_data_changed affects the data in that node.  node_col_changed
552  * affects the data in that node for that column.  node_inserted,
553  * node_removed, and no_change don't affect any data in this way.
554  **/
555 gpointer
e_tree_model_value_at(ETreeModel * tree_model,ETreePath path,gint col)556 e_tree_model_value_at (ETreeModel *tree_model,
557                        ETreePath path,
558                        gint col)
559 {
560 	ETreeModelInterface *iface;
561 
562 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
563 
564 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
565 	g_return_val_if_fail (iface->value_at != NULL, NULL);
566 
567 	return iface->value_at (tree_model, path, col);
568 }
569 
570 /**
571  * e_tree_model_duplicate_value:
572  * @tree_model:
573  * @col:
574  * @value:
575  *
576  *
577  * Return value:
578  **/
579 gpointer
e_tree_model_duplicate_value(ETreeModel * tree_model,gint col,gconstpointer value)580 e_tree_model_duplicate_value (ETreeModel *tree_model,
581                               gint col,
582                               gconstpointer value)
583 {
584 	ETreeModelInterface *iface;
585 
586 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
587 
588 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
589 	g_return_val_if_fail (iface->duplicate_value != NULL, NULL);
590 
591 	return iface->duplicate_value (tree_model, col, value);
592 }
593 
594 /**
595  * e_tree_model_free_value:
596  * @tree_model:
597  * @col:
598  * @value:
599  *
600  *
601  * Return value:
602  **/
603 void
e_tree_model_free_value(ETreeModel * tree_model,gint col,gpointer value)604 e_tree_model_free_value (ETreeModel *tree_model,
605                          gint col,
606                          gpointer value)
607 {
608 	ETreeModelInterface *iface;
609 
610 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
611 
612 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
613 	g_return_if_fail (iface->free_value != NULL);
614 
615 	iface->free_value (tree_model, col, value);
616 }
617 
618 /**
619  * e_tree_model_initialize_value:
620  * @tree_model:
621  * @col:
622  *
623  *
624  *
625  * Return value:
626  **/
627 gpointer
e_tree_model_initialize_value(ETreeModel * tree_model,gint col)628 e_tree_model_initialize_value (ETreeModel *tree_model,
629                                gint col)
630 {
631 	ETreeModelInterface *iface;
632 
633 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
634 
635 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
636 	g_return_val_if_fail (iface->initialize_value != NULL, NULL);
637 
638 	return iface->initialize_value (tree_model, col);
639 }
640 
641 /**
642  * e_tree_model_value_is_empty:
643  * @tree_model:
644  * @col:
645  * @value:
646  *
647  *
648  * Return value:
649  **/
650 gboolean
e_tree_model_value_is_empty(ETreeModel * tree_model,gint col,gconstpointer value)651 e_tree_model_value_is_empty (ETreeModel *tree_model,
652                              gint col,
653                              gconstpointer value)
654 {
655 	ETreeModelInterface *iface;
656 
657 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), TRUE);
658 
659 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
660 	g_return_val_if_fail (iface->value_is_empty != NULL, TRUE);
661 
662 	return iface->value_is_empty (tree_model, col, value);
663 }
664 
665 /**
666  * e_tree_model_value_to_string:
667  * @tree_model:
668  * @col:
669  * @value:
670  *
671  *
672  * Return value:
673  **/
674 gchar *
e_tree_model_value_to_string(ETreeModel * tree_model,gint col,gconstpointer value)675 e_tree_model_value_to_string (ETreeModel *tree_model,
676                               gint col,
677                               gconstpointer value)
678 {
679 	ETreeModelInterface *iface;
680 
681 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
682 
683 	iface = E_TREE_MODEL_GET_INTERFACE (tree_model);
684 	g_return_val_if_fail (iface->value_to_string != NULL, NULL);
685 
686 	return iface->value_to_string (tree_model, col, value);
687 }
688 
689 /**
690  * e_tree_model_node_traverse:
691  * @tree_model:
692  * @path:
693  * @func:
694  * @data:
695  *
696  *
697  **/
698 void
e_tree_model_node_traverse(ETreeModel * tree_model,ETreePath path,ETreePathFunc func,gpointer data)699 e_tree_model_node_traverse (ETreeModel *tree_model,
700                             ETreePath path,
701                             ETreePathFunc func,
702                             gpointer data)
703 {
704 	ETreePath child;
705 
706 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
707 	g_return_if_fail (path != NULL);
708 
709 	child = e_tree_model_node_get_first_child (tree_model, path);
710 
711 	while (child) {
712 		ETreePath next_child;
713 
714 		next_child = e_tree_model_node_get_next (tree_model, child);
715 		e_tree_model_node_traverse (tree_model, child, func, data);
716 		if (func (tree_model, child, data))
717 			return;
718 
719 		child = next_child;
720 	}
721 }
722 
723 static ETreePath
e_tree_model_node_real_traverse(ETreeModel * model,ETreePath path,ETreePath end_path,ETreePathFunc func,gpointer data)724 e_tree_model_node_real_traverse (ETreeModel *model,
725                                  ETreePath path,
726                                  ETreePath end_path,
727                                  ETreePathFunc func,
728                                  gpointer data)
729 {
730 	ETreePath child;
731 
732 	g_return_val_if_fail (E_IS_TREE_MODEL (model), NULL);
733 	g_return_val_if_fail (path != NULL, NULL);
734 
735 	child = e_tree_model_node_get_first_child (model, path);
736 
737 	while (child) {
738 		ETreePath result;
739 
740 		if (child == end_path || func (model, child, data))
741 			return child;
742 
743 		if ((result = e_tree_model_node_real_traverse (
744 			model, child, end_path, func, data)))
745 			return result;
746 
747 		child = e_tree_model_node_get_next (model, child);
748 	}
749 
750 	return NULL;
751 }
752 
753 /**
754  * e_tree_model_node_find:
755  * @tree_model:
756  * @path:
757  * @end_path:
758  * @func:
759  * @data:
760  *
761  *
762  **/
763 ETreePath
e_tree_model_node_find(ETreeModel * tree_model,ETreePath path,ETreePath end_path,ETreePathFunc func,gpointer data)764 e_tree_model_node_find (ETreeModel *tree_model,
765                         ETreePath path,
766                         ETreePath end_path,
767                         ETreePathFunc func,
768                         gpointer data)
769 {
770 	ETreePath result;
771 	ETreePath next;
772 
773 	g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
774 
775 	/* Just search the whole tree in this case. */
776 	if (path == NULL) {
777 		ETreePath root;
778 		root = e_tree_model_get_root (tree_model);
779 
780 		if (end_path == root || func (tree_model, root, data))
781 			return root;
782 
783 		result = e_tree_model_node_real_traverse (
784 			tree_model, root, end_path, func, data);
785 		if (result)
786 			return result;
787 
788 		return NULL;
789 	}
790 
791 	while (1) {
792 
793 		if ((result = e_tree_model_node_real_traverse (
794 			tree_model, path, end_path, func, data)))
795 			return result;
796 		next = e_tree_model_node_get_next (tree_model, path);
797 
798 		while (next == NULL) {
799 			path = e_tree_model_node_get_parent (tree_model, path);
800 
801 			if (path == NULL)
802 				return NULL;
803 
804 			next = e_tree_model_node_get_next (tree_model, path);
805 		}
806 
807 		if (end_path == next || func (tree_model, next, data))
808 			return next;
809 
810 		path = next;
811 	}
812 }
813 
814