aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table/e-tree-table-adapter.c
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/table/e-tree-table-adapter.c')
-rw-r--r--widgets/table/e-tree-table-adapter.c1413
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;
-}