1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008 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/>. */
19 #include <gtk/gtksignal.h>
20 #include <gtk/gtkbox.h>
21 #include <glade/glade.h>
24 #include "text-data-import-dialog.h"
27 #include <ui/syntax-gen.h>
28 #include <language/syntax-string-source.h>
29 #include <libpspp/message.h>
32 #include <data/procedure.h>
34 #include "psppire-data-window.h"
35 #include "psppire-syntax-window.h"
39 #include "goto-case-dialog.h"
40 #include "weight-cases-dialog.h"
41 #include "split-file-dialog.h"
42 #include "transpose-dialog.h"
43 #include "sort-cases-dialog.h"
44 #include "select-cases-dialog.h"
45 #include "compute-dialog.h"
46 #include "find-dialog.h"
47 #include "rank-dialog.h"
48 #include "recode-dialog.h"
49 #include "comments-dialog.h"
50 #include "variable-info-dialog.h"
51 #include "descriptives-dialog.h"
52 #include "crosstabs-dialog.h"
53 #include "frequencies-dialog.h"
54 #include "examine-dialog.h"
55 #include "dict-display.h"
56 #include "regression-dialog.h"
57 #include "oneway-anova-dialog.h"
58 #include "t-test-independent-samples-dialog.h"
59 #include "t-test-one-sample.h"
60 #include "t-test-paired-samples.h"
64 #define _(msgid) gettext (msgid)
65 #define N_(msgid) msgid
69 static void psppire_data_window_base_finalize (PsppireDataWindowClass *, gpointer);
70 static void psppire_data_window_base_init (PsppireDataWindowClass *class);
71 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
72 static void psppire_data_window_init (PsppireDataWindow *data_editor);
76 psppire_data_window_get_type (void)
78 static GType psppire_data_window_type = 0;
80 if (!psppire_data_window_type)
82 static const GTypeInfo psppire_data_window_info =
84 sizeof (PsppireDataWindowClass),
85 (GBaseInitFunc) psppire_data_window_base_init,
86 (GBaseFinalizeFunc) psppire_data_window_base_finalize,
87 (GClassInitFunc)psppire_data_window_class_init,
88 (GClassFinalizeFunc) NULL,
90 sizeof (PsppireDataWindow),
92 (GInstanceInitFunc) psppire_data_window_init,
95 psppire_data_window_type =
96 g_type_register_static (PSPPIRE_WINDOW_TYPE, "PsppireDataWindow",
97 &psppire_data_window_info, 0);
100 return psppire_data_window_type;
103 static GObjectClass *parent_class ;
106 psppire_data_window_finalize (GObject *object)
108 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (object);
110 g_object_unref (de->builder);
112 if (G_OBJECT_CLASS (parent_class)->finalize)
113 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
118 psppire_data_window_class_init (PsppireDataWindowClass *class)
120 parent_class = g_type_class_peek_parent (class);
125 psppire_data_window_base_init (PsppireDataWindowClass *class)
127 GObjectClass *object_class = G_OBJECT_CLASS (class);
129 object_class->finalize = psppire_data_window_finalize;
135 psppire_data_window_base_finalize (PsppireDataWindowClass *class,
144 extern PsppireVarStore *the_var_store;
145 extern struct dataset *the_dataset;
146 extern PsppireDataStore *the_data_store ;
150 update_paste_menuitems (GtkWidget *w, gboolean x, gpointer data)
152 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
154 GtkWidget *edit_paste = get_widget_assert (de->xml, "edit_paste");
156 gtk_widget_set_sensitive (edit_paste, x);
160 update_cut_copy_menuitems (GtkWidget *w, gboolean x, gpointer data)
162 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
164 GtkWidget *edit_copy = get_widget_assert (de->xml, "edit_copy");
165 GtkWidget *edit_cut = get_widget_assert (de->xml, "edit_cut");
167 gtk_widget_set_sensitive (edit_copy, x);
168 gtk_widget_set_sensitive (edit_cut, x);
171 /* Run the EXECUTE command. */
173 execute (GtkMenuItem *mi, gpointer data)
175 struct getl_interface *sss = create_syntax_string_source ("EXECUTE.");
177 execute_syntax (sss);
181 transformation_change_callback (bool transformations_pending,
184 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
187 GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1"));
189 GtkWidget *menuitem =
190 gtk_ui_manager_get_widget (uim,"/ui/menubar/transform/transform_run-pending");
192 GtkWidget *status_label =
193 get_widget_assert (de->builder, "case-counter-area");
195 gtk_widget_set_sensitive (menuitem, transformations_pending);
198 if ( transformations_pending)
199 gtk_label_set_text (GTK_LABEL (status_label),
200 _("Transformations Pending"));
202 gtk_label_set_text (GTK_LABEL (status_label), "");
205 /* Callback for when the dictionary changes its filter variable */
207 on_filter_change (GObject *o, gint filter_index, gpointer data)
209 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
211 GtkWidget *filter_status_area =
212 get_widget_assert (de->builder, "filter-use-status-area");
214 if ( filter_index == -1 )
216 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
220 PsppireVarStore *vs = NULL;
221 struct variable *var ;
224 g_object_get (de->data_editor, "var-store", &vs, NULL);
226 var = psppire_dict_get_variable (vs->dict, filter_index);
228 text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
230 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
236 /* Callback for when the dictionary changes its split variables */
238 on_split_change (PsppireDict *dict, gpointer data)
240 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
242 size_t n_split_vars = dict_get_split_cnt (dict->dict);
244 GtkWidget *split_status_area =
245 get_widget_assert (de->builder, "split-file-status-area");
247 if ( n_split_vars == 0 )
249 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
255 const struct variable *const * split_vars =
256 dict_get_split_vars (dict->dict);
258 text = g_string_new (_("Split by "));
260 for (i = 0 ; i < n_split_vars - 1; ++i )
262 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
264 g_string_append (text, var_get_name (split_vars[i]));
266 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
268 g_string_free (text, TRUE);
275 /* Callback for when the dictionary changes its weights */
277 on_weight_change (GObject *o, gint weight_index, gpointer data)
279 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
281 GtkWidget *weight_status_area =
282 get_widget_assert (de->builder, "weight-status-area");
284 if ( weight_index == -1 )
286 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
290 struct variable *var ;
291 PsppireVarStore *vs = NULL;
294 g_object_get (de->data_editor, "var-store", &vs, NULL);
296 var = psppire_dict_get_variable (vs->dict, weight_index);
298 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
300 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
306 /* Puts FILE_NAME into the recent list.
307 If it's already in the list, it moves it to the top
310 add_most_recent (const char *file_name)
312 #if RECENT_LISTS_AVAILABLE
314 GtkRecentManager *manager = gtk_recent_manager_get_default();
315 gchar *uri = g_filename_to_uri (file_name, NULL, NULL);
317 gtk_recent_manager_remove_item (manager, uri, NULL);
319 if ( ! gtk_recent_manager_add_item (manager, uri))
320 g_warning ("Could not add item %s to recent list\n",uri);
327 psppire_data_window_load_file (PsppireDataWindow *de,
328 const gchar *file_name)
330 struct getl_interface *sss;
331 struct string filename;
333 ds_init_empty (&filename);
334 syntax_gen_string (&filename, ss_cstr (file_name));
336 sss = create_syntax_string_source ("GET FILE=%s.",
337 ds_cstr (&filename));
338 ds_destroy (&filename);
340 if (execute_syntax (sss) )
342 psppire_window_set_filename (PSPPIRE_WINDOW (de), file_name);
343 add_most_recent (file_name);
346 psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
347 free (de->file_name);
349 de->file_name = g_strdup (file_name);
353 /* Callback for the data_open action.
354 Prompts for a filename and opens it */
356 open_data_dialog (GtkAction *action, PsppireDataWindow *de)
359 gtk_file_chooser_dialog_new (_("Open"),
361 GTK_FILE_CHOOSER_ACTION_OPEN,
362 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
363 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
366 GtkFileFilter *filter = gtk_file_filter_new ();
367 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
368 gtk_file_filter_add_pattern (filter, "*.sav");
369 gtk_file_filter_add_pattern (filter, "*.SAV");
370 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
372 filter = gtk_file_filter_new ();
373 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
374 gtk_file_filter_add_pattern (filter, "*.por");
375 gtk_file_filter_add_pattern (filter, "*.POR");
376 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
378 filter = gtk_file_filter_new ();
379 gtk_file_filter_set_name (filter, _("All Files"));
380 gtk_file_filter_add_pattern (filter, "*");
381 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
386 gchar *dir_name = g_path_get_dirname (de->file_name);
387 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
392 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
394 case GTK_RESPONSE_ACCEPT:
397 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
399 psppire_data_window_load_file (de, name);
408 gtk_widget_destroy (dialog);
411 /* Returns true if NAME has a suffix which might denote a PSPP file */
413 name_has_suffix (const gchar *name)
415 if ( g_str_has_suffix (name, ".sav"))
417 if ( g_str_has_suffix (name, ".SAV"))
419 if ( g_str_has_suffix (name, ".por"))
421 if ( g_str_has_suffix (name, ".POR"))
428 /* Append SUFFIX to the filename of DE */
430 append_filename_suffix (PsppireDataWindow *de, const gchar *suffix)
432 if ( ! name_has_suffix (de->file_name))
434 gchar *s = de->file_name;
435 de->file_name = g_strconcat (de->file_name, suffix, NULL);
440 /* Save DE to file */
442 save_file (PsppireDataWindow *de)
444 struct getl_interface *sss;
445 struct string file_name ;
447 g_assert (de->file_name);
449 ds_init_empty (&file_name);
450 syntax_gen_string (&file_name, ss_cstr (de->file_name));
452 if ( de->save_as_portable )
454 append_filename_suffix (de, ".por");
455 sss = create_syntax_string_source ("EXPORT OUTFILE=%s.",
456 ds_cstr (&file_name));
460 append_filename_suffix (de, ".sav");
461 sss = create_syntax_string_source ("SAVE OUTFILE=%s.",
462 ds_cstr (&file_name));
465 ds_destroy (&file_name);
467 execute_syntax (sss);
469 psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
474 insert_case (GtkAction *action, gpointer data)
476 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (data);
478 psppire_data_editor_insert_case (dw->data_editor);
482 on_insert_variable (GtkAction *action, gpointer data)
484 PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
485 psppire_data_editor_insert_variable (de);
489 /* Callback for data_save_as action. Prompt for a filename and save */
491 data_save_as_dialog (GtkAction *action, PsppireDataWindow *de)
493 GtkWidget *button_sys;
495 gtk_file_chooser_dialog_new (_("Save"),
497 GTK_FILE_CHOOSER_ACTION_SAVE,
498 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
499 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
502 GtkFileFilter *filter = gtk_file_filter_new ();
503 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
504 gtk_file_filter_add_pattern (filter, "*.sav");
505 gtk_file_filter_add_pattern (filter, "*.SAV");
506 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
508 filter = gtk_file_filter_new ();
509 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
510 gtk_file_filter_add_pattern (filter, "*.por");
511 gtk_file_filter_add_pattern (filter, "*.POR");
512 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
514 filter = gtk_file_filter_new ();
515 gtk_file_filter_set_name (filter, _("All Files"));
516 gtk_file_filter_add_pattern (filter, "*");
517 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
520 GtkWidget *button_por;
521 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
523 gtk_radio_button_new_with_label (NULL, _("System File"));
526 gtk_radio_button_new_with_label
527 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
530 gtk_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
531 gtk_box_pack_start_defaults (GTK_BOX (vbox), button_por);
533 gtk_widget_show_all (vbox);
535 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
538 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
540 case GTK_RESPONSE_ACCEPT:
542 g_free (de->file_name);
545 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
547 de->save_as_portable =
548 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
550 if ( de->save_as_portable)
551 append_filename_suffix (de, ".por");
553 append_filename_suffix (de, ".sav");
557 psppire_window_set_filename (PSPPIRE_WINDOW (de), de->file_name);
564 gtk_widget_destroy (dialog);
568 /* Callback for data_save action.
569 If there's an existing file name, then just save,
570 otherwise prompt for a file name, then save */
572 data_save (GtkAction *action, PsppireDataWindow *de)
577 data_save_as_dialog (action, de);
581 /* Callback for data_new action.
582 Performs the NEW FILE command */
584 new_file (GtkAction *action, PsppireDataWindow *de)
586 struct getl_interface *sss =
587 create_syntax_string_source ("NEW FILE.");
589 execute_syntax (sss);
591 g_free (de->file_name);
592 de->file_name = NULL;
594 psppire_window_set_filename (PSPPIRE_WINDOW (de), NULL);
601 on_edit_paste (GtkAction *a, gpointer data)
603 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
605 psppire_data_editor_clip_paste (de->data_editor);
609 on_edit_copy (GtkMenuItem *m, gpointer data)
611 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
613 psppire_data_editor_clip_copy (de->data_editor);
619 on_edit_cut (GtkMenuItem *m, gpointer data)
621 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
623 psppire_data_editor_clip_cut (de->data_editor);
628 status_bar_activate (GtkToggleAction *action, gpointer data)
630 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
631 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
633 if ( gtk_toggle_action_get_active (action) )
634 gtk_widget_show (statusbar);
636 gtk_widget_hide (statusbar);
641 grid_lines_activate (GtkToggleAction *action, gpointer data)
643 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
644 const gboolean grid_visible = gtk_toggle_action_get_active (action);
646 psppire_data_editor_show_grid (de->data_editor, grid_visible);
650 data_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
652 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
654 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
659 variable_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
661 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
663 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
668 fonts_activate (GtkMenuItem *menuitem, gpointer data)
670 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
671 PangoFontDescription *current_font;
674 gtk_font_selection_dialog_new (_("Font Selection"));
677 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
678 font_name = pango_font_description_to_string (current_font);
680 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
684 gtk_window_set_transient_for (GTK_WINDOW (dialog),
685 GTK_WINDOW (get_widget_assert (de->builder,
687 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
689 const gchar *font = gtk_font_selection_dialog_get_font_name
690 (GTK_FONT_SELECTION_DIALOG (dialog));
692 PangoFontDescription* font_desc =
693 pango_font_description_from_string (font);
695 psppire_data_editor_set_font (de->data_editor, font_desc);
698 gtk_widget_hide (dialog);
703 /* Callback for the value labels action */
705 toggle_value_labels (GtkToggleAction *ta, gpointer data)
707 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
709 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
713 toggle_split_window (GtkToggleAction *ta, gpointer data)
715 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
717 psppire_data_editor_split_window (de->data_editor,
718 gtk_toggle_action_get_active (ta));
723 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
725 /* FIXME: Need to be more intelligent here.
726 Give the user the opportunity to save any unsaved data.
728 g_object_unref (the_data_store);
735 create_data_sheet_variable_popup_menu (PsppireDataWindow *de)
737 GtkWidget *menu = gtk_menu_new ();
739 GtkWidget *sort_ascending =
740 gtk_action_create_menu_item (gtk_action_new ("sort-up",
743 "gtk-sort-ascending"));
745 GtkWidget *sort_descending =
746 gtk_action_create_menu_item (gtk_action_new ("sort-down",
747 _("Sort Descending"),
749 "gtk-sort-descending"));
751 GtkWidget *insert_variable =
752 gtk_menu_item_new_with_label (_("Insert Variable"));
754 GtkWidget *clear_variable =
755 gtk_menu_item_new_with_label (_("Clear"));
758 gtk_action_connect_proxy (de->delete_variables,
762 gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
765 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
766 gtk_separator_menu_item_new ());
769 gtk_menu_shell_append (GTK_MENU_SHELL (menu), clear_variable);
772 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
773 gtk_separator_menu_item_new ());
776 gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_ascending);
779 g_signal_connect_swapped (G_OBJECT (sort_ascending), "activate",
780 G_CALLBACK (psppire_data_editor_sort_ascending),
783 g_signal_connect_swapped (G_OBJECT (sort_descending), "activate",
784 G_CALLBACK (psppire_data_editor_sort_descending),
787 g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
788 G_CALLBACK (gtk_action_activate),
789 de->insert_variable);
792 gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_descending);
794 gtk_widget_show_all (menu);
801 create_data_sheet_cases_popup_menu (PsppireDataWindow *de)
803 GtkWidget *menu = gtk_menu_new ();
805 GtkWidget *insert_case =
806 gtk_menu_item_new_with_label (_("Insert Case"));
808 GtkWidget *delete_case =
809 gtk_menu_item_new_with_label (_("Clear"));
812 gtk_action_connect_proxy (de->delete_cases,
816 gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_case);
818 g_signal_connect_swapped (G_OBJECT (insert_case), "activate",
819 G_CALLBACK (gtk_action_activate),
823 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
824 gtk_separator_menu_item_new ());
827 gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_case);
830 gtk_widget_show_all (menu);
837 create_var_sheet_variable_popup_menu (PsppireDataWindow *de)
839 GtkWidget *menu = gtk_menu_new ();
841 GtkWidget *insert_variable =
842 gtk_menu_item_new_with_label (_("Insert Variable"));
844 GtkWidget *delete_variable =
845 gtk_menu_item_new_with_label (_("Clear"));
848 gtk_action_connect_proxy (de->delete_variables,
852 gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
854 g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
855 G_CALLBACK (gtk_action_activate),
856 de->insert_variable);
859 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
860 gtk_separator_menu_item_new ());
863 gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_variable);
866 gtk_widget_show_all (menu);
872 #if RECENT_LISTS_AVAILABLE
875 on_recent_data_select (GtkMenuShell *menushell, gpointer user_data)
878 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
881 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
883 file = g_filename_from_uri (uri, NULL, NULL);
887 psppire_data_window_load_file (de, file);
893 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
900 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
902 file = g_filename_from_uri (uri, NULL, NULL);
906 se = psppire_syntax_window_new ();
908 psppire_syntax_window_load_from_file (PSPPIRE_SYNTAX_WINDOW (se), file, NULL);
909 gtk_widget_show (se);
917 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
919 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
921 gtk_action_set_visible (de->delete_cases, case_num != -1);
926 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
928 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
930 gtk_action_set_visible (de->delete_variables, var != -1);
933 /* Callback for when the datasheet/varsheet is selected */
935 on_switch_sheet (GtkNotebook *notebook,
936 GtkNotebookPage *page,
940 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
943 GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1"));
945 GtkWidget *view_data =
946 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
948 GtkWidget *view_variables =
949 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
953 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
954 gtk_widget_hide (view_variables);
955 gtk_widget_show (view_data);
956 gtk_action_set_sensitive (de->insert_variable, TRUE);
957 gtk_action_set_sensitive (de->insert_case, FALSE);
958 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
960 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
961 gtk_widget_show (view_variables);
962 gtk_widget_hide (view_data);
963 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
964 gtk_action_set_sensitive (de->insert_case, TRUE);
967 g_assert_not_reached ();
972 update_paste_menuitem (de, page_num);
978 resolve_action (GtkBuilder *builder, const gchar *action, const gchar *proxy)
981 GObject *act = get_object_assert (builder, action);
982 g_assert (GTK_IS_ACTION (act));
986 pr = get_object_assert (builder, proxy);
987 g_assert (GTK_IS_WIDGET (pr));
991 gtk_action_connect_proxy (GTK_ACTION (act), GTK_WIDGET (pr));
993 return GTK_ACTION (act);
998 set_unsaved (gpointer w)
1000 psppire_window_set_unsaved (PSPPIRE_WINDOW (w), TRUE);
1004 psppire_data_window_init (PsppireDataWindow *de)
1006 PsppireVarStore *vs;
1014 GtkWidget *box = gtk_vbox_new (FALSE, 0);
1015 de->xml = XML_NEW ("data-editor.glade");
1016 de->builder = builder_new ("data-editor.ui");
1018 menubar = get_widget_assert (de->builder, "menubar");
1019 hb = get_widget_assert (de->builder, "handlebox1");
1020 sb = get_widget_assert (de->builder, "status-bar");
1022 de->file_name = NULL;
1025 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (the_var_store, the_data_store));
1027 g_signal_connect_swapped (the_data_store, "case-changed",
1028 G_CALLBACK (set_unsaved), de);
1030 g_signal_connect_swapped (the_data_store, "case-inserted",
1031 G_CALLBACK (set_unsaved), de);
1033 g_signal_connect_swapped (the_data_store, "cases-deleted",
1034 G_CALLBACK (set_unsaved), de);
1036 dataset_set_callback (the_dataset, set_unsaved, de);
1038 connect_help (de->builder);
1040 g_object_ref (menubar);
1041 gtk_widget_unparent (menubar);
1044 gtk_widget_unparent (hb);
1047 gtk_widget_unparent (sb);
1049 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
1050 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
1051 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
1052 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
1054 gtk_container_add (GTK_CONTAINER (de), box);
1056 g_signal_connect (de->data_editor, "data-selection-changed",
1057 G_CALLBACK (update_cut_copy_menuitems), de);
1059 g_signal_connect (de->data_editor, "data-available-changed",
1060 G_CALLBACK (update_paste_menuitems), de);
1062 dataset_add_transform_change_callback (the_dataset,
1063 transformation_change_callback,
1069 g_assert(vs); /* Traps a possible bug in w32 build */
1071 g_signal_connect (vs->dict, "weight-changed",
1072 G_CALLBACK (on_weight_change),
1075 g_signal_connect (vs->dict, "filter-changed",
1076 G_CALLBACK (on_filter_change),
1079 g_signal_connect (vs->dict, "split-changed",
1080 G_CALLBACK (on_split_change),
1084 g_signal_connect (get_widget_assert (de->xml, "edit_copy"),
1086 G_CALLBACK (on_edit_copy), de);
1088 g_signal_connect (get_widget_assert (de->xml, "edit_cut"),
1090 G_CALLBACK (on_edit_cut), de);
1095 de->action_data_open =
1096 resolve_action (de->builder, "file_open_data", "button-open");
1098 g_object_set (de->action_data_open,
1099 "tooltip", _("Open a data file"),
1100 "stock-id", "gtk-open",
1103 g_signal_connect (de->action_data_open, "activate",
1104 G_CALLBACK (open_data_dialog), de);
1109 de->action_data_new =
1110 resolve_action (de->builder, "file_new_data", NULL);
1112 g_object_set (de->action_data_new,
1113 "tooltip", _("New data file"),
1114 "stock-id", "gtk-new",
1117 g_signal_connect (de->action_data_new, "activate",
1118 G_CALLBACK (new_file), de);
1124 de->invoke_text_import_assistant =
1125 resolve_action (de->builder, "file_import-text", NULL);
1127 g_object_set (de->invoke_text_import_assistant,
1128 "tooltip", _("Import text data file"),
1129 "stock-id", "gtk-convert",
1132 g_signal_connect (de->invoke_text_import_assistant, "activate",
1133 G_CALLBACK (text_data_import_assistant), de);
1139 de->action_data_save =
1140 resolve_action (de->builder, "file_save", "button-save");
1143 g_object_set (de->action_data_save,
1144 "tooltip", _("Save data to file"),
1145 "stock-id", "gtk-save",
1148 g_signal_connect (de->action_data_save, "activate",
1149 G_CALLBACK (data_save), de);
1155 de->action_data_save_as =
1156 resolve_action (de->builder, "file_save_as", NULL);
1158 g_object_set (de->action_data_save_as,
1159 "label", _("Save As"),
1160 "tooltip", _("Save data to file"),
1161 "stock-id", "gtk-save-as",
1164 g_signal_connect (de->action_data_save_as, "activate",
1165 G_CALLBACK (data_save_as_dialog), de);
1170 GObject *value_labels_action =
1171 resolve_action (de->builder,
1172 "view_value-labels", "togglebutton-value-labels");
1174 g_object_set (value_labels_action,
1175 "tooltip", _("Show/hide value labels"),
1176 "stock-id", "pspp-value-labels",
1179 g_signal_connect (value_labels_action, "toggled",
1180 G_CALLBACK (toggle_value_labels), de);
1184 g_signal_connect (get_widget_assert (de->xml, "edit_paste"), "activate",
1185 G_CALLBACK (on_edit_paste),
1190 resolve_action (de->builder, "edit_clear-cases", NULL);
1193 g_object_set (de->delete_cases,
1194 "label", _("Clear"),
1195 "tooltip", _("Delete the cases at the selected position(s)"),
1196 "stock-id", "gtk-clear",
1199 g_signal_connect_swapped (de->delete_cases, "activate",
1200 G_CALLBACK (psppire_data_editor_delete_cases),
1203 gtk_action_set_visible (de->delete_cases, FALSE);
1208 de->delete_variables =
1209 resolve_action (de->builder, "edit_clear-variables", NULL);
1211 g_object_set (de->delete_variables,
1212 "label", _("Clear"),
1213 "tooltip", _("Delete the variables at the selected position(s)"),
1214 "stock-id", "gtk-clear",
1218 g_signal_connect_swapped (de->delete_variables, "activate",
1219 G_CALLBACK (psppire_data_editor_delete_variables),
1222 gtk_action_set_visible (de->delete_variables, FALSE);
1226 de->insert_variable =
1227 resolve_action (de->builder, "edit_insert-variable",
1228 "button-insert-variable");
1230 g_object_set (de->insert_variable,
1231 "tooltip", _("Create a new variable at the current position"),
1232 "stock-id", "pspp-insert-variable",
1235 g_signal_connect (de->insert_variable, "activate",
1236 G_CALLBACK (on_insert_variable), de->data_editor);
1243 resolve_action (de->builder, "edit_insert-case", "button-insert-case");
1245 g_object_set (de->insert_case,
1246 "tooltip", _("Create a new case at the current position"),
1247 "stock-id", "pspp-insert-case",
1250 g_signal_connect (de->insert_case, "activate",
1251 G_CALLBACK (insert_case), de);
1257 de->invoke_goto_dialog =
1258 resolve_action (de->builder, "edit_goto-case", "button-goto-case");
1261 g_object_set (de->invoke_goto_dialog,
1262 "tooltip", _("Jump to a Case in the Data Sheet"),
1263 "stock-id", "gtk-jump-to",
1266 g_signal_connect (de->invoke_goto_dialog, "activate",
1267 G_CALLBACK (goto_case_dialog), de);
1272 de->invoke_weight_cases_dialog =
1273 resolve_action (de->builder, "data_weight-cases", "button-weight-cases");
1276 g_object_set (de->invoke_weight_cases_dialog,
1277 "stock-id", "pspp-weight-cases",
1278 "tooltip", _("Weight cases by variable"),
1281 g_signal_connect (de->invoke_weight_cases_dialog, "activate",
1282 G_CALLBACK (weight_cases_dialog), de);
1286 de->invoke_transpose_dialog =
1287 resolve_action (de->builder, "data_transpose", NULL);
1290 g_object_set (de->invoke_transpose_dialog,
1291 "tooltip", _("Transpose the cases with the variables"),
1292 "stock-id", "pspp-transpose",
1295 g_signal_connect (de->invoke_transpose_dialog, "activate",
1296 G_CALLBACK (transpose_dialog), de);
1300 de->invoke_split_file_dialog =
1301 resolve_action (de->builder, "data_split-file", "button-split-file");
1303 g_object_set (de->invoke_split_file_dialog,
1304 "tooltip", _("Split the active file"),
1305 "stock-id", "pspp-split-file",
1308 g_signal_connect (de->invoke_split_file_dialog, "activate",
1309 G_CALLBACK (split_file_dialog), de);
1314 de->invoke_sort_cases_dialog =
1315 resolve_action (de->builder, "data_sort-cases", NULL);
1318 g_object_set (de->invoke_sort_cases_dialog,
1319 "tooltip", _("Sort cases in the active file"),
1320 "stock-id", "gtk-sort-ascending",
1323 g_signal_connect (de->invoke_sort_cases_dialog, "activate",
1324 G_CALLBACK (sort_cases_dialog), de);
1329 de->invoke_select_cases_dialog =
1330 resolve_action (de->builder, "data_select-cases", "button-select-cases");
1332 g_object_set (de->invoke_select_cases_dialog,
1333 "tooltip", _("Select cases from the active file"),
1334 "stock-id", "pspp-select-cases",
1337 g_signal_connect (de->invoke_select_cases_dialog, "activate",
1338 G_CALLBACK (select_cases_dialog), de);
1343 de->invoke_compute_dialog =
1344 resolve_action (de->builder, "transform_compute", NULL);
1346 g_object_set (de->invoke_compute_dialog,
1347 "tooltip", _("Compute new values for a variable"),
1348 "stock-id", "pspp-compute",
1351 g_signal_connect (de->invoke_compute_dialog, "activate",
1352 G_CALLBACK (compute_dialog), de);
1357 de->invoke_oneway_anova_dialog =
1358 resolve_action (de->builder, "oneway-anova", NULL);
1360 g_object_set (de->invoke_oneway_anova_dialog,
1361 "tooltip", _("Perform one way analysis of variance"),
1364 g_signal_connect (de->invoke_oneway_anova_dialog, "activate",
1365 G_CALLBACK (oneway_anova_dialog), de);
1370 de->invoke_t_test_independent_samples_dialog =
1371 resolve_action (de->builder, "indep-t-test", NULL);
1374 g_object_set (de->invoke_t_test_independent_samples_dialog,
1376 _("Calculate T Test for samples from independent groups"),
1379 g_signal_connect (de->invoke_t_test_independent_samples_dialog, "activate",
1380 G_CALLBACK (t_test_independent_samples_dialog), de);
1385 de->invoke_t_test_paired_samples_dialog =
1386 resolve_action (de->builder, "paired-t-test", NULL);
1388 g_object_set (de->invoke_t_test_paired_samples_dialog,
1390 _("Calculate T Test for paired samples"),
1393 g_signal_connect (de->invoke_t_test_paired_samples_dialog, "activate",
1394 G_CALLBACK (t_test_paired_samples_dialog), de);
1399 de->invoke_t_test_one_sample_dialog =
1400 resolve_action (de->builder, "one-sample-t-test", NULL);
1402 g_object_set (de->invoke_t_test_one_sample_dialog,
1404 _("Calculate T Test for sample from a single distribution"),
1407 g_signal_connect (de->invoke_t_test_one_sample_dialog, "activate",
1408 G_CALLBACK (t_test_one_sample_dialog), de);
1413 de->invoke_comments_dialog =
1414 resolve_action (de->builder, "utilities_comments", NULL);
1417 g_object_set (de->invoke_comments_dialog,
1419 _("Commentary text for the data file"),
1422 g_signal_connect (de->invoke_comments_dialog, "activate",
1423 G_CALLBACK (comments_dialog), de);
1429 de->invoke_find_dialog =
1430 resolve_action (de->builder, "edit_find", "button-find");
1432 g_object_set (de->invoke_find_dialog, "stock-id", "gtk-find", NULL);
1434 g_signal_connect (de->invoke_find_dialog, "activate",
1435 G_CALLBACK (find_dialog), de);
1438 de->invoke_rank_dialog =
1439 resolve_action (de->builder, "transform_rank", NULL);
1441 g_object_set (de->invoke_rank_dialog,
1442 "stock-id", "pspp-rank-cases",
1443 "tooltip", _("Rank Cases"),
1446 g_signal_connect (de->invoke_rank_dialog, "activate",
1447 G_CALLBACK (rank_dialog), de);
1452 de->invoke_recode_same_dialog =
1453 resolve_action (de->builder, "transform_recode-same", NULL);
1455 g_object_set (de->invoke_recode_same_dialog,
1456 "stock-id", "pspp-recode-same",
1457 "tooltip", _("Recode values into the same variables"),
1460 g_signal_connect (de->invoke_recode_same_dialog, "activate",
1461 G_CALLBACK (recode_same_dialog), de);
1466 de->invoke_recode_different_dialog =
1467 resolve_action (de->builder, "transform_recode-different", NULL);
1469 g_object_set (de->invoke_recode_same_dialog,
1470 "stock-id", "pspp-recode-different",
1471 "tooltip", _("Recode values into different variables"),
1474 g_signal_connect (de->invoke_recode_different_dialog, "activate",
1475 G_CALLBACK (recode_different_dialog), de);
1480 de->invoke_variable_info_dialog =
1481 resolve_action (de->builder, "utilities_variables", "button-goto-variable");
1483 g_object_set (de->invoke_variable_info_dialog,
1484 "stock-id", "pspp-goto-variable",
1485 "tooltip", _("Jump to variable"),
1488 g_signal_connect (de->invoke_variable_info_dialog, "activate",
1489 G_CALLBACK (variable_info_dialog), de);
1494 de->invoke_descriptives_dialog =
1495 resolve_action (de->builder, "analyze_descriptives", NULL);
1497 g_object_set (de->invoke_descriptives_dialog,
1498 "tooltip", _("Calculate descriptive statistics (mean, variance, ...)"),
1499 "stock-id", "pspp-descriptives",
1502 g_signal_connect (de->invoke_descriptives_dialog, "activate",
1503 G_CALLBACK (descriptives_dialog), de);
1508 de->invoke_frequencies_dialog =
1509 resolve_action (de->builder, "analyze_frequencies", NULL);
1511 g_object_set (de->invoke_frequencies_dialog,
1512 "tooltip", _("Generate frequency statistics"),
1513 "stock-id", "pspp-frequencies",
1516 g_signal_connect (de->invoke_frequencies_dialog, "activate",
1517 G_CALLBACK (frequencies_dialog), de);
1521 de->invoke_crosstabs_dialog =
1522 resolve_action (de->builder, "crosstabs", NULL);
1524 g_object_set (de->invoke_crosstabs_dialog,
1525 "tooltip", _("Generate crosstabulations"),
1526 "stock-id", "pspp-crosstabs",
1529 g_signal_connect (de->invoke_crosstabs_dialog, "activate",
1530 G_CALLBACK (crosstabs_dialog), de);
1536 de->invoke_examine_dialog =
1537 resolve_action (de->builder, "analyze_explore", NULL);
1539 g_object_set (de->invoke_examine_dialog,
1540 "tooltip", _("Examine Data by Factors"),
1541 "stock-id", "pspp-examine",
1544 g_signal_connect (de->invoke_examine_dialog, "activate",
1545 G_CALLBACK (examine_dialog), de);
1550 de->invoke_regression_dialog =
1551 resolve_action (de->builder, "linear-regression", NULL);
1553 g_object_set (de->invoke_regression_dialog,
1554 "tooltip", _("Estimate parameters of the linear model"),
1555 "stock-id", "pspp-regression",
1559 g_signal_connect (de->invoke_regression_dialog, "activate",
1560 G_CALLBACK (regression_dialog), de);
1565 #if RECENT_LISTS_AVAILABLE && 0
1567 GtkRecentManager *rm = gtk_recent_manager_get_default ();
1568 GtkWidget *recent_data = get_object_assert (de->builder, "file_recent-data");
1569 GtkWidget *recent_files = get_object_assert (de->builder, "file_recent-files");
1570 GtkWidget *recent_separator = get_object_assert (de->builder, "file_separator1");
1572 GtkWidget *menu = gtk_recent_chooser_menu_new_for_manager (rm);
1574 GtkRecentFilter *filter = gtk_recent_filter_new ();
1576 gtk_widget_show (recent_data);
1577 gtk_widget_show (recent_files);
1578 gtk_widget_show (recent_separator);
1580 gtk_recent_filter_add_pattern (filter, "*.sav");
1581 gtk_recent_filter_add_pattern (filter, "*.SAV");
1583 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1585 gtk_widget_set_sensitive (recent_data, TRUE);
1586 g_signal_connect (menu, "selection-done",
1587 G_CALLBACK (on_recent_data_select), de);
1589 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu);
1592 filter = gtk_recent_filter_new ();
1593 menu = gtk_recent_chooser_menu_new_for_manager (rm);
1595 gtk_recent_filter_add_pattern (filter, "*.sps");
1596 gtk_recent_filter_add_pattern (filter, "*.SPS");
1598 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1600 gtk_widget_set_sensitive (recent_files, TRUE);
1601 g_signal_connect (menu, "selection-done",
1602 G_CALLBACK (on_recent_files_select), de);
1604 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu);
1608 g_signal_connect (get_object_assert (de->builder,"file_new_syntax"),
1610 G_CALLBACK (create_syntax_window),
1613 g_signal_connect (get_object_assert (de->builder,"file_open_syntax"),
1615 G_CALLBACK (open_syntax_window),
1619 GObject *abt = get_object_assert (de->builder, "help_about");
1620 g_object_set (abt, "stock-id", "gtk-about", NULL);
1621 g_signal_connect (abt,
1623 G_CALLBACK (about_new),
1628 g_signal_connect (get_object_assert (de->builder,"help_reference"),
1630 G_CALLBACK (reference_manual),
1634 g_signal_connect (de->data_editor,
1636 G_CALLBACK (enable_delete_cases),
1639 g_signal_connect (de->data_editor,
1640 "variables-selected",
1641 G_CALLBACK (enable_delete_variables),
1645 g_signal_connect (GTK_NOTEBOOK (de->data_editor),
1647 G_CALLBACK (on_switch_sheet), de);
1649 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1650 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1652 g_signal_connect (get_object_assert (de->builder, "view_statusbar"),
1654 G_CALLBACK (status_bar_activate), de);
1657 g_signal_connect (get_object_assert (de->builder, "view_gridlines"),
1659 G_CALLBACK (grid_lines_activate), de);
1663 g_signal_connect (get_object_assert (de->builder, "view_data"),
1665 G_CALLBACK (data_view_activate), de);
1667 g_signal_connect (get_object_assert (de->builder, "view_variables"),
1669 G_CALLBACK (variable_view_activate), de);
1673 GtkAction *font_action =
1674 resolve_action (de->builder, "view_fonts", NULL);
1676 g_object_set (font_action,
1677 "stock-id", "gtk-select-font",
1680 g_signal_connect (font_action,
1682 G_CALLBACK (fonts_activate), de);
1687 g_signal_connect (get_object_assert (de->builder, "file_quit"),
1689 G_CALLBACK (file_quit), de);
1691 g_signal_connect (get_object_assert (de->builder, "transform_run-pending"),
1693 G_CALLBACK (execute), de);
1696 g_signal_connect (get_object_assert (de->builder, "windows_minimise_all"),
1698 G_CALLBACK (psppire_window_minimise_all), NULL);
1702 GtkAction *split_window_action =
1703 resolve_action (de->builder, "windows_split", NULL);
1705 g_object_set (split_window_action,
1706 "tooltip", _("Split the window vertically and horizontally"),
1707 "stock-id", "pspp-split-window",
1710 g_signal_connect (split_window_action, "toggled",
1711 G_CALLBACK (toggle_split_window),
1715 de->data_sheet_variable_popup_menu =
1716 GTK_MENU (create_data_sheet_variable_popup_menu (de));
1718 de->var_sheet_variable_popup_menu =
1719 GTK_MENU (create_var_sheet_variable_popup_menu (de));
1721 de->data_sheet_cases_popup_menu =
1722 GTK_MENU (create_data_sheet_cases_popup_menu (de));
1724 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1"));
1726 PSPPIRE_WINDOW (de)->menu =
1727 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
1730 g_object_set (de->data_editor,
1731 "datasheet-column-menu", de->data_sheet_variable_popup_menu,
1732 "datasheet-row-menu", de->data_sheet_cases_popup_menu,
1733 "varsheet-row-menu", de->var_sheet_variable_popup_menu,
1736 gtk_widget_show (GTK_WIDGET (de->data_editor));
1737 gtk_widget_show (box);
1742 psppire_data_window_new (void)
1744 return GTK_WIDGET (g_object_new (psppire_data_window_get_type (),
1745 "description", _("Data Editor"),