diff options
-rw-r--r-- | widgets/table/e-table-without.c | 202 | ||||
-rw-r--r-- | widgets/table/e-table-without.h | 38 |
2 files changed, 206 insertions, 34 deletions
diff --git a/widgets/table/e-table-without.c b/widgets/table/e-table-without.c index ba70ee5651..4769d53647 100644 --- a/widgets/table/e-table-without.c +++ b/widgets/table/e-table-without.c @@ -24,32 +24,104 @@ static ETableSubsetClass *parent_class; struct _ETableWithoutPrivate { GHashTable *hash; + + GHashFunc hash_func; + GCompareFunc compare_func; + + ETableWithoutGetKeyFunc get_key_func; + ETableWithoutDuplicateKeyFunc duplicate_key_func; + ETableWithoutFreeKeyFunc free_gotten_key_func; + ETableWithoutFreeKeyFunc free_duplicated_key_func; + + void *closure; }; +static gboolean +check (ETableWithout *etw, int model_row) +{ + gboolean ret_val; + void *key; + ETableSubset *etss = E_TABLE_SUBSET (etw); + + key = etw->priv->get_key_func (etss->source, model_row, etw->priv->closure); + ret_val = (g_hash_table_lookup (etw->priv->hash, key) != NULL); + etw->priv->free_gotten_key_func (key, etw->priv->closure); + return ret_val; +} + +static gboolean +check_with_key (ETableWithout *etw, void *key, int model_row) +{ + gboolean ret_val; + void *key2; + ETableSubset *etss = E_TABLE_SUBSET (etw); + + key2 = etw->priv->get_key_func (etss->source, model_row, etw->priv->closure); + ret_val = (etw->priv->compare_func (key, key2)); + etw->priv->free_gotten_key_func (key, etw->priv->closure); + return ret_val; +} + +static gint +etw_view_to_model_row (ETableWithout *etw, int view_row) +{ + ETableSubset *etss = E_TABLE_SUBSET (etw); + return etss->map_table[view_row]; +} + +static void +add_row (ETableWithout *etw, int model_row) +{ + ETableSubset *etss = E_TABLE_SUBSET (etw); + + etss->map_table = g_renew (int, etss->map_table, etss->n_map + 1); + + etss->map_table[etss->n_map++] = model_row; + + e_table_model_row_inserted (E_TABLE_MODEL (etw), etss->n_map - 1); +} + static void -etw_proxy_model_rows_inserted (ETableSubset *etss, ETableModel *etm, int row, int count) +remove_row (ETableWithout *etw, int view_row) +{ + ETableSubset *etss = E_TABLE_SUBSET (etw); + + memmove (etss->map_table + view_row, etss->map_table + view_row + 1, (etss->n_map - view_row - 1) * sizeof (int)); + etss->n_map --; + e_table_model_row_deleted (E_TABLE_MODEL (etw), view_row); +} + +static void +etw_proxy_model_rows_inserted (ETableSubset *etss, ETableModel *etm, int model_row, int count) { int i; + ETableWithout *etw = E_TABLE_WITHOUT (etss); + /* i is View row */ for (i = 0; i < etss->n_map; i++) { - if (etss->map_table[i] > row) + if (etss->map_table[i] > model_row) etss->map_table[i] += count; } - for (i = row; i < row + count; i++) { - if (check ()) { - add_row (); + /* i is Model row */ + for (i = model_row; i < model_row + count; i++) { + if (check (etw, i)) { + add_row (etw, i); } } } static void -etw_proxy_model_rows_deleted (ETableSubset *etss, ETableModel *etm, int row, int count) +etw_proxy_model_rows_deleted (ETableSubset *etss, ETableModel *etm, int model_row, int count) { - for (i = 0; i < n_map; i++) { - if (etss->map_table[i] >= row && etss->map_table[i] < row + count) - remove_row (); - else if (etss->map_table[i] >= row + count) + int i; /* View row */ + ETableWithout *etw = E_TABLE_WITHOUT (etss); + + for (i = 0; i < etss->n_map; i++) { + if (etss->map_table[i] >= model_row && etss->map_table[i] < model_row + count) { + remove_row (etw, i); + i--; + } else if (etss->map_table[i] >= model_row + count) etss->map_table[i] -= count; } } @@ -57,14 +129,17 @@ etw_proxy_model_rows_deleted (ETableSubset *etss, ETableModel *etm, int row, int static void etw_proxy_model_changed (ETableSubset *etss, ETableModel *etm) { - int i; - int j; + int i; /* Model row */ + int j; /* View row */ int row_count; + ETableWithout *etw = E_TABLE_WITHOUT (etss); + g_free (etss->map_table); row_count = e_table_model_row_count (etm); etss->map_table = g_new (int, row_count); - for (i = 0; i < row_count; i++) { - if (check ()) { + + for (i = 0, j = 0; i < row_count; i++) { + if (check (etw, i)) { etss->map_table[j++] = i; } } @@ -75,10 +150,9 @@ etw_proxy_model_changed (ETableSubset *etss, ETableModel *etm) } static void -etw_class_init (GtkObjectClass *object_class) +etw_class_init (ETableWithoutClass *klass) { - ETableWithoutClass *klass = E_TABLE_WITHOUT_CLASS (object_class); - ETableSubsetClass *etss_class = E_TABLE_SUBSET_CLASS (object_class); + ETableSubsetClass *etss_class = E_TABLE_SUBSET_CLASS (klass); parent_class = gtk_type_class (PARENT_TYPE); etss_class->proxy_model_rows_inserted = etw_proxy_model_rows_inserted; @@ -86,25 +160,70 @@ etw_class_init (GtkObjectClass *object_class) etss_class->proxy_model_changed = etw_proxy_model_changed; } -E_MAKE_TYPE(e_table_without, "ETableWithout", ETableWithout, etw_class_init, NULL, PARENT_TYPE); +static void +etw_init (ETableWithout *etw) +{ + etw->priv = g_new (ETableWithoutPrivate, 1); + etw->priv->hash_func = NULL; + etw->priv->compare_func = NULL; + etw->priv->get_key_func = NULL; + etw->priv->duplicate_key_func = NULL; + etw->priv->free_gotten_key_func = NULL; + etw->priv->free_duplicated_key_func = NULL; +} + +E_MAKE_TYPE(e_table_without, "ETableWithout", ETableWithout, etw_class_init, etw_init, PARENT_TYPE); ETableModel * -e_table_without_construct (ETableWithout *etw, - ETableModel *source) +e_table_without_construct (ETableWithout *etw, + ETableModel *source, + GHashFunc hash_func, + GCompareFunc compare_func, + ETableWithoutGetKeyFunc get_key_func, + ETableWithoutDuplicateKeyFunc duplicate_key_func, + ETableWithoutFreeKeyFunc free_gotten_key_func, + ETableWithoutFreeKeyFunc free_duplicated_key_func, + void *closure) { if (e_table_subset_construct (E_TABLE_SUBSET(etw), source, 1) == NULL) return NULL; E_TABLE_SUBSET(etw)->n_map = 0; + etw->priv->hash_func = hash_func; + etw->priv->compare_func = compare_func; + etw->priv->get_key_func = get_key_func; + etw->priv->duplicate_key_func = duplicate_key_func; + etw->priv->free_gotten_key_func = free_gotten_key_func; + etw->priv->free_duplicated_key_func = free_duplicated_key_func; + etw->priv->closure = closure; + + etw->priv->hash = g_hash_table_new (etw->priv->hash_func, etw->priv->compare_func); + return E_TABLE_MODEL (etw); } ETableModel * -e_table_without_new (ETableModel *source) +e_table_without_new (ETableModel *source, + GHashFunc hash_func, + GCompareFunc compare_func, + ETableWithoutGetKeyFunc get_key_func, + ETableWithoutDuplicateKeyFunc duplicate_key_func, + ETableWithoutFreeKeyFunc free_gotten_key_func, + ETableWithoutFreeKeyFunc free_duplicated_key_func, + void *closure) { ETableWithout *etw = gtk_type_new (E_TABLE_WITHOUT_TYPE); - if (e_table_without_construct (etw, source) == NULL){ + if (e_table_without_construct (etw, + source, + hash_func, + compare_func, + get_key_func, + duplicate_key_func, + free_gotten_key_func, + free_duplicated_key_func, + closure) + == NULL) { gtk_object_unref (GTK_OBJECT (etw)); return NULL; } @@ -115,11 +234,32 @@ e_table_without_new (ETableModel *source) void e_table_without_add (ETableWithout *etw, void *key) { + int i; /* View row */ + ETableSubset *etss = E_TABLE_SUBSET (etw); + + key = etw->priv->duplicate_key_func (key, etw->priv->closure); + + g_hash_table_insert (etw->priv->hash, key, key); + for (i = 0; i < etss->n_map; i++) { + if (check_with_key (etw, key, etw_view_to_model_row (etw, i))) { + remove_row (etw, i); + i --; + } + } +} + +/* An adopted key will later be freed using the free_duplicated_key function. */ +void e_table_without_add_adopt (ETableWithout *etw, + void *key) +{ + int i; /* View row */ ETableSubset *etss = E_TABLE_SUBSET (etw); + g_hash_table_insert (etw->priv->hash, key, key); for (i = 0; i < etss->n_map; i++) { - if (check_with_key (etss->source, i, key)) { - remove_row (); + if (check_with_key (etw, key, etw_view_to_model_row (etw, i))) { + remove_row (etw, i); + i --; } } } @@ -127,10 +267,20 @@ void e_table_without_add (ETableWithout *etw, void e_table_without_remove (ETableWithout *etw, void *key) { + int i; /* Model row */ ETableSubset *etss = E_TABLE_SUBSET (etw); + int count; + void *old_key; + + count = e_table_model_row_count (etss->source); + for (i = 0; i < count; i++) { - if (check_with_key (etss)) { - add_row (); + if (check_with_key (etw, key, i)) { + add_row (etw, i); } } + if (g_hash_table_lookup_extended (etw->priv->hash, key, &old_key, NULL)) { + etw->priv->free_duplicated_key_func (key, etw->priv->closure); + g_hash_table_remove (etw->priv->hash, key); + } } diff --git a/widgets/table/e-table-without.h b/widgets/table/e-table-without.h index 59a86b0126..e73932c713 100644 --- a/widgets/table/e-table-without.h +++ b/widgets/table/e-table-without.h @@ -16,6 +16,13 @@ extern "C" { #define E_IS_TABLE_WITHOUT_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_WITHOUT_TYPE)) typedef struct _ETableWithoutPrivate ETableWithoutPrivate; +typedef void *(*ETableWithoutGetKeyFunc) (ETableModel *source, + int row, + void *closure); +typedef void *(*ETableWithoutDuplicateKeyFunc) (const void *key, + void *closure); +typedef void (*ETableWithoutFreeKeyFunc) (void *key, + void *closure); typedef struct { ETableSubset base; @@ -27,15 +34,30 @@ typedef struct { ETableSubsetClass parent_class; } ETableWithoutClass; - GtkType e_table_without_get_type (void); -ETableModel *e_table_without_new (ETableModel *etm); -ETableModel *e_table_without_construct (ETableWithout *etw, - ETableModel *source); -void e_table_without_add (ETableWithout *etw, - void *key); -void e_table_without_remove (ETableWithout *etw, - void *key); +ETableModel *e_table_without_new (ETableModel *source, + GHashFunc hash_func, + GCompareFunc compare_func, + ETableWithoutGetKeyFunc get_key_func, + ETableWithoutDuplicateKeyFunc duplicate_key_func, + ETableWithoutFreeKeyFunc free_gotten_key_func, + ETableWithoutFreeKeyFunc free_duplicated_key_func, + void *closure); +ETableModel *e_table_without_construct (ETableWithout *etw, + ETableModel *source, + GHashFunc hash_func, + GCompareFunc compare_func, + ETableWithoutGetKeyFunc get_key_func, + ETableWithoutDuplicateKeyFunc duplicate_key_func, + ETableWithoutFreeKeyFunc free_gotten_key_func, + ETableWithoutFreeKeyFunc free_duplicated_key_func, + void *closure); +void e_table_without_add (ETableWithout *etw, + void *key); +void e_table_without_add_adopt (ETableWithout *etw, + void *key); +void e_table_without_remove (ETableWithout *etw, + void *key); #ifdef __cplusplus } #endif /* __cplusplus */ |