diff options
author | Mike Kestner <mkestner@ximian.com> | 2003-03-04 14:53:46 +0800 |
---|---|---|
committer | Mike Kestner <mkestner@src.gnome.org> | 2003-03-04 14:53:46 +0800 |
commit | e366ce662a05377da22830fe9548a4d1ae337fa3 (patch) | |
tree | c969f36cf3feda2a4a3be3120687646b8d9e5bea /widgets/table/e-tree-selection-model.c | |
parent | 76f925a77b8479c7c6e08913b072e3fb2b826b14 (diff) | |
download | gsoc2013-evolution-e366ce662a05377da22830fe9548a4d1ae337fa3.tar.gz gsoc2013-evolution-e366ce662a05377da22830fe9548a4d1ae337fa3.tar.zst gsoc2013-evolution-e366ce662a05377da22830fe9548a4d1ae337fa3.zip |
rewrite to store selected paths in a hashtable instead of a tree. lose the
2003-03-04 Mike Kestner <mkestner@ximian.com>
* e-tree-selection-model.c : rewrite to store selected paths in a
hashtable instead of a tree.
* e-tree-table-adapter.c : lose the hacky orig_position api since
etsm doesn't need it anymore.
svn path=/trunk/; revision=20136
Diffstat (limited to 'widgets/table/e-tree-selection-model.c')
-rw-r--r-- | widgets/table/e-tree-selection-model.c | 905 |
1 files changed, 140 insertions, 765 deletions
diff --git a/widgets/table/e-tree-selection-model.c b/widgets/table/e-tree-selection-model.c index 17c596062a..db486795fa 100644 --- a/widgets/table/e-tree-selection-model.c +++ b/widgets/table/e-tree-selection-model.c @@ -1,10 +1,11 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-tree-selection-model.c - * Copyright 2000, 2001, Ximian, Inc. + * Copyright 2000, 2001, 2003 Ximian, Inc. * * Authors: * Chris Lahey <clahey@ximian.com> + * Mike Kestner <mkestner@ximian.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,11 +23,7 @@ */ #include <config.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtksignal.h> #include "e-tree-selection-model.h" -#include <gal/util/e-bit-array.h> -#include <gal/util/e-sorter.h> #include <gal/util/e-i18n.h> #include <gal/util/e-util.h> #include <gdk/gdkkeysyms.h> @@ -44,408 +41,82 @@ enum { PROP_ETTA, }; -typedef struct ETreeSelectionModelNode { - guint selected : 1; - guint all_children_selected : 1; - guint any_children_selected : 1; - EBitArray *all_children_selected_array; - EBitArray *any_children_selected_array; - struct ETreeSelectionModelNode **children; - int num_children; -} ETreeSelectionModelNode; - struct ETreeSelectionModelPriv { ETreeTableAdapter *etta; ETreeModel *model; - ETreeSelectionModelNode *root; - + GHashTable *paths; ETreePath cursor_path; + ETreePath end_path; gint cursor_col; - ETreePath selection_start_path; - - char *cursor_save_id; - - int frozen_count; - - int tree_model_pre_change_id; - int tree_model_no_change_id; - int tree_model_node_changed_id; - int tree_model_node_data_changed_id; - int tree_model_node_col_changed_id; - int tree_model_node_inserted_id; - int tree_model_node_removed_id; - int tree_model_node_deleted_id; - - /* Anything other than -1 means that the selection is a single - * row. This being -1 does not impart any information. */ - int selected_row; - /* Anything other than -1 means that the selection is a all - * rows between selection_start_path and cursor_path where - * selected_range_end is the rwo number of cursor_path. This - * being -1 does not impart any information. */ - int selected_range_end; -}; - -/* ETreeSelectionModelNode helpers */ - -static ETreeSelectionModelNode * -e_tree_selection_model_node_new (void) -{ - ETreeSelectionModelNode *node = g_new(ETreeSelectionModelNode, 1); - - node->selected = 0; - node->all_children_selected = 0; - node->any_children_selected = 0; - node->all_children_selected_array = NULL; - node->any_children_selected_array = NULL; - node->children = NULL; - node->num_children = -1; - - return node; -} - -static void -e_tree_selection_model_node_fill_children(ETreeSelectionModel *etsm, ETreePath path, ETreeSelectionModelNode *selection_node) -{ - int i; - for (selection_node->num_children = 0, path = e_tree_model_node_get_first_child(etsm->priv->model, path); - path; - path = e_tree_model_node_get_next(etsm->priv->model, path)) - selection_node->num_children++; - selection_node->children = g_new(ETreeSelectionModelNode *, selection_node->num_children); - for (i = 0; i < selection_node->num_children; i++) { - selection_node->children[i] = NULL; - } -} - -static void -e_tree_selection_model_node_free(ETreeSelectionModelNode *node) -{ - int i; - - if (node->all_children_selected_array) - g_object_unref(node->all_children_selected_array); - if (node->any_children_selected_array) - g_object_unref(node->any_children_selected_array); - - for (i = 0; i < node->num_children; i++) - if (node->children[i]) - e_tree_selection_model_node_free(node->children[i]); - g_free(node->children); - - g_free(node); -} - - -/* Other helper functions */ -static ETreePath -etsm_node_at_row(ETreeSelectionModel *etsm, int row) -{ - ETreePath path; - - if (!(row >= 0 && row < e_table_model_row_count(E_TABLE_MODEL(etsm->priv->etta)))) - return NULL; - - path = e_tree_table_adapter_node_at_row(etsm->priv->etta, row); - - return path; -} -static int -etsm_row_of_node(ETreeSelectionModel *etsm, ETreePath path) -{ - if (path) - return e_tree_table_adapter_row_of_node(etsm->priv->etta, path); - else - return -1; -} + gint tree_model_node_removed_id; + gint tree_model_node_deleted_id; +}; -static int -etsm_cursor_row_real (ETreeSelectionModel *etsm) +static gint +get_cursor_row (ETreeSelectionModel *etsm) { if (etsm->priv->cursor_path) - return etsm_row_of_node(etsm, etsm->priv->cursor_path); - else - return -1; -} - -static void -etsm_real_clear (ETreeSelectionModel *etsm) -{ - if (etsm->priv->root) { - e_tree_selection_model_node_free(etsm->priv->root); - etsm->priv->root = NULL; - } -} - + return e_tree_table_adapter_row_of_node(etsm->priv->etta, etsm->priv->cursor_path); -static ETreeSelectionModelNode * -etsm_find_node_unless_equals (ETreeSelectionModel *etsm, - ETreePath path, - gboolean grow) -{ - ETreeSelectionModelNode *selection_node; - ETreePath parent; - - parent = e_tree_model_node_get_parent(etsm->priv->model, path); - - if (parent) { - selection_node = etsm_find_node_unless_equals(etsm, parent, grow); - if (selection_node) { - int position = e_tree_table_adapter_orig_position(etsm->priv->etta, path); - if (selection_node->all_children_selected && grow) - return NULL; - if (!(selection_node->any_children_selected || grow)) - return NULL; - if (selection_node->all_children_selected_array && e_bit_array_value_at(selection_node->all_children_selected_array, position) && grow) - return NULL; - if (selection_node->any_children_selected_array && ! (e_bit_array_value_at(selection_node->any_children_selected_array, position) || grow)) - return NULL; - if (selection_node->children == NULL) { - e_tree_selection_model_node_fill_children(etsm, parent, selection_node); - } - if (!selection_node->children[position]) - selection_node->children[position] = e_tree_selection_model_node_new(); - - return selection_node->children[position]; - } else - return NULL; - } else { - if (!etsm->priv->root) - etsm->priv->root = e_tree_selection_model_node_new(); - return etsm->priv->root; - } + return -1; } static void -update_parents (ETreeSelectionModel *etsm, ETreePath path) +clear_selection (ETreeSelectionModel *etsm) { - int i; - int depth; - int *orig_position_sequence; - ETreeSelectionModelNode **node_sequence; - ETreePath parents; - - if (!etsm->priv->root) - return; - - depth = e_tree_model_node_depth (etsm->priv->model, path); - - orig_position_sequence = g_new(int, depth + 1); - node_sequence = g_new(ETreeSelectionModelNode *, depth + 1); - - parents = path; - - for (i = depth; i > 0; i--) { - if (!parents) { - g_free(orig_position_sequence); - g_free(node_sequence); - return; - } - orig_position_sequence[i] = e_tree_table_adapter_orig_position(etsm->priv->etta, parents); - parents = e_tree_model_node_get_parent(etsm->priv->model, parents); - } - - node_sequence[0] = etsm->priv->root; - for (i = 0; i < depth; i++) { - node_sequence[i + 1] = NULL; - - if (node_sequence[i]->children) - node_sequence[i + 1] = node_sequence[i]->children[orig_position_sequence[i + 1]]; - - if (node_sequence[i + 1] == NULL) { - g_free(orig_position_sequence); - g_free(node_sequence); - return; - } - } - - if (node_sequence[depth]->num_children == -1) - e_tree_selection_model_node_fill_children(etsm, path, node_sequence[depth]); - - if (!node_sequence[depth]->all_children_selected_array) - node_sequence[depth]->all_children_selected_array = e_bit_array_new(node_sequence[depth]->num_children); - if (!node_sequence[depth]->any_children_selected_array) - node_sequence[depth]->any_children_selected_array = e_bit_array_new(node_sequence[depth]->num_children); - - node_sequence[depth]->all_children_selected = - e_bit_array_cross_and(node_sequence[depth]->all_children_selected_array) && - node_sequence[depth]->selected; - - node_sequence[depth]->any_children_selected = - e_bit_array_cross_or(node_sequence[depth]->any_children_selected_array) || - node_sequence[depth]->selected; - - for (i = depth - 1; i >= 0; i--) { - gboolean all_children, any_children; - - if (!node_sequence[i]->all_children_selected_array) - node_sequence[i]->all_children_selected_array = e_bit_array_new(node_sequence[i]->num_children); - if (!node_sequence[i]->any_children_selected_array) - node_sequence[i]->any_children_selected_array = e_bit_array_new(node_sequence[i]->num_children); - - e_bit_array_change_one_row(node_sequence[i]->all_children_selected_array, - orig_position_sequence[i + 1], node_sequence[i + 1]->all_children_selected); - e_bit_array_change_one_row(node_sequence[i]->any_children_selected_array, - orig_position_sequence[i + 1], node_sequence[i + 1]->any_children_selected); - - all_children = node_sequence[i]->all_children_selected; - any_children = node_sequence[i]->any_children_selected; - - node_sequence[i]->all_children_selected = - e_bit_array_cross_and(node_sequence[i]->all_children_selected_array) && - node_sequence[i]->selected; - node_sequence[i]->any_children_selected = - e_bit_array_cross_or(node_sequence[i]->any_children_selected_array) || - node_sequence[i]->selected; - - if (all_children == node_sequence[i]->all_children_selected && - any_children == node_sequence[i]->any_children_selected) - break; - } - - g_free(orig_position_sequence); - g_free(node_sequence); + g_hash_table_destroy (etsm->priv->paths); + etsm->priv->paths = g_hash_table_new (NULL, NULL);; } - static void -etsm_change_one_path(ETreeSelectionModel *etsm, ETreePath path, gboolean grow) +change_one_path (ETreeSelectionModel *etsm, ETreePath path, gboolean grow) { - ETreeSelectionModelNode *node; - if (!path) return; - node = etsm_find_node_unless_equals (etsm, path, grow); - - if (node) { - node->selected = grow; - update_parents(etsm, path); - } -} - -static void -etsm_real_select_single_path (ETreeSelectionModel *etsm, ETreePath path) -{ - etsm_real_clear (etsm); - etsm_change_one_path(etsm, path, TRUE); - etsm->priv->selection_start_path = path; - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; -} - - -/* Signal handlers */ - -static void -etsm_freeze (ETreeSelectionModel *etsm) -{ - etsm->priv->frozen_count ++; -} - -static void -etsm_unfreeze (ETreeSelectionModel *etsm) -{ - etsm->priv->frozen_count --; -} - -static void -etsm_pre_change (ETreeModel *etm, ETreeSelectionModel *etsm) -{ - g_free (etsm->priv->cursor_save_id); - etsm->priv->cursor_save_id = NULL; - - if (e_tree_model_has_get_node_by_id (etm) && - e_tree_model_has_save_id (etm) && - etsm->priv->cursor_path) { - etsm->priv->cursor_save_id = e_tree_model_get_save_id (etm, etsm->priv->cursor_path); - } - - etsm_freeze (etsm); + if (grow) + g_hash_table_insert (etsm->priv->paths, path, path); + else if (g_hash_table_lookup (etsm->priv->paths, path)) + g_hash_table_remove (etsm->priv->paths, path); } static void -etsm_no_change (ETreeModel *etm, ETreeSelectionModel *etsm) +select_single_path (ETreeSelectionModel *etsm, ETreePath path) { - etsm_unfreeze (etsm); + clear_selection (etsm); + change_one_path(etsm, path, TRUE); } static void -clear_tree (ETreeSelectionModel *etsm, ETreeModel *etm) +select_range (ETreeSelectionModel *etsm, gint start, gint end) { - int cursor_row; - - etsm_real_clear (etsm); - etsm->priv->cursor_path = NULL; + gint i; - if (e_tree_model_has_get_node_by_id (etm) && etsm->priv->cursor_save_id) { - ETreePath cursor_path; - - cursor_path = e_tree_model_get_node_by_id (etm, etsm->priv->cursor_save_id); - etsm->priv->cursor_path = cursor_path; - if (cursor_path != NULL && etsm->priv->cursor_col == -1) - etsm->priv->cursor_col = 0; - - etsm_real_select_single_path(etsm, cursor_path); + if (start > end) { + i = start; + start = end; + end = i; } - cursor_row = etsm_cursor_row_real (etsm); - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; - e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); - if (cursor_row != -1) - e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), cursor_row, etsm->priv->cursor_col); - else { - e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), -1, -1); - e_selection_model_cursor_activated(E_SELECTION_MODEL(etsm), -1, -1); + for (i = start; i <= end; i++) { + ETreePath path = e_tree_table_adapter_node_at_row (etsm->priv->etta, i); + if (path) + g_hash_table_insert (etsm->priv->paths, path, path); } - - g_free (etsm->priv->cursor_save_id); - etsm->priv->cursor_save_id = NULL; -} - -static void -etsm_node_changed (ETreeModel *etm, ETreePath node, ETreeSelectionModel *etsm) -{ - clear_tree (etsm, etm); - etsm_unfreeze (etsm); -} - -static void -etsm_node_data_changed (ETreeModel *etm, ETreePath node, ETreeSelectionModel *etsm) -{ - g_free (etsm->priv->cursor_save_id); - etsm->priv->cursor_save_id = NULL; - etsm_unfreeze (etsm); -} - -static void -etsm_node_col_changed (ETreeModel *etm, ETreePath node, int col, ETreeSelectionModel *etsm) -{ - g_free (etsm->priv->cursor_save_id); - etsm->priv->cursor_save_id = NULL; - etsm_unfreeze (etsm); -} - -static void -etsm_node_inserted (ETreeModel *etm, ETreePath parent, ETreePath child, ETreeSelectionModel *etsm) -{ - clear_tree (etsm, etm); - etsm_unfreeze (etsm); } static void etsm_node_removed (ETreeModel *etm, ETreePath parent, ETreePath child, int old_position, ETreeSelectionModel *etsm) { + change_one_path(etsm, child, FALSE); } static void etsm_node_deleted (ETreeModel *etm, ETreePath child, ETreeSelectionModel *etsm) { - clear_tree (etsm, etm); - etsm_unfreeze (etsm); + change_one_path(etsm, child, FALSE); } @@ -460,18 +131,6 @@ add_model(ETreeSelectionModel *etsm, ETreeModel *model) return; g_object_ref(priv->model); - priv->tree_model_pre_change_id = g_signal_connect_after (G_OBJECT (priv->model), "pre_change", - G_CALLBACK (etsm_pre_change), etsm); - priv->tree_model_no_change_id = g_signal_connect_after (G_OBJECT (priv->model), "no_change", - G_CALLBACK (etsm_no_change), etsm); - priv->tree_model_node_changed_id = g_signal_connect_after (G_OBJECT (priv->model), "node_changed", - G_CALLBACK (etsm_node_changed), etsm); - priv->tree_model_node_data_changed_id = g_signal_connect_after (G_OBJECT (priv->model), "node_data_changed", - G_CALLBACK (etsm_node_data_changed), etsm); - priv->tree_model_node_col_changed_id = g_signal_connect_after (G_OBJECT (priv->model), "node_col_changed", - G_CALLBACK (etsm_node_col_changed), etsm); - priv->tree_model_node_inserted_id = g_signal_connect_after (G_OBJECT (priv->model), "node_inserted", - G_CALLBACK (etsm_node_inserted), etsm); priv->tree_model_node_removed_id = g_signal_connect_after (G_OBJECT (priv->model), "node_removed", G_CALLBACK (etsm_node_removed), etsm); priv->tree_model_node_deleted_id = g_signal_connect_after (G_OBJECT (priv->model), "node_deleted", @@ -487,18 +146,6 @@ drop_model(ETreeSelectionModel *etsm) return; g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_pre_change_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_no_change_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_node_changed_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_node_data_changed_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_node_col_changed_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), - priv->tree_model_node_inserted_id); - g_signal_handler_disconnect (G_OBJECT (priv->model), priv->tree_model_node_removed_id); g_signal_handler_disconnect (G_OBJECT (priv->model), priv->tree_model_node_deleted_id); @@ -506,40 +153,35 @@ drop_model(ETreeSelectionModel *etsm) g_object_unref (priv->model); priv->model = NULL; - priv->tree_model_pre_change_id = 0; - priv->tree_model_no_change_id = 0; - priv->tree_model_node_changed_id = 0; - priv->tree_model_node_data_changed_id = 0; - priv->tree_model_node_col_changed_id = 0; - priv->tree_model_node_inserted_id = 0; priv->tree_model_node_removed_id = 0; priv->tree_model_node_deleted_id = 0; } - -/* Virtual functions */ static void etsm_dispose (GObject *object) { - ETreeSelectionModel *etsm; + ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL (object); - etsm = E_TREE_SELECTION_MODEL (object); + drop_model(etsm); - if (etsm->priv) { - etsm_real_clear (etsm); - etsm->priv->cursor_path = NULL; + if (G_OBJECT_CLASS (parent_class)->dispose) + (* G_OBJECT_CLASS (parent_class)->dispose) (object); +} - drop_model(etsm); - - g_free (etsm->priv->cursor_save_id); - etsm->priv->cursor_save_id = NULL; +static void +etsm_finalize (GObject *object) +{ + ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL (object); + if (etsm->priv) { + clear_selection (etsm); + g_hash_table_destroy (etsm->priv->paths); g_free (etsm->priv); etsm->priv = NULL; } - if (G_OBJECT_CLASS (parent_class)->dispose) - (* G_OBJECT_CLASS (parent_class)->dispose) (object); + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } static void @@ -549,7 +191,7 @@ etsm_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *ps switch (prop_id){ case PROP_CURSOR_ROW: - g_value_set_int (value, etsm_cursor_row_real(etsm)); + g_value_set_int (value, get_cursor_row(etsm)); break; case PROP_CURSOR_COL: @@ -578,7 +220,7 @@ etsm_set_property (GObject *object, guint prop_id, const GValue *value, GParamSp break; case PROP_CURSOR_COL: - e_selection_model_do_something(esm, etsm_cursor_row_real(etsm), g_value_get_int(value), 0); + e_selection_model_do_something(esm, get_cursor_row(etsm), g_value_get_int(value), 0); break; case PROP_MODEL: @@ -592,73 +234,13 @@ etsm_set_property (GObject *object, guint prop_id, const GValue *value, GParamSp } } -static ETreeSelectionModelNode * -etsm_recurse_is_path_selected (ETreeSelectionModel *etsm, - ETreePath path, - gboolean *is_selected) -{ - ETreeSelectionModelNode *selection_node; - ETreePath parent; - - parent = e_tree_model_node_get_parent(etsm->priv->model, path); - - if (parent) { - selection_node = etsm_recurse_is_path_selected (etsm, parent, is_selected); - if (selection_node) { - int position = e_tree_table_adapter_orig_position(etsm->priv->etta, path); - if (position < 0 || position >= selection_node->num_children) { - *is_selected = FALSE; - return NULL; - } - if (selection_node->all_children_selected) { - *is_selected = TRUE; - return NULL; - } - if (! selection_node->any_children_selected) { - *is_selected = FALSE; - return NULL; - } - if (selection_node->all_children_selected_array && e_bit_array_value_at(selection_node->all_children_selected_array, position)) { - *is_selected = TRUE; - return NULL; - } - if (selection_node->any_children_selected_array && ! e_bit_array_value_at(selection_node->any_children_selected_array, position)) { - *is_selected = FALSE; - return NULL; - } - if (!selection_node->children) { - *is_selected = FALSE; - return NULL; - } - return selection_node->children[position]; - } else - return NULL; - } else { - if (etsm->priv->root) { - return etsm->priv->root; - } else { - *is_selected = FALSE; - return NULL; - } - } -} - static gboolean -etsm_is_path_selected (ETreeSelectionModel *etsm, - ETreePath path) +etsm_is_path_selected (ETreeSelectionModel *etsm, ETreePath path) { - ETreeSelectionModelNode *selection_node; - gboolean ret_val; - - if (!path) - return FALSE; - - selection_node = etsm_recurse_is_path_selected (etsm, path, &ret_val); + if (path && g_hash_table_lookup (etsm->priv->paths, path)) + return TRUE; - if (selection_node) - ret_val = selection_node->selected; - - return ret_val; + return FALSE; } /** @@ -693,10 +275,11 @@ typedef struct { } ModelAndCallback; static void -etsm_row_foreach_cb (ETreePath path, gpointer user_data) +etsm_row_foreach_cb (gpointer key, gpointer value, gpointer user_data) { + ETreePath path = key; ModelAndCallback *mac = user_data; - int row = etsm_row_of_node(mac->etsm, path); + int row = e_tree_table_adapter_row_of_node(mac->etsm->priv->etta, path); if (row >= 0) mac->callback(row, mac->closure); } @@ -722,7 +305,7 @@ etsm_foreach (ESelectionModel *selection, mac.callback = callback; mac.closure = closure; - e_tree_selection_model_foreach(etsm, etsm_row_foreach_cb, &mac); + g_hash_table_foreach(etsm->priv->paths, etsm_row_foreach_cb, &mac); } /** @@ -736,63 +319,13 @@ etsm_clear(ESelectionModel *selection) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - etsm_real_clear (etsm); + clear_selection (etsm); etsm->priv->cursor_path = NULL; - etsm->priv->cursor_col = -1; - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), -1, -1); } -/* Standard functions */ -static void -etsm_selected_count_all_recurse (ETreeSelectionModel *etsm, - ETreePath path, - int *count) -{ - ETreePath child; - - (*count) ++; - - child = e_tree_model_node_get_first_child(E_TREE_MODEL(etsm->priv->model), path); - for ( ; child; child = e_tree_model_node_get_next(E_TREE_MODEL(etsm->priv->model), child)) - if (child) - etsm_selected_count_all_recurse (etsm, child, count); -} - -static void -etsm_selected_count_recurse (ETreeSelectionModel *etsm, - ETreeSelectionModelNode *selection_node, - ETreePath path, - int *count) -{ - if (selection_node->all_children_selected) { - if (path) - etsm_selected_count_all_recurse(etsm, path, count); - return; - } - - if (selection_node->selected) { - (*count) ++; - } - - if (!selection_node->any_children_selected) - return; - - if (selection_node->children) { - ETreePath child = e_tree_model_node_get_first_child(E_TREE_MODEL(etsm->priv->model), path); - int i; - for (i = 0; child && i < selection_node->num_children; i++, child = e_tree_model_node_get_next(E_TREE_MODEL(etsm->priv->model), child)) - if (selection_node->all_children_selected_array && e_bit_array_value_at(selection_node->all_children_selected_array, i)) - etsm_selected_count_all_recurse (etsm, child, count); - else if (selection_node->children[i]) - etsm_selected_count_recurse (etsm, selection_node->children[i], child, count); - - } -} - /** * e_selection_model_selected_count * @selection: #ESelectionModel to count @@ -805,16 +338,15 @@ static gint etsm_selected_count (ESelectionModel *selection) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - int count = 0; - if (etsm->priv->root) { - ETreePath model_root; - model_root = e_tree_model_get_root(etsm->priv->model); - etsm_selected_count_recurse(etsm, etsm->priv->root, model_root, &count); - if (!e_tree_table_adapter_root_node_is_visible (etsm->priv->etta) && etsm_is_path_selected (etsm, e_tree_model_get_root(etsm->priv->model))) { - count --; - } - } - return count; + + return g_hash_table_size (etsm->priv->paths); +} + +static int +etsm_row_count (ESelectionModel *selection) +{ + ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); + return e_table_model_row_count(E_TABLE_MODEL(etsm->priv->etta)); } /** @@ -834,54 +366,14 @@ etsm_select_all (ESelectionModel *selection) if (root == NULL) return; - etsm_real_clear (etsm); + clear_selection (etsm); + select_range (etsm, 0, etsm_row_count (selection) - 1); - etsm->priv->root = e_tree_selection_model_node_new(); - etsm->priv->root->selected = TRUE; - etsm->priv->root->all_children_selected = TRUE; - etsm->priv->root->any_children_selected = TRUE; - - e_tree_selection_model_node_fill_children(etsm, root, etsm->priv->root); - etsm->priv->root->all_children_selected_array = NULL; - etsm->priv->root->any_children_selected_array = NULL; - - if (etsm->priv->cursor_col == -1) - etsm->priv->cursor_col = 0; if (etsm->priv->cursor_path == NULL) - etsm->priv->cursor_path = etsm_node_at_row(etsm, 0); - etsm->priv->selection_start_path = etsm_node_at_row(etsm, 0); - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; - e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); - e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), etsm_cursor_row_real(etsm), etsm->priv->cursor_col); -} + etsm->priv->cursor_path = e_tree_table_adapter_node_at_row(etsm->priv->etta, 0); -static void -etsm_invert_selection_recurse (ETreeSelectionModel *etsm, - ETreeSelectionModelNode *selection_node) -{ - gboolean temp; - EBitArray *temp_eba; - selection_node->selected = ! selection_node->selected; - - temp = selection_node->all_children_selected; - selection_node->all_children_selected = ! selection_node->any_children_selected; - selection_node->any_children_selected = ! temp; - - temp_eba = selection_node->all_children_selected_array; - selection_node->all_children_selected_array = selection_node->any_children_selected_array; - selection_node->any_children_selected_array = temp_eba; - if (selection_node->all_children_selected_array) - e_bit_array_invert_selection(selection_node->all_children_selected_array); - if (selection_node->any_children_selected_array) - e_bit_array_invert_selection(selection_node->any_children_selected_array); - if (selection_node->children) { - int i; - for (i = 0; i < selection_node->num_children; i++) { - if (selection_node->children[i]) - etsm_invert_selection_recurse (etsm, selection_node->children[i]); - } - } + e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); + e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), get_cursor_row(etsm), etsm->priv->cursor_col); } /** @@ -895,31 +387,29 @@ static void etsm_invert_selection (ESelectionModel *selection) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); + gint count = etsm_row_count (selection); + gint i; + + for (i = 0; i < count; i++) { + ETreePath path = e_tree_table_adapter_node_at_row (etsm->priv->etta, i); + if (!path) + continue; + if (g_hash_table_lookup (etsm->priv->paths, path)) + g_hash_table_remove (etsm->priv->paths, path); + else + g_hash_table_insert (etsm->priv->paths, path, path); + } - if (etsm->priv->root) - etsm_invert_selection_recurse (etsm, etsm->priv->root); - etsm->priv->cursor_col = -1; etsm->priv->cursor_path = NULL; - etsm->priv->selection_start_path = etsm_node_at_row(etsm, 0); - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), -1, -1); } -static int -etsm_row_count (ESelectionModel *selection) -{ - ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - return e_table_model_row_count(E_TABLE_MODEL(etsm->priv->etta)); -} - static void etsm_change_one_row(ESelectionModel *selection, int row, gboolean grow) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - ETreeSelectionModelNode *node; ETreePath path; g_return_if_fail(row < e_table_model_row_count(E_TABLE_MODEL(etsm->priv->etta))); @@ -931,12 +421,7 @@ etsm_change_one_row(ESelectionModel *selection, int row, gboolean grow) if (!path) return; - node = etsm_find_node_unless_equals (etsm, path, grow); - - if (node) { - node->selected = grow; - update_parents(etsm, path); - } + change_one_path (etsm, path, grow); } static void @@ -952,35 +437,18 @@ etsm_change_cursor (ESelectionModel *selection, int row, int col) if (row == -1) { etsm->priv->cursor_path = NULL; } else { - etsm->priv->cursor_path = etsm_node_at_row(etsm, row); + etsm->priv->cursor_path = e_tree_table_adapter_node_at_row(etsm->priv->etta, row); } etsm->priv->cursor_col = col; } -static void -etsm_change_range(ESelectionModel *selection, int start, int end, gboolean grow) -{ - int i; - if (start != end) { - if (selection->sorter && e_sorter_needs_sorting(selection->sorter)) { - for ( i = start; i < end; i++) { - e_selection_model_change_one_row(selection, e_sorter_sorted_to_model(selection->sorter, i), grow); - } - } else { - for ( i = start; i < end; i++) { - e_selection_model_change_one_row(selection, i, grow); - } - } - } -} - -static int +static gint etsm_cursor_row (ESelectionModel *selection) { - return etsm_cursor_row_real(E_TREE_SELECTION_MODEL(selection)); + return get_cursor_row(E_TREE_SELECTION_MODEL(selection)); } -static int +static gint etsm_cursor_col (ESelectionModel *selection) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); @@ -988,172 +456,98 @@ etsm_cursor_col (ESelectionModel *selection) } static void -etsm_select_single_row (ESelectionModel *selection, int row) +etsm_select_single_row (ESelectionModel *selection, gint row) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - int selected_row = etsm->priv->selected_row; - - etsm_real_clear (etsm); - etsm_change_one_row(selection, row, TRUE); - etsm->priv->selection_start_path = etsm_node_at_row(etsm, row); - - etsm->priv->selected_row = row; - etsm->priv->selected_range_end = -1; - if (selected_row != -1) { - if (selected_row != etsm->priv->selected_row) { - e_selection_model_selection_row_changed(E_SELECTION_MODEL(etsm), selected_row); - e_selection_model_selection_row_changed(E_SELECTION_MODEL(etsm), row); - } - } else { - e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); - } + ETreePath path = e_tree_table_adapter_node_at_row (etsm->priv->etta, row); + + g_return_if_fail (path != NULL); + + select_single_path (etsm, path); + + e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); } static void -etsm_toggle_single_row (ESelectionModel *selection, int row) +etsm_toggle_single_row (ESelectionModel *selection, gint row) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); + ETreePath path = e_tree_table_adapter_node_at_row(etsm->priv->etta, row); - etsm->priv->selection_start_path = etsm_node_at_row(etsm, row); + g_return_if_fail (path); - etsm_change_one_row(selection, row, !etsm_is_row_selected(selection, row)); + if (g_hash_table_lookup (etsm->priv->paths, path)) + g_hash_table_remove (etsm->priv->paths, path); + else + g_hash_table_insert (etsm->priv->paths, path, path); - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); } static void -etsm_real_move_selection_end (ETreeSelectionModel *etsm, int row) +etsm_real_move_selection_end (ETreeSelectionModel *etsm, gint row) { - ESelectionModel *selection = E_SELECTION_MODEL (etsm); - int old_start; - int old_end; - int new_start; - int new_end; - int start_row = etsm_row_of_node(etsm, etsm->priv->selection_start_path); - if (selection->sorter && e_sorter_needs_sorting(selection->sorter)) { - old_start = MIN (e_sorter_model_to_sorted(selection->sorter, start_row), - e_sorter_model_to_sorted(selection->sorter, etsm_cursor_row_real(etsm))); - old_end = MAX (e_sorter_model_to_sorted(selection->sorter, start_row), - e_sorter_model_to_sorted(selection->sorter, etsm_cursor_row_real(etsm))) + 1; - new_start = MIN (e_sorter_model_to_sorted(selection->sorter, start_row), - e_sorter_model_to_sorted(selection->sorter, row)); - new_end = MAX (e_sorter_model_to_sorted(selection->sorter, start_row), - e_sorter_model_to_sorted(selection->sorter, row)) + 1; - } else { - old_start = MIN (start_row, etsm_cursor_row_real(etsm)); - old_end = MAX (start_row, etsm_cursor_row_real(etsm)) + 1; - new_start = MIN (start_row, row); - new_end = MAX (start_row, row) + 1; - } - /* This wouldn't work nearly so smoothly if one end of the selection weren't held in place. */ - if (old_start < new_start) - etsm_change_range(selection, old_start, new_start, FALSE); - if (new_start < old_start) - etsm_change_range(selection, new_start, old_start, TRUE); - if (old_end < new_end) - etsm_change_range(selection, old_end, new_end, TRUE); - if (new_end < old_end) - etsm_change_range(selection, new_end, old_end, FALSE); - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; + ETreePath end_path = e_tree_table_adapter_node_at_row (etsm->priv->etta, row); + gint cursor; + + g_return_if_fail (end_path); + + cursor = e_tree_table_adapter_row_of_node(etsm->priv->etta, etsm->priv->cursor_path); + clear_selection (etsm); + select_range (etsm, cursor, row); } static void -etsm_move_selection_end (ESelectionModel *selection, int row) +etsm_move_selection_end (ESelectionModel *selection, gint row) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); + g_return_if_fail (etsm->priv->cursor_path); + etsm_real_move_selection_end (etsm, row); e_selection_model_selection_changed(E_SELECTION_MODEL(selection)); } static void -etsm_set_selection_end (ESelectionModel *selection, int row) +etsm_set_selection_end (ESelectionModel *selection, gint row) { ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection); - int selected_range_end = etsm->priv->selected_range_end; - etsm_real_select_single_path(etsm, etsm->priv->selection_start_path); - etsm->priv->cursor_path = etsm->priv->selection_start_path; + g_return_if_fail (etsm->priv->cursor_path); + etsm_real_move_selection_end(etsm, row); - etsm->priv->selected_range_end = row; - if (selected_range_end != -1 && row != -1) { - if (selected_range_end == row - 1 || - selected_range_end == row + 1) { - e_selection_model_selection_row_changed(E_SELECTION_MODEL(etsm), selected_range_end); - e_selection_model_selection_row_changed(E_SELECTION_MODEL(etsm), row); - return; - } - } e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); } - -/* Standard functions */ -static void -etsm_foreach_all_recurse (ETreeSelectionModel *etsm, - ETreePath path, - ETreeForeachFunc callback, - gpointer closure) -{ - ETreePath child; - - callback(path, closure); - - child = e_tree_model_node_get_first_child(E_TREE_MODEL(etsm->priv->model), path); - for ( ; child; child = e_tree_model_node_get_next(E_TREE_MODEL(etsm->priv->model), child)) - if (child) - etsm_foreach_all_recurse (etsm, child, callback, closure); -} +struct foreach_path_t { + ETreeForeachFunc callback; + gpointer closure; +}; static void -etsm_foreach_recurse (ETreeSelectionModel *etsm, - ETreeSelectionModelNode *selection_node, - ETreePath path, - ETreeForeachFunc callback, - gpointer closure) +foreach_path (gpointer key, gpointer value, gpointer data) { - if (selection_node->all_children_selected) { - if (path) - etsm_foreach_all_recurse(etsm, path, callback, closure); - return; - } - if (!selection_node->any_children_selected) - return; - - if (selection_node->selected) { - callback(path, closure); - } - - if (selection_node->children) { - ETreePath child = e_tree_model_node_get_first_child(E_TREE_MODEL(etsm->priv->model), path); - int i; - for (i = 0; i < selection_node->num_children; i++, child = e_tree_model_node_get_next(E_TREE_MODEL(etsm->priv->model), child)) - if (selection_node->all_children_selected_array && e_bit_array_value_at(selection_node->all_children_selected_array, i)) - etsm_foreach_all_recurse(etsm, child, callback, closure); - else if (selection_node->children[i]) - etsm_foreach_recurse (etsm, selection_node->children[i], child, callback, closure); - } + ETreePath path = key; + struct foreach_path_t *c = data; + c->callback (path, c->closure); } void -e_tree_selection_model_foreach (ETreeSelectionModel *etsm, - ETreeForeachFunc callback, - gpointer closure) +e_tree_selection_model_foreach (ETreeSelectionModel *etsm, ETreeForeachFunc callback, gpointer closure) { - if (etsm->priv->root) { - ETreePath model_root; - model_root = e_tree_model_get_root(etsm->priv->model); - etsm_foreach_recurse(etsm, etsm->priv->root, model_root, callback, closure); + if (etsm->priv->paths) { + struct foreach_path_t c; + c.callback = callback; + c.closure = closure; + g_hash_table_foreach(etsm->priv->paths, foreach_path, &c); + return; } } void e_tree_selection_model_select_single_path (ETreeSelectionModel *etsm, ETreePath path) { - etsm_real_select_single_path (etsm, path); + select_single_path (etsm, path); e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); } @@ -1161,10 +555,7 @@ e_tree_selection_model_select_single_path (ETreeSelectionModel *etsm, ETreePath void e_tree_selection_model_add_to_selection (ETreeSelectionModel *etsm, ETreePath path) { - etsm_change_one_path(etsm, path, TRUE); - etsm->priv->selection_start_path = path; - etsm->priv->selected_row = -1; - etsm->priv->selected_range_end = -1; + change_one_path(etsm, path, TRUE); e_selection_model_selection_changed(E_SELECTION_MODEL(etsm)); } @@ -1176,7 +567,7 @@ e_tree_selection_model_change_cursor (ETreeSelectionModel *etsm, ETreePath path) etsm->priv->cursor_path = path; - row = etsm_cursor_row_real(etsm); + row = get_cursor_row(etsm); E_SELECTION_MODEL (etsm)->old_selection = -1; @@ -1201,30 +592,13 @@ e_tree_selection_model_init (ETreeSelectionModel *etsm) priv->etta = NULL; priv->model = NULL; - priv->root = NULL; + priv->paths = g_hash_table_new (NULL, NULL); priv->cursor_path = NULL; priv->cursor_col = -1; - priv->selection_start_path = NULL; - - priv->cursor_save_id = NULL; - - priv->frozen_count = 0; - priv->frozen_count = 0; - - - priv->tree_model_pre_change_id = 0; - priv->tree_model_no_change_id = 0; - priv->tree_model_node_changed_id = 0; - priv->tree_model_node_data_changed_id = 0; - priv->tree_model_node_col_changed_id = 0; - priv->tree_model_node_inserted_id = 0; priv->tree_model_node_removed_id = 0; priv->tree_model_node_deleted_id = 0; - - priv->selected_row = -1; - priv->selected_range_end = -1; } static void @@ -1239,6 +613,7 @@ e_tree_selection_model_class_init (ETreeSelectionModelClass *klass) esm_class = E_SELECTION_MODEL_CLASS(klass); object_class->dispose = etsm_dispose; + object_class->finalize = etsm_finalize; object_class->get_property = etsm_get_property; object_class->set_property = etsm_set_property; |