From fd4ffbd38ccef4d2a35675a50f89e0b5f2d6d86e Mon Sep 17 00:00:00 2001 From: Christopher James Lahey Date: Tue, 12 Mar 2002 14:30:53 +0000 Subject: Added e-table-search.lo. 2002-03-12 Christopher James Lahey * gal/Makefile.am (libgal_la_LIBADD): Added e-table-search.lo. * gal/util/e-util.c, gal/util/e-util.h (e_marshal_BOOL__STRING): Added this marshal function. From gal/e-table/ChangeLog: 2002-03-12 Christopher James Lahey * Makefile.am (libetable_la_SOURCES): Added e-table-search.c. (libetableinclude_HEADERS): Added e-table-search.h. * e-cell.h: Added ETableSearchFun here. * e-table-col.h: Added search here. * e-table-column-specification.c, e-table-column-specification.h: Added search here. * e-table-extras.c, e-table-extras.h (e_table_extras_add_search): Added ETableSearchFuncs here. * e-table-memory-store.c (e_table_memory_store_insert, e_table_memory_store_insert_adopt): Handle row == -1 here. * e-table-search.c, e-table-search.h: New class to reusably handle the semantics of searching for a string. * e-table-simple.c, e-table-simple.h: Added a bunch of simple functions here for if your table is all strings. Should be reusable. * e-table-utils.c (et_col_spec_to_col): Added support for searches here. * e-table.c, e-table.h: Added an ETableSearch here. svn path=/trunk/; revision=16119 --- widgets/table/e-cell.h | 3 + widgets/table/e-table-col.h | 37 ++--- widgets/table/e-table-column-specification.c | 4 + widgets/table/e-table-column-specification.h | 1 + widgets/table/e-table-extras.c | 44 +++++- widgets/table/e-table-extras.h | 41 ++--- widgets/table/e-table-memory-store.c | 12 +- widgets/table/e-table-search.c | 219 +++++++++++++++++++++++++++ widgets/table/e-table-search.h | 68 +++++++++ widgets/table/e-table-simple.c | 30 ++++ widgets/table/e-table-simple.h | 69 +++++---- widgets/table/e-table-utils.c | 14 +- widgets/table/e-table.c | 108 +++++++++++++ widgets/table/e-table.h | 9 ++ 14 files changed, 587 insertions(+), 72 deletions(-) create mode 100644 widgets/table/e-table-search.c create mode 100644 widgets/table/e-table-search.h (limited to 'widgets/table') diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h index f872d0c81f..d0f0f196a3 100644 --- a/widgets/table/e-cell.h +++ b/widgets/table/e-cell.h @@ -39,6 +39,9 @@ BEGIN_GNOME_DECLS #define E_IS_CELL(o) (GTK_CHECK_TYPE ((o), E_CELL_TYPE)) #define E_IS_CELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TYPE)) +typedef gboolean (*ETableSearchFunc) (gconstpointer haystack, + const char *needle); + typedef enum { E_CELL_SELECTED = 1 << 0, diff --git a/widgets/table/e-table-col.h b/widgets/table/e-table-col.h index 62aa90caf1..485bd2d84c 100644 --- a/widgets/table/e-table-col.h +++ b/widgets/table/e-table-col.h @@ -47,26 +47,27 @@ typedef enum { * Information about a single column */ typedef struct { - GtkObject base; - char *text; - GdkPixbuf *pixbuf; - int min_width; - int width; - double expansion; - short x; - GCompareFunc compare; - unsigned int is_pixbuf:1; - unsigned int selected:1; - unsigned int resizable:1; - unsigned int disabled:1; - unsigned int sortable:1; - unsigned int groupable:1; - int col_idx; - int priority; + GtkObject base; + char *text; + GdkPixbuf *pixbuf; + int min_width; + int width; + double expansion; + short x; + GCompareFunc compare; + ETableSearchFunc search; + unsigned int is_pixbuf:1; + unsigned int selected:1; + unsigned int resizable:1; + unsigned int disabled:1; + unsigned int sortable:1; + unsigned int groupable:1; + int col_idx; + int priority; - GtkJustification justification; + GtkJustification justification; - ECell *ecell; + ECell *ecell; } ETableCol; typedef struct { diff --git a/widgets/table/e-table-column-specification.c b/widgets/table/e-table-column-specification.c index 81f4e45eb2..30bb80c779 100644 --- a/widgets/table/e-table-column-specification.c +++ b/widgets/table/e-table-column-specification.c @@ -41,6 +41,7 @@ free_strings (ETableColumnSpecification *etcs) g_free(etcs->pixbuf); g_free(etcs->cell); g_free(etcs->compare); + g_free(etcs->search); } static void @@ -75,6 +76,7 @@ etcs_init (ETableColumnSpecification *specification) specification->cell = NULL; specification->compare = NULL; + specification->search = NULL; specification->priority = 0; } @@ -105,6 +107,7 @@ e_table_column_specification_load_from_node (ETableColumnSpecification *etcs, etcs->cell = e_xml_get_string_prop_by_name (node, "cell"); etcs->compare = e_xml_get_string_prop_by_name (node, "compare"); + etcs->search = e_xml_get_string_prop_by_name (node, "search"); etcs->priority = e_xml_get_integer_prop_by_name_with_default (node, "priority", 0); if (etcs->title == NULL) @@ -132,6 +135,7 @@ e_table_column_specification_save_to_node (ETableColumnSpecification *specificat e_xml_set_string_prop_by_name(node, "cell", specification->cell); e_xml_set_string_prop_by_name(node, "compare", specification->compare); + e_xml_set_string_prop_by_name(node, "search", specification->search); if (specification->priority != 0) e_xml_set_integer_prop_by_name (node, "priority", specification->priority); diff --git a/widgets/table/e-table-column-specification.h b/widgets/table/e-table-column-specification.h index f451e949cb..bcd2889dc1 100644 --- a/widgets/table/e-table-column-specification.h +++ b/widgets/table/e-table-column-specification.h @@ -52,6 +52,7 @@ typedef struct { char *cell; char *compare; + char *search; int priority; } ETableColumnSpecification; diff --git a/widgets/table/e-table-extras.c b/widgets/table/e-table-extras.c index d5cb1191ad..9f80557901 100644 --- a/widgets/table/e-table-extras.c +++ b/widgets/table/e-table-extras.c @@ -33,6 +33,7 @@ #include "gal/e-table/e-cell-size.h" #include "gal/e-table/e-cell-tree.h" #include "e-table-extras.h" +#include #define PARENT_TYPE (gtk_object_get_type()) @@ -65,14 +66,17 @@ ete_destroy (GtkObject *object) g_hash_table_foreach (ete->cells, (GHFunc) cell_hash_free, NULL); g_hash_table_foreach (ete->compares, (GHFunc) g_free, NULL); + g_hash_table_foreach (ete->searches, (GHFunc) g_free, NULL); g_hash_table_foreach (ete->pixbufs, (GHFunc) pixbuf_hash_free, NULL); g_hash_table_destroy (ete->cells); g_hash_table_destroy (ete->compares); + g_hash_table_destroy (ete->searches); g_hash_table_destroy (ete->pixbufs); ete->cells = NULL; ete->compares = NULL; + ete->searches = NULL; ete->pixbufs = NULL; GTK_OBJECT_CLASS (ete_parent_class)->destroy (object); @@ -95,17 +99,30 @@ e_strint_compare(gconstpointer data1, gconstpointer data2) return g_int_compare(GINT_TO_POINTER(int1), GINT_TO_POINTER(int2)); } +static gboolean +e_string_search(gconstpointer haystack, const char *needle) +{ + int length = g_utf8_strlen (needle, -1); + if (g_utf8_strncasecmp (haystack, needle, length) == 0) + return TRUE; + else + return FALSE; +} + static void ete_init (ETableExtras *extras) { extras->cells = g_hash_table_new(g_str_hash, g_str_equal); extras->compares = g_hash_table_new(g_str_hash, g_str_equal); + extras->searches = g_hash_table_new(g_str_hash, g_str_equal); extras->pixbufs = g_hash_table_new(g_str_hash, g_str_equal); e_table_extras_add_compare(extras, "string", g_str_compare); e_table_extras_add_compare(extras, "integer", g_int_compare); e_table_extras_add_compare(extras, "string-integer", e_strint_compare); + e_table_extras_add_search(extras, "string", e_string_search); + e_table_extras_add_cell(extras, "checkbox", e_cell_checkbox_new()); e_table_extras_add_cell(extras, "date", e_cell_date_new (NULL, GTK_JUSTIFY_LEFT)); e_table_extras_add_cell(extras, "number", e_cell_number_new (NULL, GTK_JUSTIFY_RIGHT)); @@ -162,8 +179,8 @@ e_table_extras_add_compare (ETableExtras *extras, gchar *old_key; GCompareFunc old_compare; - if (g_hash_table_lookup_extended (extras->cells, id, (gpointer *)&old_key, (gpointer *)&old_compare)) { - g_hash_table_remove (extras->cells, old_key); + if (g_hash_table_lookup_extended (extras->compares, id, (gpointer *)&old_key, (gpointer *)&old_compare)) { + g_hash_table_remove (extras->compares, old_key); g_free (old_key); } @@ -177,6 +194,29 @@ e_table_extras_get_compare (ETableExtras *extras, return g_hash_table_lookup(extras->compares, id); } +void +e_table_extras_add_search (ETableExtras *extras, + char *id, + ETableSearchFunc search) +{ + gchar *old_key; + ETableSearchFunc old_search; + + if (g_hash_table_lookup_extended (extras->searches, id, (gpointer *)&old_key, (gpointer *)&old_search)) { + g_hash_table_remove (extras->searches, old_key); + g_free (old_key); + } + + g_hash_table_insert(extras->searches, g_strdup(id), search); +} + +ETableSearchFunc +e_table_extras_get_search (ETableExtras *extras, + char *id) +{ + return g_hash_table_lookup(extras->searches, id); +} + void e_table_extras_add_pixbuf (ETableExtras *extras, char *id, diff --git a/widgets/table/e-table-extras.h b/widgets/table/e-table-extras.h index 073a9559b8..a077319aec 100644 --- a/widgets/table/e-table-extras.h +++ b/widgets/table/e-table-extras.h @@ -43,32 +43,39 @@ typedef struct { GHashTable *cells; GHashTable *compares; GHashTable *pixbufs; + GHashTable *searches; } ETableExtras; typedef struct { GtkObjectClass parent_class; } ETableExtrasClass; -GtkType e_table_extras_get_type (void); -ETableExtras *e_table_extras_new (void); +GtkType e_table_extras_get_type (void); +ETableExtras *e_table_extras_new (void); -void e_table_extras_add_cell (ETableExtras *extras, - char *id, - ECell *cell); -ECell *e_table_extras_get_cell (ETableExtras *extras, - char *id); +void e_table_extras_add_cell (ETableExtras *extras, + char *id, + ECell *cell); +ECell *e_table_extras_get_cell (ETableExtras *extras, + char *id); -void e_table_extras_add_compare (ETableExtras *extras, - char *id, - GCompareFunc compare); -GCompareFunc e_table_extras_get_compare (ETableExtras *extras, - char *id); +void e_table_extras_add_compare (ETableExtras *extras, + char *id, + GCompareFunc compare); +GCompareFunc e_table_extras_get_compare (ETableExtras *extras, + char *id); -void e_table_extras_add_pixbuf (ETableExtras *extras, - char *id, - GdkPixbuf *pixbuf); -GdkPixbuf *e_table_extras_get_pixbuf (ETableExtras *extras, - char *id); +void e_table_extras_add_search (ETableExtras *extras, + char *id, + ETableSearchFunc search); +ETableSearchFunc e_table_extras_get_search (ETableExtras *extras, + char *id); + +void e_table_extras_add_pixbuf (ETableExtras *extras, + char *id, + GdkPixbuf *pixbuf); +GdkPixbuf *e_table_extras_get_pixbuf (ETableExtras *extras, + char *id); END_GNOME_DECLS diff --git a/widgets/table/e-table-memory-store.c b/widgets/table/e-table-memory-store.c index c54bfb6190..d3485e1153 100644 --- a/widgets/table/e-table-memory-store.c +++ b/widgets/table/e-table-memory-store.c @@ -320,7 +320,10 @@ e_table_memory_store_insert (ETableMemoryStore *etms, int row, void **store, gpo int i; e_table_memory_insert (E_TABLE_MEMORY (etms), row, data); + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + if (row == -1) + row = row_count - 1; etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); memmove (etms->priv->store + etms->priv->col_count * (row + 1), etms->priv->store + etms->priv->col_count * row, @@ -357,14 +360,15 @@ e_table_memory_store_insert_adopt (ETableMemoryStore *etms, int row, void **stor int row_count; int i; - row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); - e_table_memory_insert (E_TABLE_MEMORY (etms), row, data); - etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * (row_count + 1) * sizeof (void *)); + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + if (row == -1) + row = row_count - 1; + etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); memmove (etms->priv->store + etms->priv->col_count * (row + 1), etms->priv->store + etms->priv->col_count * row, - etms->priv->col_count * (row_count - row) * sizeof (void *)); + etms->priv->col_count * (row_count - row - 1) * sizeof (void *)); for (i = 0; i < etms->priv->col_count; i++) { STORE_LOCATOR(etms, i, row) = store[i]; diff --git a/widgets/table/e-table-search.c b/widgets/table/e-table-search.c new file mode 100644 index 0000000000..88b6673c86 --- /dev/null +++ b/widgets/table/e-table-search.c @@ -0,0 +1,219 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-search.c + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include +#include "e-table-search.h" +#include "gal/util/e-util.h" + +#define ETS_CLASS(e) ((ETableSearchClass *)((GtkObject *)e)->klass) + +#define PARENT_TYPE gtk_object_get_type () + +#define d(x) + +d(static gint depth = 0); + +struct _ETableSearchPrivate { + guint timeout_id; + + char *search_string; + gunichar last_character; +}; + +static GtkObjectClass *e_table_search_parent_class; + +enum { + SEARCH_SEARCH, + SEARCH_ACCEPT, + LAST_SIGNAL +}; + +static guint e_table_search_signals [LAST_SIGNAL] = { 0, }; + +static gboolean +e_table_search_search (ETableSearch *e_table_search, char *string) +{ + gboolean ret_val; + g_return_val_if_fail (e_table_search != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_SEARCH (e_table_search), FALSE); + + gtk_signal_emit (GTK_OBJECT (e_table_search), + e_table_search_signals [SEARCH_SEARCH], string, &ret_val); + + return ret_val; +} + +static void +e_table_search_accept (ETableSearch *e_table_search) +{ + g_return_if_fail (e_table_search != NULL); + g_return_if_fail (E_IS_TABLE_SEARCH (e_table_search)); + + gtk_signal_emit (GTK_OBJECT (e_table_search), + e_table_search_signals [SEARCH_ACCEPT]); +} + +static gboolean +ets_accept (gpointer data) +{ + ETableSearch *ets = data; + e_table_search_accept (ets); + g_free (ets->priv->search_string); + + ets->priv->timeout_id = 0; + ets->priv->search_string = g_strdup (""); + ets->priv->last_character = 0; + + return FALSE; +} + +static void +drop_timeout (ETableSearch *ets) +{ + if (ets->priv->timeout_id) { + g_source_remove (ets->priv->timeout_id); + } + ets->priv->timeout_id = 0; +} + +static void +add_timeout (ETableSearch *ets) +{ + drop_timeout (ets); + ets->priv->timeout_id = g_timeout_add (1000, ets_accept, ets); +} + +static void +e_table_search_destroy (GtkObject *object) +{ + if (e_table_search_parent_class->destroy) + (*e_table_search_parent_class->destroy)(object); +} + +static void +e_table_search_class_init (GtkObjectClass *object_class) +{ + ETableSearchClass *klass = E_TABLE_SEARCH_CLASS(object_class); + e_table_search_parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = e_table_search_destroy; + + e_table_search_signals [SEARCH_SEARCH] = + gtk_signal_new ("search", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (ETableSearchClass, search), + e_marshal_BOOL__STRING, + GTK_TYPE_BOOL, 1, GTK_TYPE_STRING); + + e_table_search_signals [SEARCH_ACCEPT] = + gtk_signal_new ("accept", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (ETableSearchClass, accept), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + E_OBJECT_CLASS_ADD_SIGNALS (object_class, e_table_search_signals, LAST_SIGNAL); + + klass->search = NULL; + klass->accept = NULL; +} + +static void +e_table_search_init (ETableSearch *ets) +{ + ets->priv = g_new (ETableSearchPrivate, 1); + + ets->priv->timeout_id = 0; + ets->priv->search_string = g_strdup (""); + ets->priv->last_character = 0; +} + + +guint +e_table_search_get_type (void) +{ + static guint type = 0; + + if (!type) + { + GtkTypeInfo info = + { + "ETableSearch", + sizeof (ETableSearch), + sizeof (ETableSearchClass), + (GtkClassInitFunc) e_table_search_class_init, + (GtkObjectInitFunc) e_table_search_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +ETableSearch * +e_table_search_new (void) +{ + ETableSearch *ets = gtk_type_new (e_table_search_get_type()); + + return ets; +} + +/** + * e_table_search_column_count: + * @e_table_search: The e-table-search to operate on + * + * Returns: the number of columns in the table search. + */ +void +e_table_search_input_character (ETableSearch *ets, gunichar character) +{ + char character_utf8[7]; + + g_return_if_fail (ets != NULL); + g_return_if_fail (E_IS_TABLE_SEARCH (ets)); + + character_utf8 [g_unichar_to_utf8 (character, character_utf8)] = 0; + + if (character != ets->priv->last_character) { + char *temp_string; + temp_string = g_strdup_printf ("%s%s", ets->priv->search_string, character_utf8); + if (e_table_search_search (ets, temp_string)) { + g_free (ets->priv->search_string); + ets->priv->search_string = temp_string; + add_timeout (ets); + } else { + g_free (temp_string); + } + } else { + e_table_search_search (ets, ets->priv->search_string); + add_timeout (ets); + } + ets->priv->last_character = character; +} diff --git a/widgets/table/e-table-search.h b/widgets/table/e-table-search.h new file mode 100644 index 0000000000..a439aafbe5 --- /dev/null +++ b/widgets/table/e-table-search.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-search.h + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _E_TABLE_SEARCH_H_ +#define _E_TABLE_SEARCH_H_ + +#include +#include +#include + +BEGIN_GNOME_DECLS + +#define E_TABLE_SEARCH_TYPE (e_table_search_get_type ()) +#define E_TABLE_SEARCH(o) (GTK_CHECK_CAST ((o), E_TABLE_SEARCH_TYPE, ETableSearch)) +#define E_TABLE_SEARCH_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SEARCH_TYPE, ETableSearchClass)) +#define E_IS_TABLE_SEARCH(o) (GTK_CHECK_TYPE ((o), E_TABLE_SEARCH_TYPE)) +#define E_IS_TABLE_SEARCH_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SEARCH_TYPE)) + +typedef struct _ETableSearchPrivate ETableSearchPrivate; + +typedef struct { + GtkObject base; + + ETableSearchPrivate *priv; +} ETableSearch; + +typedef struct { + GtkObjectClass parent_class; + + /* + * Signals + */ + gboolean (*search) (ETableSearch *ets, char *string /* utf8 */); + void (*accept) (ETableSearch *ets); + void (*cancelled) (ETableSearch *ets); +} ETableSearchClass; + +GtkType e_table_search_get_type (void); +ETableSearch *e_table_search_new (void); + +/**/ +void e_table_search_input_character (ETableSearch *e_table_search, + gunichar character); +void e_table_search_cancel (ETableSearch *e_table_search); + +END_GNOME_DECLS + +#endif /* _E_TABLE_SEARCH_H_ */ diff --git a/widgets/table/e-table-simple.c b/widgets/table/e-table-simple.c index 635a8e445a..11cfafd01f 100644 --- a/widgets/table/e-table-simple.c +++ b/widgets/table/e-table-simple.c @@ -281,3 +281,33 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, return (ETableModel *) et; } + +void * +e_table_simple_string_duplicate_value (ETableModel *etm, int col, const void *val, void *data) +{ + return g_strdup (val); +} + +void +e_table_simple_string_free_value (ETableModel *etm, int col, void *val, void *data) +{ + g_free (val); +} + +void * +e_table_simple_string_initialize_value (ETableModel *etm, int col, void *data) +{ + return g_strdup (""); +} + +gboolean +e_table_simple_string_value_is_empty (ETableModel *etm, int col, const void *val, void *data) +{ + return !(val && * (char *) val); +} + +char * +e_table_simple_string_value_to_string (ETableModel *etm, int col, const void *val, void *data) +{ + return g_strdup (val); +} diff --git a/widgets/table/e-table-simple.h b/widgets/table/e-table-simple.h index 0521809438..6dfe28f573 100644 --- a/widgets/table/e-table-simple.h +++ b/widgets/table/e-table-simple.h @@ -26,10 +26,9 @@ #define _E_TABLE_SIMPLE_H_ #include +#include -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +BEGIN_GNOME_DECLS #define E_TABLE_SIMPLE_TYPE (e_table_simple_get_type ()) #define E_TABLE_SIMPLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SIMPLE_TYPE, ETableSimple)) @@ -72,7 +71,7 @@ typedef struct { ETableSimpleFreeValueFn free_value; ETableSimpleInitializeValueFn initialize_value; ETableSimpleValueIsEmptyFn value_is_empty; - ETableSimpleValueToStringFn value_to_string; + ETableSimpleValueToStringFn value_to_string; void *data; } ETableSimple; @@ -80,29 +79,45 @@ typedef struct { ETableModelClass parent_class; } ETableSimpleClass; -GtkType e_table_simple_get_type (void); - -ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, - ETableSimpleRowCountFn row_count, - ETableSimpleAppendRowFn append_row, - - ETableSimpleValueAtFn value_at, - ETableSimpleSetValueAtFn set_value_at, - ETableSimpleIsCellEditableFn is_cell_editable, - - ETableSimpleHasSaveIdFn has_save_id, - ETableSimpleGetSaveIdFn get_save_id, - - ETableSimpleDuplicateValueFn duplicate_value, - ETableSimpleFreeValueFn free_value, - ETableSimpleInitializeValueFn initialize_value, - ETableSimpleValueIsEmptyFn value_is_empty, - ETableSimpleValueToStringFn value_to_string, - void *data); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +GtkType e_table_simple_get_type (void); +ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, + ETableSimpleRowCountFn row_count, + ETableSimpleAppendRowFn append_row, + ETableSimpleValueAtFn value_at, + ETableSimpleSetValueAtFn set_value_at, + ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleHasSaveIdFn has_save_id, + ETableSimpleGetSaveIdFn get_save_id, + ETableSimpleDuplicateValueFn duplicate_value, + ETableSimpleFreeValueFn free_value, + ETableSimpleInitializeValueFn initialize_value, + ETableSimpleValueIsEmptyFn value_is_empty, + ETableSimpleValueToStringFn value_to_string, + void *data); + + +/* Helper functions for if your values are all just strings. */ +void *e_table_simple_string_duplicate_value (ETableModel *etm, + int col, + const void *val, + void *data); +void e_table_simple_string_free_value (ETableModel *etm, + int col, + void *val, + void *data); +void *e_table_simple_string_initialize_value (ETableModel *etm, + int col, + void *data); +gboolean e_table_simple_string_value_is_empty (ETableModel *etm, + int col, + const void *val, + void *data); +char *e_table_simple_string_value_to_string (ETableModel *etm, + int col, + const void *val, + void *data); + +END_GNOME_DECLS #endif /* _E_TABLE_SIMPLE_H_ */ diff --git a/widgets/table/e-table-utils.c b/widgets/table/e-table-utils.c index 4c84be94ca..a155d49b0a 100644 --- a/widgets/table/e-table-utils.c +++ b/widgets/table/e-table-utils.c @@ -71,11 +71,16 @@ et_col_spec_to_col (ETableColumnSpecification *col_spec, ETableExtras *ete) { ETableCol *col = NULL; - ECell *cell; - GCompareFunc compare; + ECell *cell = NULL; + GCompareFunc compare = NULL; + ETableSearchFunc search = NULL; - cell = e_table_extras_get_cell(ete, col_spec->cell); - compare = e_table_extras_get_compare(ete, col_spec->compare); + if (col_spec->cell) + cell = e_table_extras_get_cell(ete, col_spec->cell); + if (col_spec->compare) + compare = e_table_extras_get_compare(ete, col_spec->compare); + if (col_spec->search) + search = e_table_extras_get_search(ete, col_spec->search); if (cell && compare) { if (col_spec->pixbuf && *col_spec->pixbuf) { @@ -97,6 +102,7 @@ et_col_spec_to_col (ETableColumnSpecification *col_spec, col_spec->expansion, col_spec->minimum_width, cell, compare, col_spec->resizable, col_spec->disabled, col_spec->priority); } + col->search = search; } return col; } diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 02ae76bcc3..72874991d3 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -255,6 +255,16 @@ et_destroy (GtkObject *object) et_disconnect_model (et); + if (et->search) { + if (et->search_search_id) + gtk_signal_disconnect (GTK_OBJECT (et->search), + et->search_search_id); + if (et->search_accept_id) + gtk_signal_disconnect (GTK_OBJECT (et->search), + et->search_accept_id); + gtk_object_unref (GTK_OBJECT (et->search)); + } + if (et->group_info_change_id) gtk_signal_disconnect (GTK_OBJECT (et->sort_info), et->group_info_change_id); @@ -305,6 +315,76 @@ et_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (parent_class)->unrealize (widget); } +static gboolean +check_row (ETable *et, int model_row, int col, ETableSearchFunc search, char *string) +{ + const void *value; + + value = e_table_model_value_at (et->model, col, model_row); + + return search (value, string); +} + +static gboolean +et_search_search (ETableSearch *search, char *string, ETable *et) +{ + int cursor; + int rows; + int i; + int col; + ETableSearchFunc search_func; + + col = et->current_search_col; + if (col == -1) + return FALSE; + + rows = e_table_model_row_count (et->model); + + search_func = et->current_search; + + gtk_object_get(GTK_OBJECT(et->selection), + "cursor_row", &cursor, + NULL); + + cursor = e_sorter_model_to_sorted (E_SORTER (et->sorter), cursor); + + for (i = cursor + 1; i < rows; i++) { + int model_row = e_sorter_sorted_to_model (E_SORTER (et->sorter), i); + if (check_row (et, model_row, col, search_func, string)) { + e_selection_model_select_as_key_press(E_SELECTION_MODEL (et->selection), model_row, col, GDK_CONTROL_MASK); + return TRUE; + } + } + + for (i = 0; i < cursor; i++) { + int model_row = e_sorter_sorted_to_model (E_SORTER (et->sorter), i); + if (check_row (et, model_row, col, search_func, string)) { + e_selection_model_select_as_key_press(E_SELECTION_MODEL (et->selection), model_row, col, GDK_CONTROL_MASK); + return TRUE; + } + } + + cursor = e_sorter_sorted_to_model (E_SORTER (et->sorter), cursor); + + /* Check if the cursor row is the only matching row. */ + return (cursor < rows && cursor >= 0 && check_row (et, cursor, col, search_func, string)); +} + +static void +et_search_accept (ETableSearch *search, ETable *et) +{ + int col, cursor; + + col = et->current_search_col; + if (col == -1) + return; + + gtk_object_get(GTK_OBJECT(et->selection), + "cursor_row", &cursor, + NULL); + e_selection_model_select_as_key_press(E_SELECTION_MODEL (et->selection), cursor, col, 0); +} + static void e_table_init (GtkObject *object) { @@ -351,6 +431,18 @@ e_table_init (GtkObject *object) e_table->selection = e_table_selection_model_new(); e_table->cursor_loc = E_TABLE_CURSOR_LOC_NONE; e_table->spec = NULL; + + e_table->search = e_table_search_new(); + + e_table->search_search_id = + gtk_signal_connect (GTK_OBJECT (e_table->search), "search", + GTK_SIGNAL_FUNC (et_search_search), e_table); + e_table->search_accept_id = + gtk_signal_connect (GTK_OBJECT (e_table->search), "accept", + GTK_SIGNAL_FUNC (et_search_accept), e_table); + + e_table->current_search = NULL; + e_table->current_search_col = -1; } /* Grab_focus handler for the ETable */ @@ -642,6 +734,11 @@ group_key_press (ETableGroup *etg, int row, int col, GdkEvent *event, ETable *et return_val = 1; break; default: + if ((key->keyval >= GDK_a && key->keyval <= GDK_z) || + (key->keyval >= GDK_A && key->keyval <= GDK_Z) || + (key->keyval >= GDK_0 && key->keyval <= GDK_9)) { + e_table_search_input_character (et->search, key->keyval); + } gtk_signal_emit (GTK_OBJECT (et), et_signals [KEY_PRESS], row, col, event, &return_val); @@ -1220,6 +1317,7 @@ et_real_construct (ETable *e_table, ETableModel *etm, ETableExtras *ete, ETableSpecification *specification, ETableState *state) { int row = 0; + int col_count, i; if (ete) gtk_object_ref(GTK_OBJECT(ete)); @@ -1236,6 +1334,16 @@ et_real_construct (ETable *e_table, ETableModel *etm, ETableExtras *ete, e_table->cursor_mode = specification->cursor_mode; e_table->full_header = e_table_spec_to_full_header(specification, ete); + col_count = e_table_header_count (e_table->full_header); + for (i = 0; i < col_count; i++) { + ETableCol *col = e_table_header_get_column(e_table->full_header, i); + if (col && col->search) { + e_table->current_search_col = col->col_idx; + e_table->current_search = col->search; + break; + } + } + gtk_object_set(GTK_OBJECT(e_table->selection), "selection_mode", specification->selection_mode, "cursor_mode", specification->cursor_mode, diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index c1cc971674..932420bb1b 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -39,6 +39,7 @@ #include #include #include +#include #include BEGIN_GNOME_DECLS @@ -74,6 +75,14 @@ typedef struct { ETableCursorLoc cursor_loc; ETableSpecification *spec; + ETableSearch *search; + + ETableSearchFunc current_search; + int current_search_col; + + guint search_search_id; + guint search_accept_id; + int table_model_change_id; int table_row_change_id; int table_cell_change_id; -- cgit v1.2.3