evolution-3.6.4/widgets/table/e-tree-model.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-tree-model.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-tree-model.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  *
  15  *
  16  * Authors:
  17  *		Chris Lahey  <clahey@ximian.com>
  18  *		Chris Toshok <toshok@ximian.com>
  19  *
  20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  21  *
  22  */
  23 
  24 #ifdef HAVE_CONFIG_H
  25 #include <config.h>
  26 #endif
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <unistd.h>
  31 #include <fcntl.h>
  32 
  33 #include <gtk/gtk.h>
  34 #include <libxml/parser.h>
  35 #include <libxml/xmlmemory.h>
  36 
  37 #include "e-util/e-util.h"
  38 #include "libevolution-utils/e-xml-utils.h"
  39 
  40 #include "e-tree-model.h"
  41 
  42 #define ETM_CLASS(e) (E_TREE_MODEL_GET_CLASS(e))
  43 
  44 #define d(x)
  45 
  46 G_DEFINE_TYPE (ETreeModel, e_tree_model, G_TYPE_OBJECT)
  47 
  48 enum {
  49 	PRE_CHANGE,
  50 	NO_CHANGE,
  51 	NODE_CHANGED,
  52 	NODE_DATA_CHANGED,
  53 	NODE_COL_CHANGED,
  54 	NODE_INSERTED,
  55 	NODE_REMOVED,
  56 	NODE_DELETED,
  57 	NODE_REQUEST_COLLAPSE,
  58 	REBUILT,
  59 	LAST_SIGNAL
  60 };
  61 
  62 static guint signals[LAST_SIGNAL] = {0, };
  63 
  64 static void
  65 e_tree_model_class_init (ETreeModelClass *class)
  66 {
  67 	GObjectClass *object_class = G_OBJECT_CLASS (class);
  68 
  69 	signals[PRE_CHANGE] = g_signal_new (
  70 		"pre_change",
  71 		G_TYPE_FROM_CLASS (object_class),
  72 		G_SIGNAL_RUN_LAST,
  73 		G_STRUCT_OFFSET (ETreeModelClass, pre_change),
  74 		(GSignalAccumulator) NULL, NULL,
  75 		g_cclosure_marshal_VOID__VOID,
  76 		G_TYPE_NONE, 0);
  77 
  78 	signals[NO_CHANGE] = g_signal_new (
  79 		"no_change",
  80 		G_TYPE_FROM_CLASS (object_class),
  81 		G_SIGNAL_RUN_LAST,
  82 		G_STRUCT_OFFSET (ETreeModelClass, no_change),
  83 		(GSignalAccumulator) NULL, NULL,
  84 		g_cclosure_marshal_VOID__VOID,
  85 		G_TYPE_NONE, 0);
  86 
  87 	signals[REBUILT] = g_signal_new (
  88 		"rebuilt",
  89 		G_TYPE_FROM_CLASS (object_class),
  90 		G_SIGNAL_RUN_LAST,
  91 		G_STRUCT_OFFSET (ETreeModelClass, rebuilt),
  92 		(GSignalAccumulator) NULL, NULL,
  93 		g_cclosure_marshal_VOID__VOID,
  94 		G_TYPE_NONE, 0);
  95 
  96 	signals[NODE_CHANGED] = g_signal_new (
  97 		"node_changed",
  98 		G_TYPE_FROM_CLASS (object_class),
  99 		G_SIGNAL_RUN_LAST,
 100 		G_STRUCT_OFFSET (ETreeModelClass, node_changed),
 101 		(GSignalAccumulator) NULL, NULL,
 102 		g_cclosure_marshal_VOID__POINTER,
 103 		G_TYPE_NONE, 1,
 104 		G_TYPE_POINTER);
 105 
 106 	signals[NODE_DATA_CHANGED] = g_signal_new (
 107 		"node_data_changed",
 108 		G_TYPE_FROM_CLASS (object_class),
 109 		G_SIGNAL_RUN_LAST,
 110 		G_STRUCT_OFFSET (ETreeModelClass, node_data_changed),
 111 		(GSignalAccumulator) NULL, NULL,
 112 		g_cclosure_marshal_VOID__POINTER,
 113 		G_TYPE_NONE, 1,
 114 		G_TYPE_POINTER);
 115 
 116 	signals[NODE_COL_CHANGED] = g_signal_new (
 117 		"node_col_changed",
 118 		G_TYPE_FROM_CLASS (object_class),
 119 		G_SIGNAL_RUN_LAST,
 120 		G_STRUCT_OFFSET (ETreeModelClass, node_col_changed),
 121 		(GSignalAccumulator) NULL, NULL,
 122 		e_marshal_VOID__POINTER_INT,
 123 		G_TYPE_NONE, 2,
 124 		G_TYPE_POINTER,
 125 		G_TYPE_INT);
 126 
 127 	signals[NODE_INSERTED] = g_signal_new (
 128 		"node_inserted",
 129 		G_TYPE_FROM_CLASS (object_class),
 130 		G_SIGNAL_RUN_LAST,
 131 		G_STRUCT_OFFSET (ETreeModelClass, node_inserted),
 132 		(GSignalAccumulator) NULL, NULL,
 133 		e_marshal_VOID__POINTER_POINTER,
 134 		G_TYPE_NONE, 2,
 135 		G_TYPE_POINTER,
 136 		G_TYPE_POINTER);
 137 
 138 	signals[NODE_REMOVED] = g_signal_new (
 139 		"node_removed",
 140 		G_TYPE_FROM_CLASS (object_class),
 141 		G_SIGNAL_RUN_LAST,
 142 		G_STRUCT_OFFSET (ETreeModelClass, node_removed),
 143 		(GSignalAccumulator) NULL, NULL,
 144 		e_marshal_VOID__POINTER_POINTER_INT,
 145 		G_TYPE_NONE, 3,
 146 		G_TYPE_POINTER,
 147 		G_TYPE_POINTER,
 148 		G_TYPE_INT);
 149 
 150 	signals[NODE_DELETED] = g_signal_new (
 151 		"node_deleted",
 152 		G_TYPE_FROM_CLASS (object_class),
 153 		G_SIGNAL_RUN_LAST,
 154 		G_STRUCT_OFFSET (ETreeModelClass, node_deleted),
 155 		(GSignalAccumulator) NULL, NULL,
 156 		g_cclosure_marshal_VOID__POINTER,
 157 		G_TYPE_NONE, 1,
 158 		G_TYPE_POINTER);
 159 
 160 	signals[NODE_REQUEST_COLLAPSE] = g_signal_new (
 161 		"node_request_collapse",
 162 		G_TYPE_FROM_CLASS (object_class),
 163 		G_SIGNAL_RUN_LAST,
 164 		G_STRUCT_OFFSET (ETreeModelClass, node_request_collapse),
 165 		(GSignalAccumulator) NULL, NULL,
 166 		g_cclosure_marshal_VOID__POINTER,
 167 		G_TYPE_NONE, 1,
 168 		G_TYPE_POINTER);
 169 
 170 	class->get_root              = NULL;
 171 
 172 	class->get_parent            = NULL;
 173 	class->get_first_child       = NULL;
 174 	class->get_last_child        = NULL;
 175 	class->get_next              = NULL;
 176 	class->get_prev              = NULL;
 177 
 178 	class->is_root               = NULL;
 179 	class->is_expandable         = NULL;
 180 	class->get_children          = NULL;
 181 	class->depth                 = NULL;
 182 
 183 	class->icon_at               = NULL;
 184 
 185 	class->get_expanded_default  = NULL;
 186 	class->column_count          = NULL;
 187 
 188 	class->has_save_id           = NULL;
 189 	class->get_save_id           = NULL;
 190 	class->has_get_node_by_id    = NULL;
 191 	class->get_node_by_id        = NULL;
 192 
 193 	class->has_change_pending    = NULL;
 194 
 195 	class->sort_value_at	  = NULL;
 196 	class->value_at              = NULL;
 197 	class->set_value_at          = NULL;
 198 	class->is_editable           = NULL;
 199 
 200 	class->duplicate_value       = NULL;
 201 	class->free_value            = NULL;
 202 	class->initialize_value      = NULL;
 203 	class->value_is_empty        = NULL;
 204 	class->value_to_string       = NULL;
 205 
 206 	class->pre_change            = NULL;
 207 	class->no_change             = NULL;
 208 	class->rebuilt		     = NULL;
 209 	class->node_changed          = NULL;
 210 	class->node_data_changed     = NULL;
 211 	class->node_col_changed      = NULL;
 212 	class->node_inserted         = NULL;
 213 	class->node_removed          = NULL;
 214 	class->node_deleted          = NULL;
 215 	class->node_request_collapse = NULL;
 216 }
 217 
 218 static void
 219 e_tree_model_init (ETreeModel *tree_model)
 220 {
 221 	/* nothing to do */
 222 }
 223 
 224 /* signals */
 225 
 226 /**
 227  * e_tree_model_node_changed:
 228  * @tree_model:
 229  * @node:
 230  *
 231  *
 232  *
 233  * Return value:
 234  **/
 235 void
 236 e_tree_model_pre_change (ETreeModel *tree_model)
 237 {
 238 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 239 
 240 	g_signal_emit (tree_model, signals[PRE_CHANGE], 0);
 241 }
 242 
 243 /**
 244  * e_tree_model_node_changed:
 245  * @tree_model:
 246  * @node:
 247  *
 248  *
 249  *
 250  * Return value:
 251  **/
 252 void
 253 e_tree_model_no_change (ETreeModel *tree_model)
 254 {
 255 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 256 
 257 	g_signal_emit (tree_model, signals[NO_CHANGE], 0);
 258 }
 259 
 260 /**
 261  * e_tree_model_rebuilt:
 262  * @tree_model:
 263  * @node:
 264  *
 265  *
 266  *
 267  * Return value:
 268  **/
 269 void
 270 e_tree_model_rebuilt (ETreeModel *tree_model)
 271 {
 272 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 273 
 274 	g_signal_emit (tree_model, signals[REBUILT], 0);
 275 }
 276 /**
 277  * e_tree_model_node_changed:
 278  * @tree_model:
 279  * @node:
 280  *
 281  *
 282  *
 283  * Return value:
 284  **/
 285 void
 286 e_tree_model_node_changed (ETreeModel *tree_model,
 287                            ETreePath node)
 288 {
 289 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 290 
 291 	g_signal_emit (tree_model, signals[NODE_CHANGED], 0, node);
 292 }
 293 
 294 /**
 295  * e_tree_model_node_data_changed:
 296  * @tree_model:
 297  * @node:
 298  *
 299  *
 300  *
 301  * Return value:
 302  **/
 303 void
 304 e_tree_model_node_data_changed (ETreeModel *tree_model,
 305                                 ETreePath node)
 306 {
 307 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 308 
 309 	g_signal_emit (tree_model, signals[NODE_DATA_CHANGED], 0, node);
 310 }
 311 
 312 /**
 313  * e_tree_model_node_col_changed:
 314  * @tree_model:
 315  * @node:
 316  *
 317  *
 318  *
 319  * Return value:
 320  **/
 321 void
 322 e_tree_model_node_col_changed (ETreeModel *tree_model,
 323                                ETreePath node,
 324                                gint col)
 325 {
 326 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 327 
 328 	g_signal_emit (tree_model, signals[NODE_COL_CHANGED], 0, node, col);
 329 }
 330 
 331 /**
 332  * e_tree_model_node_inserted:
 333  * @tree_model:
 334  * @parent_node:
 335  * @inserted_node:
 336  *
 337  *
 338  **/
 339 void
 340 e_tree_model_node_inserted (ETreeModel *tree_model,
 341                             ETreePath parent_node,
 342                             ETreePath inserted_node)
 343 {
 344 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 345 
 346 	g_signal_emit (
 347 		tree_model, signals[NODE_INSERTED], 0,
 348 		parent_node, inserted_node);
 349 }
 350 
 351 /**
 352  * e_tree_model_node_removed:
 353  * @tree_model:
 354  * @parent_node:
 355  * @removed_node:
 356  *
 357  *
 358  **/
 359 void
 360 e_tree_model_node_removed (ETreeModel *tree_model,
 361                            ETreePath parent_node,
 362                            ETreePath removed_node,
 363                            gint old_position)
 364 {
 365 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 366 
 367 	g_signal_emit (
 368 		tree_model, signals[NODE_REMOVED], 0,
 369 		parent_node, removed_node, old_position);
 370 }
 371 
 372 /**
 373  * e_tree_model_node_deleted:
 374  * @tree_model:
 375  * @deleted_node:
 376  *
 377  *
 378  **/
 379 void
 380 e_tree_model_node_deleted (ETreeModel *tree_model,
 381                            ETreePath deleted_node)
 382 {
 383 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 384 
 385 	g_signal_emit (tree_model, signals[NODE_DELETED], 0, deleted_node);
 386 }
 387 
 388 /**
 389  * e_tree_model_node_request_collapse:
 390  * @tree_model:
 391  * @collapsed_node:
 392  *
 393  *
 394  **/
 395 void
 396 e_tree_model_node_request_collapse (ETreeModel *tree_model,
 397                                     ETreePath collapsed_node)
 398 {
 399 	g_return_if_fail (E_IS_TREE_MODEL (tree_model));
 400 
 401 	g_signal_emit (tree_model, signals[NODE_REQUEST_COLLAPSE], 0, collapsed_node);
 402 }
 403 
 404 /**
 405  * e_tree_model_new
 406  *
 407  * XXX docs here.
 408  *
 409  * return values: a newly constructed ETreeModel.
 410  */
 411 ETreeModel *
 412 e_tree_model_new (void)
 413 {
 414 	return g_object_new (E_TYPE_TREE_MODEL, NULL);
 415 }
 416 
 417 /**
 418  * e_tree_model_get_root
 419  * @etree: the ETreeModel of which we want the root node.
 420  *
 421  * Accessor for the root node of @etree.
 422  *
 423  * return values: the ETreePath corresponding to the root node.
 424  */
 425 ETreePath
 426 e_tree_model_get_root (ETreeModel *etree)
 427 {
 428 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 429 
 430 	if (ETM_CLASS (etree)->get_root)
 431 		return ETM_CLASS (etree)->get_root (etree);
 432 	else
 433 		return NULL;
 434 }
 435 
 436 /**
 437  * e_tree_model_node_get_parent:
 438  * @etree:
 439  * @path:
 440  *
 441  *
 442  *
 443  * Return value:
 444  **/
 445 ETreePath
 446 e_tree_model_node_get_parent (ETreeModel *etree,
 447                               ETreePath node)
 448 {
 449 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 450 
 451 	if (ETM_CLASS (etree)->get_parent)
 452 		return ETM_CLASS (etree)->get_parent (etree, node);
 453 	else
 454 		return NULL;
 455 }
 456 
 457 /**
 458  * e_tree_model_node_get_first_child:
 459  * @etree:
 460  * @node:
 461  *
 462  *
 463  *
 464  * Return value:
 465  **/
 466 ETreePath
 467 e_tree_model_node_get_first_child (ETreeModel *etree,
 468                                    ETreePath node)
 469 {
 470 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 471 
 472 	if (ETM_CLASS (etree)->get_first_child)
 473 		return ETM_CLASS (etree)->get_first_child (etree, node);
 474 	else
 475 		return NULL;
 476 }
 477 
 478 /**
 479  * e_tree_model_node_get_last_child:
 480  * @etree:
 481  * @node:
 482  *
 483  *
 484  *
 485  * Return value:
 486  **/
 487 ETreePath
 488 e_tree_model_node_get_last_child (ETreeModel *etree,
 489                                   ETreePath node)
 490 {
 491 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 492 
 493 	if (ETM_CLASS (etree)->get_last_child)
 494 		return ETM_CLASS (etree)->get_last_child (etree, node);
 495 	else
 496 		return NULL;
 497 }
 498 
 499 /**
 500  * e_tree_model_node_get_next:
 501  * @etree:
 502  * @node:
 503  *
 504  *
 505  *
 506  * Return value:
 507  **/
 508 ETreePath
 509 e_tree_model_node_get_next (ETreeModel *etree,
 510                             ETreePath node)
 511 {
 512 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 513 
 514 	if (ETM_CLASS (etree)->get_next)
 515 		return ETM_CLASS (etree)->get_next (etree, node);
 516 	else
 517 		return NULL;
 518 }
 519 
 520 /**
 521  * e_tree_model_node_get_prev:
 522  * @etree:
 523  * @node:
 524  *
 525  *
 526  *
 527  * Return value:
 528  **/
 529 ETreePath
 530 e_tree_model_node_get_prev (ETreeModel *etree,
 531                             ETreePath node)
 532 {
 533 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 534 
 535 	if (ETM_CLASS (etree)->get_prev)
 536 		return ETM_CLASS (etree)->get_prev (etree, node);
 537 	else
 538 		return NULL;
 539 }
 540 
 541 /**
 542  * e_tree_model_node_is_root:
 543  * @etree:
 544  * @path:
 545  *
 546  *
 547  *
 548  * Return value:
 549  **/
 550 gboolean
 551 e_tree_model_node_is_root (ETreeModel *etree,
 552                            ETreePath node)
 553 {
 554 	g_return_val_if_fail (etree != NULL, FALSE);
 555 
 556 	if (ETM_CLASS (etree)->is_root)
 557 		return ETM_CLASS (etree)->is_root (etree, node);
 558 	else
 559 		return FALSE;
 560 }
 561 
 562 /**
 563  * e_tree_model_node_is_expandable:
 564  * @etree:
 565  * @path:
 566  *
 567  *
 568  *
 569  * Return value:
 570  **/
 571 gboolean
 572 e_tree_model_node_is_expandable (ETreeModel *etree,
 573                                  ETreePath node)
 574 {
 575 	g_return_val_if_fail (etree != NULL, FALSE);
 576 	g_return_val_if_fail (node != NULL, FALSE);
 577 
 578 	if (ETM_CLASS (etree)->is_expandable)
 579 		return ETM_CLASS (etree)->is_expandable (etree, node);
 580 	else
 581 		return FALSE;
 582 }
 583 
 584 guint
 585 e_tree_model_node_get_children (ETreeModel *etree,
 586                                 ETreePath node,
 587                                 ETreePath **nodes)
 588 {
 589 	g_return_val_if_fail (etree != NULL, 0);
 590 	if (ETM_CLASS (etree)->get_children)
 591 		return ETM_CLASS (etree)->get_children (etree, node, nodes);
 592 	else
 593 		return 0;
 594 }
 595 
 596 /**
 597  * e_tree_model_node_depth:
 598  * @etree:
 599  * @path:
 600  *
 601  *
 602  *
 603  * Return value:
 604  **/
 605 guint
 606 e_tree_model_node_depth (ETreeModel *etree,
 607                          ETreePath node)
 608 {
 609 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
 610 
 611 	if (ETM_CLASS (etree)->depth)
 612 		return ETM_CLASS (etree)->depth (etree, node);
 613 	else
 614 		return 0;
 615 }
 616 
 617 /**
 618  * e_tree_model_icon_at
 619  * @etree: The ETreeModel.
 620  * @path: The ETreePath to the node we're getting the icon of.
 621  *
 622  * XXX docs here.
 623  *
 624  * return values: the GdkPixbuf associated with this node.
 625  */
 626 GdkPixbuf *
 627 e_tree_model_icon_at (ETreeModel *etree,
 628                       ETreePath node)
 629 {
 630 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 631 
 632 	if (ETM_CLASS (etree)->icon_at)
 633 		return ETM_CLASS (etree)->icon_at (etree, node);
 634 	else
 635 		return NULL;
 636 }
 637 
 638 /**
 639  * e_tree_model_get_expanded_default
 640  * @etree: The ETreeModel.
 641  *
 642  * XXX docs here.
 643  *
 644  * return values: Whether nodes should be expanded by default.
 645  */
 646 gboolean
 647 e_tree_model_get_expanded_default (ETreeModel *etree)
 648 {
 649 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
 650 
 651 	if (ETM_CLASS (etree)->get_expanded_default)
 652 		return ETM_CLASS (etree)->get_expanded_default (etree);
 653 	else
 654 		return FALSE;
 655 }
 656 
 657 /**
 658  * e_tree_model_column_count
 659  * @etree: The ETreeModel.
 660  *
 661  * XXX docs here.
 662  *
 663  * return values: The number of columns
 664  */
 665 gint
 666 e_tree_model_column_count (ETreeModel *etree)
 667 {
 668 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
 669 
 670 	if (ETM_CLASS (etree)->column_count)
 671 		return ETM_CLASS (etree)->column_count (etree);
 672 	else
 673 		return 0;
 674 }
 675 
 676 /**
 677  * e_tree_model_has_save_id
 678  * @etree: The ETreeModel.
 679  *
 680  * XXX docs here.
 681  *
 682  * return values: Whether this tree has valid save id data.
 683  */
 684 gboolean
 685 e_tree_model_has_save_id (ETreeModel *etree)
 686 {
 687 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
 688 
 689 	if (ETM_CLASS (etree)->has_save_id)
 690 		return ETM_CLASS (etree)->has_save_id (etree);
 691 	else
 692 		return FALSE;
 693 }
 694 
 695 /**
 696  * e_tree_model_get_save_id
 697  * @etree: The ETreeModel.
 698  * @node: The ETreePath.
 699  *
 700  * XXX docs here.
 701  *
 702  * return values: The save id for this path.
 703  */
 704 gchar *
 705 e_tree_model_get_save_id (ETreeModel *etree,
 706                           ETreePath node)
 707 {
 708 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 709 
 710 	if (ETM_CLASS (etree)->get_save_id)
 711 		return ETM_CLASS (etree)->get_save_id (etree, node);
 712 	else
 713 		return NULL;
 714 }
 715 
 716 /**
 717  * e_tree_model_has_get_node_by_id
 718  * @etree: The ETreeModel.
 719  *
 720  * XXX docs here.
 721  *
 722  * return values: Whether this tree can quickly get a node from its save id.
 723  */
 724 gboolean
 725 e_tree_model_has_get_node_by_id (ETreeModel *etree)
 726 {
 727 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
 728 
 729 	if (ETM_CLASS (etree)->has_get_node_by_id)
 730 		return ETM_CLASS (etree)->has_get_node_by_id (etree);
 731 	else
 732 		return FALSE;
 733 }
 734 
 735 /**
 736  * e_tree_model_get_node_by_id
 737  * @etree: The ETreeModel.
 738  * @node: The ETreePath.
 739  *
 740  * get_node_by_id(get_save_id(node)) should be the original node.
 741  * Likewise if get_node_by_id is not NULL, then
 742  * get_save_id(get_node_by_id(string)) should be a copy of the
 743  * original string.
 744  *
 745  * return values: The path for this save id.
 746  */
 747 ETreePath
 748 e_tree_model_get_node_by_id (ETreeModel *etree,
 749                              const gchar *save_id)
 750 {
 751 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 752 
 753 	if (ETM_CLASS (etree)->get_node_by_id)
 754 		return ETM_CLASS (etree)->get_node_by_id (etree, save_id);
 755 	else
 756 		return NULL;
 757 }
 758 
 759 /**
 760  * e_tree_model_has_change_pending
 761  * @etree: The ETreeModel.
 762  *
 763  * XXX docs here.
 764  *
 765  * return values: Whether this tree has valid save id data.
 766  */
 767 gboolean
 768 e_tree_model_has_change_pending (ETreeModel *etree)
 769 {
 770 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
 771 
 772 	if (ETM_CLASS (etree)->has_change_pending)
 773 		return ETM_CLASS (etree)->has_change_pending (etree);
 774 	else
 775 		return FALSE;
 776 }
 777 
 778 /**
 779  * e_tree_model_sort_value_at:
 780  * @etree: The ETreeModel.
 781  * @node: The ETreePath to the node we're getting the data from.
 782  * @col: the column to retrieve data from
 783  *
 784  * Return value: This function returns the value that is stored by the
 785  * @etree in column @col and node @node.  The data returned can be a
 786  * pointer or any data value that can be stored inside a pointer.
 787  *
 788  * The data returned is typically used by an sort renderer if it wants
 789  * to proxy the data of cell value_at at a better sorting order.
 790  *
 791  * The data returned must be valid until the model sends a signal that
 792  * affect that piece of data.  node_changed and node_deleted affect
 793  * all data in tha t node and all nodes under that node.
 794  * node_data_changed affects the data in that node.  node_col_changed
 795  * affects the data in that node for that column.  node_inserted,
 796  * node_removed, and no_change don't affect any data in this way.
 797  **/
 798 gpointer
 799 e_tree_model_sort_value_at (ETreeModel *etree,
 800                             ETreePath node,
 801                             gint col)
 802 {
 803 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 804 
 805 	if (ETM_CLASS (etree)->sort_value_at)
 806 		return ETM_CLASS (etree)->sort_value_at (etree, node, col);
 807 	else
 808 		return NULL;
 809 }
 810 
 811 /**
 812  * e_tree_model_value_at:
 813  * @etree: The ETreeModel.
 814  * @node: The ETreePath to the node we're getting the data from.
 815  * @col: the column to retrieve data from
 816  *
 817  * Return value: This function returns the value that is stored by the
 818  * @etree in column @col and node @node.  The data returned can be a
 819  * pointer or any data value that can be stored inside a pointer.
 820  *
 821  * The data returned is typically used by an ECell renderer.
 822  *
 823  * The data returned must be valid until the model sends a signal that
 824  * affect that piece of data.  node_changed and node_deleted affect
 825  * all data in tha t node and all nodes under that node.
 826  * node_data_changed affects the data in that node.  node_col_changed
 827  * affects the data in that node for that column.  node_inserted,
 828  * node_removed, and no_change don't affect any data in this way.
 829  **/
 830 gpointer
 831 e_tree_model_value_at (ETreeModel *etree,
 832                        ETreePath node,
 833                        gint col)
 834 {
 835 	g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
 836 
 837 	if (ETM_CLASS (etree)->value_at)
 838 		return ETM_CLASS (etree)->value_at (etree, node, col);
 839 	else
 840 		return NULL;
 841 }
 842 
 843 void
 844 e_tree_model_set_value_at (ETreeModel *etree,
 845                            ETreePath node,
 846                            gint col,
 847                            gconstpointer val)
 848 {
 849 	g_return_if_fail (E_IS_TREE_MODEL (etree));
 850 
 851 	if (ETM_CLASS (etree)->set_value_at)
 852 		ETM_CLASS (etree)->set_value_at (etree, node, col, val);
 853 }
 854 
 855 /**
 856  * e_tree_model_node_is_editable:
 857  * @etree:
 858  * @path:
 859  *
 860  *
 861  *
 862  * Return value:
 863  **/
 864 gboolean
 865 e_tree_model_node_is_editable (ETreeModel *etree,
 866                                ETreePath node,
 867                                gint col)
 868 {
 869 	g_return_val_if_fail (etree != NULL, FALSE);
 870 
 871 	if (ETM_CLASS (etree)->is_editable)
 872 		return ETM_CLASS (etree)->is_editable (etree, node, col);
 873 	else
 874 		return FALSE;
 875 }
 876 
 877 /**
 878  * e_tree_model_duplicate_value:
 879  * @etree:
 880  * @path:
 881  *
 882  *
 883  *
 884  * Return value:
 885  **/
 886 gpointer
 887 e_tree_model_duplicate_value (ETreeModel *etree,
 888                               gint col,
 889                               gconstpointer value)
 890 {
 891 	g_return_val_if_fail (etree != NULL, NULL);
 892 
 893 	if (ETM_CLASS (etree)->duplicate_value)
 894 		return ETM_CLASS (etree)->duplicate_value (etree, col, value);
 895 	else
 896 		return NULL;
 897 }
 898 
 899 /**
 900  * e_tree_model_free_value:
 901  * @etree:
 902  * @path:
 903  *
 904  *
 905  *
 906  * Return value:
 907  **/
 908 void
 909 e_tree_model_free_value (ETreeModel *etree,
 910                          gint col,
 911                          gpointer value)
 912 {
 913 	g_return_if_fail (etree != NULL);
 914 
 915 	if (ETM_CLASS (etree)->free_value)
 916 		ETM_CLASS (etree)->free_value (etree, col, value);
 917 }
 918 
 919 /**
 920  * e_tree_model_initialize_value:
 921  * @etree:
 922  * @path:
 923  *
 924  *
 925  *
 926  * Return value:
 927  **/
 928 gpointer
 929 e_tree_model_initialize_value (ETreeModel *etree,
 930                                gint col)
 931 {
 932 	g_return_val_if_fail (etree != NULL, NULL);
 933 
 934 	if (ETM_CLASS (etree)->initialize_value)
 935 		return ETM_CLASS (etree)->initialize_value (etree, col);
 936 	else
 937 		return NULL;
 938 }
 939 
 940 /**
 941  * e_tree_model_value_is_empty:
 942  * @etree:
 943  * @path:
 944  *
 945  *
 946  *
 947  * Return value:
 948  **/
 949 gboolean
 950 e_tree_model_value_is_empty (ETreeModel *etree,
 951                              gint col,
 952                              gconstpointer value)
 953 {
 954 	g_return_val_if_fail (etree != NULL, TRUE);
 955 
 956 	if (ETM_CLASS (etree)->value_is_empty)
 957 		return ETM_CLASS (etree)->value_is_empty (etree, col, value);
 958 	else
 959 		return TRUE;
 960 }
 961 
 962 /**
 963  * e_tree_model_value_to_string:
 964  * @etree:
 965  * @path:
 966  *
 967  *
 968  *
 969  * Return value:
 970  **/
 971 gchar *
 972 e_tree_model_value_to_string (ETreeModel *etree,
 973                               gint col,
 974                               gconstpointer value)
 975 {
 976 	g_return_val_if_fail (etree != NULL, g_strdup (""));
 977 
 978 	if (ETM_CLASS (etree)->value_to_string)
 979 		return ETM_CLASS (etree)->value_to_string (etree, col, value);
 980 	else
 981 		return g_strdup ("");
 982 }
 983 
 984 /**
 985  * e_tree_model_node_traverse:
 986  * @model:
 987  * @path:
 988  * @func:
 989  * @data:
 990  *
 991  *
 992  **/
 993 void
 994 e_tree_model_node_traverse (ETreeModel *model,
 995                             ETreePath path,
 996                             ETreePathFunc func,
 997                             gpointer data)
 998 {
 999 	ETreePath child;
1000 
1001 	g_return_if_fail (E_IS_TREE_MODEL (model));
1002 	g_return_if_fail (path != NULL);
1003 
1004 	child = e_tree_model_node_get_first_child (model, path);
1005 
1006 	while (child) {
1007 		ETreePath next_child;
1008 
1009 		next_child = e_tree_model_node_get_next (model, child);
1010 		e_tree_model_node_traverse (model, child, func, data);
1011 		if (func (model, child, data))
1012 			return;
1013 
1014 		child = next_child;
1015 	}
1016 }
1017 
1018 /**
1019  * e_tree_model_node_traverse_preorder:
1020  * @model:
1021  * @path:
1022  * @func:
1023  * @data:
1024  *
1025  *
1026  **/
1027 void
1028 e_tree_model_node_traverse_preorder (ETreeModel *model,
1029                                      ETreePath path,
1030                                      ETreePathFunc func,
1031                                      gpointer data)
1032 {
1033 	ETreePath child;
1034 
1035 	g_return_if_fail (E_IS_TREE_MODEL (model));
1036 	g_return_if_fail (path != NULL);
1037 
1038 	child = e_tree_model_node_get_first_child (model, path);
1039 
1040 	while (child) {
1041 		ETreePath next_child;
1042 
1043 		if (func (model, child, data))
1044 			return;
1045 
1046 		next_child = e_tree_model_node_get_next (model, child);
1047 		e_tree_model_node_traverse_preorder (model, child, func, data);
1048 
1049 		child = next_child;
1050 	}
1051 }
1052 
1053 /**
1054  * e_tree_model_node_traverse_preorder:
1055  * @model:
1056  * @path:
1057  * @func:
1058  * @data:
1059  *
1060  *
1061  **/
1062 static ETreePath
1063 e_tree_model_node_real_traverse (ETreeModel *model,
1064                                  ETreePath path,
1065                                  ETreePath end_path,
1066                                  gboolean forward_direction,
1067                                  ETreePathFunc func,
1068                                  gpointer data)
1069 {
1070 	ETreePath child;
1071 
1072 	g_return_val_if_fail (E_IS_TREE_MODEL (model), NULL);
1073 	g_return_val_if_fail (path != NULL, NULL);
1074 
1075 	if (forward_direction)
1076 		child = e_tree_model_node_get_first_child (model, path);
1077 	else
1078 		child = e_tree_model_node_get_last_child (model, path);
1079 
1080 	while (child) {
1081 		ETreePath result;
1082 
1083 		if (forward_direction && (child == end_path || func (model, child, data)))
1084 			return child;
1085 
1086 		if ((result = e_tree_model_node_real_traverse (
1087 			model, child, end_path,
1088 			forward_direction, func, data)))
1089 			return result;
1090 
1091 		if (!forward_direction && (child == end_path || func (model, child, data)))
1092 			return child;
1093 
1094 		if (forward_direction)
1095 			child = e_tree_model_node_get_next (model, child);
1096 		else
1097 			child = e_tree_model_node_get_prev (model, child);
1098 	}
1099 	return NULL;
1100 }
1101 
1102 /**
1103  * e_tree_model_node_traverse_preorder:
1104  * @model:
1105  * @path:
1106  * @func:
1107  * @data:
1108  *
1109  *
1110  **/
1111 ETreePath
1112 e_tree_model_node_find (ETreeModel *model,
1113                         ETreePath path,
1114                         ETreePath end_path,
1115                         gboolean forward_direction,
1116                         ETreePathFunc func,
1117                         gpointer data)
1118 {
1119 	ETreePath result;
1120 	ETreePath next;
1121 
1122 	g_return_val_if_fail (E_IS_TREE_MODEL (model), NULL);
1123 
1124 	/* Just search the whole tree in this case. */
1125 	if (path == NULL) {
1126 		ETreePath root;
1127 		root = e_tree_model_get_root (model);
1128 
1129 		if (forward_direction && (end_path == root || func (model, root, data)))
1130 			return root;
1131 
1132 		result = e_tree_model_node_real_traverse (
1133 			model, root, end_path, forward_direction, func, data);
1134 		if (result)
1135 			return result;
1136 
1137 		if (!forward_direction && (end_path == root || func (model, root, data)))
1138 			return root;
1139 
1140 		return NULL;
1141 	}
1142 
1143 	while (1) {
1144 
1145 		if (forward_direction) {
1146 			if ((result = e_tree_model_node_real_traverse (
1147 				model, path, end_path,
1148 				forward_direction, func, data)))
1149 				return result;
1150 			next = e_tree_model_node_get_next (model, path);
1151 		} else {
1152 			next = e_tree_model_node_get_prev (model, path);
1153 			if (next && (result = e_tree_model_node_real_traverse (
1154 				model, next, end_path,
1155 				forward_direction, func, data)))
1156 				return result;
1157 		}
1158 
1159 		while (next == NULL) {
1160 			path = e_tree_model_node_get_parent (model, path);
1161 
1162 			if (path == NULL)
1163 				return NULL;
1164 
1165 			if (forward_direction)
1166 				next = e_tree_model_node_get_next (model, path);
1167 			else
1168 				next = path;
1169 		}
1170 
1171 		if (end_path == next || func (model, next, data))
1172 			return next;
1173 
1174 		path = next;
1175 	}
1176 }