From: John Darrington Date: Wed, 18 Jul 2007 00:50:58 +0000 (+0000) Subject: Added the ability to resize string variables from the GUI. Thanks to X-Git-Tag: v0.6.0~377 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f514231dd2fc0c2adc1ebab5c46a4b55d2bd9c2b;p=pspp-builds.git Added the ability to resize string variables from the GUI. Thanks to Ben for his comments. --- diff --git a/src/data/ChangeLog b/src/data/ChangeLog index 26c751ab..7d8ef4dd 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,16 @@ +2007-07-18 John Darrington + + * datasheet.c (datasheet_delete_columns): Added assertion to check + we're not deleting outside the range of the sheet. + + + * dictionary.c dictionary.h variable.c: Added the ability for string + variables to be resized. + + * vardict.h: Added some prototypes (moved from dictionary.h) as + these should only be called by variable.c + + 2007-07-14 John Darrington * sfm-reader.c: Respect case_cnt field in file header. diff --git a/src/data/datasheet.c b/src/data/datasheet.c index 971144cb..913c8e5a 100644 --- a/src/data/datasheet.c +++ b/src/data/datasheet.c @@ -354,6 +354,8 @@ datasheet_delete_columns (struct datasheet *ds, size_t start, size_t cnt) { size_t lcol; + assert ( start + cnt <= axis_get_size (ds->columns) ); + /* Free up columns for reuse. */ for (lcol = start; lcol < start + cnt; lcol++) { diff --git a/src/data/dictionary.c b/src/data/dictionary.c index d580474e..44504ed9 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -156,14 +156,22 @@ dict_clear (struct dictionary *d) while (d->var_cnt > 0 ) { - var_clear_vardict (d->var[d->var_cnt - 1]); - var_destroy (d->var[d->var_cnt -1]); + struct variable *v = d->var[d->var_cnt - 1]; + int dict_index = var_get_dict_index (v); + int case_index = var_get_case_index (v); + int val_cnt = var_get_value_cnt (v); + + var_clear_vardict (v); + var_destroy (v); d->var_cnt--; if (d->callbacks && d->callbacks->var_deleted ) - d->callbacks->var_deleted (d, d->var_cnt, d->cb_data); + d->callbacks->var_deleted (d, + dict_index, case_index, val_cnt, + d->cb_data); } + free (d->var); d->var = NULL; d->var_cnt = d->var_cap = 0; @@ -418,7 +426,7 @@ set_var_dict_index (struct variable *v, int dict_index) d->callbacks->var_changed (d, dict_index, d->cb_data); } -/* Sets the case_index in V's vardict to DICT_INDEX. */ +/* Sets the case_index in V's vardict to CASE_INDEX. */ static void set_var_case_index (struct variable *v, int case_index) { @@ -455,6 +463,8 @@ void dict_delete_var (struct dictionary *d, struct variable *v) { int dict_index = var_get_dict_index (v); + const int case_index = var_get_case_index (v); + const int val_cnt = var_get_value_cnt (v); assert (dict_contains_var (d, v)); @@ -487,7 +497,7 @@ dict_delete_var (struct dictionary *d, struct variable *v) var_destroy (v); if (d->callbacks && d->callbacks->var_deleted ) - d->callbacks->var_deleted (d, dict_index, d->cb_data); + d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data); } /* Deletes the COUNT variables listed in VARS from D. This is @@ -834,6 +844,33 @@ dict_compact_values (struct dictionary *d) } } + +/* + Reassigns case indices for D, increasing each index above START by + the value PADDING. +*/ +static void +dict_pad_values (struct dictionary *d, int start, int padding) +{ + size_t i; + + if ( padding <= 0 ) + return; + + for (i = 0; i < d->var_cnt; ++i) + { + struct variable *v = d->var[i]; + + int index = var_get_case_index (v); + + if ( index >= start) + set_var_case_index (v, index + padding); + } + + d->next_value_idx += padding; +} + + /* Returns the number of values that would be used by a case if dict_compact_values() were called. */ size_t @@ -1388,3 +1425,23 @@ dict_var_changed (const struct variable *v) d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); } } + + +/* Called from variable.c to notify the dictionary that the variable's width + has changed */ +void +dict_var_resized (const struct variable *v, int delta) +{ + if ( var_has_vardict (v)) + { + const struct vardict_info *vdi = var_get_vardict (v); + struct dictionary *d; + + d = vdi->dict; + + dict_pad_values (d, var_get_case_index(v) + 1, delta); + + if ( d->callbacks && d->callbacks->var_resized ) + d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data); + } +} diff --git a/src/data/dictionary.h b/src/data/dictionary.h index 9dbd7733..4887a310 100644 --- a/src/data/dictionary.h +++ b/src/data/dictionary.h @@ -29,8 +29,9 @@ struct string; struct dict_callbacks { void (*var_added) (struct dictionary *, int, void *); - void (*var_deleted) (struct dictionary *, int, void *); + void (*var_deleted) (struct dictionary *, int, int, int, void *); void (*var_changed) (struct dictionary *, int, void *); + void (*var_resized) (struct dictionary *, int, int, void *); void (*weight_changed) (struct dictionary *, int, void *); void (*filter_changed) (struct dictionary *, int, void *); void (*split_changed) (struct dictionary *, void *); @@ -148,7 +149,4 @@ void dict_clear_vectors (struct dictionary *); void dict_assign_short_names (struct dictionary *); -/* Called only from variable.c */ -void dict_var_changed (const struct variable *v); - #endif /* dictionary.h */ diff --git a/src/data/vardict.h b/src/data/vardict.h index 4e124afc..aaf8ba05 100644 --- a/src/data/vardict.h +++ b/src/data/vardict.h @@ -36,4 +36,9 @@ void var_set_vardict (struct variable *, const struct vardict_info *); bool var_has_vardict (const struct variable *); void var_clear_vardict (struct variable *); + +/* Called only from variable.c, but defined in dictionary.c */ +void dict_var_changed (const struct variable *v); +void dict_var_resized (const struct variable *v, int delta); + #endif /* data/vardict.h */ diff --git a/src/data/variable.c b/src/data/variable.c index aa65606f..a10a8ade 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -29,6 +29,7 @@ #include "value-labels.h" #include "vardict.h" +#include #include #include #include @@ -349,6 +350,7 @@ var_get_width (const struct variable *v) void var_set_width (struct variable *v, int new_width) { + const int old_width = v->width; enum var_type new_type = var_type_from_width (new_width); if (mv_is_resizable (&v->miss, new_width)) @@ -382,6 +384,14 @@ var_set_width (struct variable *v, int new_width) v->width = new_width; + { + const int old_val_count = value_cnt_from_width (old_width); + const int new_val_count = value_cnt_from_width (new_width); + + if ( old_val_count != new_val_count) + dict_var_resized (v, new_val_count - old_val_count); + } + dict_var_changed (v); } diff --git a/src/ui/gui/ChangeLog b/src/ui/gui/ChangeLog index 602e59d2..23707386 100644 --- a/src/ui/gui/ChangeLog +++ b/src/ui/gui/ChangeLog @@ -1,3 +1,13 @@ +2007-07-18 John Darrington + + * psppire-case-file.c psppire-case-file.h psppire-data-store.c + psppire-dict.c psppire-dict.h psppire-var-store.c : Added the + ability to resize string variables. Fixed associated problems + inserting/deleting variables. + + * helper.c helper.h (marshaller_VOID__INT_INT_INT): New marshaller + function. + 2007-07-16 John Darrington * data-editor.c: File Open dialog remembers directory. Thanks to diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c index 22072578..09711f1b 100644 --- a/src/ui/gui/helper.c +++ b/src/ui/gui/helper.c @@ -20,6 +20,8 @@ */ #include +#include + #include #include "helper.h" #include "message-dialog.h" @@ -208,3 +210,49 @@ execute_syntax (struct getl_interface *sss) } + +#ifdef G_ENABLE_DEBUG +# define g_marshal_value_peek_int(v) g_value_get_int (v) +#else +# define g_marshal_value_peek_int(v) (v)->data[0].v_int +#endif + + +/* VOID:INT,INT,INT */ +void +marshaller_VOID__INT_INT_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__INT_INT_INT) (gpointer data1, + gint arg_1, + gint arg_2, + gint arg_3, + gpointer data2); + register GMarshalFunc_VOID__INT_INT_INT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__INT_INT_INT) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_int (param_values + 1), + g_marshal_value_peek_int (param_values + 2), + g_marshal_value_peek_int (param_values + 3), + data2); +} diff --git a/src/ui/gui/helper.h b/src/ui/gui/helper.h index 5a245361..ddced00f 100644 --- a/src/ui/gui/helper.h +++ b/src/ui/gui/helper.h @@ -61,5 +61,12 @@ gboolean execute_syntax (struct getl_interface *sss); glade_xml_new (relocate(PKGDATADIR "/" FILE), NULL, NULL) +void marshaller_VOID__INT_INT_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + #endif diff --git a/src/ui/gui/psppire-case-file.c b/src/ui/gui/psppire-case-file.c index 7de97f5c..455ac2b7 100644 --- a/src/ui/gui/psppire-case-file.c +++ b/src/ui/gui/psppire-case-file.c @@ -341,25 +341,33 @@ psppire_case_file_sort (PsppireCaseFile *cf, struct case_ordering *ordering) /* Resize the cases in the casefile, by inserting N_VALUES into every - one of them. */ + one of them at the position immediately preceeding WHERE. +*/ gboolean psppire_case_file_insert_values (PsppireCaseFile *cf, - gint n_values, gint before) + gint n_values, gint where) { - union value *values; g_return_val_if_fail (cf, FALSE); g_return_val_if_fail (cf->accessible, FALSE); + if ( n_values == 0 ) + return FALSE; + + g_assert (n_values > 0); + if ( ! cf->datasheet ) cf->datasheet = datasheet_create (NULL); - values = xcalloc (n_values, sizeof *values); - datasheet_insert_columns (cf->datasheet, values, n_values, before); + { + union value *values = xcalloc (n_values, sizeof *values); + datasheet_insert_columns (cf->datasheet, values, n_values, where); free (values); + } return TRUE; } + /* Fills C with the CASENUMth case. Returns true on success, false otherwise. */ diff --git a/src/ui/gui/psppire-case-file.h b/src/ui/gui/psppire-case-file.h index 7ef3daa2..1dc297ac 100644 --- a/src/ui/gui/psppire-case-file.h +++ b/src/ui/gui/psppire-case-file.h @@ -93,7 +93,7 @@ void psppire_case_file_clear (PsppireCaseFile *cf); gboolean psppire_case_file_delete_cases (PsppireCaseFile *cf, casenumber n_rows, casenumber first); -gboolean psppire_case_file_insert_values (PsppireCaseFile *cf, gint n_values, gint before); +gboolean psppire_case_file_insert_values (PsppireCaseFile *cf, gint n_values, gint where); struct case_ordering; diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c index 638661a5..cc755761 100644 --- a/src/ui/gui/psppire-data-store.c +++ b/src/ui/gui/psppire-data-store.c @@ -282,30 +282,27 @@ changed_case_callback (GtkWidget *w, gint casenum, gpointer data) } +/* + A callback which occurs after a variable has been deleted. + */ static void -delete_variables_callback (GObject *obj, gint var_num, gint n_vars, gpointer data) +delete_variable_callback (GObject *obj, gint dict_index, + gint case_index, gint val_cnt, + gpointer data) { - PsppireDataStore *store ; + PsppireDataStore *store = PSPPIRE_DATA_STORE (data); - g_return_if_fail (data); - - store = PSPPIRE_DATA_STORE (data); - - g_sheet_model_columns_deleted (G_SHEET_MODEL (store), var_num, n_vars); + g_sheet_model_columns_deleted (G_SHEET_MODEL (store), dict_index, 1); g_sheet_column_columns_changed (G_SHEET_COLUMN (store), - var_num, -1); + dict_index, -1); } static void variable_changed_callback (GObject *obj, gint var_num, gpointer data) { - PsppireDataStore *store; - - g_return_if_fail (data); - - store = PSPPIRE_DATA_STORE (data); + PsppireDataStore *store = PSPPIRE_DATA_STORE (data); g_sheet_column_columns_changed (G_SHEET_COLUMN (store), var_num, 1); @@ -353,13 +350,16 @@ static void dict_size_change_callback (GObject *obj, gint posn, gint adjustment, gpointer data) { - PsppireDataStore *store ; + PsppireDataStore *store = PSPPIRE_DATA_STORE (data); - g_return_if_fail (data); + const struct variable *v = psppire_dict_get_variable (store->dict, posn); - store = PSPPIRE_DATA_STORE (data); + const gint new_val_width = value_cnt_from_width (var_get_width (v)); - psppire_case_file_insert_values (store->case_file, adjustment, posn); + if ( adjustment > 0 ) + psppire_case_file_insert_values (store->case_file, adjustment, + new_val_width - adjustment + + var_get_case_index(v)); } @@ -432,15 +432,14 @@ psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *di G_CALLBACK (insert_variable_callback), data_store); - g_signal_connect (dict, "variables-deleted", - G_CALLBACK (delete_variables_callback), + g_signal_connect (dict, "variable-deleted", + G_CALLBACK (delete_variable_callback), data_store); g_signal_connect (dict, "variable-changed", G_CALLBACK (variable_changed_callback), data_store); - g_signal_connect (dict, "dict-size-changed", G_CALLBACK (dict_size_change_callback), data_store); diff --git a/src/ui/gui/psppire-dict.c b/src/ui/gui/psppire-dict.c index 3e37343b..31761136 100644 --- a/src/ui/gui/psppire-dict.c +++ b/src/ui/gui/psppire-dict.c @@ -45,7 +45,7 @@ static GObjectClass *parent_class = NULL; enum {VARIABLE_CHANGED, VARIABLE_RESIZED, VARIABLE_INSERTED, - VARIABLES_DELETED, + VARIABLE_DELETED, WEIGHT_CHANGED, FILTER_CHANGED, SPLIT_CHANGED, @@ -131,15 +131,16 @@ psppire_dict_class_init (PsppireDictClass *class) G_TYPE_INT); - signals [VARIABLES_DELETED] = - g_signal_new ("variables_deleted", + signals [VARIABLE_DELETED] = + g_signal_new ("variable-deleted", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - gtkextra_VOID__INT_INT, + marshaller_VOID__INT_INT_INT, G_TYPE_NONE, - 2, + 3, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); @@ -211,9 +212,11 @@ addcb (struct dictionary *d, int idx, void *pd) } static void -delcb (struct dictionary *d, int idx, void *pd) +delcb (struct dictionary *d, int dict_idx, int case_idx, int value_cnt, + void *pd) { - g_signal_emit (pd, signals [VARIABLES_DELETED], 0, idx, 1); + g_signal_emit (pd, signals [VARIABLE_DELETED], 0, + dict_idx, case_idx, value_cnt ); } static void @@ -222,6 +225,12 @@ mutcb (struct dictionary *d, int idx, void *pd) g_signal_emit (pd, signals [VARIABLE_CHANGED], 0, idx); } +static void +resize_cb (struct dictionary *d, int idx, int delta, void *pd) +{ + g_signal_emit (pd, signals [VARIABLE_RESIZED], 0, idx, delta); +} + static void weight_changed_callback (struct dictionary *d, int idx, void *pd) { @@ -246,6 +255,7 @@ static const struct dict_callbacks gui_callbacks = addcb, delcb, mutcb, + resize_cb, weight_changed_callback, filter_changed_callback, split_changed_callback @@ -346,7 +356,6 @@ psppire_dict_delete_variables (PsppireDict *d, gint first, gint n) var = dict_get_var (d->dict, first); dict_delete_var (d->dict, var); } - dict_compact_values (d->dict); } @@ -467,8 +476,6 @@ psppire_dict_resize_variable (PsppireDict *d, const struct variable *pv, if ( old_size == new_size ) return ; - dict_compact_values (d->dict); - fv = var_get_case_index (pv); g_signal_emit (d, signals [VARIABLE_RESIZED], 0, @@ -764,3 +771,29 @@ psppire_dict_get_weight_variable (const PsppireDict *dict) { return dict_get_weight (dict->dict); } + + + +#if DEBUGGING +void +psppire_dict_dump (const PsppireDict *dict) +{ + gint i; + const struct dictionary *d = dict->dict; + + int *map = dict_get_compacted_dict_index_to_case_index (d); + + for (i = 0; i < dict_get_var_cnt (d); ++i) + { + const struct variable *v = psppire_dict_get_variable (dict, i); + int di = var_get_dict_index (v); + g_print ("\"%s\" idx=%d, fv=%d(%d), size=%d\n", + var_get_name(v), + di, + var_get_case_index(v), + map[di], + value_cnt_from_width(var_get_width(v))); + + } +} +#endif diff --git a/src/ui/gui/psppire-dict.h b/src/ui/gui/psppire-dict.h index 9314dbe4..397097bf 100644 --- a/src/ui/gui/psppire-dict.h +++ b/src/ui/gui/psppire-dict.h @@ -57,7 +57,6 @@ struct _PsppireDict struct _PsppireDictClass { GObjectClass parent_class; - }; @@ -103,6 +102,9 @@ void psppire_dict_replace_dictionary (PsppireDict *, struct dictionary *); struct variable * psppire_dict_get_weight_variable (const PsppireDict *); +#if DEBUGGING +void psppire_dict_dump (const PsppireDict *); +#endif G_END_DECLS diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c index 3ba2da2a..c296bfe2 100644 --- a/src/ui/gui/psppire-var-store.c +++ b/src/ui/gui/psppire-var-store.c @@ -271,11 +271,11 @@ var_change_callback (GtkWidget *w, gint n, gpointer data) static void -var_delete_callback (GtkWidget *w, gint first, gint n, gpointer data) +var_delete_callback (GtkWidget *w, gint dict_idx, gint case_idx, gint val_cnt, gpointer data) { GSheetModel *model = G_SHEET_MODEL (data); - g_sheet_model_rows_deleted (model, first, n); + g_sheet_model_rows_deleted (model, dict_idx, 1); } @@ -308,7 +308,7 @@ psppire_var_store_set_dictionary (PsppireVarStore *var_store, PsppireDict *dict) g_signal_connect (dict, "variable-changed", G_CALLBACK (var_change_callback), var_store); - g_signal_connect (dict, "variables-deleted", G_CALLBACK (var_delete_callback), + g_signal_connect (dict, "variable-deleted", G_CALLBACK (var_delete_callback), var_store); g_signal_connect (dict, "variable-inserted", G_CALLBACK (var_insert_callback),