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/c-strcase.h"
67 #include "gl/xvasprintf.h"
70 #define _(msgid) gettext (msgid)
71 #define N_(msgid) msgid
73 struct session *the_session;
74 struct ll_list all_data_windows = LL_INITIALIZER (all_data_windows);
76 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
77 static void psppire_data_window_init (PsppireDataWindow *data_editor);
80 static void psppire_data_window_iface_init (PsppireWindowIface *iface);
82 static void psppire_data_window_dispose (GObject *object);
83 static void psppire_data_window_set_property (GObject *object,
87 static void psppire_data_window_get_property (GObject *object,
93 psppire_data_window_get_type (void)
95 static GType psppire_data_window_type = 0;
97 if (!psppire_data_window_type)
99 static const GTypeInfo psppire_data_window_info =
101 sizeof (PsppireDataWindowClass),
104 (GClassInitFunc)psppire_data_window_class_init,
105 (GClassFinalizeFunc) NULL,
107 sizeof (PsppireDataWindow),
109 (GInstanceInitFunc) psppire_data_window_init,
112 static const GInterfaceInfo window_interface_info =
114 (GInterfaceInitFunc) psppire_data_window_iface_init,
119 psppire_data_window_type =
120 g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireDataWindow",
121 &psppire_data_window_info, 0);
124 g_type_add_interface_static (psppire_data_window_type,
125 PSPPIRE_TYPE_WINDOW_MODEL,
126 &window_interface_info);
129 return psppire_data_window_type;
132 static GObjectClass *parent_class ;
139 psppire_data_window_class_init (PsppireDataWindowClass *class)
141 GObjectClass *object_class = G_OBJECT_CLASS (class);
143 parent_class = g_type_class_peek_parent (class);
145 object_class->dispose = psppire_data_window_dispose;
146 object_class->set_property = psppire_data_window_set_property;
147 object_class->get_property = psppire_data_window_get_property;
149 g_object_class_install_property (
150 object_class, PROP_DATASET,
151 g_param_spec_pointer ("dataset", "Dataset",
152 "'struct datset *' represented by the window",
153 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
157 set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
159 GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
161 gtk_action_set_sensitive (edit_paste, x);
165 set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
167 GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
168 GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
170 gtk_action_set_sensitive (edit_copy, x);
171 gtk_action_set_sensitive (edit_cut, x);
174 /* Run the EXECUTE command. */
176 execute (PsppireDataWindow *dw)
178 execute_const_syntax_string (dw, "EXECUTE.");
182 transformation_change_callback (bool transformations_pending,
185 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
187 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
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 PsppireDict *dict = NULL;
222 struct variable *var ;
225 g_object_get (de->data_editor, "var-store", &vs, NULL);
226 g_object_get (vs, "dictionary", &dict, NULL);
228 var = psppire_dict_get_variable (dict, filter_index);
230 text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
232 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
238 /* Callback for when the dictionary changes its split variables */
240 on_split_change (PsppireDict *dict, gpointer data)
242 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
244 size_t n_split_vars = dict_get_split_cnt (dict->dict);
246 GtkWidget *split_status_area =
247 get_widget_assert (de->builder, "split-file-status-area");
249 if ( n_split_vars == 0 )
251 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
257 const struct variable *const * split_vars =
258 dict_get_split_vars (dict->dict);
260 text = g_string_new (_("Split by "));
262 for (i = 0 ; i < n_split_vars - 1; ++i )
264 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
266 g_string_append (text, var_get_name (split_vars[i]));
268 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
270 g_string_free (text, TRUE);
277 /* Callback for when the dictionary changes its weights */
279 on_weight_change (GObject *o, gint weight_index, gpointer data)
281 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
283 GtkWidget *weight_status_area =
284 get_widget_assert (de->builder, "weight-status-area");
286 if ( weight_index == -1 )
288 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
292 struct variable *var ;
293 PsppireVarStore *vs = NULL;
294 PsppireDict *dict = NULL;
297 g_object_get (de->data_editor, "var-store", &vs, NULL);
298 g_object_get (vs, "dictionary", &dict, NULL);
300 var = psppire_dict_get_variable (dict, weight_index);
302 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
304 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
312 dump_rm (GtkRecentManager *rm)
314 GList *items = gtk_recent_manager_get_items (rm);
318 g_print ("Recent Items:\n");
319 for (i = items; i; i = i->next)
321 GtkRecentInfo *ri = i->data;
323 g_print ("Item: %s (Mime: %s) (Desc: %s) (URI: %s)\n",
324 gtk_recent_info_get_short_name (ri),
325 gtk_recent_info_get_mime_type (ri),
326 gtk_recent_info_get_description (ri),
327 gtk_recent_info_get_uri (ri)
331 gtk_recent_info_unref (ri);
339 name_has_por_suffix (const gchar *name)
341 size_t length = strlen (name);
342 return length > 4 && !c_strcasecmp (&name[length - 4], ".por");
346 name_has_sav_suffix (const gchar *name)
348 size_t length = strlen (name);
349 return length > 4 && !c_strcasecmp (&name[length - 4], ".sav");
352 /* Returns true if NAME has a suffix which might denote a PSPP file */
354 name_has_suffix (const gchar *name)
356 return name_has_por_suffix (name) || name_has_sav_suffix (name);
360 load_file (PsppireWindow *de, const gchar *file_name)
362 gchar *utf8_file_name;
363 struct string filename;
367 ds_init_empty (&filename);
369 utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
371 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
373 g_free (utf8_file_name);
375 syntax = g_strdup_printf ("GET FILE=%s.", ds_cstr (&filename));
376 ds_destroy (&filename);
378 ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
379 lex_reader_for_string (syntax));
386 /* Save DE to file */
388 save_file (PsppireWindow *w)
390 const gchar *file_name = NULL;
391 gchar *utf8_file_name = NULL;
393 struct string filename ;
394 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
397 file_name = psppire_window_get_filename (w);
399 fnx = g_string_new (file_name);
401 if ( ! name_has_suffix (fnx->str))
403 if ( de->save_as_portable)
404 g_string_append (fnx, ".por");
406 g_string_append (fnx, ".sav");
409 ds_init_empty (&filename);
411 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
413 g_string_free (fnx, TRUE);
415 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
416 g_free (utf8_file_name);
418 syntax = g_strdup_printf ("%s OUTFILE=%s.",
419 de->save_as_portable ? "EXPORT" : "SAVE",
420 ds_cstr (&filename));
422 ds_destroy (&filename);
424 g_free (execute_syntax_string (de, syntax));
429 insert_case (PsppireDataWindow *dw)
431 psppire_data_editor_insert_case (dw->data_editor);
435 on_insert_variable (PsppireDataWindow *dw)
437 psppire_data_editor_insert_variable (dw->data_editor);
442 display_dict (PsppireDataWindow *de)
444 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
448 sysfile_info (PsppireDataWindow *de)
450 GtkWidget *dialog = psppire_window_file_chooser_dialog (PSPPIRE_WINDOW (de));
452 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
454 struct string filename;
456 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
458 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
463 ds_init_empty (&filename);
465 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
467 g_free (utf8_file_name);
469 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
470 g_free (execute_syntax_string (de, syntax));
473 gtk_widget_destroy (dialog);
477 /* PsppireWindow 'pick_filename' callback: prompt for a filename to save as. */
479 data_pick_filename (PsppireWindow *window)
481 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
482 GtkWidget *button_sys;
484 gtk_file_chooser_dialog_new (_("Save"),
486 GTK_FILE_CHOOSER_ACTION_SAVE,
487 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
488 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
491 GtkFileFilter *filter = gtk_file_filter_new ();
492 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
493 gtk_file_filter_add_pattern (filter, "*.sav");
494 gtk_file_filter_add_pattern (filter, "*.SAV");
495 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
497 filter = gtk_file_filter_new ();
498 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
499 gtk_file_filter_add_pattern (filter, "*.por");
500 gtk_file_filter_add_pattern (filter, "*.POR");
501 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
503 filter = gtk_file_filter_new ();
504 gtk_file_filter_set_name (filter, _("All Files"));
505 gtk_file_filter_add_pattern (filter, "*");
506 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
509 GtkWidget *button_por;
510 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
512 gtk_radio_button_new_with_label (NULL, _("System File"));
515 gtk_radio_button_new_with_label
516 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
519 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
520 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
522 gtk_widget_show_all (vbox);
524 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
527 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
530 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
532 case GTK_RESPONSE_ACCEPT:
537 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
540 de->save_as_portable =
541 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
543 if ( ! name_has_suffix (filename->str))
545 if ( de->save_as_portable)
546 g_string_append (filename, ".por");
548 g_string_append (filename, ".sav");
551 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
553 g_string_free (filename, TRUE);
560 gtk_widget_destroy (dialog);
564 confirm_delete_dataset (PsppireDataWindow *de,
565 const char *old_dataset,
566 const char *new_dataset,
567 const char *existing_dataset)
572 dialog = gtk_message_dialog_new (
573 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
574 _("Delete Existing Dataset?"));
576 gtk_message_dialog_format_secondary_text (
577 GTK_MESSAGE_DIALOG (dialog),
578 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
579 "dataset named \"%s\". Are you sure that you want to do this?"),
580 old_dataset, new_dataset, existing_dataset);
582 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
583 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
584 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
587 g_object_set (dialog, "icon-name", "psppicon", NULL);
589 result = gtk_dialog_run (GTK_DIALOG (dialog));
591 gtk_widget_destroy (dialog);
593 return result == GTK_RESPONSE_OK;
597 on_rename_dataset (PsppireDataWindow *de)
599 struct dataset *ds = de->dataset;
600 struct session *session = dataset_session (ds);
601 const char *old_name = dataset_name (ds);
602 struct dataset *existing_dataset;
606 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
608 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
612 if (new_name == NULL)
615 existing_dataset = session_lookup_dataset (session, new_name);
616 if (existing_dataset == NULL || existing_dataset == ds
617 || confirm_delete_dataset (de, old_name, new_name,
618 dataset_name (existing_dataset)))
619 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
626 on_edit_paste (PsppireDataWindow *de)
628 psppire_data_editor_clip_paste (de->data_editor);
632 on_edit_copy (PsppireDataWindow *de)
634 psppire_data_editor_clip_copy (de->data_editor);
640 on_edit_cut (PsppireDataWindow *de)
642 psppire_data_editor_clip_cut (de->data_editor);
647 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
649 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
651 if ( gtk_toggle_action_get_active (action))
652 gtk_widget_show (statusbar);
654 gtk_widget_hide (statusbar);
659 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
661 const gboolean grid_visible = gtk_toggle_action_get_active (action);
663 psppire_data_editor_show_grid (de->data_editor, grid_visible);
667 data_view_activate (PsppireDataWindow *de)
669 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
674 variable_view_activate (PsppireDataWindow *de)
676 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
681 fonts_activate (PsppireDataWindow *de)
683 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
684 PangoFontDescription *current_font;
687 gtk_font_selection_dialog_new (_("Font Selection"));
690 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
691 font_name = pango_font_description_to_string (current_font);
693 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
697 gtk_window_set_transient_for (GTK_WINDOW (dialog),
698 GTK_WINDOW (toplevel));
700 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
702 const gchar *font = gtk_font_selection_dialog_get_font_name
703 (GTK_FONT_SELECTION_DIALOG (dialog));
705 PangoFontDescription* font_desc =
706 pango_font_description_from_string (font);
708 psppire_data_editor_set_font (de->data_editor, font_desc);
711 gtk_widget_hide (dialog);
716 /* Callback for the value labels action */
718 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
720 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
724 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
726 psppire_data_editor_split_window (de->data_editor,
727 gtk_toggle_action_get_active (ta));
732 file_quit (PsppireDataWindow *de)
734 /* FIXME: Need to be more intelligent here.
735 Give the user the opportunity to save any unsaved data.
742 on_recent_data_select (GtkMenuShell *menushell,
743 PsppireWindow *window)
748 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
750 file = g_filename_from_uri (uri, NULL, NULL);
754 open_data_window (window, file);
760 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
767 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
769 file = g_filename_from_uri (uri, NULL, NULL);
773 se = psppire_syntax_window_new ();
775 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
776 gtk_widget_show (se);
778 gtk_widget_destroy (se);
785 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
787 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
789 gtk_action_set_visible (de->delete_cases, case_num != -1);
794 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
796 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
798 gtk_action_set_visible (de->delete_variables, var != -1);
801 /* Callback for when the datasheet/varsheet is selected */
803 on_switch_sheet (GtkNotebook *notebook,
804 GtkNotebookPage *page,
808 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
810 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
812 GtkWidget *view_data =
813 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
815 GtkWidget *view_variables =
816 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
820 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
821 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
823 gtk_action_set_sensitive (de->insert_variable, TRUE);
824 gtk_action_set_sensitive (de->insert_case, FALSE);
825 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
827 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
828 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
829 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
830 gtk_action_set_sensitive (de->insert_case, TRUE);
833 g_assert_not_reached ();
838 update_paste_menuitem (de, page_num);
845 set_unsaved (gpointer w)
847 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
851 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
852 Returns a pointer to the action
855 connect_action (PsppireDataWindow *dw, const char *action_name,
858 GtkAction *action = get_action_assert (dw->builder, action_name);
860 g_signal_connect_swapped (action, "activate", handler, dw);
865 /* Initializes as much of a PsppireDataWindow as we can and must before the
866 dataset has been set.
868 In particular, the 'menu' member is required in case the "filename" property
869 is set before the "dataset" property: otherwise PsppireWindow will try to
870 modify the menu as part of the "filename" property_set() function and end up
871 with a Gtk-CRITICAL since 'menu' is NULL. */
873 psppire_data_window_init (PsppireDataWindow *de)
877 de->builder = builder_new ("data-editor.ui");
879 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
881 PSPPIRE_WINDOW (de)->menu =
882 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
886 psppire_data_window_finish_init (PsppireDataWindow *de,
889 static const struct dataset_callbacks cbs =
891 set_unsaved, /* changed */
892 transformation_change_callback, /* transformations_changed */
901 GtkWidget *box = gtk_vbox_new (FALSE, 0);
904 dict = psppire_dict_new_from_dict (dataset_dict (ds));
905 de->var_store = psppire_var_store_new (dict);
906 de->data_store = psppire_data_store_new (dict);
907 psppire_data_store_set_reader (de->data_store, NULL);
909 menubar = get_widget_assert (de->builder, "menubar");
910 hb = get_widget_assert (de->builder, "handlebox1");
911 sb = get_widget_assert (de->builder, "status-bar");
914 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
917 g_signal_connect_swapped (de->data_store, "case-changed",
918 G_CALLBACK (set_unsaved), de);
920 g_signal_connect_swapped (de->data_store, "case-inserted",
921 G_CALLBACK (set_unsaved), de);
923 g_signal_connect_swapped (de->data_store, "cases-deleted",
924 G_CALLBACK (set_unsaved), de);
926 dataset_set_callbacks (de->dataset, &cbs, de);
928 connect_help (de->builder);
930 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
931 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
932 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
933 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
935 gtk_container_add (GTK_CONTAINER (de), box);
937 set_cut_copy_menuitem_sensitivity (de, FALSE);
939 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
940 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
943 set_paste_menuitem_sensitivity (de, FALSE);
945 g_signal_connect_swapped (de->data_editor, "data-available-changed",
946 G_CALLBACK (set_paste_menuitem_sensitivity), de);
948 g_signal_connect (dict, "weight-changed",
949 G_CALLBACK (on_weight_change),
952 g_signal_connect (dict, "filter-changed",
953 G_CALLBACK (on_filter_change),
956 g_signal_connect (dict, "split-changed",
957 G_CALLBACK (on_split_change),
961 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
963 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
965 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
967 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
969 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
971 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
973 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
975 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
977 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
979 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
981 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
983 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
985 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
987 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
989 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
992 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
994 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
996 gtk_action_set_visible (de->delete_cases, FALSE);
1001 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1003 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1005 gtk_action_set_visible (de->delete_variables, FALSE);
1009 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1011 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1013 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1015 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1017 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1019 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1021 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1023 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1026 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1028 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1030 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1032 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1034 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1036 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1038 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1040 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1042 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1044 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1046 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1048 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1050 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1052 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1054 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1056 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1058 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1060 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1062 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1064 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1066 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1070 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1072 GtkWidget *recent_data =
1073 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1075 GtkWidget *recent_files =
1076 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1079 GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
1080 gtk_recent_manager_get_default ());
1082 GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
1083 gtk_recent_manager_get_default ());
1086 GtkRecentFilter *filter = gtk_recent_filter_new ();
1088 gtk_recent_filter_add_pattern (filter, "*.sav");
1089 gtk_recent_filter_add_pattern (filter, "*.SAV");
1090 gtk_recent_filter_add_pattern (filter, "*.por");
1091 gtk_recent_filter_add_pattern (filter, "*.POR");
1093 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1095 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1098 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1101 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1104 GtkRecentFilter *filter = gtk_recent_filter_new ();
1106 gtk_recent_filter_add_pattern (filter, "*.sps");
1107 gtk_recent_filter_add_pattern (filter, "*.SPS");
1109 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1111 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1114 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1116 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1120 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1123 g_signal_connect (de->data_editor,
1125 G_CALLBACK (enable_delete_cases),
1128 g_signal_connect (de->data_editor,
1129 "variables-selected",
1130 G_CALLBACK (enable_delete_variables),
1134 g_signal_connect (de->data_editor,
1136 G_CALLBACK (on_switch_sheet), de);
1138 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1139 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1141 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1143 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1145 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1147 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1149 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1151 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1153 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1155 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1157 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1160 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1162 merge_help_menu (uim);
1166 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1167 "datasheet-cases-popup");
1169 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1170 "varsheet-variable-popup");
1172 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1173 "datasheet-variable-popup");
1175 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1176 G_CALLBACK (psppire_data_editor_sort_ascending),
1179 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1180 G_CALLBACK (psppire_data_editor_sort_descending),
1183 g_object_set (de->data_editor,
1184 "datasheet-column-menu", data_sheet_variable_popup_menu,
1185 "datasheet-row-menu", data_sheet_cases_popup_menu,
1186 "varsheet-row-menu", var_sheet_variable_popup_menu,
1190 gtk_widget_show (GTK_WIDGET (de->data_editor));
1191 gtk_widget_show (box);
1193 ll_push_head (&all_data_windows, &de->ll);
1197 psppire_data_window_dispose (GObject *object)
1199 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1201 if (dw->builder != NULL)
1203 g_object_unref (dw->builder);
1209 g_object_unref (dw->var_store);
1210 dw->var_store = NULL;
1215 g_object_unref (dw->data_store);
1216 dw->data_store = NULL;
1219 if (dw->ll.next != NULL)
1221 ll_remove (&dw->ll);
1225 if (G_OBJECT_CLASS (parent_class)->dispose)
1226 G_OBJECT_CLASS (parent_class)->dispose (object);
1230 psppire_data_window_set_property (GObject *object,
1232 const GValue *value,
1235 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1240 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1243 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1249 psppire_data_window_get_property (GObject *object,
1254 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1259 g_value_set_pointer (value, window->dataset);
1262 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1268 psppire_data_window_new (struct dataset *ds)
1272 if (the_session == NULL)
1273 the_session = session_create ();
1277 static int n_datasets;
1280 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1281 ds = dataset_create (the_session, dataset_name);
1282 free (dataset_name);
1284 assert (dataset_session (ds) == the_session);
1288 psppire_data_window_get_type (),
1289 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1290 "description", _("Data Editor"),
1294 if (dataset_name (ds) != NULL)
1295 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1301 psppire_data_window_is_empty (PsppireDataWindow *dw)
1303 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1307 psppire_data_window_iface_init (PsppireWindowIface *iface)
1309 iface->save = save_file;
1310 iface->pick_filename = data_pick_filename;
1311 iface->load = load_file;
1315 psppire_default_data_window (void)
1317 if (ll_is_empty (&all_data_windows))
1318 create_data_window ();
1319 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1323 psppire_data_window_set_default (PsppireDataWindow *pdw)
1325 ll_remove (&pdw->ll);
1326 ll_push_head (&all_data_windows, &pdw->ll);
1330 psppire_data_window_undefault (PsppireDataWindow *pdw)
1332 ll_remove (&pdw->ll);
1333 ll_push_tail (&all_data_windows, &pdw->ll);
1337 psppire_data_window_for_dataset (struct dataset *ds)
1339 PsppireDataWindow *pdw;
1341 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1342 if (pdw->dataset == ds)
1349 create_data_window (void)
1351 gtk_widget_show (psppire_data_window_new (NULL));
1355 open_data_window (PsppireWindow *victim, const char *file_name)
1359 if (PSPPIRE_IS_DATA_WINDOW (victim)
1360 && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
1361 window = GTK_WIDGET (victim);
1363 window = psppire_data_window_new (NULL);
1365 psppire_window_load (PSPPIRE_WINDOW (window), file_name);
1366 gtk_widget_show (window);