aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorChristopher James Lahey <clahey@helixcode.com>2000-02-25 12:08:59 +0800
committerChris Lahey <clahey@src.gnome.org>2000-02-25 12:08:59 +0800
commit14bfde56c8c54c7ad947dcf96be38f8b4e71e53e (patch)
tree68a453e6dfaebe6fbd92cd03c9a2dc797fa6bc85 /widgets
parent675d1c25dbedaccbb135dc8ccd784e6706aa4aaa (diff)
downloadgsoc2013-evolution-14bfde56c8c54c7ad947dcf96be38f8b4e71e53e.tar.gz
gsoc2013-evolution-14bfde56c8c54c7ad947dcf96be38f8b4e71e53e.tar.zst
gsoc2013-evolution-14bfde56c8c54c7ad947dcf96be38f8b4e71e53e.zip
Added duplicate_value and add_value. Use the new compare functions. Made
2000-02-24 Christopher James Lahey <clahey@helixcode.com> * test-table.c: Added duplicate_value and add_value. Use the new compare functions. Made it so we only create one model to better test model view stuff. Changed the test to not have as many extra, useless, columns. * test-cols.c, test-check.c: Added duplicate_value and add_value. Use the new compare functions. * e-table.c, e-table.h: Use all the new features of e-table-groups (sorting and grouping). Handle on the fly reorganization of groups in an idle loop. Compare functions now are to return -1 if the first item is greater, 0 if they are equal, or 1 if the second item is greater. * e-table-subset.c, e-table-subset.h: Made e-table-subset disconnect properly from its signals when it dies. * e-table-subset-variable.c, e-table-subset-variable.h: Virtualized the add and remove commands so that e_table_sorted_variable could override the add command to do sorting. * e-table-sorted.c: Fixed this to inherit properly from ETableSubset. * e-table-simple.h, e-table-simple.c: Added handling of duplicate_value and free_value; * e-table-model.c, e-table-model.h: Added duplicate_value and free_value for memory allocation of table elements outside the table. * e-table-item.c: Fixed a crashing bug. * e-table-group.c: Added sorting. Fixed destruction to delete the right things. * e-table-group-leaf.c, e-table-group-leaf.h: Pass column and sort order information into the e_table_sorted_variable. Properly destroy things when deleted. * e-table-group-container.c, e-table-group-container.h: Properly handle the list of subgroups. Handle proper sorting and grouping of subgroups. * e-table-sorted-variable.c, e-table-sorted-variable.h: Files to do a sorted model that stays sorted as you add and remove rows. * Makefile.am: Added e-table-sorted-variable.c and e-table-sorted-variable.h. svn path=/trunk/; revision=1930
Diffstat (limited to 'widgets')
-rw-r--r--widgets/e-table/ChangeLog52
-rw-r--r--widgets/e-table/Makefile.am2
-rw-r--r--widgets/e-table/e-table-group-container.c56
-rw-r--r--widgets/e-table/e-table-group-container.h5
-rw-r--r--widgets/e-table/e-table-group-leaf.c18
-rw-r--r--widgets/e-table/e-table-group-leaf.h6
-rw-r--r--widgets/e-table/e-table-group.c39
-rw-r--r--widgets/e-table/e-table-item.c4
-rw-r--r--widgets/e-table/e-table-model.c66
-rw-r--r--widgets/e-table/e-table-model.h9
-rw-r--r--widgets/e-table/e-table-simple.c22
-rw-r--r--widgets/e-table/e-table-simple.h6
-rw-r--r--widgets/e-table/e-table-sorted-variable.c148
-rw-r--r--widgets/e-table/e-table-sorted-variable.h34
-rw-r--r--widgets/e-table/e-table-sorted.c2
-rw-r--r--widgets/e-table/e-table-subset-variable.c80
-rw-r--r--widgets/e-table/e-table-subset-variable.h5
-rw-r--r--widgets/e-table/e-table-subset.c41
-rw-r--r--widgets/e-table/e-table-subset.h4
-rw-r--r--widgets/e-table/e-table.c98
-rw-r--r--widgets/e-table/e-table.h10
-rw-r--r--widgets/e-table/test-check.c26
-rw-r--r--widgets/e-table/test-cols.c27
-rw-r--r--widgets/e-table/test-table.c39
-rw-r--r--widgets/table/e-table-group-container.c56
-rw-r--r--widgets/table/e-table-group-container.h5
-rw-r--r--widgets/table/e-table-group-leaf.c18
-rw-r--r--widgets/table/e-table-group-leaf.h6
-rw-r--r--widgets/table/e-table-group.c39
-rw-r--r--widgets/table/e-table-item.c4
-rw-r--r--widgets/table/e-table-model.c66
-rw-r--r--widgets/table/e-table-model.h9
-rw-r--r--widgets/table/e-table-simple.c22
-rw-r--r--widgets/table/e-table-simple.h6
-rw-r--r--widgets/table/e-table-sorted-variable.c148
-rw-r--r--widgets/table/e-table-sorted-variable.h34
-rw-r--r--widgets/table/e-table-sorted.c2
-rw-r--r--widgets/table/e-table-subset-variable.c80
-rw-r--r--widgets/table/e-table-subset-variable.h5
-rw-r--r--widgets/table/e-table-subset.c41
-rw-r--r--widgets/table/e-table-subset.h4
-rw-r--r--widgets/table/e-table.c98
-rw-r--r--widgets/table/e-table.h10
-rw-r--r--widgets/table/test-check.c26
-rw-r--r--widgets/table/test-cols.c27
-rw-r--r--widgets/table/test-table.c39
46 files changed, 1354 insertions, 190 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog
index e4caa9707c..4c4a9d65cd 100644
--- a/widgets/e-table/ChangeLog
+++ b/widgets/e-table/ChangeLog
@@ -1,5 +1,57 @@
2000-02-24 Christopher James Lahey <clahey@helixcode.com>
+ * test-table.c: Added duplicate_value and add_value. Use the new
+ compare functions. Made it so we only create one model to better
+ test model view stuff. Changed the test to not have as many
+ extra, useless, columns.
+
+ * test-cols.c, test-check.c: Added duplicate_value and add_value. Use the new
+ compare functions.
+
+ * e-table.c, e-table.h: Use all the new features of e-table-groups
+ (sorting and grouping). Handle on the fly reorganization of
+ groups in an idle loop. Compare functions now are to return -1 if
+ the first item is greater, 0 if they are equal, or 1 if the second
+ item is greater.
+
+ * e-table-subset.c, e-table-subset.h: Made e-table-subset
+ disconnect properly from its signals when it dies.
+
+ * e-table-subset-variable.c, e-table-subset-variable.h:
+ Virtualized the add and remove commands so that
+ e_table_sorted_variable could override the add command to do sorting.
+
+ * e-table-sorted.c: Fixed this to inherit properly from
+ ETableSubset.
+
+ * e-table-simple.h, e-table-simple.c: Added handling of
+ duplicate_value and free_value;
+
+ * e-table-model.c, e-table-model.h: Added duplicate_value and
+ free_value for memory allocation of table elements outside the
+ table.
+
+ * e-table-item.c: Fixed a crashing bug.
+
+ * e-table-group.c: Added sorting. Fixed destruction to delete the
+ right things.
+
+ * e-table-group-leaf.c, e-table-group-leaf.h: Pass column and sort
+ order information into the e_table_sorted_variable. Properly
+ destroy things when deleted.
+
+ * e-table-group-container.c, e-table-group-container.h: Properly
+ handle the list of subgroups. Handle proper sorting and grouping
+ of subgroups.
+
+ * e-table-sorted-variable.c, e-table-sorted-variable.h: Files to
+ do a sorted model that stays sorted as you add and remove rows.
+
+ * Makefile.am: Added e-table-sorted-variable.c and
+ e-table-sorted-variable.h.
+
+2000-02-24 Christopher James Lahey <clahey@helixcode.com>
+
* e-table-item.c: Made keyboard focus navigation work across
groups.
diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am
index 0780ae7c57..c6fe615258 100644
--- a/widgets/e-table/Makefile.am
+++ b/widgets/e-table/Makefile.am
@@ -39,6 +39,8 @@ libetable_a_SOURCES = \
e-table-simple.h \
e-table-sorted.c \
e-table-sorted.h \
+ e-table-sorted-variable.c \
+ e-table-sorted-variable.h \
e-table-subset.c \
e-table-subset.h \
e-table-subset-variable.c \
diff --git a/widgets/e-table/e-table-group-container.c b/widgets/e-table/e-table-group-container.c
index 634d7934ef..4b30f6af29 100644
--- a/widgets/e-table/e-table-group-container.c
+++ b/widgets/e-table/e-table-group-container.c
@@ -60,14 +60,41 @@ typedef struct {
} ETableGroupContainerChildNode;
static void
+e_table_group_container_child_node_free(ETableGroupContainer *etgc, ETableGroupContainerChildNode *child_node)
+{
+ ETableGroup *etg = E_TABLE_GROUP(etgc);
+ ETableGroup *child = child_node->child;
+ gtk_object_destroy(GTK_OBJECT(child));
+ e_table_model_free_value(etg->model, etgc->ecol->col_idx, child_node->key);
+ gtk_object_destroy(GTK_OBJECT(child_node->text));
+ gtk_object_destroy(GTK_OBJECT(child_node->rect));
+}
+
+static void
+e_table_group_container_list_free(ETableGroupContainer *etgc)
+{
+ ETableGroupContainerChildNode *child_node;
+ GList *list;
+ for ( list = etgc->children; list; list = g_list_next(list) ) {
+ child_node = (ETableGroupContainerChildNode *) list->data;
+ e_table_group_container_child_node_free(etgc, child_node);
+ }
+ g_list_free(etgc->children);
+}
+
+static void
etgc_destroy (GtkObject *object)
{
ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (object);
gdk_font_unref(etgc->font);
+ gtk_object_unref(GTK_OBJECT(etgc->ecol));
+ gtk_object_destroy(GTK_OBJECT(etgc->rect));
+ e_table_group_container_list_free(etgc);
GTK_OBJECT_CLASS (etgc_parent_class)->destroy (object);
}
+
#if 0
void
e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item)
@@ -168,11 +195,13 @@ void
e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules)
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules)
{
e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model);
etgc->ecol = ecol;
+ gtk_object_ref(GTK_OBJECT(etgc->ecol));
etgc->child_rules = child_rules;
+ etgc->ascending = ascending;
etgc->font = gdk_font_load ("lucidasans-10");
#if 0
@@ -217,7 +246,7 @@ 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, xmlNode *child_rules)
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules)
{
ETableGroupContainer *etgc;
@@ -227,7 +256,7 @@ e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_
etgc = gtk_type_new (e_table_group_container_get_type ());
e_table_group_container_construct (parent, etgc, full_header, header,
- model, ecol, child_rules);
+ model, ecol, ascending, child_rules);
return E_TABLE_GROUP (etgc);
}
@@ -498,15 +527,21 @@ static void etgc_add (ETableGroup *etg, gint row)
GList *list = etgc->children;
ETableGroup *child;
ETableGroupContainerChildNode *child_node;
- for ( ; list; list = g_list_next(list) ) {
+ int i = 0;
+ for ( ; list; list = g_list_next(list), i++ ) {
+ int comp_val;
child_node = (ETableGroupContainerChildNode *)(list->data);
- if ( (*comp)(child_node->key, val) ) {
+ comp_val = (*comp)(child_node->key, val);
+ if ( comp_val == 0 ) {
child = child_node->child;
child_node->count ++;
e_table_group_add(child, row);
compute_text(etgc, child_node);
return;
}
+ if ( (comp_val > 0 && etgc->ascending) ||
+ (comp_val < 0 && (!etgc->ascending)) )
+ break;
}
child_node = g_new(ETableGroupContainerChildNode, 1);
child_node->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc),
@@ -524,13 +559,17 @@ static void etgc_add (ETableGroup *etg, gint row)
NULL);
child = e_table_group_new(GNOME_CANVAS_GROUP(etgc), etg->full_header, etg->header, etg->model, etgc->child_rules);
child_node->child = child;
- child_node->key = val;
+ child_node->key = e_table_model_duplicate_value(etg->model, etgc->ecol->col_idx, val);
gtk_signal_connect(GTK_OBJECT(child), "resize",
etgc_child_resize, etgc);
child_node->count = 1;
e_table_group_add(child, row);
- etgc->children = g_list_append(etgc->children, child_node);
+ if ( list ) {
+ etgc->children = g_list_insert(etgc->children, child_node, i);
+ }
+ else
+ etgc->children = g_list_append(etgc->children, child_node);
compute_text(etgc, child_node);
etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg));
}
@@ -545,8 +584,7 @@ static gboolean etgc_remove (ETableGroup *etg, gint row)
if ( e_table_group_remove(child, row) ) {
child_node->count --;
if ( child_node->count == 0 ) {
- gtk_object_unref(GTK_OBJECT(child_node->text));
- gtk_object_unref(GTK_OBJECT(child));
+ e_table_group_container_child_node_free(etgc, child_node);
etgc->children = g_list_remove(etgc->children, child_node);
g_free(child_node);
} else {
diff --git a/widgets/e-table/e-table-group-container.h b/widgets/e-table/e-table-group-container.h
index 4942f9e695..2234e77ac1 100644
--- a/widgets/e-table/e-table-group-container.h
+++ b/widgets/e-table/e-table-group-container.h
@@ -20,6 +20,7 @@ typedef struct {
* The ETableCol used to group this set
*/
ETableCol *ecol;
+ gint ascending;
/*
* List of ETableGroups we stack
@@ -55,11 +56,11 @@ typedef struct {
} ETableGroupContainerClass;
ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules);
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules);
void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules);
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules);
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 ba73ad9886..2e939453d7 100644
--- a/widgets/e-table/e-table-group-leaf.c
+++ b/widgets/e-table/e-table-group-leaf.c
@@ -36,23 +36,31 @@ static void etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static void
etgl_destroy (GtkObject *object)
{
- GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object);
+ ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF(object);
+ gtk_object_unref(GTK_OBJECT(etgl->subset));
+ gtk_object_destroy(GTK_OBJECT(etgl->item));
+ if ( GTK_OBJECT_CLASS (etgl_parent_class)->destroy )
+ GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object);
}
static void
e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model)
+ ETableModel *model,
+ int col,
+ int ascending)
{
+ etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new(model, col, ascending, e_table_header_get_column(full_header, col)->compare));
e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model);
- etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_subset_variable_new(model));
}
ETableGroup *
e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model)
+ ETableModel *model,
+ int col,
+ int ascending)
{
ETableGroupLeaf *etgl;
@@ -61,7 +69,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);
+ header, model, col, ascending);
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 372bf4cc70..6ffd9066d1 100644
--- a/widgets/e-table/e-table-group-leaf.h
+++ b/widgets/e-table/e-table-group-leaf.h
@@ -4,7 +4,7 @@
#include <libgnomeui/gnome-canvas.h>
#include "e-table-group.h"
-#include "e-table-subset-variable.h"
+#include "e-table-sorted-variable.h"
#include "e-table-item.h"
#define E_TABLE_GROUP_LEAF_TYPE (e_table_group_leaf_get_type ())
@@ -33,7 +33,9 @@ typedef struct {
ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model);
+ ETableModel *model,
+ int col,
+ int ascending);
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 1f4e2037cd..6ae8a25db7 100644
--- a/widgets/e-table/e-table-group.c
+++ b/widgets/e-table/e-table-group.c
@@ -17,6 +17,7 @@
#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
@@ -45,7 +46,7 @@ enum {
static void etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static void etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static gboolean etg_get_focus (ETableGroup *etg);
-
+static void etg_destroy (GtkObject *object);
#if 0
GnomeCanvasItem *
e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
@@ -64,6 +65,17 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
}
#endif
+static void
+etg_destroy (GtkObject *object)
+{
+ ETableGroup *etg = E_TABLE_GROUP(object);
+ gtk_object_unref(GTK_OBJECT(etg->header));
+ gtk_object_unref(GTK_OBJECT(etg->full_header));
+ gtk_object_unref(GTK_OBJECT(etg->model));
+ if ( GTK_OBJECT_CLASS (etg_parent_class)->destroy )
+ GTK_OBJECT_CLASS (etg_parent_class)->destroy (object);
+}
+
ETableGroup *
e_table_group_new (GnomeCanvasGroup *parent,
ETableHeader *full_header,
@@ -71,17 +83,22 @@ e_table_group_new (GnomeCanvasGroup *parent,
ETableModel *model,
xmlNode *rules)
{
+ 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")) {
- gint col_idx = atoi(xmlGetProp(rules, "column"));
ETableCol *col;
- if ( col_idx > e_table_header_count(full_header) )
- return e_table_group_leaf_new(parent, full_header, header, model);
- col = e_table_header_get_columns(full_header)[col_idx];
- return e_table_group_container_new(parent, full_header, header, model, col, rules->childs);
+ 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);
} else {
- return e_table_group_leaf_new(parent, full_header, header, model);
+ return e_table_group_leaf_new(parent, full_header, header, model, column, ascending);
}
return NULL;
}
@@ -93,10 +110,13 @@ e_table_group_construct (GnomeCanvasGroup *parent,
ETableHeader *header,
ETableModel *model)
{
- gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL);
etg->full_header = full_header;
+ gtk_object_ref(GTK_OBJECT(etg->full_header));
etg->header = header;
+ gtk_object_ref(GTK_OBJECT(etg->header));
etg->model = model;
+ gtk_object_ref(GTK_OBJECT(etg->model));
+ gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL);
}
void
@@ -311,6 +331,7 @@ etg_class_init (GtkObjectClass *object_class)
object_class->set_arg = etg_set_arg;
object_class->get_arg = etg_get_arg;
+ object_class->destroy = etg_destroy;
item_class->event = etg_event;
diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c
index 286b1a8352..a7d5573fad 100644
--- a/widgets/e-table/e-table-item.c
+++ b/widgets/e-table/e-table-item.c
@@ -307,6 +307,10 @@ static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
eti->rows = e_table_model_row_count (eti->table_model);
+
+ if (eti->focused_row > eti->rows - 1) {
+ eti->focused_row = eti->rows - 1;
+ }
if (eti->cell_views)
eti_compute_height (eti);
diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c
index e84e6da4d3..ef14b98018 100644
--- a/widgets/e-table/e-table-model.c
+++ b/widgets/e-table/e-table-model.c
@@ -13,6 +13,9 @@
#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
+#define PARENT_TYPE gtk_object_get_type();
+
+
static GtkObjectClass *e_table_model_parent_class;
enum {
@@ -80,6 +83,28 @@ e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
+void *
+e_table_model_duplicate_value (ETableModel *e_table_model, int col, const void *value)
+{
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ if (ETM_CLASS (e_table_model)->duplicate_value)
+ return ETM_CLASS (e_table_model)->duplicate_value (e_table_model, col, value);
+ else
+ return NULL;
+}
+
+void
+e_table_model_free_value (ETableModel *e_table_model, int col, void *value)
+{
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
+
+ if (ETM_CLASS (e_table_model)->free_value)
+ ETM_CLASS (e_table_model)->free_value (e_table_model, col, value);
+}
+
static void
e_table_model_destroy (GtkObject *object)
{
@@ -121,27 +146,30 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
-GtkType
+
+guint
e_table_model_get_type (void)
{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableModel",
- sizeof (ETableModel),
- sizeof (ETableModelClass),
- (GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (gtk_object_get_type (), &info);
- }
-
- return type;
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "ETableModle",
+ sizeof (ETableModel),
+ sizeof (ETableModelClass),
+ (GtkClassInitFunc) e_table_model_class_init,
+ NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gtk_object_get_type(), &info);
+ }
+
+ return type;
}
void
diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h
index 9f2dbbf87c..ceca8e348f 100644
--- a/widgets/e-table/e-table-model.h
+++ b/widgets/e-table/e-table-model.h
@@ -27,6 +27,10 @@ typedef struct {
void *(*value_at) (ETableModel *etm, int col, int row);
void (*set_value_at) (ETableModel *etm, int col, int row, const void *value);
gboolean (*is_cell_editable) (ETableModel *etm, int col, int row);
+
+ void *(*duplicate_value) (ETableModel *etm, int col, const void *value);
+ void (*free_value) (ETableModel *etm, int col, void *value);
+
void (*thaw) (ETableModel *etm);
/*
* Signals
@@ -48,9 +52,12 @@ int e_table_model_column_count (ETableModel *e_table_model);
const char *e_table_model_column_name (ETableModel *e_table_model, int col);
int e_table_model_row_count (ETableModel *e_table_model);
void *e_table_model_value_at (ETableModel *e_table_model, int col, int row);
-void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data);
+void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *value);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
+void *e_table_model_duplicate_value (ETableModel *e_table_model, int col, const void *value);
+void e_table_model_free_value (ETableModel *e_table_model, int col, void *value);
+
void e_table_model_freeze (ETableModel *e_table_model);
void e_table_model_thaw (ETableModel *e_table_model);
diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c
index 1f64d08f39..e90abfcc4f 100644
--- a/widgets/e-table/e-table-simple.c
+++ b/widgets/e-table/e-table-simple.c
@@ -55,6 +55,22 @@ simple_is_cell_editable (ETableModel *etm, int col, int row)
return simple->is_cell_editable (etm, col, row, simple->data);
}
+static void *
+simple_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->duplicate_value (etm, col, value, simple->data);
+}
+
+static void
+simple_free_value (ETableModel *etm, int col, void *value)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ simple->free_value (etm, col, value, simple->data);
+}
+
static void
simple_thaw (ETableModel *etm)
{
@@ -73,6 +89,8 @@ e_table_simple_class_init (GtkObjectClass *object_class)
model_class->value_at = simple_value_at;
model_class->set_value_at = simple_set_value_at;
model_class->is_cell_editable = simple_is_cell_editable;
+ model_class->duplicate_value = simple_duplicate_value;
+ model_class->free_value = simple_free_value;
model_class->thaw = simple_thaw;
}
@@ -105,6 +123,8 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count,
ETableSimpleValueAtFn value_at,
ETableSimpleSetValueAtFn set_value_at,
ETableSimpleIsCellEditableFn is_cell_editable,
+ ETableSimpleDuplicateValueFn duplicate_value,
+ ETableSimpleFreeValueFn free_value,
ETableSimpleThawFn thaw,
void *data)
{
@@ -118,6 +138,8 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count,
et->set_value_at = set_value_at;
et->is_cell_editable = is_cell_editable;
et->thaw = thaw;
+ et->duplicate_value = duplicate_value;
+ et->free_value = free_value;
et->data = data;
return (ETableModel *) et;
diff --git a/widgets/e-table/e-table-simple.h b/widgets/e-table/e-table-simple.h
index a3164eefc0..51134f45aa 100644
--- a/widgets/e-table/e-table-simple.h
+++ b/widgets/e-table/e-table-simple.h
@@ -9,6 +9,8 @@ typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *dat
typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data);
typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data);
typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data);
+typedef void *(*ETableSimpleDuplicateValueFn) (ETableModel *etm, int col, const void *val, void *data);
+typedef void (*ETableSimpleFreeValueFn) (ETableModel *etm, int col, void *val, void *data);
typedef void (*ETableSimpleThawFn) (ETableModel *etm, void *data);
typedef struct {
@@ -19,6 +21,8 @@ typedef struct {
ETableSimpleValueAtFn value_at;
ETableSimpleSetValueAtFn set_value_at;
ETableSimpleIsCellEditableFn is_cell_editable;
+ ETableSimpleDuplicateValueFn duplicate_value;
+ ETableSimpleFreeValueFn free_value;
ETableSimpleThawFn thaw;
void *data;
} ETableSimple;
@@ -34,6 +38,8 @@ ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count,
ETableSimpleValueAtFn value_at,
ETableSimpleSetValueAtFn set_value_at,
ETableSimpleIsCellEditableFn is_cell_editable,
+ ETableSimpleDuplicateValueFn duplicate_value,
+ ETableSimpleFreeValueFn free_value,
ETableSimpleThawFn thaw,
void *data);
diff --git a/widgets/e-table/e-table-sorted-variable.c b/widgets/e-table/e-table-sorted-variable.c
new file mode 100644
index 0000000000..478038fdb7
--- /dev/null
+++ b/widgets/e-table/e-table-sorted-variable.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * E-table-sorted.c: Implements a table that sorts another table
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 Helix Code, Inc.
+ */
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
+#include <string.h>
+#include "e-util/e-util.h"
+#include "e-table-sorted-variable.h"
+
+#define PARENT_TYPE E_TABLE_SUBSET_VARIABLE_TYPE
+
+#define INCREMENT_AMOUNT 10
+
+static ETableSubsetVariableClass *etsv_parent_class;
+
+static void etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv);
+static void etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv);
+static void etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv);
+static void etsv_add (ETableSubsetVariable *etssv, gint row);
+
+static void
+etsv_destroy (GtkObject *object)
+{
+ ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (object);
+ ETableSubset *etss = E_TABLE_SUBSET (object);
+
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_row_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_cell_changed_id);
+
+ etsv->table_model_changed_id = 0;
+ etsv->table_model_row_changed_id = 0;
+ etsv->table_model_cell_changed_id = 0;
+
+ GTK_OBJECT_CLASS (etsv_parent_class)->destroy (object);
+}
+
+static void
+etsv_class_init (GtkObjectClass *object_class)
+{
+ ETableSubsetVariableClass *etssv_class = E_TABLE_SUBSET_VARIABLE_CLASS(object_class);
+
+ etsv_parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = etsv_destroy;
+
+ etssv_class->add = etsv_add;
+}
+
+E_MAKE_TYPE(e_table_sorted_variable, "ETableSortedVariable", ETableSortedVariable, etsv_class_init, NULL, PARENT_TYPE);
+
+static void
+etsv_add (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(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;
+
+ 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) )
+ break;
+ }
+ if ( etss->n_map + 1 > etssv->n_vals_allocated ) {
+ etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
+ etssv->n_vals_allocated += INCREMENT_AMOUNT;
+ }
+ if ( i < etss->n_map )
+ memmove(etss->map_table + i + 1, etss->map_table + i, (etss->n_map - i) * sizeof(int));
+ etss->map_table[i] = row;
+ etss->n_map++;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+}
+
+ETableModel *
+e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompareFunc compare)
+{
+ ETableSortedVariable *etsv = gtk_type_new (E_TABLE_SORTED_VARIABLE_TYPE);
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE (etsv);
+
+ if (e_table_subset_variable_construct (etssv, source) == NULL){
+ gtk_object_destroy (GTK_OBJECT (etsv));
+ return NULL;
+ }
+
+ etsv->sort_col = col;
+ etsv->ascending = ascending;
+ etsv->compare = compare;
+
+ etsv->table_model_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_changed), etsv);
+ etsv->table_model_row_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_row_changed), etsv);
+ etsv->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_cell_changed), etsv);
+
+ return E_TABLE_MODEL(etsv);
+}
+
+static void
+etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv)
+{
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ /* FIXME: do_resort(); */
+ }
+}
+
+static void
+etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv)
+{
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv);
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ if(e_table_subset_variable_remove(etssv, row))
+ e_table_subset_variable_add(etssv, row);
+ }
+}
+
+static void
+etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv)
+{
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv);
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ if ( col == etsv->sort_col ) {
+ 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
new file mode 100644
index 0000000000..cf188acd4a
--- /dev/null
+++ b/widgets/e-table/e-table-sorted-variable.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _E_TABLE_SORTED_VARIABLE_H_
+#define _E_TABLE_SORTED_VARIABLE_H_
+
+#include <gtk/gtkobject.h>
+#include "e-table-model.h"
+#include "e-table-subset-variable.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))
+#define E_TABLE_SORTED_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORTED_VARIABLE_TYPE, ETableSortedVariableClass))
+#define E_IS_TABLE_SORTED_VARIABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORTED_VARIABLE_TYPE))
+#define E_IS_TABLE_SORTED_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_VARIABLE_TYPE))
+
+typedef struct {
+ ETableSubsetVariable base;
+
+ short sort_col;
+ int ascending;
+ GCompareFunc compare;
+
+ int table_model_changed_id;
+ int table_model_row_changed_id;
+ int table_model_cell_changed_id;
+} ETableSortedVariable;
+
+typedef struct {
+ ETableSubsetVariableClass parent_class;
+} ETableSortedVariableClass;
+
+GtkType e_table_sorted_variable_get_type (void);
+ETableModel *e_table_sorted_variable_new (ETableModel *etm, int col, int ascending, GCompareFunc compare);
+
+#endif /* _E_TABLE_SORTED_VARIABLE_H_ */
diff --git a/widgets/e-table/e-table-sorted.c b/widgets/e-table/e-table-sorted.c
index 16644a45b1..c754f4cff7 100644
--- a/widgets/e-table/e-table-sorted.c
+++ b/widgets/e-table/e-table-sorted.c
@@ -13,7 +13,7 @@
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
-static ETableModelClass *ets_parent_class;
+static ETableSubsetClass *ets_parent_class;
static void
ets_class_init (GtkObjectClass *klass)
diff --git a/widgets/e-table/e-table-subset-variable.c b/widgets/e-table/e-table-subset-variable.c
index 76da03c44f..5a3e0f2ddf 100644
--- a/widgets/e-table/e-table-subset-variable.c
+++ b/widgets/e-table/e-table-subset-variable.c
@@ -14,16 +14,58 @@
#include "e-util/e-util.h"
#include "e-table-subset-variable.h"
+#define ETSSV_CLASS(e) ((ETableSubsetVariableClass *)((GtkObject *)e)->klass)
+
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
#define INCREMENT_AMOUNT 10
-static ETableModelClass *etssv_parent_class;
+static ETableSubsetClass *etssv_parent_class;
+
+static void
+etssv_add (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(etssv);
+ ETableSubset *etss = E_TABLE_SUBSET(etssv);
+
+ if ( etss->n_map + 1 > etssv->n_vals_allocated ) {
+ etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
+ etssv->n_vals_allocated += INCREMENT_AMOUNT;
+ }
+ etss->map_table[etss->n_map++] = row;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+}
+
+static gboolean
+etssv_remove (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(etssv);
+ ETableSubset *etss = E_TABLE_SUBSET(etssv);
+ int i;
+
+ for ( i = 0; i < etss->n_map; i++ ) {
+ if (etss->map_table[i] == row) {
+ memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int));
+ etss->n_map --;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
static void
-etssv_class_init (GtkObjectClass *klass)
+etssv_class_init (GtkObjectClass *object_class)
{
+ ETableSubsetVariableClass *klass = E_TABLE_SUBSET_VARIABLE_CLASS(object_class);
etssv_parent_class = gtk_type_class (PARENT_TYPE);
+
+ klass->add = etssv_add;
+ klass->remove = etssv_remove;
}
E_MAKE_TYPE(e_table_subset_variable, "ETableSubsetVariable", ETableSubsetVariable, etssv_class_init, NULL, PARENT_TYPE);
@@ -56,34 +98,24 @@ void
e_table_subset_variable_add (ETableSubsetVariable *etssv,
gint row)
{
- ETableModel *etm = E_TABLE_MODEL(etssv);
- ETableSubset *etss = E_TABLE_SUBSET(etssv);
-
- if ( etss->n_map + 1 > etssv->n_vals_allocated )
- etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
- etss->map_table[etss->n_map++] = row;
- if ( !etm->frozen )
- e_table_model_changed(etm);
+ g_return_if_fail (etssv != NULL);
+ g_return_if_fail (E_IS_TABLE_SUBSET_VARIABLE(etssv));
+
+ if (ETSSV_CLASS(etssv)->add)
+ ETSSV_CLASS (etssv)->add (etssv, row);
}
gboolean
e_table_subset_variable_remove (ETableSubsetVariable *etssv,
gint row)
{
- ETableModel *etm = E_TABLE_MODEL(etssv);
- ETableSubset *etss = E_TABLE_SUBSET(etssv);
- int i;
-
- for ( i = 0; i < etss->n_map; i++ ) {
- if (etss->map_table[i] == row) {
- memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int));
- etss->n_map --;
- if ( !etm->frozen )
- e_table_model_changed(etm);
- return TRUE;
- }
- }
- return FALSE;
+ g_return_val_if_fail (etssv != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_SUBSET_VARIABLE(etssv), FALSE);
+
+ if (ETSSV_CLASS(etssv)->remove)
+ return ETSSV_CLASS (etssv)->remove (etssv, row);
+ else
+ return FALSE;
}
void
diff --git a/widgets/e-table/e-table-subset-variable.h b/widgets/e-table/e-table-subset-variable.h
index 9755fb2477..8ac0af0382 100644
--- a/widgets/e-table/e-table-subset-variable.h
+++ b/widgets/e-table/e-table-subset-variable.h
@@ -19,6 +19,11 @@ typedef struct {
typedef struct {
ETableSubsetClass parent_class;
+
+ void (*add) (ETableSubsetVariable *ets,
+ gint row);
+ gboolean (*remove) (ETableSubsetVariable *ets,
+ gint row);
} ETableSubsetVariableClass;
GtkType e_table_subset_variable_get_type (void);
diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c
index a09d221980..b4473b87ef 100644
--- a/widgets/e-table/e-table-subset.c
+++ b/widgets/e-table/e-table-subset.c
@@ -25,6 +25,17 @@ etss_destroy (GtkObject *object)
if (etss->source)
gtk_object_unref (GTK_OBJECT (etss->source));
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_row_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_cell_changed_id);
+
+ etss->table_model_changed_id = 0;
+ etss->table_model_row_changed_id = 0;
+ etss->table_model_cell_changed_id = 0;
+
if (etss->map_table)
free (etss->map_table);
@@ -71,6 +82,22 @@ etss_is_cell_editable (ETableModel *etm, int col, int row)
return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]);
}
+static void *
+etss_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ ETableSubset *etss = (ETableSubset *)etm;
+
+ return e_table_model_duplicate_value (etss->source, col, value);
+}
+
+static void
+etss_free_value (ETableModel *etm, int col, void *value)
+{
+ ETableSubset *etss = (ETableSubset *)etm;
+
+ e_table_model_free_value (etss->source, col, value);
+}
+
static void
etss_thaw (ETableModel *etm)
{
@@ -91,6 +118,8 @@ etss_class_init (GtkObjectClass *klass)
table_class->value_at = etss_value_at;
table_class->set_value_at = etss_set_value_at;
table_class->is_cell_editable = etss_is_cell_editable;
+ table_class->duplicate_value = etss_duplicate_value;
+ table_class->free_value = etss_free_value;
table_class->thaw = etss_thaw;
}
@@ -155,12 +184,12 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals)
for (i = 0; i < nvals; i++)
etss->map_table [i] = i;
- gtk_signal_connect (GTK_OBJECT (source), "model_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
+ etss->table_model_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
+ etss->table_model_row_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
+ etss->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
return E_TABLE_MODEL (etss);
}
diff --git a/widgets/e-table/e-table-subset.h b/widgets/e-table/e-table-subset.h
index d8af1696f5..074120a410 100644
--- a/widgets/e-table/e-table-subset.h
+++ b/widgets/e-table/e-table-subset.h
@@ -17,6 +17,10 @@ typedef struct {
ETableModel *source;
int n_map;
int *map_table;
+
+ int table_model_changed_id;
+ int table_model_row_changed_id;
+ int table_model_cell_changed_id;
} ETableSubset;
typedef struct {
diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c
index 551ef52227..e508e24e02 100644
--- a/widgets/e-table/e-table.c
+++ b/widgets/e-table/e-table.c
@@ -34,6 +34,8 @@
static GtkObjectClass *e_table_parent_class;
+static void e_table_fill_table (ETable *e_table, ETableModel *model);
+
static void
et_destroy (GtkObject *object)
{
@@ -42,6 +44,20 @@ 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_widget_destroy (GTK_WIDGET (et->header_canvas));
+ gtk_widget_destroy (GTK_WIDGET (et->table_canvas));
+
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_model_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_row_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_cell_change_id);
+
+ if (et->rebuild_idle_id) {
+ g_source_remove(et->rebuild_idle_id);
+ et->rebuild_idle_id = 0;
+ }
(*e_table_parent_class->destroy)(object);
}
@@ -54,6 +70,11 @@ e_table_init (GtkObject *object)
e_table->draw_grid = 1;
e_table->draw_focus = 1;
e_table->spreadsheet = 1;
+
+ e_table->need_rebuild = 0;
+ e_table->need_row_changes = 0;
+ e_table->row_changes_list = NULL;
+ e_table->rebuild_idle_id = 0;
}
static ETableHeader *
@@ -528,6 +549,72 @@ table_canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t
}
static void
+change_row (gpointer key, gpointer value, gpointer data)
+{
+ ETable *et = E_TABLE(data);
+ gint row = GPOINTER_TO_INT(key);
+ if ( e_table_group_remove(et->group, row) ) {
+ e_table_group_add(et->group, row);
+ }
+}
+
+static gboolean
+changed_idle (gpointer data)
+{
+ ETable *et = E_TABLE(data);
+ if ( et->need_rebuild ) {
+ gtk_object_destroy( GTK_OBJECT(et->group ) );
+ et->group = e_table_group_new(GNOME_CANVAS_GROUP(et->table_canvas->root),
+ et->full_header,
+ et->header,
+ et->model,
+ e_xml_get_child_by_name(xmlDocGetRootElement(et->specification), "grouping")->childs);
+ e_table_fill_table(et, et->model);
+ } else if (et->need_row_changes) {
+ g_hash_table_foreach(et->row_changes_list, change_row, et);
+ }
+ et->need_rebuild = 0;
+ et->need_row_changes = 0;
+ if (et->row_changes_list)
+ g_hash_table_destroy(et->row_changes_list);
+ et->row_changes_list = NULL;
+ et->rebuild_idle_id = 0;
+ return FALSE;
+}
+
+static void
+et_table_model_changed (ETableModel *model, ETable *et)
+{
+ et->need_rebuild = TRUE;
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
+et_table_row_changed (ETableModel *table_model, int row, ETable *et)
+{
+ if ( !et->need_rebuild ) {
+ if (!et->need_row_changes) {
+ et->need_row_changes = 1;
+ et->row_changes_list = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+ if (!g_hash_table_lookup(et->row_changes_list, GINT_TO_POINTER(row))) {
+ g_hash_table_insert(et->row_changes_list, GINT_TO_POINTER(row), GINT_TO_POINTER(row + 1));
+ }
+ }
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
+et_table_cell_changed (ETableModel *table_model, int view_col, int row, ETable *et)
+{
+ et_table_row_changed(table_model, row, et);
+}
+
+static void
e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, ETableModel *model, xmlNode *xml_grouping)
{
e_table->table_canvas = GNOME_CANVAS(gnome_canvas_new ());
@@ -546,6 +633,17 @@ e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *h
model,
xml_grouping->childs);
+ e_table->table_model_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_changed",
+ GTK_SIGNAL_FUNC (et_table_model_changed), e_table);
+
+ e_table->table_row_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_row_changed",
+ GTK_SIGNAL_FUNC (et_table_row_changed), e_table);
+
+ e_table->table_cell_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_cell_changed",
+ GTK_SIGNAL_FUNC (et_table_cell_changed), e_table);
}
static void
diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h
index a372d8042c..841013c09a 100644
--- a/widgets/e-table/e-table.h
+++ b/widgets/e-table/e-table.h
@@ -26,6 +26,10 @@ typedef struct {
ETableGroup *group;
+ int table_model_change_id;
+ int table_row_change_id;
+ int table_cell_change_id;
+
GnomeCanvas *header_canvas, *table_canvas;
GnomeCanvasItem *header_item, *root;
@@ -35,6 +39,12 @@ typedef struct {
guint draw_grid:1;
guint draw_focus:1;
guint spreadsheet:1;
+
+ guint need_rebuild:1;
+ guint need_row_changes:1;
+
+ GHashTable *row_changes_list;
+ gint rebuild_idle_id;
} ETable;
typedef struct {
diff --git a/widgets/e-table/test-check.c b/widgets/e-table/test-check.c
index a6a59788ad..7894898255 100644
--- a/widgets/e-table/test-check.c
+++ b/widgets/e-table/test-check.c
@@ -14,6 +14,7 @@
#include "e-table-item.h"
#include "e-util/e-cursors.h"
#include "e-util/e-canvas-utils.h"
+#include "e-util/e-util.h"
#include "e-cell-text.h"
#include "e-cell-checkbox.h"
@@ -79,6 +80,24 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ if (col == 0){
+ return (void *) value;
+ } else {
+ return g_strdup(value);
+ }
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ if (col != 0){
+ g_free(value);
+ }
+}
+
static void
thaw (ETableModel *etc, void *data)
{
@@ -107,7 +126,8 @@ check_test (void)
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value, thaw, NULL);
/*
* Header
@@ -118,11 +138,11 @@ check_test (void)
cell_image_check = e_cell_checkbox_new ();
pixbuf = gdk_pixbuf_new_from_file("clip.png");
- col_0 = e_table_col_new_with_pixbuf (0, pixbuf, 18, 18, cell_image_check, g_int_equal, TRUE);
+ col_0 = e_table_col_new_with_pixbuf (0, pixbuf, 18, 18, cell_image_check, g_int_compare, TRUE);
gdk_pixbuf_unref(pixbuf);
e_table_header_add_column (e_table_header, col_0, 0);
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
+ col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_compare, TRUE);
e_table_header_add_column (e_table_header, col_1, 1);
e_table_col_set_arrow ( col_1, E_TABLE_COL_ARROW_DOWN );
diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c
index adc9ed6c20..d65b9945b7 100644
--- a/widgets/e-table/test-cols.c
+++ b/widgets/e-table/test-cols.c
@@ -10,6 +10,7 @@
#include <gnome.h>
#include "e-util/e-canvas-utils.h"
#include "e-util/e-cursors.h"
+#include "e-util/e-util.h"
#include "e-table-simple.h"
#include "e-table-header.h"
#include "e-table-header-item.h"
@@ -79,6 +80,24 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ if (col == 0){
+ return (void *)value;
+ } else {
+ return g_strdup(value);
+ }
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ if (col != 0){
+ g_free(value);
+ }
+}
+
static void
set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc)
{
@@ -106,7 +125,9 @@ multi_cols_test (void)
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value,
+ thaw, NULL);
/*
* Header
@@ -131,10 +152,10 @@ multi_cols_test (void)
g_free (images);
}
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
+ col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_compare, TRUE);
e_table_header_add_column (e_table_header, col_1, 0);
- col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE);
+ col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_compare, TRUE);
e_table_header_add_column (e_table_header, col_0, 1);
/*
diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c
index 1bd50e1479..0fdf32fcbe 100644
--- a/widgets/e-table/test-table.c
+++ b/widgets/e-table/test-table.c
@@ -176,6 +176,18 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ return g_strdup(value);
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ g_free(value);
+}
+
static void
thaw (ETableModel *etc, void *data)
{
@@ -205,7 +217,8 @@ table_browser_test (void)
*/
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value, thaw, NULL);
/*
* Header
@@ -217,7 +230,7 @@ table_browser_test (void)
ETableCol *ecol = e_table_col_new (
i, column_labels [i],
80, 20, cell_left_just,
- g_str_equal, TRUE);
+ g_str_compare, TRUE);
e_table_header_add_column (e_table_header, ecol, i);
}
@@ -263,7 +276,6 @@ static void
do_e_table_demo (const char *spec)
{
GtkWidget *e_table, *window, *frame;
- ETableModel *e_table_model;
ECell *cell_left_just;
ETableHeader *full_header;
int i;
@@ -271,9 +283,14 @@ do_e_table_demo (const char *spec)
/*
* Data model
*/
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ static ETableModel *e_table_model = NULL;
+
+ if ( e_table_model == NULL )
+ e_table_model =
+ e_table_simple_new (col_count, row_count, value_at,
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value,
+ thaw, NULL);
full_header = e_table_header_new ();
cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT, TRUE);
@@ -282,7 +299,7 @@ do_e_table_demo (const char *spec)
ETableCol *ecol = e_table_col_new (
i, column_labels [i],
80, 20, cell_left_just,
- g_str_equal, TRUE);
+ g_str_compare, TRUE);
e_table_header_add_column (full_header, ecol, i);
}
@@ -306,9 +323,9 @@ e_table_test (void)
load_data ();
if (1){/*getenv ("DO")){*/
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf/> </grouping> </ETableSpecification>");
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <group column=\"4\"> <leaf/> </group> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf column=\"3\" ascending=\"1\"/> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\" ascending=\"1\"> <group column=\"4\" ascending=\"0\"> <leaf column=\"2\" ascending=\"1\"/> </group> </group> </grouping> </ETableSpecification>");
}
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\"> <leaf/> </group> </grouping> </ETableSpecification>");
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <leaf/> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\" ascending=\"1\"> <leaf column=\"2\" ascending=\"1\"/> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\" ascending=\"1\"> <leaf column=\"2\" ascending=\"1\"/> </group> </grouping> </ETableSpecification>");
}
diff --git a/widgets/table/e-table-group-container.c b/widgets/table/e-table-group-container.c
index 634d7934ef..4b30f6af29 100644
--- a/widgets/table/e-table-group-container.c
+++ b/widgets/table/e-table-group-container.c
@@ -60,14 +60,41 @@ typedef struct {
} ETableGroupContainerChildNode;
static void
+e_table_group_container_child_node_free(ETableGroupContainer *etgc, ETableGroupContainerChildNode *child_node)
+{
+ ETableGroup *etg = E_TABLE_GROUP(etgc);
+ ETableGroup *child = child_node->child;
+ gtk_object_destroy(GTK_OBJECT(child));
+ e_table_model_free_value(etg->model, etgc->ecol->col_idx, child_node->key);
+ gtk_object_destroy(GTK_OBJECT(child_node->text));
+ gtk_object_destroy(GTK_OBJECT(child_node->rect));
+}
+
+static void
+e_table_group_container_list_free(ETableGroupContainer *etgc)
+{
+ ETableGroupContainerChildNode *child_node;
+ GList *list;
+ for ( list = etgc->children; list; list = g_list_next(list) ) {
+ child_node = (ETableGroupContainerChildNode *) list->data;
+ e_table_group_container_child_node_free(etgc, child_node);
+ }
+ g_list_free(etgc->children);
+}
+
+static void
etgc_destroy (GtkObject *object)
{
ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (object);
gdk_font_unref(etgc->font);
+ gtk_object_unref(GTK_OBJECT(etgc->ecol));
+ gtk_object_destroy(GTK_OBJECT(etgc->rect));
+ e_table_group_container_list_free(etgc);
GTK_OBJECT_CLASS (etgc_parent_class)->destroy (object);
}
+
#if 0
void
e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item)
@@ -168,11 +195,13 @@ void
e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules)
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules)
{
e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model);
etgc->ecol = ecol;
+ gtk_object_ref(GTK_OBJECT(etgc->ecol));
etgc->child_rules = child_rules;
+ etgc->ascending = ascending;
etgc->font = gdk_font_load ("lucidasans-10");
#if 0
@@ -217,7 +246,7 @@ 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, xmlNode *child_rules)
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules)
{
ETableGroupContainer *etgc;
@@ -227,7 +256,7 @@ e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_
etgc = gtk_type_new (e_table_group_container_get_type ());
e_table_group_container_construct (parent, etgc, full_header, header,
- model, ecol, child_rules);
+ model, ecol, ascending, child_rules);
return E_TABLE_GROUP (etgc);
}
@@ -498,15 +527,21 @@ static void etgc_add (ETableGroup *etg, gint row)
GList *list = etgc->children;
ETableGroup *child;
ETableGroupContainerChildNode *child_node;
- for ( ; list; list = g_list_next(list) ) {
+ int i = 0;
+ for ( ; list; list = g_list_next(list), i++ ) {
+ int comp_val;
child_node = (ETableGroupContainerChildNode *)(list->data);
- if ( (*comp)(child_node->key, val) ) {
+ comp_val = (*comp)(child_node->key, val);
+ if ( comp_val == 0 ) {
child = child_node->child;
child_node->count ++;
e_table_group_add(child, row);
compute_text(etgc, child_node);
return;
}
+ if ( (comp_val > 0 && etgc->ascending) ||
+ (comp_val < 0 && (!etgc->ascending)) )
+ break;
}
child_node = g_new(ETableGroupContainerChildNode, 1);
child_node->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc),
@@ -524,13 +559,17 @@ static void etgc_add (ETableGroup *etg, gint row)
NULL);
child = e_table_group_new(GNOME_CANVAS_GROUP(etgc), etg->full_header, etg->header, etg->model, etgc->child_rules);
child_node->child = child;
- child_node->key = val;
+ child_node->key = e_table_model_duplicate_value(etg->model, etgc->ecol->col_idx, val);
gtk_signal_connect(GTK_OBJECT(child), "resize",
etgc_child_resize, etgc);
child_node->count = 1;
e_table_group_add(child, row);
- etgc->children = g_list_append(etgc->children, child_node);
+ if ( list ) {
+ etgc->children = g_list_insert(etgc->children, child_node, i);
+ }
+ else
+ etgc->children = g_list_append(etgc->children, child_node);
compute_text(etgc, child_node);
etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg));
}
@@ -545,8 +584,7 @@ static gboolean etgc_remove (ETableGroup *etg, gint row)
if ( e_table_group_remove(child, row) ) {
child_node->count --;
if ( child_node->count == 0 ) {
- gtk_object_unref(GTK_OBJECT(child_node->text));
- gtk_object_unref(GTK_OBJECT(child));
+ e_table_group_container_child_node_free(etgc, child_node);
etgc->children = g_list_remove(etgc->children, child_node);
g_free(child_node);
} else {
diff --git a/widgets/table/e-table-group-container.h b/widgets/table/e-table-group-container.h
index 4942f9e695..2234e77ac1 100644
--- a/widgets/table/e-table-group-container.h
+++ b/widgets/table/e-table-group-container.h
@@ -20,6 +20,7 @@ typedef struct {
* The ETableCol used to group this set
*/
ETableCol *ecol;
+ gint ascending;
/*
* List of ETableGroups we stack
@@ -55,11 +56,11 @@ typedef struct {
} ETableGroupContainerClass;
ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules);
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules);
void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model, ETableCol *ecol, xmlNode *child_rules);
+ ETableModel *model, ETableCol *ecol, int ascending, xmlNode *child_rules);
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 ba73ad9886..2e939453d7 100644
--- a/widgets/table/e-table-group-leaf.c
+++ b/widgets/table/e-table-group-leaf.c
@@ -36,23 +36,31 @@ static void etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static void
etgl_destroy (GtkObject *object)
{
- GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object);
+ ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF(object);
+ gtk_object_unref(GTK_OBJECT(etgl->subset));
+ gtk_object_destroy(GTK_OBJECT(etgl->item));
+ if ( GTK_OBJECT_CLASS (etgl_parent_class)->destroy )
+ GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object);
}
static void
e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model)
+ ETableModel *model,
+ int col,
+ int ascending)
{
+ etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_sorted_variable_new(model, col, ascending, e_table_header_get_column(full_header, col)->compare));
e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model);
- etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_subset_variable_new(model));
}
ETableGroup *
e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model)
+ ETableModel *model,
+ int col,
+ int ascending)
{
ETableGroupLeaf *etgl;
@@ -61,7 +69,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);
+ header, model, col, ascending);
return E_TABLE_GROUP (etgl);
}
diff --git a/widgets/table/e-table-group-leaf.h b/widgets/table/e-table-group-leaf.h
index 372bf4cc70..6ffd9066d1 100644
--- a/widgets/table/e-table-group-leaf.h
+++ b/widgets/table/e-table-group-leaf.h
@@ -4,7 +4,7 @@
#include <libgnomeui/gnome-canvas.h>
#include "e-table-group.h"
-#include "e-table-subset-variable.h"
+#include "e-table-sorted-variable.h"
#include "e-table-item.h"
#define E_TABLE_GROUP_LEAF_TYPE (e_table_group_leaf_get_type ())
@@ -33,7 +33,9 @@ typedef struct {
ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent,
ETableHeader *full_header,
ETableHeader *header,
- ETableModel *model);
+ ETableModel *model,
+ int col,
+ int ascending);
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 1f4e2037cd..6ae8a25db7 100644
--- a/widgets/table/e-table-group.c
+++ b/widgets/table/e-table-group.c
@@ -17,6 +17,7 @@
#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
@@ -45,7 +46,7 @@ enum {
static void etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static void etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static gboolean etg_get_focus (ETableGroup *etg);
-
+static void etg_destroy (GtkObject *object);
#if 0
GnomeCanvasItem *
e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
@@ -64,6 +65,17 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
}
#endif
+static void
+etg_destroy (GtkObject *object)
+{
+ ETableGroup *etg = E_TABLE_GROUP(object);
+ gtk_object_unref(GTK_OBJECT(etg->header));
+ gtk_object_unref(GTK_OBJECT(etg->full_header));
+ gtk_object_unref(GTK_OBJECT(etg->model));
+ if ( GTK_OBJECT_CLASS (etg_parent_class)->destroy )
+ GTK_OBJECT_CLASS (etg_parent_class)->destroy (object);
+}
+
ETableGroup *
e_table_group_new (GnomeCanvasGroup *parent,
ETableHeader *full_header,
@@ -71,17 +83,22 @@ e_table_group_new (GnomeCanvasGroup *parent,
ETableModel *model,
xmlNode *rules)
{
+ 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")) {
- gint col_idx = atoi(xmlGetProp(rules, "column"));
ETableCol *col;
- if ( col_idx > e_table_header_count(full_header) )
- return e_table_group_leaf_new(parent, full_header, header, model);
- col = e_table_header_get_columns(full_header)[col_idx];
- return e_table_group_container_new(parent, full_header, header, model, col, rules->childs);
+ 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);
} else {
- return e_table_group_leaf_new(parent, full_header, header, model);
+ return e_table_group_leaf_new(parent, full_header, header, model, column, ascending);
}
return NULL;
}
@@ -93,10 +110,13 @@ e_table_group_construct (GnomeCanvasGroup *parent,
ETableHeader *header,
ETableModel *model)
{
- gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL);
etg->full_header = full_header;
+ gtk_object_ref(GTK_OBJECT(etg->full_header));
etg->header = header;
+ gtk_object_ref(GTK_OBJECT(etg->header));
etg->model = model;
+ gtk_object_ref(GTK_OBJECT(etg->model));
+ gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL);
}
void
@@ -311,6 +331,7 @@ etg_class_init (GtkObjectClass *object_class)
object_class->set_arg = etg_set_arg;
object_class->get_arg = etg_get_arg;
+ object_class->destroy = etg_destroy;
item_class->event = etg_event;
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index 286b1a8352..a7d5573fad 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -307,6 +307,10 @@ static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
eti->rows = e_table_model_row_count (eti->table_model);
+
+ if (eti->focused_row > eti->rows - 1) {
+ eti->focused_row = eti->rows - 1;
+ }
if (eti->cell_views)
eti_compute_height (eti);
diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c
index e84e6da4d3..ef14b98018 100644
--- a/widgets/table/e-table-model.c
+++ b/widgets/table/e-table-model.c
@@ -13,6 +13,9 @@
#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
+#define PARENT_TYPE gtk_object_get_type();
+
+
static GtkObjectClass *e_table_model_parent_class;
enum {
@@ -80,6 +83,28 @@ e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
+void *
+e_table_model_duplicate_value (ETableModel *e_table_model, int col, const void *value)
+{
+ g_return_val_if_fail (e_table_model != NULL, NULL);
+ g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
+
+ if (ETM_CLASS (e_table_model)->duplicate_value)
+ return ETM_CLASS (e_table_model)->duplicate_value (e_table_model, col, value);
+ else
+ return NULL;
+}
+
+void
+e_table_model_free_value (ETableModel *e_table_model, int col, void *value)
+{
+ g_return_if_fail (e_table_model != NULL);
+ g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
+
+ if (ETM_CLASS (e_table_model)->free_value)
+ ETM_CLASS (e_table_model)->free_value (e_table_model, col, value);
+}
+
static void
e_table_model_destroy (GtkObject *object)
{
@@ -121,27 +146,30 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
-GtkType
+
+guint
e_table_model_get_type (void)
{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableModel",
- sizeof (ETableModel),
- sizeof (ETableModelClass),
- (GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (gtk_object_get_type (), &info);
- }
-
- return type;
+ static guint type = 0;
+
+ if (!type)
+ {
+ GtkTypeInfo info =
+ {
+ "ETableModle",
+ sizeof (ETableModel),
+ sizeof (ETableModelClass),
+ (GtkClassInitFunc) e_table_model_class_init,
+ NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gtk_object_get_type(), &info);
+ }
+
+ return type;
}
void
diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h
index 9f2dbbf87c..ceca8e348f 100644
--- a/widgets/table/e-table-model.h
+++ b/widgets/table/e-table-model.h
@@ -27,6 +27,10 @@ typedef struct {
void *(*value_at) (ETableModel *etm, int col, int row);
void (*set_value_at) (ETableModel *etm, int col, int row, const void *value);
gboolean (*is_cell_editable) (ETableModel *etm, int col, int row);
+
+ void *(*duplicate_value) (ETableModel *etm, int col, const void *value);
+ void (*free_value) (ETableModel *etm, int col, void *value);
+
void (*thaw) (ETableModel *etm);
/*
* Signals
@@ -48,9 +52,12 @@ int e_table_model_column_count (ETableModel *e_table_model);
const char *e_table_model_column_name (ETableModel *e_table_model, int col);
int e_table_model_row_count (ETableModel *e_table_model);
void *e_table_model_value_at (ETableModel *e_table_model, int col, int row);
-void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data);
+void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *value);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
+void *e_table_model_duplicate_value (ETableModel *e_table_model, int col, const void *value);
+void e_table_model_free_value (ETableModel *e_table_model, int col, void *value);
+
void e_table_model_freeze (ETableModel *e_table_model);
void e_table_model_thaw (ETableModel *e_table_model);
diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c
index 1f64d08f39..e90abfcc4f 100644
--- a/widgets/table/e-table-simple.c
+++ b/widgets/table/e-table-simple.c
@@ -55,6 +55,22 @@ simple_is_cell_editable (ETableModel *etm, int col, int row)
return simple->is_cell_editable (etm, col, row, simple->data);
}
+static void *
+simple_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ return simple->duplicate_value (etm, col, value, simple->data);
+}
+
+static void
+simple_free_value (ETableModel *etm, int col, void *value)
+{
+ ETableSimple *simple = (ETableSimple *)etm;
+
+ simple->free_value (etm, col, value, simple->data);
+}
+
static void
simple_thaw (ETableModel *etm)
{
@@ -73,6 +89,8 @@ e_table_simple_class_init (GtkObjectClass *object_class)
model_class->value_at = simple_value_at;
model_class->set_value_at = simple_set_value_at;
model_class->is_cell_editable = simple_is_cell_editable;
+ model_class->duplicate_value = simple_duplicate_value;
+ model_class->free_value = simple_free_value;
model_class->thaw = simple_thaw;
}
@@ -105,6 +123,8 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count,
ETableSimpleValueAtFn value_at,
ETableSimpleSetValueAtFn set_value_at,
ETableSimpleIsCellEditableFn is_cell_editable,
+ ETableSimpleDuplicateValueFn duplicate_value,
+ ETableSimpleFreeValueFn free_value,
ETableSimpleThawFn thaw,
void *data)
{
@@ -118,6 +138,8 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count,
et->set_value_at = set_value_at;
et->is_cell_editable = is_cell_editable;
et->thaw = thaw;
+ et->duplicate_value = duplicate_value;
+ et->free_value = free_value;
et->data = data;
return (ETableModel *) et;
diff --git a/widgets/table/e-table-simple.h b/widgets/table/e-table-simple.h
index a3164eefc0..51134f45aa 100644
--- a/widgets/table/e-table-simple.h
+++ b/widgets/table/e-table-simple.h
@@ -9,6 +9,8 @@ typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *dat
typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data);
typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data);
typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data);
+typedef void *(*ETableSimpleDuplicateValueFn) (ETableModel *etm, int col, const void *val, void *data);
+typedef void (*ETableSimpleFreeValueFn) (ETableModel *etm, int col, void *val, void *data);
typedef void (*ETableSimpleThawFn) (ETableModel *etm, void *data);
typedef struct {
@@ -19,6 +21,8 @@ typedef struct {
ETableSimpleValueAtFn value_at;
ETableSimpleSetValueAtFn set_value_at;
ETableSimpleIsCellEditableFn is_cell_editable;
+ ETableSimpleDuplicateValueFn duplicate_value;
+ ETableSimpleFreeValueFn free_value;
ETableSimpleThawFn thaw;
void *data;
} ETableSimple;
@@ -34,6 +38,8 @@ ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count,
ETableSimpleValueAtFn value_at,
ETableSimpleSetValueAtFn set_value_at,
ETableSimpleIsCellEditableFn is_cell_editable,
+ ETableSimpleDuplicateValueFn duplicate_value,
+ ETableSimpleFreeValueFn free_value,
ETableSimpleThawFn thaw,
void *data);
diff --git a/widgets/table/e-table-sorted-variable.c b/widgets/table/e-table-sorted-variable.c
new file mode 100644
index 0000000000..478038fdb7
--- /dev/null
+++ b/widgets/table/e-table-sorted-variable.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * E-table-sorted.c: Implements a table that sorts another table
+ *
+ * Author:
+ * Miguel de Icaza (miguel@gnu.org)
+ *
+ * (C) 1999 Helix Code, Inc.
+ */
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
+#include <string.h>
+#include "e-util/e-util.h"
+#include "e-table-sorted-variable.h"
+
+#define PARENT_TYPE E_TABLE_SUBSET_VARIABLE_TYPE
+
+#define INCREMENT_AMOUNT 10
+
+static ETableSubsetVariableClass *etsv_parent_class;
+
+static void etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv);
+static void etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv);
+static void etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv);
+static void etsv_add (ETableSubsetVariable *etssv, gint row);
+
+static void
+etsv_destroy (GtkObject *object)
+{
+ ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (object);
+ ETableSubset *etss = E_TABLE_SUBSET (object);
+
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_row_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etsv->table_model_cell_changed_id);
+
+ etsv->table_model_changed_id = 0;
+ etsv->table_model_row_changed_id = 0;
+ etsv->table_model_cell_changed_id = 0;
+
+ GTK_OBJECT_CLASS (etsv_parent_class)->destroy (object);
+}
+
+static void
+etsv_class_init (GtkObjectClass *object_class)
+{
+ ETableSubsetVariableClass *etssv_class = E_TABLE_SUBSET_VARIABLE_CLASS(object_class);
+
+ etsv_parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = etsv_destroy;
+
+ etssv_class->add = etsv_add;
+}
+
+E_MAKE_TYPE(e_table_sorted_variable, "ETableSortedVariable", ETableSortedVariable, etsv_class_init, NULL, PARENT_TYPE);
+
+static void
+etsv_add (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(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;
+
+ 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) )
+ break;
+ }
+ if ( etss->n_map + 1 > etssv->n_vals_allocated ) {
+ etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
+ etssv->n_vals_allocated += INCREMENT_AMOUNT;
+ }
+ if ( i < etss->n_map )
+ memmove(etss->map_table + i + 1, etss->map_table + i, (etss->n_map - i) * sizeof(int));
+ etss->map_table[i] = row;
+ etss->n_map++;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+}
+
+ETableModel *
+e_table_sorted_variable_new (ETableModel *source, int col, int ascending, GCompareFunc compare)
+{
+ ETableSortedVariable *etsv = gtk_type_new (E_TABLE_SORTED_VARIABLE_TYPE);
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE (etsv);
+
+ if (e_table_subset_variable_construct (etssv, source) == NULL){
+ gtk_object_destroy (GTK_OBJECT (etsv));
+ return NULL;
+ }
+
+ etsv->sort_col = col;
+ etsv->ascending = ascending;
+ etsv->compare = compare;
+
+ etsv->table_model_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_changed), etsv);
+ etsv->table_model_row_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_row_changed), etsv);
+ etsv->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
+ GTK_SIGNAL_FUNC (etsv_proxy_model_cell_changed), etsv);
+
+ return E_TABLE_MODEL(etsv);
+}
+
+static void
+etsv_proxy_model_changed (ETableModel *etm, ETableSortedVariable *etsv)
+{
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ /* FIXME: do_resort(); */
+ }
+}
+
+static void
+etsv_proxy_model_row_changed (ETableModel *etm, int row, ETableSortedVariable *etsv)
+{
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv);
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ if(e_table_subset_variable_remove(etssv, row))
+ e_table_subset_variable_add(etssv, row);
+ }
+}
+
+static void
+etsv_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSortedVariable *etsv)
+{
+ ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE(etsv);
+ if ( !E_TABLE_MODEL(etsv)->frozen ) {
+ if ( col == etsv->sort_col ) {
+ 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
new file mode 100644
index 0000000000..cf188acd4a
--- /dev/null
+++ b/widgets/table/e-table-sorted-variable.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _E_TABLE_SORTED_VARIABLE_H_
+#define _E_TABLE_SORTED_VARIABLE_H_
+
+#include <gtk/gtkobject.h>
+#include "e-table-model.h"
+#include "e-table-subset-variable.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))
+#define E_TABLE_SORTED_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORTED_VARIABLE_TYPE, ETableSortedVariableClass))
+#define E_IS_TABLE_SORTED_VARIABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORTED_VARIABLE_TYPE))
+#define E_IS_TABLE_SORTED_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_VARIABLE_TYPE))
+
+typedef struct {
+ ETableSubsetVariable base;
+
+ short sort_col;
+ int ascending;
+ GCompareFunc compare;
+
+ int table_model_changed_id;
+ int table_model_row_changed_id;
+ int table_model_cell_changed_id;
+} ETableSortedVariable;
+
+typedef struct {
+ ETableSubsetVariableClass parent_class;
+} ETableSortedVariableClass;
+
+GtkType e_table_sorted_variable_get_type (void);
+ETableModel *e_table_sorted_variable_new (ETableModel *etm, int col, int ascending, GCompareFunc compare);
+
+#endif /* _E_TABLE_SORTED_VARIABLE_H_ */
diff --git a/widgets/table/e-table-sorted.c b/widgets/table/e-table-sorted.c
index 16644a45b1..c754f4cff7 100644
--- a/widgets/table/e-table-sorted.c
+++ b/widgets/table/e-table-sorted.c
@@ -13,7 +13,7 @@
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
-static ETableModelClass *ets_parent_class;
+static ETableSubsetClass *ets_parent_class;
static void
ets_class_init (GtkObjectClass *klass)
diff --git a/widgets/table/e-table-subset-variable.c b/widgets/table/e-table-subset-variable.c
index 76da03c44f..5a3e0f2ddf 100644
--- a/widgets/table/e-table-subset-variable.c
+++ b/widgets/table/e-table-subset-variable.c
@@ -14,16 +14,58 @@
#include "e-util/e-util.h"
#include "e-table-subset-variable.h"
+#define ETSSV_CLASS(e) ((ETableSubsetVariableClass *)((GtkObject *)e)->klass)
+
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
#define INCREMENT_AMOUNT 10
-static ETableModelClass *etssv_parent_class;
+static ETableSubsetClass *etssv_parent_class;
+
+static void
+etssv_add (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(etssv);
+ ETableSubset *etss = E_TABLE_SUBSET(etssv);
+
+ if ( etss->n_map + 1 > etssv->n_vals_allocated ) {
+ etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
+ etssv->n_vals_allocated += INCREMENT_AMOUNT;
+ }
+ etss->map_table[etss->n_map++] = row;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+}
+
+static gboolean
+etssv_remove (ETableSubsetVariable *etssv,
+ gint row)
+{
+ ETableModel *etm = E_TABLE_MODEL(etssv);
+ ETableSubset *etss = E_TABLE_SUBSET(etssv);
+ int i;
+
+ for ( i = 0; i < etss->n_map; i++ ) {
+ if (etss->map_table[i] == row) {
+ memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int));
+ etss->n_map --;
+ if ( !etm->frozen )
+ e_table_model_changed(etm);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
static void
-etssv_class_init (GtkObjectClass *klass)
+etssv_class_init (GtkObjectClass *object_class)
{
+ ETableSubsetVariableClass *klass = E_TABLE_SUBSET_VARIABLE_CLASS(object_class);
etssv_parent_class = gtk_type_class (PARENT_TYPE);
+
+ klass->add = etssv_add;
+ klass->remove = etssv_remove;
}
E_MAKE_TYPE(e_table_subset_variable, "ETableSubsetVariable", ETableSubsetVariable, etssv_class_init, NULL, PARENT_TYPE);
@@ -56,34 +98,24 @@ void
e_table_subset_variable_add (ETableSubsetVariable *etssv,
gint row)
{
- ETableModel *etm = E_TABLE_MODEL(etssv);
- ETableSubset *etss = E_TABLE_SUBSET(etssv);
-
- if ( etss->n_map + 1 > etssv->n_vals_allocated )
- etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int));
- etss->map_table[etss->n_map++] = row;
- if ( !etm->frozen )
- e_table_model_changed(etm);
+ g_return_if_fail (etssv != NULL);
+ g_return_if_fail (E_IS_TABLE_SUBSET_VARIABLE(etssv));
+
+ if (ETSSV_CLASS(etssv)->add)
+ ETSSV_CLASS (etssv)->add (etssv, row);
}
gboolean
e_table_subset_variable_remove (ETableSubsetVariable *etssv,
gint row)
{
- ETableModel *etm = E_TABLE_MODEL(etssv);
- ETableSubset *etss = E_TABLE_SUBSET(etssv);
- int i;
-
- for ( i = 0; i < etss->n_map; i++ ) {
- if (etss->map_table[i] == row) {
- memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int));
- etss->n_map --;
- if ( !etm->frozen )
- e_table_model_changed(etm);
- return TRUE;
- }
- }
- return FALSE;
+ g_return_val_if_fail (etssv != NULL, FALSE);
+ g_return_val_if_fail (E_IS_TABLE_SUBSET_VARIABLE(etssv), FALSE);
+
+ if (ETSSV_CLASS(etssv)->remove)
+ return ETSSV_CLASS (etssv)->remove (etssv, row);
+ else
+ return FALSE;
}
void
diff --git a/widgets/table/e-table-subset-variable.h b/widgets/table/e-table-subset-variable.h
index 9755fb2477..8ac0af0382 100644
--- a/widgets/table/e-table-subset-variable.h
+++ b/widgets/table/e-table-subset-variable.h
@@ -19,6 +19,11 @@ typedef struct {
typedef struct {
ETableSubsetClass parent_class;
+
+ void (*add) (ETableSubsetVariable *ets,
+ gint row);
+ gboolean (*remove) (ETableSubsetVariable *ets,
+ gint row);
} ETableSubsetVariableClass;
GtkType e_table_subset_variable_get_type (void);
diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c
index a09d221980..b4473b87ef 100644
--- a/widgets/table/e-table-subset.c
+++ b/widgets/table/e-table-subset.c
@@ -25,6 +25,17 @@ etss_destroy (GtkObject *object)
if (etss->source)
gtk_object_unref (GTK_OBJECT (etss->source));
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_row_changed_id);
+ gtk_signal_disconnect (GTK_OBJECT (etss->source),
+ etss->table_model_cell_changed_id);
+
+ etss->table_model_changed_id = 0;
+ etss->table_model_row_changed_id = 0;
+ etss->table_model_cell_changed_id = 0;
+
if (etss->map_table)
free (etss->map_table);
@@ -71,6 +82,22 @@ etss_is_cell_editable (ETableModel *etm, int col, int row)
return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]);
}
+static void *
+etss_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ ETableSubset *etss = (ETableSubset *)etm;
+
+ return e_table_model_duplicate_value (etss->source, col, value);
+}
+
+static void
+etss_free_value (ETableModel *etm, int col, void *value)
+{
+ ETableSubset *etss = (ETableSubset *)etm;
+
+ e_table_model_free_value (etss->source, col, value);
+}
+
static void
etss_thaw (ETableModel *etm)
{
@@ -91,6 +118,8 @@ etss_class_init (GtkObjectClass *klass)
table_class->value_at = etss_value_at;
table_class->set_value_at = etss_set_value_at;
table_class->is_cell_editable = etss_is_cell_editable;
+ table_class->duplicate_value = etss_duplicate_value;
+ table_class->free_value = etss_free_value;
table_class->thaw = etss_thaw;
}
@@ -155,12 +184,12 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals)
for (i = 0; i < nvals; i++)
etss->map_table [i] = i;
- gtk_signal_connect (GTK_OBJECT (source), "model_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
+ etss->table_model_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
+ etss->table_model_row_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
+ etss->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
return E_TABLE_MODEL (etss);
}
diff --git a/widgets/table/e-table-subset.h b/widgets/table/e-table-subset.h
index d8af1696f5..074120a410 100644
--- a/widgets/table/e-table-subset.h
+++ b/widgets/table/e-table-subset.h
@@ -17,6 +17,10 @@ typedef struct {
ETableModel *source;
int n_map;
int *map_table;
+
+ int table_model_changed_id;
+ int table_model_row_changed_id;
+ int table_model_cell_changed_id;
} ETableSubset;
typedef struct {
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 551ef52227..e508e24e02 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -34,6 +34,8 @@
static GtkObjectClass *e_table_parent_class;
+static void e_table_fill_table (ETable *e_table, ETableModel *model);
+
static void
et_destroy (GtkObject *object)
{
@@ -42,6 +44,20 @@ 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_widget_destroy (GTK_WIDGET (et->header_canvas));
+ gtk_widget_destroy (GTK_WIDGET (et->table_canvas));
+
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_model_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_row_change_id);
+ gtk_signal_disconnect (GTK_OBJECT (et->model),
+ et->table_cell_change_id);
+
+ if (et->rebuild_idle_id) {
+ g_source_remove(et->rebuild_idle_id);
+ et->rebuild_idle_id = 0;
+ }
(*e_table_parent_class->destroy)(object);
}
@@ -54,6 +70,11 @@ e_table_init (GtkObject *object)
e_table->draw_grid = 1;
e_table->draw_focus = 1;
e_table->spreadsheet = 1;
+
+ e_table->need_rebuild = 0;
+ e_table->need_row_changes = 0;
+ e_table->row_changes_list = NULL;
+ e_table->rebuild_idle_id = 0;
}
static ETableHeader *
@@ -528,6 +549,72 @@ table_canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t
}
static void
+change_row (gpointer key, gpointer value, gpointer data)
+{
+ ETable *et = E_TABLE(data);
+ gint row = GPOINTER_TO_INT(key);
+ if ( e_table_group_remove(et->group, row) ) {
+ e_table_group_add(et->group, row);
+ }
+}
+
+static gboolean
+changed_idle (gpointer data)
+{
+ ETable *et = E_TABLE(data);
+ if ( et->need_rebuild ) {
+ gtk_object_destroy( GTK_OBJECT(et->group ) );
+ et->group = e_table_group_new(GNOME_CANVAS_GROUP(et->table_canvas->root),
+ et->full_header,
+ et->header,
+ et->model,
+ e_xml_get_child_by_name(xmlDocGetRootElement(et->specification), "grouping")->childs);
+ e_table_fill_table(et, et->model);
+ } else if (et->need_row_changes) {
+ g_hash_table_foreach(et->row_changes_list, change_row, et);
+ }
+ et->need_rebuild = 0;
+ et->need_row_changes = 0;
+ if (et->row_changes_list)
+ g_hash_table_destroy(et->row_changes_list);
+ et->row_changes_list = NULL;
+ et->rebuild_idle_id = 0;
+ return FALSE;
+}
+
+static void
+et_table_model_changed (ETableModel *model, ETable *et)
+{
+ et->need_rebuild = TRUE;
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
+et_table_row_changed (ETableModel *table_model, int row, ETable *et)
+{
+ if ( !et->need_rebuild ) {
+ if (!et->need_row_changes) {
+ et->need_row_changes = 1;
+ et->row_changes_list = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+ if (!g_hash_table_lookup(et->row_changes_list, GINT_TO_POINTER(row))) {
+ g_hash_table_insert(et->row_changes_list, GINT_TO_POINTER(row), GINT_TO_POINTER(row + 1));
+ }
+ }
+ if ( !et->rebuild_idle_id ) {
+ et->rebuild_idle_id = g_idle_add(changed_idle, et);
+ }
+}
+
+static void
+et_table_cell_changed (ETableModel *table_model, int view_col, int row, ETable *et)
+{
+ et_table_row_changed(table_model, row, et);
+}
+
+static void
e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, ETableModel *model, xmlNode *xml_grouping)
{
e_table->table_canvas = GNOME_CANVAS(gnome_canvas_new ());
@@ -546,6 +633,17 @@ e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *h
model,
xml_grouping->childs);
+ e_table->table_model_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_changed",
+ GTK_SIGNAL_FUNC (et_table_model_changed), e_table);
+
+ e_table->table_row_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_row_changed",
+ GTK_SIGNAL_FUNC (et_table_row_changed), e_table);
+
+ e_table->table_cell_change_id = gtk_signal_connect (
+ GTK_OBJECT (model), "model_cell_changed",
+ GTK_SIGNAL_FUNC (et_table_cell_changed), e_table);
}
static void
diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h
index a372d8042c..841013c09a 100644
--- a/widgets/table/e-table.h
+++ b/widgets/table/e-table.h
@@ -26,6 +26,10 @@ typedef struct {
ETableGroup *group;
+ int table_model_change_id;
+ int table_row_change_id;
+ int table_cell_change_id;
+
GnomeCanvas *header_canvas, *table_canvas;
GnomeCanvasItem *header_item, *root;
@@ -35,6 +39,12 @@ typedef struct {
guint draw_grid:1;
guint draw_focus:1;
guint spreadsheet:1;
+
+ guint need_rebuild:1;
+ guint need_row_changes:1;
+
+ GHashTable *row_changes_list;
+ gint rebuild_idle_id;
} ETable;
typedef struct {
diff --git a/widgets/table/test-check.c b/widgets/table/test-check.c
index a6a59788ad..7894898255 100644
--- a/widgets/table/test-check.c
+++ b/widgets/table/test-check.c
@@ -14,6 +14,7 @@
#include "e-table-item.h"
#include "e-util/e-cursors.h"
#include "e-util/e-canvas-utils.h"
+#include "e-util/e-util.h"
#include "e-cell-text.h"
#include "e-cell-checkbox.h"
@@ -79,6 +80,24 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ if (col == 0){
+ return (void *) value;
+ } else {
+ return g_strdup(value);
+ }
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ if (col != 0){
+ g_free(value);
+ }
+}
+
static void
thaw (ETableModel *etc, void *data)
{
@@ -107,7 +126,8 @@ check_test (void)
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value, thaw, NULL);
/*
* Header
@@ -118,11 +138,11 @@ check_test (void)
cell_image_check = e_cell_checkbox_new ();
pixbuf = gdk_pixbuf_new_from_file("clip.png");
- col_0 = e_table_col_new_with_pixbuf (0, pixbuf, 18, 18, cell_image_check, g_int_equal, TRUE);
+ col_0 = e_table_col_new_with_pixbuf (0, pixbuf, 18, 18, cell_image_check, g_int_compare, TRUE);
gdk_pixbuf_unref(pixbuf);
e_table_header_add_column (e_table_header, col_0, 0);
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
+ col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_compare, TRUE);
e_table_header_add_column (e_table_header, col_1, 1);
e_table_col_set_arrow ( col_1, E_TABLE_COL_ARROW_DOWN );
diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c
index adc9ed6c20..d65b9945b7 100644
--- a/widgets/table/test-cols.c
+++ b/widgets/table/test-cols.c
@@ -10,6 +10,7 @@
#include <gnome.h>
#include "e-util/e-canvas-utils.h"
#include "e-util/e-cursors.h"
+#include "e-util/e-util.h"
#include "e-table-simple.h"
#include "e-table-header.h"
#include "e-table-header-item.h"
@@ -79,6 +80,24 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ if (col == 0){
+ return (void *)value;
+ } else {
+ return g_strdup(value);
+ }
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ if (col != 0){
+ g_free(value);
+ }
+}
+
static void
set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc)
{
@@ -106,7 +125,9 @@ multi_cols_test (void)
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value,
+ thaw, NULL);
/*
* Header
@@ -131,10 +152,10 @@ multi_cols_test (void)
g_free (images);
}
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
+ col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_compare, TRUE);
e_table_header_add_column (e_table_header, col_1, 0);
- col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE);
+ col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_compare, TRUE);
e_table_header_add_column (e_table_header, col_0, 1);
/*
diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c
index 1bd50e1479..0fdf32fcbe 100644
--- a/widgets/table/test-table.c
+++ b/widgets/table/test-table.c
@@ -176,6 +176,18 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data)
return TRUE;
}
+static void *
+duplicate_value (ETableModel *etc, int col, const void *value, void *data)
+{
+ return g_strdup(value);
+}
+
+static void
+free_value (ETableModel *etc, int col, void *value, void *data)
+{
+ g_free(value);
+}
+
static void
thaw (ETableModel *etc, void *data)
{
@@ -205,7 +217,8 @@ table_browser_test (void)
*/
e_table_model = e_table_simple_new (
col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value, thaw, NULL);
/*
* Header
@@ -217,7 +230,7 @@ table_browser_test (void)
ETableCol *ecol = e_table_col_new (
i, column_labels [i],
80, 20, cell_left_just,
- g_str_equal, TRUE);
+ g_str_compare, TRUE);
e_table_header_add_column (e_table_header, ecol, i);
}
@@ -263,7 +276,6 @@ static void
do_e_table_demo (const char *spec)
{
GtkWidget *e_table, *window, *frame;
- ETableModel *e_table_model;
ECell *cell_left_just;
ETableHeader *full_header;
int i;
@@ -271,9 +283,14 @@ do_e_table_demo (const char *spec)
/*
* Data model
*/
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, thaw, NULL);
+ static ETableModel *e_table_model = NULL;
+
+ if ( e_table_model == NULL )
+ e_table_model =
+ e_table_simple_new (col_count, row_count, value_at,
+ set_value_at, is_cell_editable,
+ duplicate_value, free_value,
+ thaw, NULL);
full_header = e_table_header_new ();
cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT, TRUE);
@@ -282,7 +299,7 @@ do_e_table_demo (const char *spec)
ETableCol *ecol = e_table_col_new (
i, column_labels [i],
80, 20, cell_left_just,
- g_str_equal, TRUE);
+ g_str_compare, TRUE);
e_table_header_add_column (full_header, ecol, i);
}
@@ -306,9 +323,9 @@ e_table_test (void)
load_data ();
if (1){/*getenv ("DO")){*/
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf/> </grouping> </ETableSpecification>");
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <group column=\"4\"> <leaf/> </group> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf column=\"3\" ascending=\"1\"/> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\" ascending=\"1\"> <group column=\"4\" ascending=\"0\"> <leaf column=\"2\" ascending=\"1\"/> </group> </group> </grouping> </ETableSpecification>");
}
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\"> <leaf/> </group> </grouping> </ETableSpecification>");
- do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <leaf/> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\" ascending=\"1\"> <leaf column=\"2\" ascending=\"1\"/> </group> </grouping> </ETableSpecification>");
+ do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\" ascending=\"1\"> <leaf column=\"2\" ascending=\"1\"/> </group> </grouping> </ETableSpecification>");
}