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");
390 add_most_recent (ds_cstr (&filename), mime_type);
395 /* Save DE to file */
397 save_file (PsppireWindow *w)
399 const gchar *file_name = NULL;
400 gchar *utf8_file_name = NULL;
402 struct string filename ;
403 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
406 file_name = psppire_window_get_filename (w);
408 fnx = g_string_new (file_name);
410 if ( ! name_has_suffix (fnx->str))
412 if ( de->save_as_portable)
413 g_string_append (fnx, ".por");
415 g_string_append (fnx, ".sav");
418 ds_init_empty (&filename);
420 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
422 g_string_free (fnx, TRUE);
424 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
425 g_free (utf8_file_name);
427 syntax = g_strdup_printf ("%s OUTFILE=%s.",
428 de->save_as_portable ? "EXPORT" : "SAVE",
429 ds_cstr (&filename));
431 ds_destroy (&filename);
433 g_free (execute_syntax_string (de, syntax));
438 insert_case (PsppireDataWindow *dw)
440 psppire_data_editor_insert_case (dw->data_editor);
444 on_insert_variable (PsppireDataWindow *dw)
446 psppire_data_editor_insert_variable (dw->data_editor);
451 display_dict (PsppireDataWindow *de)
453 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
457 sysfile_info (PsppireDataWindow *de)
459 GtkWidget *dialog = psppire_window_file_chooser_dialog (PSPPIRE_WINDOW (de));
461 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
463 struct string filename;
465 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
467 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
472 ds_init_empty (&filename);
474 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
476 g_free (utf8_file_name);
478 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
479 g_free (execute_syntax_string (de, syntax));
482 gtk_widget_destroy (dialog);
486 /* PsppireWindow 'pick_filename' callback: prompt for a filename to save as. */
488 data_pick_filename (PsppireWindow *window)
490 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
491 GtkWidget *button_sys;
493 gtk_file_chooser_dialog_new (_("Save"),
495 GTK_FILE_CHOOSER_ACTION_SAVE,
496 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
497 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
500 GtkFileFilter *filter = gtk_file_filter_new ();
501 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
502 gtk_file_filter_add_pattern (filter, "*.sav");
503 gtk_file_filter_add_pattern (filter, "*.SAV");
504 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
506 filter = gtk_file_filter_new ();
507 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
508 gtk_file_filter_add_pattern (filter, "*.por");
509 gtk_file_filter_add_pattern (filter, "*.POR");
510 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
512 filter = gtk_file_filter_new ();
513 gtk_file_filter_set_name (filter, _("All Files"));
514 gtk_file_filter_add_pattern (filter, "*");
515 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
518 GtkWidget *button_por;
519 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
521 gtk_radio_button_new_with_label (NULL, _("System File"));
524 gtk_radio_button_new_with_label
525 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
528 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
529 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
531 gtk_widget_show_all (vbox);
533 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
536 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
539 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
541 case GTK_RESPONSE_ACCEPT:
546 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
549 de->save_as_portable =
550 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
552 if ( ! name_has_suffix (filename->str))
554 if ( de->save_as_portable)
555 g_string_append (filename, ".por");
557 g_string_append (filename, ".sav");
560 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
562 g_string_free (filename, TRUE);
569 gtk_widget_destroy (dialog);
573 confirm_delete_dataset (PsppireDataWindow *de,
574 const char *old_dataset,
575 const char *new_dataset,
576 const char *existing_dataset)
581 dialog = gtk_message_dialog_new (
582 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
583 _("Delete Existing Dataset?"));
585 gtk_message_dialog_format_secondary_text (
586 GTK_MESSAGE_DIALOG (dialog),
587 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
588 "dataset named \"%s\". Are you sure that you want to do this?"),
589 old_dataset, new_dataset, existing_dataset);
591 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
592 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
593 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
596 g_object_set (dialog, "icon-name", "psppicon", NULL);
598 result = gtk_dialog_run (GTK_DIALOG (dialog));
600 gtk_widget_destroy (dialog);
602 return result == GTK_RESPONSE_OK;
606 on_rename_dataset (PsppireDataWindow *de)
608 struct dataset *ds = de->dataset;
609 struct session *session = dataset_session (ds);
610 const char *old_name = dataset_name (ds);
611 struct dataset *existing_dataset;
615 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
617 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
621 if (new_name == NULL)
624 existing_dataset = session_lookup_dataset (session, new_name);
625 if (existing_dataset == NULL || existing_dataset == ds
626 || confirm_delete_dataset (de, old_name, new_name,
627 dataset_name (existing_dataset)))
628 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
635 on_edit_paste (PsppireDataWindow *de)
637 psppire_data_editor_clip_paste (de->data_editor);
641 on_edit_copy (PsppireDataWindow *de)
643 psppire_data_editor_clip_copy (de->data_editor);
649 on_edit_cut (PsppireDataWindow *de)
651 psppire_data_editor_clip_cut (de->data_editor);
656 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
658 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
660 if ( gtk_toggle_action_get_active (action))
661 gtk_widget_show (statusbar);
663 gtk_widget_hide (statusbar);
668 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
670 const gboolean grid_visible = gtk_toggle_action_get_active (action);
672 psppire_data_editor_show_grid (de->data_editor, grid_visible);
676 data_view_activate (PsppireDataWindow *de)
678 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
683 variable_view_activate (PsppireDataWindow *de)
685 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
690 fonts_activate (PsppireDataWindow *de)
692 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
693 PangoFontDescription *current_font;
696 gtk_font_selection_dialog_new (_("Font Selection"));
699 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
700 font_name = pango_font_description_to_string (current_font);
702 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
706 gtk_window_set_transient_for (GTK_WINDOW (dialog),
707 GTK_WINDOW (toplevel));
709 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
711 const gchar *font = gtk_font_selection_dialog_get_font_name
712 (GTK_FONT_SELECTION_DIALOG (dialog));
714 PangoFontDescription* font_desc =
715 pango_font_description_from_string (font);
717 psppire_data_editor_set_font (de->data_editor, font_desc);
720 gtk_widget_hide (dialog);
725 /* Callback for the value labels action */
727 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
729 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
733 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
735 psppire_data_editor_split_window (de->data_editor,
736 gtk_toggle_action_get_active (ta));
741 file_quit (PsppireDataWindow *de)
743 /* FIXME: Need to be more intelligent here.
744 Give the user the opportunity to save any unsaved data.
751 on_recent_data_select (GtkMenuShell *menushell,
752 PsppireWindow *window)
757 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
759 file = g_filename_from_uri (uri, NULL, NULL);
763 open_data_window (window, file);
769 charset_from_mime_type (const char *mime_type)
775 if (mime_type == NULL)
778 charset = c_strcasestr (mime_type, "charset=");
786 /* Parse a "quoted-string" as defined by RFC 822. */
787 for (p++; *p != '\0' && *p != '"'; p++)
790 ds_put_byte (&s, *p);
791 else if (*++p != '\0')
792 ds_put_byte (&s, *p);
797 /* Parse a "token" as defined by RFC 2045. */
798 while (*p > 32 && *p < 127 && strchr ("()<>@,;:\\\"/[]?=", *p) == NULL)
799 ds_put_byte (&s, *p++);
801 if (!ds_is_empty (&s))
802 return ds_steal_cstr (&s);
809 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
816 /* Get the file name and its encoding. */
817 item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (menushell));
818 file = g_filename_from_uri (gtk_recent_info_get_uri (item), NULL, NULL);
819 encoding = charset_from_mime_type (gtk_recent_info_get_mime_type (item));
820 gtk_recent_info_unref (item);
822 se = psppire_syntax_window_new (encoding);
826 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
827 gtk_widget_show (se);
829 gtk_widget_destroy (se);
836 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
838 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
840 gtk_action_set_visible (de->delete_cases, case_num != -1);
845 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
847 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
849 gtk_action_set_visible (de->delete_variables, var != -1);
852 /* Callback for when the datasheet/varsheet is selected */
854 on_switch_sheet (GtkNotebook *notebook,
855 GtkNotebookPage *page,
859 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
861 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
863 GtkWidget *view_data =
864 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
866 GtkWidget *view_variables =
867 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
871 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
872 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
874 gtk_action_set_sensitive (de->insert_variable, TRUE);
875 gtk_action_set_sensitive (de->insert_case, FALSE);
876 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
878 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
879 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
880 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
881 gtk_action_set_sensitive (de->insert_case, TRUE);
884 g_assert_not_reached ();
889 update_paste_menuitem (de, page_num);
896 set_unsaved (gpointer w)
898 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
902 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
903 Returns a pointer to the action
906 connect_action (PsppireDataWindow *dw, const char *action_name,
909 GtkAction *action = get_action_assert (dw->builder, action_name);
911 g_signal_connect_swapped (action, "activate", handler, dw);
916 /* Initializes as much of a PsppireDataWindow as we can and must before the
917 dataset has been set.
919 In particular, the 'menu' member is required in case the "filename" property
920 is set before the "dataset" property: otherwise PsppireWindow will try to
921 modify the menu as part of the "filename" property_set() function and end up
922 with a Gtk-CRITICAL since 'menu' is NULL. */
924 psppire_data_window_init (PsppireDataWindow *de)
928 de->builder = builder_new ("data-editor.ui");
930 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
932 PSPPIRE_WINDOW (de)->menu =
933 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
937 psppire_data_window_finish_init (PsppireDataWindow *de,
940 static const struct dataset_callbacks cbs =
942 set_unsaved, /* changed */
943 transformation_change_callback, /* transformations_changed */
952 GtkWidget *box = gtk_vbox_new (FALSE, 0);
955 dict = psppire_dict_new_from_dict (dataset_dict (ds));
956 de->var_store = psppire_var_store_new (dict);
957 de->data_store = psppire_data_store_new (dict);
958 psppire_data_store_set_reader (de->data_store, NULL);
960 menubar = get_widget_assert (de->builder, "menubar");
961 hb = get_widget_assert (de->builder, "handlebox1");
962 sb = get_widget_assert (de->builder, "status-bar");
965 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
968 g_signal_connect_swapped (de->data_store, "case-changed",
969 G_CALLBACK (set_unsaved), de);
971 g_signal_connect_swapped (de->data_store, "case-inserted",
972 G_CALLBACK (set_unsaved), de);
974 g_signal_connect_swapped (de->data_store, "cases-deleted",
975 G_CALLBACK (set_unsaved), de);
977 dataset_set_callbacks (de->dataset, &cbs, de);
979 connect_help (de->builder);
981 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
982 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
983 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
984 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
986 gtk_container_add (GTK_CONTAINER (de), box);
988 set_cut_copy_menuitem_sensitivity (de, FALSE);
990 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
991 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
994 set_paste_menuitem_sensitivity (de, FALSE);
996 g_signal_connect_swapped (de->data_editor, "data-available-changed",
997 G_CALLBACK (set_paste_menuitem_sensitivity), de);
999 g_signal_connect (dict, "weight-changed",
1000 G_CALLBACK (on_weight_change),
1003 g_signal_connect (dict, "filter-changed",
1004 G_CALLBACK (on_filter_change),
1007 g_signal_connect (dict, "split-changed",
1008 G_CALLBACK (on_split_change),
1012 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
1014 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
1016 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
1018 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
1020 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
1022 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
1024 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
1026 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
1028 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
1030 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
1032 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
1034 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
1036 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
1038 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
1040 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
1043 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
1045 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
1047 gtk_action_set_visible (de->delete_cases, FALSE);
1052 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1054 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1056 gtk_action_set_visible (de->delete_variables, FALSE);
1060 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1062 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1064 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1066 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1068 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1070 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1072 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1074 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1077 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1079 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1081 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1083 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1085 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1087 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1089 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1091 connect_action (de, "transform_count", G_CALLBACK (count_dialog));
1093 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1095 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1097 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1099 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1101 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1103 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1105 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1107 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1109 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1111 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1113 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1115 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1117 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1119 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1120 connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
1124 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1126 GtkWidget *recent_data =
1127 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1129 GtkWidget *recent_files =
1130 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1133 GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
1134 gtk_recent_manager_get_default ());
1136 GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
1137 gtk_recent_manager_get_default ());
1139 g_object_set (menu_data, "show-tips", TRUE, NULL);
1140 g_object_set (menu_files, "show-tips", TRUE, NULL);
1143 GtkRecentFilter *filter = gtk_recent_filter_new ();
1145 gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
1146 gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
1148 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1150 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1153 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1156 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1159 GtkRecentFilter *filter = gtk_recent_filter_new ();
1161 gtk_recent_filter_add_pattern (filter, "*.sps");
1162 gtk_recent_filter_add_pattern (filter, "*.SPS");
1164 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1166 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1169 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1171 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1175 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1178 g_signal_connect (de->data_editor,
1180 G_CALLBACK (enable_delete_cases),
1183 g_signal_connect (de->data_editor,
1184 "variables-selected",
1185 G_CALLBACK (enable_delete_variables),
1189 g_signal_connect (de->data_editor,
1191 G_CALLBACK (on_switch_sheet), de);
1193 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1194 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1196 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1198 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1200 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1202 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1204 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1206 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1208 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1210 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1212 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1215 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1217 merge_help_menu (uim);
1221 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1222 "datasheet-cases-popup");
1224 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1225 "varsheet-variable-popup");
1227 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1228 "datasheet-variable-popup");
1230 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1231 G_CALLBACK (psppire_data_editor_sort_ascending),
1234 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1235 G_CALLBACK (psppire_data_editor_sort_descending),
1238 g_object_set (de->data_editor,
1239 "datasheet-column-menu", data_sheet_variable_popup_menu,
1240 "datasheet-row-menu", data_sheet_cases_popup_menu,
1241 "varsheet-row-menu", var_sheet_variable_popup_menu,
1245 gtk_widget_show (GTK_WIDGET (de->data_editor));
1246 gtk_widget_show (box);
1248 ll_push_head (&all_data_windows, &de->ll);
1252 psppire_data_window_dispose (GObject *object)
1254 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1256 if (dw->builder != NULL)
1258 g_object_unref (dw->builder);
1264 g_object_unref (dw->var_store);
1265 dw->var_store = NULL;
1270 g_object_unref (dw->data_store);
1271 dw->data_store = NULL;
1274 if (dw->ll.next != NULL)
1276 ll_remove (&dw->ll);
1280 if (G_OBJECT_CLASS (parent_class)->dispose)
1281 G_OBJECT_CLASS (parent_class)->dispose (object);
1285 psppire_data_window_set_property (GObject *object,
1287 const GValue *value,
1290 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1295 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1298 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1304 psppire_data_window_get_property (GObject *object,
1309 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1314 g_value_set_pointer (value, window->dataset);
1317 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1323 psppire_data_window_new (struct dataset *ds)
1327 if (the_session == NULL)
1328 the_session = session_create ();
1332 static int n_datasets;
1335 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1336 ds = dataset_create (the_session, dataset_name);
1337 free (dataset_name);
1339 assert (dataset_session (ds) == the_session);
1343 psppire_data_window_get_type (),
1344 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1345 "description", _("Data Editor"),
1349 if (dataset_name (ds) != NULL)
1350 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1356 psppire_data_window_is_empty (PsppireDataWindow *dw)
1358 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1362 psppire_data_window_iface_init (PsppireWindowIface *iface)
1364 iface->save = save_file;
1365 iface->pick_filename = data_pick_filename;
1366 iface->load = load_file;
1370 psppire_default_data_window (void)
1372 if (ll_is_empty (&all_data_windows))
1373 create_data_window ();
1374 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1378 psppire_data_window_set_default (PsppireDataWindow *pdw)
1380 ll_remove (&pdw->ll);
1381 ll_push_head (&all_data_windows, &pdw->ll);
1385 psppire_data_window_undefault (PsppireDataWindow *pdw)
1387 ll_remove (&pdw->ll);
1388 ll_push_tail (&all_data_windows, &pdw->ll);
1392 psppire_data_window_for_dataset (struct dataset *ds)
1394 PsppireDataWindow *pdw;
1396 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1397 if (pdw->dataset == ds)
1404 create_data_window (void)
1406 gtk_widget_show (psppire_data_window_new (NULL));
1410 open_data_window (PsppireWindow *victim, const char *file_name)
1414 if (PSPPIRE_IS_DATA_WINDOW (victim)
1415 && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
1416 window = GTK_WIDGET (victim);
1418 window = psppire_data_window_new (NULL);
1420 psppire_window_load (PSPPIRE_WINDOW (window), file_name);
1421 gtk_widget_show (window);