From 40d58afa7ce854ae8154a7f0ce32997f57d99ea4 Mon Sep 17 00:00:00 2001 From: Christopher James Lahey Date: Fri, 23 Feb 2001 23:00:09 +0000 Subject: Added e-table/e-table-sorting-utils.lo. 2001-02-23 Christopher James Lahey * gal/Makefile.am (libgal_la_LIBADD): Added e-table/e-table-sorting-utils.lo. From gal/e-table/ChangeLog: 2001-02-23 Christopher James Lahey * Makefile.am (libetable_la_SOURCES): Added e-table-sorting-utils.c. (libetableinclude_HEADERS): Added e-table-sorting-utils.h. * e-table-group-container.c: Implemented add_array method. Use add_array to implement add_all instead of using add. Did some general clean up. * e-table-group-leaf.c, e-table-group-leaf.h: Implemented add_array method. Changed everything to use an ETableSubset variable instead of an ETableSortedVariable. Implemented it as ETableSortedVariable if there's grouping involved and ETableSorted if there isn't. * e-table-group.c, e-table-group.h: Added add_array method. Added unused get_position code. * e-table-sorted-variable.c, e-table-sorted-variable.h: Moved a lot of the actual implementation of sorting to e-table-sorting-utils.c. Got rid of the signal handlers here since we weren't using them and ETableSubset has the proxy virtual methods. * e-table-sorted.c, e-table-sorted.h: Completely replaced these files with a variation on ETableSortedVariable that doesn't have the add methods and such but instead just mimics the source model's set of rows completely. * e-table-sorter.c, e-table-sorter.h: Added functions to get at the arrays here. * e-table-sorting-utils.c, e-table-sorting-utils.h: Utility functions for doing sorting. * e-table-subset-variable.c, e-table-subset-variable.h: Added add_array method. * e-table-subset.c, e-table-subset.h: Made it so that the signal hookups to the source model's signals are virtual methods. * e-table.c, e-table.h: Don't call add_all and add and remove type functions if not grouped. Don't rebuild for sort changes unless it was either grouped before or will be grouped now. svn path=/trunk/; revision=8374 --- widgets/table/e-table-sorted-variable.c | 385 +------------------------------- 1 file changed, 3 insertions(+), 382 deletions(-) (limited to 'widgets/table/e-table-sorted-variable.c') diff --git a/widgets/table/e-table-sorted-variable.c b/widgets/table/e-table-sorted-variable.c index 94362f547c..3416e5d9d3 100644 --- a/widgets/table/e-table-sorted-variable.c +++ b/widgets/table/e-table-sorted-variable.c @@ -13,6 +13,7 @@ #include #include "gal/util/e-util.h" #include "e-table-sorted-variable.h" +#include "e-table-sorting-utils.h" #define d(x) @@ -25,11 +26,6 @@ static ETableSubsetVariableClass *etsv_parent_class; -static void etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv); -#if 0 -static void etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv); -static void etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv); -#endif static void etsv_sort_info_changed (ETableSortInfo *info, ETableSortedVariable *etsv); static void etsv_sort (ETableSortedVariable *etsv); static void etsv_add (ETableSubsetVariable *etssv, gint row); @@ -39,16 +35,7 @@ static void etsv_destroy (GtkObject *object) { ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (object); - ETableSubset *etss = E_TABLE_SUBSET (object); - - gtk_signal_disconnect (GTK_OBJECT (etss->source), - etsv->table_model_changed_id); -#if 0 - gtk_signal_disconnect (GTK_OBJECT (etss->source), - etsv->table_model_row_changed_id); - gtk_signal_disconnect (GTK_OBJECT (etss->source), - etsv->table_model_cell_changed_id); -#endif + gtk_signal_disconnect (GTK_OBJECT (etsv->sort_info), etsv->sort_info_changed_id); @@ -59,10 +46,6 @@ etsv_destroy (GtkObject *object) g_source_remove(etsv->insert_idle_id); } - etsv->table_model_changed_id = 0; - etsv->table_model_row_changed_id = 0; - etsv->table_model_cell_changed_id = 0; - if (etsv->sort_info) gtk_object_unref(GTK_OBJECT(etsv->sort_info)); if (etsv->full_header) @@ -90,9 +73,6 @@ etsv_init (ETableSortedVariable *etsv) etsv->full_header = NULL; etsv->sort_info = NULL; - etsv->table_model_changed_id = 0; - etsv->table_model_row_changed_id = 0; - etsv->table_model_cell_changed_id = 0; etsv->sort_info_changed_id = 0; etsv->sort_idle_id = 0; @@ -279,390 +259,31 @@ e_table_sorted_variable_new (ETableModel *source, ETableHeader *full_header, ETa etsv->full_header = full_header; gtk_object_ref(GTK_OBJECT(etsv->full_header)); - etsv->table_model_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_changed", - GTK_SIGNAL_FUNC (etsv_proxy_model_changed), etsv); -#if 0 - etsv->table_model_row_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_row_changed", - GTK_SIGNAL_FUNC (etsv_proxy_model_row_changed), etsv); - etsv->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed", - GTK_SIGNAL_FUNC (etsv_proxy_model_cell_changed), etsv); -#endif etsv->sort_info_changed_id = gtk_signal_connect (GTK_OBJECT (sort_info), "sort_info_changed", GTK_SIGNAL_FUNC (etsv_sort_info_changed), etsv); return E_TABLE_MODEL(etsv); } -static void -etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv) -{ - /* FIXME: do_resort (); */ -} -#if 0 -static void -etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv) -{ - ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv); - - if (e_table_subset_variable_remove(etssv, row)) - e_table_subset_variable_add (etssv, row); -} - -static void -etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv) -{ - ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv); - - if (e_table_subset_variable_remove(etssv, row)) - e_table_subset_variable_add (etssv, row); -} -#endif - static void etsv_sort_info_changed (ETableSortInfo *info, ETableSortedVariable *etsv) { etsv_sort(etsv); } -static ETableSortedVariable *etsv_closure; -void **vals_closure; -int cols_closure; -int *ascending_closure; -GCompareFunc *compare_closure; - -/* FIXME: Make it not cache the second and later columns (as if anyone cares.) */ - -static int -qsort_callback(const void *data1, const void *data2) -{ - gint row1 = *(int *)data1; - gint row2 = *(int *)data2; - int j; - int sort_count = e_table_sort_info_sorting_get_count(etsv_closure->sort_info); - int comp_val = 0; - int ascending = 1; - for (j = 0; j < sort_count; j++) { - comp_val = (*(compare_closure[j]))(vals_closure[cols_closure * row1 + j], vals_closure[cols_closure * row2 + j]); - ascending = ascending_closure[j]; - if (comp_val != 0) - break; - } - if (comp_val == 0) { - if (row1 < row2) - comp_val = -1; - if (row1 > row2) - comp_val = 1; - } - if (!ascending) - comp_val = -comp_val; - return comp_val; -} - -struct _subinfo { - int start; - GArray *rowsort; /* an array of row info's */ -}; - -struct _rowinfo { - int row; - struct _subinfo *subinfo; - struct _group_info *groupinfo; -}; - -static int -qsort_callback_complex(const void *data1, const void *data2) -{ - gint row1 = ((struct _rowinfo *)data1)->row; - gint row2 = ((struct _rowinfo *)data2)->row; - int j; - int sort_count = e_table_sort_info_sorting_get_count(etsv_closure->sort_info); - int comp_val = 0; - int ascending = 1; - for (j = 0; j < sort_count; j++) { - comp_val = (*(compare_closure[j]))(vals_closure[cols_closure * row1 + j], vals_closure[cols_closure * row2 + j]); - ascending = ascending_closure[j]; - if (comp_val != 0) - break; - } - if (comp_val == 0) { - if (row1 < row2) - comp_val = -1; - if (row1 > row2) - comp_val = 1; - } - if (!ascending) - comp_val = -comp_val; - return comp_val; -} - -/* if sortgroup is like: -0 1 1 1 -1 1 2 2 -2 2 3 2 -3 2 4 3 -4 3 5 3 -5 2 6 1 -6 1 0 1 - - Want to sort the 1's first - Then sort each group of 2's, offsetting into the output by the new root 1 location - ... Recursively ... -*/ - -struct _group_info { - char *group; - int row; -}; - -#ifdef DEBUG -#undef DEBUG -#endif -/*#define DEBUG*/ - -#ifdef DEBUG -static int total=0; -static int total_sorted=0; -#endif - -/* builds the info needed to sort everything */ -static struct _subinfo * -etsv_sort_build_subset(ETableSortedVariable *etsv, struct _group_info *groupinfo, int start, int *end) -{ -/* ETableSubset *etss = E_TABLE_SUBSET(etsv);*/ - int rows = E_TABLE_SUBSET(etsv)->n_map; - int i, lastinsert; - GArray *rowsort = g_array_new(0, 0, sizeof(struct _rowinfo)); - struct _subinfo *subinfo, *newsub; - char *id, *newid; - int idlen, newidlen; - int cmp; - int cmplen; - - subinfo = g_malloc0(sizeof(*subinfo)); - subinfo->rowsort = rowsort; - subinfo->start = start; - lastinsert = -1; - id = groupinfo[start].group; - newid = strrchr(id, '/'); - idlen = strlen(id); - if (newid) - cmplen = newid-id; - else - cmplen = idlen; - d(printf("%d scanning level %s\n", start, id)); - for (i=start;ilen; - g_array_append_val(rowsort, rowinfo); -#ifdef DEBUG - total++; -#endif - } else if (newidlen > idlen) { - /* must be a new subtree */ - d(printf("%d checking subtree instead\n", start)); - newsub = etsv_sort_build_subset(etsv, groupinfo, i, &i); - d(printf("found %d nodes in subtree\n", newsub->rowsort->len)); - g_array_index(rowsort, struct _rowinfo, lastinsert).subinfo = newsub; - } else { - i--; - break; - } - } - if (end) - *end = i; - d(printf("finished level %s start was %d end was %d\n", id, start, i)); - return subinfo; -} - -/* sort each level, and then sort each level below that level (once we know - where the sublevel will fit in the overall list) */ -static int -etsv_sort_subset(ETableSortedVariable *etsv, struct _subinfo *subinfo, int startoffset) -{ - GArray *rowsort = subinfo->rowsort; - ETableSubset *etss = E_TABLE_SUBSET(etsv); - int offset, i; - - d(printf("sorting subset start %d rows %d\n", startoffset, rowsort->len)); - - /* first, sort the actual data */ - qsort(rowsort->data, rowsort->len, sizeof(struct _rowinfo), qsort_callback_complex); - - /* then put it back in the map table, where appropriate */ - offset = startoffset; - for (i=0;ilen;i++) { - struct _rowinfo *rowinfo; - - d(printf("setting offset %d\n", offset)); - - rowinfo = &g_array_index(rowsort, struct _rowinfo, i); - etss->map_table[offset] = rowinfo->row; - if (rowinfo->subinfo) { - offset = etsv_sort_subset(etsv, rowinfo->subinfo, offset+1); - } else - offset += 1; - } - d(printf("end sort subset start %d\n", startoffset)); - - return offset; -} - -static void -etsv_sort_free_subset(ETableSortedVariable *etsv, struct _subinfo *subinfo) -{ - int i; - - for (i=0;irowsort->len;i++) { - struct _rowinfo *rowinfo; - - rowinfo = &g_array_index(subinfo->rowsort, struct _rowinfo, i); - if (rowinfo->subinfo) - etsv_sort_free_subset(etsv, rowinfo->subinfo); - } - g_array_free(subinfo->rowsort, TRUE); - g_free(subinfo); -} - -static int -sort_groups_compare(const void *ap, const void *bp) -{ - struct _group_info *a = (struct _group_info *)ap; - struct _group_info *b = (struct _group_info *)bp; - - return strcmp(a->group, b->group); -} - -#ifdef DEBUG -static void -print_id(int key, int val, void *data) -{ - printf("gained id %d\n", key); -} -#endif - -/* use the sort group to select subsorts */ -static void -etsv_sort_by_group(ETableSortedVariable *etsv) -{ - ETableSubset *etss = E_TABLE_SUBSET(etsv); - int rows = E_TABLE_SUBSET(etsv)->n_map; - struct _group_info *groups; - struct _subinfo *subinfo; - int i; -#ifdef DEBUG - GHashTable *members = g_hash_table_new(0, 0); - - total = 0; - total_sorted = 0; -#endif - - d(printf("sorting %d rows\n", rows)); - - if (rows == 0) - return; - - /* get the subset rows */ - groups = g_malloc(sizeof(struct _group_info) * rows); - for (i=0;imap_table[i]; - groups[i].group = g_strdup(e_table_model_row_sort_group(etss->source, groups[i].row)); -#ifdef DEBUG - g_hash_table_insert(members, etss->map_table[i], 1); - etss->map_table[i] = 0; -#endif - } - - /* sort the group info */ - qsort(groups, rows, sizeof(struct _group_info), sort_groups_compare); - - d(printf("sorted groups:\n"); - for (i=0;imap_table[i]) == 0) { - printf("lost id %d\n", etss->map_table[i]); - } - g_hash_table_remove(members, etss->map_table[i]); - } - g_hash_table_foreach(members, print_id, 0); - - printf("total rows = %d, total processed = %d, total sorted = %d\n", rows, total, total_sorted); -#endif - -} - static void etsv_sort(ETableSortedVariable *etsv) { ETableSubset *etss = E_TABLE_SUBSET(etsv); static int reentering = 0; - int rows = E_TABLE_SUBSET(etsv)->n_map; - int total_rows; - int i; - int j; - int cols; if (reentering) return; reentering = 1; e_table_model_pre_change(E_TABLE_MODEL(etsv)); - total_rows = e_table_model_row_count(E_TABLE_SUBSET(etsv)->source); - cols = e_table_sort_info_sorting_get_count(etsv->sort_info); - cols_closure = cols; - etsv_closure = etsv; - vals_closure = g_new(void *, total_rows * cols); - ascending_closure = g_new(int, cols); - compare_closure = g_new(GCompareFunc, cols); - for (j = 0; j < cols; j++) { - ETableSortColumn column = e_table_sort_info_sorting_get_nth(etsv->sort_info, j); - ETableCol *col; - col = e_table_header_get_column_by_col_idx(etsv->full_header, column.column); - if (col == NULL) - col = e_table_header_get_column (etsv->full_header, e_table_header_count (etsv->full_header) - 1); - for (i = 0; i < rows; i++) { -#if 0 - if( !(i & 0xff) ) { - while(gtk_events_pending()) - gtk_main_iteration(); - } -#endif - vals_closure[E_TABLE_SUBSET(etsv)->map_table[i] * cols + j] = e_table_model_value_at (etss->source, col->col_idx, E_TABLE_SUBSET(etsv)->map_table[i]); - } - compare_closure[j] = col->compare; - ascending_closure[j] = column.ascending; - } + e_table_sorting_utils_sort(etss->source, etsv->sort_info, etsv->full_header, etss->map_table, etss->n_map); - if (e_table_model_has_sort_group(etss->source)) { - etsv_sort_by_group(etsv); - } else { - qsort(E_TABLE_SUBSET(etsv)->map_table, rows, sizeof(int), qsort_callback); - } - g_free(vals_closure); - g_free(ascending_closure); - g_free(compare_closure); e_table_model_changed (E_TABLE_MODEL(etsv)); reentering = 0; } -- cgit v1.2.3