From 4f122d673cbe7cd1e11a951c5dd9f6d5e23431b7 Mon Sep 17 00:00:00 2001 From: Christopher James Lahey Date: Thu, 21 Feb 2002 19:02:32 +0000 Subject: Added e-table-memory-store.lo. 2002-02-21 Christopher James Lahey * gal/Makefile.am (libgal_la_LIBADD): Added e-table-memory-store.lo. From gal/e-table/ChangeLog: 2002-02-21 Christopher James Lahey * Makefile.am (libetable_la_SOURCES): Added e-table-memory-store.c. (libetableinclude_HEADERS): Added e-table-memory-store.h. * e-table-config-no-group.glade, e-table-config.glade: Updated these. * e-table-config.c, e-table-config.h: Updated this to have a working field list editor. * e-table-memory-store.c, e-table-memory-store.h: New ETableModel that is a complete store of all the data in your table. No callbacks at all. * e-table-subset-variable.c, e-table-subset-variable.h (e_table_subset_variable_clear): Added this simple function * e-table-subset.c (etss_get_save_id): Made this return the row number g_strdup_printfed if the source model doesn't support save ids. 2002-02-20 Christopher James Lahey * e-table-sorter.c, e-table-sorter.h: Connect to the model_rows_inserted, model_rows_deleted, and group_info_changed here. svn path=/trunk/; revision=15783 --- widgets/table/e-table-config-no-group.glade | 172 ++++++++----- widgets/table/e-table-config.c | 301 ++++++++++++++++++++++- widgets/table/e-table-config.glade | 228 ++++++++++------- widgets/table/e-table-config.h | 8 + widgets/table/e-table-memory-store.c | 363 ++++++++++++++++++++++++++++ widgets/table/e-table-memory-store.h | 109 +++++++++ widgets/table/e-table-sorter.c | 36 +++ widgets/table/e-table-sorter.h | 3 + widgets/table/e-table-subset-variable.c | 15 ++ widgets/table/e-table-subset-variable.h | 41 ++-- widgets/table/e-table-subset.c | 9 +- 11 files changed, 1101 insertions(+), 184 deletions(-) create mode 100644 widgets/table/e-table-memory-store.c create mode 100644 widgets/table/e-table-memory-store.h diff --git a/widgets/table/e-table-config-no-group.glade b/widgets/table/e-table-config-no-group.glade index 6f32c14e0c..1e49a59a06 100644 --- a/widgets/table/e-table-config-no-group.glade +++ b/widgets/table/e-table-config-no-group.glade @@ -188,32 +188,17 @@ - GtkScrolledWindow - scrolledwindow1 - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS + Custom + custom-available + e_table_proxy_etable_available_new + 0 + 0 + Thu, 21 Feb 2002 05:42:43 GMT 0 True True - - - GtkViewport - viewport1 - GTK_SHADOW_IN - - - Custom - available-field-list - e_table_proxy_etable_new - 0 - 0 - Sun, 18 Mar 2001 23:59:35 GMT - - @@ -238,32 +223,17 @@ - GtkScrolledWindow - scrolledwindow2 - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS + Custom + custom-shown + e_table_proxy_etable_shown_new + 0 + 0 + Thu, 21 Feb 2002 15:52:40 GMT 0 True True - - - GtkViewport - viewport2 - GTK_SHADOW_IN - - - Custom - fields-shown - e_table_proxy_etable_new - 0 - 0 - Sun, 18 Mar 2001 23:59:49 GMT - - @@ -1605,12 +1575,66 @@ GtkTable table1 2 - 1 + 2 3 False 2 4 + + GtkButton + button-sort + True + True + + clicked + on_sort_clicked + Tue, 03 Oct 2000 22:10:58 GMT + + + GTK_RELIEF_NORMAL + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label-sort + + GTK_JUSTIFY_LEFT + True + 0 + 0.5 + 0 + 0 + + 1 + 2 + 1 + 2 + 0 + 0 + True + False + False + False + True + True + + + GtkLabel label4 @@ -1624,8 +1648,8 @@ 2 3 - 0 - 1 + 1 + 2 0 0 False @@ -1633,25 +1657,23 @@ False False True - False + True - GtkButton - button-sort - True - True - - clicked - on_sort_clicked - Tue, 03 Oct 2000 22:10:58 GMT - - - GTK_RELIEF_NORMAL + GtkLabel + label21 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 - 0 - 1 + 2 + 3 0 1 0 @@ -1661,13 +1683,13 @@ False False True - False + True GtkLabel - label-sort + label-fields GTK_JUSTIFY_LEFT True @@ -1690,6 +1712,34 @@ True + + + GtkButton + button-fields + True + True + + clicked + on_sort_clicked + Tue, 03 Oct 2000 22:10:58 GMT + + + GTK_RELIEF_NORMAL + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + diff --git a/widgets/table/e-table-config.c b/widgets/table/e-table-config.c index 030f11b2f1..6b9ec94159 100644 --- a/widgets/table/e-table-config.c +++ b/widgets/table/e-table-config.c @@ -44,6 +44,10 @@ #include "gal/util/e-util.h" #include "gal/util/e-i18n.h" +#include +#include +#include + #define PARENT_TYPE (gtk_object_get_type()) @@ -333,6 +337,22 @@ config_group_info_update (ETableConfig *config) g_string_free (res, TRUE); } +static void +setup_fields (ETableConfig *config) +{ + int i; + + e_table_without_show_all (config->available_model); + e_table_subset_variable_clear (config->shown_model); + + if (config->temp_state) { + for (i = 0; i < config->temp_state->col_count; i++) { + e_table_subset_variable_add (config->shown_model, config->temp_state->columns[i]); + e_table_without_hide (config->available_model, (void *) config->temp_state->columns[i]); + } + } +} + static void config_fields_info_update (ETableConfig *config) { @@ -340,8 +360,6 @@ config_fields_info_update (ETableConfig *config) GString *res = g_string_new (""); int i; - return; - for (i = 0; i < config->state->col_count; i++){ for (column = config->source_spec->columns; *column; column++){ @@ -388,10 +406,10 @@ do_sort_and_group_config_dialog (ETableConfig *config, gboolean is_sort) case 0: if (is_sort){ e_table_sort_info_sorting_truncate ( - config->state->sort_info, 0); + config->temp_state->sort_info, 0); } else { e_table_sort_info_grouping_truncate ( - config->state->sort_info, 0); + config->temp_state->sort_info, 0); } update_sort_and_group_config_dialog (config, is_sort); continue; @@ -423,21 +441,101 @@ do_sort_and_group_config_dialog (ETableConfig *config, gboolean is_sort) config_group_info_update (config); } -GtkWidget *e_table_proxy_etable_new (void); +static void +do_fields_config_dialog (ETableConfig *config) +{ + int button, running = 1; + + config->temp_state = e_table_state_duplicate (config->state); + + setup_fields (config); + + do { + button = gnome_dialog_run (GNOME_DIALOG(config->dialog_show_fields)); + switch (button){ + /* OK */ + case 0: + gtk_object_unref (GTK_OBJECT (config->state)); + config->state = config->temp_state; + config->temp_state = 0; + running = 0; + gnome_property_box_changed ( + GNOME_PROPERTY_BOX (config->dialog_toplevel)); + break; + + /* CANCEL */ + case 1: + gtk_object_unref (GTK_OBJECT (config->temp_state)); + config->temp_state = 0; + running = 0; + break; + } + + } while (running); + gnome_dialog_close (GNOME_DIALOG (config->dialog_show_fields)); + + config_fields_info_update (config); +} + + +ETableMemoryStoreColumnInfo store_columns[] = { + E_TABLE_MEMORY_STORE_STRING, + E_TABLE_MEMORY_STORE_TERMINATOR +}; + +static ETableModel *global_store; /* Glade better not be reentrant any time soon. */ + +static void +create_global_store (ETableConfig *config) +{ + int i; + + global_store = e_table_memory_store_new (store_columns); + for (i = 0; config->source_spec->columns[i]; i++) { + e_table_memory_store_insert (E_TABLE_MEMORY_STORE (global_store), i, (void **) &config->source_spec->columns[i]->title, NULL); + } +} + +char *spec = " \ + \ + \ + \ + \ + "; + +GtkWidget *e_table_proxy_etable_shown_new (void); GtkWidget * -e_table_proxy_etable_new (void) +e_table_proxy_etable_shown_new (void) { - return gtk_label_new ("Field selection dialog not\nimplemented here yet."); + ETableModel *model = NULL; + + model = e_table_subset_variable_new (global_store); + + return e_table_scrolled_new (model, NULL, spec, NULL); +} + +GtkWidget *e_table_proxy_etable_available_new (void); + +GtkWidget * +e_table_proxy_etable_available_new (void) +{ + ETableModel *model; + + model = e_table_without_new (global_store, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + e_table_without_show_all (E_TABLE_WITHOUT (model)); + + return e_table_scrolled_new (model, NULL, spec, NULL); } static void config_button_fields (GtkWidget *widget, ETableConfig *config) { - gnome_dialog_run (GNOME_DIALOG(config->dialog_show_fields)); - gnome_dialog_close (GNOME_DIALOG (config->dialog_show_fields)); + do_fields_config_dialog (config); } - + static void config_button_sort (GtkWidget *widget, ETableConfig *config) { @@ -712,16 +810,198 @@ configure_group_dialog (ETableConfig *config, GladeXML *gui) } } +static void +add_column (int model_row, gpointer closure) +{ + GList **columns = closure; + *columns = g_list_prepend (*columns, GINT_TO_POINTER (model_row)); +} + +static void +config_button_add (GtkWidget *widget, ETableConfig *config) +{ + GList *columns = NULL; + GList *column; + int count; + int i; + + e_table_selected_row_foreach (config->available, add_column, &columns); + columns = g_list_reverse (columns); + + count = g_list_length (columns); + + config->temp_state->columns = g_renew (int, config->temp_state->columns, config->temp_state->col_count + count); + config->temp_state->expansions = g_renew (double, config->temp_state->expansions, config->temp_state->col_count + count); + i = config->temp_state->col_count; + for (column = columns; column; column = column->next) { + config->temp_state->columns[i] = e_table_subset_view_to_model_row (E_TABLE_SUBSET (config->available_model), GPOINTER_TO_INT (column->data)); + config->temp_state->expansions[i] = config->source_spec->columns[config->temp_state->columns[i]]->expansion; + i++; + } + config->temp_state->col_count += count; + + g_list_free (columns); + + setup_fields (config); +} + +static void +config_button_remove (GtkWidget *widget, ETableConfig *config) +{ + GList *columns = NULL; + GList *column; + + e_table_selected_row_foreach (config->shown, add_column, &columns); + + for (column = columns; column; column = column->next) { + int row = GPOINTER_TO_INT (column->data); + + memmove (config->temp_state->columns + row, config->temp_state->columns + row + 1, sizeof (int) * (config->temp_state->col_count - row - 1)); + memmove (config->temp_state->expansions + row, config->temp_state->expansions + row + 1, sizeof (double) * (config->temp_state->col_count - row - 1)); + config->temp_state->col_count --; + } + config->temp_state->columns = g_renew (int, config->temp_state->columns, config->temp_state->col_count); + config->temp_state->expansions = g_renew (double, config->temp_state->expansions, config->temp_state->col_count); + + g_list_free (columns); + + setup_fields (config); +} + +static void +config_button_up (GtkWidget *widget, ETableConfig *config) +{ + GList *columns = NULL; + GList *column; + int *new_shown; + double *new_expansions; + int next_col; + double next_expansion; + int i; + + e_table_selected_row_foreach (config->shown, add_column, &columns); + columns = g_list_reverse (columns); + + new_shown = g_new (int, config->temp_state->col_count); + new_expansions = g_new (double, config->temp_state->col_count); + + column = columns; + + next_col = config->temp_state->columns[0]; + next_expansion = config->temp_state->expansions[0]; + + for (i = 1; i < config->temp_state->col_count; i++) { + if (column && (GPOINTER_TO_INT (column->data) == i)) { + new_expansions[i - 1] = config->temp_state->expansions[i]; + new_shown[i - 1] = config->temp_state->columns[i]; + column = column->next; + } else { + new_shown[i - 1] = next_col; + next_col = config->temp_state->columns[i]; + + new_expansions[i - 1] = next_expansion; + next_expansion = config->temp_state->expansions[i]; + } + } + + new_shown[i - 1] = next_col; + new_expansions[i - 1] = next_expansion; + + g_free (config->temp_state->columns); + g_free (config->temp_state->expansions); + + config->temp_state->columns = new_shown; + config->temp_state->expansions = new_expansions; + + g_list_free (columns); + + setup_fields (config); +} + +static void +config_button_down (GtkWidget *widget, ETableConfig *config) +{ + GList *columns = NULL; + GList *column; + int *new_shown; + double *new_expansions; + int next_col; + double next_expansion; + int i; + + e_table_selected_row_foreach (config->shown, add_column, &columns); + + new_shown = g_new (int, config->temp_state->col_count); + new_expansions = g_new (double, config->temp_state->col_count); + + column = columns; + + next_col = config->temp_state->columns[config->temp_state->col_count - 1]; + next_expansion = config->temp_state->expansions[config->temp_state->col_count - 1]; + + for (i = config->temp_state->col_count - 1; i > 0; i--) { + if (column && (GPOINTER_TO_INT (column->data) == i - 1)) { + new_expansions[i] = config->temp_state->expansions[i - 1]; + new_shown[i] = config->temp_state->columns[i - 1]; + column = column->next; + } else { + new_shown[i] = next_col; + next_col = config->temp_state->columns[i - 1]; + + new_expansions[i] = next_expansion; + next_expansion = config->temp_state->expansions[i - 1]; + } + } + + new_shown[0] = next_col; + new_expansions[0] = next_expansion; + + g_free (config->temp_state->columns); + g_free (config->temp_state->expansions); + + config->temp_state->columns = new_shown; + config->temp_state->expansions = new_expansions; + + g_list_free (columns); + + setup_fields (config); +} + +static void +configure_fields_dialog (ETableConfig *config, GladeXML *gui) +{ + config->available = e_table_scrolled_get_table (E_TABLE_SCROLLED (glade_xml_get_widget (gui, "custom-available"))); + gtk_object_get (GTK_OBJECT (config->available), + "model", &config->available_model, + NULL); + + config->shown = e_table_scrolled_get_table (E_TABLE_SCROLLED (glade_xml_get_widget (gui, "custom-shown"))); + gtk_object_get (GTK_OBJECT (config->shown), + "model", &config->shown_model, + NULL); + + connect_button (config, gui, "button-add", config_button_add); + connect_button (config, gui, "button-remove", config_button_remove); + connect_button (config, gui, "button-up", config_button_up); + connect_button (config, gui, "button-down", config_button_down); + + setup_fields (config); +} + static void setup_gui (ETableConfig *config) { GladeXML *gui; + create_global_store (config); + if (e_table_sort_info_get_can_group (config->state->sort_info)) { gui = glade_xml_new_with_domain (ETABLE_GLADEDIR "/e-table-config.glade", NULL, PACKAGE); } else { gui = glade_xml_new_with_domain (ETABLE_GLADEDIR "/e-table-config-no-group.glade", NULL, PACKAGE); } + + gtk_object_unref (GTK_OBJECT (global_store)); config->dialog_toplevel = glade_xml_get_widget ( gui, "e-table-config"); @@ -756,6 +1036,7 @@ setup_gui (ETableConfig *config) configure_sort_dialog (config, gui); configure_group_dialog (config, gui); + configure_fields_dialog (config, gui); gtk_signal_connect ( GTK_OBJECT (config->dialog_toplevel), "destroy", diff --git a/widgets/table/e-table-config.glade b/widgets/table/e-table-config.glade index 42bef34956..f7f0683f7e 100644 --- a/widgets/table/e-table-config.glade +++ b/widgets/table/e-table-config.glade @@ -188,32 +188,17 @@ - GtkScrolledWindow - scrolledwindow1 - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS + Custom + custom-available + e_table_proxy_etable_available_new + 0 + 0 + Thu, 21 Feb 2002 16:09:53 GMT 0 True True - - - GtkViewport - viewport1 - GTK_SHADOW_IN - - - Custom - available-field-list - e_table_proxy_etable_new - 0 - 0 - Sun, 18 Mar 2001 23:59:35 GMT - - @@ -238,32 +223,17 @@ - GtkScrolledWindow - scrolledwindow2 - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS + Custom + custom-shown + e_table_proxy_etable_shown_new + 0 + 0 + Thu, 21 Feb 2002 16:09:58 GMT 0 True True - - - GtkViewport - viewport2 - GTK_SHADOW_IN - - - Custom - fields-shown - e_table_proxy_etable_new - 0 - 0 - Sun, 18 Mar 2001 23:59:49 GMT - - @@ -1605,27 +1575,57 @@ GtkTable table1 2 - 2 + 3 3 False 2 4 - GtkLabel - label3 - - GTK_JUSTIFY_CENTER - False - 0 - 0.5 - 0 - 0 + GtkButton + button-sort + True + True + + clicked + on_sort_clicked + Tue, 03 Oct 2000 22:10:58 GMT + + + GTK_RELIEF_NORMAL - 2 - 3 - 0 - 1 + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkButton + button-group + True + True + + clicked + on_group_by_clicked + Tue, 03 Oct 2000 22:10:50 GMT + + + GTK_RELIEF_NORMAL + + 0 + 1 + 1 + 2 0 0 False @@ -1639,61 +1639,59 @@ GtkLabel - label4 + label-group - GTK_JUSTIFY_CENTER - False + GTK_JUSTIFY_LEFT + True 0 0.5 0 0 - 2 - 3 + 1 + 2 1 2 0 0 - False + True False False False True - False + True - GtkButton - button-sort - True - True - - clicked - on_sort_clicked - Tue, 03 Oct 2000 22:10:58 GMT - - - GTK_RELIEF_NORMAL + GtkLabel + label-sort + + GTK_JUSTIFY_LEFT + True + 0 + 0.5 + 0 + 0 - 0 - 1 - 1 - 2 + 1 + 2 + 2 + 3 0 0 - False + True False False False True - False + True GtkButton - button-group + button-fields True True @@ -1701,7 +1699,7 @@ on_group_by_clicked Tue, 03 Oct 2000 22:10:50 GMT - + GTK_RELIEF_NORMAL 0 @@ -1721,7 +1719,7 @@ GtkLabel - label-group + label-fields GTK_JUSTIFY_LEFT True @@ -1747,22 +1745,74 @@ GtkLabel - label-sort + label3 - GTK_JUSTIFY_LEFT - True + GTK_JUSTIFY_CENTER + False 0 0.5 0 0 - 1 - 2 + 2 + 3 1 2 0 0 - True + False + False + False + False + True + True + + + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 2 + 3 + 2 + 3 + 0 + 0 + False + False + False + False + True + True + + + + + GtkLabel + label22 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 2 + 3 + 0 + 1 + 0 + 0 + False False False False diff --git a/widgets/table/e-table-config.h b/widgets/table/e-table-config.h index b87aa14d64..46bf1507ac 100644 --- a/widgets/table/e-table-config.h +++ b/widgets/table/e-table-config.h @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include BEGIN_GNOME_DECLS @@ -75,6 +78,11 @@ typedef struct { ETableConfigSortWidgets sort [4]; ETableConfigSortWidgets group [4]; + ETable *available; + ETableWithout *available_model; + ETable *shown; + ETableSubsetVariable *shown_model; + /* * List of valid column names */ diff --git a/widgets/table/e-table-memory-store.c b/widgets/table/e-table-memory-store.c new file mode 100644 index 0000000000..276bb99104 --- /dev/null +++ b/widgets/table/e-table-memory-store.c @@ -0,0 +1,363 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-memory-store.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-memory-store.h" + +#define PARENT_TYPE e_table_memory_get_type () + +#define STORE_LOCATOR(etms, col, row) (*((etms)->priv->store + (row) * (etms)->priv->col_count + (col))) + +struct _ETableMemoryStorePrivate { + int col_count; + ETableMemoryStoreColumnInfo *columns; + void **store; +}; + +static void * +duplicate_value (ETableMemoryStore *etms, int col, const void *val) +{ + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (val); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.duplicate_value) + return etms->priv->columns[col].custom.duplicate_value (E_TABLE_MODEL (etms), col, val, NULL); + break; + default: + break; + } + return (void *) val; +} + +static int +etms_column_count (ETableModel *etm) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return etms->priv->col_count; +} + +static void * +etms_value_at (ETableModel *etm, int col, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return STORE_LOCATOR (etms, col, row); +} + +static void +etms_set_value_at (ETableModel *etm, int col, int row, const void *val) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + STORE_LOCATOR (etms, col, row) = duplicate_value (etms, col, val); + + e_table_model_cell_changed (etm, col, row); +} + +static gboolean +etms_is_cell_editable (ETableModel *etm, int col, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return etms->priv->columns[col].editable; +} + +/* The default for etms_duplicate_value is to return the raw value. */ +static void * +etms_duplicate_value (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + return duplicate_value (etms, col, value); +} + +static void +etms_free_value (ETableModel *etm, int col, void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + g_free (value); + break; + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.free_value) + etms->priv->columns[col].custom.free_value (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } +} + +static void * +etms_initialize_value (ETableModel *etm, int col) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (""); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.initialize_value) + return etms->priv->columns[col].custom.initialize_value (E_TABLE_MODEL (etms), col, NULL); + break; + default: + break; + } + return 0; +} + +static gboolean +etms_value_is_empty (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return !(value && *(char *) value); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.value_is_empty) + return etms->priv->columns[col].custom.value_is_empty (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } + return value == 0; +} + +static char * +etms_value_to_string (ETableModel *etm, int col, const void *value) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + + switch (etms->priv->columns[col].type) { + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING: + return g_strdup (value); + case E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM: + if (etms->priv->columns[col].custom.value_is_empty) + return etms->priv->columns[col].custom.value_to_string (E_TABLE_MODEL (etms), col, value, NULL); + break; + default: + break; + } + return g_strdup_printf ("%d", GPOINTER_TO_INT (value)); +} + +static void +etms_append_row (ETableModel *etm, ETableModel *source, int row) +{ + ETableMemoryStore *etms = E_TABLE_MEMORY_STORE(etm); + void **new_data; + int i; + int row_count; + + new_data = g_new (void *, etms->priv->col_count); + + for (i = 0; i < etms->priv->col_count; i++) { + new_data[i] = e_table_model_value_at (source, i, row); + } + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + + e_table_memory_store_insert (etms, row_count, new_data, NULL); +} + +static void +e_table_memory_store_init (ETableMemoryStore *etms) +{ + etms->priv = g_new (ETableMemoryStorePrivate, 1); + + etms->priv->col_count = 0; + etms->priv->columns = NULL; + etms->priv->store = NULL; +} + +static void +e_table_memory_store_class_init (GtkObjectClass *object_class) +{ + ETableModelClass *model_class = (ETableModelClass *) object_class; + + model_class->column_count = etms_column_count; + model_class->value_at = etms_value_at; + model_class->set_value_at = etms_set_value_at; + model_class->is_cell_editable = etms_is_cell_editable; + model_class->duplicate_value = etms_duplicate_value; + model_class->free_value = etms_free_value; + model_class->initialize_value = etms_initialize_value; + model_class->value_is_empty = etms_value_is_empty; + model_class->value_to_string = etms_value_to_string; + model_class->append_row = etms_append_row; +} + +GtkType +e_table_memory_store_get_type (void) +{ + static GtkType type = 0; + + if (!type){ + GtkTypeInfo info = { + "ETableMemoryStore", + sizeof (ETableMemoryStore), + sizeof (ETableMemoryStoreClass), + (GtkClassInitFunc) e_table_memory_store_class_init, + (GtkObjectInitFunc) e_table_memory_store_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +/** + * e_table_memory_store_new: + * @col_count: + * @value_at: + * @set_value_at: + * @is_cell_editable: + * @duplicate_value: + * @free_value: + * @initialize_value: + * @value_is_empty: + * @value_to_string: + * @data: closure pointer. + * + * This initializes a new ETableMemoryStoreModel object. ETableMemoryStoreModel is + * an implementaiton of the abstract class ETableModel. The ETableMemoryStoreModel + * is designed to allow people to easily create ETableModels without having + * to create a new GtkType derived from ETableModel every time they need one. + * + * Instead, ETableMemoryStoreModel uses a setup based in callback functions, every + * callback function signature mimics the signature of each ETableModel method + * and passes the extra @data pointer to each one of the method to provide them + * with any context they might want to use. + * + * Returns: An ETableMemoryStoreModel object (which is also an ETableModel + * object). + */ +ETableModel * +e_table_memory_store_new (ETableMemoryStoreColumnInfo *columns) +{ + ETableMemoryStore *et; + + et = gtk_type_new (e_table_memory_store_get_type ()); + + if (e_table_memory_store_construct (et, columns)) { + return (ETableModel *) et; + } else { + gtk_object_unref (GTK_OBJECT (et)); + return NULL; + } +} + +ETableModel * +e_table_memory_store_construct (ETableMemoryStore *etms, ETableMemoryStoreColumnInfo *columns) +{ + int i; + for (i = 0; columns[i].type != E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR; i++) + /* Intentionally blank */; + etms->priv->col_count = i; + + etms->priv->columns = g_new (ETableMemoryStoreColumnInfo, etms->priv->col_count + 1); + + memcpy (etms->priv->columns, columns, (etms->priv->col_count + 1) * sizeof (ETableMemoryStoreColumnInfo)); + + return E_TABLE_MODEL (etms); +} + + +void +e_table_memory_store_adopt_value_at (ETableMemoryStore *etms, int col, int row, void *value) +{ + STORE_LOCATOR (etms, col, row) = value; + + e_table_model_cell_changed (E_TABLE_MODEL (etms), col, row); +} + +/* The size of these arrays is the number of columns. */ +void +e_table_memory_store_insert (ETableMemoryStore *etms, int row, void **store, gpointer data) +{ + int row_count; + int i; + + e_table_memory_insert (E_TABLE_MEMORY (etms), row, data); + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + 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 - 1) * sizeof (void *)); + + for (i = 0; i < etms->priv->col_count; i++) { + STORE_LOCATOR(etms, i, row) = duplicate_value(etms, i, store[i]); + } +} + +void +e_table_memory_store_insert_adopt (ETableMemoryStore *etms, int row, void **store, gpointer data) +{ + 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 *)); + 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 *)); + + for (i = 0; i < etms->priv->col_count; i++) { + STORE_LOCATOR(etms, i, row) = store[i]; + } +} + +void +e_table_memory_store_remove (ETableMemoryStore *etms, int row) +{ + int row_count; + + e_table_memory_remove (E_TABLE_MEMORY (etms), row); + + row_count = e_table_model_row_count (E_TABLE_MODEL (etms)); + memmove (etms->priv->store + etms->priv->col_count * row, + etms->priv->store + etms->priv->col_count * (row + 1), + etms->priv->col_count * (row_count - row) * sizeof (void *)); + etms->priv->store = g_realloc (etms->priv->store, etms->priv->col_count * row_count * sizeof (void *)); +} + +void +e_table_memory_store_clear (ETableMemoryStore *etms) +{ + e_table_memory_clear (E_TABLE_MEMORY (etms)); + + g_free (etms->priv->store); + etms->priv->store = NULL; +} diff --git a/widgets/table/e-table-memory-store.h b/widgets/table/e-table-memory-store.h new file mode 100644 index 0000000000..33a84a2b1b --- /dev/null +++ b/widgets/table/e-table-memory-store.h @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-memory-store.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_MEMORY_STORE_H_ +#define _E_TABLE_MEMORY_STORE_H_ + +#include +#include +#include + +BEGIN_GNOME_DECLS + +#define E_TABLE_MEMORY_STORE_TYPE (e_table_memory_store_get_type ()) +#define E_TABLE_MEMORY_STORE(o) (GTK_CHECK_CAST ((o), E_TABLE_MEMORY_STORE_TYPE, ETableMemoryStore)) +#define E_TABLE_MEMORY_STORE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_MEMORY_STORE_TYPE, ETableMemoryStoreClass)) +#define E_IS_TABLE_MEMORY_STORE(o) (GTK_CHECK_TYPE ((o), E_TABLE_MEMORY_STORE_TYPE)) +#define E_IS_TABLE_MEMORY_STORE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_MEMORY_STORE_TYPE)) + +typedef enum { + E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_INTEGER, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, + E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM +} ETableMemoryStoreColumnType; + +typedef struct { + ETableMemoryCalbacksDuplicateValueFn duplicate_value; + ETableMemoryCalbacksFreeValueFn free_value; + ETableMemoryCalbacksInitializeValueFn initialize_value; + ETableMemoryCalbacksValueIsEmptyFn value_is_empty; + ETableMemoryCalbacksValueToStringFn value_to_string; +} ETableMemoryStoreCustomColumn; + +typedef struct { + ETableMemoryStoreColumnType type; + ETableMemoryStoreCustomColumn custom; + guint editable : 1; +} ETableMemoryStoreColumnInfo; + +#define E_TABLE_MEMORY_STORE_TERMINATOR { E_TABLE_MEMORY_STORE_COLUMN_TYPE_TERMINATOR, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_INTEGER { E_TABLE_MEMORY_STORE_COLUMN_TYPE_INTEGER, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_STRING { E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, { NULL }, FALSE } +#define E_TABLE_MEMORY_STORE_EDITABLE_STRING { E_TABLE_MEMORY_STORE_COLUMN_TYPE_STRING, { NULL }, TRUE } +#define E_TABLE_MEMORY_STORE_CUSTOM(editable, duplicate, free, initialize, empty, string) \ + { E_TABLE_MEMORY_STORE_COLUMN_TYPE_CUSTOM, \ + { (duplicate), (free), (initialize), (empty), (string) }, editable } + +typedef struct _ETableMemoryStorePrivate ETableMemoryStorePrivate; + +typedef struct { + ETableMemory parent; + + ETableMemoryStorePrivate *priv; +} ETableMemoryStore; + +typedef struct { + ETableMemoryClass parent_class; +} ETableMemoryStoreClass; + +GtkType e_table_memory_store_get_type (void); + +/* Object Creation */ +ETableModel *e_table_memory_store_new (ETableMemoryStoreColumnInfo *columns); +ETableModel *e_table_memory_store_construct (ETableMemoryStore *store, + ETableMemoryStoreColumnInfo *columns); + +/* Adopt a value instead of copying it. */ +void e_table_memory_store_adopt_value_at (ETableMemoryStore *etms, + int col, + int row, + void *value); + +/* The size of these arrays is the number of columns. */ +void e_table_memory_store_insert (ETableMemoryStore *etms, + int row, + void **store, + gpointer data); +void e_table_memory_store_insert_adopt (ETableMemoryStore *etms, + int row, + void **store, + gpointer data); +void e_table_memory_store_remove (ETableMemoryStore *etms, + int row); +void e_table_memory_store_clear (ETableMemoryStore *etms); + +END_GNOME_DECLS + +#endif /* _E_TABLE_MEMORY_STORE_H_ */ + diff --git a/widgets/table/e-table-sorter.c b/widgets/table/e-table-sorter.c index 879234b742..6afafb6824 100644 --- a/widgets/table/e-table-sorter.c +++ b/widgets/table/e-table-sorter.c @@ -45,6 +45,8 @@ static ESorterClass *parent_class; static void ets_model_changed (ETableModel *etm, ETableSorter *ets); static void ets_model_row_changed (ETableModel *etm, int row, ETableSorter *ets); static void ets_model_cell_changed (ETableModel *etm, int col, int row, ETableSorter *ets); +static void ets_model_rows_inserted (ETableModel *etm, int row, int count, ETableSorter *ets); +static void ets_model_rows_deleted (ETableModel *etm, int row, int count, ETableSorter *ets); static void ets_sort_info_changed (ETableSortInfo *info, ETableSorter *ets); static void ets_clean (ETableSorter *ets); static void ets_sort (ETableSorter *ets); @@ -67,13 +69,22 @@ ets_destroy (GtkObject *object) ets->table_model_row_changed_id); gtk_signal_disconnect (GTK_OBJECT (ets->source), ets->table_model_cell_changed_id); + gtk_signal_disconnect (GTK_OBJECT (ets->source), + ets->table_model_rows_inserted_id); + gtk_signal_disconnect (GTK_OBJECT (ets->source), + ets->table_model_rows_deleted_id); gtk_signal_disconnect (GTK_OBJECT (ets->sort_info), ets->sort_info_changed_id); + gtk_signal_disconnect (GTK_OBJECT (ets->sort_info), + ets->group_info_changed_id); ets->table_model_changed_id = 0; ets->table_model_row_changed_id = 0; ets->table_model_cell_changed_id = 0; + ets->table_model_rows_inserted_id = 0; + ets->table_model_rows_deleted_id = 0; ets->sort_info_changed_id = 0; + ets->group_info_changed_id = 0; if (ets->sort_info) gtk_object_unref(GTK_OBJECT(ets->sort_info)); @@ -95,6 +106,8 @@ ets_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) if (ets->sort_info) { if (ets->sort_info_changed_id) gtk_signal_disconnect(GTK_OBJECT(ets->sort_info), ets->sort_info_changed_id); + if (ets->group_info_changed_id) + gtk_signal_disconnect(GTK_OBJECT(ets->sort_info), ets->group_info_changed_id); gtk_object_unref(GTK_OBJECT(ets->sort_info)); } @@ -102,6 +115,8 @@ ets_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) gtk_object_ref(GTK_OBJECT(ets->sort_info)); ets->sort_info_changed_id = gtk_signal_connect (GTK_OBJECT (ets->sort_info), "sort_info_changed", GTK_SIGNAL_FUNC (ets_sort_info_changed), ets); + ets->group_info_changed_id = gtk_signal_connect (GTK_OBJECT (ets->sort_info), "group_info_changed", + GTK_SIGNAL_FUNC (ets_sort_info_changed), ets); ets_clean (ets); break; @@ -155,7 +170,10 @@ ets_init (ETableSorter *ets) ets->table_model_changed_id = 0; ets->table_model_row_changed_id = 0; ets->table_model_cell_changed_id = 0; + ets->table_model_rows_inserted_id = 0; + ets->table_model_rows_deleted_id = 0; ets->sort_info_changed_id = 0; + ets->group_info_changed_id = 0; } E_MAKE_TYPE(e_table_sorter, "ETableSorter", ETableSorter, ets_class_init, ets_init, PARENT_TYPE); @@ -178,8 +196,14 @@ e_table_sorter_new (ETableModel *source, ETableHeader *full_header, ETableSortIn GTK_SIGNAL_FUNC (ets_model_row_changed), ets); ets->table_model_cell_changed_id = gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed", GTK_SIGNAL_FUNC (ets_model_cell_changed), ets); + ets->table_model_rows_inserted_id = gtk_signal_connect (GTK_OBJECT (source), "model_rows_inserted", + GTK_SIGNAL_FUNC (ets_model_rows_inserted), ets); + ets->table_model_rows_deleted_id = gtk_signal_connect (GTK_OBJECT (source), "model_rows_deleted", + GTK_SIGNAL_FUNC (ets_model_rows_deleted), ets); ets->sort_info_changed_id = gtk_signal_connect (GTK_OBJECT (sort_info), "sort_info_changed", GTK_SIGNAL_FUNC (ets_sort_info_changed), ets); + ets->group_info_changed_id = gtk_signal_connect (GTK_OBJECT (sort_info), "group_info_changed", + GTK_SIGNAL_FUNC (ets_sort_info_changed), ets); return ets; } @@ -202,6 +226,18 @@ ets_model_cell_changed (ETableModel *etm, int col, int row, ETableSorter *ets) ets_clean(ets); } +static void +ets_model_rows_inserted (ETableModel *etm, int row, int count, ETableSorter *ets) +{ + ets_clean(ets); +} + +static void +ets_model_rows_deleted (ETableModel *etm, int row, int count, ETableSorter *ets) +{ + ets_clean(ets); +} + static void ets_sort_info_changed (ETableSortInfo *info, ETableSorter *ets) { diff --git a/widgets/table/e-table-sorter.h b/widgets/table/e-table-sorter.h index 02d51c5522..b0097b9155 100644 --- a/widgets/table/e-table-sorter.h +++ b/widgets/table/e-table-sorter.h @@ -56,7 +56,10 @@ typedef struct { int table_model_changed_id; int table_model_row_changed_id; int table_model_cell_changed_id; + int table_model_rows_inserted_id; + int table_model_rows_deleted_id; int sort_info_changed_id; + int group_info_changed_id; } ETableSorter; typedef struct { diff --git a/widgets/table/e-table-subset-variable.c b/widgets/table/e-table-subset-variable.c index a55f162bcf..6d298d6050 100644 --- a/widgets/table/e-table-subset-variable.c +++ b/widgets/table/e-table-subset-variable.c @@ -202,6 +202,21 @@ e_table_subset_variable_remove (ETableSubsetVariable *etssv, return FALSE; } +void +e_table_subset_variable_clear (ETableSubsetVariable *etssv) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + + e_table_model_pre_change (etm); + etss->n_map = 0; + g_free (etss->map_table); + etss->map_table = g_new (unsigned int, 1); + etssv->n_vals_allocated = 1; + + e_table_model_changed (etm); +} + void e_table_subset_variable_increment (ETableSubsetVariable *etssv, gint position, diff --git a/widgets/table/e-table-subset-variable.h b/widgets/table/e-table-subset-variable.h index 4ee55f5670..eae291b1d2 100644 --- a/widgets/table/e-table-subset-variable.h +++ b/widgets/table/e-table-subset-variable.h @@ -56,26 +56,27 @@ typedef struct { gint row); } ETableSubsetVariableClass; -GtkType e_table_subset_variable_get_type (void); -ETableModel *e_table_subset_variable_new (ETableModel *etm); -ETableModel *e_table_subset_variable_construct (ETableSubsetVariable *etssv, - ETableModel *source); -void e_table_subset_variable_add (ETableSubsetVariable *ets, - gint row); -void e_table_subset_variable_add_array (ETableSubsetVariable *ets, - const gint *array, - gint count); -void e_table_subset_variable_add_all (ETableSubsetVariable *ets); -gboolean e_table_subset_variable_remove (ETableSubsetVariable *ets, - gint row); -void e_table_subset_variable_increment (ETableSubsetVariable *ets, - gint position, - gint amount); -void e_table_subset_variable_decrement (ETableSubsetVariable *ets, - gint position, - gint amount); -void e_table_subset_variable_set_allocation (ETableSubsetVariable *ets, - gint total); +GtkType e_table_subset_variable_get_type (void); +ETableModel *e_table_subset_variable_new (ETableModel *etm); +ETableModel *e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source); +void e_table_subset_variable_add (ETableSubsetVariable *ets, + gint row); +void e_table_subset_variable_add_array (ETableSubsetVariable *ets, + const gint *array, + gint count); +void e_table_subset_variable_add_all (ETableSubsetVariable *ets); +gboolean e_table_subset_variable_remove (ETableSubsetVariable *ets, + gint row); +void e_table_subset_variable_clear (ETableSubsetVariable *ets); +void e_table_subset_variable_increment (ETableSubsetVariable *ets, + gint position, + gint amount); +void e_table_subset_variable_decrement (ETableSubsetVariable *ets, + gint position, + gint amount); +void e_table_subset_variable_set_allocation (ETableSubsetVariable *ets, + gint total); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c index d57867bd2a..c5399ce402 100644 --- a/widgets/table/e-table-subset.c +++ b/widgets/table/e-table-subset.c @@ -163,9 +163,7 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) static gboolean etss_has_save_id (ETableModel *etm) { - ETableSubset *etss = (ETableSubset *)etm; - - return e_table_model_has_save_id (etss->source); + return TRUE; } static char * @@ -173,7 +171,10 @@ etss_get_save_id (ETableModel *etm, int row) { ETableSubset *etss = (ETableSubset *)etm; - return e_table_model_get_save_id (etss->source, etss->map_table [row]); + if (e_table_model_has_save_id (etss->source)) + return e_table_model_get_save_id (etss->source, etss->map_table [row]); + else + return g_strdup_printf ("%d", etss->map_table[row]); } static void -- cgit v1.2.3