Returns the total number of nodes in the tree model, including hidden nodes in collapsed tree branches.
815 lines
19 KiB
C
815 lines
19 KiB
C
/*
|
|
* e-tree-model.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*/
|
|
|
|
#include "e-tree-model.h"
|
|
|
|
enum {
|
|
PRE_CHANGE,
|
|
NODE_CHANGED,
|
|
NODE_DATA_CHANGED,
|
|
NODE_INSERTED,
|
|
NODE_REMOVED,
|
|
NODE_DELETED,
|
|
REBUILT,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL];
|
|
|
|
G_DEFINE_INTERFACE (ETreeModel, e_tree_model, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
e_tree_model_default_init (ETreeModelInterface *interface)
|
|
{
|
|
signals[PRE_CHANGE] = g_signal_new (
|
|
"pre_change",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, pre_change),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
signals[REBUILT] = g_signal_new (
|
|
"rebuilt",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, rebuilt),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
signals[NODE_CHANGED] = g_signal_new (
|
|
"node_changed",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, node_changed),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
|
|
signals[NODE_DATA_CHANGED] = g_signal_new (
|
|
"node_data_changed",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, node_data_changed),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
|
|
signals[NODE_INSERTED] = g_signal_new (
|
|
"node_inserted",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, node_inserted),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 2,
|
|
G_TYPE_POINTER,
|
|
G_TYPE_POINTER);
|
|
|
|
signals[NODE_REMOVED] = g_signal_new (
|
|
"node_removed",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, node_removed),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 3,
|
|
G_TYPE_POINTER,
|
|
G_TYPE_POINTER,
|
|
G_TYPE_INT);
|
|
|
|
signals[NODE_DELETED] = g_signal_new (
|
|
"node_deleted",
|
|
G_TYPE_FROM_INTERFACE (interface),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ETreeModelInterface, node_deleted),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_POINTER);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_pre_change:
|
|
* @tree_model:
|
|
*
|
|
* Return value:
|
|
**/
|
|
void
|
|
e_tree_model_pre_change (ETreeModel *tree_model)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (tree_model, signals[PRE_CHANGE], 0);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_rebuilt:
|
|
* @tree_model:
|
|
*
|
|
* Return value:
|
|
**/
|
|
void
|
|
e_tree_model_rebuilt (ETreeModel *tree_model)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (tree_model, signals[REBUILT], 0);
|
|
}
|
|
/**
|
|
* e_tree_model_node_changed:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
void
|
|
e_tree_model_node_changed (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (tree_model, signals[NODE_CHANGED], 0, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_data_changed:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
void
|
|
e_tree_model_node_data_changed (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (tree_model, signals[NODE_DATA_CHANGED], 0, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_inserted:
|
|
* @tree_model:
|
|
* @parent_path:
|
|
* @inserted_path:
|
|
*
|
|
*
|
|
**/
|
|
void
|
|
e_tree_model_node_inserted (ETreeModel *tree_model,
|
|
ETreePath parent_path,
|
|
ETreePath inserted_path)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (
|
|
tree_model, signals[NODE_INSERTED], 0,
|
|
parent_path, inserted_path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_removed:
|
|
* @tree_model:
|
|
* @parent_path:
|
|
* @removed_path:
|
|
*
|
|
*
|
|
**/
|
|
void
|
|
e_tree_model_node_removed (ETreeModel *tree_model,
|
|
ETreePath parent_path,
|
|
ETreePath removed_path,
|
|
gint old_position)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (
|
|
tree_model, signals[NODE_REMOVED], 0,
|
|
parent_path, removed_path, old_position);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_deleted:
|
|
* @tree_model:
|
|
* @deleted_path:
|
|
*
|
|
*
|
|
**/
|
|
void
|
|
e_tree_model_node_deleted (ETreeModel *tree_model,
|
|
ETreePath deleted_path)
|
|
{
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
g_signal_emit (tree_model, signals[NODE_DELETED], 0, deleted_path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_get_root
|
|
* @tree_model: the ETreeModel of which we want the root node.
|
|
*
|
|
* Accessor for the root node of @tree_model.
|
|
*
|
|
* return values: the ETreePath corresponding to the root node.
|
|
*/
|
|
ETreePath
|
|
e_tree_model_get_root (ETreeModel *tree_model)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_root != NULL, NULL);
|
|
|
|
return interface->get_root (tree_model);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_get_parent:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
ETreePath
|
|
e_tree_model_node_get_parent (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_parent != NULL, NULL);
|
|
|
|
return interface->get_parent (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_get_first_child:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
ETreePath
|
|
e_tree_model_node_get_first_child (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_first_child != NULL, NULL);
|
|
|
|
return interface->get_first_child (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_get_next:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
ETreePath
|
|
e_tree_model_node_get_next (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_next != NULL, NULL);
|
|
|
|
return interface->get_next (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_is_root:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gboolean
|
|
e_tree_model_node_is_root (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->is_root != NULL, FALSE);
|
|
|
|
return interface->is_root (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_is_expandable:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gboolean
|
|
e_tree_model_node_is_expandable (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
|
|
g_return_val_if_fail (path != NULL, FALSE);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->is_expandable != NULL, FALSE);
|
|
|
|
return interface->is_expandable (tree_model, path);
|
|
}
|
|
|
|
guint
|
|
e_tree_model_node_get_n_nodes (ETreeModel *tree_model)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_n_nodes != NULL, 0);
|
|
|
|
return interface->get_n_nodes (tree_model);
|
|
}
|
|
|
|
guint
|
|
e_tree_model_node_get_n_children (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_n_children != NULL, 0);
|
|
|
|
return interface->get_n_children (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_depth:
|
|
* @tree_model:
|
|
* @path:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
guint
|
|
e_tree_model_node_depth (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->depth != NULL, 0);
|
|
|
|
return interface->depth (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_get_expanded_default
|
|
* @tree_model: The ETreeModel.
|
|
*
|
|
* XXX docs here.
|
|
*
|
|
* return values: Whether nodes should be expanded by default.
|
|
*/
|
|
gboolean
|
|
e_tree_model_get_expanded_default (ETreeModel *tree_model)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), FALSE);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_expanded_default != NULL, FALSE);
|
|
|
|
return interface->get_expanded_default (tree_model);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_column_count
|
|
* @tree_model: The ETreeModel.
|
|
*
|
|
* XXX docs here.
|
|
*
|
|
* return values: The number of columns
|
|
*/
|
|
gint
|
|
e_tree_model_column_count (ETreeModel *tree_model)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), 0);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->column_count != NULL, 0);
|
|
|
|
return interface->column_count (tree_model);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_get_save_id
|
|
* @tree_model: The ETreeModel.
|
|
* @path: The ETreePath.
|
|
*
|
|
* XXX docs here.
|
|
*
|
|
* return values: The save id for this path.
|
|
*/
|
|
gchar *
|
|
e_tree_model_get_save_id (ETreeModel *tree_model,
|
|
ETreePath path)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_save_id != NULL, NULL);
|
|
|
|
return interface->get_save_id (tree_model, path);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_get_node_by_id
|
|
* @tree_model: The ETreeModel.
|
|
* @save_id:
|
|
*
|
|
* get_node_by_id(get_save_id(node)) should be the original node.
|
|
* Likewise if get_node_by_id is not NULL, then
|
|
* get_save_id(get_node_by_id(string)) should be a copy of the
|
|
* original string.
|
|
*
|
|
* return values: The path for this save id.
|
|
*/
|
|
ETreePath
|
|
e_tree_model_get_node_by_id (ETreeModel *tree_model,
|
|
const gchar *save_id)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->get_node_by_id != NULL, NULL);
|
|
|
|
return interface->get_node_by_id (tree_model, save_id);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_sort_value_at:
|
|
* @tree_model: The ETreeModel.
|
|
* @path: The ETreePath to the node we're getting the data from.
|
|
* @col: the column to retrieve data from
|
|
*
|
|
* Return value: This function returns the value that is stored by the
|
|
* @tree_model in column @col and node @path. The data returned can be a
|
|
* pointer or any data value that can be stored inside a pointer.
|
|
*
|
|
* The data returned is typically used by an sort renderer if it wants
|
|
* to proxy the data of cell value_at at a better sorting order.
|
|
*
|
|
* The data returned must be valid until the model sends a signal that
|
|
* affect that piece of data. node_changed and node_deleted affect
|
|
* all data in tha t node and all nodes under that node.
|
|
* node_data_changed affects the data in that node. node_col_changed
|
|
* affects the data in that node for that column. node_inserted,
|
|
* node_removed, and no_change don't affect any data in this way.
|
|
**/
|
|
gpointer
|
|
e_tree_model_sort_value_at (ETreeModel *tree_model,
|
|
ETreePath path,
|
|
gint col)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->sort_value_at != NULL, NULL);
|
|
|
|
return interface->sort_value_at (tree_model, path, col);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_value_at:
|
|
* @tree_model: The ETreeModel.
|
|
* @path: The ETreePath to the node we're getting the data from.
|
|
* @col: the column to retrieve data from
|
|
*
|
|
* Return value: This function returns the value that is stored by the
|
|
* @tree_model in column @col and node @path. The data returned can be a
|
|
* pointer or any data value that can be stored inside a pointer.
|
|
*
|
|
* The data returned is typically used by an ECell renderer.
|
|
*
|
|
* The data returned must be valid until the model sends a signal that
|
|
* affect that piece of data. node_changed and node_deleted affect
|
|
* all data in tha t node and all nodes under that node.
|
|
* node_data_changed affects the data in that node. node_col_changed
|
|
* affects the data in that node for that column. node_inserted,
|
|
* node_removed, and no_change don't affect any data in this way.
|
|
**/
|
|
gpointer
|
|
e_tree_model_value_at (ETreeModel *tree_model,
|
|
ETreePath path,
|
|
gint col)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->value_at != NULL, NULL);
|
|
|
|
return interface->value_at (tree_model, path, col);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_duplicate_value:
|
|
* @tree_model:
|
|
* @col:
|
|
* @value:
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gpointer
|
|
e_tree_model_duplicate_value (ETreeModel *tree_model,
|
|
gint col,
|
|
gconstpointer value)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->duplicate_value != NULL, NULL);
|
|
|
|
return interface->duplicate_value (tree_model, col, value);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_free_value:
|
|
* @tree_model:
|
|
* @col:
|
|
* @value:
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
void
|
|
e_tree_model_free_value (ETreeModel *tree_model,
|
|
gint col,
|
|
gpointer value)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_if_fail (interface->free_value != NULL);
|
|
|
|
interface->free_value (tree_model, col, value);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_initialize_value:
|
|
* @tree_model:
|
|
* @col:
|
|
*
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gpointer
|
|
e_tree_model_initialize_value (ETreeModel *tree_model,
|
|
gint col)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->initialize_value != NULL, NULL);
|
|
|
|
return interface->initialize_value (tree_model, col);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_value_is_empty:
|
|
* @tree_model:
|
|
* @col:
|
|
* @value:
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gboolean
|
|
e_tree_model_value_is_empty (ETreeModel *tree_model,
|
|
gint col,
|
|
gconstpointer value)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), TRUE);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->value_is_empty != NULL, TRUE);
|
|
|
|
return interface->value_is_empty (tree_model, col, value);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_value_to_string:
|
|
* @tree_model:
|
|
* @col:
|
|
* @value:
|
|
*
|
|
*
|
|
* Return value:
|
|
**/
|
|
gchar *
|
|
e_tree_model_value_to_string (ETreeModel *tree_model,
|
|
gint col,
|
|
gconstpointer value)
|
|
{
|
|
ETreeModelInterface *interface;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
interface = E_TREE_MODEL_GET_INTERFACE (tree_model);
|
|
g_return_val_if_fail (interface->value_to_string != NULL, NULL);
|
|
|
|
return interface->value_to_string (tree_model, col, value);
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_traverse:
|
|
* @tree_model:
|
|
* @path:
|
|
* @func:
|
|
* @data:
|
|
*
|
|
*
|
|
**/
|
|
void
|
|
e_tree_model_node_traverse (ETreeModel *tree_model,
|
|
ETreePath path,
|
|
ETreePathFunc func,
|
|
gpointer data)
|
|
{
|
|
ETreePath child;
|
|
|
|
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
|
|
g_return_if_fail (path != NULL);
|
|
|
|
child = e_tree_model_node_get_first_child (tree_model, path);
|
|
|
|
while (child) {
|
|
ETreePath next_child;
|
|
|
|
next_child = e_tree_model_node_get_next (tree_model, child);
|
|
e_tree_model_node_traverse (tree_model, child, func, data);
|
|
if (func (tree_model, child, data))
|
|
return;
|
|
|
|
child = next_child;
|
|
}
|
|
}
|
|
|
|
static ETreePath
|
|
e_tree_model_node_real_traverse (ETreeModel *model,
|
|
ETreePath path,
|
|
ETreePath end_path,
|
|
ETreePathFunc func,
|
|
gpointer data)
|
|
{
|
|
ETreePath child;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (model), NULL);
|
|
g_return_val_if_fail (path != NULL, NULL);
|
|
|
|
child = e_tree_model_node_get_first_child (model, path);
|
|
|
|
while (child) {
|
|
ETreePath result;
|
|
|
|
if (child == end_path || func (model, child, data))
|
|
return child;
|
|
|
|
if ((result = e_tree_model_node_real_traverse (
|
|
model, child, end_path, func, data)))
|
|
return result;
|
|
|
|
child = e_tree_model_node_get_next (model, child);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* e_tree_model_node_find:
|
|
* @tree_model:
|
|
* @path:
|
|
* @end_path:
|
|
* @func:
|
|
* @data:
|
|
*
|
|
*
|
|
**/
|
|
ETreePath
|
|
e_tree_model_node_find (ETreeModel *tree_model,
|
|
ETreePath path,
|
|
ETreePath end_path,
|
|
ETreePathFunc func,
|
|
gpointer data)
|
|
{
|
|
ETreePath result;
|
|
ETreePath next;
|
|
|
|
g_return_val_if_fail (E_IS_TREE_MODEL (tree_model), NULL);
|
|
|
|
/* Just search the whole tree in this case. */
|
|
if (path == NULL) {
|
|
ETreePath root;
|
|
root = e_tree_model_get_root (tree_model);
|
|
|
|
if (end_path == root || func (tree_model, root, data))
|
|
return root;
|
|
|
|
result = e_tree_model_node_real_traverse (
|
|
tree_model, root, end_path, func, data);
|
|
if (result)
|
|
return result;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
while (1) {
|
|
|
|
if ((result = e_tree_model_node_real_traverse (
|
|
tree_model, path, end_path, func, data)))
|
|
return result;
|
|
next = e_tree_model_node_get_next (tree_model, path);
|
|
|
|
while (next == NULL) {
|
|
path = e_tree_model_node_get_parent (tree_model, path);
|
|
|
|
if (path == NULL)
|
|
return NULL;
|
|
|
|
next = e_tree_model_node_get_next (tree_model, path);
|
|
}
|
|
|
|
if (end_path == next || func (tree_model, next, data))
|
|
return next;
|
|
|
|
path = next;
|
|
}
|
|
}
|
|
|