diff options
Diffstat (limited to 'widgets/table/e-tree-table-adapter.c')
-rw-r--r-- | widgets/table/e-tree-table-adapter.c | 1413 |
1 files changed, 0 insertions, 1413 deletions
diff --git a/widgets/table/e-tree-table-adapter.c b/widgets/table/e-tree-table-adapter.c deleted file mode 100644 index c610039c83..0000000000 --- a/widgets/table/e-tree-table-adapter.c +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * 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/> - * - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> - -#include <glib/gstdio.h> -#include <libxml/tree.h> -#include <libxml/parser.h> - -#include <libedataserver/libedataserver.h> - -#include "e-util/e-util.h" -#include "libevolution-utils/e-xml-utils.h" - -#include "e-table-sorting-utils.h" -#include "e-tree-table-adapter.h" - -#define E_TREE_TABLE_ADAPTER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_TREE_TABLE_ADAPTER, ETreeTableAdapterPrivate)) - -/* workaround for avoiding API breakage */ -#define etta_get_type e_tree_table_adapter_get_type -G_DEFINE_TYPE (ETreeTableAdapter, etta, E_TYPE_TABLE_MODEL) -#define d(x) - -#define INCREMENT_AMOUNT 100 - -enum { - SORTING_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0, }; - -typedef struct { - ETreePath path; - guint32 num_visible_children; - guint32 index; - - guint expanded : 1; - guint expandable : 1; - guint expandable_set : 1; -} node_t; - -struct _ETreeTableAdapterPrivate { - ETreeModel *source; - ETableSortInfo *sort_info; - ETableHeader *header; - - gint n_map; - gint n_vals_allocated; - node_t **map_table; - GHashTable *nodes; - GNode *root; - - guint root_visible : 1; - guint remap_needed : 1; - - gint last_access; - - gint pre_change_id; - gint no_change_id; - gint rebuilt_id; - gint node_changed_id; - gint node_data_changed_id; - gint node_col_changed_id; - gint node_inserted_id; - gint node_removed_id; - gint node_request_collapse_id; - gint sort_info_changed_id; - - guint resort_idle_id; - - gint force_expanded_state; /* use this instead of model's default if not 0; <0 ... collapse, >0 ... expand */ -}; - -static void etta_sort_info_changed (ETableSortInfo *sort_info, ETreeTableAdapter *etta); - -static GNode * -lookup_gnode (ETreeTableAdapter *etta, - ETreePath path) -{ - GNode *gnode; - - if (!path) - return NULL; - - gnode = g_hash_table_lookup (etta->priv->nodes, path); - - return gnode; -} - -static void -resize_map (ETreeTableAdapter *etta, - gint size) -{ - if (size > etta->priv->n_vals_allocated) { - etta->priv->n_vals_allocated = MAX (etta->priv->n_vals_allocated + INCREMENT_AMOUNT, size); - etta->priv->map_table = g_renew (node_t *, etta->priv->map_table, etta->priv->n_vals_allocated); - } - - etta->priv->n_map = size; -} - -static void -move_map_elements (ETreeTableAdapter *etta, - gint to, - gint from, - gint count) -{ - if (count <= 0 || from >= etta->priv->n_map) - return; - memmove (etta->priv->map_table + to, etta->priv->map_table + from, count * sizeof (node_t *)); - etta->priv->remap_needed = TRUE; -} - -static gint -fill_map (ETreeTableAdapter *etta, - gint index, - GNode *gnode) -{ - GNode *p; - - if ((gnode != etta->priv->root) || etta->priv->root_visible) - etta->priv->map_table[index++] = gnode->data; - - for (p = gnode->children; p; p = p->next) - index = fill_map (etta, index, p); - - etta->priv->remap_needed = TRUE; - return index; -} - -static void -remap_indices (ETreeTableAdapter *etta) -{ - gint i; - for (i = 0; i < etta->priv->n_map; i++) - etta->priv->map_table[i]->index = i; - etta->priv->remap_needed = FALSE; -} - -static node_t * -get_node (ETreeTableAdapter *etta, - ETreePath path) -{ - GNode *gnode = lookup_gnode (etta, path); - - if (!gnode) - return NULL; - - return (node_t *) gnode->data; -} - -static void -resort_node (ETreeTableAdapter *etta, - GNode *gnode, - gboolean recurse) -{ - node_t *node = (node_t *) gnode->data; - ETreePath *paths, path; - GNode *prev, *curr; - gint i, count; - gboolean sort_needed; - - if (node->num_visible_children == 0) - return; - - sort_needed = etta->priv->sort_info && e_table_sort_info_sorting_get_count (etta->priv->sort_info) > 0; - - for (i = 0, path = e_tree_model_node_get_first_child (etta->priv->source, node->path); path; - path = e_tree_model_node_get_next (etta->priv->source, path), i++); - - count = i; - if (count <= 1) - return; - - paths = g_new0 (ETreePath, count); - - for (i = 0, path = e_tree_model_node_get_first_child (etta->priv->source, node->path); path; - path = e_tree_model_node_get_next (etta->priv->source, path), i++) - paths[i] = path; - - if (count > 1 && sort_needed) - e_table_sorting_utils_tree_sort (etta->priv->source, etta->priv->sort_info, etta->priv->header, paths, count); - - prev = NULL; - for (i = 0; i < count; i++) { - curr = lookup_gnode (etta, paths[i]); - if (!curr) - continue; - - if (prev) - prev->next = curr; - else - gnode->children = curr; - - curr->prev = prev; - curr->next = NULL; - prev = curr; - if (recurse) - resort_node (etta, curr, recurse); - } - - g_free (paths); -} - -static gint -get_row (ETreeTableAdapter *etta, - ETreePath path) -{ - node_t *node = get_node (etta, path); - if (!node) - return -1; - - if (etta->priv->remap_needed) - remap_indices (etta); - - return node->index; -} - -static ETreePath -get_path (ETreeTableAdapter *etta, - gint row) -{ - if (row == -1 && etta->priv->n_map > 0) - row = etta->priv->n_map - 1; - else if (row < 0 || row >= etta->priv->n_map) - return NULL; - - return etta->priv->map_table[row]->path; -} - -static void -kill_gnode (GNode *node, - ETreeTableAdapter *etta) -{ - g_hash_table_remove (etta->priv->nodes, ((node_t *) node->data)->path); - - while (node->children) { - GNode *next = node->children->next; - kill_gnode (node->children, etta); - node->children = next; - } - - g_free (node->data); - if (node == etta->priv->root) - etta->priv->root = NULL; - g_node_destroy (node); -} - -static void -update_child_counts (GNode *gnode, - gint delta) -{ - while (gnode) { - node_t *node = (node_t *) gnode->data; - node->num_visible_children += delta; - gnode = gnode->parent; - } -} - -static gint -delete_children (ETreeTableAdapter *etta, - GNode *gnode) -{ - node_t *node = (node_t *) gnode->data; - gint to_remove = node ? node->num_visible_children : 0; - - if (to_remove == 0) - return 0; - - while (gnode->children) { - GNode *next = gnode->children->next; - kill_gnode (gnode->children, etta); - gnode->children = next; - } - - return to_remove; -} - -static void -delete_node (ETreeTableAdapter *etta, - ETreePath parent, - ETreePath path) -{ - gint to_remove = 1; - gint parent_row = get_row (etta, parent); - gint row = get_row (etta, path); - GNode *gnode = lookup_gnode (etta, path); - GNode *parent_gnode = lookup_gnode (etta, parent); - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - - if (row == -1) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - - to_remove += delete_children (etta, gnode); - kill_gnode (gnode, etta); - - move_map_elements (etta, row, row + to_remove, etta->priv->n_map - row - to_remove); - resize_map (etta, etta->priv->n_map - to_remove); - - if (parent_gnode != NULL) { - node_t *parent_node = parent_gnode->data; - gboolean expandable = e_tree_model_node_is_expandable (etta->priv->source, parent); - - update_child_counts (parent_gnode, - to_remove); - if (parent_node->expandable != expandable) { - e_table_model_pre_change (E_TABLE_MODEL (etta)); - parent_node->expandable = expandable; - e_table_model_row_changed (E_TABLE_MODEL (etta), parent_row); - } - - resort_node (etta, parent_gnode, FALSE); - } - - e_table_model_rows_deleted (E_TABLE_MODEL (etta), row, to_remove); -} - -static GNode * -create_gnode (ETreeTableAdapter *etta, - ETreePath path) -{ - GNode *gnode; - node_t *node; - - node = g_new0 (node_t, 1); - node->path = path; - node->index = -1; - node->expanded = etta->priv->force_expanded_state == 0 ? e_tree_model_get_expanded_default (etta->priv->source) : etta->priv->force_expanded_state > 0; - node->expandable = e_tree_model_node_is_expandable (etta->priv->source, path); - node->expandable_set = 1; - node->num_visible_children = 0; - gnode = g_node_new (node); - g_hash_table_insert (etta->priv->nodes, path, gnode); - return gnode; -} - -static gint -insert_children (ETreeTableAdapter *etta, - GNode *gnode) -{ - ETreePath path, tmp; - gint count = 0; - gint pos = 0; - - path = ((node_t *) gnode->data)->path; - for (tmp = e_tree_model_node_get_first_child (etta->priv->source, path); - tmp; - tmp = e_tree_model_node_get_next (etta->priv->source, tmp), pos++) { - GNode *child = create_gnode (etta, tmp); - node_t *node = (node_t *) child->data; - if (node->expanded) - node->num_visible_children = insert_children (etta, child); - g_node_prepend (gnode, child); - count += node->num_visible_children + 1; - } - g_node_reverse_children (gnode); - return count; -} - -static void -generate_tree (ETreeTableAdapter *etta, - ETreePath path) -{ - GNode *gnode; - node_t *node; - gint size; - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - - g_return_if_fail (e_tree_model_node_is_root (etta->priv->source, path)); - - if (etta->priv->root) - kill_gnode (etta->priv->root, etta); - resize_map (etta, 0); - - gnode = create_gnode (etta, path); - node = (node_t *) gnode->data; - node->expanded = TRUE; - node->num_visible_children = insert_children (etta, gnode); - if (etta->priv->sort_info && e_table_sort_info_sorting_get_count (etta->priv->sort_info) > 0) - resort_node (etta, gnode, TRUE); - - etta->priv->root = gnode; - size = etta->priv->root_visible ? node->num_visible_children + 1 : node->num_visible_children; - resize_map (etta, size); - fill_map (etta, 0, gnode); - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -static void -insert_node (ETreeTableAdapter *etta, - ETreePath parent, - ETreePath path) -{ - GNode *gnode, *parent_gnode; - node_t *node, *parent_node; - gboolean expandable; - gint size, row; - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - - if (get_node (etta, path)) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - - parent_gnode = lookup_gnode (etta, parent); - if (!parent_gnode) { - ETreePath grandparent = e_tree_model_node_get_parent (etta->priv->source, parent); - if (e_tree_model_node_is_root (etta->priv->source, parent)) - generate_tree (etta, parent); - else - insert_node (etta, grandparent, parent); - e_table_model_changed (E_TABLE_MODEL (etta)); - return; - } - - parent_node = (node_t *) parent_gnode->data; - - if (parent_gnode != etta->priv->root) { - expandable = e_tree_model_node_is_expandable (etta->priv->source, parent); - if (parent_node->expandable != expandable) { - e_table_model_pre_change (E_TABLE_MODEL (etta)); - parent_node->expandable = expandable; - parent_node->expandable_set = 1; - e_table_model_row_changed (E_TABLE_MODEL (etta), parent_node->index); - } - } - - if (!e_tree_table_adapter_node_is_expanded (etta, parent)) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - - gnode = create_gnode (etta, path); - node = (node_t *) gnode->data; - - if (node->expanded) - node->num_visible_children = insert_children (etta, gnode); - - g_node_append (parent_gnode, gnode); - update_child_counts (parent_gnode, node->num_visible_children + 1); - resort_node (etta, parent_gnode, FALSE); - resort_node (etta, gnode, TRUE); - - size = node->num_visible_children + 1; - resize_map (etta, etta->priv->n_map + size); - if (parent_gnode == etta->priv->root) - row = 0; - else { - gint new_size = parent_node->num_visible_children + 1; - gint old_size = new_size - size; - row = parent_node->index; - move_map_elements (etta, row + new_size, row + old_size, etta->priv->n_map - row - new_size); - } - fill_map (etta, row, parent_gnode); - e_table_model_rows_inserted (E_TABLE_MODEL (etta), get_row (etta, path), size); -} - -typedef struct { - GSList *paths; - gboolean expanded; -} check_expanded_closure; - -static gboolean -check_expanded (GNode *gnode, - gpointer data) -{ - check_expanded_closure *closure = (check_expanded_closure *) data; - node_t *node = (node_t *) gnode->data; - - if (node->expanded != closure->expanded) - closure->paths = g_slist_prepend (closure->paths, node->path); - - return FALSE; -} - -static void -update_node (ETreeTableAdapter *etta, - ETreePath path) -{ - check_expanded_closure closure; - ETreePath parent = e_tree_model_node_get_parent (etta->priv->source, path); - GNode *gnode = lookup_gnode (etta, path); - GSList *l; - - closure.expanded = e_tree_model_get_expanded_default (etta->priv->source); - closure.paths = NULL; - - if (gnode) - g_node_traverse (gnode, G_POST_ORDER, G_TRAVERSE_ALL, -1, check_expanded, &closure); - - if (e_tree_model_node_is_root (etta->priv->source, path)) - generate_tree (etta, path); - else { - delete_node (etta, parent, path); - insert_node (etta, parent, path); - } - - for (l = closure.paths; l; l = l->next) - if (lookup_gnode (etta, l->data)) - e_tree_table_adapter_node_set_expanded (etta, l->data, !closure.expanded); - - g_slist_free (closure.paths); -} - -static void -etta_finalize (GObject *object) -{ - ETreeTableAdapterPrivate *priv; - - priv = E_TREE_TABLE_ADAPTER_GET_PRIVATE (object); - - if (priv->resort_idle_id) { - g_source_remove (priv->resort_idle_id); - priv->resort_idle_id = 0; - } - - if (priv->root) { - kill_gnode (priv->root, E_TREE_TABLE_ADAPTER (object)); - priv->root = NULL; - } - - g_hash_table_destroy (priv->nodes); - - g_free (priv->map_table); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (etta_parent_class)->finalize (object); -} - -static void -etta_dispose (GObject *object) -{ - ETreeTableAdapterPrivate *priv; - - priv = E_TREE_TABLE_ADAPTER_GET_PRIVATE (object); - - if (priv->sort_info) { - g_signal_handler_disconnect ( - priv->sort_info, priv->sort_info_changed_id); - g_object_unref (priv->sort_info); - priv->sort_info = NULL; - } - - if (priv->header) { - g_object_unref (priv->header); - priv->header = NULL; - } - - if (priv->source) { - g_signal_handler_disconnect ( - priv->source, priv->pre_change_id); - g_signal_handler_disconnect ( - priv->source, priv->no_change_id); - g_signal_handler_disconnect ( - priv->source, priv->rebuilt_id); - g_signal_handler_disconnect ( - priv->source, priv->node_changed_id); - g_signal_handler_disconnect ( - priv->source, priv->node_data_changed_id); - g_signal_handler_disconnect ( - priv->source, priv->node_col_changed_id); - g_signal_handler_disconnect ( - priv->source, priv->node_inserted_id); - g_signal_handler_disconnect ( - priv->source, priv->node_removed_id); - g_signal_handler_disconnect ( - priv->source, priv->node_request_collapse_id); - - g_object_unref (priv->source); - priv->source = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (etta_parent_class)->dispose (object); -} - -static gint -etta_column_count (ETableModel *etm) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_column_count (etta->priv->source); -} - -static gboolean -etta_has_save_id (ETableModel *etm) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_has_save_id (etta->priv->source); -} - -static gchar * -etta_get_save_id (ETableModel *etm, - gint row) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_get_save_id (etta->priv->source, get_path (etta, row)); -} - -static gboolean -etta_has_change_pending (ETableModel *etm) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_has_change_pending (etta->priv->source); -} - -static gint -etta_row_count (ETableModel *etm) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return etta->priv->n_map; -} - -static gpointer -etta_value_at (ETableModel *etm, - gint col, - gint row) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - switch (col) { - case -1: - if (row == -1) - return NULL; - return get_path (etta, row); - case -2: - return etta->priv->source; - case -3: - return etta; - default: - return e_tree_model_value_at (etta->priv->source, get_path (etta, row), col); - } -} - -static void -etta_set_value_at (ETableModel *etm, - gint col, - gint row, - gconstpointer val) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - e_tree_model_set_value_at (etta->priv->source, get_path (etta, row), col, val); -} - -static gboolean -etta_is_cell_editable (ETableModel *etm, - gint col, - gint row) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_node_is_editable (etta->priv->source, get_path (etta, row), col); -} - -static void -etta_append_row (ETableModel *etm, - ETableModel *source, - gint row) -{ -} - -static gpointer -etta_duplicate_value (ETableModel *etm, - gint col, - gconstpointer value) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_duplicate_value (etta->priv->source, col, value); -} - -static void -etta_free_value (ETableModel *etm, - gint col, - gpointer value) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - e_tree_model_free_value (etta->priv->source, col, value); -} - -static gpointer -etta_initialize_value (ETableModel *etm, - gint col) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_initialize_value (etta->priv->source, col); -} - -static gboolean -etta_value_is_empty (ETableModel *etm, - gint col, - gconstpointer value) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_value_is_empty (etta->priv->source, col, value); -} - -static gchar * -etta_value_to_string (ETableModel *etm, - gint col, - gconstpointer value) -{ - ETreeTableAdapter *etta = (ETreeTableAdapter *) etm; - - return e_tree_model_value_to_string (etta->priv->source, col, value); -} - -static void -etta_class_init (ETreeTableAdapterClass *class) -{ - GObjectClass *object_class; - ETableModelClass *table_model_class; - - g_type_class_add_private (class, sizeof (ETreeTableAdapterPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = etta_dispose; - object_class->finalize = etta_finalize; - - table_model_class = E_TABLE_MODEL_CLASS (class); - table_model_class->column_count = etta_column_count; - table_model_class->row_count = etta_row_count; - table_model_class->append_row = etta_append_row; - - table_model_class->value_at = etta_value_at; - table_model_class->set_value_at = etta_set_value_at; - table_model_class->is_cell_editable = etta_is_cell_editable; - - table_model_class->has_save_id = etta_has_save_id; - table_model_class->get_save_id = etta_get_save_id; - - table_model_class->has_change_pending = etta_has_change_pending; - table_model_class->duplicate_value = etta_duplicate_value; - table_model_class->free_value = etta_free_value; - table_model_class->initialize_value = etta_initialize_value; - table_model_class->value_is_empty = etta_value_is_empty; - table_model_class->value_to_string = etta_value_to_string; - - class->sorting_changed = NULL; - - signals[SORTING_CHANGED] = g_signal_new ( - "sorting_changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETreeTableAdapterClass, sorting_changed), - NULL, NULL, - e_marshal_BOOLEAN__NONE, - G_TYPE_BOOLEAN, 0, - G_TYPE_NONE); -} - -static void -etta_init (ETreeTableAdapter *etta) -{ - etta->priv = E_TREE_TABLE_ADAPTER_GET_PRIVATE (etta); - - etta->priv->root_visible = TRUE; - etta->priv->remap_needed = TRUE; -} - -static void -etta_proxy_pre_change (ETreeModel *etm, - ETreeTableAdapter *etta) -{ - e_table_model_pre_change (E_TABLE_MODEL (etta)); -} - -static void -etta_proxy_no_change (ETreeModel *etm, - ETreeTableAdapter *etta) -{ - e_table_model_no_change (E_TABLE_MODEL (etta)); -} - -static void -etta_proxy_rebuilt (ETreeModel *etm, - ETreeTableAdapter *etta) -{ - if (!etta->priv->root) - return; - kill_gnode (etta->priv->root, etta); - etta->priv->root = NULL; - g_hash_table_destroy (etta->priv->nodes); - etta->priv->nodes = g_hash_table_new (NULL, NULL); -} - -static gboolean -resort_model (ETreeTableAdapter *etta) -{ - etta_sort_info_changed (NULL, etta); - etta->priv->resort_idle_id = 0; - return FALSE; -} - -static void -etta_proxy_node_changed (ETreeModel *etm, - ETreePath path, - ETreeTableAdapter *etta) -{ - update_node (etta, path); - e_table_model_changed (E_TABLE_MODEL (etta)); - - /* FIXME: Really it shouldnt be required. But a lot of thread - * which were supposed to be present in the list is way below - */ - if (!etta->priv->resort_idle_id) - etta->priv->resort_idle_id = g_idle_add ((GSourceFunc) resort_model, etta); -} - -static void -etta_proxy_node_data_changed (ETreeModel *etm, - ETreePath path, - ETreeTableAdapter *etta) -{ - gint row = get_row (etta, path); - - if (row == -1) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - - e_table_model_row_changed (E_TABLE_MODEL (etta), row); -} - -static void -etta_proxy_node_col_changed (ETreeModel *etm, - ETreePath path, - gint col, - ETreeTableAdapter *etta) -{ - gint row = get_row (etta, path); - - if (row == -1) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - - e_table_model_cell_changed (E_TABLE_MODEL (etta), col, row); -} - -static void -etta_proxy_node_inserted (ETreeModel *etm, - ETreePath parent, - ETreePath child, - ETreeTableAdapter *etta) -{ - if (e_tree_model_node_is_root (etm, child)) - generate_tree (etta, child); - else - insert_node (etta, parent, child); - - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -static void -etta_proxy_node_removed (ETreeModel *etm, - ETreePath parent, - ETreePath child, - gint old_position, - ETreeTableAdapter *etta) -{ - delete_node (etta, parent, child); - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -static void -etta_proxy_node_request_collapse (ETreeModel *etm, - ETreePath node, - ETreeTableAdapter *etta) -{ - e_tree_table_adapter_node_set_expanded (etta, node, FALSE); -} - -static void -etta_sort_info_changed (ETableSortInfo *sort_info, - ETreeTableAdapter *etta) -{ - if (!etta->priv->root) - return; - - /* the function is called also internally, with sort_info = NULL, - * thus skip those in signal emit */ - if (sort_info) { - gboolean handled = FALSE; - - g_signal_emit (etta, signals[SORTING_CHANGED], 0, &handled); - - if (handled) - return; - } - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - resort_node (etta, etta->priv->root, TRUE); - fill_map (etta, 0, etta->priv->root); - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -ETableModel * -e_tree_table_adapter_construct (ETreeTableAdapter *etta, - ETreeModel *source, - ETableSortInfo *sort_info, - ETableHeader *header) -{ - ETreePath root; - - etta->priv->source = source; - g_object_ref (source); - - etta->priv->sort_info = sort_info; - if (sort_info) { - g_object_ref (sort_info); - etta->priv->sort_info_changed_id = g_signal_connect ( - sort_info, "sort_info_changed", - G_CALLBACK (etta_sort_info_changed), etta); - } - - etta->priv->header = header; - if (header) - g_object_ref (header); - - etta->priv->nodes = g_hash_table_new (NULL, NULL); - - root = e_tree_model_get_root (source); - - if (root) - generate_tree (etta, root); - - etta->priv->pre_change_id = g_signal_connect ( - source, "pre_change", - G_CALLBACK (etta_proxy_pre_change), etta); - etta->priv->no_change_id = g_signal_connect ( - source, "no_change", - G_CALLBACK (etta_proxy_no_change), etta); - etta->priv->rebuilt_id = g_signal_connect ( - source, "rebuilt", - G_CALLBACK (etta_proxy_rebuilt), etta); - etta->priv->node_changed_id = g_signal_connect ( - source, "node_changed", - G_CALLBACK (etta_proxy_node_changed), etta); - etta->priv->node_data_changed_id = g_signal_connect ( - source, "node_data_changed", - G_CALLBACK (etta_proxy_node_data_changed), etta); - etta->priv->node_col_changed_id = g_signal_connect ( - source, "node_col_changed", - G_CALLBACK (etta_proxy_node_col_changed), etta); - etta->priv->node_inserted_id = g_signal_connect ( - source, "node_inserted", - G_CALLBACK (etta_proxy_node_inserted), etta); - etta->priv->node_removed_id = g_signal_connect ( - source, "node_removed", - G_CALLBACK (etta_proxy_node_removed), etta); - etta->priv->node_request_collapse_id = g_signal_connect ( - source, "node_request_collapse", - G_CALLBACK (etta_proxy_node_request_collapse), etta); - - return E_TABLE_MODEL (etta); -} - -ETableModel * -e_tree_table_adapter_new (ETreeModel *source, - ETableSortInfo *sort_info, - ETableHeader *header) -{ - ETreeTableAdapter *etta = g_object_new (E_TYPE_TREE_TABLE_ADAPTER, NULL); - - e_tree_table_adapter_construct (etta, source, sort_info, header); - - return (ETableModel *) etta; -} - -typedef struct { - xmlNode *root; - gboolean expanded_default; - ETreeModel *model; -} TreeAndRoot; - -static void -save_expanded_state_func (gpointer keyp, - gpointer value, - gpointer data) -{ - ETreePath path = keyp; - node_t *node = ((GNode *) value)->data; - TreeAndRoot *tar = data; - xmlNode *xmlnode; - - if (node->expanded != tar->expanded_default) { - gchar *save_id = e_tree_model_get_save_id (tar->model, path); - xmlnode = xmlNewChild (tar->root, NULL, (const guchar *)"node", NULL); - e_xml_set_string_prop_by_name (xmlnode, (const guchar *)"id", save_id); - g_free (save_id); - } -} - -xmlDoc * -e_tree_table_adapter_save_expanded_state_xml (ETreeTableAdapter *etta) -{ - TreeAndRoot tar; - xmlDocPtr doc; - xmlNode *root; - - g_return_val_if_fail (etta != NULL, NULL); - - doc = xmlNewDoc ((const guchar *)"1.0"); - root = xmlNewDocNode (doc, NULL, (const guchar *)"expanded_state", NULL); - xmlDocSetRootElement (doc, root); - - tar.model = etta->priv->source; - tar.root = root; - tar.expanded_default = e_tree_model_get_expanded_default (etta->priv->source); - - e_xml_set_integer_prop_by_name (root, (const guchar *)"vers", 2); - e_xml_set_bool_prop_by_name (root, (const guchar *)"default", tar.expanded_default); - - g_hash_table_foreach (etta->priv->nodes, save_expanded_state_func, &tar); - - return doc; -} - -void -e_tree_table_adapter_save_expanded_state (ETreeTableAdapter *etta, - const gchar *filename) -{ - xmlDoc *doc; - - g_return_if_fail (etta != NULL); - - doc = e_tree_table_adapter_save_expanded_state_xml (etta); - if (doc) { - e_xml_save_file (filename, doc); - xmlFreeDoc (doc); - } -} - -static xmlDoc * -open_file (ETreeTableAdapter *etta, - const gchar *filename) -{ - xmlDoc *doc; - xmlNode *root; - gint vers; - gboolean model_default, saved_default; - - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) - return NULL; - -#ifdef G_OS_WIN32 - { - gchar *locale_filename = g_win32_locale_filename_from_utf8 (filename); - doc = xmlParseFile (locale_filename); - g_free (locale_filename); - } -#else - doc = xmlParseFile (filename); -#endif - - if (!doc) - return NULL; - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp ((gchar *) root->name, "expanded_state")) { - xmlFreeDoc (doc); - return NULL; - } - - vers = e_xml_get_integer_prop_by_name_with_default (root, (const guchar *)"vers", 0); - if (vers > 2) { - xmlFreeDoc (doc); - return NULL; - } - model_default = e_tree_model_get_expanded_default (etta->priv->source); - saved_default = e_xml_get_bool_prop_by_name_with_default (root, (const guchar *)"default", !model_default); - if (saved_default != model_default) { - xmlFreeDoc (doc); - return NULL; - } - - return doc; -} - -/* state: <0 ... collapse; 0 ... use default; >0 ... expand */ -void -e_tree_table_adapter_force_expanded_state (ETreeTableAdapter *etta, - gint state) -{ - g_return_if_fail (etta != NULL); - - etta->priv->force_expanded_state = state; -} - -void -e_tree_table_adapter_load_expanded_state_xml (ETreeTableAdapter *etta, - xmlDoc *doc) -{ - xmlNode *root, *child; - gboolean model_default; - gboolean file_default = FALSE; - - g_return_if_fail (etta != NULL); - g_return_if_fail (doc != NULL); - - root = xmlDocGetRootElement (doc); - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - - model_default = e_tree_model_get_expanded_default (etta->priv->source); - - if (!strcmp ((gchar *) root->name, "expanded_state")) { - gchar *state; - - state = e_xml_get_string_prop_by_name_with_default (root, (const guchar *)"default", ""); - - if (state[0] == 't') - file_default = TRUE; - else - file_default = FALSE; /* Even unspecified we'll consider as false */ - - g_free (state); - } - - /* Incase the default is changed, lets forget the changes and stick to default */ - - if (file_default != model_default) { - xmlFreeDoc (doc); - return; - } - - for (child = root->xmlChildrenNode; child; child = child->next) { - gchar *id; - ETreePath path; - - if (strcmp ((gchar *) child->name, "node")) { - d (g_warning ("unknown node '%s' in %s", child->name, filename)); - continue; - } - - id = e_xml_get_string_prop_by_name_with_default (child, (const guchar *)"id", ""); - - if (!strcmp (id, "")) { - g_free (id); - continue; - } - - path = e_tree_model_get_node_by_id (etta->priv->source, id); - if (path) - e_tree_table_adapter_node_set_expanded (etta, path, !model_default); - - g_free (id); - } - - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -void -e_tree_table_adapter_load_expanded_state (ETreeTableAdapter *etta, - const gchar *filename) -{ - xmlDoc *doc; - - g_return_if_fail (etta != NULL); - - doc = open_file (etta, filename); - if (!doc) - return; - - e_tree_table_adapter_load_expanded_state_xml (etta, doc); - - xmlFreeDoc (doc); -} - -void -e_tree_table_adapter_root_node_set_visible (ETreeTableAdapter *etta, - gboolean visible) -{ - gint size; - - g_return_if_fail (etta != NULL); - - if (etta->priv->root_visible == visible) - return; - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - - etta->priv->root_visible = visible; - if (!visible) { - ETreePath root = e_tree_model_get_root (etta->priv->source); - if (root) - e_tree_table_adapter_node_set_expanded (etta, root, TRUE); - } - size = (visible ? 1 : 0) + (etta->priv->root ? ((node_t *) etta->priv->root->data)->num_visible_children : 0); - resize_map (etta, size); - if (etta->priv->root) - fill_map (etta, 0, etta->priv->root); - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -void -e_tree_table_adapter_node_set_expanded (ETreeTableAdapter *etta, - ETreePath path, - gboolean expanded) -{ - GNode *gnode = lookup_gnode (etta, path); - node_t *node; - gint row; - - if (!expanded && (!gnode || (e_tree_model_node_is_root (etta->priv->source, path) && !etta->priv->root_visible))) - return; - - if (!gnode && expanded) { - ETreePath parent = e_tree_model_node_get_parent (etta->priv->source, path); - g_return_if_fail (parent != NULL); - e_tree_table_adapter_node_set_expanded (etta, parent, expanded); - gnode = lookup_gnode (etta, path); - } - g_return_if_fail (gnode != NULL); - - node = (node_t *) gnode->data; - - if (expanded == node->expanded) - return; - - node->expanded = expanded; - - row = get_row (etta, path); - if (row == -1) - return; - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - e_table_model_pre_change (E_TABLE_MODEL (etta)); - e_table_model_row_changed (E_TABLE_MODEL (etta), row); - - if (expanded) { - gint num_children = insert_children (etta, gnode); - update_child_counts (gnode, num_children); - if (etta->priv->sort_info && e_table_sort_info_sorting_get_count (etta->priv->sort_info) > 0) - resort_node (etta, gnode, TRUE); - resize_map (etta, etta->priv->n_map + num_children); - move_map_elements (etta, row + 1 + num_children, row + 1, etta->priv->n_map - row - 1 - num_children); - fill_map (etta, row, gnode); - if (num_children != 0) { - e_table_model_rows_inserted (E_TABLE_MODEL (etta), row + 1, num_children); - } else - e_table_model_no_change (E_TABLE_MODEL (etta)); - } else { - gint num_children = delete_children (etta, gnode); - if (num_children == 0) { - e_table_model_no_change (E_TABLE_MODEL (etta)); - return; - } - move_map_elements (etta, row + 1, row + 1 + num_children, etta->priv->n_map - row - 1 - num_children); - update_child_counts (gnode, - num_children); - resize_map (etta, etta->priv->n_map - num_children); - e_table_model_rows_deleted (E_TABLE_MODEL (etta), row + 1, num_children); - } -} - -void -e_tree_table_adapter_node_set_expanded_recurse (ETreeTableAdapter *etta, - ETreePath path, - gboolean expanded) -{ - ETreePath children; - - e_tree_table_adapter_node_set_expanded (etta, path, expanded); - - for (children = e_tree_model_node_get_first_child (etta->priv->source, path); - children; - children = e_tree_model_node_get_next (etta->priv->source, children)) { - e_tree_table_adapter_node_set_expanded_recurse (etta, children, expanded); - } -} - -ETreePath -e_tree_table_adapter_node_at_row (ETreeTableAdapter *etta, - gint row) -{ - return get_path (etta, row); -} - -gint -e_tree_table_adapter_row_of_node (ETreeTableAdapter *etta, - ETreePath path) -{ - return get_row (etta, path); -} - -gboolean -e_tree_table_adapter_root_node_is_visible (ETreeTableAdapter *etta) -{ - return etta->priv->root_visible; -} - -void -e_tree_table_adapter_show_node (ETreeTableAdapter *etta, - ETreePath path) -{ - ETreePath parent; - - parent = e_tree_model_node_get_parent (etta->priv->source, path); - - while (parent) { - e_tree_table_adapter_node_set_expanded (etta, parent, TRUE); - parent = e_tree_model_node_get_parent (etta->priv->source, parent); - } -} - -gboolean -e_tree_table_adapter_node_is_expanded (ETreeTableAdapter *etta, - ETreePath path) -{ - node_t *node = get_node (etta, path); - if (!e_tree_model_node_is_expandable (etta->priv->source, path) || !node) - return FALSE; - - return node->expanded; -} - -void -e_tree_table_adapter_set_sort_info (ETreeTableAdapter *etta, - ETableSortInfo *sort_info) -{ - if (etta->priv->sort_info) { - g_signal_handler_disconnect ( - etta->priv->sort_info, - etta->priv->sort_info_changed_id); - g_object_unref (etta->priv->sort_info); - } - - etta->priv->sort_info = sort_info; - if (sort_info) { - g_object_ref (sort_info); - etta->priv->sort_info_changed_id = g_signal_connect ( - sort_info, "sort_info_changed", - G_CALLBACK (etta_sort_info_changed), etta); - } - - if (!etta->priv->root) - return; - - e_table_model_pre_change (E_TABLE_MODEL (etta)); - resort_node (etta, etta->priv->root, TRUE); - fill_map (etta, 0, etta->priv->root); - e_table_model_changed (E_TABLE_MODEL (etta)); -} - -ETableSortInfo * -e_tree_table_adapter_get_sort_info (ETreeTableAdapter *etta) -{ - g_return_val_if_fail (etta != NULL, NULL); - - return etta->priv->sort_info; -} - -ETableHeader * -e_tree_table_adapter_get_header (ETreeTableAdapter *etta) -{ - g_return_val_if_fail (etta != NULL, NULL); - - return etta->priv->header; -} - -ETreePath -e_tree_table_adapter_node_get_next (ETreeTableAdapter *etta, - ETreePath path) -{ - GNode *node = lookup_gnode (etta, path); - - if (node && node->next) - return ((node_t *) node->next->data)->path; - - return NULL; -} |