X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fdata-editor.c;h=28f15e01c4dddbec2244d4a37e8221098cf5585a;hb=3358031c44f487dde08fddf3ebf9200eb9087d7e;hp=30e587ef5cb2dbafabf2e12fd481bc9850c58fcc;hpb=28a74a7e6490448857ecfd5ead1c3ae3ddfea9d7;p=pspp-builds.git diff --git a/src/ui/gui/data-editor.c b/src/ui/gui/data-editor.c index 30e587ef..28f15e01 100644 --- a/src/ui/gui/data-editor.c +++ b/src/ui/gui/data-editor.c @@ -33,6 +33,7 @@ #include "transpose-dialog.h" #include "sort-cases-dialog.h" #include "compute-dialog.h" +#include "goto-case-dialog.h" #include "comments-dialog.h" #include "variable-info-dialog.h" #include "dict-display.h" @@ -50,6 +51,15 @@ #include "psppire-var-store.h" +static void create_data_sheet_variable_popup_menu (struct data_editor *); +static void create_data_sheet_cases_popup_menu (struct data_editor *); + +static void popup_variable_menu (GtkSheet *, gint, + GdkEventButton *, gpointer data); + +static void popup_cases_menu (GtkSheet *, gint, + GdkEventButton *, gpointer data); + /* Update the data_ref_entry with the reference of the active cell */ static gint update_data_ref_entry (const GtkSheet *sheet, gint row, gint col, gpointer data); @@ -57,6 +67,9 @@ static gint update_data_ref_entry (const GtkSheet *sheet, static void register_data_editor_actions (struct data_editor *de); static void insert_variable (GtkAction *, gpointer data); +static void insert_case (GtkAction *a, gpointer data); +static void delete_cases (GtkAction *a, gpointer data); +static void delete_variables (GtkAction *a, gpointer data); /* Switch between the VAR SHEET and the DATA SHEET */ @@ -95,30 +108,24 @@ static void value_labels_toggled (GtkToggleToolButton *, gpointer); static void file_quit (GtkCheckMenuItem *, gpointer ); -static void on_clear_activate (GtkMenuItem *, gpointer); - static void -enable_edit_clear (GtkWidget *w, gint row, gpointer data) +enable_delete_cases (GtkWidget *w, gint var, gpointer data) { struct data_editor *de = data; - GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear"); - - gtk_widget_set_sensitive (menuitem, TRUE); + gtk_action_set_visible (de->delete_cases, var != -1); } -static gboolean -disable_edit_clear (GtkWidget *w, gint x, gint y, gpointer data) + +static void +enable_delete_variables (GtkWidget *w, gint var, gpointer data) { struct data_editor *de = data; - GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear"); - - gtk_widget_set_sensitive (menuitem, FALSE); - - return FALSE; + gtk_action_set_visible (de->delete_variables, var != -1); } + static void open_data_file (const gchar *, struct data_editor *); @@ -129,7 +136,6 @@ static void on_recent_data_select (GtkMenuShell *menushell, gpointer user_data) { gchar *file; - struct data_editor *de = user_data; gchar *uri = @@ -238,6 +244,37 @@ new_data_editor (void) register_data_editor_actions (de); + + de->delete_cases = + gtk_action_new ("clear-cases", + _("Clear"), + _("Delete the cases at the selected position(s)"), + "pspp-clear-cases"); + + g_signal_connect (de->delete_cases, "activate", + G_CALLBACK (delete_cases), de); + + gtk_action_connect_proxy (de->delete_cases, + get_widget_assert (de->xml, "edit_clear-cases")); + + + gtk_action_set_visible (de->delete_cases, FALSE); + + de->delete_variables = + gtk_action_new ("clear-variables", + _("Clear"), + _("Delete the variables at the selected position(s)"), + "pspp-clear-variables"); + + g_signal_connect (de->delete_variables, "activate", + G_CALLBACK (delete_variables), de); + + gtk_action_connect_proxy (de->delete_variables, + get_widget_assert (de->xml, "edit_clear-variables") + ); + + gtk_action_set_visible (de->delete_variables, FALSE); + de->insert_variable = gtk_action_new ("insert-variable", _("Insert Variable"), @@ -256,6 +293,48 @@ new_data_editor (void) get_widget_assert (de->xml, "data_insert-variable") ); + + de->insert_case = + gtk_action_new ("insert-case", + _("Insert Case"), + _("Create a new case at the current position"), + "pspp-insert-case"); + + g_signal_connect (de->insert_case, "activate", + G_CALLBACK (insert_case), de); + + + gtk_action_connect_proxy (de->insert_case, + get_widget_assert (de->xml, "button-insert-case") + ); + + + gtk_action_connect_proxy (de->insert_case, + get_widget_assert (de->xml, "data_insert-case") + ); + + + + de->invoke_goto_dialog = + gtk_action_new ("goto-case-dialog", + _("Goto Case"), + _("Jump to a Case in the Data Sheet"), + "gtk-jump-to"); + + + gtk_action_connect_proxy (de->invoke_goto_dialog, + get_widget_assert (de->xml, "button-goto-case") + ); + + gtk_action_connect_proxy (de->invoke_goto_dialog, + get_widget_assert (de->xml, "data_goto-case") + ); + + + g_signal_connect (de->invoke_goto_dialog, "activate", + G_CALLBACK (goto_case_dialog), de); + + de->invoke_weight_cases_dialog = gtk_action_new ("weight-cases-dialog", _("Weights"), @@ -344,11 +423,16 @@ new_data_editor (void) GtkRecentManager *rm = gtk_recent_manager_get_default (); GtkWidget *recent_data = get_widget_assert (de->xml, "file_recent-data"); GtkWidget *recent_files = get_widget_assert (de->xml, "file_recent-files"); + GtkWidget *recent_separator = get_widget_assert (de->xml, "file_separator1"); GtkWidget *menu = gtk_recent_chooser_menu_new_for_manager (rm); GtkRecentFilter *filter = gtk_recent_filter_new (); + gtk_widget_show (recent_data); + gtk_widget_show (recent_files); + gtk_widget_show (recent_separator); + gtk_recent_filter_add_pattern (filter, "*.sav"); gtk_recent_filter_add_pattern (filter, "*.SAV"); @@ -397,14 +481,6 @@ new_data_editor (void) G_CALLBACK (gtk_action_activate), de->action_data_save_as); - - g_signal_connect (get_widget_assert (de->xml,"edit_clear"), - "activate", - G_CALLBACK (on_clear_activate), - de); - - - gtk_action_connect_proxy (de->invoke_weight_cases_dialog, get_widget_assert (de->xml, "data_weight-cases") ); @@ -444,26 +520,31 @@ new_data_editor (void) G_CALLBACK (reference_manual), e->window); - g_signal_connect (get_widget_assert (de->xml,"data_sheet"), + g_signal_connect (data_sheet, "double-click-column", G_CALLBACK (click2column), de); - g_signal_connect (get_widget_assert (de->xml, "variable_sheet"), - "double-click-row", - GTK_SIGNAL_FUNC (click2row), + g_signal_connect (data_sheet, + "select-column", + G_CALLBACK (enable_delete_variables), de); - g_signal_connect (get_widget_assert (de->xml, "variable_sheet"), + g_signal_connect (data_sheet, "select-row", - GTK_SIGNAL_FUNC (enable_edit_clear), + G_CALLBACK (enable_delete_cases), de); - g_signal_connect (get_widget_assert (de->xml, "variable_sheet"), - "activate", - GTK_SIGNAL_FUNC (disable_edit_clear), + + g_signal_connect (var_sheet, + "double-click-row", + GTK_SIGNAL_FUNC (click2row), de); + g_signal_connect_after (var_sheet, + "select-row", + G_CALLBACK (enable_delete_variables), + de); g_signal_connect (get_widget_assert (de->xml, "notebook"), "switch-page", @@ -537,6 +618,16 @@ new_data_editor (void) G_CALLBACK (minimise_all_windows), NULL); + create_data_sheet_variable_popup_menu (de); + create_data_sheet_cases_popup_menu (de); + + g_signal_connect (G_OBJECT (data_sheet), "button-event-column", + G_CALLBACK (popup_variable_menu), de); + + g_signal_connect (G_OBJECT (data_sheet), "button-event-row", + G_CALLBACK (popup_cases_menu), de); + + select_sheet (de, PAGE_DATA_SHEET); return de; @@ -606,9 +697,6 @@ new_data_window (GtkMenuItem *menuitem, gpointer parent) static void select_sheet (struct data_editor *de, guint page_num) { - GtkWidget *insert_variable = get_widget_assert (de->xml, "data_insert-variable"); - GtkWidget *insert_cases = get_widget_assert (de->xml, "insert-cases"); - GtkWidget *view_data = get_widget_assert (de->xml, "view_data"); GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables"); @@ -617,15 +705,15 @@ select_sheet (struct data_editor *de, guint page_num) case PAGE_VAR_SHEET: gtk_widget_hide (view_variables); gtk_widget_show (view_data); - gtk_widget_set_sensitive (insert_variable, TRUE); - gtk_widget_set_sensitive (insert_cases, FALSE); + gtk_action_set_sensitive (de->insert_variable, TRUE); + gtk_action_set_sensitive (de->insert_case, FALSE); + gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE); break; case PAGE_DATA_SHEET: gtk_widget_show (view_variables); gtk_widget_hide (view_data); -#if 0 - gtk_widget_set_sensitive (insert_cases, TRUE); -#endif + gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE); + gtk_action_set_sensitive (de->insert_case, TRUE); break; default: g_assert_not_reached (); @@ -796,45 +884,102 @@ file_quit (GtkCheckMenuItem *menuitem, gpointer data) gtk_main_quit (); } +static void +delete_cases (GtkAction *action, gpointer data) +{ + struct data_editor *de = data; + GtkSheet *data_sheet = + GTK_SHEET (get_widget_assert (de->xml, "data_sheet")); + GtkSheetRange range; + + PsppireDataStore *data_store = PSPPIRE_DATA_STORE + (gtk_sheet_get_model (data_sheet) ); + + + /* This shouldn't be able to happen, because the action + should be disabled */ + g_return_if_fail (gtk_sheet_get_state (data_sheet) + == GTK_SHEET_ROW_SELECTED ); + + gtk_sheet_get_selected_range (data_sheet, &range); + + gtk_sheet_unselect_range (data_sheet); + + psppire_data_store_delete_cases (data_store, range.row0, + 1 + range.rowi - range.row0); + +} -/* Callback for when the Clear item in the edit menu is activated */ static void -on_clear_activate (GtkMenuItem *menuitem, gpointer data) +delete_variables (GtkAction *a, gpointer data) { struct data_editor *de = data; + GtkSheetRange range; GtkNotebook *notebook = GTK_NOTEBOOK (get_widget_assert (de->xml, "notebook")); - switch ( gtk_notebook_get_current_page (notebook) ) + const gint page = gtk_notebook_get_current_page (notebook); + + GtkSheet *sheet = GTK_SHEET (get_widget_assert (de->xml, + (page == PAGE_VAR_SHEET) ? + "variable_sheet" : + "data_sheet")); + + + gtk_sheet_get_selected_range (sheet, &range); + + switch ( page ) { case PAGE_VAR_SHEET: { - GtkSheet *var_sheet = - GTK_SHEET (get_widget_assert (de->xml, "variable_sheet")); - - PsppireVarStore *vs = PSPPIRE_VAR_STORE - (gtk_sheet_get_model (var_sheet) ); - - /* This shouldn't be able to happen, because the menuitem - should be disabled */ - g_return_if_fail (var_sheet->state == GTK_SHEET_ROW_SELECTED ); + PsppireVarStore *vs = + PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet)); psppire_dict_delete_variables (vs->dict, - var_sheet->range.row0, + range.row0, 1 + - var_sheet->range.rowi - - var_sheet->range.row0 ); + range.rowi - + range.row0 ); } break; - case PAGE_DATA_SHEET: - break; - default: - g_assert_not_reached (); - } + case PAGE_DATA_SHEET: + { + PsppireDataStore *ds = + PSPPIRE_DATA_STORE (gtk_sheet_get_model (sheet)); + + psppire_dict_delete_variables (ds->dict, + range.col0, + 1 + + range.coli - + range.col0 ); + } + break; + }; + + gtk_sheet_unselect_range (sheet); } +static void +insert_case (GtkAction *action, gpointer data) +{ + gint current_row ; + struct data_editor *de = data; + + GtkSheet *data_sheet = + GTK_SHEET (get_widget_assert (de->xml, "data_sheet")); + + PsppireDataStore *ds = PSPPIRE_DATA_STORE + (gtk_sheet_get_model (data_sheet) ); + + + gtk_sheet_get_active_cell (data_sheet, ¤t_row, NULL); + + if (current_row < 0) current_row = 0; + + psppire_data_store_insert_new_case (ds, current_row); +} /* Insert a new variable before the current row in the variable sheet, or before the current column in the data sheet, whichever is selected */ @@ -896,7 +1041,8 @@ on_split_change (PsppireDict *dict, gpointer data) { gint i; GString *text; - const struct variable *const * split_vars = dict_get_split_vars (dict->dict); + const struct variable *const * split_vars = + dict_get_split_vars (dict->dict); text = g_string_new (_("Split by ")); @@ -1245,6 +1391,15 @@ open_data_dialog (GtkAction *action, struct data_editor *de) gtk_file_filter_add_pattern (filter, "*"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + if ( de->file_name) + { + gchar *dir_name = g_path_get_dirname (de->file_name); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + dir_name); + free (dir_name); + } + switch (gtk_dialog_run (GTK_DIALOG (dialog))) { case GTK_RESPONSE_ACCEPT: @@ -1336,3 +1491,196 @@ update_data_ref_entry (const GtkSheet *sheet, gint row, gint col, gpointer data) return FALSE; } + + + + + +static void +do_sort (PsppireDataStore *ds, int var, gboolean descend) +{ + GString *string = g_string_new ("SORT CASES BY "); + + const struct variable *v = + psppire_dict_get_variable (ds->dict, var); + + g_string_append_printf (string, "%s", var_get_name (v)); + + if ( descend ) + g_string_append (string, " (D)"); + + g_string_append (string, "."); + + execute_syntax (create_syntax_string_source (string->str)); + + g_string_free (string, TRUE); +} + + +static void +sort_up (GtkMenuItem *item, gpointer data) +{ + GtkSheet *sheet = data; + GtkSheetRange range; + gtk_sheet_get_selected_range (sheet, &range); + + do_sort (PSPPIRE_DATA_STORE (gtk_sheet_get_model(sheet)), + range.col0, FALSE); + +} + +static void +sort_down (GtkMenuItem *item, gpointer data) +{ + GtkSheet *sheet = data; + GtkSheetRange range; + gtk_sheet_get_selected_range (sheet, &range); + + do_sort (PSPPIRE_DATA_STORE (gtk_sheet_get_model(sheet)), + range.col0, TRUE); +} + + + + +static void +create_data_sheet_variable_popup_menu (struct data_editor *de) +{ + GtkSheet *sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet")); + GtkWidget *menu = gtk_menu_new (); + + GtkWidget *sort_ascending = + gtk_menu_item_new_with_label (_("Sort Ascending")); + + GtkWidget *sort_descending = + gtk_menu_item_new_with_label (_("Sort Descending")); + + + GtkWidget *insert_variable = + gtk_menu_item_new_with_label (_("Insert Variable")); + + GtkWidget *clear_variable = + gtk_menu_item_new_with_label (_("Clear")); + + + gtk_action_connect_proxy (de->insert_variable, + insert_variable ); + + + gtk_action_connect_proxy (de->delete_variables, + clear_variable ); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_separator_menu_item_new ()); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), clear_variable); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_separator_menu_item_new ()); + + + g_signal_connect (G_OBJECT (sort_ascending), "activate", + G_CALLBACK (sort_up), sheet); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_ascending); + + + g_signal_connect (G_OBJECT (sort_descending), "activate", + G_CALLBACK (sort_down), sheet); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_descending); + + gtk_widget_show_all (menu); + + + de->data_sheet_variable_popup_menu = GTK_MENU(menu); +} + + +static void +create_data_sheet_cases_popup_menu (struct data_editor *de) +{ + GtkWidget *menu = gtk_menu_new (); + + GtkWidget *insert_case = + gtk_menu_item_new_with_label (_("Insert Case")); + + GtkWidget *delete_case = + gtk_menu_item_new_with_label (_("Clear")); + + + gtk_action_connect_proxy (de->insert_case, + insert_case); + + + gtk_action_connect_proxy (de->delete_cases, + delete_case); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_case); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_separator_menu_item_new ()); + + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_case); + + + gtk_widget_show_all (menu); + + + de->data_sheet_cases_popup_menu = GTK_MENU (menu); +} + + +static void +popup_variable_menu (GtkSheet *sheet, gint column, + GdkEventButton *event, gpointer data) +{ + struct data_editor *de = data; + + PsppireDataStore *data_store = + PSPPIRE_DATA_STORE (gtk_sheet_get_model (sheet)); + + const struct variable *v = + psppire_dict_get_variable (data_store->dict, column); + + if ( v && event->button == 3) + { + + gtk_sheet_select_column (sheet, column); + + gtk_menu_popup (GTK_MENU (de->data_sheet_variable_popup_menu), + NULL, NULL, NULL, NULL, + event->button, event->time); + } +} + + +static void +popup_cases_menu (GtkSheet *sheet, gint row, + GdkEventButton *event, gpointer data) +{ + struct data_editor *de = data; + + PsppireDataStore *data_store = + PSPPIRE_DATA_STORE (gtk_sheet_get_model (sheet)); + + if ( row <= psppire_data_store_get_case_count (data_store) && + event->button == 3) + { + gtk_sheet_select_row (sheet, row); + + gtk_menu_popup (GTK_MENU (de->data_sheet_cases_popup_menu), + NULL, NULL, NULL, NULL, + event->button, event->time); + } +}