diff options
-rw-r--r-- | widgets/table/e-tree-model.c | 134 | ||||
-rw-r--r-- | widgets/table/e-tree-model.h | 14 |
2 files changed, 99 insertions, 49 deletions
diff --git a/widgets/table/e-tree-model.c b/widgets/table/e-tree-model.c index 2fa542ca9b..d5b69656d5 100644 --- a/widgets/table/e-tree-model.c +++ b/widgets/table/e-tree-model.c @@ -35,6 +35,7 @@ typedef struct { gboolean expanded; guint visible_descendents; char *save_id; + ETreePathCompareFunc compare; gpointer node_data; } ENode; @@ -846,50 +847,6 @@ add_visible_descendents_to_array (ETreeModel *etm, GNode *gnode, int *row, int * } } -void -e_tree_model_node_sort (ETreeModel *tree_model, - ETreePath *node, - GCompareFunc compare) -{ - int num_nodes = g_node_n_children (node); - ETreePath **path_array; - gboolean *expanded; - int i; - int child_index; - gboolean node_expanded = e_tree_model_node_is_expanded (tree_model, node); - - if (num_nodes == 0) - return; - - path_array = g_new (ETreePath*, num_nodes); - expanded = g_new (gboolean, num_nodes); - - child_index = e_tree_model_row_of_node (tree_model, node) + 1; - - for (i = 0; i < num_nodes; i ++) { - path_array[i] = g_node_first_child(node); - expanded[i] = e_tree_model_node_is_expanded (tree_model, path_array[i]); - e_tree_model_node_set_expanded(tree_model, path_array[i], FALSE); - if (node_expanded) - tree_model->row_array = g_array_remove_index (tree_model->row_array, child_index); - g_node_unlink (path_array[i]); - } - - qsort (path_array, num_nodes, sizeof(ETreePath*), compare); - - for (i = num_nodes - 1; i >= 0; i --) { - g_node_prepend (node, path_array[i]); - if (node_expanded) - tree_model->row_array = g_array_insert_val (tree_model->row_array, child_index, path_array[i]); - e_tree_model_node_set_expanded (tree_model, path_array[i], expanded[i]); - } - - g_free (path_array); - g_free (expanded); - - e_table_model_changed (E_TABLE_MODEL (tree_model)); -} - static void save_expanded_state_func (char *key, gboolean expanded, gpointer user_data) { @@ -1040,3 +997,92 @@ e_tree_model_node_set_save_id (ETreeModel *etm, ETreePath *node, const char *id) etm->num_collapsed_to_save ++; } } + + + +void +e_tree_model_node_set_compare_function (ETreeModel *tree_model, + ETreePath *node, + ETreePathCompareFunc compare) +{ + ENode *enode; + gboolean need_sort; + + g_return_if_fail (E_TREE_MODEL (tree_model)); + g_return_if_fail (node && node->data); + + enode = (ENode*)node->data; + + need_sort = (compare != enode->compare); + + enode->compare = compare; + + if (need_sort) + e_tree_model_node_sort (tree_model, node); +} + +typedef struct { + ETreeModel *model; + ETreePath *path; + ETreePathCompareFunc compare; + gboolean was_expanded; +} ETreeSortInfo; + +static gint +e_tree_model_node_compare (ETreeSortInfo *info1, ETreeSortInfo *info2) +{ + return info1->compare (info1->model, info1->path, info2->path); +} + +void +e_tree_model_node_sort (ETreeModel *tree_model, + ETreePath *node) +{ + int num_nodes = g_node_n_children (node); + ETreeSortInfo *sort_info; + int i; + int child_index; + gboolean node_expanded = e_tree_model_node_is_expanded (tree_model, node); + ENode *enode; + + g_return_if_fail (E_TREE_MODEL (tree_model)); + g_return_if_fail (node && node->data); + + enode = (ENode*)node->data; + + g_return_if_fail (enode->compare); + + if (num_nodes == 0) + return; + + sort_info = g_new (ETreeSortInfo, num_nodes); + + child_index = e_tree_model_row_of_node (tree_model, node) + 1; + + for (i = 0; i < num_nodes; i ++) { + + sort_info[i].path = g_node_first_child(node); + sort_info[i].was_expanded = e_tree_model_node_is_expanded (tree_model, sort_info[i].path); + sort_info[i].model = tree_model; + sort_info[i].compare = enode->compare; + + e_tree_model_node_set_expanded(tree_model, sort_info[i].path, FALSE); + if (node_expanded) + tree_model->row_array = g_array_remove_index (tree_model->row_array, child_index); + g_node_unlink (sort_info[i].path); + } + + qsort (sort_info, num_nodes, sizeof(ETreeSortInfo), (GCompareFunc)e_tree_model_node_compare); + + for (i = num_nodes - 1; i >= 0; i --) { + g_node_prepend (node, sort_info[i].path); + if (node_expanded) + tree_model->row_array = g_array_insert_val (tree_model->row_array, child_index, sort_info[i].path); + e_tree_model_node_set_expanded (tree_model, sort_info[i].path, sort_info[i].was_expanded); + } + + g_free (sort_info); + + e_table_model_changed (E_TABLE_MODEL (tree_model)); +} + diff --git a/widgets/table/e-tree-model.h b/widgets/table/e-tree-model.h index b00101ca8e..ab142cc217 100644 --- a/widgets/table/e-tree-model.h +++ b/widgets/table/e-tree-model.h @@ -12,8 +12,11 @@ #define E_IS_TREE_MODEL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TREE_MODEL_TYPE)) typedef GNode ETreePath; +typedef struct ETreeModel ETreeModel; +typedef struct ETreeModelClass ETreeModelClass; +typedef gint (*ETreePathCompareFunc)(ETreeModel *, ETreePath *path1, ETreePath *path2); -typedef struct { +struct ETreeModel { ETableModel base; GNode *root; gboolean root_visible; @@ -21,9 +24,9 @@ typedef struct { guint32 num_expanded_to_save; guint32 num_collapsed_to_save; GHashTable *expanded_state; /* used for loading/saving expanded state */ -} ETreeModel; +}; -typedef struct { +struct ETreeModelClass { ETableModelClass parent_class; /* @@ -62,7 +65,7 @@ typedef struct { void (*node_collapsed) (ETreeModel *etm, ETreePath *node); void (*node_expanded) (ETreeModel *etm, ETreePath *node, gboolean *allow_expand); -} ETreeModelClass; +}; GtkType e_tree_model_get_type (void); void e_tree_model_construct (ETreeModel *etree); @@ -100,7 +103,8 @@ void e_tree_model_root_node_set_visible (ETreeModel *etree, gboolean visib gboolean e_tree_model_root_node_is_visible (ETreeModel *etree); /* sort routine, analogous to gtk_ctree_node_sort */ -void e_tree_model_node_sort (ETreeModel *tree_model, ETreePath *node, GCompareFunc compare); +void e_tree_model_node_set_compare_function (ETreeModel *tree_model, ETreePath *node, ETreePathCompareFunc compare); +void e_tree_model_node_sort (ETreeModel *tree_model, ETreePath *node); /* ** Routines for emitting signals on the ETreeModel |