diff options
33 files changed, 827 insertions, 344 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index 0166aeddaa..c8c6f279b7 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,14 @@ +2000-04-06 Christopher James Lahey <clahey@helixcode.com> + + * test-cols.c, test-table.c: Got rid of some warnings. + + * e-table-group-container.c, e-table-group-container.h, + e-table-group-leaf.c, e-table-group-leaf.h, e-table-group.c, + e-table-group.h, e-table-header-item.c, e-table-header-item.h, + e-table-sort-info.c, e-table-sort-info.h, + e-table-sorted-variable.c, e-table-sorted-variable.h, e-table.c, + e-table.h: Changed ETableSortInfo to not use xml internally. + 2000-04-06 Miguel de Icaza <miguel@gnu.org> * e-cell-text.c: Killed ARG_EDITABLE. diff --git a/widgets/e-table/e-table-group-container.c b/widgets/e-table/e-table-group-container.c index d5de4cf847..f660cd01c3 100644 --- a/widgets/e-table/e-table-group-container.c +++ b/widgets/e-table/e-table-group-container.c @@ -3,7 +3,7 @@ * E-Table-Group.c: Implements the grouping objects for elements on a table * * Author: - * Chris Lahey (clahey@helixcode.com) + * Chris Lahey <clahey@helixcode.com> * Miguel de Icaza (miguel@gnu.org) * * Copyright 1999, 2000 Helix Code, Inc. @@ -88,6 +88,9 @@ etgc_destroy (GtkObject *object) if (etgc->ecol){ gtk_object_unref (GTK_OBJECT(etgc->ecol)); } + if (etgc->sort_info){ + gtk_object_unref (GTK_OBJECT(etgc->sort_info)); + } if (etgc->rect){ gtk_object_destroy (GTK_OBJECT(etgc->rect)); } @@ -196,13 +199,24 @@ void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules) + ETableModel *model, ETableSortInfo *sort_info, int n) { + ETableCol *col; + ETableSortColumn column = e_table_sort_info_grouping_get_nth(sort_info, n); + + if (column.column > e_table_header_count (full_header)) + col = e_table_header_get_columns (full_header)[e_table_header_count (full_header) - 1]; + else + col = e_table_header_get_columns (full_header)[column.column]; + e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model); - etgc->ecol = ecol; + etgc->ecol = col; gtk_object_ref (GTK_OBJECT(etgc->ecol)); - etgc->child_rules = child_rules; - etgc->ascending = ascending; + etgc->sort_info = sort_info; + gtk_object_ref (GTK_OBJECT(etgc->sort_info)); + etgc->n = n; + etgc->ascending = column.ascending; + etgc->font = gdk_font_load ("lucidasans-10"); if (!etgc->font){ @@ -252,18 +266,16 @@ e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContaine ETableGroup * e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, - int ascending, xmlNode *child_rules) + ETableModel *model, ETableSortInfo *sort_info, int n) { ETableGroupContainer *etgc; g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (ecol != NULL, NULL); etgc = gtk_type_new (e_table_group_container_get_type ()); e_table_group_container_construct (parent, etgc, full_header, header, - model, ecol, ascending, child_rules); + model, sort_info, n); return E_TABLE_GROUP (etgc); } @@ -581,7 +593,7 @@ etgc_add (ETableGroup *etg, gint row) "fill_color", "black", NULL); child = e_table_group_new (GNOME_CANVAS_GROUP (etgc), etg->full_header, - etg->header, etg->model, etgc->child_rules); + etg->header, etg->model, etgc->sort_info, etgc->n + 1); gtk_signal_connect (GTK_OBJECT (child), "row_selection", GTK_SIGNAL_FUNC (child_row_selection), etgc); child_node->child = child; @@ -795,8 +807,10 @@ etgc_reflow (GnomeCanvasItem *item, gint flags) ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(item); gboolean frozen; - gtk_object_get (GTK_OBJECT(etgc), "frozen", &frozen, NULL); - + gtk_object_get (GTK_OBJECT(etgc), + "frozen", &frozen, + NULL); + if (frozen){ etgc->idle = 0; return; diff --git a/widgets/e-table/e-table-group-container.h b/widgets/e-table/e-table-group-container.h index 4070624456..50424009f2 100644 --- a/widgets/e-table/e-table-group-container.h +++ b/widgets/e-table/e-table-group-container.h @@ -36,7 +36,8 @@ typedef struct { gdouble width, height; - void *child_rules; + ETableSortInfo *sort_info; + int n; gint idle; @@ -51,11 +52,11 @@ typedef struct { } ETableGroupContainerClass; ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules); + ETableModel *model, ETableSortInfo *sort_info, int n); void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules); + ETableModel *model, ETableSortInfo *sort_info, int n); GtkType e_table_group_container_get_type (void); diff --git a/widgets/e-table/e-table-group-leaf.c b/widgets/e-table/e-table-group-leaf.c index 0c14129031..dcb606d3b8 100644 --- a/widgets/e-table/e-table-group-leaf.c +++ b/widgets/e-table/e-table-group-leaf.c @@ -51,10 +51,9 @@ e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending) + ETableSortInfo *sort_info) { - etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new (model, col, ascending, e_table_header_get_column(full_header, col)->compare)); + etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new (model, full_header, sort_info)); e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model); } @@ -62,8 +61,7 @@ ETableGroup * e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending) + ETableSortInfo *sort_info) { ETableGroupLeaf *etgl; @@ -72,7 +70,7 @@ e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_heade etgl = gtk_type_new (e_table_group_leaf_get_type ()); e_table_group_leaf_construct (parent, etgl, full_header, - header, model, col, ascending); + header, model, sort_info); return E_TABLE_GROUP (etgl); } diff --git a/widgets/e-table/e-table-group-leaf.h b/widgets/e-table/e-table-group-leaf.h index 6ffd9066d1..1be5969af4 100644 --- a/widgets/e-table/e-table-group-leaf.h +++ b/widgets/e-table/e-table-group-leaf.h @@ -34,8 +34,7 @@ ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending); + ETableSortInfo *sort_info); GtkType e_table_group_leaf_get_type (void); #endif /* _E_TABLE_GROUP_LEAF_H_ */ diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c index 9d4b899dc2..a829d83546 100644 --- a/widgets/e-table/e-table-group.c +++ b/widgets/e-table/e-table-group.c @@ -15,9 +15,7 @@ #include "e-table-group-leaf.h" #include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <gnome-xml/parser.h> #include "e-util/e-util.h" -#include "e-util/e-xml-utils.h" #define TITLE_HEIGHT 16 #define GROUP_INDENT 10 @@ -84,24 +82,15 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - xmlNode *rules) + ETableSortInfo *sort_info, + int n) { - int column; - int ascending; - g_return_val_if_fail (model != NULL, NULL); - - column = e_xml_get_integer_prop_by_name (rules, "column"); - ascending = e_xml_get_integer_prop_by_name (rules, "ascending"); - - if (rules && !xmlStrcmp(rules->name, "group")) { - ETableCol *col; - if (column > e_table_header_count (full_header)) - return e_table_group_leaf_new (parent, full_header, header, model, column, ascending); - col = e_table_header_get_columns (full_header)[column]; - return e_table_group_container_new (parent, full_header, header, model, col, ascending, rules->childs); + + if (n < e_table_sort_info_grouping_get_count(sort_info)) { + return e_table_group_container_new (parent, full_header, header, model, sort_info, n); } else { - return e_table_group_leaf_new (parent, full_header, header, model, column, ascending); + return e_table_group_leaf_new (parent, full_header, header, model, sort_info); } return NULL; } diff --git a/widgets/e-table/e-table-group.h b/widgets/e-table/e-table-group.h index 35b3069b20..877f38cf3f 100644 --- a/widgets/e-table/e-table-group.h +++ b/widgets/e-table/e-table-group.h @@ -3,9 +3,9 @@ #define _E_TABLE_GROUP_H_ #include <libgnomeui/gnome-canvas.h> -#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-table-sort-info.h" #include "e-util/e-util.h" #define E_TABLE_GROUP_TYPE (e_table_group_get_type ()) @@ -78,7 +78,8 @@ ETableGroup *e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - xmlNode *rules); + ETableSortInfo *sort_info, + int n); void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, ETableHeader *full_header, diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index 77ed032999..966ad257ad 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -79,6 +79,8 @@ ethi_destroy (GtkObject *object){ if (ethi->sort_info){ if (ethi->sort_info_changed_id) gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->sort_info_changed_id); + if (ethi->group_info_changed_id) + gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->group_info_changed_id); gtk_object_unref (GTK_OBJECT(ethi->sort_info)); } @@ -210,12 +212,16 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) if (ethi->sort_info){ if (ethi->sort_info_changed_id) gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->sort_info_changed_id); + if (ethi->group_info_changed_id) + gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->group_info_changed_id); gtk_object_unref (GTK_OBJECT(ethi->sort_info)); } ethi->sort_info = GTK_VALUE_POINTER (*arg); gtk_object_ref (GTK_OBJECT(ethi->sort_info)); ethi->sort_info_changed_id = gtk_signal_connect (GTK_OBJECT(ethi->sort_info), "sort_info_changed", - GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); + GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); + ethi->group_info_changed_id = gtk_signal_connect (GTK_OBJECT(ethi->sort_info), "group_info_changed", + GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); break; } @@ -603,7 +609,6 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width int x1, x2; int col; GHashTable *arrows = g_hash_table_new (NULL, NULL); - xmlNode *node; gint group_indent = 0; #if 0 @@ -612,24 +617,26 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width #endif if (ethi->sort_info) { - xmlNode *grouping; - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); - for (node = grouping->childs; node && strcmp (node->name, "leaf"); node = node->childs) { + int length = e_table_sort_info_grouping_get_count(ethi->sort_info); + int i; + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); group_indent ++; g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); } - if (node) + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } } ethi->group_indent_width = group_indent * GROUP_INDENT; @@ -767,8 +774,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) int col_width; GdkPixmap *pixmap; GdkGC *gc; + int group_indent = 0; GHashTable *arrows = g_hash_table_new (NULL, NULL); - xmlNode *node; ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); if (ethi->drag_col < ethi->eth->frozen_count && ethi->drag_col >= 0){ @@ -780,23 +787,26 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) if (ethi->sort_info) { - xmlNode *grouping; - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); - for (node = grouping->childs; node && strcmp (node->name, "leaf"); node = node->childs) { + int length = e_table_sort_info_grouping_get_count(ethi->sort_info); + int i; + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); + group_indent ++; g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); } - if (node) + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } } list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); @@ -927,36 +937,46 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) } else if (ethi->maybe_drag && ethi->sort_info) { ETableCol *col; int model_col; - xmlNode *node; - xmlNode *grouping; - - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); + int length; + int i; + int found = FALSE; col = e_table_header_get_column (ethi->eth, ethi_find_col_by_x (ethi, e->button.x)); model_col = col->col_idx; - for (node = grouping->childs; node->childs && strcmp (node->name, "leaf"); node = node->childs) { - if (model_col == e_xml_get_integer_prop_by_name (node, "column")){ - int ascending = e_xml_get_integer_prop_by_name (node, "ascending"); + + length = e_table_sort_info_grouping_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); + if (model_col == column.column){ + int ascending = column.ascending; ascending = ! ascending; - e_xml_set_integer_prop_by_name (node, "ascending", ascending); + column.ascending = ascending; + e_table_sort_info_grouping_set_nth(ethi->sort_info, i, column); + found = 1; break; } } - if (!node){ - } - if (node && !strcmp (node->name, "leaf")){ - if (model_col == e_xml_get_integer_prop_by_name (node, "column")){ - int ascending = e_xml_get_integer_prop_by_name (node, "ascending"); - ascending = ! ascending; - e_xml_set_integer_prop_by_name (node, "ascending", ascending); - } else { - e_xml_set_integer_prop_by_name (node, "ascending", 1); - e_xml_set_integer_prop_by_name (node, "column", model_col); + if (!found) { + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); + if (model_col == column.column){ + int ascending = column.ascending; + ascending = ! ascending; + column.ascending = ascending; + e_table_sort_info_sorting_set_nth(ethi->sort_info, i, column); + found = 1; + break; + } } } - e_table_sort_info_changed (ethi->sort_info); + if (!found) { + ETableSortColumn column = { model_col, 1 }; + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + if (length == 0) + length++; + e_table_sort_info_sorting_set_nth(ethi->sort_info, length - 1, column); + } } if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); @@ -996,7 +1016,7 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); - gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_POINTER, + gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_OBJECT, GTK_ARG_WRITABLE, ARG_SORT_INFO); /* @@ -1030,6 +1050,7 @@ ethi_init (GnomeCanvasItem *item) ethi->sort_info = NULL; ethi->sort_info_changed_id = 0; + ethi->group_info_changed_id = 0; ethi->group_indent_width = 0; } diff --git a/widgets/e-table/e-table-header-item.h b/widgets/e-table/e-table-header-item.h index add488d2f7..6aeefa885d 100644 --- a/widgets/e-table/e-table-header-item.h +++ b/widgets/e-table/e-table-header-item.h @@ -48,7 +48,7 @@ typedef struct { int click_x, click_y; int drag_col, drag_mark; guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id; - guint sort_info_changed_id; + guint sort_info_changed_id, group_info_changed_id; GnomeCanvasItem *drag_mark_item, *remove_item; GdkBitmap *stipple; diff --git a/widgets/e-table/e-table-sort-info.c b/widgets/e-table/e-table-sort-info.c index bf90a13602..b33784c140 100644 --- a/widgets/e-table/e-table-sort-info.c +++ b/widgets/e-table/e-table-sort-info.c @@ -9,7 +9,6 @@ */ #include <config.h> #include <gtk/gtksignal.h> -#include <gnome-xml/tree.h> #include "e-table-sort-info.h" #include "e-util/e-util.h" @@ -22,51 +21,47 @@ static GtkObjectClass *e_table_sort_info_parent_class; enum { SORT_INFO_CHANGED, + GROUP_INFO_CHANGED, LAST_SIGNAL }; static guint e_table_sort_info_signals [LAST_SIGNAL] = { 0, }; -enum { - ARG_0, - ARG_GROUPING -}; - static void -etsi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +etsi_destroy (GtkObject *object) { ETableSortInfo *etsi; - etsi = E_TABLE_SORT_INFO (o); - - switch (arg_id){ - case ARG_GROUPING: - etsi->grouping = GTK_VALUE_POINTER (*arg); - break; - } + etsi = E_TABLE_SORT_INFO (object); + + if (etsi->groupings) + g_free(etsi->groupings); + if (etsi->sortings) + g_free(etsi->sortings); } static void -etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_table_sort_info_init (ETableSortInfo *info) { - ETableSortInfo *etsi; - - etsi = E_TABLE_SORT_INFO (o); - - switch (arg_id){ - case ARG_GROUPING: - GTK_VALUE_POINTER (*arg) = etsi->grouping; - break; - } + info->group_count = 0; + info->groupings = NULL; + info->sort_count = 0; + info->sortings = NULL; + info->frozen = 0; + info->sort_info_changed = 0; + info->group_info_changed = 0; } static void -e_table_sort_info_class_init (GtkObjectClass *object_class) +e_table_sort_info_class_init (ETableSortInfoClass *klass) { + GtkObjectClass *object_class; + e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class = GTK_OBJECT_CLASS(klass); - object_class->set_arg = etsi_set_arg; - object_class->get_arg = etsi_get_arg; + object_class->destroy = etsi_destroy; e_table_sort_info_signals [SORT_INFO_CHANGED] = gtk_signal_new ("sort_info_changed", @@ -76,25 +71,154 @@ e_table_sort_info_class_init (GtkObjectClass *object_class) gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); - gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); + e_table_sort_info_signals [GROUP_INFO_CHANGED] = + gtk_signal_new ("group_info_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableSortInfoClass, group_info_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); - gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER, - GTK_ARG_READWRITE, ARG_GROUPING); + klass->sort_info_changed = NULL; + klass->group_info_changed = NULL; + + gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); } E_MAKE_TYPE(e_table_sort_info, "ETableSortInfo", ETableSortInfo, - e_table_sort_info_class_init, NULL, PARENT_TYPE); + e_table_sort_info_class_init, e_table_sort_info_init, PARENT_TYPE); -void -e_table_sort_info_changed (ETableSortInfo *e_table_sort_info) +static void +e_table_sort_info_sort_info_changed (ETableSortInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); + + if (info->frozen) { + info->sort_info_changed = 1; + } else { + gtk_signal_emit (GTK_OBJECT (info), + e_table_sort_info_signals [SORT_INFO_CHANGED]); + } +} + +static void +e_table_sort_info_group_info_changed (ETableSortInfo *info) { - g_return_if_fail (e_table_sort_info != NULL); - g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info)); + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); - gtk_signal_emit (GTK_OBJECT (e_table_sort_info), - e_table_sort_info_signals [SORT_INFO_CHANGED]); + if (info->frozen) { + info->group_info_changed = 1; + } else { + gtk_signal_emit (GTK_OBJECT (info), + e_table_sort_info_signals [GROUP_INFO_CHANGED]); + } +} + +void +e_table_sort_info_freeze (ETableSortInfo *info) +{ + info->frozen = 1; +} + +void +e_table_sort_info_thaw (ETableSortInfo *info) +{ + info->frozen = 0; + if (info->sort_info_changed) { + info->sort_info_changed = 0; + e_table_sort_info_sort_info_changed(info); + } + if (info->group_info_changed) { + info->group_info_changed = 0; + e_table_sort_info_group_info_changed(info); + } +} + + +guint +e_table_sort_info_grouping_get_count (ETableSortInfo *info) +{ + return info->group_count; +} + +void +e_table_sort_info_grouping_truncate (ETableSortInfo *info, int length) +{ + if (length < info->group_count) { + info->group_count = length; + } + if (length > info->group_count) { + info->groupings = g_realloc(info->groupings, length * sizeof(ETableSortColumn)); + info->group_count = length; + } + e_table_sort_info_group_info_changed(info); +} + +ETableSortColumn +e_table_sort_info_grouping_get_nth (ETableSortInfo *info, int n) +{ + if (n < info->group_count) { + return info->groupings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +void +e_table_sort_info_grouping_set_nth (ETableSortInfo *info, int n, ETableSortColumn column) +{ + if (n >= info->group_count) { + e_table_sort_info_grouping_truncate(info, n + 1); + } + info->groupings[n] = column; + e_table_sort_info_group_info_changed(info); +} + + +guint +e_table_sort_info_sorting_get_count (ETableSortInfo *info) +{ + return info->sort_count; +} + +void +e_table_sort_info_sorting_truncate (ETableSortInfo *info, int length) +{ + if (length < info->sort_count) { + info->sort_count = length; + } + if (length > info->sort_count) { + info->sortings = g_realloc(info->sortings, length * sizeof(ETableSortColumn)); + info->sort_count = length; + } + e_table_sort_info_sort_info_changed(info); } +ETableSortColumn +e_table_sort_info_sorting_get_nth (ETableSortInfo *info, int n) +{ + if (n < info->sort_count) { + return info->sortings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +void +e_table_sort_info_sorting_set_nth (ETableSortInfo *info, int n, ETableSortColumn column) +{ + if (n >= info->sort_count) { + e_table_sort_info_sorting_truncate(info, n + 1); + } + info->sortings[n] = column; + e_table_sort_info_sort_info_changed(info); +} + + ETableSortInfo * e_table_sort_info_new (void) { diff --git a/widgets/e-table/e-table-sort-info.h b/widgets/e-table/e-table-sort-info.h index 0fc4cd52ef..6446230116 100644 --- a/widgets/e-table/e-table-sort-info.h +++ b/widgets/e-table/e-table-sort-info.h @@ -1,4 +1,3 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SORT_INFO_H_ #define _E_TABLE_SORT_INFO_H_ @@ -11,10 +10,24 @@ #define E_IS_TABLE_SORT_INFO(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORT_INFO_TYPE)) #define E_IS_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORT_INFO_TYPE)) +typedef struct _ETableSortColumn ETableSortColumn; + +struct _ETableSortColumn { + guint column : 31; + guint ascending : 1; +}; + typedef struct { GtkObject base; - - xmlNode *grouping; + + gint group_count; + ETableSortColumn *groupings; + gint sort_count; + ETableSortColumn *sortings; + + guint frozen : 1; + guint sort_info_changed : 1; + guint group_info_changed : 1; } ETableSortInfo; typedef struct { @@ -23,15 +36,25 @@ typedef struct { /* * Signals */ - void (*sort_info_changed) (ETableSortInfo *etm); + void (*sort_info_changed) (ETableSortInfo *info); + void (*group_info_changed) (ETableSortInfo *info); } ETableSortInfoClass; -GtkType e_table_sort_info_get_type (void); +GtkType e_table_sort_info_get_type (void); + +void e_table_sort_info_freeze (ETableSortInfo *info); +void e_table_sort_info_thaw (ETableSortInfo *info); + +guint e_table_sort_info_grouping_get_count (ETableSortInfo *info); +void e_table_sort_info_grouping_truncate (ETableSortInfo *info, int length); +ETableSortColumn e_table_sort_info_grouping_get_nth (ETableSortInfo *info, int n); +void e_table_sort_info_grouping_set_nth (ETableSortInfo *info, int n, ETableSortColumn column); + +guint e_table_sort_info_sorting_get_count (ETableSortInfo *info); +void e_table_sort_info_sorting_truncate (ETableSortInfo *info, int length); +ETableSortColumn e_table_sort_info_sorting_get_nth (ETableSortInfo *info, int n); +void e_table_sort_info_sorting_set_nth (ETableSortInfo *info, int n, ETableSortColumn column); -/* - * Routines for emitting signals on the e_table - */ -void e_table_sort_info_changed (ETableSortInfo *e_table_sort_info); -ETableSortInfo *e_table_sort_info_new (void); +ETableSortInfo *e_table_sort_info_new (void); #endif /* _E_TABLE_SORT_INFO_H_ */ diff --git a/widgets/e-table/e-table-sorted-variable.c b/widgets/e-table/e-table-sorted-variable.c index 153295fc78..a1a9a35a09 100644 --- a/widgets/e-table/e-table-sorted-variable.c +++ b/widgets/e-table/e-table-sorted-variable.c @@ -41,6 +41,11 @@ etsv_destroy (GtkObject *object) 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) + gtk_object_unref(GTK_OBJECT(etsv->full_header)); GTK_OBJECT_CLASS (etsv_parent_class)->destroy (object); } @@ -67,17 +72,33 @@ etsv_add (ETableSubsetVariable *etssv, ETableSubset *etss = E_TABLE_SUBSET(etssv); ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE(etssv); int i; - int col = etsv->sort_col; - GCompareFunc comp = etsv->compare; - gint ascending = etsv->ascending; + ETableCol *last_col = NULL; + void *val = NULL; - void *val = e_table_model_value_at (etss->source, col, row); - /* FIXME: binary search anyone? */ for (i = 0; i < etss->n_map; i++){ - int comp_val = (*comp)(val, e_table_model_value_at (etss->source, col, etss->map_table[i])); - if ((ascending && comp_val < 0) || ((!ascending) && comp_val > 0)) + int j; + int sort_count = e_table_sort_info_sorting_get_count(etsv->sort_info); + int comp_val = 0; + int ascending = 1; + for (j = 0; j < sort_count; j++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(etsv->sort_info, j); + ETableCol *col; + if (column.column > e_table_header_count (etsv->full_header)) + col = e_table_header_get_columns (etsv->full_header)[e_table_header_count (etsv->full_header) - 1]; + else + col = e_table_header_get_columns (etsv->full_header)[column.column]; + if (last_col != col) + val = e_table_model_value_at (etss->source, col->col_idx, row); + last_col = col; + comp_val = (*col->compare)(val, e_table_model_value_at (etss->source, col->col_idx, etss->map_table[i])); + ascending = column.ascending; + if (comp_val != 0) + break; + } + if (((ascending && comp_val < 0) || ((!ascending) && comp_val > 0))) break; + if (comp_val == 0) if ((ascending && row < etss->map_table[i]) || ((!ascending) && row > etss->map_table[i])) break; @@ -95,7 +116,7 @@ etsv_add (ETableSubsetVariable *etssv, } ETableModel * -e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompareFunc compare) +e_table_sorted_variable_new (ETableModel *source, ETableHeader *full_header, ETableSortInfo *sort_info) { ETableSortedVariable *etsv = gtk_type_new (E_TABLE_SORTED_VARIABLE_TYPE); ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE (etsv); @@ -105,9 +126,10 @@ e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompa return NULL; } - etsv->sort_col = col; - etsv->ascending = ascending; - etsv->compare = compare; + etsv->sort_info = sort_info; + gtk_object_ref(GTK_OBJECT(etsv->sort_info)); + 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); @@ -142,10 +164,8 @@ etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedV { ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv); if (!E_TABLE_MODEL(etsv)->frozen){ - if (col == etsv->sort_col){ - if (e_table_subset_variable_remove(etssv, row)) - e_table_subset_variable_add (etssv, row); - } + if (e_table_subset_variable_remove(etssv, row)) + e_table_subset_variable_add (etssv, row); } } diff --git a/widgets/e-table/e-table-sorted-variable.h b/widgets/e-table/e-table-sorted-variable.h index cf188acd4a..1a22679040 100644 --- a/widgets/e-table/e-table-sorted-variable.h +++ b/widgets/e-table/e-table-sorted-variable.h @@ -5,6 +5,8 @@ #include <gtk/gtkobject.h> #include "e-table-model.h" #include "e-table-subset-variable.h" +#include "e-table-sort-info.h" +#include "e-table-header.h" #define E_TABLE_SORTED_VARIABLE_TYPE (e_table_sorted_variable_get_type ()) #define E_TABLE_SORTED_VARIABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_VARIABLE_TYPE, ETableSortedVariable)) @@ -15,9 +17,9 @@ typedef struct { ETableSubsetVariable base; - short sort_col; - int ascending; - GCompareFunc compare; + ETableSortInfo *sort_info; + + ETableHeader *full_header; int table_model_changed_id; int table_model_row_changed_id; @@ -29,6 +31,6 @@ typedef struct { } ETableSortedVariableClass; GtkType e_table_sorted_variable_get_type (void); -ETableModel *e_table_sorted_variable_new (ETableModel *etm, int col, int ascending, GCompareFunc compare); +ETableModel *e_table_sorted_variable_new (ETableModel *etm, ETableHeader *header, ETableSortInfo *sort_info); #endif /* _E_TABLE_SORTED_VARIABLE_H_ */ diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 7360666d06..1dc931474d 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -60,6 +60,9 @@ et_destroy (GtkObject *object) if (et->sort_info_change_id) gtk_signal_disconnect (GTK_OBJECT (et->sort_info), et->sort_info_change_id); + if (et->group_info_change_id) + gtk_signal_disconnect (GTK_OBJECT (et->sort_info), + et->group_info_change_id); gtk_object_unref (GTK_OBJECT (et->model)); gtk_object_unref (GTK_OBJECT (et->full_header)); @@ -85,6 +88,7 @@ e_table_init (GtkObject *object) e_table->sort_info = NULL; e_table->sort_info_change_id = 0; + e_table->group_info_change_id = 0; e_table->draw_grid = 1; e_table->draw_focus = 1; @@ -140,6 +144,7 @@ e_table_setup_header (ETable *e_table) { xmlNode *root; xmlNode *grouping; + int i; e_table->header_canvas = GNOME_CANVAS (e_canvas_new ()); gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); @@ -152,13 +157,27 @@ e_table_setup_header (ETable *e_table) gtk_object_ref (GTK_OBJECT (e_table->sort_info)); gtk_object_sink (GTK_OBJECT (e_table->sort_info)); - gtk_object_set (GTK_OBJECT (e_table->sort_info), - "grouping", grouping, - NULL); + i = 0; + for (grouping = grouping->childs; grouping && strcmp (grouping->name, "leaf"); grouping = grouping->childs) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, "column"); + column.ascending = e_xml_get_integer_prop_by_name (grouping, "ascending"); + e_table_sort_info_grouping_set_nth(e_table->sort_info, i++, column); + } + i = 0; + for (; grouping; grouping = grouping->childs) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, "column"); + column.ascending = e_xml_get_integer_prop_by_name (grouping, "ascending"); + e_table_sort_info_sorting_set_nth(e_table->sort_info, i++, column); + } e_table->sort_info_change_id = gtk_signal_connect (GTK_OBJECT (e_table->sort_info), "sort_info_changed", GTK_SIGNAL_FUNC (sort_info_changed), e_table); + e_table->group_info_change_id = + gtk_signal_connect (GTK_OBJECT (e_table->sort_info), "group_info_changed", + GTK_SIGNAL_FUNC (sort_info_changed), e_table); e_table->header_item = gnome_canvas_item_new ( gnome_canvas_root (e_table->header_canvas), @@ -631,8 +650,8 @@ changed_idle (gpointer data) et->full_header, et->header, et->model, - e_xml_get_child_by_name (xmlDocGetRootElement (et->specification), - "grouping")->childs); + et->sort_info, + 0); gtk_signal_connect (GTK_OBJECT (et->group), "row_selection", GTK_SIGNAL_FUNC (group_row_selection), et); e_table_fill_table (et, et->model); @@ -687,7 +706,7 @@ et_table_cell_changed (ETableModel *table_model, int view_col, int row, ETable * static void e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, xmlNode *xml_grouping) + ETableModel *model) { e_table->table_canvas = GNOME_CANVAS (e_canvas_new ()); gtk_signal_connect ( @@ -703,7 +722,8 @@ e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *h full_header, header, model, - xml_grouping->childs); + e_table->sort_info, + 0); gtk_signal_connect (GTK_OBJECT(e_table->group), "row_selection", GTK_SIGNAL_FUNC(group_row_selection), e_table); @@ -763,7 +783,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, e_table->header = e_table_make_header (e_table, full_header, xmlColumns); e_table_setup_header (e_table); - e_table_setup_table (e_table, full_header, e_table->header, etm, xmlGrouping); + e_table_setup_table (e_table, full_header, e_table->header, etm); e_table_fill_table (e_table, etm); vbox = gtk_vbox_new (FALSE, 0); @@ -853,11 +873,32 @@ et_build_column_spec (ETable *e_table) static xmlNode * et_build_grouping_spec (ETable *e_table) { + xmlNode *node; xmlNode *grouping; xmlNode *root; + int i; + int length; root = xmlDocGetRootElement (e_table->specification); - grouping = xmlCopyNode (e_xml_get_child_by_name(root, "grouping"), TRUE); + xmlCopyNode (e_xml_get_child_by_name(root, "grouping"), TRUE); + grouping = xmlNewNode (NULL, "grouping"); + node = grouping; + length = e_table_sort_info_grouping_get_count(e_table->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(e_table->sort_info, i); + xmlNode *new_node = xmlNewChild(node, NULL, "group", NULL); + e_xml_set_integer_prop_by_name (new_node, "column", column.column); + e_xml_set_integer_prop_by_name (new_node, "ascending", column.ascending); + node = new_node; + } + length = e_table_sort_info_sorting_get_count(e_table->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(e_table->sort_info, i); + xmlNode *new_node = xmlNewChild(node, NULL, "leaf", NULL); + e_xml_set_integer_prop_by_name (new_node, "column", column.column); + e_xml_set_integer_prop_by_name (new_node, "ascending", column.ascending); + node = new_node; + } return grouping; } diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index 3cca3422b3..39333f159a 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -34,6 +34,7 @@ typedef struct { int table_cell_change_id; int sort_info_change_id; + int group_info_change_id; GnomeCanvas *header_canvas, *table_canvas; diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c index 15e07d94da..f60d22d915 100644 --- a/widgets/e-table/test-cols.c +++ b/widgets/e-table/test-cols.c @@ -9,6 +9,7 @@ #include <string.h> #include <gnome.h> #include "e-util/e-canvas-utils.h" +#include "e-util/e-canvas.h" #include "e-util/e-cursors.h" #include "e-util/e-util.h" #include "e-table-simple.h" diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c index 0fd086681c..2ff657c863 100644 --- a/widgets/e-table/test-table.c +++ b/widgets/e-table/test-table.c @@ -17,6 +17,7 @@ #include "e-table-item.h" #include "e-cell-text.h" #include "e-table.h" +#include "e-table-config.h" #include "table-test.h" @@ -346,7 +347,7 @@ do_e_table_demo (const char *spec) gtk_widget_show (window); if (getenv ("TEST")){ - e_table_do_gui_config (NULL, e_table); + e_table_do_gui_config (NULL, E_TABLE(e_table)); } } diff --git a/widgets/table/e-table-group-container.c b/widgets/table/e-table-group-container.c index d5de4cf847..f660cd01c3 100644 --- a/widgets/table/e-table-group-container.c +++ b/widgets/table/e-table-group-container.c @@ -3,7 +3,7 @@ * E-Table-Group.c: Implements the grouping objects for elements on a table * * Author: - * Chris Lahey (clahey@helixcode.com) + * Chris Lahey <clahey@helixcode.com> * Miguel de Icaza (miguel@gnu.org) * * Copyright 1999, 2000 Helix Code, Inc. @@ -88,6 +88,9 @@ etgc_destroy (GtkObject *object) if (etgc->ecol){ gtk_object_unref (GTK_OBJECT(etgc->ecol)); } + if (etgc->sort_info){ + gtk_object_unref (GTK_OBJECT(etgc->sort_info)); + } if (etgc->rect){ gtk_object_destroy (GTK_OBJECT(etgc->rect)); } @@ -196,13 +199,24 @@ void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules) + ETableModel *model, ETableSortInfo *sort_info, int n) { + ETableCol *col; + ETableSortColumn column = e_table_sort_info_grouping_get_nth(sort_info, n); + + if (column.column > e_table_header_count (full_header)) + col = e_table_header_get_columns (full_header)[e_table_header_count (full_header) - 1]; + else + col = e_table_header_get_columns (full_header)[column.column]; + e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model); - etgc->ecol = ecol; + etgc->ecol = col; gtk_object_ref (GTK_OBJECT(etgc->ecol)); - etgc->child_rules = child_rules; - etgc->ascending = ascending; + etgc->sort_info = sort_info; + gtk_object_ref (GTK_OBJECT(etgc->sort_info)); + etgc->n = n; + etgc->ascending = column.ascending; + etgc->font = gdk_font_load ("lucidasans-10"); if (!etgc->font){ @@ -252,18 +266,16 @@ e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContaine ETableGroup * e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, - int ascending, xmlNode *child_rules) + ETableModel *model, ETableSortInfo *sort_info, int n) { ETableGroupContainer *etgc; g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (ecol != NULL, NULL); etgc = gtk_type_new (e_table_group_container_get_type ()); e_table_group_container_construct (parent, etgc, full_header, header, - model, ecol, ascending, child_rules); + model, sort_info, n); return E_TABLE_GROUP (etgc); } @@ -581,7 +593,7 @@ etgc_add (ETableGroup *etg, gint row) "fill_color", "black", NULL); child = e_table_group_new (GNOME_CANVAS_GROUP (etgc), etg->full_header, - etg->header, etg->model, etgc->child_rules); + etg->header, etg->model, etgc->sort_info, etgc->n + 1); gtk_signal_connect (GTK_OBJECT (child), "row_selection", GTK_SIGNAL_FUNC (child_row_selection), etgc); child_node->child = child; @@ -795,8 +807,10 @@ etgc_reflow (GnomeCanvasItem *item, gint flags) ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(item); gboolean frozen; - gtk_object_get (GTK_OBJECT(etgc), "frozen", &frozen, NULL); - + gtk_object_get (GTK_OBJECT(etgc), + "frozen", &frozen, + NULL); + if (frozen){ etgc->idle = 0; return; diff --git a/widgets/table/e-table-group-container.h b/widgets/table/e-table-group-container.h index 4070624456..50424009f2 100644 --- a/widgets/table/e-table-group-container.h +++ b/widgets/table/e-table-group-container.h @@ -36,7 +36,8 @@ typedef struct { gdouble width, height; - void *child_rules; + ETableSortInfo *sort_info; + int n; gint idle; @@ -51,11 +52,11 @@ typedef struct { } ETableGroupContainerClass; ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules); + ETableModel *model, ETableSortInfo *sort_info, int n); void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules); + ETableModel *model, ETableSortInfo *sort_info, int n); GtkType e_table_group_container_get_type (void); diff --git a/widgets/table/e-table-group-leaf.c b/widgets/table/e-table-group-leaf.c index 0c14129031..dcb606d3b8 100644 --- a/widgets/table/e-table-group-leaf.c +++ b/widgets/table/e-table-group-leaf.c @@ -51,10 +51,9 @@ e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending) + ETableSortInfo *sort_info) { - etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new (model, col, ascending, e_table_header_get_column(full_header, col)->compare)); + etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new (model, full_header, sort_info)); e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model); } @@ -62,8 +61,7 @@ ETableGroup * e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending) + ETableSortInfo *sort_info) { ETableGroupLeaf *etgl; @@ -72,7 +70,7 @@ e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_heade etgl = gtk_type_new (e_table_group_leaf_get_type ()); e_table_group_leaf_construct (parent, etgl, full_header, - header, model, col, ascending); + header, model, sort_info); return E_TABLE_GROUP (etgl); } diff --git a/widgets/table/e-table-group-leaf.h b/widgets/table/e-table-group-leaf.h index 6ffd9066d1..1be5969af4 100644 --- a/widgets/table/e-table-group-leaf.h +++ b/widgets/table/e-table-group-leaf.h @@ -34,8 +34,7 @@ ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - int col, - int ascending); + ETableSortInfo *sort_info); GtkType e_table_group_leaf_get_type (void); #endif /* _E_TABLE_GROUP_LEAF_H_ */ diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c index 9d4b899dc2..a829d83546 100644 --- a/widgets/table/e-table-group.c +++ b/widgets/table/e-table-group.c @@ -15,9 +15,7 @@ #include "e-table-group-leaf.h" #include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <gnome-xml/parser.h> #include "e-util/e-util.h" -#include "e-util/e-xml-utils.h" #define TITLE_HEIGHT 16 #define GROUP_INDENT 10 @@ -84,24 +82,15 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - xmlNode *rules) + ETableSortInfo *sort_info, + int n) { - int column; - int ascending; - g_return_val_if_fail (model != NULL, NULL); - - column = e_xml_get_integer_prop_by_name (rules, "column"); - ascending = e_xml_get_integer_prop_by_name (rules, "ascending"); - - if (rules && !xmlStrcmp(rules->name, "group")) { - ETableCol *col; - if (column > e_table_header_count (full_header)) - return e_table_group_leaf_new (parent, full_header, header, model, column, ascending); - col = e_table_header_get_columns (full_header)[column]; - return e_table_group_container_new (parent, full_header, header, model, col, ascending, rules->childs); + + if (n < e_table_sort_info_grouping_get_count(sort_info)) { + return e_table_group_container_new (parent, full_header, header, model, sort_info, n); } else { - return e_table_group_leaf_new (parent, full_header, header, model, column, ascending); + return e_table_group_leaf_new (parent, full_header, header, model, sort_info); } return NULL; } diff --git a/widgets/table/e-table-group.h b/widgets/table/e-table-group.h index 35b3069b20..877f38cf3f 100644 --- a/widgets/table/e-table-group.h +++ b/widgets/table/e-table-group.h @@ -3,9 +3,9 @@ #define _E_TABLE_GROUP_H_ #include <libgnomeui/gnome-canvas.h> -#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-table-sort-info.h" #include "e-util/e-util.h" #define E_TABLE_GROUP_TYPE (e_table_group_get_type ()) @@ -78,7 +78,8 @@ ETableGroup *e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, ETableModel *model, - xmlNode *rules); + ETableSortInfo *sort_info, + int n); void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, ETableHeader *full_header, diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index 77ed032999..966ad257ad 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -79,6 +79,8 @@ ethi_destroy (GtkObject *object){ if (ethi->sort_info){ if (ethi->sort_info_changed_id) gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->sort_info_changed_id); + if (ethi->group_info_changed_id) + gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->group_info_changed_id); gtk_object_unref (GTK_OBJECT(ethi->sort_info)); } @@ -210,12 +212,16 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) if (ethi->sort_info){ if (ethi->sort_info_changed_id) gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->sort_info_changed_id); + if (ethi->group_info_changed_id) + gtk_signal_disconnect (GTK_OBJECT(ethi->sort_info), ethi->group_info_changed_id); gtk_object_unref (GTK_OBJECT(ethi->sort_info)); } ethi->sort_info = GTK_VALUE_POINTER (*arg); gtk_object_ref (GTK_OBJECT(ethi->sort_info)); ethi->sort_info_changed_id = gtk_signal_connect (GTK_OBJECT(ethi->sort_info), "sort_info_changed", - GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); + GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); + ethi->group_info_changed_id = gtk_signal_connect (GTK_OBJECT(ethi->sort_info), "group_info_changed", + GTK_SIGNAL_FUNC(ethi_sort_info_changed), ethi); break; } @@ -603,7 +609,6 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width int x1, x2; int col; GHashTable *arrows = g_hash_table_new (NULL, NULL); - xmlNode *node; gint group_indent = 0; #if 0 @@ -612,24 +617,26 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width #endif if (ethi->sort_info) { - xmlNode *grouping; - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); - for (node = grouping->childs; node && strcmp (node->name, "leaf"); node = node->childs) { + int length = e_table_sort_info_grouping_get_count(ethi->sort_info); + int i; + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); group_indent ++; g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); } - if (node) + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } } ethi->group_indent_width = group_indent * GROUP_INDENT; @@ -767,8 +774,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) int col_width; GdkPixmap *pixmap; GdkGC *gc; + int group_indent = 0; GHashTable *arrows = g_hash_table_new (NULL, NULL); - xmlNode *node; ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); if (ethi->drag_col < ethi->eth->frozen_count && ethi->drag_col >= 0){ @@ -780,23 +787,26 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) if (ethi->sort_info) { - xmlNode *grouping; - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); - for (node = grouping->childs; node && strcmp (node->name, "leaf"); node = node->childs) { + int length = e_table_sort_info_grouping_get_count(ethi->sort_info); + int i; + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); + group_indent ++; g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); } - if (node) + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); g_hash_table_insert (arrows, - (gpointer) e_xml_get_integer_prop_by_name (node, "column"), - (gpointer) (e_xml_get_integer_prop_by_name (node, "ascending") ? - E_TABLE_COL_ARROW_DOWN : - E_TABLE_COL_ARROW_UP)); + (gpointer) column.column, + (gpointer) (column.ascending ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } } list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); @@ -927,36 +937,46 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) } else if (ethi->maybe_drag && ethi->sort_info) { ETableCol *col; int model_col; - xmlNode *node; - xmlNode *grouping; - - gtk_object_get (GTK_OBJECT(ethi->sort_info), - "grouping", &grouping, - NULL); + int length; + int i; + int found = FALSE; col = e_table_header_get_column (ethi->eth, ethi_find_col_by_x (ethi, e->button.x)); model_col = col->col_idx; - for (node = grouping->childs; node->childs && strcmp (node->name, "leaf"); node = node->childs) { - if (model_col == e_xml_get_integer_prop_by_name (node, "column")){ - int ascending = e_xml_get_integer_prop_by_name (node, "ascending"); + + length = e_table_sort_info_grouping_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(ethi->sort_info, i); + if (model_col == column.column){ + int ascending = column.ascending; ascending = ! ascending; - e_xml_set_integer_prop_by_name (node, "ascending", ascending); + column.ascending = ascending; + e_table_sort_info_grouping_set_nth(ethi->sort_info, i, column); + found = 1; break; } } - if (!node){ - } - if (node && !strcmp (node->name, "leaf")){ - if (model_col == e_xml_get_integer_prop_by_name (node, "column")){ - int ascending = e_xml_get_integer_prop_by_name (node, "ascending"); - ascending = ! ascending; - e_xml_set_integer_prop_by_name (node, "ascending", ascending); - } else { - e_xml_set_integer_prop_by_name (node, "ascending", 1); - e_xml_set_integer_prop_by_name (node, "column", model_col); + if (!found) { + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(ethi->sort_info, i); + if (model_col == column.column){ + int ascending = column.ascending; + ascending = ! ascending; + column.ascending = ascending; + e_table_sort_info_sorting_set_nth(ethi->sort_info, i, column); + found = 1; + break; + } } } - e_table_sort_info_changed (ethi->sort_info); + if (!found) { + ETableSortColumn column = { model_col, 1 }; + length = e_table_sort_info_sorting_get_count(ethi->sort_info); + if (length == 0) + length++; + e_table_sort_info_sorting_set_nth(ethi->sort_info, length - 1, column); + } } if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); @@ -996,7 +1016,7 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); - gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_POINTER, + gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_OBJECT, GTK_ARG_WRITABLE, ARG_SORT_INFO); /* @@ -1030,6 +1050,7 @@ ethi_init (GnomeCanvasItem *item) ethi->sort_info = NULL; ethi->sort_info_changed_id = 0; + ethi->group_info_changed_id = 0; ethi->group_indent_width = 0; } diff --git a/widgets/table/e-table-header-item.h b/widgets/table/e-table-header-item.h index add488d2f7..6aeefa885d 100644 --- a/widgets/table/e-table-header-item.h +++ b/widgets/table/e-table-header-item.h @@ -48,7 +48,7 @@ typedef struct { int click_x, click_y; int drag_col, drag_mark; guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id; - guint sort_info_changed_id; + guint sort_info_changed_id, group_info_changed_id; GnomeCanvasItem *drag_mark_item, *remove_item; GdkBitmap *stipple; diff --git a/widgets/table/e-table-sort-info.c b/widgets/table/e-table-sort-info.c index bf90a13602..b33784c140 100644 --- a/widgets/table/e-table-sort-info.c +++ b/widgets/table/e-table-sort-info.c @@ -9,7 +9,6 @@ */ #include <config.h> #include <gtk/gtksignal.h> -#include <gnome-xml/tree.h> #include "e-table-sort-info.h" #include "e-util/e-util.h" @@ -22,51 +21,47 @@ static GtkObjectClass *e_table_sort_info_parent_class; enum { SORT_INFO_CHANGED, + GROUP_INFO_CHANGED, LAST_SIGNAL }; static guint e_table_sort_info_signals [LAST_SIGNAL] = { 0, }; -enum { - ARG_0, - ARG_GROUPING -}; - static void -etsi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +etsi_destroy (GtkObject *object) { ETableSortInfo *etsi; - etsi = E_TABLE_SORT_INFO (o); - - switch (arg_id){ - case ARG_GROUPING: - etsi->grouping = GTK_VALUE_POINTER (*arg); - break; - } + etsi = E_TABLE_SORT_INFO (object); + + if (etsi->groupings) + g_free(etsi->groupings); + if (etsi->sortings) + g_free(etsi->sortings); } static void -etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_table_sort_info_init (ETableSortInfo *info) { - ETableSortInfo *etsi; - - etsi = E_TABLE_SORT_INFO (o); - - switch (arg_id){ - case ARG_GROUPING: - GTK_VALUE_POINTER (*arg) = etsi->grouping; - break; - } + info->group_count = 0; + info->groupings = NULL; + info->sort_count = 0; + info->sortings = NULL; + info->frozen = 0; + info->sort_info_changed = 0; + info->group_info_changed = 0; } static void -e_table_sort_info_class_init (GtkObjectClass *object_class) +e_table_sort_info_class_init (ETableSortInfoClass *klass) { + GtkObjectClass *object_class; + e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class = GTK_OBJECT_CLASS(klass); - object_class->set_arg = etsi_set_arg; - object_class->get_arg = etsi_get_arg; + object_class->destroy = etsi_destroy; e_table_sort_info_signals [SORT_INFO_CHANGED] = gtk_signal_new ("sort_info_changed", @@ -76,25 +71,154 @@ e_table_sort_info_class_init (GtkObjectClass *object_class) gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); - gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); + e_table_sort_info_signals [GROUP_INFO_CHANGED] = + gtk_signal_new ("group_info_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableSortInfoClass, group_info_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); - gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER, - GTK_ARG_READWRITE, ARG_GROUPING); + klass->sort_info_changed = NULL; + klass->group_info_changed = NULL; + + gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); } E_MAKE_TYPE(e_table_sort_info, "ETableSortInfo", ETableSortInfo, - e_table_sort_info_class_init, NULL, PARENT_TYPE); + e_table_sort_info_class_init, e_table_sort_info_init, PARENT_TYPE); -void -e_table_sort_info_changed (ETableSortInfo *e_table_sort_info) +static void +e_table_sort_info_sort_info_changed (ETableSortInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); + + if (info->frozen) { + info->sort_info_changed = 1; + } else { + gtk_signal_emit (GTK_OBJECT (info), + e_table_sort_info_signals [SORT_INFO_CHANGED]); + } +} + +static void +e_table_sort_info_group_info_changed (ETableSortInfo *info) { - g_return_if_fail (e_table_sort_info != NULL); - g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info)); + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); - gtk_signal_emit (GTK_OBJECT (e_table_sort_info), - e_table_sort_info_signals [SORT_INFO_CHANGED]); + if (info->frozen) { + info->group_info_changed = 1; + } else { + gtk_signal_emit (GTK_OBJECT (info), + e_table_sort_info_signals [GROUP_INFO_CHANGED]); + } +} + +void +e_table_sort_info_freeze (ETableSortInfo *info) +{ + info->frozen = 1; +} + +void +e_table_sort_info_thaw (ETableSortInfo *info) +{ + info->frozen = 0; + if (info->sort_info_changed) { + info->sort_info_changed = 0; + e_table_sort_info_sort_info_changed(info); + } + if (info->group_info_changed) { + info->group_info_changed = 0; + e_table_sort_info_group_info_changed(info); + } +} + + +guint +e_table_sort_info_grouping_get_count (ETableSortInfo *info) +{ + return info->group_count; +} + +void +e_table_sort_info_grouping_truncate (ETableSortInfo *info, int length) +{ + if (length < info->group_count) { + info->group_count = length; + } + if (length > info->group_count) { + info->groupings = g_realloc(info->groupings, length * sizeof(ETableSortColumn)); + info->group_count = length; + } + e_table_sort_info_group_info_changed(info); +} + +ETableSortColumn +e_table_sort_info_grouping_get_nth (ETableSortInfo *info, int n) +{ + if (n < info->group_count) { + return info->groupings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +void +e_table_sort_info_grouping_set_nth (ETableSortInfo *info, int n, ETableSortColumn column) +{ + if (n >= info->group_count) { + e_table_sort_info_grouping_truncate(info, n + 1); + } + info->groupings[n] = column; + e_table_sort_info_group_info_changed(info); +} + + +guint +e_table_sort_info_sorting_get_count (ETableSortInfo *info) +{ + return info->sort_count; +} + +void +e_table_sort_info_sorting_truncate (ETableSortInfo *info, int length) +{ + if (length < info->sort_count) { + info->sort_count = length; + } + if (length > info->sort_count) { + info->sortings = g_realloc(info->sortings, length * sizeof(ETableSortColumn)); + info->sort_count = length; + } + e_table_sort_info_sort_info_changed(info); } +ETableSortColumn +e_table_sort_info_sorting_get_nth (ETableSortInfo *info, int n) +{ + if (n < info->sort_count) { + return info->sortings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +void +e_table_sort_info_sorting_set_nth (ETableSortInfo *info, int n, ETableSortColumn column) +{ + if (n >= info->sort_count) { + e_table_sort_info_sorting_truncate(info, n + 1); + } + info->sortings[n] = column; + e_table_sort_info_sort_info_changed(info); +} + + ETableSortInfo * e_table_sort_info_new (void) { diff --git a/widgets/table/e-table-sort-info.h b/widgets/table/e-table-sort-info.h index 0fc4cd52ef..6446230116 100644 --- a/widgets/table/e-table-sort-info.h +++ b/widgets/table/e-table-sort-info.h @@ -1,4 +1,3 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SORT_INFO_H_ #define _E_TABLE_SORT_INFO_H_ @@ -11,10 +10,24 @@ #define E_IS_TABLE_SORT_INFO(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORT_INFO_TYPE)) #define E_IS_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORT_INFO_TYPE)) +typedef struct _ETableSortColumn ETableSortColumn; + +struct _ETableSortColumn { + guint column : 31; + guint ascending : 1; +}; + typedef struct { GtkObject base; - - xmlNode *grouping; + + gint group_count; + ETableSortColumn *groupings; + gint sort_count; + ETableSortColumn *sortings; + + guint frozen : 1; + guint sort_info_changed : 1; + guint group_info_changed : 1; } ETableSortInfo; typedef struct { @@ -23,15 +36,25 @@ typedef struct { /* * Signals */ - void (*sort_info_changed) (ETableSortInfo *etm); + void (*sort_info_changed) (ETableSortInfo *info); + void (*group_info_changed) (ETableSortInfo *info); } ETableSortInfoClass; -GtkType e_table_sort_info_get_type (void); +GtkType e_table_sort_info_get_type (void); + +void e_table_sort_info_freeze (ETableSortInfo *info); +void e_table_sort_info_thaw (ETableSortInfo *info); + +guint e_table_sort_info_grouping_get_count (ETableSortInfo *info); +void e_table_sort_info_grouping_truncate (ETableSortInfo *info, int length); +ETableSortColumn e_table_sort_info_grouping_get_nth (ETableSortInfo *info, int n); +void e_table_sort_info_grouping_set_nth (ETableSortInfo *info, int n, ETableSortColumn column); + +guint e_table_sort_info_sorting_get_count (ETableSortInfo *info); +void e_table_sort_info_sorting_truncate (ETableSortInfo *info, int length); +ETableSortColumn e_table_sort_info_sorting_get_nth (ETableSortInfo *info, int n); +void e_table_sort_info_sorting_set_nth (ETableSortInfo *info, int n, ETableSortColumn column); -/* - * Routines for emitting signals on the e_table - */ -void e_table_sort_info_changed (ETableSortInfo *e_table_sort_info); -ETableSortInfo *e_table_sort_info_new (void); +ETableSortInfo *e_table_sort_info_new (void); #endif /* _E_TABLE_SORT_INFO_H_ */ diff --git a/widgets/table/e-table-sorted-variable.c b/widgets/table/e-table-sorted-variable.c index 153295fc78..a1a9a35a09 100644 --- a/widgets/table/e-table-sorted-variable.c +++ b/widgets/table/e-table-sorted-variable.c @@ -41,6 +41,11 @@ etsv_destroy (GtkObject *object) 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) + gtk_object_unref(GTK_OBJECT(etsv->full_header)); GTK_OBJECT_CLASS (etsv_parent_class)->destroy (object); } @@ -67,17 +72,33 @@ etsv_add (ETableSubsetVariable *etssv, ETableSubset *etss = E_TABLE_SUBSET(etssv); ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE(etssv); int i; - int col = etsv->sort_col; - GCompareFunc comp = etsv->compare; - gint ascending = etsv->ascending; + ETableCol *last_col = NULL; + void *val = NULL; - void *val = e_table_model_value_at (etss->source, col, row); - /* FIXME: binary search anyone? */ for (i = 0; i < etss->n_map; i++){ - int comp_val = (*comp)(val, e_table_model_value_at (etss->source, col, etss->map_table[i])); - if ((ascending && comp_val < 0) || ((!ascending) && comp_val > 0)) + int j; + int sort_count = e_table_sort_info_sorting_get_count(etsv->sort_info); + int comp_val = 0; + int ascending = 1; + for (j = 0; j < sort_count; j++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(etsv->sort_info, j); + ETableCol *col; + if (column.column > e_table_header_count (etsv->full_header)) + col = e_table_header_get_columns (etsv->full_header)[e_table_header_count (etsv->full_header) - 1]; + else + col = e_table_header_get_columns (etsv->full_header)[column.column]; + if (last_col != col) + val = e_table_model_value_at (etss->source, col->col_idx, row); + last_col = col; + comp_val = (*col->compare)(val, e_table_model_value_at (etss->source, col->col_idx, etss->map_table[i])); + ascending = column.ascending; + if (comp_val != 0) + break; + } + if (((ascending && comp_val < 0) || ((!ascending) && comp_val > 0))) break; + if (comp_val == 0) if ((ascending && row < etss->map_table[i]) || ((!ascending) && row > etss->map_table[i])) break; @@ -95,7 +116,7 @@ etsv_add (ETableSubsetVariable *etssv, } ETableModel * -e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompareFunc compare) +e_table_sorted_variable_new (ETableModel *source, ETableHeader *full_header, ETableSortInfo *sort_info) { ETableSortedVariable *etsv = gtk_type_new (E_TABLE_SORTED_VARIABLE_TYPE); ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE (etsv); @@ -105,9 +126,10 @@ e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompa return NULL; } - etsv->sort_col = col; - etsv->ascending = ascending; - etsv->compare = compare; + etsv->sort_info = sort_info; + gtk_object_ref(GTK_OBJECT(etsv->sort_info)); + 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); @@ -142,10 +164,8 @@ etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedV { ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv); if (!E_TABLE_MODEL(etsv)->frozen){ - if (col == etsv->sort_col){ - if (e_table_subset_variable_remove(etssv, row)) - e_table_subset_variable_add (etssv, row); - } + if (e_table_subset_variable_remove(etssv, row)) + e_table_subset_variable_add (etssv, row); } } diff --git a/widgets/table/e-table-sorted-variable.h b/widgets/table/e-table-sorted-variable.h index cf188acd4a..1a22679040 100644 --- a/widgets/table/e-table-sorted-variable.h +++ b/widgets/table/e-table-sorted-variable.h @@ -5,6 +5,8 @@ #include <gtk/gtkobject.h> #include "e-table-model.h" #include "e-table-subset-variable.h" +#include "e-table-sort-info.h" +#include "e-table-header.h" #define E_TABLE_SORTED_VARIABLE_TYPE (e_table_sorted_variable_get_type ()) #define E_TABLE_SORTED_VARIABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_VARIABLE_TYPE, ETableSortedVariable)) @@ -15,9 +17,9 @@ typedef struct { ETableSubsetVariable base; - short sort_col; - int ascending; - GCompareFunc compare; + ETableSortInfo *sort_info; + + ETableHeader *full_header; int table_model_changed_id; int table_model_row_changed_id; @@ -29,6 +31,6 @@ typedef struct { } ETableSortedVariableClass; GtkType e_table_sorted_variable_get_type (void); -ETableModel *e_table_sorted_variable_new (ETableModel *etm, int col, int ascending, GCompareFunc compare); +ETableModel *e_table_sorted_variable_new (ETableModel *etm, ETableHeader *header, ETableSortInfo *sort_info); #endif /* _E_TABLE_SORTED_VARIABLE_H_ */ diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 7360666d06..1dc931474d 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -60,6 +60,9 @@ et_destroy (GtkObject *object) if (et->sort_info_change_id) gtk_signal_disconnect (GTK_OBJECT (et->sort_info), et->sort_info_change_id); + if (et->group_info_change_id) + gtk_signal_disconnect (GTK_OBJECT (et->sort_info), + et->group_info_change_id); gtk_object_unref (GTK_OBJECT (et->model)); gtk_object_unref (GTK_OBJECT (et->full_header)); @@ -85,6 +88,7 @@ e_table_init (GtkObject *object) e_table->sort_info = NULL; e_table->sort_info_change_id = 0; + e_table->group_info_change_id = 0; e_table->draw_grid = 1; e_table->draw_focus = 1; @@ -140,6 +144,7 @@ e_table_setup_header (ETable *e_table) { xmlNode *root; xmlNode *grouping; + int i; e_table->header_canvas = GNOME_CANVAS (e_canvas_new ()); gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); @@ -152,13 +157,27 @@ e_table_setup_header (ETable *e_table) gtk_object_ref (GTK_OBJECT (e_table->sort_info)); gtk_object_sink (GTK_OBJECT (e_table->sort_info)); - gtk_object_set (GTK_OBJECT (e_table->sort_info), - "grouping", grouping, - NULL); + i = 0; + for (grouping = grouping->childs; grouping && strcmp (grouping->name, "leaf"); grouping = grouping->childs) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, "column"); + column.ascending = e_xml_get_integer_prop_by_name (grouping, "ascending"); + e_table_sort_info_grouping_set_nth(e_table->sort_info, i++, column); + } + i = 0; + for (; grouping; grouping = grouping->childs) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, "column"); + column.ascending = e_xml_get_integer_prop_by_name (grouping, "ascending"); + e_table_sort_info_sorting_set_nth(e_table->sort_info, i++, column); + } e_table->sort_info_change_id = gtk_signal_connect (GTK_OBJECT (e_table->sort_info), "sort_info_changed", GTK_SIGNAL_FUNC (sort_info_changed), e_table); + e_table->group_info_change_id = + gtk_signal_connect (GTK_OBJECT (e_table->sort_info), "group_info_changed", + GTK_SIGNAL_FUNC (sort_info_changed), e_table); e_table->header_item = gnome_canvas_item_new ( gnome_canvas_root (e_table->header_canvas), @@ -631,8 +650,8 @@ changed_idle (gpointer data) et->full_header, et->header, et->model, - e_xml_get_child_by_name (xmlDocGetRootElement (et->specification), - "grouping")->childs); + et->sort_info, + 0); gtk_signal_connect (GTK_OBJECT (et->group), "row_selection", GTK_SIGNAL_FUNC (group_row_selection), et); e_table_fill_table (et, et->model); @@ -687,7 +706,7 @@ et_table_cell_changed (ETableModel *table_model, int view_col, int row, ETable * static void e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, - ETableModel *model, xmlNode *xml_grouping) + ETableModel *model) { e_table->table_canvas = GNOME_CANVAS (e_canvas_new ()); gtk_signal_connect ( @@ -703,7 +722,8 @@ e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *h full_header, header, model, - xml_grouping->childs); + e_table->sort_info, + 0); gtk_signal_connect (GTK_OBJECT(e_table->group), "row_selection", GTK_SIGNAL_FUNC(group_row_selection), e_table); @@ -763,7 +783,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, e_table->header = e_table_make_header (e_table, full_header, xmlColumns); e_table_setup_header (e_table); - e_table_setup_table (e_table, full_header, e_table->header, etm, xmlGrouping); + e_table_setup_table (e_table, full_header, e_table->header, etm); e_table_fill_table (e_table, etm); vbox = gtk_vbox_new (FALSE, 0); @@ -853,11 +873,32 @@ et_build_column_spec (ETable *e_table) static xmlNode * et_build_grouping_spec (ETable *e_table) { + xmlNode *node; xmlNode *grouping; xmlNode *root; + int i; + int length; root = xmlDocGetRootElement (e_table->specification); - grouping = xmlCopyNode (e_xml_get_child_by_name(root, "grouping"), TRUE); + xmlCopyNode (e_xml_get_child_by_name(root, "grouping"), TRUE); + grouping = xmlNewNode (NULL, "grouping"); + node = grouping; + length = e_table_sort_info_grouping_get_count(e_table->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth(e_table->sort_info, i); + xmlNode *new_node = xmlNewChild(node, NULL, "group", NULL); + e_xml_set_integer_prop_by_name (new_node, "column", column.column); + e_xml_set_integer_prop_by_name (new_node, "ascending", column.ascending); + node = new_node; + } + length = e_table_sort_info_sorting_get_count(e_table->sort_info); + for (i = 0; i < length; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth(e_table->sort_info, i); + xmlNode *new_node = xmlNewChild(node, NULL, "leaf", NULL); + e_xml_set_integer_prop_by_name (new_node, "column", column.column); + e_xml_set_integer_prop_by_name (new_node, "ascending", column.ascending); + node = new_node; + } return grouping; } diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index 3cca3422b3..39333f159a 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -34,6 +34,7 @@ typedef struct { int table_cell_change_id; int sort_info_change_id; + int group_info_change_id; GnomeCanvas *header_canvas, *table_canvas; diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c index 15e07d94da..f60d22d915 100644 --- a/widgets/table/test-cols.c +++ b/widgets/table/test-cols.c @@ -9,6 +9,7 @@ #include <string.h> #include <gnome.h> #include "e-util/e-canvas-utils.h" +#include "e-util/e-canvas.h" #include "e-util/e-cursors.h" #include "e-util/e-util.h" #include "e-table-simple.h" diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c index 0fd086681c..2ff657c863 100644 --- a/widgets/table/test-table.c +++ b/widgets/table/test-table.c @@ -17,6 +17,7 @@ #include "e-table-item.h" #include "e-cell-text.h" #include "e-table.h" +#include "e-table-config.h" #include "table-test.h" @@ -346,7 +347,7 @@ do_e_table_demo (const char *spec) gtk_widget_show (window); if (getenv ("TEST")){ - e_table_do_gui_config (NULL, e_table); + e_table_do_gui_config (NULL, E_TABLE(e_table)); } } |