aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/table/e-tree-selection-model.c68
-rw-r--r--widgets/table/e-tree-selection-model.h12
-rw-r--r--widgets/table/e-tree-sorted.c91
-rw-r--r--widgets/table/e-tree-table-adapter.c20
-rw-r--r--widgets/table/e-tree.c6
5 files changed, 150 insertions, 47 deletions
diff --git a/widgets/table/e-tree-selection-model.c b/widgets/table/e-tree-selection-model.c
index bfca69472a..b57efb5e11 100644
--- a/widgets/table/e-tree-selection-model.c
+++ b/widgets/table/e-tree-selection-model.c
@@ -52,7 +52,7 @@ struct ETreeSelectionModelPriv {
ETreePath cursor_path;
gint cursor_col;
- gint selection_start_row;
+ ETreePath selection_start_path;
int tree_model_pre_change_id;
int tree_model_node_changed_id;
@@ -789,7 +789,7 @@ etsm_select_all (ESelectionModel *selection)
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_row = 0;
+ etsm->priv->selection_start_path = etsm_node_at_row(etsm, 0);
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);
}
@@ -839,7 +839,7 @@ etsm_invert_selection (ESelectionModel *selection)
etsm->priv->cursor_col = -1;
etsm->priv->cursor_path = NULL;
- etsm->priv->selection_start_row = 0;
+ etsm->priv->selection_start_path = etsm_node_at_row(etsm, 0);
e_selection_model_selection_changed(E_SELECTION_MODEL(etsm));
e_selection_model_cursor_changed(E_SELECTION_MODEL(etsm), -1, -1);
}
@@ -870,6 +870,27 @@ etsm_change_one_row(ESelectionModel *selection, int row, gboolean grow)
}
static void
+etsm_change_one_path(ETreeSelectionModel *etsm, ETreePath path, gboolean grow)
+{
+ ETreeSelectionModelNode *node;
+
+ if (!path)
+ return;
+
+ path = e_tree_sorted_model_to_view_path(etsm->priv->ets, path);
+
+ if (!path)
+ return;
+
+ node = etsm_find_node_unless_equals (etsm, path, grow);
+
+ if (node) {
+ node->selected = grow;
+ update_parents(etsm, path);
+ }
+}
+
+static void
etsm_change_cursor (ESelectionModel *selection, int row, int col)
{
ETreeSelectionModel *etsm;
@@ -924,7 +945,7 @@ etsm_select_single_row (ESelectionModel *selection, int row)
etsm_real_clear (etsm);
etsm_change_one_row(selection, row, TRUE);
- etsm->priv->selection_start_row = row;
+ etsm->priv->selection_start_path = etsm_node_at_row(etsm, row);
e_selection_model_selection_changed(E_SELECTION_MODEL(etsm));
}
@@ -934,7 +955,7 @@ etsm_toggle_single_row (ESelectionModel *selection, int row)
{
ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection);
- etsm->priv->selection_start_row = row;
+ etsm->priv->selection_start_path = etsm_node_at_row(etsm, row);
etsm_change_one_row(selection, row, !etsm_is_row_selected(selection, row));
@@ -949,20 +970,21 @@ etsm_move_selection_end (ESelectionModel *selection, int row)
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, etsm->priv->selection_start_row),
+ 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, etsm->priv->selection_start_row),
+ 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, etsm->priv->selection_start_row),
+ 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, etsm->priv->selection_start_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 (etsm->priv->selection_start_row, etsm_cursor_row_real(etsm));
- old_end = MAX (etsm->priv->selection_start_row, etsm_cursor_row_real(etsm)) + 1;
- new_start = MIN (etsm->priv->selection_start_row, row);
- new_end = MAX (etsm->priv->selection_start_row, row) + 1;
+ 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)
@@ -980,11 +1002,8 @@ static void
etsm_set_selection_end (ESelectionModel *selection, int row)
{
ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL(selection);
- etsm_select_single_row(selection, etsm->priv->selection_start_row);
- if (etsm->priv->selection_start_row != -1)
- etsm->priv->cursor_path = etsm_node_at_row(etsm, etsm->priv->selection_start_row);
- else
- etsm->priv->cursor_path = NULL;
+ e_tree_selection_model_select_single_path(etsm, etsm->priv->selection_start_path);
+ etsm->priv->cursor_path = etsm->priv->selection_start_path;
e_selection_model_move_selection_end(selection, row);
}
@@ -1046,6 +1065,16 @@ e_tree_selection_model_foreach (ETreeSelectionModel *etsm,
}
}
+void
+e_tree_selection_model_select_single_path (ETreeSelectionModel *etsm, ETreePath path)
+{
+ etsm_real_clear (etsm);
+ etsm_change_one_path(etsm, path, TRUE);
+ etsm->priv->selection_start_path = path;
+
+ e_selection_model_selection_changed(E_SELECTION_MODEL(etsm));
+}
+
static void
e_tree_selection_model_init (ETreeSelectionModel *etsm)
@@ -1062,7 +1091,7 @@ e_tree_selection_model_init (ETreeSelectionModel *etsm)
priv->cursor_path = NULL;
priv->cursor_col = -1;
- priv->selection_start_row = 0;
+ priv->selection_start_path = NULL;
priv->tree_model_pre_change_id = 0;
priv->tree_model_node_changed_id = 0;
@@ -1134,4 +1163,3 @@ e_tree_selection_model_new (void)
E_MAKE_TYPE(e_tree_selection_model, "ETreeSelectionModel", ETreeSelectionModel,
e_tree_selection_model_class_init, e_tree_selection_model_init, PARENT_TYPE);
-
diff --git a/widgets/table/e-tree-selection-model.h b/widgets/table/e-tree-selection-model.h
index e95ce97e68..624d527b07 100644
--- a/widgets/table/e-tree-selection-model.h
+++ b/widgets/table/e-tree-selection-model.h
@@ -34,11 +34,13 @@ typedef struct {
} ETreeSelectionModelClass;
-GtkType e_tree_selection_model_get_type (void);
-ESelectionModel *e_tree_selection_model_new (void);
-void e_tree_selection_model_foreach (ETreeSelectionModel *etsm,
- ETreeForeachFunc callback,
- gpointer closure);
+GtkType e_tree_selection_model_get_type (void);
+ESelectionModel *e_tree_selection_model_new (void);
+void e_tree_selection_model_foreach (ETreeSelectionModel *etsm,
+ ETreeForeachFunc callback,
+ gpointer closure);
+void e_tree_selection_model_select_single_path (ETreeSelectionModel *etsm,
+ ETreePath path);
#ifdef __cplusplus
}
diff --git a/widgets/table/e-tree-sorted.c b/widgets/table/e-tree-sorted.c
index 7c3ca95287..3d70e019e4 100644
--- a/widgets/table/e-tree-sorted.c
+++ b/widgets/table/e-tree-sorted.c
@@ -68,6 +68,8 @@ struct ETreeSortedPriv {
ETableSortInfo *sort_info;
ETableHeader *full_header;
+ ETreeSortedPath *last_access;
+
int tree_model_pre_change_id;
int tree_model_node_changed_id;
int tree_model_node_data_changed_id;
@@ -122,6 +124,45 @@ ets_insert_idle(ETreeSorted *ets)
/* Helper functions */
+static inline ETreeSortedPath *
+check_last_access (ETreeSorted *ets, ETreePath corresponding)
+{
+ ETreeSortedPath *parent;
+ int end;
+ int start;
+ int i;
+
+ if (ets->priv->last_access == NULL)
+ return NULL;
+
+ if (ets->priv->last_access == corresponding) {
+ d(g_print("Found last access %p at %p.", ets->priv->last_access, ets->priv->last_access));
+ return ets->priv->last_access;
+ }
+
+ parent = ets->priv->last_access->parent;
+ if (parent && parent->children) {
+ i = ets->priv->last_access->position;
+ end = MIN(parent->num_children, i + 10);
+ for (; i < end; i++) {
+ if (parent->children[i] && parent->children[i]->corresponding == corresponding) {
+ d(g_print("Found last access %p at %p.", ets->priv->last_access, parent->children[i]));
+ return parent->children[i];
+ }
+ }
+
+ i = ets->priv->last_access->position - 1;
+ start = MAX(0, i - 10);
+ for (; i >= start; i--) {
+ if (parent->children[i] && parent->children[i]->corresponding == corresponding) {
+ d(g_print("Found last access %p at %p.", ets->priv->last_access, parent->children[i]));
+ return parent->children[i];
+ }
+ }
+ }
+ return NULL;
+}
+
static ETreeSortedPath *
find_path(ETreeSorted *ets, ETreePath corresponding)
{
@@ -129,14 +170,16 @@ find_path(ETreeSorted *ets, ETreePath corresponding)
ETreePath *sequence;
int i;
ETreeSortedPath *path;
+ ETreeSortedPath *check_last;
if (corresponding == NULL)
return NULL;
-#if 0
- if (etta->priv->last_access != -1 && etta->priv->map_table[etta->priv->last_access] == path)
- return etta->priv->last_access;
-#endif
+ check_last = check_last_access (ets, corresponding);
+ if (check_last) {
+ d(g_print(" (find_path)\n"));
+ return check_last;
+ }
depth = e_tree_model_node_depth(ets->priv->source, corresponding);
@@ -171,9 +214,8 @@ find_path(ETreeSorted *ets, ETreePath corresponding)
}
g_free (sequence);
-#if 0
- ets->priv->last_access = row;
-#endif
+ d(g_print("Didn't find last access %p. Setting to %p. (find_path)\n", ets->priv->last_access, path));
+ ets->priv->last_access = path;
return path;
}
@@ -204,14 +246,16 @@ find_or_create_path(ETreeSorted *ets, ETreePath corresponding)
ETreePath *sequence;
int i;
ETreeSortedPath *path;
+ ETreeSortedPath *check_last;
if (corresponding == NULL)
return NULL;
-#if 0
- if (etta->priv->last_access != -1 && etta->priv->map_table[etta->priv->last_access] == path)
- return etta->priv->last_access;
-#endif
+ check_last = check_last_access (ets, corresponding);
+ if (check_last) {
+ d(g_print(" (find_or_create_path)\n"));
+ return check_last;
+ }
depth = e_tree_model_node_depth(ets->priv->source, corresponding);
@@ -245,9 +289,8 @@ find_or_create_path(ETreeSorted *ets, ETreePath corresponding)
}
g_free (sequence);
-#if 0
- ets->priv->last_access = row;
-#endif
+ d(g_print("Didn't find last access %p. Setting to %p. (find_or_create_path)\n", ets->priv->last_access, path));
+ ets->priv->last_access = path;
return path;
}
@@ -864,6 +907,9 @@ ets_proxy_pre_change (ETreeModel *etm, ETreeSorted *ets)
static void
ets_proxy_node_changed (ETreeModel *etm, ETreePath node, ETreeSorted *ets)
{
+ ets->priv->last_access = NULL;
+ d(g_print("Setting last access %p. (ets_proxy_node_changed)\n", ets->priv->last_access));
+
if (e_tree_model_node_is_root(ets->priv->source, node)) {
if (ets->priv->root) {
free_path(ets->priv->root);
@@ -979,6 +1025,9 @@ ets_proxy_node_removed (ETreeModel *etm, ETreePath parent, ETreePath child, int
else
path = find_path(ets, child);
+ d(g_print("Setting last access %p. (ets_proxy_node_removed)\n ", ets->priv->last_access));
+ ets->priv->last_access = NULL;
+
if (path && parent_path && parent_path->num_children != -1) {
int i;
for (i = 0; i < parent_path->num_children; i++) {
@@ -1078,7 +1127,9 @@ e_tree_sorted_init (GtkObject *object)
priv->sort_info = NULL;
priv->full_header = NULL;
- priv->tree_model_pre_change_id = 0;
+ priv->last_access = NULL;
+
+ priv->tree_model_pre_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;
@@ -1152,9 +1203,11 @@ e_tree_sorted_view_to_model_path (ETreeSorted *ets,
ETreePath view_path)
{
ETreeSortedPath *path = view_path;
- if (path)
+ if (path) {
+ ets->priv->last_access = path;
+ d(g_print("Setting last access %p. (e_tree_sorted_view_to_model_path)\n", ets->priv->last_access));
return path->corresponding;
- else
+ } else
return NULL;
}
@@ -1162,9 +1215,7 @@ ETreePath
e_tree_sorted_model_to_view_path (ETreeSorted *ets,
ETreePath model_path)
{
- ETreeSortedPath *path = find_or_create_path(ets, model_path);
-
- return path;
+ return find_or_create_path(ets, model_path);
}
int
diff --git a/widgets/table/e-tree-table-adapter.c b/widgets/table/e-tree-table-adapter.c
index 5498d82358..71c73d7724 100644
--- a/widgets/table/e-tree-table-adapter.c
+++ b/widgets/table/e-tree-table-adapter.c
@@ -233,8 +233,23 @@ find_row_num(ETreeTableAdapter *etta, ETreePath path)
if (path == NULL)
return -1;
- if (etta->priv->last_access != -1 && etta->priv->map_table[etta->priv->last_access] == path)
- return etta->priv->last_access;
+ if (etta->priv->last_access != -1) {
+ int end = MIN(etta->priv->n_map, etta->priv->last_access + 10);
+ int start = MAX(0, etta->priv->last_access - 10);
+ for (i = etta->priv->last_access; i < end; i++) {
+ if(etta->priv->map_table[i] == path) {
+ d(g_print("Found last access %d at row %d. (find_row_num)\n", etta->priv->last_access, i));
+ return i;
+ }
+ }
+ for (i = etta->priv->last_access - 1; i <= start; i++) {
+ if(etta->priv->map_table[i] == path) {
+ d(g_print("Found last access %d at row %d. (find_row_num)\n", etta->priv->last_access, i));
+ return i;
+ }
+ }
+ }
+
depth = e_tree_model_node_depth(etta->priv->source, path);
@@ -268,6 +283,7 @@ find_row_num(ETreeTableAdapter *etta, ETreePath path)
}
g_free (sequence);
+ d(g_print("Didn't find last access %d. Setting to %d. (find_row_num)\n", etta->priv->last_access, row));
etta->priv->last_access = row;
return row;
}
diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c
index 42b279bef3..0aa2668546 100644
--- a/widgets/table/e-tree.c
+++ b/widgets/table/e-tree.c
@@ -1033,11 +1033,16 @@ e_tree_new_from_spec_file (ETreeModel *etm, ETableExtras *ete, const char *spec_
void
e_tree_set_cursor (ETree *e_tree, ETreePath path)
{
+#ifndef E_TREE_USE_TREE_SELECTION
int row;
+#endif
g_return_if_fail(e_tree != NULL);
g_return_if_fail(E_IS_TREE(e_tree));
g_return_if_fail(path != NULL);
+#ifdef E_TREE_USE_TREE_SELECTION
+ e_tree_selection_model_select_single_path (E_TREE_SELECTION_MODEL(e_tree->priv->selection), path);
+#else
path = e_tree_sorted_model_to_view_path(e_tree->priv->sorted, path);
row = e_tree_table_adapter_row_of_node(E_TREE_TABLE_ADAPTER(e_tree->priv->etta), path);
@@ -1048,6 +1053,7 @@ e_tree_set_cursor (ETree *e_tree, ETreePath path)
gtk_object_set(GTK_OBJECT(e_tree->priv->selection),
"cursor_row", row,
NULL);
+#endif
}
ETreePath