aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table/e-tree-model.c
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/table/e-tree-model.c')
-rw-r--r--widgets/table/e-tree-model.c1755
1 files changed, 343 insertions, 1412 deletions
diff --git a/widgets/table/e-tree-model.c b/widgets/table/e-tree-model.c
index 0658cef7db..389e37223a 100644
--- a/widgets/table/e-tree-model.c
+++ b/widgets/table/e-tree-model.c
@@ -4,10 +4,11 @@
*
* Author:
* Chris Toshok (toshok@ximian.com)
+ * Chris Lahey <clahey@ximian.com>
*
* Adapted from the gtree code and ETableModel.
*
- * (C) 2000 Ximian, Inc.
+ * (C) 2000, 2001 Ximian, Inc.
*/
#include <config.h>
@@ -27,566 +28,37 @@
#define ETM_CLASS(e) ((ETreeModelClass *)((GtkObject *)e)->klass)
-#define PARENT_TYPE E_TABLE_MODEL_TYPE
+#define PARENT_TYPE (gtk_object_get_type())
-#define TREEPATH_CHUNK_AREA_SIZE (30 * sizeof (ETreePath))
-
-static ETableModel *e_tree_model_parent_class;
-
-struct ETreeModelPriv {
- GMemChunk *node_chunk;
- ETreePath *root;
- gboolean root_visible;
- GArray *row_array; /* used in the mapping between ETable and our tree */
- GHashTable *expanded_state; /* used for loading/saving expanded state */
- GString *sort_group; /* for caching the last sort group info */
- gboolean expanded_default; /* whether nodes are created expanded or collapsed by default */
- gint frozen;
-};
-
-struct ETreePath {
- gboolean expanded;
- gboolean expanded_set;
- guint visible_descendents;
- char *save_id;
- ETreePathCompareFunc compare;
- gpointer node_data;
-
- /* parent/child/sibling pointers */
- ETreePath *parent;
- ETreePath *next_sibling;
- ETreePath *prev_sibling;
- ETreePath *first_child;
- ETreePath *last_child;
- guint32 num_children;
-};
+static GtkObjectClass *parent_class;
enum {
+ PRE_CHANGE,
NODE_CHANGED,
+ NODE_DATA_CHANGED,
+ NODE_COL_CHANGED,
NODE_INSERTED,
NODE_REMOVED,
- NODE_COLLAPSED,
- NODE_EXPANDED,
LAST_SIGNAL
};
static guint e_tree_model_signals [LAST_SIGNAL] = {0, };
-static void add_visible_descendents_to_array (ETreeModel *etm, ETreePath *node, int *row, int *count);
-
-
-/* ETreePath functions */
-
-static int
-e_tree_path_depth (ETreePath *path)
-{
- int depth = 0;
- while (path) {
- depth ++;
- path = path->parent;
- }
- return depth;
-}
-
-static void
-e_tree_path_insert (ETreePath *parent, int position, ETreePath *child)
-{
- g_return_if_fail (position <= parent->num_children || position == -1);
-
- child->parent = parent;
-
- if (parent->first_child == NULL)
- parent->first_child = child;
-
- if (position == -1 || position == parent->num_children) {
- child->prev_sibling = parent->last_child;
- if (parent->last_child)
- parent->last_child->next_sibling = child;
- parent->last_child = child;
- }
- else {
- ETreePath *c;
- for (c = parent->first_child; c; c = c->next_sibling) {
- if (position == 0) {
- child->next_sibling = c;
- child->prev_sibling = c->prev_sibling;
-
- if (child->next_sibling)
- child->next_sibling->prev_sibling = child;
- if (child->prev_sibling)
- child->prev_sibling->next_sibling = child;
-
- if (parent->first_child == c)
- parent->first_child = child;
- break;
- }
- position --;
- }
- }
-
- parent->num_children++;
-}
-
-static void
-e_tree_path_unlink (ETreePath *path)
-{
- ETreePath *parent = path->parent;
-
- /* unlink first/last child if applicable */
- if (parent) {
- if (path == parent->first_child)
- parent->first_child = path->next_sibling;
- if (path == parent->last_child)
- parent->last_child = path->prev_sibling;
-
- parent->num_children --;
- }
-
- /* unlink prev/next sibling links */
- if (path->next_sibling)
- path->next_sibling->prev_sibling = path->prev_sibling;
- if (path->prev_sibling)
- path->prev_sibling->next_sibling = path->next_sibling;
-
- path->parent = NULL;
- path->next_sibling = NULL;
- path->prev_sibling = NULL;
-}
-
-/**
- * e_tree_model_node_traverse:
- * @model:
- * @path:
- * @func:
- * @data:
- *
- *
- **/
-void
-e_tree_model_node_traverse (ETreeModel *model, ETreePath *path, ETreePathFunc func, gpointer data)
-{
- ETreePath *child;
-
- g_return_if_fail (path);
-
- child = path->first_child;
-
- while (child) {
- ETreePath *next_child = child->next_sibling;
- e_tree_model_node_traverse (model, child, func, data);
- if (func (model, child, data) == TRUE)
- return;
-
- child = next_child;
- }
-}
-
-
-
-/**
- * e_tree_model_freeze:
- * @etm: the ETreeModel to freeze.
- *
- * This function prepares an ETreeModel for a period of much change.
- * All signals regarding changes to the tree are deferred until we
- * thaw the tree.
- *
- **/
-void
-e_tree_model_freeze(ETreeModel *etm)
-{
- ETreeModelPriv *priv = etm->priv;
-
- priv->frozen ++;
-}
-
-/**
- * e_tree_model_thaw:
- * @etm: the ETreeModel to thaw.
- *
- * This function thaws an ETreeModel. All the defered signals can add
- * up to a lot, we don't know - so we just emit a model_changed
- * signal.
- *
- **/
-void
-e_tree_model_thaw(ETreeModel *etm)
-{
- ETreeModelPriv *priv = etm->priv;
-
- if (priv->frozen > 0)
- priv->frozen --;
- if (priv->frozen == 0) {
- e_table_model_changed(E_TABLE_MODEL(etm));
- }
-}
-
-
-/* virtual methods */
-
-static void
-etree_destroy (GtkObject *object)
-{
- ETreeModel *etree = E_TREE_MODEL (object);
- ETreeModelPriv *priv = etree->priv;
-
- /* XXX lots of stuff to free here */
-
- if (priv->root)
- e_tree_model_node_remove (etree, priv->root);
-
- g_array_free (priv->row_array, TRUE);
- g_hash_table_destroy (priv->expanded_state);
-
- g_string_free(priv->sort_group, TRUE);
-
- g_free (priv);
-
- GTK_OBJECT_CLASS (e_tree_model_parent_class)->destroy (object);
-}
-
-static ETreePath*
-etree_get_root (ETreeModel *etm)
-{
- ETreeModelPriv *priv = etm->priv;
- return priv->root;
-}
-
-static ETreePath*
-etree_get_parent (ETreeModel *etm, ETreePath *path)
-{
- g_return_val_if_fail (path, NULL);
-
- return path->parent;
-}
-
-static ETreePath*
-etree_get_next (ETreeModel *etm, ETreePath *node)
-{
- g_return_val_if_fail (node, NULL);
-
- return node->next_sibling;
-}
-
-static ETreePath*
-etree_get_prev (ETreeModel *etm, ETreePath *node)
-{
- g_return_val_if_fail (node, NULL);
-
- return node->prev_sibling;
-}
-
-static ETreePath*
-etree_get_first_child (ETreeModel *etm, ETreePath *node)
-{
- g_return_val_if_fail (node, NULL);
-
- return node->first_child;
-}
-
-static ETreePath*
-etree_get_last_child (ETreeModel *etm, ETreePath *node)
-{
- g_return_val_if_fail (node, NULL);
-
- return node->last_child;
-}
-
-static guint
-etree_get_children (ETreeModel *etm, ETreePath* node, ETreePath ***paths)
-{
- guint n_children;
-
- g_return_val_if_fail (node, 0);
-
- n_children = node->num_children;
-
- if (paths) {
- ETreePath *p;
- int i = 0;
- (*paths) = g_malloc (sizeof (ETreePath*) * n_children);
- for (p = node->first_child; p; p = p->next_sibling) {
- (*paths)[i++] = p;
- }
- }
-
- return n_children;
-}
-
-static gboolean
-etree_is_expanded (ETreeModel *etm, ETreePath* node)
-{
- g_return_val_if_fail (node, FALSE);
-
- return node->expanded;
-}
-
-static gboolean
-etree_is_visible (ETreeModel *etm, ETreePath* node)
-{
- g_return_val_if_fail (node, FALSE);
-
- for (node = node->parent; node; node = node->parent) {
- if (!node->expanded)
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-etree_set_expanded (ETreeModel *etm, ETreePath* node, gboolean expanded)
-{
- ETreeModelPriv *priv = etm->priv;
- ETreePath *child;
- int row;
-
- g_return_if_fail (node);
-
- node->expanded_set = TRUE;
-
- if (node->expanded == expanded)
- return;
-
- if (expanded) {
- gboolean allow_expand = TRUE;
- e_tree_model_node_expanded (etm, node, &allow_expand);
- if (!allow_expand)
- return;
- }
-
- node->expanded = expanded;
- if (node->save_id) {
- g_hash_table_insert (priv->expanded_state, node->save_id, (gpointer)expanded);
- }
-
- /* if the node wasn't visible at present */
- if ((row = e_tree_model_row_of_node (etm, node)) == -1) {
- if (!expanded) {
- e_tree_model_node_collapsed (etm, node);
- }
- return;
- }
-
- row++;
-
- if (expanded) {
- ETreePath *parent;
-
- if (e_tree_model_node_is_visible (etm, node)) {
- node->visible_descendents = 0;
- for (child = node->first_child; child;
- child = child->next_sibling) {
- add_visible_descendents_to_array (etm, child, &row, &node->visible_descendents);
- }
- }
- /* now iterate back up the tree, adding to our
- ancestors' visible descendents */
-
- for (parent = node->parent; parent; parent = parent->parent) {
- parent->visible_descendents += node->visible_descendents;
- }
- }
- else {
- int i;
- ETreePath *parent;
-
- if (e_tree_model_node_is_visible (etm, node)) {
- for (i = 0; i < node->visible_descendents; i ++) {
- priv->row_array = g_array_remove_index (priv->row_array, row);
- e_table_model_row_deleted (E_TABLE_MODEL (etm), row);
- }
- }
- /* now iterate back up the tree, subtracting from our
- ancestors' visible descendents */
-
- for (parent = node->parent; parent; parent = parent->parent) {
- parent->visible_descendents -= node->visible_descendents;
- }
-
- node->visible_descendents = 0;
-
- e_tree_model_node_collapsed (etm, node);
- }
-}
-
-/**
- * e_tree_model_set_expanded_default:
- * @etree: The ETreeModel we're setting the default expanded behavior on.
- * @expanded: Whether or not newly inserted parent nodes should be expanded by default.
- *
- *
- **/
-void
-e_tree_model_show_node (ETreeModel *etm, ETreePath* node)
-{
- ETreePath *parent;
-
- parent = e_tree_model_node_get_parent(etm, node);
- if (parent) {
- e_tree_model_show_node(etm, parent);
- e_tree_model_node_set_expanded(etm, parent, TRUE);
- }
-}
-
-void
-e_tree_model_set_expanded_default (ETreeModel *etree,
- gboolean expanded)
-{
- ETreeModelPriv *priv = etree->priv;
-
- priv->expanded_default = expanded;
-}
-
-/* fairly naive implementation */
-static void
-etree_set_expanded_recurse (ETreeModel *etm, ETreePath* node, gboolean expanded)
-{
- ETreePath *child;
-
- e_tree_model_node_set_expanded (etm, node, expanded);
-
- for (child = node->first_child; child; child = child->next_sibling)
- e_tree_model_node_set_expanded_recurse (etm, child, expanded);
-}
-
-static ETreePath *
-etree_node_at_row (ETreeModel *etree, int row)
-{
- ETreeModelPriv *priv = etree->priv;
-
- g_return_val_if_fail (row < priv->row_array->len, NULL);
-
- return g_array_index (priv->row_array, ETreePath*, row);
-}
-
-
-/* ETable analogs */
-static void*
-etree_value_at (ETreeModel *etm, ETreePath* node, int col)
-{
- /* shouldn't be called */
- g_assert (0);
- return NULL;
-}
-
-static GdkPixbuf*
-etree_icon_at (ETreeModel *etm, ETreePath* node)
-{
- /* shouldn't be called */
- g_assert (0);
- return NULL;
-}
-
-static void
-etree_set_value_at (ETreeModel *etm, ETreePath* node, int col, const void *val)
-{
- /* shouldn't be called */
- g_assert (0);
-}
-
-static gboolean
-etree_is_editable (ETreeModel *etm, ETreePath* node, int col)
-{
- /* shouldn't be called */
- g_assert(0);
- return FALSE;
-}
-
-
-/* ETable virtual functions we map */
-static int
-etable_row_count (ETableModel *etm)
-{
- ETreeModel *tree = E_TREE_MODEL (etm);
- ETreeModelPriv *priv = tree->priv;
- return priv->row_array->len;
-}
-
-static void *
-etable_value_at (ETableModel *etm, int col, int row)
-{
- ETreeModel *etree = E_TREE_MODEL(etm);
- ETreeModelClass *et_class = ETM_CLASS(etm);
- ETreePath* node = e_tree_model_node_at_row (etree, row);
-
- if (node == NULL)
- g_warning ("node is NULL for row %d in etable_value_at\n", row);
-
- if (col == -1)
- return node;
- else if (col == -2)
- return etm;
- else
- return et_class->value_at (etree, node, col);
-}
-
-static void
-etable_set_value_at (ETableModel *etm, int col, int row, const void *val)
-{
- ETreeModel *etree = E_TREE_MODEL(etm);
- ETreeModelClass *et_class = ETM_CLASS(etm);
- ETreePath* node = e_tree_model_node_at_row (etree, row);
-
- g_return_if_fail (node);
-
- et_class->set_value_at (etree, node, col, val);
-}
-
-static gboolean
-etable_is_cell_editable (ETableModel *etm, int col, int row)
-{
- ETreeModel *etree = E_TREE_MODEL(etm);
- ETreeModelClass *et_class = ETM_CLASS(etm);
- ETreePath* node = e_tree_model_node_at_row (etree, row);
-
- g_return_val_if_fail (node, FALSE);
-
- return et_class->is_editable (etree, node, col);
-}
-
-static void
-build_sort_group(GString *out, ETreePath *node)
-{
- if (node->parent) {
- build_sort_group(out, node->parent);
- }
- g_string_sprintfa(out, "/%p", node);
-}
-
-static const char *
-etable_row_sort_group(ETableModel *etm, int row)
-{
- ETreeModel *etree = E_TREE_MODEL(etm);
- ETreeModelPriv *priv = etree->priv;
- ETreePath* node = e_tree_model_node_at_row (etree, row);
-
- g_return_val_if_fail (node, "");
-
- g_string_truncate(priv->sort_group, 0);
- if (node)
- build_sort_group(priv->sort_group, node);
-
- return priv->sort_group->str;
-}
-
-static gboolean
-etable_has_sort_group(ETableModel *etm)
-{
- /* could optimise for the flat &/or unexpanded tree case */
- return TRUE;
-}
-
static void
e_tree_model_class_init (GtkObjectClass *klass)
{
- ETableModelClass *table_class = (ETableModelClass *) klass;
ETreeModelClass *tree_class = (ETreeModelClass *) klass;
- e_tree_model_parent_class = gtk_type_class (PARENT_TYPE);
-
- klass->destroy = etree_destroy;
+ parent_class = gtk_type_class (PARENT_TYPE);
+
+ e_tree_model_signals [PRE_CHANGE] =
+ gtk_signal_new ("pre_change",
+ GTK_RUN_LAST,
+ klass->type,
+ GTK_SIGNAL_OFFSET (ETreeModelClass, pre_change),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
e_tree_model_signals [NODE_CHANGED] =
gtk_signal_new ("node_changed",
@@ -596,6 +68,22 @@ e_tree_model_class_init (GtkObjectClass *klass)
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+ e_tree_model_signals [NODE_DATA_CHANGED] =
+ gtk_signal_new ("node_data_changed",
+ GTK_RUN_LAST,
+ klass->type,
+ GTK_SIGNAL_OFFSET (ETreeModelClass, node_data_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+
+ e_tree_model_signals [NODE_COL_CHANGED] =
+ gtk_signal_new ("node_col_changed",
+ GTK_RUN_LAST,
+ klass->type,
+ GTK_SIGNAL_OFFSET (ETreeModelClass, node_col_changed),
+ gtk_marshal_NONE__POINTER_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
+
e_tree_model_signals [NODE_INSERTED] =
gtk_signal_new ("node_inserted",
GTK_RUN_LAST,
@@ -612,66 +100,50 @@ e_tree_model_class_init (GtkObjectClass *klass)
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER);
- e_tree_model_signals [NODE_COLLAPSED] =
- gtk_signal_new ("node_collapsed",
- GTK_RUN_LAST,
- klass->type,
- GTK_SIGNAL_OFFSET (ETreeModelClass, node_collapsed),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+ gtk_object_class_add_signals (klass, e_tree_model_signals, LAST_SIGNAL);
- e_tree_model_signals [NODE_EXPANDED] =
- gtk_signal_new ("node_expanded",
- GTK_RUN_LAST,
- klass->type,
- GTK_SIGNAL_OFFSET (ETreeModelClass, node_expanded),
- gtk_marshal_NONE__POINTER_POINTER,
- GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER);
+ tree_class->get_root = NULL;
- gtk_object_class_add_signals (klass, e_tree_model_signals, LAST_SIGNAL);
+ tree_class->get_parent = NULL;
+ tree_class->get_first_child = NULL;
+ tree_class->get_last_child = NULL;
+ tree_class->get_next = NULL;
+ tree_class->get_prev = NULL;
+
+ tree_class->is_root = NULL;
+ tree_class->is_expandable = NULL;
+ tree_class->get_children = NULL;
+ tree_class->depth = NULL;
+
+ tree_class->icon_at = NULL;
+
+ tree_class->get_expanded_default = NULL;
+ tree_class->column_count = NULL;
- table_class->row_count = etable_row_count;
- table_class->value_at = etable_value_at;
- table_class->set_value_at = etable_set_value_at;
- table_class->is_cell_editable = etable_is_cell_editable;
-#if 0
- /* XX need to pass these through */
- table_class->duplicate_value = etable_duplicate_value;
- table_class->free_value = etable_free_value;
- table_class->initialize_value = etable_initialize_value;
- table_class->value_is_empty = etable_value_is_empty;
- table_class->value_to_string = etable_value_to_string;
- table_class->thaw = etable_thaw;
-#endif
-
- table_class->row_sort_group = etable_row_sort_group;
- table_class->has_sort_group = etable_has_sort_group;
-
- tree_class->get_root = etree_get_root;
- tree_class->get_prev = etree_get_prev;
- tree_class->get_next = etree_get_next;
- tree_class->get_first_child = etree_get_first_child;
- tree_class->get_last_child = etree_get_last_child;
- tree_class->get_parent = etree_get_parent;
-
- tree_class->value_at = etree_value_at;
- tree_class->icon_at = etree_icon_at;
- tree_class->set_value_at = etree_set_value_at;
- tree_class->is_editable = etree_is_editable;
-
- tree_class->get_children = etree_get_children;
- tree_class->is_expanded = etree_is_expanded;
- tree_class->is_visible = etree_is_visible;
- tree_class->set_expanded = etree_set_expanded;
- tree_class->set_expanded_recurse = etree_set_expanded_recurse;
- tree_class->node_at_row = etree_node_at_row;
+ tree_class->has_save_id = NULL;
+ tree_class->get_save_id = NULL;
+
+ tree_class->value_at = NULL;
+ tree_class->set_value_at = NULL;
+ tree_class->is_editable = NULL;
+
+ tree_class->duplicate_value = NULL;
+ tree_class->free_value = NULL;
+ tree_class->initialize_value = NULL;
+ tree_class->value_is_empty = NULL;
+ tree_class->value_to_string = NULL;
+
+ tree_class->pre_change = NULL;
+ tree_class->node_changed = NULL;
+ tree_class->node_data_changed = NULL;
+ tree_class->node_col_changed = NULL;
+ tree_class->node_inserted = NULL;
+ tree_class->node_removed = NULL;
}
static void
e_tree_init (GtkObject *object)
{
- ETreeModel *etree = (ETreeModel *)object;
- e_tree_model_construct (etree);
}
E_MAKE_TYPE(e_tree_model, "ETreeModel", ETreeModel, e_tree_model_class_init, e_tree_init, PARENT_TYPE)
@@ -689,136 +161,114 @@ E_MAKE_TYPE(e_tree_model, "ETreeModel", ETreeModel, e_tree_model_class_init, e_t
* Return value:
**/
void
-e_tree_model_node_changed (ETreeModel *tree_model, ETreePath *node)
+e_tree_model_pre_change (ETreeModel *tree_model)
{
- int row;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
- row = e_tree_model_row_of_node (tree_model, node);
- if (row != -1)
- e_table_model_row_changed (E_TABLE_MODEL (tree_model), row);
-
gtk_signal_emit (GTK_OBJECT (tree_model),
- e_tree_model_signals [NODE_CHANGED], node);
+ e_tree_model_signals [PRE_CHANGE]);
}
/**
- * e_tree_model_node_inserted:
+ * e_tree_model_node_changed:
* @tree_model:
- * @parent_node:
- * @inserted_node:
+ * @node:
*
*
+ *
+ * Return value:
**/
void
-e_tree_model_node_inserted (ETreeModel *tree_model,
- ETreePath *parent_node,
- ETreePath *inserted_node)
+e_tree_model_node_changed (ETreeModel *tree_model, ETreePath node)
{
- int row;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
-
- row = e_tree_model_row_of_node (tree_model, inserted_node);
- if (row != -1)
- e_table_model_row_inserted (E_TABLE_MODEL (tree_model), row);
gtk_signal_emit (GTK_OBJECT (tree_model),
- e_tree_model_signals [NODE_INSERTED],
- parent_node, inserted_node);
+ e_tree_model_signals [NODE_CHANGED], node);
}
/**
- * e_tree_model_node_removed:
+ * e_tree_model_node_data_changed:
* @tree_model:
- * @parent_node:
- * @removed_node:
+ * @node:
+ *
*
*
+ * Return value:
**/
void
-e_tree_model_node_removed (ETreeModel *tree_model, ETreePath *parent_node, ETreePath *removed_node)
+e_tree_model_node_data_changed (ETreeModel *tree_model, ETreePath node)
{
- int row;
-
g_return_if_fail (tree_model != NULL);
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
-
- row = e_tree_model_row_of_node (tree_model, removed_node);
- if (row != -1)
- e_table_model_row_deleted (E_TABLE_MODEL (tree_model), row);
gtk_signal_emit (GTK_OBJECT (tree_model),
- e_tree_model_signals [NODE_REMOVED],
- parent_node, removed_node);
+ e_tree_model_signals [NODE_DATA_CHANGED], node);
}
/**
- * e_tree_model_node_collapsed:
+ * e_tree_model_node_col_changed:
* @tree_model:
* @node:
*
*
+ *
+ * Return value:
**/
void
-e_tree_model_node_collapsed (ETreeModel *tree_model, ETreePath *node)
+e_tree_model_node_col_changed (ETreeModel *tree_model, ETreePath node, int col)
{
g_return_if_fail (tree_model != NULL);
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
gtk_signal_emit (GTK_OBJECT (tree_model),
- e_tree_model_signals [NODE_COLLAPSED],
- node);
+ e_tree_model_signals [NODE_COL_CHANGED], node, col);
}
/**
- * e_tree_model_node_expanded:
+ * e_tree_model_node_inserted:
* @tree_model:
- * @node:
- * @allow_expand:
+ * @parent_node:
+ * @inserted_node:
*
*
**/
void
-e_tree_model_node_expanded (ETreeModel *tree_model, ETreePath *node, gboolean *allow_expand)
+e_tree_model_node_inserted (ETreeModel *tree_model,
+ ETreePath parent_node,
+ ETreePath inserted_node)
{
g_return_if_fail (tree_model != NULL);
g_return_if_fail (E_IS_TREE_MODEL (tree_model));
-
+
gtk_signal_emit (GTK_OBJECT (tree_model),
- e_tree_model_signals [NODE_EXPANDED],
- node, allow_expand);
+ e_tree_model_signals [NODE_INSERTED],
+ parent_node, inserted_node);
}
-
-
/**
- * e_tree_model_construct:
- * @etree:
+ * e_tree_model_node_removed:
+ * @tree_model:
+ * @parent_node:
+ * @removed_node:
*
*
**/
void
-e_tree_model_construct (ETreeModel *etree)
+e_tree_model_node_removed (ETreeModel *tree_model, ETreePath parent_node, ETreePath removed_node)
{
- ETreeModelPriv *priv;
-
- g_return_if_fail (etree != NULL);
- g_return_if_fail (E_IS_TREE_MODEL (etree));
-
- priv = g_new0 (ETreeModelPriv, 1);
- etree->priv = priv;
-
- priv->node_chunk = g_mem_chunk_create (ETreePath, TREEPATH_CHUNK_AREA_SIZE, G_ALLOC_AND_FREE);
- priv->root = NULL;
- priv->root_visible = TRUE;
- priv->row_array = g_array_new (FALSE, FALSE, sizeof(ETreePath*));
- priv->expanded_state = g_hash_table_new (g_str_hash, g_str_equal);
- priv->sort_group = g_string_new("");
- priv->frozen = 0;
+ g_return_if_fail (tree_model != NULL);
+ g_return_if_fail (E_IS_TREE_MODEL (tree_model));
+
+ gtk_signal_emit (GTK_OBJECT (tree_model),
+ e_tree_model_signals [NODE_REMOVED],
+ parent_node, removed_node);
}
+
+
/**
* e_tree_model_new
*
@@ -844,124 +294,35 @@ e_tree_model_new ()
*
* return values: the ETreePath corresponding to the root node.
*/
-ETreePath *
+ETreePath
e_tree_model_get_root (ETreeModel *etree)
{
g_return_val_if_fail (etree != NULL, NULL);
g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- return ETM_CLASS(etree)->get_root(etree);
-}
-
-/**
- * e_tree_model_node_at_row
- * @etree: the ETreeModel.
- * @row:
- *
- * XXX docs here.
- *
- * return values: the ETreePath corresponding to @row.
- */
-ETreePath *
-e_tree_model_node_at_row (ETreeModel *etree, int row)
-{
- g_return_val_if_fail (etree != NULL, NULL);
- g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
-
- return ETM_CLASS(etree)->node_at_row (etree, row);
-}
-
-/**
- * e_tree_model_icon_of_node
- * @etree: The ETreeModel.
- * @path: The ETreePath to the node we're getting the icon of.
- *
- * XXX docs here.
- *
- * return values: the GdkPixbuf associated with this node.
- */
-GdkPixbuf *
-e_tree_model_icon_of_node (ETreeModel *etree, ETreePath *path)
-{
- g_return_val_if_fail (etree != NULL, NULL);
- g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
-
- return ETM_CLASS(etree)->icon_at (etree, path);
-}
-
-/**
- * e_tree_model_row_of_node
- * @etree: The ETreeModel.
- * @node: The node whose row we're looking up.
- *
- * return values: an int.
- */
-int
-e_tree_model_row_of_node (ETreeModel *etree, ETreePath *node)
-{
- ETreeModelPriv *priv;
- int i;
-
- g_return_val_if_fail (etree != NULL, 0);
- g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
-
- priv = etree->priv;
- for (i = 0; i < priv->row_array->len; i ++)
- if (g_array_index (priv->row_array, ETreePath*, i) == node)
- return i;
-
- return -1;
-}
-
-/**
- * e_tree_model_root_node_set_visible
- *
- * return values: none
- */
-void
-e_tree_model_root_node_set_visible (ETreeModel *etm, gboolean visible)
-{
- ETreeModelPriv *priv;
-
- g_return_if_fail (etm != NULL);
- g_return_if_fail (E_IS_TREE_MODEL (etm));
-
- priv = etm->priv;
- if (visible != priv->root_visible) {
- priv->root_visible = visible;
- if (priv->root) {
- if (visible) {
- priv->row_array = g_array_insert_val (priv->row_array, 0, priv->root);
- }
- else {
- ETreePath *root_path = e_tree_model_get_root (etm);
- e_tree_model_node_set_expanded (etm, root_path, TRUE);
- priv->row_array = g_array_remove_index (priv->row_array, 0);
- }
-
- e_table_model_changed (E_TABLE_MODEL (etm));
- }
- }
+ if (ETM_CLASS(etree)->get_root)
+ return ETM_CLASS(etree)->get_root(etree);
+ else
+ return NULL;
}
/**
- * e_tree_model_root_node_is_visible:
- * @etm:
+ * e_tree_model_node_get_parent:
+ * @etree:
+ * @path:
*
*
*
* Return value:
**/
-gboolean
-e_tree_model_root_node_is_visible (ETreeModel *etm)
+ETreePath
+e_tree_model_node_get_parent (ETreeModel *etree, ETreePath node)
{
- ETreeModelPriv *priv;
-
- g_return_val_if_fail (etm != NULL, FALSE);
- g_return_val_if_fail (E_IS_TREE_MODEL (etm), FALSE);
-
- priv = etm->priv;
- return priv->root_visible;
+ g_return_val_if_fail(etree != NULL, NULL);
+ if (ETM_CLASS(etree)->get_parent)
+ return ETM_CLASS(etree)->get_parent(etree, node);
+ else
+ return NULL;
}
/**
@@ -973,13 +334,16 @@ e_tree_model_root_node_is_visible (ETreeModel *etm)
*
* Return value:
**/
-ETreePath *
-e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath *node)
+ETreePath
+e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail (etree != NULL, NULL);
g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- return ETM_CLASS(etree)->get_first_child(etree, node);
+ if (ETM_CLASS(etree)->get_first_child)
+ return ETM_CLASS(etree)->get_first_child(etree, node);
+ else
+ return NULL;
}
/**
@@ -991,13 +355,16 @@ e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath *node)
*
* Return value:
**/
-ETreePath *
-e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath *node)
+ETreePath
+e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail (etree != NULL, NULL);
g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- return ETM_CLASS(etree)->get_last_child(etree, node);
+ if (ETM_CLASS(etree)->get_last_child)
+ return ETM_CLASS(etree)->get_last_child(etree, node);
+ else
+ return NULL;
}
@@ -1010,13 +377,16 @@ e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath *node)
*
* Return value:
**/
-ETreePath *
-e_tree_model_node_get_next (ETreeModel *etree, ETreePath *node)
+ETreePath
+e_tree_model_node_get_next (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail (etree != NULL, NULL);
g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- return ETM_CLASS(etree)->get_next(etree, node);
+ if (ETM_CLASS(etree)->get_next)
+ return ETM_CLASS(etree)->get_next(etree, node);
+ else
+ return NULL;
}
/**
@@ -1028,47 +398,16 @@ e_tree_model_node_get_next (ETreeModel *etree, ETreePath *node)
*
* Return value:
**/
-ETreePath *
-e_tree_model_node_get_prev (ETreeModel *etree, ETreePath *node)
+ETreePath
+e_tree_model_node_get_prev (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail (etree != NULL, NULL);
g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- return ETM_CLASS(etree)->get_prev(etree, node);
-}
-
-/**
- * e_tree_model_node_depth:
- * @etree:
- * @path:
- *
- *
- *
- * Return value:
- **/
-guint
-e_tree_model_node_depth (ETreeModel *etree, ETreePath *path)
-{
- g_return_val_if_fail (etree != NULL, 0);
- g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
-
- return e_tree_path_depth (path) - 1;
-}
-
-/**
- * e_tree_model_node_get_parent:
- * @etree:
- * @path:
- *
- *
- *
- * Return value:
- **/
-ETreePath *
-e_tree_model_node_get_parent (ETreeModel *etree, ETreePath *path)
-{
- g_return_val_if_fail(etree != NULL, NULL);
- return ETM_CLASS(etree)->get_parent(etree, path);
+ if (ETM_CLASS(etree)->get_prev)
+ return ETM_CLASS(etree)->get_prev(etree, node);
+ else
+ return NULL;
}
/**
@@ -1081,10 +420,14 @@ e_tree_model_node_get_parent (ETreeModel *etree, ETreePath *path)
* Return value:
**/
gboolean
-e_tree_model_node_is_root (ETreeModel *etree, ETreePath *path)
+e_tree_model_node_is_root (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail(etree != NULL, FALSE);
- return (e_tree_model_node_depth (etree, path) == 0);
+
+ if (ETM_CLASS(etree)->is_root)
+ return ETM_CLASS(etree)->is_root(etree, node);
+ else
+ return FALSE;
}
/**
@@ -1097,30 +440,28 @@ e_tree_model_node_is_root (ETreeModel *etree, ETreePath *path)
* Return value:
**/
gboolean
-e_tree_model_node_is_expandable (ETreeModel *etree, ETreePath *path)
+e_tree_model_node_is_expandable (ETreeModel *etree, ETreePath node)
{
g_return_val_if_fail(etree != NULL, FALSE);
- return (e_tree_model_node_get_children (etree, path, NULL) > 0);
+
+ if (ETM_CLASS(etree)->is_expandable)
+ return ETM_CLASS(etree)->is_expandable(etree, node);
+ else
+ return FALSE;
}
-/**
- * e_tree_model_node_is_expanded:
- * @etree:
- * @path:
- *
- *
- *
- * Return value:
- **/
-gboolean
-e_tree_model_node_is_expanded (ETreeModel *etree, ETreePath *path)
+guint
+e_tree_model_node_get_children (ETreeModel *etree, ETreePath node, ETreePath **nodes)
{
- g_return_val_if_fail(etree != NULL, FALSE);
- return ETM_CLASS(etree)->is_expanded (etree, path);
+ g_return_val_if_fail(etree != NULL, 0);
+ if (ETM_CLASS(etree)->get_children)
+ return ETM_CLASS(etree)->get_children (etree, node, nodes);
+ else
+ return 0;
}
/**
- * e_tree_model_node_is_visible:
+ * e_tree_model_node_depth:
* @etree:
* @path:
*
@@ -1128,290 +469,182 @@ e_tree_model_node_is_expanded (ETreeModel *etree, ETreePath *path)
*
* Return value:
**/
-gboolean
-e_tree_model_node_is_visible (ETreeModel *etree, ETreePath *path)
+guint
+e_tree_model_node_depth (ETreeModel *etree, ETreePath node)
{
- g_return_val_if_fail(etree != NULL, FALSE);
- return ETM_CLASS(etree)->is_visible (etree, path);
+ g_return_val_if_fail (etree != NULL, 0);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
+
+ if (ETM_CLASS(etree)->depth)
+ return ETM_CLASS(etree)->depth(etree, node);
+ else
+ return 0;
}
/**
- * e_tree_model_node_set_expanded:
- * @etree:
- * @path:
- * @expanded:
- *
- *
- **/
-void
-e_tree_model_node_set_expanded (ETreeModel *etree, ETreePath *path, gboolean expanded)
+ * e_tree_model_icon_at
+ * @etree: The ETreeModel.
+ * @path: The ETreePath to the node we're getting the icon of.
+ *
+ * XXX docs here.
+ *
+ * return values: the GdkPixbuf associated with this node.
+ */
+GdkPixbuf *
+e_tree_model_icon_at (ETreeModel *etree, ETreePath node)
{
- g_return_if_fail(etree != NULL);
- ETM_CLASS(etree)->set_expanded (etree, path, expanded);
+ g_return_val_if_fail (etree != NULL, NULL);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
+
+ if (ETM_CLASS(etree)->icon_at)
+ return ETM_CLASS(etree)->icon_at (etree, node);
+ else
+ return NULL;
}
/**
- * e_tree_model_node_set_expanded_recurse:
- * @etree:
- * @path:
- * @expanded:
- *
- *
- **/
-void
-e_tree_model_node_set_expanded_recurse (ETreeModel *etree, ETreePath *path, gboolean expanded)
+ * e_tree_model_get_expanded_default
+ * @etree: The ETreeModel.
+ *
+ * XXX docs here.
+ *
+ * return values: Whether nodes should be expanded by default.
+ */
+gboolean
+e_tree_model_get_expanded_default (ETreeModel *etree)
{
- g_return_if_fail(etree != NULL);
- ETM_CLASS(etree)->set_expanded_recurse (etree, path, expanded);
-}
+ g_return_val_if_fail (etree != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
-guint
-e_tree_model_node_get_children (ETreeModel *etree, ETreePath *path, ETreePath ***paths)
-{
- g_return_val_if_fail(etree != NULL, 0);
- return ETM_CLASS(etree)->get_children (etree, path, paths);
+ if (ETM_CLASS(etree)->get_expanded_default)
+ return ETM_CLASS(etree)->get_expanded_default (etree);
+ else
+ return FALSE;
}
/**
- * e_tree_model_node_num_visible_descendents:
- * @etm:
- * @node:
- *
- *
- *
- * Return value:
- **/
-guint
-e_tree_model_node_num_visible_descendents (ETreeModel *etm, ETreePath *node)
+ * e_tree_model_column_count
+ * @etree: The ETreeModel.
+ *
+ * XXX docs here.
+ *
+ * return values: The number of columns
+ */
+gint
+e_tree_model_column_count (ETreeModel *etree)
{
- g_return_val_if_fail(node != NULL, 0);
- return node->visible_descendents;
+ g_return_val_if_fail (etree != NULL, 0);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0);
+
+ if (ETM_CLASS(etree)->column_count)
+ return ETM_CLASS(etree)->column_count (etree);
+ else
+ return 0;
}
/**
- * e_tree_model_node_get_data:
- * @etm:
- * @node:
- *
- *
- *
- * Return value:
- **/
-gpointer
-e_tree_model_node_get_data (ETreeModel *etm, ETreePath *node)
+ * e_tree_model_has_save_id
+ * @etree: The ETreeModel.
+ *
+ * XXX docs here.
+ *
+ * return values: Whether this tree has valid save id data.
+ */
+gboolean
+e_tree_model_has_save_id (ETreeModel *etree)
{
- g_return_val_if_fail (node, NULL);
+ g_return_val_if_fail (etree != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE);
- return node->node_data;
+ if (ETM_CLASS(etree)->has_save_id)
+ return ETM_CLASS(etree)->has_save_id (etree);
+ else
+ return FALSE;
}
/**
- * e_tree_model_node_set_data:
- * @etm:
- * @node:
- * @node_data:
- *
- *
- **/
-void
-e_tree_model_node_set_data (ETreeModel *etm, ETreePath *node, gpointer node_data)
+ * e_tree_model_get_save_id
+ * @etree: The ETreeModel.
+ * @node: The ETreePath.
+ *
+ * XXX docs here.
+ *
+ * return values: The save id for this path.
+ */
+gchar *
+e_tree_model_get_save_id (ETreeModel *etree, ETreePath node)
{
- g_return_if_fail (node);
+ g_return_val_if_fail (etree != NULL, NULL);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
- node->node_data = node_data;
+ if (ETM_CLASS(etree)->get_save_id)
+ return ETM_CLASS(etree)->get_save_id (etree, node);
+ else
+ return NULL;
}
/**
- * e_tree_model_node_insert:
- * @tree_model:
- * @parent_path:
- * @position:
- * @node_data:
- *
- *
- *
- * Return value:
- **/
-ETreePath*
-e_tree_model_node_insert (ETreeModel *tree_model,
- ETreePath *parent_path,
- int position,
- gpointer node_data)
+ * e_tree_model_icon_of_node
+ * @etree: The ETreeModel.
+ * @path: The ETreePath to the node we're getting the icon of.
+ *
+ * XXX docs here.
+ *
+ * return values: the GdkPixbuf associated with this node.
+ */
+void *
+e_tree_model_value_at (ETreeModel *etree, ETreePath node, int col)
{
- ETreeModelPriv *priv;
- ETreePath *new_path;
-
- g_return_val_if_fail(tree_model != NULL, NULL);
-
- priv = tree_model->priv;
-
- g_return_val_if_fail (parent_path != NULL || priv->root == NULL, NULL);
-
- priv = tree_model->priv;
-
- new_path = g_chunk_new0 (ETreePath, priv->node_chunk);
-
- new_path->expanded = FALSE;
- new_path->node_data = node_data;
-
- if (parent_path != NULL) {
-
- if (parent_path->first_child == NULL
- && !parent_path->expanded_set) {
- e_tree_model_node_set_expanded (tree_model,
- parent_path,
- priv->expanded_default);
- }
-
- e_tree_path_insert (parent_path, position, new_path);
-
- if (e_tree_model_node_is_visible (tree_model, new_path)) {
- int parent_row, child_offset = 0;
- ETreePath *n;
-
- /* we need to iterate back up to the root, incrementing the number of visible
- descendents */
- for (n = parent_path; n; n = n->parent) {
- n->visible_descendents ++;
- }
-
- /* determine if we are inserting at the end of this parent */
- if (position == -1 || position == parent_path->num_children) {
- position = e_tree_model_node_num_visible_descendents (tree_model, parent_path) - 1;
- } else {
- /* if we're not inserting at the end of the array, position is the child node we're
- inserting at, not the absolute row position - need to count expanded nodes before it too */
- int i = position;
-
- n = e_tree_model_node_get_first_child(tree_model, parent_path);
- while (n != NULL && i > 0) {
- child_offset += n->visible_descendents;
- n = n->next_sibling;
- i--;
- }
- }
-
-
- /* if the parent is the root, no need to search for its position since it aint there */
- if (parent_path->parent == NULL) {
- parent_row = -1;
- } else {
- parent_row = e_tree_model_row_of_node (tree_model, parent_path);
- }
-
- e_table_model_pre_change(E_TABLE_MODEL(tree_model));
-
- priv->row_array = g_array_insert_val (priv->row_array,
- parent_row + position + 1 + child_offset, new_path);
-
- /* only do this if we know a changed signal isn't coming later on */
- if (priv->frozen == 0)
- e_table_model_row_inserted (E_TABLE_MODEL(tree_model), parent_row + position + 1 + child_offset);
- }
-
- if (parent_path->compare)
- e_tree_model_node_sort (tree_model, parent_path);
- }
- else {
- priv->root = new_path;
- if (priv->root_visible) {
- priv->row_array = g_array_insert_val (priv->row_array, 0, priv->root);
- e_table_model_row_inserted (E_TABLE_MODEL (tree_model), 0);
- }
- else {
- /* need to mark the new node as expanded or
- we'll never see it's children */
- new_path->expanded = TRUE;
- new_path->expanded_set = TRUE;
- }
- }
-
- return new_path;
+ g_return_val_if_fail (etree != NULL, NULL);
+ g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL);
+
+ if (ETM_CLASS(etree)->value_at)
+ return ETM_CLASS(etree)->value_at (etree, node, col);
+ else
+ return NULL;
}
/**
- * e_tree_model_node_insert_id:
- * @tree_model:
- * @parent_path:
- * @position:
- * @node_data:
- * @save_id:
- *
- *
- *
- * Return value:
- **/
-ETreePath*
-e_tree_model_node_insert_id (ETreeModel *tree_model,
- ETreePath *parent_path,
- int position,
- gpointer node_data,
- const char *save_id)
+ * e_tree_model_icon_of_node
+ * @etree: The ETreeModel.
+ * @path: The ETreePath to the node we're getting the icon of.
+ *
+ * XXX docs here.
+ *
+ * return values: the GdkPixbuf associated with this node.
+ */
+void
+e_tree_model_set_value_at (ETreeModel *etree, ETreePath node, int col, const void *val)
{
- ETreePath *path;
-
- g_return_val_if_fail(tree_model != NULL, NULL);
-
- path = e_tree_model_node_insert (tree_model, parent_path, position, node_data);
-
- e_tree_model_node_set_save_id (tree_model, path, save_id);
+ g_return_if_fail (etree != NULL);
+ g_return_if_fail (E_IS_TREE_MODEL (etree));
- return path;
+ if (ETM_CLASS(etree)->set_value_at)
+ ETM_CLASS(etree)->set_value_at (etree, node, col, val);
}
/**
- * e_tree_model_node_insert_before:
+ * e_tree_model_node_is_editable:
* @etree:
- * @parent:
- * @sibling:
- * @node_data:
+ * @path:
*
*
*
* Return value:
**/
-ETreePath *
-e_tree_model_node_insert_before (ETreeModel *etree,
- ETreePath *parent,
- ETreePath *sibling,
- gpointer node_data)
+gboolean
+e_tree_model_node_is_editable (ETreeModel *etree, ETreePath node, int col)
{
- ETreePath *child;
- int position = 0;
-
- g_return_val_if_fail(etree != NULL, NULL);
-
- for (child = parent->first_child; child; child = child->next_sibling) {
- if (child == sibling)
- break;
- position ++;
- }
- return e_tree_model_node_insert (etree, parent, position, node_data);
-}
+ g_return_val_if_fail(etree != NULL, FALSE);
-/* just blows away child data, doesn't take into account unlinking/etc */
-static void
-child_free(ETreeModel *etree, ETreePath *node)
-{
- ETreePath *child, *next;
- ETreeModelPriv *priv = etree->priv;
-
- child = node->first_child;
- while (child) {
- next = child->next_sibling;
- child_free(etree, child);
- child = next;
- }
-
- if (node->save_id) {
- g_hash_table_remove(priv->expanded_state, node->save_id);
- g_free(node->save_id);
- }
- g_chunk_free(node, priv->node_chunk);
+ if (ETM_CLASS(etree)->is_editable)
+ return ETM_CLASS(etree)->is_editable(etree, node, col);
+ else
+ return FALSE;
}
/**
- * e_tree_model_node_remove:
+ * e_tree_model_duplicate_value:
* @etree:
* @path:
*
@@ -1419,393 +652,91 @@ child_free(ETreeModel *etree, ETreePath *node)
*
* Return value:
**/
-gpointer
-e_tree_model_node_remove (ETreeModel *etree, ETreePath *path)
+void *
+e_tree_model_duplicate_value (ETreeModel *etree, int col, const void *value)
{
- ETreeModelPriv *priv = etree->priv;
- ETreePath *parent = path->parent;
- gpointer ret = path->node_data;
- int row, visible = 0, base = 0;
- gboolean dochanged;
-
g_return_val_if_fail(etree != NULL, NULL);
- /* work out what range of visible rows to remove */
- if (parent) {
- if (e_tree_model_node_is_visible(etree, path)) {
- base = e_tree_model_row_of_node(etree, path);
- visible = path->visible_descendents + 1;
- }
- } else if (path == priv->root) {
- priv->root = NULL;
- if (priv->root_visible) {
- base = 0;
- visible = path->visible_descendents + 1;
- } else {
- base = 0;
- visible = path->visible_descendents;
- }
- } else {
- g_warning("Trying to remove invalid path %p", path);
+ if (ETM_CLASS(etree)->duplicate_value)
+ return ETM_CLASS(etree)->duplicate_value(etree, col, value);
+ else
return NULL;
- }
-
- /* unlink this node - we only have to unlink the root node being removed,
- since the others are only references from this node */
- e_tree_path_unlink (path);
-
- /*printf("removing %d nodes from position %d\n", visible, base);*/
-
- if (visible > 0) {
- /* fix up the parent visible counts */
- for (; parent; parent = parent->parent) {
- parent->visible_descendents -= visible;
- }
-
- /* if we have a lot of nodes to remove, then we dont row_deleted each one */
- /* could probably be tuned, but this'll do, since its normally only when we
- remove the whole lot do we really care */
- dochanged = (visible > 1000) || (visible > (priv->row_array->len / 4));
-
- e_table_model_pre_change(E_TABLE_MODEL (etree));
-
- /* and physically remove them */
- if (visible == priv->row_array->len) {
- g_array_set_size(priv->row_array, 0);
- } else {
- memmove(&g_array_index(priv->row_array, ETreePath *, base),
- &g_array_index(priv->row_array, ETreePath *, base+visible),
- (priv->row_array->len - (base+visible)) * sizeof(ETreePath *));
- g_array_set_size(priv->row_array, priv->row_array->len - visible);
- }
-
- /* tell the system we've removed (these) nodes */
- if (priv->frozen == 0) {
- if (dochanged) {
- e_table_model_changed(E_TABLE_MODEL(etree));
- } else {
- for (row=visible-1;row>=0;row--) {
- e_table_model_row_deleted(E_TABLE_MODEL(etree), row+base);
- }
- }
- }
- }
-
- child_free(etree, path);
-
- return ret;
-}
-
-static void
-add_visible_descendents_to_array (ETreeModel *etm, ETreePath *node, int *row, int *count)
-{
- ETreeModelPriv *priv = etm->priv;
-
- /* add a row for this node */
- e_table_model_pre_change(E_TABLE_MODEL (etm));
- priv->row_array = g_array_insert_val (priv->row_array, (*row), node);
- if (priv->frozen == 0)
- e_table_model_row_inserted (E_TABLE_MODEL (etm), (*row));
- (*row) ++;
- (*count) ++;
-
- /* then loop over its children, calling this routine for each
- of them */
- if (node->expanded) {
- ETreePath *child;
- for (child = node->first_child; child;
- child = child->next_sibling) {
- add_visible_descendents_to_array (etm, child, row, count);
- }
- }
-}
-
-static void
-save_expanded_state_func (char *key, gboolean expanded, gpointer user_data)
-{
- if (expanded) {
- xmlNode *root = (xmlNode*)user_data;
- xmlNode *node_root = xmlNewNode (NULL, (xmlChar*) "node");
-
- xmlAddChild (root, node_root);
- xmlNewChild (node_root, NULL, (xmlChar *) "id", (xmlChar*) key);
- }
}
/**
- * e_tree_model_save_expanded_state:
- * @etm:
- * @filename:
+ * e_tree_model_free_value:
+ * @etree:
+ * @path:
*
*
*
* Return value:
**/
-gboolean
-e_tree_model_save_expanded_state (ETreeModel *etm, const char *filename)
-{
- xmlDoc *doc;
- xmlNode *root;
- int fd, rv;
- xmlChar *buf;
- int buf_size;
- ETreeModelPriv *priv = etm->priv;
-
- g_return_val_if_fail(etm != NULL, FALSE);
-
- doc = xmlNewDoc ((xmlChar*) "1.0");
- root = xmlNewDocNode (doc, NULL,
- (xmlChar *) "expanded_state",
- NULL);
- xmlDocSetRootElement (doc, root);
-
- g_hash_table_foreach (priv->expanded_state,
- (GHFunc)save_expanded_state_func,
- root);
-
- fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0777);
-
- xmlDocDumpMemory (doc, &buf, &buf_size);
-
- if (buf == NULL) {
- g_error ("Failed to write %s: xmlBufferCreate() == NULL", filename);
- return FALSE;
- }
-
- rv = write (fd, buf, buf_size);
- xmlFree (buf);
- close (fd);
-
- if (0 > rv) {
- g_error ("Failed to write new %s: %d\n", filename, errno);
- unlink (filename);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static char *
-get_string_value (xmlNode *node,
- const char *name)
+void
+e_tree_model_free_value (ETreeModel *etree, int col, void *value)
{
- xmlNode *p;
- xmlChar *xml_string;
- char *retval;
-
- p = e_xml_get_child_by_name (node, (xmlChar *) name);
- if (p == NULL)
- return NULL;
-
- p = e_xml_get_child_by_name (p, (xmlChar *) "text");
- if (p == NULL) /* there's no text between the tags, return the empty string */
- return g_strdup("");
-
- xml_string = xmlNodeListGetString (node->doc, p, 1);
- retval = g_strdup ((char *) xml_string);
- xmlFree (xml_string);
+ g_return_if_fail(etree != NULL);
- return retval;
+ if (ETM_CLASS(etree)->free_value)
+ ETM_CLASS(etree)->free_value(etree, col, value);
}
/**
- * e_tree_model_load_expanded_state:
- * @etm:
- * @filename:
+ * e_tree_model_initialize_value:
+ * @etree:
+ * @path:
*
*
*
* Return value:
**/
-gboolean
-e_tree_model_load_expanded_state (ETreeModel *etm, const char *filename)
+void *
+e_tree_model_initialize_value (ETreeModel *etree, int col)
{
- ETreeModelPriv *priv = etm->priv;
- xmlDoc *doc;
- xmlNode *root;
- xmlNode *child;
-
- g_return_val_if_fail(etm != NULL, FALSE);
-
- doc = xmlParseFile (filename);
- if (!doc)
- return FALSE;
-
- root = xmlDocGetRootElement (doc);
- if (root == NULL || strcmp (root->name, "expanded_state")) {
- xmlFreeDoc (doc);
- return FALSE;
- }
-
- for (child = root->childs; child; child = child->next) {
- char *id;
-
- if (strcmp (child->name, "node")) {
- g_warning ("unknown node '%s' in %s", child->name, filename);
- continue;
- }
-
- id = get_string_value (child, "id");
-
- g_hash_table_insert (priv->expanded_state, id, (gpointer)TRUE);
- }
-
- xmlFreeDoc (doc);
+ g_return_val_if_fail(etree != NULL, NULL);
- return TRUE;
+ if (ETM_CLASS(etree)->initialize_value)
+ return ETM_CLASS(etree)->initialize_value(etree, col);
+ else
+ return NULL;
}
-
/**
- * e_tree_model_node_set_save_id:
- * @etm:
- * @node:
- * @id:
+ * e_tree_model_value_is_empty:
+ * @etree:
+ * @path:
*
*
- **/
-void
-e_tree_model_node_set_save_id (ETreeModel *etm, ETreePath *node, const char *id)
-{
- char *key;
- gboolean expanded_state;
- ETreeModelPriv *priv;
-
- g_return_if_fail(etm != NULL);
- g_return_if_fail (E_TREE_MODEL (etm));
- g_return_if_fail (node);
-
- priv = etm->priv;
-
- if (g_hash_table_lookup_extended (priv->expanded_state,
- id, (gpointer*)&key, (gpointer*)&expanded_state)) {
-
- e_tree_model_node_set_expanded (etm, node,
- expanded_state);
-
- /* important that this comes after the e_tree_model_node_set_expanded */
- node->save_id = key;
- }
- else {
- node->save_id = g_strdup (id);
-
- g_hash_table_insert (priv->expanded_state, node->save_id, (gpointer)node->expanded);
- }
-}
-
-
-
-/**
- * e_tree_model_node_set_compare_function:
- * @tree_model:
- * @node:
- * @compare:
- *
*
+ * Return value:
**/
-void
-e_tree_model_node_set_compare_function (ETreeModel *tree_model,
- ETreePath *node,
- ETreePathCompareFunc compare)
+gboolean
+e_tree_model_value_is_empty (ETreeModel *etree, int col, const void *value)
{
- gboolean need_sort;
-
- g_return_if_fail (tree_model != NULL);
- g_return_if_fail (E_TREE_MODEL (tree_model));
- g_return_if_fail (node);
+ g_return_val_if_fail(etree != NULL, TRUE);
- need_sort = (compare != node->compare);
-
- node->compare = compare;
-
- if (need_sort)
- e_tree_model_node_sort (tree_model, node);
-}
-
-typedef struct {
- ETreeModel *model;
- ETreePath *path;
- ETreePathCompareFunc compare;
- gboolean was_expanded;
-} ETreeSortInfo;
-
-static gint
-e_tree_model_node_compare (ETreeSortInfo *info1, ETreeSortInfo *info2)
-{
- return info1->compare (info1->model, info1->path, info2->path);
+ if (ETM_CLASS(etree)->value_is_empty)
+ return ETM_CLASS(etree)->value_is_empty(etree, col, value);
+ else
+ return TRUE;
}
/**
- * e_tree_model_node_sort:
- * @tree_model:
- * @node:
+ * e_tree_model_value_to_string:
+ * @etree:
+ * @path:
+ *
*
*
+ * Return value:
**/
-void
-e_tree_model_node_sort (ETreeModel *tree_model,
- ETreePath *node)
+char *
+e_tree_model_value_to_string (ETreeModel *etree, int col, const void *value)
{
- int num_nodes = node->num_children;
- ETreeSortInfo *sort_info;
- int i;
- int child_index;
- gboolean node_expanded;
- ETreeModelPriv *priv = tree_model->priv;;
-
- node_expanded = e_tree_model_node_is_expanded (tree_model, node);
-
- g_return_if_fail (tree_model != NULL);
- g_return_if_fail (E_TREE_MODEL (tree_model));
- g_return_if_fail (node);
-
- g_return_if_fail (node->compare);
-
- if (num_nodes == 0)
- return;
+ g_return_val_if_fail(etree != NULL, g_strdup(""));
- e_table_model_pre_change(E_TABLE_MODEL (tree_model));
-
- sort_info = g_new (ETreeSortInfo, num_nodes);
-
- child_index = e_tree_model_row_of_node (tree_model, node) + 1;
-
- /* collect our info and remove the children */
- for (i = 0; i < num_nodes; i ++) {
- sort_info[i].path = node->first_child;
- sort_info[i].was_expanded = e_tree_model_node_is_expanded (tree_model, sort_info[i].path);
- sort_info[i].model = tree_model;
- sort_info[i].compare = node->compare;
-
- e_tree_model_node_set_expanded(tree_model, sort_info[i].path, FALSE);
- if (node_expanded)
- priv->row_array = g_array_remove_index (priv->row_array, child_index);
- e_tree_path_unlink (sort_info[i].path);
- }
-
- /* sort things */
- qsort (sort_info, num_nodes, sizeof(ETreeSortInfo), (GCompareFunc)e_tree_model_node_compare);
-
- /* reinsert the children nodes into the tree in the sorted order */
- for (i = 0; i < num_nodes; i ++) {
- e_tree_path_insert (node, i, sort_info[i].path);
- if (node_expanded)
- priv->row_array = g_array_insert_val (priv->row_array, child_index + i,
- sort_info[i].path);
- }
-
- /* make another pass expanding the children as needed.
-
- XXX this used to be in the loop above, but a recent change
- (either here or in the etable code) causes an assertion and
- a crash */
- for (i = 0; i < num_nodes; i ++) {
- e_tree_model_node_set_expanded (tree_model, sort_info[i].path, sort_info[i].was_expanded);
- }
-
- g_free (sort_info);
-
- if (priv->frozen == 0)
- e_table_model_changed (E_TABLE_MODEL (tree_model));
+ if (ETM_CLASS(etree)->value_to_string)
+ return ETM_CLASS(etree)->value_to_string(etree, col, value);
+ else
+ return g_strdup("");
}
-