diff options
Diffstat (limited to 'widgets/e-table/e-tree-model.c')
-rw-r--r-- | widgets/e-table/e-tree-model.c | 760 |
1 files changed, 0 insertions, 760 deletions
diff --git a/widgets/e-table/e-tree-model.c b/widgets/e-table/e-tree-model.c deleted file mode 100644 index c57bf2d683..0000000000 --- a/widgets/e-table/e-tree-model.c +++ /dev/null @@ -1,760 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-tree-model.c: a Tree Model - * - * Author: - * Chris Toshok (toshok@helixcode.com) - * - * Adapted from the gtree code and ETableModel. - * - * (C) 2000 Helix Code, Inc. - */ -#include <config.h> -#include <gtk/gtksignal.h> -#include <stdlib.h> -#include "e-util/e-util.h" -#include "e-tree-model.h" - -#define ETM_CLASS(e) ((ETreeModelClass *)((GtkObject *)e)->klass) - -#define PARENT_TYPE E_TABLE_MODEL_TYPE - -static ETableModel *e_tree_model_parent_class; - -typedef struct { - gboolean expanded; - guint visible_descendents; - gpointer node_data; -} ENode; - -enum { - NODE_CHANGED, - NODE_INSERTED, - NODE_REMOVED, - LAST_SIGNAL -}; - -static guint e_tree_model_signals [LAST_SIGNAL] = {0, }; - -static void add_visible_descendents_to_array (ETreeModel *etm, GNode *gnode, int *row, int *count); - - -/* virtual methods */ - -static void -etree_destroy (GtkObject *object) -{ - ETreeModel *etree = E_TREE_MODEL (object); - - /* XXX lots of stuff to free here */ - g_array_free (etree->row_array, TRUE); - - GTK_OBJECT_CLASS (e_tree_model_parent_class)->destroy (object); -} - -static ETreePath* -etree_get_root (ETreeModel *etm) -{ - return etm->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 g_node_next_sibling(node); -} - -static ETreePath* -etree_get_prev (ETreeModel *etm, ETreePath *node) -{ - g_return_val_if_fail (node, NULL); - - return g_node_prev_sibling (node); -} - -static guint -etree_get_children (ETreeModel *etm, ETreePath* node, ETreePath ***paths) -{ - guint n_children; - - g_return_val_if_fail (node, 0); - - n_children = g_node_n_children (node); - - if (paths) { - int i; - (*paths) = g_malloc (sizeof (ETreePath*) * n_children); - for (i = 0; i < n_children; i ++) { - (*paths)[i] = g_node_nth_child (node, i); - } - } - - return n_children; -} - -static gboolean -etree_is_expanded (ETreeModel *etm, ETreePath* node) -{ - g_return_val_if_fail (node && node->data, FALSE); - - return ((ENode*)node->data)->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 (!((ENode*)node->data)->expanded) - return FALSE; - } - - return TRUE; -} - -static void -etree_set_expanded (ETreeModel *etm, ETreePath* node, gboolean expanded) -{ - GNode *child; - ENode *enode; - int row; - - g_return_if_fail (node && node->data); - - enode = ((ENode*)node->data); - - if (enode->expanded == expanded) - return; - - enode->expanded = expanded; - - /* if the node wasn't visible at present */ - if ((row = e_tree_model_row_of_node (etm, node)) == -1) - return; - - row++; - - if (expanded) { - GNode *parent; - - if (e_tree_model_node_is_visible (etm, node)) { - enode->visible_descendents = 0; - for (child = g_node_first_child (node); child; - child = g_node_next_sibling (child)) { - add_visible_descendents_to_array (etm, child, &row, &enode->visible_descendents); - } - } - /* now iterate back up the tree, adding to our - ancestors' visible descendents */ - - for (parent = node->parent; parent; parent = parent->parent) { - ENode *parent_enode = (ENode*)parent->data; - parent_enode->visible_descendents += enode->visible_descendents; - } - } - else { - int i; - GNode *parent; - - if (e_tree_model_node_is_visible (etm, node)) { - for (i = 0; i < enode->visible_descendents; i ++) { - etm->row_array = g_array_remove_index (etm->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) { - ENode *parent_enode = (ENode*)parent->data; - - parent_enode->visible_descendents -= enode->visible_descendents; - } - - enode->visible_descendents = 0; - } -} - -/* fairly naive implementation */ -static void -etree_set_expanded_recurse (ETreeModel *etm, ETreePath* node, gboolean expanded) -{ - ETreePath **paths; - guint num_children; - int i; - - e_tree_model_node_set_expanded (etm, node, expanded); - - num_children = e_tree_model_node_get_children (etm, node, &paths); - if (num_children) { - for (i = 0; i < num_children; i ++) { - e_tree_model_node_set_expanded_recurse (etm, paths[i], expanded); - } - - g_free (paths); - } -} - -static ETreePath * -etree_node_at_row (ETreeModel *etree, int row) -{ - g_return_val_if_fail (row < etree->row_array->len, NULL); - - return g_array_index (etree->row_array, GNode*, 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); - return tree->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); - - g_return_val_if_fail (node, NULL); - - 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 -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; - - e_tree_model_signals [NODE_CHANGED] = - gtk_signal_new ("node_changed", - GTK_RUN_LAST, - klass->type, - GTK_SIGNAL_OFFSET (ETreeModelClass, node_changed), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - e_tree_model_signals [NODE_INSERTED] = - gtk_signal_new ("node_inserted", - GTK_RUN_LAST, - klass->type, - GTK_SIGNAL_OFFSET (ETreeModelClass, node_inserted), - gtk_marshal_NONE__POINTER_POINTER, - GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); - - e_tree_model_signals [NODE_REMOVED] = - gtk_signal_new ("node_removed", - GTK_RUN_LAST, - klass->type, - GTK_SIGNAL_OFFSET (ETreeModelClass, node_removed), - gtk_marshal_NONE__POINTER_POINTER, - GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); - - gtk_object_class_add_signals (klass, e_tree_model_signals, LAST_SIGNAL); - - 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 - - tree_class->get_root = etree_get_root; - tree_class->get_prev = etree_get_prev; - tree_class->get_next = etree_get_next; - 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; -} - -E_MAKE_TYPE(e_tree_model, "ETreeModel", ETreeModel, e_tree_model_class_init, NULL, PARENT_TYPE) - - -/* signals */ -void -e_tree_model_node_changed (ETreeModel *tree_model, ETreePath *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_CHANGED]); -} - -void -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_INSERTED], - parent_node, inserted_node); -} - -void -e_tree_model_node_removed (ETreeModel *tree_model, ETreePath *parent_node, ETreePath *removed_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_REMOVED], - parent_node, removed_node); -} - - -void -e_tree_model_construct (ETreeModel *etree) -{ - etree->root = NULL; - etree->root_visible = TRUE; - etree->row_array = g_array_new (FALSE, FALSE, sizeof(GNode*)); -} - -ETreeModel * -e_tree_model_new () -{ - ETreeModel *et; - - et = gtk_type_new (e_tree_model_get_type ()); - - return et; -} - -ETreePath * -e_tree_model_get_root (ETreeModel *etree) -{ - return ETM_CLASS(etree)->get_root(etree); -} - -ETreePath * -e_tree_model_node_at_row (ETreeModel *etree, int row) -{ - return ETM_CLASS(etree)->node_at_row (etree, row); -} - -GdkPixbuf * -e_tree_model_icon_of_node (ETreeModel *etree, ETreePath *path) -{ - return ETM_CLASS(etree)->icon_at (etree, path); -} - -int -e_tree_model_row_of_node (ETreeModel *etree, ETreePath *node) -{ - int i; - - for (i = 0; i < etree->row_array->len; i ++) - if (g_array_index (etree->row_array, GNode*, i) == node) - return i; - - g_warning ("e_tree_model_row_of_node failed for node %p\n", node); - - return -1; -} - -void -e_tree_model_root_node_set_visible (ETreeModel *etm, gboolean visible) -{ - if (visible != etm->root_visible) { - etm->root_visible = visible; - if (etm->root) { - if (visible) { - etm->row_array = g_array_insert_val (etm->row_array, 0, etm->root); - } - else { - ETreePath *root_path = e_tree_model_get_root (etm); - e_tree_model_node_set_expanded (etm, root_path, TRUE); - etm->row_array = g_array_remove_index (etm->row_array, 0); - } - - e_table_model_changed (E_TABLE_MODEL (etm)); - } - } -} - -gboolean -e_tree_model_root_node_is_visible (ETreeModel *etm) -{ - return etm->root_visible; -} - - -ETreePath * -e_tree_model_node_get_next (ETreeModel *etree, ETreePath *node) -{ - return ETM_CLASS(etree)->get_next(etree, node); -} - -ETreePath * -e_tree_model_node_get_prev (ETreeModel *etree, ETreePath *node) -{ - return ETM_CLASS(etree)->get_prev(etree, node); -} - -guint -e_tree_model_node_depth (ETreeModel *etree, ETreePath *path) -{ - return g_node_depth (path) - 1; -} - -ETreePath * -e_tree_model_node_get_parent (ETreeModel *etree, ETreePath *path) -{ - return ETM_CLASS(etree)->get_parent(etree, path); -} - -gboolean -e_tree_model_node_is_root (ETreeModel *etree, ETreePath *path) -{ - return (e_tree_model_node_depth (etree, path) == 0); -} - -gboolean -e_tree_model_node_is_expandable (ETreeModel *etree, ETreePath *path) -{ - return (e_tree_model_node_get_children (etree, path, NULL) > 0); -} - -gboolean -e_tree_model_node_is_expanded (ETreeModel *etree, ETreePath *path) -{ - return ETM_CLASS(etree)->is_expanded (etree, path); -} - -gboolean -e_tree_model_node_is_visible (ETreeModel *etree, ETreePath *path) -{ - return ETM_CLASS(etree)->is_visible (etree, path); -} - -void -e_tree_model_node_set_expanded (ETreeModel *etree, ETreePath *path, gboolean expanded) -{ - ETM_CLASS(etree)->set_expanded (etree, path, expanded); -} - -void -e_tree_model_node_set_expanded_recurse (ETreeModel *etree, ETreePath *path, gboolean expanded) -{ - ETM_CLASS(etree)->set_expanded_recurse (etree, path, expanded); -} - -guint -e_tree_model_node_get_children (ETreeModel *etree, ETreePath *path, ETreePath ***paths) -{ - return ETM_CLASS(etree)->get_children (etree, path, paths); -} - -guint -e_tree_model_node_num_visible_descendents (ETreeModel *etm, ETreePath *node) -{ - ENode *enode = (ENode*)node->data; - - return enode->visible_descendents; -} - -gpointer -e_tree_model_node_get_data (ETreeModel *etm, ETreePath *node) -{ - ENode *enode; - - g_return_val_if_fail (node && node->data, NULL); - - enode = (ENode*)node->data; - - return enode->node_data; -} - -void -e_tree_model_node_set_data (ETreeModel *etm, ETreePath *node, gpointer node_data) -{ - ENode *enode; - - g_return_if_fail (node && node->data); - - enode = (ENode*)node->data; - - enode->node_data = node_data; -} - -ETreePath* -e_tree_model_node_insert (ETreeModel *tree_model, - ETreePath *parent_path, - int position, - gpointer node_data) -{ - ENode *node; - ETreePath *new_path; - - g_return_val_if_fail (parent_path != NULL || tree_model->root == NULL, NULL); - - node = g_new0 (ENode, 1); - - node->expanded = FALSE; - node->node_data = node_data; - - if (parent_path != NULL) { - - new_path = g_node_new (node); - - g_node_insert (parent_path, position, new_path); - - if (e_tree_model_node_is_visible (tree_model, new_path)) { - int parent_row; - GNode *n; - - /* we need to iterate back up to the root, incrementing the number of visible - descendents */ - for (n = parent_path; n; n = n->parent) { - ENode *parent_enode = (ENode*)n->data; - - parent_enode->visible_descendents ++; - } - - /* finally, insert a row into the table */ - if (position == -1) - position = e_tree_model_node_num_visible_descendents (tree_model, parent_path) - 1; - - parent_row = e_tree_model_row_of_node (tree_model, parent_path); - - tree_model->row_array = g_array_insert_val (tree_model->row_array, - parent_row + position + 1, new_path); - - e_table_model_row_inserted (E_TABLE_MODEL(tree_model), parent_row + position + 1); - } - } - else { - tree_model->root = g_node_new (node); - if (tree_model->root_visible) { - tree_model->row_array = g_array_insert_val (tree_model->row_array, 0, tree_model->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 */ - node->expanded = TRUE; - } - new_path = tree_model->root; - } - - return new_path; -} - -ETreePath * -e_tree_model_node_insert_before (ETreeModel *etree, - ETreePath *parent, - ETreePath *sibling, - gpointer node_data) -{ - return e_tree_model_node_insert (etree, parent, - g_node_child_position (parent, sibling), - node_data); -} - -static void -child_remove (GNode *node, gpointer etree) -{ - e_tree_model_node_remove (etree, node); -} - -gpointer -e_tree_model_node_remove (ETreeModel *etree, ETreePath *path) -{ - GNode *parent = path->parent; - ENode *enode = (ENode*)path->data; - gpointer ret = enode->node_data; - - /* remove children */ - g_node_children_foreach (path, G_TRAVERSE_ALL, child_remove, etree); - - /* clean up the display */ - if (parent) { - if (e_tree_model_node_is_visible (etree, path)) { - int row = e_tree_model_row_of_node (etree, path); - e_table_model_row_deleted (E_TABLE_MODEL (etree), row); - etree->row_array = g_array_remove_index (etree->row_array, row); - - /* we need to iterate back up to the root, incrementing the number of visible - descendents */ - for (; parent; parent = parent->parent) { - ENode *parent_enode = (ENode*)parent->data; - - parent_enode->visible_descendents --; - } - } - } - else if (path == etree->root) { - etree->root = NULL; - if (etree->root_visible) { - etree->row_array = g_array_remove_index (etree->row_array, 0); - e_table_model_row_deleted (E_TABLE_MODEL (etree), 0); - } - } - else { - /* XXX invalid path */ - return NULL; - } - - - /* now free up the storage from that path */ - g_node_destroy (path); - g_free (enode); - - return ret; -} - - -static void -add_visible_descendents_to_array (ETreeModel *etm, GNode *gnode, int *row, int *count) -{ - GNode *child; - ENode *enode; - - /* add a row for this node */ - etm->row_array = g_array_insert_val (etm->row_array, (*row), gnode); - e_table_model_row_inserted (E_TABLE_MODEL (etm), (*row)++); - (*count) ++; - - /* then loop over its children, calling this routine for each - of them */ - enode = (ENode*)gnode->data; - if (enode->expanded) { - for (child = g_node_first_child (gnode); child; - child = g_node_next_sibling (child)) { - add_visible_descendents_to_array (etm, child, row, count); - } - } -} - -void -e_tree_model_node_sort (ETreeModel *tree_model, - ETreePath *node, - GCompareFunc compare) -{ - int num_nodes = g_node_n_children (node); - ETreePath **path_array; - int i; - - if (num_nodes == 0) - return; - - path_array = g_new (ETreePath*, num_nodes); - - for (i = 0; i < num_nodes; i ++) { - path_array[i] = g_node_first_child(node); - g_node_unlink (path_array[i]); - } - - qsort (path_array, num_nodes, sizeof(ETreePath*), compare); - - for (i = 0; i < num_nodes; i ++) { - g_node_append (node, path_array[i]); - } - - g_free (path_array); - - e_table_model_changed (E_TABLE_MODEL (tree_model)); -} |