aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorChristopher James Lahey <clahey@helixcode.com>2000-03-06 07:15:14 +0800
committerChris Lahey <clahey@src.gnome.org>2000-03-06 07:15:14 +0800
commit3de981ec78d529eb1bd9b2f98f154eae91dffc6d (patch)
treee8758124523b6c534890aa80f5b918981be6ce00 /widgets
parent645f69dcf6d0b6162c5c7843371c559486234175 (diff)
downloadgsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.gz
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.bz2
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.lz
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.xz
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.zst
gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.zip
Added support for the sorting info. The Etable creates a sort_info object,
2000-03-05 Christopher James Lahey <clahey@helixcode.com> * e-table.c, e-table.h: Added support for the sorting info. The Etable creates a sort_info object, and then connects to the signals to rearrange the rows when the sort_info changes. It also passes the info object to the ETableHeaderItem. * e-table-model.c: Fixed a typo where ETableModel was written as ETableModle. * e-table-header.c, e-table-header.h: Added some code for sorting here, but it's not used. I don't think we want this code, but I wanted to check it in at least once so that it's not lost. * e-table-header-item.c, e-table-header-item.h: Added a "sort_info" argument to ETableHeaderItem. Added display of current sort settings. Added support for clicking to change the sort settings. * e-table-col.h: E_TABLE_COL_ARROW_NONE is marked as being = 0 since this is required in other places. (I think C defines this as being the case, but it's good to have the = 0 there so that it's obvious that it has to be first.) * TODO: Mark sorting as done. * e-table-sort-info.c, e-table-sort-info.h: New files for containing the xml grouping/sorting information and for sending signals on that information. * Makefile.am: Added e-table-sort-info.c and e-table-sort-info.h. svn path=/trunk/; revision=2060
Diffstat (limited to 'widgets')
-rw-r--r--widgets/e-table/ChangeLog32
-rw-r--r--widgets/e-table/Makefile.am2
-rw-r--r--widgets/e-table/TODO13
-rw-r--r--widgets/e-table/e-table-col.h2
-rw-r--r--widgets/e-table/e-table-header-item.c109
-rw-r--r--widgets/e-table/e-table-header-item.h8
-rw-r--r--widgets/e-table/e-table-header.c131
-rw-r--r--widgets/e-table/e-table-header.h27
-rw-r--r--widgets/e-table/e-table-model.c2
-rw-r--r--widgets/e-table/e-table-sort-info.c124
-rw-r--r--widgets/e-table/e-table-sort-info.h37
-rw-r--r--widgets/e-table/e-table.c40
-rw-r--r--widgets/e-table/e-table.h5
-rw-r--r--widgets/table/e-table-col.h2
-rw-r--r--widgets/table/e-table-header-item.c109
-rw-r--r--widgets/table/e-table-header-item.h8
-rw-r--r--widgets/table/e-table-header.c131
-rw-r--r--widgets/table/e-table-header.h27
-rw-r--r--widgets/table/e-table-model.c2
-rw-r--r--widgets/table/e-table-sort-info.c124
-rw-r--r--widgets/table/e-table-sort-info.h37
-rw-r--r--widgets/table/e-table.c40
-rw-r--r--widgets/table/e-table.h5
23 files changed, 992 insertions, 25 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog
index be5b2fad0a..9a074a3e8b 100644
--- a/widgets/e-table/ChangeLog
+++ b/widgets/e-table/ChangeLog
@@ -1,3 +1,35 @@
+2000-03-05 Christopher James Lahey <clahey@helixcode.com>
+
+ * e-table.c, e-table.h: Added support for the sorting info. The
+ Etable creates a sort_info object, and then connects to the
+ signals to rearrange the rows when the sort_info changes. It also
+ passes the info object to the ETableHeaderItem.
+
+ * e-table-model.c: Fixed a typo where ETableModel was written as
+ ETableModle.
+
+ * e-table-header.c, e-table-header.h: Added some code for sorting
+ here, but it's not used. I don't think we want this code, but I
+ wanted to check it in at least once so that it's not lost.
+
+ * e-table-header-item.c, e-table-header-item.h: Added a
+ "sort_info" argument to ETableHeaderItem. Added display of
+ current sort settings. Added support for clicking to change the
+ sort settings.
+
+ * e-table-col.h: E_TABLE_COL_ARROW_NONE is marked as being = 0
+ since this is required in other places. (I think C defines this
+ as being the case, but it's good to have the = 0 there so that
+ it's obvious that it has to be first.)
+
+ * TODO: Mark sorting as done.
+
+ * e-table-sort-info.c, e-table-sort-info.h: New files for
+ containing the xml grouping/sorting information and for sending
+ signals on that information.
+
+ * Makefile.am: Added e-table-sort-info.c and e-table-sort-info.h.
+
2000-03-04 Christopher James Lahey <clahey@helixcode.com>
* e-table.c: Added saving of frozen_columns count. Added a
diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am
index d32b74d406..3619c6bef3 100644
--- a/widgets/e-table/Makefile.am
+++ b/widgets/e-table/Makefile.am
@@ -37,6 +37,8 @@ libetable_a_SOURCES = \
e-table-model.h \
e-table-simple.c \
e-table-simple.h \
+ e-table-sort-info.c \
+ e-table-sort-info.h \
e-table-sorted.c \
e-table-sorted.h \
e-table-sorted-variable.c \
diff --git a/widgets/e-table/TODO b/widgets/e-table/TODO
index bbad34e6ef..35ba2eb6b9 100644
--- a/widgets/e-table/TODO
+++ b/widgets/e-table/TODO
@@ -30,12 +30,11 @@ mouse grabbing for scrolling
+ * Add frozen_columns output.
* Add input and output of column widths and minimum column widths.
-* Add GUI sort
++ * Add GUI sort
- * Add a method to the ETableGroup class to change the sorting information.
- * Add a way to get sorting information out of the ETableHeader.
- * Add display of proper arrows to the ETableHeaderItem.
- * Add switching of sorting on clicks.
++ * Create an ETableSortInfo class.
++ * Add display of proper arrows to the ETableHeaderItem.
++ * Add switching of sorting on clicks.
* Add depressed button state to ETableHeaderItem?
* Add GUI grouping
@@ -71,4 +70,8 @@ mouse grabbing for scrolling
* Implement ETableDataEntry (a subclass of ETableModel).
* Build GUI for the data entry model. This should be fairly simple.
+* Draw little arrows for new column position instead of little triangles.
+* Make new column position be closest to position instead of rounding to the left.
+* Copy gtk_dnd as e_dnd.
+
* Fix known bug about navigating out of the bottom of the table.
diff --git a/widgets/e-table/e-table-col.h b/widgets/e-table/e-table-col.h
index c6f9c9dfb5..816879792e 100644
--- a/widgets/e-table/e-table-col.h
+++ b/widgets/e-table/e-table-col.h
@@ -16,7 +16,7 @@ typedef struct _ETableColClass ETableColClass;
typedef enum _ETableColArrow ETableColArrow;
enum _ETableColArrow {
- E_TABLE_COL_ARROW_NONE,
+ E_TABLE_COL_ARROW_NONE = 0,
E_TABLE_COL_ARROW_UP,
E_TABLE_COL_ARROW_DOWN
};
diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c
index 475e15c31d..82637a8a82 100644
--- a/widgets/e-table/e-table-header-item.c
+++ b/widgets/e-table/e-table-header-item.c
@@ -16,6 +16,7 @@
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "e-util/e-cursors.h"
+#include "e-util/e-xml-utils.h"
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-col-dnd.h"
@@ -55,7 +56,8 @@ enum {
ARG_TABLE_HEADER,
ARG_TABLE_X,
ARG_TABLE_Y,
- ARG_TABLE_FONTSET
+ ARG_TABLE_FONTSET,
+ ARG_SORT_INFO
};
static GtkTargetEntry ethi_drag_types [] = {
@@ -71,6 +73,8 @@ ethi_destroy (GtkObject *object){
ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object);
ethi_drop_table_header (ethi);
+ if ( ethi->sort_info )
+ gtk_object_unref(GTK_OBJECT(ethi->sort_info));
if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy)
(*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object);
@@ -181,6 +185,11 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_TABLE_FONTSET:
ethi_font_load (ethi, GTK_VALUE_STRING (*arg));
break;
+
+ case ARG_SORT_INFO:
+ ethi->sort_info = GTK_VALUE_POINTER (*arg);
+ gtk_object_ref(GTK_OBJECT(ethi->sort_info));
+ break;
}
ethi_update (item, NULL, NULL, 0);
@@ -482,7 +491,7 @@ ethi_unrealize (GnomeCanvasItem *item)
static void
draw_button (ETableHeaderItem *ethi, ETableCol *col,
GdkDrawable *drawable, GdkGC *gc, GtkStyle *style,
- int x, int y, int width, int height)
+ int x, int y, int width, int height, ETableColArrow arrow)
{
GdkRectangle clip;
int xtra;
@@ -532,7 +541,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col,
col->text, strlen (col->text));
}
- switch ( e_table_col_get_arrow(col) ) {
+ switch ( arrow ) {
case E_TABLE_COL_ARROW_NONE:
break;
case E_TABLE_COL_ARROW_UP:
@@ -544,7 +553,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col,
&clip,
GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas),
"header",
- e_table_col_get_arrow(col) == E_TABLE_COL_ARROW_UP ? GTK_ARROW_UP : GTK_ARROW_DOWN,
+ (arrow == E_TABLE_COL_ARROW_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN,
TRUE,
x + PADDING / 2 + clip.width - MIN_ARROW_SIZE - 2,
y + (ethi->height - MIN_ARROW_SIZE) / 2,
@@ -563,11 +572,34 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width
const int cols = e_table_header_count (ethi->eth);
int x1, x2;
int col;
+ GHashTable *arrows = g_hash_table_new(NULL, NULL);
+ xmlNode *node;
#if 0
printf ("My coords are: %g %g %g %g\n",
item->x1, item->y1, item->x2, item->y2);
#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) {
+ 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));
+ }
+ if ( node )
+ 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));
+ }
+
x1 = x2 = ethi->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
@@ -590,8 +622,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width
draw_button (ethi, ecol, drawable, gc,
GTK_WIDGET (canvas)->style,
- x1 - x, ethi->y1 - y, col_width, ethi->height);
+ x1 - x, ethi->y1 - y, col_width, ethi->height,
+ (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) );
}
+ g_hash_table_destroy(arrows);
}
static double
@@ -698,6 +732,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
int col_width;
GdkPixmap *pixmap;
GdkGC *gc;
+ 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 ) {
@@ -707,6 +743,27 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
if (ethi->drag_col == -1)
return;
+
+ 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) {
+ 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));
+ }
+ if ( node )
+ 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));
+ }
+
list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types));
context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event);
@@ -719,7 +776,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
gc = widget->style->bg_gc [GTK_STATE_ACTIVE];
draw_button (ethi, ecol, pixmap, gc,
widget->style,
- 0, 0, col_width, ethi->height);
+ 0, 0, col_width, ethi->height,
+ (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) );
gtk_drag_set_icon_pixmap (context,
gdk_window_get_colormap(widget->window),
pixmap,
@@ -729,6 +787,7 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
gdk_pixmap_unref(pixmap);
ethi->maybe_drag = FALSE;
+ g_hash_table_destroy(arrows);
}
/*
@@ -830,6 +889,40 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e)
if (ethi->resize_col != -1){
needs_ungrab = (ethi->resize_guide != NULL);
ethi_end_resize (ethi, ethi->resize_width);
+ } 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);
+
+ 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");
+ ascending = ! ascending;
+ e_xml_set_integer_prop_by_name(node, "ascending", ascending);
+ 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);
+ }
+ }
+ e_table_sort_info_changed(ethi->sort_info);
+ ethi_request_redraw (ethi);
}
if (needs_ungrab)
gnome_canvas_item_ungrab (item, e->button.time);
@@ -869,6 +962,8 @@ 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_ARG_WRITABLE, ARG_SORT_INFO);
/*
* Create our pixmaps for DnD
@@ -897,6 +992,8 @@ ethi_init (GnomeCanvasItem *item)
ethi->drag_col = -1;
ethi->drag_mark = -1;
+
+ ethi->sort_info = NULL;
}
GtkType
diff --git a/widgets/e-table/e-table-header-item.h b/widgets/e-table/e-table-header-item.h
index 2e889a6adf..cc3cf8e4f6 100644
--- a/widgets/e-table/e-table-header-item.h
+++ b/widgets/e-table/e-table-header-item.h
@@ -1,8 +1,11 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#ifndef _E_TABLE_HEADER_ITEM_H_
#define _E_TABLE_HEADER_ITEM_H_
#include <libgnomeui/gnome-canvas.h>
+#include <gnome-xml/tree.h>
#include "e-table-header.h"
+#include "e-table-sort-info.h"
#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ())
#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem))
@@ -45,6 +48,11 @@ typedef struct {
guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id;
GnomeCanvasItem *drag_mark_item, *remove_item;
GdkBitmap *stipple;
+
+ /*
+ * For column sorting info
+ */
+ ETableSortInfo *sort_info;
} ETableHeaderItem;
typedef struct {
diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c
index 527e7e22bc..8465f28567 100644
--- a/widgets/e-table/e-table-header.c
+++ b/widgets/e-table/e-table-header.c
@@ -350,3 +350,134 @@ e_table_header_set_frozen_columns (ETableHeader *eth, int idx)
{
eth->frozen_count = idx;
}
+
+/* Forget model-view here. Really, this information belongs in the view anyway. */
+#if 0
+static void
+set_arrows(ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ ETableCol *col;
+ for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
+ if ( col->col_idx == info.model_col )
+ e_table_column_set_arrow(col, info.ascending ? E_TABLE_COL_ARROW_DOWN : E_TABLE_COL_ARROW_UP);
+ }
+}
+
+static void
+unset_arrows(ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ ETableCol *col;
+ for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
+ if ( col->col_idx == info.model_col )
+ e_table_column_set_arrow(col, E_TABLE_COL_ARROW_NONE);
+ }
+}
+
+ETableHeaderSortInfo
+e_table_header_get_sort_info (ETableHeader *eth)
+{
+ ETableHeaderSortInfo dummy_info = {0, 1};
+ g_return_val_if_fail (eth != NULL, dummy_info);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
+
+ return eth->sort_info;
+}
+
+void
+e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ unset_arrows(eth, eth->sort_info);
+ eth->sort_info = info;
+ set_arrows(eth, eth->sort_info);
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+
+int
+e_table_header_get_group_count (ETableHeader *eth)
+{
+ g_return_val_if_fail (eth != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
+
+ return eth->grouping_count;
+}
+
+ETableHeaderSortInfo *
+e_table_header_get_groups (ETableHeader *eth)
+{
+ ETableHeaderSortInfo *ret;
+ g_return_val_if_fail (eth != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL);
+
+ ret = g_new (ETableHeaderSortInfo, eth->grouping_count);
+ memcpy (ret, eth->grouping, sizeof (ETableHeaderSortInfo) * eth->grouping_count);
+ return eth->grouping;
+}
+
+ETableHeaderSortInfo
+e_table_header_get_group (ETableHeader *eth, gint index)
+{
+ ETableHeaderSortInfo dummy_info = {0, 1};
+ g_return_val_if_fail (eth != NULL, dummy_info);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
+ g_return_val_if_fail (index >= 0, dummy_info);
+ g_return_val_if_fail (index < eth->grouping_count, dummy_info);
+
+ return eth->grouping[index];
+}
+
+void
+e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count + 1));
+ memmove(eth->grouping + index + 1, eth->grouping + index, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
+ eth->grouping[index] = info;
+
+ eth->grouping_count ++;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_header_grouping_delete (ETableHeader *eth, gint index)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ memmove(eth->grouping + index, eth->grouping + index + 1, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
+ eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - 1));
+
+ eth->grouping_count --;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx)
+{
+ ETableHeaderSortInfo info;
+
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ if ( old_idx == new_idx )
+ return;
+
+ info = eth->grouping[old_idx];
+ if ( old_idx < new_idx ) {
+ memmove(eth->grouping + old_idx, eth->grouping + old_idx + 1, sizeof(ETableHeaderSortInfo) * (new_idx - old_idx));
+ } else {
+ memmove(eth->grouping + new_idx + 1, eth->grouping + new_idx, sizeof(ETableHeaderSortInfo) * (old_idx - new_idx));
+ }
+ eth->grouping[new_idx] = info;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+#endif
diff --git a/widgets/e-table/e-table-header.h b/widgets/e-table/e-table-header.h
index 0b4e40101f..cfd4d68d4a 100644
--- a/widgets/e-table/e-table-header.h
+++ b/widgets/e-table/e-table-header.h
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#ifndef _E_TABLE_COLUMN_H_
#define _E_TABLE_COLUMN_H_
@@ -13,6 +14,13 @@ typedef struct _ETableHeader ETableHeader;
#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE))
#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE))
+#if 0
+typedef struct {
+ int model_col;
+ int ascending;
+} ETableHeaderSortInfo;
+#endif
+
/*
* A Columnar header.
*/
@@ -23,6 +31,12 @@ struct _ETableHeader {
ETableCol **columns;
gboolean selectable;
int frozen_count;
+
+#if 0
+ ETableHeaderSortInfo sort_info;
+ ETableHeaderSortInfo *grouping;
+ gint grouping_count;
+#endif
};
typedef struct {
@@ -45,6 +59,19 @@ int e_table_header_index (ETableHeader *eth,
int e_table_header_get_index_at (ETableHeader *eth,
int x_offset);
ETableCol **e_table_header_get_columns (ETableHeader *eth);
+
+#if 0
+ETableHeaderSortInfo e_table_header_get_sort_info (ETableHeader *eth);
+void e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info);
+
+int e_table_header_get_group_count (ETableHeader *eth);
+ETableHeaderSortInfo *e_table_header_get_groups (ETableHeader *eth);
+ETableHeaderSortInfo e_table_header_get_group (ETableHeader *eth, gint index);
+void e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info);
+void e_table_header_grouping_delete (ETableHeader *eth, gint index);
+void e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx);
+#endif
+
gboolean e_table_header_selection_ok (ETableHeader *eth);
int e_table_header_get_selected (ETableHeader *eth);
int e_table_header_total_width (ETableHeader *eth);
diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c
index ef14b98018..660ec20f91 100644
--- a/widgets/e-table/e-table-model.c
+++ b/widgets/e-table/e-table-model.c
@@ -156,7 +156,7 @@ e_table_model_get_type (void)
{
GtkTypeInfo info =
{
- "ETableModle",
+ "ETableModel",
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
diff --git a/widgets/e-table/e-table-sort-info.c b/widgets/e-table/e-table-sort-info.c
new file mode 100644
index 0000000000..1f465be99b
--- /dev/null
+++ b/widgets/e-table/e-table-sort-info.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-table-sort-info.c: a Table Model
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 Helix Code, Inc.
+ */
+#include <config.h>
+#include <gtk/gtksignal.h>
+#include <gnome-xml/tree.h>
+#include "e-table-sort-info.h"
+
+#define ETM_CLASS(e) ((ETableSortInfoClass *)((GtkObject *)e)->klass)
+
+#define PARENT_TYPE gtk_object_get_type();
+
+
+static GtkObjectClass *e_table_sort_info_parent_class;
+
+enum {
+ SORT_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)
+{
+ ETableSortInfo *etsi;
+
+ etsi = E_TABLE_SORT_INFO (o);
+
+ switch (arg_id){
+ case ARG_GROUPING:
+ etsi->grouping = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+}
+
+static void
+etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ ETableSortInfo *etsi;
+
+ etsi = E_TABLE_SORT_INFO (o);
+
+ switch (arg_id){
+ case ARG_GROUPING:
+ GTK_VALUE_POINTER (*arg) = etsi->grouping;
+ break;
+ }
+}
+
+static void
+e_table_sort_info_class_init (GtkObjectClass *object_class)
+{
+ e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ object_class->set_arg = etsi_set_arg;
+ object_class->get_arg = etsi_get_arg;
+
+ e_table_sort_info_signals [SORT_INFO_CHANGED] =
+ gtk_signal_new ("sort_info_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableSortInfoClass, sort_info_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL);
+
+ gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER,
+ GTK_ARG_READWRITE, ARG_GROUPING);
+}
+
+
+guint
+e_table_sort_info_get_type (void)
+{
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "ETableSortInfo",
+ sizeof (ETableSortInfo),
+ sizeof (ETableSortInfoClass),
+ (GtkClassInitFunc) e_table_sort_info_class_init,
+ NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gtk_object_get_type(), &info);
+ }
+
+ return type;
+}
+
+void
+e_table_sort_info_changed (ETableSortInfo *e_table_sort_info)
+{
+ g_return_if_fail (e_table_sort_info != NULL);
+ g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info));
+
+ gtk_signal_emit (GTK_OBJECT (e_table_sort_info),
+ e_table_sort_info_signals [SORT_INFO_CHANGED]);
+}
+
+ETableSortInfo *
+e_table_sort_info_new (void)
+{
+ return gtk_type_new (e_table_sort_info_get_type ());
+}
diff --git a/widgets/e-table/e-table-sort-info.h b/widgets/e-table/e-table-sort-info.h
new file mode 100644
index 0000000000..0fc4cd52ef
--- /dev/null
+++ b/widgets/e-table/e-table-sort-info.h
@@ -0,0 +1,37 @@
+
+/* -*- 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_
+
+#include <gtk/gtkobject.h>
+
+#define E_TABLE_SORT_INFO_TYPE (e_table_sort_info_get_type ())
+#define E_TABLE_SORT_INFO(o) (GTK_CHECK_CAST ((o), E_TABLE_SORT_INFO_TYPE, ETableSortInfo))
+#define E_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORT_INFO_TYPE, ETableSortInfoClass))
+#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 {
+ GtkObject base;
+
+ xmlNode *grouping;
+} ETableSortInfo;
+
+typedef struct {
+ GtkObjectClass parent_class;
+
+ /*
+ * Signals
+ */
+ void (*sort_info_changed) (ETableSortInfo *etm);
+} ETableSortInfoClass;
+
+GtkType e_table_sort_info_get_type (void);
+
+/*
+ * 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);
+
+#endif /* _E_TABLE_SORT_INFO_H_ */
diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c
index 4bd4417cd0..b1c14b958a 100644
--- a/widgets/e-table/e-table.c
+++ b/widgets/e-table/e-table.c
@@ -35,6 +35,7 @@
static GtkObjectClass *e_table_parent_class;
static void e_table_fill_table (ETable *e_table, ETableModel *model);
+static gboolean changed_idle (gpointer data);
static void
et_destroy (GtkObject *object)
@@ -44,6 +45,7 @@ et_destroy (GtkObject *object)
gtk_object_unref (GTK_OBJECT (et->model));
gtk_object_unref (GTK_OBJECT (et->full_header));
gtk_object_unref (GTK_OBJECT (et->header));
+ gtk_object_unref (GTK_OBJECT (et->sort_info));
gtk_widget_destroy (GTK_WIDGET (et->header_canvas));
gtk_widget_destroy (GTK_WIDGET (et->table_canvas));
@@ -53,6 +55,9 @@ et_destroy (GtkObject *object)
et->table_row_change_id);
gtk_signal_disconnect (GTK_OBJECT (et->model),
et->table_cell_change_id);
+ if (et->sort_info_change_id)
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->sort_info_change_id);
if (et->rebuild_idle_id) {
g_source_remove(et->rebuild_idle_id);
@@ -68,6 +73,9 @@ static void
e_table_init (GtkObject *object)
{
ETable *e_table = E_TABLE (object);
+
+ e_table->sort_info = NULL;
+ e_table->sort_info_change_id = 0;
e_table->draw_grid = 1;
e_table->draw_focus = 1;
@@ -110,18 +118,46 @@ header_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t
}
static void
+sort_info_changed (ETableSortInfo *info, ETable *et)
+{
+ et->need_rebuild = TRUE;
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
e_table_setup_header (ETable *e_table)
{
+ xmlNode *root;
+ xmlNode *grouping;
e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ());
-
+
gtk_widget_show (GTK_WIDGET (e_table->header_canvas));
+ root = xmlDocGetRootElement(e_table->specification);
+ grouping = e_xml_get_child_by_name(root, "grouping");
+
+ e_table->sort_info = e_table_sort_info_new();
+
+ 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);
+
+ 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->header_item = gnome_canvas_item_new (
gnome_canvas_root (e_table->header_canvas),
e_table_header_item_get_type (),
"ETableHeader", e_table->header,
"x", 0,
"y", 0,
+ "sort_info", e_table->sort_info,
NULL);
gtk_signal_connect (
@@ -705,7 +741,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm,
gtk_widget_show (vscrollbar);
gtk_table_attach (
GTK_TABLE (e_table), vscrollbar,
- 1, 2, 1, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0);
+ 1, 2, 0, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0);
gtk_widget_pop_colormap ();
gtk_widget_pop_visual ();
diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h
index 5c29c1fa0c..9c5bb9b8a0 100644
--- a/widgets/e-table/e-table.h
+++ b/widgets/e-table/e-table.h
@@ -8,6 +8,7 @@
#include "e-table-model.h"
#include "e-table-header.h"
#include "e-table-group.h"
+#include "e-table-sort-info.h"
BEGIN_GNOME_DECLS
@@ -26,10 +27,14 @@ typedef struct {
ETableGroup *group;
+ ETableSortInfo *sort_info;
+
int table_model_change_id;
int table_row_change_id;
int table_cell_change_id;
+ int sort_info_change_id;
+
GnomeCanvas *header_canvas, *table_canvas;
GnomeCanvasItem *header_item, *root;
diff --git a/widgets/table/e-table-col.h b/widgets/table/e-table-col.h
index c6f9c9dfb5..816879792e 100644
--- a/widgets/table/e-table-col.h
+++ b/widgets/table/e-table-col.h
@@ -16,7 +16,7 @@ typedef struct _ETableColClass ETableColClass;
typedef enum _ETableColArrow ETableColArrow;
enum _ETableColArrow {
- E_TABLE_COL_ARROW_NONE,
+ E_TABLE_COL_ARROW_NONE = 0,
E_TABLE_COL_ARROW_UP,
E_TABLE_COL_ARROW_DOWN
};
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c
index 475e15c31d..82637a8a82 100644
--- a/widgets/table/e-table-header-item.c
+++ b/widgets/table/e-table-header-item.c
@@ -16,6 +16,7 @@
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "e-util/e-cursors.h"
+#include "e-util/e-xml-utils.h"
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-col-dnd.h"
@@ -55,7 +56,8 @@ enum {
ARG_TABLE_HEADER,
ARG_TABLE_X,
ARG_TABLE_Y,
- ARG_TABLE_FONTSET
+ ARG_TABLE_FONTSET,
+ ARG_SORT_INFO
};
static GtkTargetEntry ethi_drag_types [] = {
@@ -71,6 +73,8 @@ ethi_destroy (GtkObject *object){
ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object);
ethi_drop_table_header (ethi);
+ if ( ethi->sort_info )
+ gtk_object_unref(GTK_OBJECT(ethi->sort_info));
if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy)
(*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object);
@@ -181,6 +185,11 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
case ARG_TABLE_FONTSET:
ethi_font_load (ethi, GTK_VALUE_STRING (*arg));
break;
+
+ case ARG_SORT_INFO:
+ ethi->sort_info = GTK_VALUE_POINTER (*arg);
+ gtk_object_ref(GTK_OBJECT(ethi->sort_info));
+ break;
}
ethi_update (item, NULL, NULL, 0);
@@ -482,7 +491,7 @@ ethi_unrealize (GnomeCanvasItem *item)
static void
draw_button (ETableHeaderItem *ethi, ETableCol *col,
GdkDrawable *drawable, GdkGC *gc, GtkStyle *style,
- int x, int y, int width, int height)
+ int x, int y, int width, int height, ETableColArrow arrow)
{
GdkRectangle clip;
int xtra;
@@ -532,7 +541,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col,
col->text, strlen (col->text));
}
- switch ( e_table_col_get_arrow(col) ) {
+ switch ( arrow ) {
case E_TABLE_COL_ARROW_NONE:
break;
case E_TABLE_COL_ARROW_UP:
@@ -544,7 +553,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col,
&clip,
GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas),
"header",
- e_table_col_get_arrow(col) == E_TABLE_COL_ARROW_UP ? GTK_ARROW_UP : GTK_ARROW_DOWN,
+ (arrow == E_TABLE_COL_ARROW_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN,
TRUE,
x + PADDING / 2 + clip.width - MIN_ARROW_SIZE - 2,
y + (ethi->height - MIN_ARROW_SIZE) / 2,
@@ -563,11 +572,34 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width
const int cols = e_table_header_count (ethi->eth);
int x1, x2;
int col;
+ GHashTable *arrows = g_hash_table_new(NULL, NULL);
+ xmlNode *node;
#if 0
printf ("My coords are: %g %g %g %g\n",
item->x1, item->y1, item->x2, item->y2);
#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) {
+ 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));
+ }
+ if ( node )
+ 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));
+ }
+
x1 = x2 = ethi->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
@@ -590,8 +622,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width
draw_button (ethi, ecol, drawable, gc,
GTK_WIDGET (canvas)->style,
- x1 - x, ethi->y1 - y, col_width, ethi->height);
+ x1 - x, ethi->y1 - y, col_width, ethi->height,
+ (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) );
}
+ g_hash_table_destroy(arrows);
}
static double
@@ -698,6 +732,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
int col_width;
GdkPixmap *pixmap;
GdkGC *gc;
+ 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 ) {
@@ -707,6 +743,27 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
if (ethi->drag_col == -1)
return;
+
+ 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) {
+ 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));
+ }
+ if ( node )
+ 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));
+ }
+
list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types));
context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event);
@@ -719,7 +776,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
gc = widget->style->bg_gc [GTK_STATE_ACTIVE];
draw_button (ethi, ecol, pixmap, gc,
widget->style,
- 0, 0, col_width, ethi->height);
+ 0, 0, col_width, ethi->height,
+ (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) );
gtk_drag_set_icon_pixmap (context,
gdk_window_get_colormap(widget->window),
pixmap,
@@ -729,6 +787,7 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
gdk_pixmap_unref(pixmap);
ethi->maybe_drag = FALSE;
+ g_hash_table_destroy(arrows);
}
/*
@@ -830,6 +889,40 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e)
if (ethi->resize_col != -1){
needs_ungrab = (ethi->resize_guide != NULL);
ethi_end_resize (ethi, ethi->resize_width);
+ } 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);
+
+ 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");
+ ascending = ! ascending;
+ e_xml_set_integer_prop_by_name(node, "ascending", ascending);
+ 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);
+ }
+ }
+ e_table_sort_info_changed(ethi->sort_info);
+ ethi_request_redraw (ethi);
}
if (needs_ungrab)
gnome_canvas_item_ungrab (item, e->button.time);
@@ -869,6 +962,8 @@ 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_ARG_WRITABLE, ARG_SORT_INFO);
/*
* Create our pixmaps for DnD
@@ -897,6 +992,8 @@ ethi_init (GnomeCanvasItem *item)
ethi->drag_col = -1;
ethi->drag_mark = -1;
+
+ ethi->sort_info = NULL;
}
GtkType
diff --git a/widgets/table/e-table-header-item.h b/widgets/table/e-table-header-item.h
index 2e889a6adf..cc3cf8e4f6 100644
--- a/widgets/table/e-table-header-item.h
+++ b/widgets/table/e-table-header-item.h
@@ -1,8 +1,11 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#ifndef _E_TABLE_HEADER_ITEM_H_
#define _E_TABLE_HEADER_ITEM_H_
#include <libgnomeui/gnome-canvas.h>
+#include <gnome-xml/tree.h>
#include "e-table-header.h"
+#include "e-table-sort-info.h"
#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ())
#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem))
@@ -45,6 +48,11 @@ typedef struct {
guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id;
GnomeCanvasItem *drag_mark_item, *remove_item;
GdkBitmap *stipple;
+
+ /*
+ * For column sorting info
+ */
+ ETableSortInfo *sort_info;
} ETableHeaderItem;
typedef struct {
diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c
index 527e7e22bc..8465f28567 100644
--- a/widgets/table/e-table-header.c
+++ b/widgets/table/e-table-header.c
@@ -350,3 +350,134 @@ e_table_header_set_frozen_columns (ETableHeader *eth, int idx)
{
eth->frozen_count = idx;
}
+
+/* Forget model-view here. Really, this information belongs in the view anyway. */
+#if 0
+static void
+set_arrows(ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ ETableCol *col;
+ for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
+ if ( col->col_idx == info.model_col )
+ e_table_column_set_arrow(col, info.ascending ? E_TABLE_COL_ARROW_DOWN : E_TABLE_COL_ARROW_UP);
+ }
+}
+
+static void
+unset_arrows(ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ ETableCol *col;
+ for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
+ if ( col->col_idx == info.model_col )
+ e_table_column_set_arrow(col, E_TABLE_COL_ARROW_NONE);
+ }
+}
+
+ETableHeaderSortInfo
+e_table_header_get_sort_info (ETableHeader *eth)
+{
+ ETableHeaderSortInfo dummy_info = {0, 1};
+ g_return_val_if_fail (eth != NULL, dummy_info);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
+
+ return eth->sort_info;
+}
+
+void
+e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ unset_arrows(eth, eth->sort_info);
+ eth->sort_info = info;
+ set_arrows(eth, eth->sort_info);
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+
+int
+e_table_header_get_group_count (ETableHeader *eth)
+{
+ g_return_val_if_fail (eth != NULL, 0);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
+
+ return eth->grouping_count;
+}
+
+ETableHeaderSortInfo *
+e_table_header_get_groups (ETableHeader *eth)
+{
+ ETableHeaderSortInfo *ret;
+ g_return_val_if_fail (eth != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL);
+
+ ret = g_new (ETableHeaderSortInfo, eth->grouping_count);
+ memcpy (ret, eth->grouping, sizeof (ETableHeaderSortInfo) * eth->grouping_count);
+ return eth->grouping;
+}
+
+ETableHeaderSortInfo
+e_table_header_get_group (ETableHeader *eth, gint index)
+{
+ ETableHeaderSortInfo dummy_info = {0, 1};
+ g_return_val_if_fail (eth != NULL, dummy_info);
+ g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
+ g_return_val_if_fail (index >= 0, dummy_info);
+ g_return_val_if_fail (index < eth->grouping_count, dummy_info);
+
+ return eth->grouping[index];
+}
+
+void
+e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count + 1));
+ memmove(eth->grouping + index + 1, eth->grouping + index, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
+ eth->grouping[index] = info;
+
+ eth->grouping_count ++;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_header_grouping_delete (ETableHeader *eth, gint index)
+{
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ memmove(eth->grouping + index, eth->grouping + index + 1, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
+ eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - 1));
+
+ eth->grouping_count --;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+
+void
+e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx)
+{
+ ETableHeaderSortInfo info;
+
+ g_return_if_fail (eth != NULL);
+ g_return_if_fail (E_IS_TABLE_HEADER (eth));
+
+ if ( old_idx == new_idx )
+ return;
+
+ info = eth->grouping[old_idx];
+ if ( old_idx < new_idx ) {
+ memmove(eth->grouping + old_idx, eth->grouping + old_idx + 1, sizeof(ETableHeaderSortInfo) * (new_idx - old_idx));
+ } else {
+ memmove(eth->grouping + new_idx + 1, eth->grouping + new_idx, sizeof(ETableHeaderSortInfo) * (old_idx - new_idx));
+ }
+ eth->grouping[new_idx] = info;
+
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+}
+#endif
diff --git a/widgets/table/e-table-header.h b/widgets/table/e-table-header.h
index 0b4e40101f..cfd4d68d4a 100644
--- a/widgets/table/e-table-header.h
+++ b/widgets/table/e-table-header.h
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#ifndef _E_TABLE_COLUMN_H_
#define _E_TABLE_COLUMN_H_
@@ -13,6 +14,13 @@ typedef struct _ETableHeader ETableHeader;
#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE))
#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE))
+#if 0
+typedef struct {
+ int model_col;
+ int ascending;
+} ETableHeaderSortInfo;
+#endif
+
/*
* A Columnar header.
*/
@@ -23,6 +31,12 @@ struct _ETableHeader {
ETableCol **columns;
gboolean selectable;
int frozen_count;
+
+#if 0
+ ETableHeaderSortInfo sort_info;
+ ETableHeaderSortInfo *grouping;
+ gint grouping_count;
+#endif
};
typedef struct {
@@ -45,6 +59,19 @@ int e_table_header_index (ETableHeader *eth,
int e_table_header_get_index_at (ETableHeader *eth,
int x_offset);
ETableCol **e_table_header_get_columns (ETableHeader *eth);
+
+#if 0
+ETableHeaderSortInfo e_table_header_get_sort_info (ETableHeader *eth);
+void e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info);
+
+int e_table_header_get_group_count (ETableHeader *eth);
+ETableHeaderSortInfo *e_table_header_get_groups (ETableHeader *eth);
+ETableHeaderSortInfo e_table_header_get_group (ETableHeader *eth, gint index);
+void e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info);
+void e_table_header_grouping_delete (ETableHeader *eth, gint index);
+void e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx);
+#endif
+
gboolean e_table_header_selection_ok (ETableHeader *eth);
int e_table_header_get_selected (ETableHeader *eth);
int e_table_header_total_width (ETableHeader *eth);
diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c
index ef14b98018..660ec20f91 100644
--- a/widgets/table/e-table-model.c
+++ b/widgets/table/e-table-model.c
@@ -156,7 +156,7 @@ e_table_model_get_type (void)
{
GtkTypeInfo info =
{
- "ETableModle",
+ "ETableModel",
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
diff --git a/widgets/table/e-table-sort-info.c b/widgets/table/e-table-sort-info.c
new file mode 100644
index 0000000000..1f465be99b
--- /dev/null
+++ b/widgets/table/e-table-sort-info.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * e-table-sort-info.c: a Table Model
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 Helix Code, Inc.
+ */
+#include <config.h>
+#include <gtk/gtksignal.h>
+#include <gnome-xml/tree.h>
+#include "e-table-sort-info.h"
+
+#define ETM_CLASS(e) ((ETableSortInfoClass *)((GtkObject *)e)->klass)
+
+#define PARENT_TYPE gtk_object_get_type();
+
+
+static GtkObjectClass *e_table_sort_info_parent_class;
+
+enum {
+ SORT_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)
+{
+ ETableSortInfo *etsi;
+
+ etsi = E_TABLE_SORT_INFO (o);
+
+ switch (arg_id){
+ case ARG_GROUPING:
+ etsi->grouping = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+}
+
+static void
+etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ ETableSortInfo *etsi;
+
+ etsi = E_TABLE_SORT_INFO (o);
+
+ switch (arg_id){
+ case ARG_GROUPING:
+ GTK_VALUE_POINTER (*arg) = etsi->grouping;
+ break;
+ }
+}
+
+static void
+e_table_sort_info_class_init (GtkObjectClass *object_class)
+{
+ e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ object_class->set_arg = etsi_set_arg;
+ object_class->get_arg = etsi_get_arg;
+
+ e_table_sort_info_signals [SORT_INFO_CHANGED] =
+ gtk_signal_new ("sort_info_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETableSortInfoClass, sort_info_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL);
+
+ gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER,
+ GTK_ARG_READWRITE, ARG_GROUPING);
+}
+
+
+guint
+e_table_sort_info_get_type (void)
+{
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "ETableSortInfo",
+ sizeof (ETableSortInfo),
+ sizeof (ETableSortInfoClass),
+ (GtkClassInitFunc) e_table_sort_info_class_init,
+ NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gtk_object_get_type(), &info);
+ }
+
+ return type;
+}
+
+void
+e_table_sort_info_changed (ETableSortInfo *e_table_sort_info)
+{
+ g_return_if_fail (e_table_sort_info != NULL);
+ g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info));
+
+ gtk_signal_emit (GTK_OBJECT (e_table_sort_info),
+ e_table_sort_info_signals [SORT_INFO_CHANGED]);
+}
+
+ETableSortInfo *
+e_table_sort_info_new (void)
+{
+ return gtk_type_new (e_table_sort_info_get_type ());
+}
diff --git a/widgets/table/e-table-sort-info.h b/widgets/table/e-table-sort-info.h
new file mode 100644
index 0000000000..0fc4cd52ef
--- /dev/null
+++ b/widgets/table/e-table-sort-info.h
@@ -0,0 +1,37 @@
+
+/* -*- 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_
+
+#include <gtk/gtkobject.h>
+
+#define E_TABLE_SORT_INFO_TYPE (e_table_sort_info_get_type ())
+#define E_TABLE_SORT_INFO(o) (GTK_CHECK_CAST ((o), E_TABLE_SORT_INFO_TYPE, ETableSortInfo))
+#define E_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORT_INFO_TYPE, ETableSortInfoClass))
+#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 {
+ GtkObject base;
+
+ xmlNode *grouping;
+} ETableSortInfo;
+
+typedef struct {
+ GtkObjectClass parent_class;
+
+ /*
+ * Signals
+ */
+ void (*sort_info_changed) (ETableSortInfo *etm);
+} ETableSortInfoClass;
+
+GtkType e_table_sort_info_get_type (void);
+
+/*
+ * 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);
+
+#endif /* _E_TABLE_SORT_INFO_H_ */
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 4bd4417cd0..b1c14b958a 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -35,6 +35,7 @@
static GtkObjectClass *e_table_parent_class;
static void e_table_fill_table (ETable *e_table, ETableModel *model);
+static gboolean changed_idle (gpointer data);
static void
et_destroy (GtkObject *object)
@@ -44,6 +45,7 @@ et_destroy (GtkObject *object)
gtk_object_unref (GTK_OBJECT (et->model));
gtk_object_unref (GTK_OBJECT (et->full_header));
gtk_object_unref (GTK_OBJECT (et->header));
+ gtk_object_unref (GTK_OBJECT (et->sort_info));
gtk_widget_destroy (GTK_WIDGET (et->header_canvas));
gtk_widget_destroy (GTK_WIDGET (et->table_canvas));
@@ -53,6 +55,9 @@ et_destroy (GtkObject *object)
et->table_row_change_id);
gtk_signal_disconnect (GTK_OBJECT (et->model),
et->table_cell_change_id);
+ if (et->sort_info_change_id)
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->sort_info_change_id);
if (et->rebuild_idle_id) {
g_source_remove(et->rebuild_idle_id);
@@ -68,6 +73,9 @@ static void
e_table_init (GtkObject *object)
{
ETable *e_table = E_TABLE (object);
+
+ e_table->sort_info = NULL;
+ e_table->sort_info_change_id = 0;
e_table->draw_grid = 1;
e_table->draw_focus = 1;
@@ -110,18 +118,46 @@ header_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t
}
static void
+sort_info_changed (ETableSortInfo *info, ETable *et)
+{
+ et->need_rebuild = TRUE;
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
e_table_setup_header (ETable *e_table)
{
+ xmlNode *root;
+ xmlNode *grouping;
e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ());
-
+
gtk_widget_show (GTK_WIDGET (e_table->header_canvas));
+ root = xmlDocGetRootElement(e_table->specification);
+ grouping = e_xml_get_child_by_name(root, "grouping");
+
+ e_table->sort_info = e_table_sort_info_new();
+
+ 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);
+
+ 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->header_item = gnome_canvas_item_new (
gnome_canvas_root (e_table->header_canvas),
e_table_header_item_get_type (),
"ETableHeader", e_table->header,
"x", 0,
"y", 0,
+ "sort_info", e_table->sort_info,
NULL);
gtk_signal_connect (
@@ -705,7 +741,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm,
gtk_widget_show (vscrollbar);
gtk_table_attach (
GTK_TABLE (e_table), vscrollbar,
- 1, 2, 1, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0);
+ 1, 2, 0, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0);
gtk_widget_pop_colormap ();
gtk_widget_pop_visual ();
diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h
index 5c29c1fa0c..9c5bb9b8a0 100644
--- a/widgets/table/e-table.h
+++ b/widgets/table/e-table.h
@@ -8,6 +8,7 @@
#include "e-table-model.h"
#include "e-table-header.h"
#include "e-table-group.h"
+#include "e-table-sort-info.h"
BEGIN_GNOME_DECLS
@@ -26,10 +27,14 @@ typedef struct {
ETableGroup *group;
+ ETableSortInfo *sort_info;
+
int table_model_change_id;
int table_row_change_id;
int table_cell_change_id;
+ int sort_info_change_id;
+
GnomeCanvas *header_canvas, *table_canvas;
GnomeCanvasItem *header_item, *root;