1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008, 2009, 2010, 2011 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/>. */
22 #include "data/any-reader.h"
23 #include "data/dataset.h"
24 #include "language/lexer/lexer.h"
25 #include "libpspp/message.h"
26 #include "ui/gui/aggregate-dialog.h"
27 #include "ui/gui/binomial-dialog.h"
28 #include "ui/gui/chi-square-dialog.h"
29 #include "ui/gui/comments-dialog.h"
30 #include "ui/gui/compute-dialog.h"
31 #include "ui/gui/correlation-dialog.h"
32 #include "ui/gui/crosstabs-dialog.h"
33 #include "ui/gui/descriptives-dialog.h"
34 #include "ui/gui/examine-dialog.h"
35 #include "ui/gui/executor.h"
36 #include "ui/gui/factor-dialog.h"
37 #include "ui/gui/find-dialog.h"
38 #include "ui/gui/frequencies-dialog.h"
39 #include "ui/gui/goto-case-dialog.h"
40 #include "ui/gui/help-menu.h"
41 #include "ui/gui/helper.h"
42 #include "ui/gui/k-related-dialog.h"
43 #include "ui/gui/oneway-anova-dialog.h"
44 #include "ui/gui/psppire-data-window.h"
45 #include "ui/gui/psppire-syntax-window.h"
46 #include "ui/gui/psppire-window.h"
47 #include "ui/gui/psppire.h"
48 #include "ui/gui/rank-dialog.h"
49 #include "ui/gui/recode-dialog.h"
50 #include "ui/gui/regression-dialog.h"
51 #include "ui/gui/reliability-dialog.h"
52 #include "ui/gui/roc-dialog.h"
53 #include "ui/gui/select-cases-dialog.h"
54 #include "ui/gui/sort-cases-dialog.h"
55 #include "ui/gui/split-file-dialog.h"
56 #include "ui/gui/t-test-independent-samples-dialog.h"
57 #include "ui/gui/t-test-one-sample.h"
58 #include "ui/gui/t-test-paired-samples.h"
59 #include "ui/gui/text-data-import-dialog.h"
60 #include "ui/gui/transpose-dialog.h"
61 #include "ui/gui/variable-info-dialog.h"
62 #include "ui/gui/weight-cases-dialog.h"
63 #include "ui/syntax-gen.h"
66 #define _(msgid) gettext (msgid)
67 #define N_(msgid) msgid
69 static PsppireDataWindow *the_data_window;
71 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
72 static void psppire_data_window_init (PsppireDataWindow *data_editor);
75 static void psppire_data_window_iface_init (PsppireWindowIface *iface);
77 static void psppire_data_window_dispose (GObject *object);
78 static void psppire_data_window_set_property (GObject *object,
82 static void psppire_data_window_get_property (GObject *object,
88 psppire_data_window_get_type (void)
90 static GType psppire_data_window_type = 0;
92 if (!psppire_data_window_type)
94 static const GTypeInfo psppire_data_window_info =
96 sizeof (PsppireDataWindowClass),
99 (GClassInitFunc)psppire_data_window_class_init,
100 (GClassFinalizeFunc) NULL,
102 sizeof (PsppireDataWindow),
104 (GInstanceInitFunc) psppire_data_window_init,
107 static const GInterfaceInfo window_interface_info =
109 (GInterfaceInitFunc) psppire_data_window_iface_init,
114 psppire_data_window_type =
115 g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireDataWindow",
116 &psppire_data_window_info, 0);
119 g_type_add_interface_static (psppire_data_window_type,
120 PSPPIRE_TYPE_WINDOW_MODEL,
121 &window_interface_info);
124 return psppire_data_window_type;
127 static GObjectClass *parent_class ;
134 psppire_data_window_class_init (PsppireDataWindowClass *class)
136 GObjectClass *object_class = G_OBJECT_CLASS (class);
138 parent_class = g_type_class_peek_parent (class);
140 object_class->dispose = psppire_data_window_dispose;
141 object_class->set_property = psppire_data_window_set_property;
142 object_class->get_property = psppire_data_window_get_property;
144 g_object_class_install_property (
145 object_class, PROP_DATASET,
146 g_param_spec_pointer ("dataset", "Dataset",
147 "'struct datset *' represented by the window",
148 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
152 extern GtkRecentManager *the_recent_mgr;
155 set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
157 GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
159 gtk_action_set_sensitive (edit_paste, x);
163 set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
165 GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
166 GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
168 gtk_action_set_sensitive (edit_copy, x);
169 gtk_action_set_sensitive (edit_cut, x);
172 /* Run the EXECUTE command. */
174 execute (PsppireDataWindow *dw)
176 execute_const_syntax_string (dw, "EXECUTE.");
180 transformation_change_callback (bool transformations_pending,
183 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
185 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
187 GtkWidget *menuitem =
188 gtk_ui_manager_get_widget (uim,"/ui/menubar/transform/transform_run-pending");
190 GtkWidget *status_label =
191 get_widget_assert (de->builder, "case-counter-area");
193 gtk_widget_set_sensitive (menuitem, transformations_pending);
196 if ( transformations_pending)
197 gtk_label_set_text (GTK_LABEL (status_label),
198 _("Transformations Pending"));
200 gtk_label_set_text (GTK_LABEL (status_label), "");
203 /* Callback for when the dictionary changes its filter variable */
205 on_filter_change (GObject *o, gint filter_index, gpointer data)
207 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
209 GtkWidget *filter_status_area =
210 get_widget_assert (de->builder, "filter-use-status-area");
212 if ( filter_index == -1 )
214 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
218 PsppireVarStore *vs = NULL;
219 PsppireDict *dict = NULL;
220 struct variable *var ;
223 g_object_get (de->data_editor, "var-store", &vs, NULL);
224 g_object_get (vs, "dictionary", &dict, NULL);
226 var = psppire_dict_get_variable (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;
292 PsppireDict *dict = NULL;
295 g_object_get (de->data_editor, "var-store", &vs, NULL);
296 g_object_get (vs, "dictionary", &dict, NULL);
298 var = psppire_dict_get_variable (dict, weight_index);
300 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
302 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
310 dump_rm (GtkRecentManager *rm)
312 GList *items = gtk_recent_manager_get_items (rm);
316 g_print ("Recent Items:\n");
317 for (i = items; i; i = i->next)
319 GtkRecentInfo *ri = i->data;
321 g_print ("Item: %s (Mime: %s) (Desc: %s) (URI: %s)\n",
322 gtk_recent_info_get_short_name (ri),
323 gtk_recent_info_get_mime_type (ri),
324 gtk_recent_info_get_description (ri),
325 gtk_recent_info_get_uri (ri)
329 gtk_recent_info_unref (ri);
338 load_file (PsppireWindow *de, const gchar *file_name)
340 gchar *utf8_file_name;
341 struct string filename;
345 ds_init_empty (&filename);
347 utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
349 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
351 g_free (utf8_file_name);
353 syntax = g_strdup_printf ("GET FILE=%s.", ds_cstr (&filename));
354 ds_destroy (&filename);
356 ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
357 lex_reader_for_string (syntax));
363 sysfile_chooser_dialog (PsppireWindow *toplevel)
366 gtk_file_chooser_dialog_new (_("Open"),
367 GTK_WINDOW (toplevel),
368 GTK_FILE_CHOOSER_ACTION_OPEN,
369 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
370 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
373 GtkFileFilter *filter;
375 filter = gtk_file_filter_new ();
376 gtk_file_filter_set_name (filter, _("Data and Syntax Files"));
377 gtk_file_filter_add_pattern (filter, "*.sav");
378 gtk_file_filter_add_pattern (filter, "*.SAV");
379 gtk_file_filter_add_pattern (filter, "*.por");
380 gtk_file_filter_add_pattern (filter, "*.POR");
381 gtk_file_filter_add_pattern (filter, "*.sps");
382 gtk_file_filter_add_pattern (filter, "*.SPS");
383 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
385 filter = gtk_file_filter_new ();
386 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
387 gtk_file_filter_add_pattern (filter, "*.sav");
388 gtk_file_filter_add_pattern (filter, "*.SAV");
389 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
391 filter = gtk_file_filter_new ();
392 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
393 gtk_file_filter_add_pattern (filter, "*.por");
394 gtk_file_filter_add_pattern (filter, "*.POR");
395 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
397 filter = gtk_file_filter_new ();
398 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
399 gtk_file_filter_add_pattern (filter, "*.sps");
400 gtk_file_filter_add_pattern (filter, "*.SPS");
401 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
403 filter = gtk_file_filter_new ();
404 gtk_file_filter_set_name (filter, _("All Files"));
405 gtk_file_filter_add_pattern (filter, "*");
406 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
410 gchar *filename = NULL;
411 g_object_get (toplevel, "filename", &filename, NULL);
413 if ( ! g_path_is_absolute (filename))
416 g_build_filename (g_get_current_dir (), filename, NULL);
417 dir_name = g_path_get_dirname (path);
422 dir_name = g_path_get_dirname (filename);
424 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
432 /* Callback for the data_open action.
433 Prompts for a filename and opens it */
435 open_window (PsppireWindow *de)
437 GtkWidget *dialog = sysfile_chooser_dialog (de);
439 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
441 case GTK_RESPONSE_ACCEPT:
444 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
446 gchar *sysname = convert_glib_filename_to_system_filename (name, NULL);
448 if (any_reader_may_open (sysname))
449 psppire_window_load (de, name);
451 open_syntax_window (name);
461 gtk_widget_destroy (dialog);
464 /* Returns true if NAME has a suffix which might denote a PSPP file */
466 name_has_suffix (const gchar *name)
468 if ( g_str_has_suffix (name, ".sav"))
470 if ( g_str_has_suffix (name, ".SAV"))
472 if ( g_str_has_suffix (name, ".por"))
474 if ( g_str_has_suffix (name, ".POR"))
481 /* Save DE to file */
483 save_file (PsppireWindow *w)
485 gchar *utf8_file_name = NULL;
486 gchar *file_name = NULL;
488 struct string filename ;
489 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
492 g_object_get (w, "filename", &file_name, NULL);
494 fnx = g_string_new (file_name);
496 if ( ! name_has_suffix (fnx->str))
498 if ( de->save_as_portable)
499 g_string_append (fnx, ".por");
501 g_string_append (fnx, ".sav");
504 ds_init_empty (&filename);
506 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
508 g_string_free (fnx, TRUE);
510 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
511 g_free (utf8_file_name);
513 syntax = g_strdup_printf ("%s OUTFILE=%s.",
514 de->save_as_portable ? "EXPORT" : "SAVE",
515 ds_cstr (&filename));
517 ds_destroy (&filename);
519 g_free (execute_syntax_string (de, syntax));
524 insert_case (PsppireDataWindow *dw)
526 psppire_data_editor_insert_case (dw->data_editor);
530 on_insert_variable (PsppireDataWindow *dw)
532 psppire_data_editor_insert_variable (dw->data_editor);
537 display_dict (PsppireDataWindow *de)
539 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
543 sysfile_info (PsppireDataWindow *de)
545 GtkWidget *dialog = sysfile_chooser_dialog (PSPPIRE_WINDOW (de));
547 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
549 struct string filename;
551 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
553 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
558 ds_init_empty (&filename);
560 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
562 g_free (utf8_file_name);
564 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
565 g_free (execute_syntax_string (de, syntax));
568 gtk_widget_destroy (dialog);
572 /* Callback for data_save_as action. Prompt for a filename and save */
574 data_save_as_dialog (PsppireDataWindow *de)
576 GtkWidget *button_sys;
578 gtk_file_chooser_dialog_new (_("Save"),
580 GTK_FILE_CHOOSER_ACTION_SAVE,
581 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
582 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
585 GtkFileFilter *filter = gtk_file_filter_new ();
586 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
587 gtk_file_filter_add_pattern (filter, "*.sav");
588 gtk_file_filter_add_pattern (filter, "*.SAV");
589 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
591 filter = gtk_file_filter_new ();
592 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
593 gtk_file_filter_add_pattern (filter, "*.por");
594 gtk_file_filter_add_pattern (filter, "*.POR");
595 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
597 filter = gtk_file_filter_new ();
598 gtk_file_filter_set_name (filter, _("All Files"));
599 gtk_file_filter_add_pattern (filter, "*");
600 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
603 GtkWidget *button_por;
604 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
606 gtk_radio_button_new_with_label (NULL, _("System File"));
609 gtk_radio_button_new_with_label
610 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
613 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
614 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
616 gtk_widget_show_all (vbox);
618 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
621 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
623 case GTK_RESPONSE_ACCEPT:
628 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
631 de->save_as_portable =
632 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
634 if ( ! name_has_suffix (filename->str))
636 if ( de->save_as_portable)
637 g_string_append (filename, ".por");
639 g_string_append (filename, ".sav");
642 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
644 save_file (PSPPIRE_WINDOW (de));
646 g_string_free (filename, TRUE);
653 gtk_widget_destroy (dialog);
657 /* Callback for data_save action.
660 data_save (PsppireWindow *de)
662 const gchar *fn = psppire_window_get_filename (de);
665 psppire_window_save (de);
667 data_save_as_dialog (PSPPIRE_DATA_WINDOW (de));
671 /* Callback for data_new action.
672 Performs the NEW FILE command */
674 new_file (PsppireDataWindow *de)
676 execute_const_syntax_string (de, "NEW FILE.");
677 psppire_window_set_filename (PSPPIRE_WINDOW (de), NULL);
683 on_edit_paste (PsppireDataWindow *de)
685 psppire_data_editor_clip_paste (de->data_editor);
689 on_edit_copy (PsppireDataWindow *de)
691 psppire_data_editor_clip_copy (de->data_editor);
697 on_edit_cut (PsppireDataWindow *de)
699 psppire_data_editor_clip_cut (de->data_editor);
704 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
706 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
708 if ( gtk_toggle_action_get_active (action))
709 gtk_widget_show (statusbar);
711 gtk_widget_hide (statusbar);
716 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
718 const gboolean grid_visible = gtk_toggle_action_get_active (action);
720 psppire_data_editor_show_grid (de->data_editor, grid_visible);
724 data_view_activate (PsppireDataWindow *de)
726 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
731 variable_view_activate (PsppireDataWindow *de)
733 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
738 fonts_activate (PsppireDataWindow *de)
740 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
741 PangoFontDescription *current_font;
744 gtk_font_selection_dialog_new (_("Font Selection"));
747 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
748 font_name = pango_font_description_to_string (current_font);
750 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
754 gtk_window_set_transient_for (GTK_WINDOW (dialog),
755 GTK_WINDOW (toplevel));
757 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
759 const gchar *font = gtk_font_selection_dialog_get_font_name
760 (GTK_FONT_SELECTION_DIALOG (dialog));
762 PangoFontDescription* font_desc =
763 pango_font_description_from_string (font);
765 psppire_data_editor_set_font (de->data_editor, font_desc);
768 gtk_widget_hide (dialog);
773 /* Callback for the value labels action */
775 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
777 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
781 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
783 psppire_data_editor_split_window (de->data_editor,
784 gtk_toggle_action_get_active (ta));
789 file_quit (PsppireDataWindow *de)
791 /* FIXME: Need to be more intelligent here.
792 Give the user the opportunity to save any unsaved data.
794 g_object_unref (de->data_store);
801 on_recent_data_select (GtkMenuShell *menushell,
802 PsppireWindow *window)
807 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
809 file = g_filename_from_uri (uri, NULL, NULL);
813 psppire_window_load (window, file);
819 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
826 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
828 file = g_filename_from_uri (uri, NULL, NULL);
832 se = psppire_syntax_window_new ();
834 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
835 gtk_widget_show (se);
837 gtk_widget_destroy (se);
844 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
846 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
848 gtk_action_set_visible (de->delete_cases, case_num != -1);
853 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
855 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
857 gtk_action_set_visible (de->delete_variables, var != -1);
860 /* Callback for when the datasheet/varsheet is selected */
862 on_switch_sheet (GtkNotebook *notebook,
863 GtkNotebookPage *page,
867 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
869 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
871 GtkWidget *view_data =
872 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
874 GtkWidget *view_variables =
875 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
879 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
880 gtk_widget_hide (view_variables);
881 gtk_widget_show (view_data);
882 gtk_action_set_sensitive (de->insert_variable, TRUE);
883 gtk_action_set_sensitive (de->insert_case, FALSE);
884 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
886 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
887 gtk_widget_show (view_variables);
888 gtk_widget_hide (view_data);
889 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
890 gtk_action_set_sensitive (de->insert_case, TRUE);
893 g_assert_not_reached ();
898 update_paste_menuitem (de, page_num);
905 set_unsaved (gpointer w)
907 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
911 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
912 Returns a pointer to the action
915 connect_action (PsppireDataWindow *dw, const char *action_name,
918 GtkAction *action = get_action_assert (dw->builder, action_name);
920 g_signal_connect_swapped (action, "activate", handler, dw);
925 /* Initializes as much of a PsppireDataWindow as we can and must before the
926 dataset has been set.
928 In particular, the 'menu' member is required in case the "filename" property
929 is set before the "dataset" property: otherwise PsppireWindow will try to
930 modify the menu as part of the "filename" property_set() function and end up
931 with a Gtk-CRITICAL since 'menu' is NULL. */
933 psppire_data_window_init (PsppireDataWindow *de)
937 de->builder = builder_new ("data-editor.ui");
939 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
941 PSPPIRE_WINDOW (de)->menu =
942 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
946 psppire_data_window_finish_init (PsppireDataWindow *de,
949 static const struct dataset_callbacks cbs =
951 set_unsaved, /* changed */
952 transformation_change_callback, /* transformations_changed */
961 GtkWidget *box = gtk_vbox_new (FALSE, 0);
964 dict = psppire_dict_new_from_dict (dataset_dict (ds));
965 de->var_store = psppire_var_store_new (dict);
966 de->data_store = psppire_data_store_new (dict);
967 psppire_data_store_set_reader (de->data_store, NULL);
969 menubar = get_widget_assert (de->builder, "menubar");
970 hb = get_widget_assert (de->builder, "handlebox1");
971 sb = get_widget_assert (de->builder, "status-bar");
974 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
977 g_signal_connect_swapped (de->data_store, "case-changed",
978 G_CALLBACK (set_unsaved), de);
980 g_signal_connect_swapped (de->data_store, "case-inserted",
981 G_CALLBACK (set_unsaved), de);
983 g_signal_connect_swapped (de->data_store, "cases-deleted",
984 G_CALLBACK (set_unsaved), de);
986 dataset_set_callbacks (de->dataset, &cbs, de);
988 connect_help (de->builder);
990 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
991 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
992 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
993 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
995 gtk_container_add (GTK_CONTAINER (de), box);
997 set_cut_copy_menuitem_sensitivity (de, FALSE);
999 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
1000 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
1003 set_paste_menuitem_sensitivity (de, FALSE);
1005 g_signal_connect_swapped (de->data_editor, "data-available-changed",
1006 G_CALLBACK (set_paste_menuitem_sensitivity), de);
1008 g_signal_connect (dict, "weight-changed",
1009 G_CALLBACK (on_weight_change),
1012 g_signal_connect (dict, "filter-changed",
1013 G_CALLBACK (on_filter_change),
1016 g_signal_connect (dict, "split-changed",
1017 G_CALLBACK (on_split_change),
1021 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
1023 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
1025 connect_action (de, "file_new_data", G_CALLBACK (new_file));
1027 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
1029 connect_action (de, "file_save", G_CALLBACK (data_save));
1031 connect_action (de, "file_open", G_CALLBACK (open_window));
1033 connect_action (de, "file_save_as", G_CALLBACK (data_save_as_dialog));
1035 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
1037 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
1039 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
1041 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
1043 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
1045 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
1047 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
1050 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
1052 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
1054 gtk_action_set_visible (de->delete_cases, FALSE);
1059 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1061 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1063 gtk_action_set_visible (de->delete_variables, FALSE);
1067 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1069 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1071 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1073 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1075 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1077 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1079 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1081 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1084 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1086 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1088 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1090 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1092 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1094 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1096 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1098 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1100 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1102 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1104 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1106 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1108 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1110 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1112 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1114 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1116 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1118 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1120 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1122 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1124 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1128 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1130 GtkWidget *recent_data =
1131 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1133 GtkWidget *recent_files =
1134 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1137 GtkWidget *menu_data =
1138 gtk_recent_chooser_menu_new_for_manager (the_recent_mgr);
1140 GtkWidget *menu_files =
1141 gtk_recent_chooser_menu_new_for_manager (the_recent_mgr);
1144 GtkRecentFilter *filter = gtk_recent_filter_new ();
1146 gtk_recent_filter_add_pattern (filter, "*.sav");
1147 gtk_recent_filter_add_pattern (filter, "*.SAV");
1148 gtk_recent_filter_add_pattern (filter, "*.por");
1149 gtk_recent_filter_add_pattern (filter, "*.POR");
1151 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1153 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1156 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1159 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1162 GtkRecentFilter *filter = gtk_recent_filter_new ();
1164 gtk_recent_filter_add_pattern (filter, "*.sps");
1165 gtk_recent_filter_add_pattern (filter, "*.SPS");
1167 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1169 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1172 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1174 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1178 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1181 g_signal_connect (de->data_editor,
1183 G_CALLBACK (enable_delete_cases),
1186 g_signal_connect (de->data_editor,
1187 "variables-selected",
1188 G_CALLBACK (enable_delete_variables),
1192 g_signal_connect (de->data_editor,
1194 G_CALLBACK (on_switch_sheet), de);
1196 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1197 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1199 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1201 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1203 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1205 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1207 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1209 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1211 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1213 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1215 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1218 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1220 merge_help_menu (uim);
1224 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1225 "datasheet-cases-popup");
1227 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1228 "varsheet-variable-popup");
1230 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1231 "datasheet-variable-popup");
1233 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1234 G_CALLBACK (psppire_data_editor_sort_ascending),
1237 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1238 G_CALLBACK (psppire_data_editor_sort_descending),
1241 g_object_set (de->data_editor,
1242 "datasheet-column-menu", data_sheet_variable_popup_menu,
1243 "datasheet-row-menu", data_sheet_cases_popup_menu,
1244 "varsheet-row-menu", var_sheet_variable_popup_menu,
1248 gtk_widget_show (GTK_WIDGET (de->data_editor));
1249 gtk_widget_show (box);
1251 the_data_window = de;
1255 psppire_data_window_dispose (GObject *object)
1257 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1259 if (dw->builder != NULL)
1261 g_object_unref (dw->builder);
1265 if (the_data_window == dw)
1266 the_data_window = NULL;
1268 G_OBJECT_CLASS (parent_class)->dispose (object);
1272 psppire_data_window_set_property (GObject *object,
1274 const GValue *value,
1277 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1282 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1285 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1291 psppire_data_window_get_property (GObject *object,
1296 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1301 g_value_set_pointer (value, window->dataset);
1304 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1311 psppire_data_window_new (struct dataset *ds)
1315 psppire_data_window_get_type (),
1316 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1317 "filename", _("PSPP-data"),
1318 "description", _("Data Editor"),
1325 psppire_data_window_iface_init (PsppireWindowIface *iface)
1327 iface->save = save_file;
1328 iface->load = load_file;
1333 psppire_default_data_window (void)
1335 if (the_data_window == NULL)
1336 gtk_widget_show (psppire_data_window_new (dataset_create ()));
1337 return the_data_window;