1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2006, 2007 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <glade/glade.h>
24 #include "window-manager.h"
25 #include <gtksheet/gtksheet.h>
29 #include "psppire-dialog.h"
30 #include "psppire-selector.h"
31 #include "weight-cases-dialog.h"
32 #include "split-file-dialog.h"
33 #include "transpose-dialog.h"
34 #include "sort-cases-dialog.h"
35 #include "compute-dialog.h"
36 #include "comments-dialog.h"
37 #include "variable-info-dialog.h"
38 #include "dict-display.h"
40 #define _(msgid) gettext (msgid)
41 #define N_(msgid) msgid
43 #include "data-editor.h"
44 #include "syntax-editor.h"
45 #include <language/syntax-string-source.h>
46 #include <libpspp/syntax-gen.h>
47 #include "window-manager.h"
49 #include "psppire-data-store.h"
50 #include "psppire-var-store.h"
53 /* Update the data_ref_entry with the reference of the active cell */
54 static gint update_data_ref_entry (const GtkSheet *sheet,
55 gint row, gint col, gpointer data);
57 static void register_data_editor_actions (struct data_editor *de);
59 static void insert_variable (GtkAction *, gpointer data);
62 /* Switch between the VAR SHEET and the DATA SHEET */
64 static gboolean click2column (GtkWidget *w, gint col, gpointer data);
66 static gboolean click2row (GtkWidget *w, gint row, gpointer data);
69 static void select_sheet (struct data_editor *de, guint page_num);
72 /* Callback for when the dictionary changes properties*/
73 static void on_weight_change (GObject *, gint, gpointer);
74 static void on_filter_change (GObject *, gint, gpointer);
75 static void on_split_change (PsppireDict *, gpointer);
77 static void data_var_select (GtkNotebook *notebook,
78 GtkNotebookPage *page,
82 static void status_bar_activate (GtkCheckMenuItem *, gpointer);
84 static void grid_lines_activate (GtkCheckMenuItem *, gpointer);
86 static void data_sheet_activate (GtkCheckMenuItem *, gpointer);
88 static void variable_sheet_activate (GtkCheckMenuItem *, gpointer );
90 static void fonts_activate (GtkMenuItem *, gpointer);
92 static void value_labels_activate (GtkCheckMenuItem *, gpointer);
93 static void value_labels_toggled (GtkToggleToolButton *, gpointer);
96 static void file_quit (GtkCheckMenuItem *, gpointer );
98 static void on_clear_activate (GtkMenuItem *, gpointer);
101 enable_edit_clear (GtkWidget *w, gint row, gpointer data)
103 struct data_editor *de = data;
105 GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
107 gtk_widget_set_sensitive (menuitem, TRUE);
111 disable_edit_clear (GtkWidget *w, gint x, gint y, gpointer data)
113 struct data_editor *de = data;
115 GtkWidget *menuitem = get_widget_assert (de->xml, "edit_clear");
117 gtk_widget_set_sensitive (menuitem, FALSE);
122 static void open_data_file (const gchar *, struct data_editor *);
126 #if RECENT_LISTS_AVAILABLE
129 on_recent_data_select (GtkMenuShell *menushell, gpointer user_data)
133 struct data_editor *de = user_data;
136 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
138 file = g_filename_from_uri (uri, NULL, NULL);
142 open_data_file (file, de);
148 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
152 struct syntax_editor *se ;
155 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
157 file = g_filename_from_uri (uri, NULL, NULL);
161 se = (struct syntax_editor *)
162 window_create (WINDOW_SYNTAX, file);
164 load_editor_from_file (se, file, NULL);
172 datum_entry_activate (GtkEntry *entry, gpointer data)
175 GtkSheet *data_sheet = GTK_SHEET (data);
176 PsppireDataStore *store = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
178 const char *text = gtk_entry_get_text (entry);
180 gtk_sheet_get_active_cell (data_sheet, &row, &column);
182 if ( row == -1 || column == -1)
185 psppire_data_store_set_string (store, text, row, column);
189 Create a new data editor.
192 new_data_editor (void)
194 struct data_editor *de ;
195 struct editor_window *e;
196 GtkSheet *var_sheet ;
197 GtkSheet *data_sheet ;
199 GtkWidget *datum_entry;
201 de = g_malloc0 (sizeof (*de));
203 e = (struct editor_window *) de;
205 de->xml = XML_NEW ("data-editor.glade");
207 var_sheet = GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
208 data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
210 vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
212 g_assert(vs); /* Traps a possible bug in win32 build */
214 g_signal_connect (G_OBJECT (data_sheet), "activate",
215 G_CALLBACK (update_data_ref_entry),
218 datum_entry = get_widget_assert (de->xml, "datum_entry");
220 g_signal_connect (G_OBJECT (datum_entry), "activate",
221 G_CALLBACK (datum_entry_activate),
224 g_signal_connect (vs->dict, "weight-changed",
225 G_CALLBACK (on_weight_change),
228 g_signal_connect (vs->dict, "filter-changed",
229 G_CALLBACK (on_filter_change),
232 g_signal_connect (vs->dict, "split-changed",
233 G_CALLBACK (on_split_change),
236 connect_help (de->xml);
239 register_data_editor_actions (de);
241 de->insert_variable =
242 gtk_action_new ("insert-variable",
243 _("Insert Variable"),
244 _("Create a new variable at the current position"),
245 "pspp-insert-variable");
247 g_signal_connect (de->insert_variable, "activate",
248 G_CALLBACK (insert_variable), de);
251 gtk_action_connect_proxy (de->insert_variable,
252 get_widget_assert (de->xml, "button-insert-variable")
255 gtk_action_connect_proxy (de->insert_variable,
256 get_widget_assert (de->xml, "data_insert-variable")
259 de->invoke_weight_cases_dialog =
260 gtk_action_new ("weight-cases-dialog",
262 _("Weight cases by variable"),
263 "pspp-weight-cases");
265 g_signal_connect (de->invoke_weight_cases_dialog, "activate",
266 G_CALLBACK (weight_cases_dialog), de);
269 de->invoke_transpose_dialog =
270 gtk_action_new ("transpose-dialog",
272 _("Transpose the cases with the variables"),
276 g_signal_connect (de->invoke_transpose_dialog, "activate",
277 G_CALLBACK (transpose_dialog), de);
281 de->invoke_split_file_dialog =
282 gtk_action_new ("split-file-dialog",
284 _("Split the active file"),
287 g_signal_connect (de->invoke_split_file_dialog, "activate",
288 G_CALLBACK (split_file_dialog), de);
292 de->invoke_sort_cases_dialog =
293 gtk_action_new ("sort-cases-dialog",
295 _("Sort cases in the active file"),
298 g_signal_connect (de->invoke_sort_cases_dialog, "activate",
299 G_CALLBACK (sort_cases_dialog), de);
302 de->invoke_compute_dialog =
303 gtk_action_new ("compute-dialog",
305 _("Compute new values for a variable"),
308 g_signal_connect (de->invoke_compute_dialog, "activate",
309 G_CALLBACK (compute_dialog), de);
311 de->invoke_comments_dialog =
312 gtk_action_new ("commments-dialog",
313 _("Data File Comments"),
314 _("Commentary text for the data file"),
317 g_signal_connect (de->invoke_comments_dialog, "activate",
318 G_CALLBACK (comments_dialog), de);
320 de->invoke_variable_info_dialog =
321 gtk_action_new ("variable-info-dialog",
323 _("Jump to Variable"),
324 "pspp-goto-variable");
326 g_signal_connect (de->invoke_variable_info_dialog, "activate",
327 G_CALLBACK (variable_info_dialog), de);
329 e->window = GTK_WINDOW (get_widget_assert (de->xml, "data_editor"));
331 g_signal_connect_swapped (get_widget_assert (de->xml,"file_new_data"),
333 G_CALLBACK (gtk_action_activate),
334 de->action_data_new);
336 g_signal_connect_swapped (get_widget_assert (de->xml,"file_open_data"),
338 G_CALLBACK (gtk_action_activate),
339 de->action_data_open);
342 #if RECENT_LISTS_AVAILABLE
344 GtkRecentManager *rm = gtk_recent_manager_get_default ();
345 GtkWidget *recent_data = get_widget_assert (de->xml, "file_recent-data");
346 GtkWidget *recent_files = get_widget_assert (de->xml, "file_recent-files");
348 GtkWidget *menu = gtk_recent_chooser_menu_new_for_manager (rm);
350 GtkRecentFilter *filter = gtk_recent_filter_new ();
352 gtk_recent_filter_add_pattern (filter, "*.sav");
353 gtk_recent_filter_add_pattern (filter, "*.SAV");
355 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
357 gtk_widget_set_sensitive (recent_data, TRUE);
358 g_signal_connect (menu, "selection-done",
359 G_CALLBACK (on_recent_data_select), de);
361 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu);
364 filter = gtk_recent_filter_new ();
365 menu = gtk_recent_chooser_menu_new_for_manager (rm);
367 gtk_recent_filter_add_pattern (filter, "*.sps");
368 gtk_recent_filter_add_pattern (filter, "*.SPS");
370 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
372 gtk_widget_set_sensitive (recent_files, TRUE);
373 g_signal_connect (menu, "selection-done",
374 G_CALLBACK (on_recent_files_select), de);
376 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu);
380 g_signal_connect (get_widget_assert (de->xml,"file_new_syntax"),
382 G_CALLBACK (new_syntax_window),
385 g_signal_connect (get_widget_assert (de->xml,"file_open_syntax"),
387 G_CALLBACK (open_syntax_window),
390 g_signal_connect_swapped (get_widget_assert (de->xml,"file_save"),
392 G_CALLBACK (gtk_action_activate),
393 de->action_data_save);
395 g_signal_connect_swapped (get_widget_assert (de->xml,"file_save_as"),
397 G_CALLBACK (gtk_action_activate),
398 de->action_data_save_as);
401 g_signal_connect (get_widget_assert (de->xml,"edit_clear"),
403 G_CALLBACK (on_clear_activate),
408 gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
409 get_widget_assert (de->xml, "data_weight-cases")
412 gtk_action_connect_proxy (de->invoke_transpose_dialog,
413 get_widget_assert (de->xml, "data_transpose")
416 gtk_action_connect_proxy (de->invoke_split_file_dialog,
417 get_widget_assert (de->xml, "data_split-file")
420 gtk_action_connect_proxy (de->invoke_sort_cases_dialog,
421 get_widget_assert (de->xml, "data_sort-cases")
424 gtk_action_connect_proxy (de->invoke_compute_dialog,
425 get_widget_assert (de->xml, "transform_compute")
428 gtk_action_connect_proxy (de->invoke_comments_dialog,
429 get_widget_assert (de->xml, "utilities_comments")
432 gtk_action_connect_proxy (de->invoke_variable_info_dialog,
433 get_widget_assert (de->xml, "utilities_variables")
436 g_signal_connect (get_widget_assert (de->xml,"help_about"),
438 G_CALLBACK (about_new),
442 g_signal_connect (get_widget_assert (de->xml,"help_reference"),
444 G_CALLBACK (reference_manual),
447 g_signal_connect (get_widget_assert (de->xml,"data_sheet"),
448 "double-click-column",
449 G_CALLBACK (click2column),
452 g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
454 GTK_SIGNAL_FUNC (click2row),
457 g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
459 GTK_SIGNAL_FUNC (enable_edit_clear),
462 g_signal_connect (get_widget_assert (de->xml, "variable_sheet"),
464 GTK_SIGNAL_FUNC (disable_edit_clear),
468 g_signal_connect (get_widget_assert (de->xml, "notebook"),
470 G_CALLBACK (data_var_select), de);
474 g_signal_connect (get_widget_assert (de->xml, "view_statusbar"),
476 G_CALLBACK (status_bar_activate), de);
479 g_signal_connect (get_widget_assert (de->xml, "view_gridlines"),
481 G_CALLBACK (grid_lines_activate), de);
485 g_signal_connect (get_widget_assert (de->xml, "view_data"),
487 G_CALLBACK (data_sheet_activate), de);
489 g_signal_connect (get_widget_assert (de->xml, "view_variables"),
491 G_CALLBACK (variable_sheet_activate), de);
495 g_signal_connect (get_widget_assert (de->xml, "view_fonts"),
497 G_CALLBACK (fonts_activate), de);
501 g_signal_connect (get_widget_assert (de->xml, "view_valuelabels"),
503 G_CALLBACK (value_labels_activate), de);
506 g_signal_connect (get_widget_assert (de->xml, "togglebutton-value-labels"),
508 G_CALLBACK (value_labels_toggled), de);
510 gtk_action_connect_proxy (de->action_data_open,
511 get_widget_assert (de->xml, "button-open")
514 gtk_action_connect_proxy (de->action_data_save,
515 get_widget_assert (de->xml, "button-save")
518 gtk_action_connect_proxy (de->invoke_variable_info_dialog,
519 get_widget_assert (de->xml, "button-goto-variable")
522 gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
523 get_widget_assert (de->xml, "button-weight-cases")
526 gtk_action_connect_proxy (de->invoke_split_file_dialog,
527 get_widget_assert (de->xml, "button-split-file")
530 g_signal_connect (get_widget_assert (de->xml, "file_quit"),
532 G_CALLBACK (file_quit), de);
535 g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
537 G_CALLBACK (minimise_all_windows), NULL);
540 select_sheet (de, PAGE_DATA_SHEET);
546 /* Callback which occurs when the var sheet's row title
547 button is double clicked */
549 click2row (GtkWidget *w, gint row, gpointer data)
551 struct data_editor *de = data;
552 GtkSheetRange visible_range;
554 gint current_row, current_column;
556 GtkWidget *data_sheet = get_widget_assert (de->xml, "data_sheet");
558 data_editor_select_sheet (de, PAGE_DATA_SHEET);
560 gtk_sheet_get_active_cell (GTK_SHEET (data_sheet),
561 ¤t_row, ¤t_column);
563 gtk_sheet_set_active_cell (GTK_SHEET (data_sheet), current_row, row);
565 gtk_sheet_get_visible_range (GTK_SHEET (data_sheet), &visible_range);
567 if ( row < visible_range.col0 || row > visible_range.coli)
569 gtk_sheet_moveto (GTK_SHEET (data_sheet),
570 current_row, row, 0, 0);
577 /* Callback which occurs when the data sheet's column title
580 click2column (GtkWidget *w, gint col, gpointer data)
582 struct data_editor *de = data;
584 gint current_row, current_column;
586 GtkWidget *var_sheet = get_widget_assert (de->xml, "variable_sheet");
588 data_editor_select_sheet (de, PAGE_VAR_SHEET);
590 gtk_sheet_get_active_cell (GTK_SHEET (var_sheet),
591 ¤t_row, ¤t_column);
593 gtk_sheet_set_active_cell (GTK_SHEET (var_sheet), col, current_column);
600 new_data_window (GtkMenuItem *menuitem, gpointer parent)
602 window_create (WINDOW_DATA, NULL);
607 select_sheet (struct data_editor *de, guint page_num)
609 GtkWidget *insert_variable = get_widget_assert (de->xml, "data_insert-variable");
610 GtkWidget *insert_cases = get_widget_assert (de->xml, "insert-cases");
612 GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
613 GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables");
618 gtk_widget_hide (view_variables);
619 gtk_widget_show (view_data);
620 gtk_widget_set_sensitive (insert_variable, TRUE);
621 gtk_widget_set_sensitive (insert_cases, FALSE);
623 case PAGE_DATA_SHEET:
624 gtk_widget_show (view_variables);
625 gtk_widget_hide (view_data);
627 gtk_widget_set_sensitive (insert_cases, TRUE);
631 g_assert_not_reached ();
638 data_var_select (GtkNotebook *notebook,
639 GtkNotebookPage *page,
643 struct data_editor *de = user_data;
645 select_sheet (de, page_num);
652 data_editor_select_sheet (struct data_editor *de, gint page)
654 gtk_notebook_set_current_page
656 GTK_NOTEBOOK (get_widget_assert (de->xml,"notebook")), page
662 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
664 struct data_editor *de = data;
665 GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
667 if ( gtk_check_menu_item_get_active (menuitem) )
668 gtk_widget_show (statusbar);
670 gtk_widget_hide (statusbar);
675 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
677 struct data_editor *de = data;
678 const bool grid_visible = gtk_check_menu_item_get_active (menuitem);
680 gtk_sheet_show_grid (GTK_SHEET (get_widget_assert (de->xml,
684 gtk_sheet_show_grid (GTK_SHEET (get_widget_assert (de->xml, "data_sheet")),
691 data_sheet_activate (GtkCheckMenuItem *menuitem, gpointer data)
693 struct data_editor *de = data;
695 data_editor_select_sheet (de, PAGE_DATA_SHEET);
700 variable_sheet_activate (GtkCheckMenuItem *menuitem, gpointer data)
702 struct data_editor *de = data;
704 data_editor_select_sheet (de, PAGE_VAR_SHEET);
709 fonts_activate (GtkMenuItem *menuitem, gpointer data)
711 struct data_editor *de = data;
713 gtk_font_selection_dialog_new (_("Font Selection"));
715 gtk_window_set_transient_for (GTK_WINDOW (dialog),
716 GTK_WINDOW (get_widget_assert (de->xml,
718 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
720 GtkSheet *data_sheet =
721 GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
723 GtkSheet *var_sheet =
724 GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
726 PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
727 PsppireVarStore *vs = PSPPIRE_VAR_STORE (gtk_sheet_get_model (var_sheet));
729 const gchar *font = gtk_font_selection_dialog_get_font_name
730 (GTK_FONT_SELECTION_DIALOG (dialog));
732 PangoFontDescription* font_desc =
733 pango_font_description_from_string (font);
735 psppire_var_store_set_font (vs, font_desc);
736 psppire_data_store_set_font (ds, font_desc);
739 gtk_widget_hide (dialog);
743 /* The next two callbacks are mutually co-operative */
745 /* Callback for the value labels menu item */
747 value_labels_activate (GtkCheckMenuItem *menuitem, gpointer data)
749 struct data_editor *de = data;
751 GtkSheet *data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
753 GtkToggleToolButton *tb =
754 GTK_TOGGLE_TOOL_BUTTON (get_widget_assert (de->xml,
755 "togglebutton-value-labels"));
757 PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
759 gboolean show_value_labels = gtk_check_menu_item_get_active (menuitem);
761 gtk_toggle_tool_button_set_active (tb, show_value_labels);
763 psppire_data_store_show_labels (ds, show_value_labels);
767 /* Callback for the value labels tooglebutton */
769 value_labels_toggled (GtkToggleToolButton *toggle_tool_button,
772 struct data_editor *de = data;
774 GtkSheet *data_sheet = GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
776 GtkCheckMenuItem *item =
777 GTK_CHECK_MENU_ITEM (get_widget_assert (de->xml, "view_valuelabels"));
779 PsppireDataStore *ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (data_sheet));
781 gboolean show_value_labels =
782 gtk_toggle_tool_button_get_active (toggle_tool_button);
784 gtk_check_menu_item_set_active (item, show_value_labels);
786 psppire_data_store_show_labels (ds, show_value_labels);
791 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
793 /* FIXME: Need to be more intelligent here.
794 Give the user the opportunity to save any unsaved data.
801 /* Callback for when the Clear item in the edit menu is activated */
803 on_clear_activate (GtkMenuItem *menuitem, gpointer data)
805 struct data_editor *de = data;
807 GtkNotebook *notebook = GTK_NOTEBOOK (get_widget_assert (de->xml,
810 switch ( gtk_notebook_get_current_page (notebook) )
814 GtkSheet *var_sheet =
815 GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
817 PsppireVarStore *vs = PSPPIRE_VAR_STORE
818 (gtk_sheet_get_model (var_sheet) );
820 /* This shouldn't be able to happen, because the menuitem
821 should be disabled */
822 g_return_if_fail (var_sheet->state == GTK_SHEET_ROW_SELECTED );
824 psppire_dict_delete_variables (vs->dict,
825 var_sheet->range.row0,
827 var_sheet->range.rowi -
828 var_sheet->range.row0 );
831 case PAGE_DATA_SHEET:
834 g_assert_not_reached ();
839 /* Insert a new variable before the current row in the variable sheet,
840 or before the current column in the data sheet, whichever is selected */
842 insert_variable (GtkAction *action, gpointer data)
844 struct data_editor *de = data;
847 GtkWidget *notebook = get_widget_assert (de->xml, "notebook");
849 GtkSheet *var_sheet =
850 GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
852 PsppireVarStore *vs = PSPPIRE_VAR_STORE
853 (gtk_sheet_get_model (var_sheet) );
855 switch ( gtk_notebook_get_current_page ( GTK_NOTEBOOK (notebook)) )
858 posn = var_sheet->active_cell.row;
860 case PAGE_DATA_SHEET:
862 GtkSheet *data_sheet =
863 GTK_SHEET (get_widget_assert (de->xml, "data_sheet"));
865 if ( data_sheet->state == GTK_SHEET_COLUMN_SELECTED )
866 posn = data_sheet->range.col0;
868 posn = data_sheet->active_cell.col;
872 g_assert_not_reached ();
875 if ( posn == -1 ) posn = 0;
877 psppire_dict_insert_variable (vs->dict, posn, NULL);
880 /* Callback for when the dictionary changes its split variables */
882 on_split_change (PsppireDict *dict, gpointer data)
884 struct data_editor *de = data;
886 size_t n_split_vars = dict_get_split_cnt (dict->dict);
888 GtkWidget *split_status_area =
889 get_widget_assert (de->xml, "split-file-status-area");
891 if ( n_split_vars == 0 )
893 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
899 const struct variable *const * split_vars = dict_get_split_vars (dict->dict);
901 text = g_string_new (_("Split by "));
903 for (i = 0 ; i < n_split_vars - 1; ++i )
905 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
907 g_string_append (text, var_get_name (split_vars[i]));
909 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
911 g_string_free (text, TRUE);
916 /* Callback for when the dictionary changes its filter variable */
918 on_filter_change (GObject *o, gint filter_index, gpointer data)
920 struct data_editor *de = data;
921 GtkWidget *filter_status_area =
922 get_widget_assert (de->xml, "filter-use-status-area");
924 if ( filter_index == -1 )
926 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
930 GtkSheet *var_sheet =
931 GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
933 PsppireVarStore *vs = PSPPIRE_VAR_STORE
934 (gtk_sheet_get_model (var_sheet) );
936 struct variable *var = psppire_dict_get_variable (vs->dict,
939 gchar *text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
941 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
947 /* Callback for when the dictionary changes its weights */
949 on_weight_change (GObject *o, gint weight_index, gpointer data)
951 struct data_editor *de = data;
952 GtkWidget *weight_status_area =
953 get_widget_assert (de->xml, "weight-status-area");
955 if ( weight_index == -1 )
957 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
961 GtkSheet *var_sheet =
962 GTK_SHEET (get_widget_assert (de->xml, "variable_sheet"));
964 PsppireVarStore *vs = PSPPIRE_VAR_STORE
965 (gtk_sheet_get_model (var_sheet) );
967 struct variable *var = psppire_dict_get_variable (vs->dict,
970 gchar *text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
972 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
981 static void data_save_as_dialog (GtkAction *, struct data_editor *de);
982 static void new_file (GtkAction *, struct editor_window *de);
983 static void open_data_dialog (GtkAction *, struct data_editor *de);
984 static void data_save (GtkAction *action, struct data_editor *e);
987 /* Create the GtkActions and connect to their signals */
989 register_data_editor_actions (struct data_editor *de)
991 de->action_data_open =
992 gtk_action_new ("data-open-dialog",
994 _("Open a data file"),
997 g_signal_connect (de->action_data_open, "activate",
998 G_CALLBACK (open_data_dialog), de);
1001 de->action_data_save = gtk_action_new ("data-save",
1003 _("Save data to file"),
1006 g_signal_connect (de->action_data_save, "activate",
1007 G_CALLBACK (data_save), de);
1011 de->action_data_save_as = gtk_action_new ("data-save-as-dialog",
1013 _("Save data to file"),
1016 g_signal_connect (de->action_data_save_as, "activate",
1017 G_CALLBACK (data_save_as_dialog), de);
1019 de->action_data_new =
1020 gtk_action_new ("data-new",
1025 g_signal_connect (de->action_data_new, "activate",
1026 G_CALLBACK (new_file), de);
1029 /* Returns true if NAME has a suffix which might denote a PSPP file */
1031 name_has_suffix (const gchar *name)
1033 if ( g_str_has_suffix (name, ".sav"))
1035 if ( g_str_has_suffix (name, ".SAV"))
1037 if ( g_str_has_suffix (name, ".por"))
1039 if ( g_str_has_suffix (name, ".POR"))
1045 /* Append SUFFIX to the filename of DE */
1047 append_filename_suffix (struct data_editor *de, const gchar *suffix)
1049 if ( ! name_has_suffix (de->file_name))
1051 gchar *s = de->file_name;
1052 de->file_name = g_strconcat (de->file_name, suffix, NULL);
1057 /* Save DE to file */
1059 save_file (struct data_editor *de)
1061 struct getl_interface *sss;
1062 struct string file_name ;
1064 g_assert (de->file_name);
1066 ds_init_cstr (&file_name, de->file_name);
1067 gen_quoted_string (&file_name);
1069 if ( de->save_as_portable )
1071 append_filename_suffix (de, ".por");
1072 sss = create_syntax_string_source ("EXPORT OUTFILE=%s.",
1073 ds_cstr (&file_name));
1077 append_filename_suffix (de, ".sav");
1078 sss = create_syntax_string_source ("SAVE OUTFILE=%s.",
1079 ds_cstr (&file_name));
1082 ds_destroy (&file_name);
1084 execute_syntax (sss);
1088 /* Callback for data_save action.
1089 If there's an existing file name, then just save,
1090 otherwise prompt for a file name, then save */
1092 data_save (GtkAction *action, struct data_editor *de)
1097 data_save_as_dialog (action, de);
1101 /* Callback for data_save_as action. Prompt for a filename and save */
1103 data_save_as_dialog (GtkAction *action, struct data_editor *de)
1105 struct editor_window *e = (struct editor_window *) de;
1107 GtkWidget *button_sys;
1109 gtk_file_chooser_dialog_new (_("Save"),
1110 GTK_WINDOW (e->window),
1111 GTK_FILE_CHOOSER_ACTION_SAVE,
1112 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1113 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1116 GtkFileFilter *filter = gtk_file_filter_new ();
1117 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
1118 gtk_file_filter_add_pattern (filter, "*.sav");
1119 gtk_file_filter_add_pattern (filter, "*.SAV");
1120 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1122 filter = gtk_file_filter_new ();
1123 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
1124 gtk_file_filter_add_pattern (filter, "*.por");
1125 gtk_file_filter_add_pattern (filter, "*.POR");
1126 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1128 filter = gtk_file_filter_new ();
1129 gtk_file_filter_set_name (filter, _("All Files"));
1130 gtk_file_filter_add_pattern (filter, "*");
1131 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1134 GtkWidget *button_por;
1135 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
1137 gtk_radio_button_new_with_label (NULL, _("System File"));
1140 gtk_radio_button_new_with_label
1141 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
1142 _("Portable File"));
1144 gtk_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
1145 gtk_box_pack_start_defaults (GTK_BOX (vbox), button_por);
1147 gtk_widget_show_all (vbox);
1149 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
1152 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
1154 case GTK_RESPONSE_ACCEPT:
1156 g_free (de->file_name);
1159 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1161 de->save_as_portable =
1162 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
1166 window_set_name_from_filename (e, de->file_name);
1173 gtk_widget_destroy (dialog);
1177 /* Callback for data_new action.
1178 Performs the NEW FILE command */
1180 new_file (GtkAction *action, struct editor_window *e)
1182 struct data_editor *de = (struct data_editor *) e;
1184 struct getl_interface *sss =
1185 create_syntax_string_source ("NEW FILE.");
1187 execute_syntax (sss);
1189 g_free (de->file_name);
1190 de->file_name = NULL;
1192 default_window_name (e);
1197 open_data_file (const gchar *file_name, struct data_editor *de)
1199 struct getl_interface *sss;
1200 struct string filename;
1202 ds_init_cstr (&filename, file_name);
1204 gen_quoted_string (&filename);
1206 sss = create_syntax_string_source ("GET FILE=%s.",
1207 ds_cstr (&filename));
1209 execute_syntax (sss);
1210 ds_destroy (&filename);
1212 window_set_name_from_filename ((struct editor_window *) de, file_name);
1216 /* Callback for the data_open action.
1217 Prompts for a filename and opens it */
1219 open_data_dialog (GtkAction *action, struct data_editor *de)
1221 struct editor_window *e = (struct editor_window *) de;
1224 gtk_file_chooser_dialog_new (_("Open"),
1225 GTK_WINDOW (e->window),
1226 GTK_FILE_CHOOSER_ACTION_OPEN,
1227 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1228 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1231 GtkFileFilter *filter = gtk_file_filter_new ();
1232 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
1233 gtk_file_filter_add_pattern (filter, "*.sav");
1234 gtk_file_filter_add_pattern (filter, "*.SAV");
1235 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1237 filter = gtk_file_filter_new ();
1238 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
1239 gtk_file_filter_add_pattern (filter, "*.por");
1240 gtk_file_filter_add_pattern (filter, "*.POR");
1241 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1243 filter = gtk_file_filter_new ();
1244 gtk_file_filter_set_name (filter, _("All Files"));
1245 gtk_file_filter_add_pattern (filter, "*");
1246 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1248 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
1250 case GTK_RESPONSE_ACCEPT:
1252 g_free (de->file_name);
1254 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1256 open_data_file (de->file_name, de);
1258 #if RECENT_LISTS_AVAILABLE
1260 GtkRecentManager *manager = gtk_recent_manager_get_default();
1261 gchar *uri = g_filename_to_uri (de->file_name, NULL, NULL);
1263 if ( ! gtk_recent_manager_add_item (manager, uri))
1264 g_warning ("Could not add item %s to recent list\n",uri);
1276 gtk_widget_destroy (dialog);
1281 /* Update the data_ref_entry with the reference of the active cell */
1283 update_data_ref_entry (const GtkSheet *sheet, gint row, gint col, gpointer data)
1285 GladeXML *data_editor_xml = data;
1287 PsppireDataStore *data_store =
1288 PSPPIRE_DATA_STORE (gtk_sheet_get_model (sheet));
1290 g_return_val_if_fail (data_editor_xml, FALSE);
1294 const struct variable *var =
1295 psppire_dict_get_variable (data_store->dict, col);
1297 /* The entry where the reference to the current cell is displayed */
1298 GtkEntry *cell_ref_entry =
1299 GTK_ENTRY (get_widget_assert (data_editor_xml,
1301 GtkEntry *datum_entry =
1302 GTK_ENTRY (get_widget_assert (data_editor_xml,
1307 gchar *text = g_strdup_printf ("%d: %s", row + FIRST_CASE_NUMBER,
1308 var_get_name (var));
1310 gchar *s = pspp_locale_to_utf8 (text, -1, 0);
1314 gtk_entry_set_text (cell_ref_entry, s);
1319 gtk_entry_set_text (cell_ref_entry, "");
1325 psppire_data_store_get_string (data_store, row,
1326 var_get_dict_index(var));
1329 gtk_entry_set_text (datum_entry, text);
1334 gtk_entry_set_text (datum_entry, "");