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/dataset.h"
23 #include "data/session.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/entry-dialog.h"
35 #include "ui/gui/examine-dialog.h"
36 #include "ui/gui/executor.h"
37 #include "ui/gui/factor-dialog.h"
38 #include "ui/gui/find-dialog.h"
39 #include "ui/gui/frequencies-dialog.h"
40 #include "ui/gui/goto-case-dialog.h"
41 #include "ui/gui/help-menu.h"
42 #include "ui/gui/helper.h"
43 #include "ui/gui/k-related-dialog.h"
44 #include "ui/gui/oneway-anova-dialog.h"
45 #include "ui/gui/psppire-data-window.h"
46 #include "ui/gui/psppire-syntax-window.h"
47 #include "ui/gui/psppire-window.h"
48 #include "ui/gui/psppire.h"
49 #include "ui/gui/rank-dialog.h"
50 #include "ui/gui/recode-dialog.h"
51 #include "ui/gui/regression-dialog.h"
52 #include "ui/gui/reliability-dialog.h"
53 #include "ui/gui/roc-dialog.h"
54 #include "ui/gui/select-cases-dialog.h"
55 #include "ui/gui/sort-cases-dialog.h"
56 #include "ui/gui/split-file-dialog.h"
57 #include "ui/gui/t-test-independent-samples-dialog.h"
58 #include "ui/gui/t-test-one-sample.h"
59 #include "ui/gui/t-test-paired-samples.h"
60 #include "ui/gui/text-data-import-dialog.h"
61 #include "ui/gui/transpose-dialog.h"
62 #include "ui/gui/variable-info-dialog.h"
63 #include "ui/gui/weight-cases-dialog.h"
64 #include "ui/syntax-gen.h"
66 #include "gl/xvasprintf.h"
69 #define _(msgid) gettext (msgid)
70 #define N_(msgid) msgid
72 struct session *the_session;
73 struct ll_list all_data_windows = LL_INITIALIZER (all_data_windows);
75 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
76 static void psppire_data_window_init (PsppireDataWindow *data_editor);
79 static void psppire_data_window_iface_init (PsppireWindowIface *iface);
81 static void psppire_data_window_dispose (GObject *object);
82 static void psppire_data_window_set_property (GObject *object,
86 static void psppire_data_window_get_property (GObject *object,
92 psppire_data_window_get_type (void)
94 static GType psppire_data_window_type = 0;
96 if (!psppire_data_window_type)
98 static const GTypeInfo psppire_data_window_info =
100 sizeof (PsppireDataWindowClass),
103 (GClassInitFunc)psppire_data_window_class_init,
104 (GClassFinalizeFunc) NULL,
106 sizeof (PsppireDataWindow),
108 (GInstanceInitFunc) psppire_data_window_init,
111 static const GInterfaceInfo window_interface_info =
113 (GInterfaceInitFunc) psppire_data_window_iface_init,
118 psppire_data_window_type =
119 g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireDataWindow",
120 &psppire_data_window_info, 0);
123 g_type_add_interface_static (psppire_data_window_type,
124 PSPPIRE_TYPE_WINDOW_MODEL,
125 &window_interface_info);
128 return psppire_data_window_type;
131 static GObjectClass *parent_class ;
138 psppire_data_window_class_init (PsppireDataWindowClass *class)
140 GObjectClass *object_class = G_OBJECT_CLASS (class);
142 parent_class = g_type_class_peek_parent (class);
144 object_class->dispose = psppire_data_window_dispose;
145 object_class->set_property = psppire_data_window_set_property;
146 object_class->get_property = psppire_data_window_get_property;
148 g_object_class_install_property (
149 object_class, PROP_DATASET,
150 g_param_spec_pointer ("dataset", "Dataset",
151 "'struct datset *' represented by the window",
152 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
156 extern GtkRecentManager *the_recent_mgr;
159 set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
161 GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
163 gtk_action_set_sensitive (edit_paste, x);
167 set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
169 GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
170 GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
172 gtk_action_set_sensitive (edit_copy, x);
173 gtk_action_set_sensitive (edit_cut, x);
176 /* Run the EXECUTE command. */
178 execute (PsppireDataWindow *dw)
180 execute_const_syntax_string (dw, "EXECUTE.");
184 transformation_change_callback (bool transformations_pending,
187 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
189 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
191 GtkWidget *menuitem =
192 gtk_ui_manager_get_widget (uim,"/ui/menubar/transform/transform_run-pending");
194 GtkWidget *status_label =
195 get_widget_assert (de->builder, "case-counter-area");
197 gtk_widget_set_sensitive (menuitem, transformations_pending);
200 if ( transformations_pending)
201 gtk_label_set_text (GTK_LABEL (status_label),
202 _("Transformations Pending"));
204 gtk_label_set_text (GTK_LABEL (status_label), "");
207 /* Callback for when the dictionary changes its filter variable */
209 on_filter_change (GObject *o, gint filter_index, gpointer data)
211 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
213 GtkWidget *filter_status_area =
214 get_widget_assert (de->builder, "filter-use-status-area");
216 if ( filter_index == -1 )
218 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
222 PsppireVarStore *vs = NULL;
223 PsppireDict *dict = NULL;
224 struct variable *var ;
227 g_object_get (de->data_editor, "var-store", &vs, NULL);
228 g_object_get (vs, "dictionary", &dict, NULL);
230 var = psppire_dict_get_variable (dict, filter_index);
232 text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
234 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
240 /* Callback for when the dictionary changes its split variables */
242 on_split_change (PsppireDict *dict, gpointer data)
244 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
246 size_t n_split_vars = dict_get_split_cnt (dict->dict);
248 GtkWidget *split_status_area =
249 get_widget_assert (de->builder, "split-file-status-area");
251 if ( n_split_vars == 0 )
253 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
259 const struct variable *const * split_vars =
260 dict_get_split_vars (dict->dict);
262 text = g_string_new (_("Split by "));
264 for (i = 0 ; i < n_split_vars - 1; ++i )
266 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
268 g_string_append (text, var_get_name (split_vars[i]));
270 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
272 g_string_free (text, TRUE);
279 /* Callback for when the dictionary changes its weights */
281 on_weight_change (GObject *o, gint weight_index, gpointer data)
283 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
285 GtkWidget *weight_status_area =
286 get_widget_assert (de->builder, "weight-status-area");
288 if ( weight_index == -1 )
290 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
294 struct variable *var ;
295 PsppireVarStore *vs = NULL;
296 PsppireDict *dict = NULL;
299 g_object_get (de->data_editor, "var-store", &vs, NULL);
300 g_object_get (vs, "dictionary", &dict, NULL);
302 var = psppire_dict_get_variable (dict, weight_index);
304 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
306 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
314 dump_rm (GtkRecentManager *rm)
316 GList *items = gtk_recent_manager_get_items (rm);
320 g_print ("Recent Items:\n");
321 for (i = items; i; i = i->next)
323 GtkRecentInfo *ri = i->data;
325 g_print ("Item: %s (Mime: %s) (Desc: %s) (URI: %s)\n",
326 gtk_recent_info_get_short_name (ri),
327 gtk_recent_info_get_mime_type (ri),
328 gtk_recent_info_get_description (ri),
329 gtk_recent_info_get_uri (ri)
333 gtk_recent_info_unref (ri);
342 load_file (PsppireWindow *de, const gchar *file_name)
344 gchar *utf8_file_name;
345 struct string filename;
349 ds_init_empty (&filename);
351 utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
353 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
355 g_free (utf8_file_name);
357 syntax = g_strdup_printf ("GET FILE=%s.", ds_cstr (&filename));
358 ds_destroy (&filename);
360 ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
361 lex_reader_for_string (syntax));
366 /* Returns true if NAME has a suffix which might denote a PSPP file */
368 name_has_suffix (const gchar *name)
370 if ( g_str_has_suffix (name, ".sav"))
372 if ( g_str_has_suffix (name, ".SAV"))
374 if ( g_str_has_suffix (name, ".por"))
376 if ( g_str_has_suffix (name, ".POR"))
383 /* Save DE to file */
385 save_file (PsppireWindow *w)
387 const gchar *file_name = NULL;
388 gchar *utf8_file_name = NULL;
390 struct string filename ;
391 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
394 file_name = psppire_window_get_filename (w);
396 fnx = g_string_new (file_name);
398 if ( ! name_has_suffix (fnx->str))
400 if ( de->save_as_portable)
401 g_string_append (fnx, ".por");
403 g_string_append (fnx, ".sav");
406 ds_init_empty (&filename);
408 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
410 g_string_free (fnx, TRUE);
412 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
413 g_free (utf8_file_name);
415 syntax = g_strdup_printf ("%s OUTFILE=%s.",
416 de->save_as_portable ? "EXPORT" : "SAVE",
417 ds_cstr (&filename));
419 ds_destroy (&filename);
421 g_free (execute_syntax_string (de, syntax));
426 insert_case (PsppireDataWindow *dw)
428 psppire_data_editor_insert_case (dw->data_editor);
432 on_insert_variable (PsppireDataWindow *dw)
434 psppire_data_editor_insert_variable (dw->data_editor);
439 display_dict (PsppireDataWindow *de)
441 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
445 sysfile_info (PsppireDataWindow *de)
447 GtkWidget *dialog = psppire_window_file_chooser_dialog (PSPPIRE_WINDOW (de));
449 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
451 struct string filename;
453 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
455 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
460 ds_init_empty (&filename);
462 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
464 g_free (utf8_file_name);
466 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
467 g_free (execute_syntax_string (de, syntax));
470 gtk_widget_destroy (dialog);
474 /* PsppireWindow 'pick_filename' callback: prompt for a filename to save as. */
476 data_pick_filename (PsppireWindow *window)
478 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
479 GtkWidget *button_sys;
481 gtk_file_chooser_dialog_new (_("Save"),
483 GTK_FILE_CHOOSER_ACTION_SAVE,
484 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
485 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
488 GtkFileFilter *filter = gtk_file_filter_new ();
489 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
490 gtk_file_filter_add_pattern (filter, "*.sav");
491 gtk_file_filter_add_pattern (filter, "*.SAV");
492 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
494 filter = gtk_file_filter_new ();
495 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
496 gtk_file_filter_add_pattern (filter, "*.por");
497 gtk_file_filter_add_pattern (filter, "*.POR");
498 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
500 filter = gtk_file_filter_new ();
501 gtk_file_filter_set_name (filter, _("All Files"));
502 gtk_file_filter_add_pattern (filter, "*");
503 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
506 GtkWidget *button_por;
507 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
509 gtk_radio_button_new_with_label (NULL, _("System File"));
512 gtk_radio_button_new_with_label
513 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
516 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
517 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
519 gtk_widget_show_all (vbox);
521 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
524 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
527 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
529 case GTK_RESPONSE_ACCEPT:
534 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
537 de->save_as_portable =
538 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
540 if ( ! name_has_suffix (filename->str))
542 if ( de->save_as_portable)
543 g_string_append (filename, ".por");
545 g_string_append (filename, ".sav");
548 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
550 g_string_free (filename, TRUE);
557 gtk_widget_destroy (dialog);
561 confirm_delete_dataset (PsppireDataWindow *de,
562 const char *old_dataset,
563 const char *new_dataset,
564 const char *existing_dataset)
569 dialog = gtk_message_dialog_new (
570 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
571 _("Delete Existing Dataset?"));
573 gtk_message_dialog_format_secondary_text (
574 GTK_MESSAGE_DIALOG (dialog),
575 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
576 "dataset named \"%s\". Are you sure that you want to do this?"),
577 old_dataset, new_dataset, existing_dataset);
579 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
580 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
581 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
584 g_object_set (dialog, "icon-name", "psppicon", NULL);
586 result = gtk_dialog_run (GTK_DIALOG (dialog));
588 gtk_widget_destroy (dialog);
590 return result == GTK_RESPONSE_OK;
594 on_rename_dataset (PsppireDataWindow *de)
596 struct dataset *ds = de->dataset;
597 struct session *session = dataset_session (ds);
598 const char *old_name = dataset_name (ds);
599 struct dataset *existing_dataset;
603 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
605 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
609 if (new_name == NULL)
612 existing_dataset = session_lookup_dataset (session, new_name);
613 if (existing_dataset == NULL || existing_dataset == ds
614 || confirm_delete_dataset (de, old_name, new_name,
615 dataset_name (existing_dataset)))
616 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
623 on_edit_paste (PsppireDataWindow *de)
625 psppire_data_editor_clip_paste (de->data_editor);
629 on_edit_copy (PsppireDataWindow *de)
631 psppire_data_editor_clip_copy (de->data_editor);
637 on_edit_cut (PsppireDataWindow *de)
639 psppire_data_editor_clip_cut (de->data_editor);
644 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
646 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
648 if ( gtk_toggle_action_get_active (action))
649 gtk_widget_show (statusbar);
651 gtk_widget_hide (statusbar);
656 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
658 const gboolean grid_visible = gtk_toggle_action_get_active (action);
660 psppire_data_editor_show_grid (de->data_editor, grid_visible);
664 data_view_activate (PsppireDataWindow *de)
666 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
671 variable_view_activate (PsppireDataWindow *de)
673 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
678 fonts_activate (PsppireDataWindow *de)
680 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
681 PangoFontDescription *current_font;
684 gtk_font_selection_dialog_new (_("Font Selection"));
687 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
688 font_name = pango_font_description_to_string (current_font);
690 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
694 gtk_window_set_transient_for (GTK_WINDOW (dialog),
695 GTK_WINDOW (toplevel));
697 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
699 const gchar *font = gtk_font_selection_dialog_get_font_name
700 (GTK_FONT_SELECTION_DIALOG (dialog));
702 PangoFontDescription* font_desc =
703 pango_font_description_from_string (font);
705 psppire_data_editor_set_font (de->data_editor, font_desc);
708 gtk_widget_hide (dialog);
713 /* Callback for the value labels action */
715 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
717 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
721 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
723 psppire_data_editor_split_window (de->data_editor,
724 gtk_toggle_action_get_active (ta));
729 file_quit (PsppireDataWindow *de)
731 /* FIXME: Need to be more intelligent here.
732 Give the user the opportunity to save any unsaved data.
739 on_recent_data_select (GtkMenuShell *menushell,
740 PsppireWindow *window)
745 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
747 file = g_filename_from_uri (uri, NULL, NULL);
751 psppire_window_load (window, file);
757 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
764 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
766 file = g_filename_from_uri (uri, NULL, NULL);
770 se = psppire_syntax_window_new ();
772 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
773 gtk_widget_show (se);
775 gtk_widget_destroy (se);
782 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
784 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
786 gtk_action_set_visible (de->delete_cases, case_num != -1);
791 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
793 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
795 gtk_action_set_visible (de->delete_variables, var != -1);
798 /* Callback for when the datasheet/varsheet is selected */
800 on_switch_sheet (GtkNotebook *notebook,
801 GtkNotebookPage *page,
805 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
807 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
809 GtkWidget *view_data =
810 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
812 GtkWidget *view_variables =
813 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
817 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
818 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
820 gtk_action_set_sensitive (de->insert_variable, TRUE);
821 gtk_action_set_sensitive (de->insert_case, FALSE);
822 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
824 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
825 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
826 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
827 gtk_action_set_sensitive (de->insert_case, TRUE);
830 g_assert_not_reached ();
835 update_paste_menuitem (de, page_num);
842 set_unsaved (gpointer w)
844 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
848 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
849 Returns a pointer to the action
852 connect_action (PsppireDataWindow *dw, const char *action_name,
855 GtkAction *action = get_action_assert (dw->builder, action_name);
857 g_signal_connect_swapped (action, "activate", handler, dw);
862 /* Initializes as much of a PsppireDataWindow as we can and must before the
863 dataset has been set.
865 In particular, the 'menu' member is required in case the "filename" property
866 is set before the "dataset" property: otherwise PsppireWindow will try to
867 modify the menu as part of the "filename" property_set() function and end up
868 with a Gtk-CRITICAL since 'menu' is NULL. */
870 psppire_data_window_init (PsppireDataWindow *de)
874 de->builder = builder_new ("data-editor.ui");
876 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
878 PSPPIRE_WINDOW (de)->menu =
879 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
883 psppire_data_window_finish_init (PsppireDataWindow *de,
886 static const struct dataset_callbacks cbs =
888 set_unsaved, /* changed */
889 transformation_change_callback, /* transformations_changed */
898 GtkWidget *box = gtk_vbox_new (FALSE, 0);
901 dict = psppire_dict_new_from_dict (dataset_dict (ds));
902 de->var_store = psppire_var_store_new (dict);
903 de->data_store = psppire_data_store_new (dict);
904 psppire_data_store_set_reader (de->data_store, NULL);
906 menubar = get_widget_assert (de->builder, "menubar");
907 hb = get_widget_assert (de->builder, "handlebox1");
908 sb = get_widget_assert (de->builder, "status-bar");
911 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
914 g_signal_connect_swapped (de->data_store, "case-changed",
915 G_CALLBACK (set_unsaved), de);
917 g_signal_connect_swapped (de->data_store, "case-inserted",
918 G_CALLBACK (set_unsaved), de);
920 g_signal_connect_swapped (de->data_store, "cases-deleted",
921 G_CALLBACK (set_unsaved), de);
923 dataset_set_callbacks (de->dataset, &cbs, de);
925 connect_help (de->builder);
927 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
928 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
929 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
930 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
932 gtk_container_add (GTK_CONTAINER (de), box);
934 set_cut_copy_menuitem_sensitivity (de, FALSE);
936 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
937 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
940 set_paste_menuitem_sensitivity (de, FALSE);
942 g_signal_connect_swapped (de->data_editor, "data-available-changed",
943 G_CALLBACK (set_paste_menuitem_sensitivity), de);
945 g_signal_connect (dict, "weight-changed",
946 G_CALLBACK (on_weight_change),
949 g_signal_connect (dict, "filter-changed",
950 G_CALLBACK (on_filter_change),
953 g_signal_connect (dict, "split-changed",
954 G_CALLBACK (on_split_change),
958 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
960 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
962 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
964 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
966 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
968 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
970 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
972 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
974 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
976 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
978 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
980 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
982 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
984 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
986 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
989 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
991 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
993 gtk_action_set_visible (de->delete_cases, FALSE);
998 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1000 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1002 gtk_action_set_visible (de->delete_variables, FALSE);
1006 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1008 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1010 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1012 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1014 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1016 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1018 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1020 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1023 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1025 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1027 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1029 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1031 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1033 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1035 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1037 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1039 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1041 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1043 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1045 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1047 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1049 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1051 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1053 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1055 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1057 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1059 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1061 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1063 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1067 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1069 GtkWidget *recent_data =
1070 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1072 GtkWidget *recent_files =
1073 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1076 GtkWidget *menu_data =
1077 gtk_recent_chooser_menu_new_for_manager (the_recent_mgr);
1079 GtkWidget *menu_files =
1080 gtk_recent_chooser_menu_new_for_manager (the_recent_mgr);
1083 GtkRecentFilter *filter = gtk_recent_filter_new ();
1085 gtk_recent_filter_add_pattern (filter, "*.sav");
1086 gtk_recent_filter_add_pattern (filter, "*.SAV");
1087 gtk_recent_filter_add_pattern (filter, "*.por");
1088 gtk_recent_filter_add_pattern (filter, "*.POR");
1090 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1092 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1095 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1098 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1101 GtkRecentFilter *filter = gtk_recent_filter_new ();
1103 gtk_recent_filter_add_pattern (filter, "*.sps");
1104 gtk_recent_filter_add_pattern (filter, "*.SPS");
1106 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1108 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1111 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1113 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1117 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1120 g_signal_connect (de->data_editor,
1122 G_CALLBACK (enable_delete_cases),
1125 g_signal_connect (de->data_editor,
1126 "variables-selected",
1127 G_CALLBACK (enable_delete_variables),
1131 g_signal_connect (de->data_editor,
1133 G_CALLBACK (on_switch_sheet), de);
1135 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1136 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1138 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1140 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1142 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1144 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1146 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1148 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1150 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1152 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1154 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1157 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1159 merge_help_menu (uim);
1163 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1164 "datasheet-cases-popup");
1166 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1167 "varsheet-variable-popup");
1169 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1170 "datasheet-variable-popup");
1172 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1173 G_CALLBACK (psppire_data_editor_sort_ascending),
1176 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1177 G_CALLBACK (psppire_data_editor_sort_descending),
1180 g_object_set (de->data_editor,
1181 "datasheet-column-menu", data_sheet_variable_popup_menu,
1182 "datasheet-row-menu", data_sheet_cases_popup_menu,
1183 "varsheet-row-menu", var_sheet_variable_popup_menu,
1187 gtk_widget_show (GTK_WIDGET (de->data_editor));
1188 gtk_widget_show (box);
1190 ll_push_head (&all_data_windows, &de->ll);
1194 psppire_data_window_dispose (GObject *object)
1196 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1198 if (dw->builder != NULL)
1200 g_object_unref (dw->builder);
1206 g_object_unref (dw->var_store);
1207 dw->var_store = NULL;
1212 g_object_unref (dw->data_store);
1213 dw->data_store = NULL;
1216 if (dw->ll.next != NULL)
1218 ll_remove (&dw->ll);
1222 if (G_OBJECT_CLASS (parent_class)->dispose)
1223 G_OBJECT_CLASS (parent_class)->dispose (object);
1227 psppire_data_window_set_property (GObject *object,
1229 const GValue *value,
1232 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1237 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1240 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1246 psppire_data_window_get_property (GObject *object,
1251 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1256 g_value_set_pointer (value, window->dataset);
1259 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1265 psppire_data_window_new (struct dataset *ds)
1269 if (the_session == NULL)
1270 the_session = session_create ();
1274 static int n_datasets;
1277 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1278 ds = dataset_create (the_session, dataset_name);
1279 free (dataset_name);
1281 assert (dataset_session (ds) == the_session);
1285 psppire_data_window_get_type (),
1286 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1287 "description", _("Data Editor"),
1291 if (dataset_name (ds) != NULL)
1292 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1298 psppire_data_window_is_empty (PsppireDataWindow *dw)
1300 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1304 psppire_data_window_iface_init (PsppireWindowIface *iface)
1306 iface->save = save_file;
1307 iface->pick_filename = data_pick_filename;
1308 iface->load = load_file;
1312 psppire_default_data_window (void)
1314 if (ll_is_empty (&all_data_windows))
1315 create_data_window ();
1316 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1320 psppire_data_window_set_default (PsppireDataWindow *pdw)
1322 ll_remove (&pdw->ll);
1323 ll_push_head (&all_data_windows, &pdw->ll);
1327 psppire_data_window_undefault (PsppireDataWindow *pdw)
1329 ll_remove (&pdw->ll);
1330 ll_push_tail (&all_data_windows, &pdw->ll);
1334 psppire_data_window_for_dataset (struct dataset *ds)
1336 PsppireDataWindow *pdw;
1338 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1339 if (pdw->dataset == ds)
1346 create_data_window (void)
1348 gtk_widget_show (psppire_data_window_new (NULL));