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