From 1ce1429567835f83a712a8a76ab80db64360d742 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sat, 20 May 2006 13:18:27 +0000 Subject: [PATCH] Fixed some bad interaction between variable and data sheets. Allowed user to specify system file on command line. --- lib/gtksheet/ChangeLog | 8 ++ lib/gtksheet/gsheetmodel.c | 93 +++++++++++++++++ lib/gtksheet/gsheetmodel.h | 22 ++++ lib/gtksheet/gtksheet.c | 172 ++++++++++++++++++++++--------- lib/gtksheet/gtksheet.h | 4 +- src/ui/gui/ChangeLog | 12 +++ src/ui/gui/data-sheet.c | 3 +- src/ui/gui/menu-actions.c | 174 +++++++++++++++++--------------- src/ui/gui/menu-actions.h | 6 +- src/ui/gui/psppire-data-store.c | 35 +++++-- src/ui/gui/psppire-dict.c | 16 +-- src/ui/gui/psppire.c | 26 +++-- 12 files changed, 412 insertions(+), 159 deletions(-) diff --git a/lib/gtksheet/ChangeLog b/lib/gtksheet/ChangeLog index 596afc3d..b4a99709 100644 --- a/lib/gtksheet/ChangeLog +++ b/lib/gtksheet/ChangeLog @@ -1,3 +1,11 @@ +Sat May 20 21:02:03 WST 2006 John Darrington + + * gsheetmodel.c gsheetmodel.h: Added columns-inserted and columns-deleted + signals. Added g_sheet_get_{row,column}_count functions. + + * gtksheet.c gtksheet.h: Allowed -1 to be passed to + gtk_sheet_set_active_cell to indicate no active cell. + Mon May 15 16:10:49 WST 2006 John Darrington * gtksheet.c: Removed code which rendered the title buttons a second diff --git a/lib/gtksheet/gsheetmodel.c b/lib/gtksheet/gsheetmodel.c index 3a447188..e6a60afc 100644 --- a/lib/gtksheet/gsheetmodel.c +++ b/lib/gtksheet/gsheetmodel.c @@ -24,6 +24,8 @@ enum { RANGE_CHANGED, ROWS_INSERTED, ROWS_DELETED, + COLUMNS_INSERTED, + COLUMNS_DELETED, LAST_SIGNAL }; @@ -108,6 +110,29 @@ g_sheet_model_base_init (gpointer g_class) G_TYPE_INT, G_TYPE_INT); + sheet_model_signals[COLUMNS_INSERTED] = + g_signal_new ("columns_inserted", + G_TYPE_SHEET_MODEL, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GSheetModelIface, columns_inserted), + NULL, NULL, + gtkextra_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + + + sheet_model_signals[COLUMNS_DELETED] = + g_signal_new ("columns_deleted", + G_TYPE_SHEET_MODEL, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GSheetModelIface, columns_deleted), + NULL, NULL, + gtkextra_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + initialized = TRUE; } @@ -237,6 +262,25 @@ g_sheet_model_rows_inserted (GSheetModel *sheet_model, } +/** + * g_sheet_model_columns_inserted: + * @sheet_model: A #GSheetModel + * @column: The column before which the new columns should be inserted. + * @n_columns: The number of columns to insert. + * + * Emits the "columns_inserted" signal on @sheet_model. + **/ +void +g_sheet_model_columns_inserted (GSheetModel *sheet_model, + gint column, gint n_columns) +{ + g_return_if_fail (G_IS_SHEET_MODEL (sheet_model)); + + g_signal_emit (sheet_model, sheet_model_signals[COLUMNS_INSERTED], 0, + column, n_columns); +} + + /** @@ -259,6 +303,27 @@ g_sheet_model_rows_deleted (GSheetModel *sheet_model, +/** + * g_sheet_model_columns_deleted: + * @sheet_model: A #GSheetModel + * @column: The first column to be deleted. + * @n_columns: The number of columns to delete. + * + * Emits the "columns_deleted" signal on @sheet_model. + **/ +void +g_sheet_model_columns_deleted (GSheetModel *sheet_model, + gint column, gint n_columns) +{ + g_return_if_fail (G_IS_SHEET_MODEL (sheet_model)); + + g_signal_emit (sheet_model, sheet_model_signals[COLUMNS_DELETED], 0, + column, n_columns); +} + + + + /** * g_sheet_model_is_editable: @@ -413,3 +478,31 @@ g_sheet_model_get_cell_border (const GSheetModel *model, +/** + * g_sheet_model_get_column_count: + * @model: A #GSheetModel + * + * Returns the total number of columns represented by the model + **/ +inline gint +g_sheet_model_get_column_count(const GSheetModel *model) +{ + g_return_val_if_fail (G_IS_SHEET_MODEL (model), -1); + + return G_SHEET_MODEL_GET_IFACE (model)->get_column_count (model); +} + +/** + * g_sheet_model_get_row_count: + * @model: A #GSheetModel + * + * Returns the total number of rows represented by the model + **/ +inline gint +g_sheet_model_get_row_count(const GSheetModel *model) +{ + g_return_val_if_fail (G_IS_SHEET_MODEL (model), -1); + + + return G_SHEET_MODEL_GET_IFACE (model)->get_row_count (model); +} diff --git a/lib/gtksheet/gsheetmodel.h b/lib/gtksheet/gsheetmodel.h index 4ee06836..39ab173f 100644 --- a/lib/gtksheet/gsheetmodel.h +++ b/lib/gtksheet/gsheetmodel.h @@ -84,6 +84,14 @@ struct _GSheetModelIface void (* rows_deleted) (GSheetModel *sheet_model, gint row, gint n_rows); + void (* columns_inserted) (GSheetModel *sheet_model, + gint column, gint n_columns); + + void (* columns_deleted) (GSheetModel *sheet_model, + gint column, gint n_columns); + + + /* Virtual Table */ @@ -114,6 +122,11 @@ struct _GSheetModelIface const GtkSheetCellBorder * (* get_cell_border) (const GSheetModel *sheet_model, gint row, gint column); + + gint (*get_column_count) (const GSheetModel *model); + + gint (*get_row_count) (const GSheetModel *model); + }; @@ -142,6 +155,13 @@ inline void g_sheet_model_rows_deleted (GSheetModel *sheet_model, inline void g_sheet_model_rows_inserted (GSheetModel *sheet_model, gint row, gint n_rows); +inline void g_sheet_model_columns_inserted (GSheetModel *sheet_model, + gint column, gint n_columns); + +inline void g_sheet_model_columns_deleted (GSheetModel *sheet_model, + gint column, gint n_columns); + + inline gboolean g_sheet_model_is_editable (const GSheetModel *model, gint row, gint column); @@ -168,7 +188,9 @@ inline const GtkSheetCellBorder * g_sheet_model_get_cell_border inline gboolean g_sheet_model_free_strings (const GSheetModel *sheet_model); +inline gint g_sheet_model_get_column_count(const GSheetModel *sheet_model); +inline gint g_sheet_model_get_row_count(const GSheetModel *sheet_model); G_END_DECLS diff --git a/lib/gtksheet/gtksheet.c b/lib/gtksheet/gtksheet.c index dd7d4190..caed10ba 100644 --- a/lib/gtksheet/gtksheet.c +++ b/lib/gtksheet/gtksheet.c @@ -79,6 +79,9 @@ enum #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag)) #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag)) +#define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED) + + #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN) #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG) #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG) @@ -1134,6 +1137,32 @@ gtk_sheet_init (GtkSheet *sheet) } +/* Callback which occurs whenever columns are inserted/deleted in the model */ +static void +columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns, + gpointer data) +{ + GtkSheet *sheet = GTK_SHEET(data); + + GtkSheetRange range; + gint model_columns = g_sheet_model_get_column_count(model); + + + /* Need to update all the columns starting from the first column and onwards. + * Previous column are unchanged, so don't need to be updated. + */ + range.col0 = first_column; + range.row0 = 0; + range.coli = xxx_column_count(sheet) - 1; + range.rowi = yyy_row_count(sheet) - 1; + + if (sheet->active_cell.col >= model_columns) + gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1); + + gtk_sheet_range_draw(sheet, &range); +} + + /* Callback which occurs whenever rows are inserted/deleted in the model */ static void rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows, @@ -1152,6 +1181,7 @@ rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows, range.coli = xxx_column_count(sheet) - 1; gtk_sheet_range_draw(sheet, &range); + } /* @@ -1251,6 +1281,12 @@ gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model) g_signal_connect(model, "rows_deleted", G_CALLBACK(rows_inserted_deleted_callback), sheet); + g_signal_connect(model, "columns_inserted", + G_CALLBACK(columns_inserted_deleted_callback), sheet); + + g_signal_connect(model, "columns_deleted", + G_CALLBACK(columns_inserted_deleted_callback), sheet); + } @@ -1293,7 +1329,6 @@ gtk_sheet_construct (GtkSheet *sheet, sheet->column_titles_visible = TRUE; sheet->autoscroll = TRUE; sheet->justify_entry = TRUE; - sheet->locked = FALSE; /* create sheet entry */ @@ -1585,16 +1620,33 @@ gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked) g_return_if_fail (sheet != NULL); g_return_if_fail (GTK_IS_SHEET (sheet)); - sheet->locked = locked; + if ( locked ) + { + GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED); + gtk_widget_hide(sheet->sheet_entry); + gtk_widget_unmap(sheet->sheet_entry); + } + else + { + GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED); + if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) + { + gtk_widget_show (sheet->sheet_entry); + gtk_widget_map (sheet->sheet_entry); + } + } + + gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked); + } gboolean -gtk_sheet_locked (GtkSheet *sheet) +gtk_sheet_locked (const GtkSheet *sheet) { g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); - return sheet->locked; + return GTK_SHEET_IS_LOCKED(sheet); } /* This routine has problems with gtk+-1.2 related with the @@ -2841,10 +2893,14 @@ gtk_sheet_map (GtkWidget * widget) gdk_window_show (sheet->row_title_window); } - if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){ - gtk_widget_show (sheet->sheet_entry); - gtk_widget_map (sheet->sheet_entry); - } + if(!GTK_WIDGET_MAPPED (sheet->sheet_entry) + && ! gtk_sheet_locked(sheet) + && sheet->active_cell.row >=0 + && sheet->active_cell.col >=0 ) + { + gtk_widget_show (sheet->sheet_entry); + gtk_widget_map (sheet->sheet_entry); + } if (GTK_WIDGET_VISIBLE (sheet->button) && !GTK_WIDGET_MAPPED (sheet->button)){ @@ -3836,7 +3892,7 @@ gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column) g_return_val_if_fail (sheet != NULL, 0); g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); - if(row < 0 || column < 0) return FALSE; + if(row < -1 || column < -1) return FALSE; if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)) return FALSE; @@ -3845,9 +3901,15 @@ gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column) if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; } - sheet->active_cell.row=row; - sheet->active_cell.col=column; + sheet->active_cell.row = row; + sheet->active_cell.col = column; + if ( row == -1 || column == -1) + { + gtk_sheet_hide_active_cell(sheet); + return TRUE; + } + if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE; if(gtk_sheet_autoscroll(sheet)) @@ -3926,13 +3988,16 @@ gtk_sheet_deactivate_cell(GtkSheet *sheet) if(!veto) return FALSE; + if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 ) + return TRUE; + gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)), (GtkSignalFunc) gtk_sheet_entry_changed, GTK_OBJECT(GTK_WIDGET(sheet))); gtk_sheet_hide_active_cell(sheet); - sheet->active_cell.row=-1; - sheet->active_cell.col=-1; + sheet->active_cell.row = -1; + sheet->active_cell.col = -1; if(GTK_SHEET_REDRAW_PENDING(sheet)){ GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING); @@ -3968,6 +4033,7 @@ gtk_sheet_hide_active_cell(GtkSheet *sheet) if(text && strlen(text)!=0){ gtk_sheet_set_cell(sheet, row, col, justification, text); gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col); + gtk_entry_set_text(GTK_ENTRY(sheet->sheet_entry), ""); } else { @@ -3982,6 +4048,7 @@ gtk_sheet_hide_active_cell(GtkSheet *sheet) row_button_release(sheet, row); #endif + gtk_widget_hide(sheet->sheet_entry); gtk_widget_unmap(sheet->sheet_entry); if(row != -1 && col != -1) @@ -4068,7 +4135,7 @@ gtk_sheet_show_active_cell(GtkSheet *sheet) /* Don't show the active cell, if there is no active cell: */ if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */ return; - + if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; if(sheet->state != GTK_SHEET_NORMAL) return; if(GTK_SHEET_IN_SELECTION(sheet)) return; @@ -4090,11 +4157,10 @@ gtk_sheet_show_active_cell(GtkSheet *sheet) gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible); - if(gtk_sheet_locked(sheet) || !attributes.is_editable){ - gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE); - }else{ - gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE); - } + if(gtk_sheet_locked(sheet) || !attributes.is_editable) + gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE); + else + gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE); /*** Added by John Gotts. Mar 25, 2005 *********/ old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry)); @@ -4128,7 +4194,7 @@ gtk_sheet_draw_active_cell(GtkSheet *sheet) row = sheet->active_cell.row; col = sheet->active_cell.col; - if(row<0 || col<0) return; + if(row < 0 || col < 0) return; if(!gtk_sheet_cell_isvisible(sheet, row, col)) return; #if 0 @@ -4654,6 +4720,9 @@ gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range) if(range->row0 < 0 || range->rowi < 0) return; if(range->col0 < 0 || range->coli < 0) return; + + if ( gtk_sheet_locked(sheet)) return ; + if(sheet->state != GTK_SHEET_NORMAL) gtk_sheet_real_unselect_range(sheet, NULL); else @@ -4914,35 +4983,40 @@ gtk_sheet_button_press (GtkWidget * widget, GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE); } else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW && - !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) { - if(sheet->state==GTK_STATE_NORMAL) { - row=sheet->active_cell.row; - column=sheet->active_cell.col; - if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; - sheet->active_cell.row=row; - sheet->active_cell.col=column; - sheet->drag_range=sheet->range; - sheet->state=GTK_SHEET_RANGE_SELECTED; - gtk_sheet_select_range(sheet, &sheet->drag_range); - } - sheet->x_drag=x; - sheet->y_drag=y; - if(row < sheet->range.row0) row++; - if(row > sheet->range.rowi) row--; - if(column < sheet->range.col0) column++; - if(column > sheet->range.coli) column--; - sheet->drag_cell.row=row; - sheet->drag_cell.col=column; - sheet->drag_range=sheet->range; - draw_xor_rectangle(sheet, sheet->drag_range); - GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG); - } - else - { - gtk_sheet_click_cell(sheet, row, column, &veto); - if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); - } - + !GTK_SHEET_IN_SELECTION(sheet) + && ! GTK_SHEET_IN_DRAG(sheet) + && ! gtk_sheet_locked(sheet) + && sheet->active_cell.row >= 0 + && sheet->active_cell.col >= 0 + ) + { + if(sheet->state==GTK_STATE_NORMAL) { + row=sheet->active_cell.row; + column=sheet->active_cell.col; + if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; + sheet->active_cell.row=row; + sheet->active_cell.col=column; + sheet->drag_range=sheet->range; + sheet->state=GTK_SHEET_RANGE_SELECTED; + gtk_sheet_select_range(sheet, &sheet->drag_range); + } + sheet->x_drag=x; + sheet->y_drag=y; + if(row < sheet->range.row0) row++; + if(row > sheet->range.rowi) row--; + if(column < sheet->range.col0) column++; + if(column > sheet->range.coli) column--; + sheet->drag_cell.row=row; + sheet->drag_cell.col=column; + sheet->drag_range=sheet->range; + draw_xor_rectangle(sheet, sheet->drag_range); + GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG); + } + else + { + gtk_sheet_click_cell(sheet, row, column, &veto); + if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); + } } if(event->window == sheet->column_title_window){ diff --git a/lib/gtksheet/gtksheet.h b/lib/gtksheet/gtksheet.h index 18c39f25..ed6cd31e 100644 --- a/lib/gtksheet/gtksheet.h +++ b/lib/gtksheet/gtksheet.h @@ -71,7 +71,6 @@ enum /* Public flags, for compatibility */ -#define GTK_SHEET_IS_LOCKED(sheet) gtk_sheet_locked(sheet) #define GTK_SHEET_ROW_FROZEN(sheet) !gtk_sheet_rows_resizable(sheet) #define GTK_SHEET_COLUMN_FROZEN(sheet) !gtk_sheet_columns_resizable(sheet) #define GTK_SHEET_AUTORESIZE(sheet) gtk_sheet_autoresize(sheet) @@ -120,7 +119,6 @@ struct _GtkSheet{ gboolean autoscroll; gboolean clip_text; gboolean justify_entry; - gboolean locked; guint freeze_count; @@ -377,7 +375,7 @@ void gtk_sheet_set_locked (GtkSheet *sheet, gboolean lock); gboolean -gtk_sheet_locked (GtkSheet *sheet); +gtk_sheet_locked (const GtkSheet *sheet); /* set sheet title */ void diff --git a/src/ui/gui/ChangeLog b/src/ui/gui/ChangeLog index 3d1b900e..4fe6e3f3 100644 --- a/src/ui/gui/ChangeLog +++ b/src/ui/gui/ChangeLog @@ -1,3 +1,15 @@ +Sat May 20 21:08:18 WST 2006 John Darrington + + * data-sheet.c, menu-actions.c menu-actions: Fixed data sheet so that + active cell is never on a deleted variable. + + * psppire-data-store.c psppire-data-store.h: Added get_var_count and + get_case_count functions. + + * psppire-dict.c: removed VARIABLE_DELETED (singular) signal. + + * psppire.c: Allowed user to specify *.sav file on command line. + Mon May 15 20:01:25 WST 2006 John Darrington * menu-actions.c psppire-case-array.c psppire-case-array.h diff --git a/src/ui/gui/data-sheet.c b/src/ui/gui/data-sheet.c index a9d980de..af32f801 100644 --- a/src/ui/gui/data-sheet.c +++ b/src/ui/gui/data-sheet.c @@ -84,7 +84,7 @@ click2column(GtkWidget *w, gint col, gpointer data) /* Update the data_ref_entry with the reference of the active cell */ -static gint +gint update_data_ref_entry(const GtkSheet *sheet, gint row, gint col) { @@ -150,6 +150,7 @@ psppire_data_sheet_create (gchar *widget_name, gchar *string1, gchar *string2, GTK_SIGNAL_FUNC (click2column), 0); + gtk_sheet_set_active_cell(GTK_SHEET(sheet), -1, -1); gtk_widget_show(sheet); return sheet; diff --git a/src/ui/gui/menu-actions.c b/src/ui/gui/menu-actions.c index 38f73ebe..d1165f38 100644 --- a/src/ui/gui/menu-actions.c +++ b/src/ui/gui/menu-actions.c @@ -76,9 +76,16 @@ void on_new1_activate (GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet"); + GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet"); + + gtk_sheet_set_active_cell(GTK_SHEET(data_sheet), -1, -1); + + gtk_sheet_set_active_cell(GTK_SHEET(var_sheet), 0, 0); + psppire_dict_clear(the_dictionary); psppire_case_array_clear(the_cases); - + psppire_set_window_title(untitled); if (psppire_handle) @@ -86,6 +93,7 @@ on_new1_activate (GtkMenuItem *menuitem, psppire_handle = 0 ; } + static gboolean populate_case_from_reader(struct ccase *c, gpointer aux) { @@ -95,6 +103,86 @@ populate_case_from_reader(struct ccase *c, gpointer aux) } +/* Load a system file. + Return TRUE if successfull +*/ +gboolean +load_system_file(const gchar *file_name) +{ + int ni ; + gint case_num; + + PsppireVarStore *var_store ; + PsppireDataStore *data_store ; + struct dictionary *new_dict; + struct sfm_read_info ri; + struct sfm_reader *reader ; + + GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet"); + GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet"); + + + g_assert(data_sheet); + g_assert(var_sheet); + + if ( psppire_handle ) + fh_free(psppire_handle); + + psppire_handle = + fh_create_file (handle_name, file_name, fh_default_properties()); + + if ( !psppire_handle ) + { + g_warning("Cannot read handle for reading system file \"%s\"\n", + file_name); + return FALSE; + } + + + reader = sfm_open_reader (psppire_handle, &new_dict, &ri); + + if ( ! reader ) + return FALSE; + + /* FIXME: We need a better way of updating a dictionary than this */ + the_dictionary = psppire_dict_new_from_dict(new_dict); + + var_store = + PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet))); + + psppire_var_store_set_dictionary(var_store, the_dictionary); + + + data_store = + PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet))); + + psppire_data_store_set_dictionary(data_store, + the_dictionary); + + psppire_case_array_clear(data_store->cases); + + + psppire_set_window_title(basename(file_name)); + + ni = dict_get_next_value_idx(the_dictionary->dict); + if ( ni == 0 ) + return FALSE; + + for(case_num=0;;case_num++) + { + if (!psppire_case_array_append_case(the_cases, + populate_case_from_reader, + reader)) + break; + } + + + sfm_close_reader(reader); + + return TRUE; +} + + void on_open1_activate (GtkMenuItem *menuitem, gpointer user_data) @@ -129,94 +217,22 @@ on_open1_activate (GtkMenuItem *menuitem, gtk_file_filter_add_pattern(filter, "*"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); - do { if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - PsppireVarStore *var_store ; - PsppireDataStore *data_store ; - struct dictionary *new_dict; - struct sfm_read_info ri; - struct sfm_reader *reader ; - - GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet"); - GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet"); - gchar *file_name; - - g_assert(data_sheet); - g_assert(var_sheet); - - file_name = gtk_file_chooser_get_filename - (GTK_FILE_CHOOSER (dialog)); - - if ( psppire_handle ) - fh_free(psppire_handle); - - psppire_handle = - fh_create_file (handle_name, file_name, fh_default_properties()); - - if ( !psppire_handle ) - { - g_warning("Cannot read handle for reading system file \"%s\"\n", - file_name); - continue; - } - - - reader = sfm_open_reader (psppire_handle, &new_dict, &ri); - - if ( ! reader ) - continue; - - the_dictionary = psppire_dict_new_from_dict(new_dict); - - var_store = - PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet))); + gchar *file_name = + gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog)); - psppire_var_store_set_dictionary(var_store, the_dictionary); - - - data_store = - PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet))); - - - psppire_data_store_set_dictionary(data_store, - the_dictionary); - - psppire_case_array_clear(data_store->cases); + finished = load_system_file(file_name) ; - - psppire_set_window_title(basename(file_name)); - - g_free (file_name); - - { - const int ni = dict_get_next_value_idx(the_dictionary->dict); - gint case_num; - if ( ni == 0 ) - goto done; - - - for(case_num=0;;case_num++) - { - if (!psppire_case_array_append_case(the_cases, - populate_case_from_reader, - reader)) - break; - } - } - - sfm_close_reader(reader); - finished = TRUE; + g_free(file_name); } else - { - finished = TRUE; - } + finished = TRUE; + } while ( ! finished ) ; - done: gtk_widget_destroy (dialog); } diff --git a/src/ui/gui/menu-actions.h b/src/ui/gui/menu-actions.h index 2e4e86ea..f4ed5c00 100644 --- a/src/ui/gui/menu-actions.h +++ b/src/ui/gui/menu-actions.h @@ -83,7 +83,11 @@ gboolean callbacks_on_init(gpointer data) ; /* Switch between the VAR SHEET and the DATA SHEET */ enum {PAGE_DATA_SHEET = 0, PAGE_VAR_SHEET}; +gboolean load_system_file(const gchar *file_name); + +void select_sheet(gint page); #endif -void select_sheet(gint page); + + diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c index 116092fd..5b40635b 100644 --- a/src/ui/gui/psppire-data-store.c +++ b/src/ui/gui/psppire-data-store.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -60,7 +61,6 @@ static gboolean psppire_data_store_clear_datum(GSheetModel *model, #define MIN_COLUMNS 10 -#define max(A,B) ((A>B)?A:B) static GObjectClass *parent_class = NULL; @@ -128,6 +128,24 @@ psppire_data_store_class_init (PsppireDataStoreClass *class) } + +static gint +psppire_data_store_get_var_count (const GSheetModel *model) +{ + const PsppireDataStore *store = PSPPIRE_DATA_STORE(model); + + return psppire_dict_get_var_cnt(store->dict); +} + +static gint +psppire_data_store_get_case_count (const GSheetModel *model) +{ + const PsppireDataStore *store = PSPPIRE_DATA_STORE(model); + + return psppire_case_array_get_n_cases(store->cases); +} + + static void psppire_data_store_init (PsppireDataStore *data_store) { @@ -158,6 +176,8 @@ psppire_data_store_sheet_model_init (GSheetModelIface *iface) iface->get_background = NULL; iface->get_font_desc = psppire_data_store_get_font_desc; iface->get_cell_border = NULL; + iface->get_column_count = psppire_data_store_get_var_count; + iface->get_row_count = psppire_data_store_get_case_count; } static @@ -167,7 +187,6 @@ gboolean always_true() } - static void delete_cases_callback(GtkWidget *w, gint first, gint n_cases, gpointer data) { @@ -215,7 +234,7 @@ changed_case_callback(GtkWidget *w, gint casenum, gpointer data) static void -delete_variables_callback(GtkWidget *w, gint var_num, gint n_vars, gpointer data) +delete_variables_callback(GObject *obj, gint var_num, gint n_vars, gpointer data) { PsppireDataStore *store ; @@ -225,11 +244,13 @@ delete_variables_callback(GtkWidget *w, gint var_num, gint n_vars, gpointer data g_sheet_column_columns_deleted(G_SHEET_COLUMN(store), var_num, n_vars); + + g_sheet_model_columns_deleted (G_SHEET_MODEL(store), var_num, n_vars); } static void -insert_variable_callback(GtkWidget *w, gint var_num, gpointer data) +insert_variable_callback(GObject *obj, gint var_num, gpointer data) { PsppireDataStore *store; @@ -247,6 +268,7 @@ insert_variable_callback(GtkWidget *w, gint var_num, gpointer data) psppire_case_array_resize(store->cases, dict_get_next_value_idx (store->dict->dict)); + g_sheet_model_columns_inserted (G_SHEET_MODEL(store), var_num, 1); } @@ -277,7 +299,6 @@ psppire_data_store_new (PsppireDict *dict, PsppireCaseArray *cases) g_signal_connect(cases, "case-changed", G_CALLBACK(changed_case_callback), retval); - psppire_data_store_set_dictionary(retval, dict); @@ -315,7 +336,6 @@ psppire_data_store_set_dictionary(PsppireDataStore *data_store, PsppireDict *dic G_CALLBACK(delete_variables_callback), data_store); - /* The entire model has changed */ g_sheet_model_range_changed (G_SHEET_MODEL(data_store), -1, -1, -1, -1); } @@ -450,6 +470,7 @@ psppire_data_store_set_string(GSheetModel *model, PsppireDataStore *store = PSPPIRE_DATA_STORE(model); const struct PsppireVariable *pv = psppire_dict_get_variable(store->dict, col); + g_return_val_if_fail(pv, FALSE); for(r = psppire_case_array_get_n_cases(store->cases) ; r <= row ; ++r ) { @@ -550,7 +571,7 @@ geometry_get_column_count(const GSheetColumn *geom) { PsppireDataStore *ds = PSPPIRE_DATA_STORE(geom); - return max(MIN_COLUMNS, psppire_dict_get_var_cnt(ds->dict)); + return MAX(MIN_COLUMNS, psppire_dict_get_var_cnt(ds->dict)); } /* Return the width that an 'M' character would occupy when typeset at diff --git a/src/ui/gui/psppire-dict.c b/src/ui/gui/psppire-dict.c index a8a8f636..0927f9c9 100644 --- a/src/ui/gui/psppire-dict.c +++ b/src/ui/gui/psppire-dict.c @@ -46,7 +46,6 @@ static GObjectClass *parent_class = NULL; enum {VARIABLE_CHANGED, VARIABLE_INSERTED, - VARIABLE_DELETED, VARIABLES_DELETED, n_SIGNALS}; @@ -119,17 +118,6 @@ psppire_dict_class_init (PsppireDictClass *class) 1, G_TYPE_INT); - signal[VARIABLE_DELETED] = - g_signal_new ("variable_deleted", - G_TYPE_FROM_CLASS(class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, - 1, - G_TYPE_INT); - signal[VARIABLES_DELETED] = g_signal_new ("variables_deleted", @@ -332,7 +320,9 @@ psppire_dict_get_variable(PsppireDict *d, gint idx) struct PsppireVariable *var ; g_return_val_if_fail(d, NULL); g_return_val_if_fail(d->dict, NULL); - g_return_val_if_fail(d->variables, NULL); + + if ( ! d->variables) + return NULL; if (idx < 0 || idx >= psppire_dict_get_var_cnt(d)) return NULL; diff --git a/src/ui/gui/psppire.c b/src/ui/gui/psppire.c index 9d01f9f7..e252acde 100644 --- a/src/ui/gui/psppire.c +++ b/src/ui/gui/psppire.c @@ -51,7 +51,8 @@ PsppireCaseArray *the_cases = 0; PsppireDataStore *data_store = 0; -static bool parse_command_line (int *argc, char ***argv); +static bool parse_command_line (int *argc, char ***argv, + gchar **filename, GError **err); int @@ -62,10 +63,16 @@ main(int argc, char *argv[]) GtkSheet *var_sheet ; GtkSheet *data_sheet ; + gchar *filename=0; + GError *err = 0; + gtk_init(&argc, &argv); - if ( ! parse_command_line(&argc, &argv) ) - return 0; + if ( ! parse_command_line(&argc, &argv, &filename, &err) ) + { + g_clear_error(&err); + return 1; + } glade_init(); @@ -101,9 +108,11 @@ main(int argc, char *argv[]) gtk_sheet_set_model(data_sheet, G_SHEET_MODEL(data_store)); - gtk_init_add(callbacks_on_init, 0); + if (filename) + gtk_init_add((GtkFunction)load_system_file, filename); + /* start the event loop */ gtk_main(); @@ -117,7 +126,7 @@ main(int argc, char *argv[]) main(). Returns true if normal execution should proceed, false if the command-line indicates that PSPP should exit. */ static bool -parse_command_line (int *argc, char ***argv) +parse_command_line (int *argc, char ***argv, gchar **filename, GError **err) { static struct option long_options[] = { @@ -137,7 +146,7 @@ parse_command_line (int *argc, char ***argv) switch (c) { case 'h': - g_print("Usage: psppire {|--help|--version}\n"); + g_printerr("Usage: psppire {|--help|--version}\n"); return false; case 'V': g_print(version); @@ -149,5 +158,10 @@ parse_command_line (int *argc, char ***argv) } } + if ( optind < *argc) + { + *filename = (*argv)[optind]; + } + return true; } -- 2.30.2