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 "libpspp/str.h"
27 #include "ui/gui/aggregate-dialog.h"
28 #include "ui/gui/binomial-dialog.h"
29 #include "ui/gui/chi-square-dialog.h"
30 #include "ui/gui/comments-dialog.h"
31 #include "ui/gui/compute-dialog.h"
32 #include "ui/gui/correlation-dialog.h"
33 #include "ui/gui/count-dialog.h"
34 #include "ui/gui/crosstabs-dialog.h"
35 #include "ui/gui/descriptives-dialog.h"
36 #include "ui/gui/entry-dialog.h"
37 #include "ui/gui/examine-dialog.h"
38 #include "ui/gui/executor.h"
39 #include "ui/gui/factor-dialog.h"
40 #include "ui/gui/find-dialog.h"
41 #include "ui/gui/frequencies-dialog.h"
42 #include "ui/gui/goto-case-dialog.h"
43 #include "ui/gui/help-menu.h"
44 #include "ui/gui/helper.h"
45 #include "ui/gui/k-related-dialog.h"
46 #include "ui/gui/npar-two-sample-related.h"
47 #include "ui/gui/oneway-anova-dialog.h"
48 #include "ui/gui/psppire-data-window.h"
49 #include "ui/gui/psppire-syntax-window.h"
50 #include "ui/gui/psppire-window.h"
51 #include "ui/gui/psppire.h"
52 #include "ui/gui/rank-dialog.h"
53 #include "ui/gui/recode-dialog.h"
54 #include "ui/gui/regression-dialog.h"
55 #include "ui/gui/reliability-dialog.h"
56 #include "ui/gui/roc-dialog.h"
57 #include "ui/gui/select-cases-dialog.h"
58 #include "ui/gui/sort-cases-dialog.h"
59 #include "ui/gui/split-file-dialog.h"
60 #include "ui/gui/t-test-independent-samples-dialog.h"
61 #include "ui/gui/t-test-one-sample.h"
62 #include "ui/gui/t-test-paired-samples.h"
63 #include "ui/gui/text-data-import-dialog.h"
64 #include "ui/gui/transpose-dialog.h"
65 #include "ui/gui/variable-info-dialog.h"
66 #include "ui/gui/weight-cases-dialog.h"
67 #include "ui/syntax-gen.h"
69 #include "gl/c-strcase.h"
70 #include "gl/c-strcasestr.h"
71 #include "gl/xvasprintf.h"
74 #define _(msgid) gettext (msgid)
75 #define N_(msgid) msgid
77 struct session *the_session;
78 struct ll_list all_data_windows = LL_INITIALIZER (all_data_windows);
80 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
81 static void psppire_data_window_init (PsppireDataWindow *data_editor);
84 static void psppire_data_window_iface_init (PsppireWindowIface *iface);
86 static void psppire_data_window_dispose (GObject *object);
87 static void psppire_data_window_set_property (GObject *object,
91 static void psppire_data_window_get_property (GObject *object,
97 psppire_data_window_get_type (void)
99 static GType psppire_data_window_type = 0;
101 if (!psppire_data_window_type)
103 static const GTypeInfo psppire_data_window_info =
105 sizeof (PsppireDataWindowClass),
108 (GClassInitFunc)psppire_data_window_class_init,
109 (GClassFinalizeFunc) NULL,
111 sizeof (PsppireDataWindow),
113 (GInstanceInitFunc) psppire_data_window_init,
116 static const GInterfaceInfo window_interface_info =
118 (GInterfaceInitFunc) psppire_data_window_iface_init,
123 psppire_data_window_type =
124 g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireDataWindow",
125 &psppire_data_window_info, 0);
128 g_type_add_interface_static (psppire_data_window_type,
129 PSPPIRE_TYPE_WINDOW_MODEL,
130 &window_interface_info);
133 return psppire_data_window_type;
136 static GObjectClass *parent_class ;
143 psppire_data_window_class_init (PsppireDataWindowClass *class)
145 GObjectClass *object_class = G_OBJECT_CLASS (class);
147 parent_class = g_type_class_peek_parent (class);
149 object_class->dispose = psppire_data_window_dispose;
150 object_class->set_property = psppire_data_window_set_property;
151 object_class->get_property = psppire_data_window_get_property;
153 g_object_class_install_property (
154 object_class, PROP_DATASET,
155 g_param_spec_pointer ("dataset", "Dataset",
156 "'struct datset *' represented by the window",
157 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
161 set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
163 GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
165 gtk_action_set_sensitive (edit_paste, x);
169 set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
171 GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
172 GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
174 gtk_action_set_sensitive (edit_copy, x);
175 gtk_action_set_sensitive (edit_cut, x);
178 /* Run the EXECUTE command. */
180 execute (PsppireDataWindow *dw)
182 execute_const_syntax_string (dw, "EXECUTE.");
186 transformation_change_callback (bool transformations_pending,
189 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
191 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
193 GtkWidget *menuitem =
194 gtk_ui_manager_get_widget (uim,"/ui/menubar/transform/transform_run-pending");
196 GtkWidget *status_label =
197 get_widget_assert (de->builder, "case-counter-area");
199 gtk_widget_set_sensitive (menuitem, transformations_pending);
202 if ( transformations_pending)
203 gtk_label_set_text (GTK_LABEL (status_label),
204 _("Transformations Pending"));
206 gtk_label_set_text (GTK_LABEL (status_label), "");
209 /* Callback for when the dictionary changes its filter variable */
211 on_filter_change (GObject *o, gint filter_index, gpointer data)
213 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
215 GtkWidget *filter_status_area =
216 get_widget_assert (de->builder, "filter-use-status-area");
218 if ( filter_index == -1 )
220 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
224 PsppireVarStore *vs = NULL;
225 PsppireDict *dict = NULL;
226 struct variable *var ;
229 g_object_get (de->data_editor, "var-store", &vs, NULL);
230 g_object_get (vs, "dictionary", &dict, NULL);
232 var = psppire_dict_get_variable (dict, filter_index);
234 text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
236 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
242 /* Callback for when the dictionary changes its split variables */
244 on_split_change (PsppireDict *dict, gpointer data)
246 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
248 size_t n_split_vars = dict_get_split_cnt (dict->dict);
250 GtkWidget *split_status_area =
251 get_widget_assert (de->builder, "split-file-status-area");
253 if ( n_split_vars == 0 )
255 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
261 const struct variable *const * split_vars =
262 dict_get_split_vars (dict->dict);
264 text = g_string_new (_("Split by "));
266 for (i = 0 ; i < n_split_vars - 1; ++i )
268 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
270 g_string_append (text, var_get_name (split_vars[i]));
272 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
274 g_string_free (text, TRUE);
281 /* Callback for when the dictionary changes its weights */
283 on_weight_change (GObject *o, gint weight_index, gpointer data)
285 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
287 GtkWidget *weight_status_area =
288 get_widget_assert (de->builder, "weight-status-area");
290 if ( weight_index == -1 )
292 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
296 struct variable *var ;
297 PsppireVarStore *vs = NULL;
298 PsppireDict *dict = NULL;
301 g_object_get (de->data_editor, "var-store", &vs, NULL);
302 g_object_get (vs, "dictionary", &dict, NULL);
304 var = psppire_dict_get_variable (dict, weight_index);
306 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
308 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
316 dump_rm (GtkRecentManager *rm)
318 GList *items = gtk_recent_manager_get_items (rm);
322 g_print ("Recent Items:\n");
323 for (i = items; i; i = i->next)
325 GtkRecentInfo *ri = i->data;
327 g_print ("Item: %s (Mime: %s) (Desc: %s) (URI: %s)\n",
328 gtk_recent_info_get_short_name (ri),
329 gtk_recent_info_get_mime_type (ri),
330 gtk_recent_info_get_description (ri),
331 gtk_recent_info_get_uri (ri)
335 gtk_recent_info_unref (ri);
343 name_has_por_suffix (const gchar *name)
345 size_t length = strlen (name);
346 return length > 4 && !c_strcasecmp (&name[length - 4], ".por");
350 name_has_sav_suffix (const gchar *name)
352 size_t length = strlen (name);
353 return length > 4 && !c_strcasecmp (&name[length - 4], ".sav");
356 /* Returns true if NAME has a suffix which might denote a PSPP file */
358 name_has_suffix (const gchar *name)
360 return name_has_por_suffix (name) || name_has_sav_suffix (name);
364 load_file (PsppireWindow *de, const gchar *file_name)
366 struct string filename;
367 gchar *utf8_file_name;
368 const char *mime_type;
372 ds_init_empty (&filename);
374 utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
376 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
378 g_free (utf8_file_name);
380 syntax = g_strdup_printf ("GET FILE=%s.", ds_cstr (&filename));
381 ds_destroy (&filename);
383 ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
384 lex_reader_for_string (syntax));
387 mime_type = (name_has_por_suffix (file_name)
388 ? "application/x-spss-por"
389 : "application/x-spss-sav");
391 add_most_recent (file_name, mime_type);
396 /* Save DE to file */
398 save_file (PsppireWindow *w)
400 const gchar *file_name = NULL;
401 gchar *utf8_file_name = NULL;
403 struct string filename ;
404 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
407 file_name = psppire_window_get_filename (w);
409 fnx = g_string_new (file_name);
411 if ( ! name_has_suffix (fnx->str))
413 if ( de->save_as_portable)
414 g_string_append (fnx, ".por");
416 g_string_append (fnx, ".sav");
419 ds_init_empty (&filename);
421 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
423 g_string_free (fnx, TRUE);
425 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
426 g_free (utf8_file_name);
428 syntax = g_strdup_printf ("%s OUTFILE=%s.",
429 de->save_as_portable ? "EXPORT" : "SAVE",
430 ds_cstr (&filename));
432 ds_destroy (&filename);
434 g_free (execute_syntax_string (de, syntax));
439 insert_case (PsppireDataWindow *dw)
441 psppire_data_editor_insert_case (dw->data_editor);
445 on_insert_variable (PsppireDataWindow *dw)
447 psppire_data_editor_insert_variable (dw->data_editor);
452 display_dict (PsppireDataWindow *de)
454 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
458 sysfile_info (PsppireDataWindow *de)
460 GtkWidget *dialog = psppire_window_file_chooser_dialog (PSPPIRE_WINDOW (de));
462 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
464 struct string filename;
466 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
468 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
473 ds_init_empty (&filename);
475 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
477 g_free (utf8_file_name);
479 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
480 g_free (execute_syntax_string (de, syntax));
483 gtk_widget_destroy (dialog);
487 /* PsppireWindow 'pick_filename' callback: prompt for a filename to save as. */
489 data_pick_filename (PsppireWindow *window)
491 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
492 GtkWidget *button_sys;
494 gtk_file_chooser_dialog_new (_("Save"),
496 GTK_FILE_CHOOSER_ACTION_SAVE,
497 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
498 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
501 GtkFileFilter *filter = gtk_file_filter_new ();
502 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
503 gtk_file_filter_add_pattern (filter, "*.sav");
504 gtk_file_filter_add_pattern (filter, "*.SAV");
505 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
507 filter = gtk_file_filter_new ();
508 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
509 gtk_file_filter_add_pattern (filter, "*.por");
510 gtk_file_filter_add_pattern (filter, "*.POR");
511 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
513 filter = gtk_file_filter_new ();
514 gtk_file_filter_set_name (filter, _("All Files"));
515 gtk_file_filter_add_pattern (filter, "*");
516 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
519 GtkWidget *button_por;
520 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
522 gtk_radio_button_new_with_label (NULL, _("System File"));
525 gtk_radio_button_new_with_label
526 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
529 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
530 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
532 gtk_widget_show_all (vbox);
534 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
537 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
540 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
542 case GTK_RESPONSE_ACCEPT:
547 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
550 de->save_as_portable =
551 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
553 if ( ! name_has_suffix (filename->str))
555 if ( de->save_as_portable)
556 g_string_append (filename, ".por");
558 g_string_append (filename, ".sav");
561 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
563 g_string_free (filename, TRUE);
570 gtk_widget_destroy (dialog);
574 confirm_delete_dataset (PsppireDataWindow *de,
575 const char *old_dataset,
576 const char *new_dataset,
577 const char *existing_dataset)
582 dialog = gtk_message_dialog_new (
583 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
584 _("Delete Existing Dataset?"));
586 gtk_message_dialog_format_secondary_text (
587 GTK_MESSAGE_DIALOG (dialog),
588 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
589 "dataset named \"%s\". Are you sure that you want to do this?"),
590 old_dataset, new_dataset, existing_dataset);
592 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
593 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
594 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
597 g_object_set (dialog, "icon-name", "psppicon", NULL);
599 result = gtk_dialog_run (GTK_DIALOG (dialog));
601 gtk_widget_destroy (dialog);
603 return result == GTK_RESPONSE_OK;
607 on_rename_dataset (PsppireDataWindow *de)
609 struct dataset *ds = de->dataset;
610 struct session *session = dataset_session (ds);
611 const char *old_name = dataset_name (ds);
612 struct dataset *existing_dataset;
616 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
618 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
622 if (new_name == NULL)
625 existing_dataset = session_lookup_dataset (session, new_name);
626 if (existing_dataset == NULL || existing_dataset == ds
627 || confirm_delete_dataset (de, old_name, new_name,
628 dataset_name (existing_dataset)))
629 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
636 on_edit_paste (PsppireDataWindow *de)
638 psppire_data_editor_clip_paste (de->data_editor);
642 on_edit_copy (PsppireDataWindow *de)
644 psppire_data_editor_clip_copy (de->data_editor);
650 on_edit_cut (PsppireDataWindow *de)
652 psppire_data_editor_clip_cut (de->data_editor);
657 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
659 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
661 if ( gtk_toggle_action_get_active (action))
662 gtk_widget_show (statusbar);
664 gtk_widget_hide (statusbar);
669 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
671 const gboolean grid_visible = gtk_toggle_action_get_active (action);
673 psppire_data_editor_show_grid (de->data_editor, grid_visible);
677 data_view_activate (PsppireDataWindow *de)
679 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
684 variable_view_activate (PsppireDataWindow *de)
686 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
691 fonts_activate (PsppireDataWindow *de)
693 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
694 PangoFontDescription *current_font;
697 gtk_font_selection_dialog_new (_("Font Selection"));
700 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
701 font_name = pango_font_description_to_string (current_font);
703 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
707 gtk_window_set_transient_for (GTK_WINDOW (dialog),
708 GTK_WINDOW (toplevel));
710 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
712 const gchar *font = gtk_font_selection_dialog_get_font_name
713 (GTK_FONT_SELECTION_DIALOG (dialog));
715 PangoFontDescription* font_desc =
716 pango_font_description_from_string (font);
718 psppire_data_editor_set_font (de->data_editor, font_desc);
721 gtk_widget_hide (dialog);
726 /* Callback for the value labels action */
728 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
730 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
734 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
736 psppire_data_editor_split_window (de->data_editor,
737 gtk_toggle_action_get_active (ta));
742 file_quit (PsppireDataWindow *de)
744 /* FIXME: Need to be more intelligent here.
745 Give the user the opportunity to save any unsaved data.
752 on_recent_data_select (GtkMenuShell *menushell,
753 PsppireWindow *window)
758 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
760 file = g_filename_from_uri (uri, NULL, NULL);
764 open_data_window (window, file);
770 charset_from_mime_type (const char *mime_type)
776 if (mime_type == NULL)
779 charset = c_strcasestr (mime_type, "charset=");
787 /* Parse a "quoted-string" as defined by RFC 822. */
788 for (p++; *p != '\0' && *p != '"'; p++)
791 ds_put_byte (&s, *p);
792 else if (*++p != '\0')
793 ds_put_byte (&s, *p);
798 /* Parse a "token" as defined by RFC 2045. */
799 while (*p > 32 && *p < 127 && strchr ("()<>@,;:\\\"/[]?=", *p) == NULL)
800 ds_put_byte (&s, *p++);
802 if (!ds_is_empty (&s))
803 return ds_steal_cstr (&s);
810 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
817 /* Get the file name and its encoding. */
818 item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (menushell));
819 file = g_filename_from_uri (gtk_recent_info_get_uri (item), NULL, NULL);
820 encoding = charset_from_mime_type (gtk_recent_info_get_mime_type (item));
821 gtk_recent_info_unref (item);
823 se = psppire_syntax_window_new (encoding);
827 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
828 gtk_widget_show (se);
830 gtk_widget_destroy (se);
837 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
839 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
841 gtk_action_set_visible (de->delete_cases, case_num != -1);
846 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
848 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
850 gtk_action_set_visible (de->delete_variables, var != -1);
853 /* Callback for when the datasheet/varsheet is selected */
855 on_switch_sheet (GtkNotebook *notebook,
856 GtkNotebookPage *page,
860 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
862 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
864 GtkWidget *view_data =
865 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
867 GtkWidget *view_variables =
868 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
872 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
873 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
875 gtk_action_set_sensitive (de->insert_variable, TRUE);
876 gtk_action_set_sensitive (de->insert_case, FALSE);
877 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
879 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
880 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
881 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
882 gtk_action_set_sensitive (de->insert_case, TRUE);
885 g_assert_not_reached ();
890 update_paste_menuitem (de, page_num);
897 set_unsaved (gpointer w)
899 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
903 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
904 Returns a pointer to the action
907 connect_action (PsppireDataWindow *dw, const char *action_name,
910 GtkAction *action = get_action_assert (dw->builder, action_name);
912 g_signal_connect_swapped (action, "activate", handler, dw);
917 /* Initializes as much of a PsppireDataWindow as we can and must before the
918 dataset has been set.
920 In particular, the 'menu' member is required in case the "filename" property
921 is set before the "dataset" property: otherwise PsppireWindow will try to
922 modify the menu as part of the "filename" property_set() function and end up
923 with a Gtk-CRITICAL since 'menu' is NULL. */
925 psppire_data_window_init (PsppireDataWindow *de)
929 de->builder = builder_new ("data-editor.ui");
931 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
933 PSPPIRE_WINDOW (de)->menu =
934 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
938 psppire_data_window_finish_init (PsppireDataWindow *de,
941 static const struct dataset_callbacks cbs =
943 set_unsaved, /* changed */
944 transformation_change_callback, /* transformations_changed */
953 GtkWidget *box = gtk_vbox_new (FALSE, 0);
956 dict = psppire_dict_new_from_dict (dataset_dict (ds));
957 de->var_store = psppire_var_store_new (dict);
958 de->data_store = psppire_data_store_new (dict);
959 psppire_data_store_set_reader (de->data_store, NULL);
961 menubar = get_widget_assert (de->builder, "menubar");
962 hb = get_widget_assert (de->builder, "handlebox1");
963 sb = get_widget_assert (de->builder, "status-bar");
966 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
969 g_signal_connect_swapped (de->data_store, "case-changed",
970 G_CALLBACK (set_unsaved), de);
972 g_signal_connect_swapped (de->data_store, "case-inserted",
973 G_CALLBACK (set_unsaved), de);
975 g_signal_connect_swapped (de->data_store, "cases-deleted",
976 G_CALLBACK (set_unsaved), de);
978 dataset_set_callbacks (de->dataset, &cbs, de);
980 connect_help (de->builder);
982 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
983 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
984 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
985 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
987 gtk_container_add (GTK_CONTAINER (de), box);
989 set_cut_copy_menuitem_sensitivity (de, FALSE);
991 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
992 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
995 set_paste_menuitem_sensitivity (de, FALSE);
997 g_signal_connect_swapped (de->data_editor, "data-available-changed",
998 G_CALLBACK (set_paste_menuitem_sensitivity), de);
1000 g_signal_connect (dict, "weight-changed",
1001 G_CALLBACK (on_weight_change),
1004 g_signal_connect (dict, "filter-changed",
1005 G_CALLBACK (on_filter_change),
1008 g_signal_connect (dict, "split-changed",
1009 G_CALLBACK (on_split_change),
1013 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
1015 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
1017 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
1019 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
1021 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
1023 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
1025 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
1027 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
1029 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
1031 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
1033 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
1035 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
1037 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
1039 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
1041 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
1044 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
1046 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
1048 gtk_action_set_visible (de->delete_cases, FALSE);
1053 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1055 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1057 gtk_action_set_visible (de->delete_variables, FALSE);
1061 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1063 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1065 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1067 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1069 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1071 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1073 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1075 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1078 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1080 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1082 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1084 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1086 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1088 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1090 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1092 connect_action (de, "transform_count", G_CALLBACK (count_dialog));
1094 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1096 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1098 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1100 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1102 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1104 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1106 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1108 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1110 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1112 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1114 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1116 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1118 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1120 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1121 connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
1125 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1127 GtkWidget *recent_data =
1128 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1130 GtkWidget *recent_files =
1131 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1134 GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
1135 gtk_recent_manager_get_default ());
1137 GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
1138 gtk_recent_manager_get_default ());
1140 g_object_set (menu_data, "show-tips", TRUE, NULL);
1141 g_object_set (menu_files, "show-tips", TRUE, NULL);
1144 GtkRecentFilter *filter = gtk_recent_filter_new ();
1146 gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
1147 gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
1149 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1151 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1154 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1157 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1160 GtkRecentFilter *filter = gtk_recent_filter_new ();
1162 gtk_recent_filter_add_pattern (filter, "*.sps");
1163 gtk_recent_filter_add_pattern (filter, "*.SPS");
1165 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1167 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1170 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1172 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1176 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1179 g_signal_connect (de->data_editor,
1181 G_CALLBACK (enable_delete_cases),
1184 g_signal_connect (de->data_editor,
1185 "variables-selected",
1186 G_CALLBACK (enable_delete_variables),
1190 g_signal_connect (de->data_editor,
1192 G_CALLBACK (on_switch_sheet), de);
1194 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1195 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1197 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1199 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1201 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1203 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1205 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1207 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1209 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1211 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1213 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1216 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1218 merge_help_menu (uim);
1222 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1223 "datasheet-cases-popup");
1225 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1226 "varsheet-variable-popup");
1228 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1229 "datasheet-variable-popup");
1231 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1232 G_CALLBACK (psppire_data_editor_sort_ascending),
1235 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1236 G_CALLBACK (psppire_data_editor_sort_descending),
1239 g_object_set (de->data_editor,
1240 "datasheet-column-menu", data_sheet_variable_popup_menu,
1241 "datasheet-row-menu", data_sheet_cases_popup_menu,
1242 "varsheet-row-menu", var_sheet_variable_popup_menu,
1246 gtk_widget_show (GTK_WIDGET (de->data_editor));
1247 gtk_widget_show (box);
1249 ll_push_head (&all_data_windows, &de->ll);
1253 psppire_data_window_dispose (GObject *object)
1255 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1257 if (dw->builder != NULL)
1259 g_object_unref (dw->builder);
1265 g_object_unref (dw->var_store);
1266 dw->var_store = NULL;
1271 g_object_unref (dw->data_store);
1272 dw->data_store = NULL;
1275 if (dw->ll.next != NULL)
1277 ll_remove (&dw->ll);
1281 if (G_OBJECT_CLASS (parent_class)->dispose)
1282 G_OBJECT_CLASS (parent_class)->dispose (object);
1286 psppire_data_window_set_property (GObject *object,
1288 const GValue *value,
1291 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1296 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1299 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1305 psppire_data_window_get_property (GObject *object,
1310 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1315 g_value_set_pointer (value, window->dataset);
1318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1324 psppire_data_window_new (struct dataset *ds)
1328 if (the_session == NULL)
1329 the_session = session_create ();
1333 static int n_datasets;
1336 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1337 ds = dataset_create (the_session, dataset_name);
1338 free (dataset_name);
1340 assert (dataset_session (ds) == the_session);
1344 psppire_data_window_get_type (),
1345 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1346 "description", _("Data Editor"),
1350 if (dataset_name (ds) != NULL)
1351 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1357 psppire_data_window_is_empty (PsppireDataWindow *dw)
1359 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1363 psppire_data_window_iface_init (PsppireWindowIface *iface)
1365 iface->save = save_file;
1366 iface->pick_filename = data_pick_filename;
1367 iface->load = load_file;
1371 psppire_default_data_window (void)
1373 if (ll_is_empty (&all_data_windows))
1374 create_data_window ();
1375 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1379 psppire_data_window_set_default (PsppireDataWindow *pdw)
1381 ll_remove (&pdw->ll);
1382 ll_push_head (&all_data_windows, &pdw->ll);
1386 psppire_data_window_undefault (PsppireDataWindow *pdw)
1388 ll_remove (&pdw->ll);
1389 ll_push_tail (&all_data_windows, &pdw->ll);
1393 psppire_data_window_for_dataset (struct dataset *ds)
1395 PsppireDataWindow *pdw;
1397 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1398 if (pdw->dataset == ds)
1405 create_data_window (void)
1407 gtk_widget_show (psppire_data_window_new (NULL));
1411 open_data_window (PsppireWindow *victim, const char *file_name)
1415 if (PSPPIRE_IS_DATA_WINDOW (victim)
1416 && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
1417 window = GTK_WIDGET (victim);
1419 window = psppire_data_window_new (NULL);
1421 psppire_window_load (PSPPIRE_WINDOW (window), file_name);
1422 gtk_widget_show (window);