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/autorecode-dialog.h"
29 #include "ui/gui/binomial-dialog.h"
30 #include "ui/gui/chi-square-dialog.h"
31 #include "ui/gui/comments-dialog.h"
32 #include "ui/gui/compute-dialog.h"
33 #include "ui/gui/correlation-dialog.h"
34 #include "ui/gui/count-dialog.h"
35 #include "ui/gui/crosstabs-dialog.h"
36 #include "ui/gui/descriptives-dialog.h"
37 #include "ui/gui/entry-dialog.h"
38 #include "ui/gui/examine-dialog.h"
39 #include "ui/gui/executor.h"
40 #include "ui/gui/factor-dialog.h"
41 #include "ui/gui/find-dialog.h"
42 #include "ui/gui/frequencies-dialog.h"
43 #include "ui/gui/goto-case-dialog.h"
44 #include "ui/gui/help-menu.h"
45 #include "ui/gui/helper.h"
46 #include "ui/gui/k-means-dialog.h"
47 #include "ui/gui/k-related-dialog.h"
48 #include "ui/gui/npar-two-sample-related.h"
49 #include "ui/gui/oneway-anova-dialog.h"
50 #include "ui/gui/psppire-data-window.h"
51 #include "ui/gui/psppire-syntax-window.h"
52 #include "ui/gui/psppire-window.h"
53 #include "ui/gui/psppire.h"
54 #include "ui/gui/rank-dialog.h"
55 #include "ui/gui/runs-dialog.h"
56 #include "ui/gui/ks-one-sample-dialog.h"
57 #include "ui/gui/recode-dialog.h"
58 #include "ui/gui/regression-dialog.h"
59 #include "ui/gui/reliability-dialog.h"
60 #include "ui/gui/roc-dialog.h"
61 #include "ui/gui/select-cases-dialog.h"
62 #include "ui/gui/sort-cases-dialog.h"
63 #include "ui/gui/split-file-dialog.h"
64 #include "ui/gui/t-test-independent-samples-dialog.h"
65 #include "ui/gui/t-test-one-sample.h"
66 #include "ui/gui/t-test-paired-samples.h"
67 #include "ui/gui/text-data-import-dialog.h"
68 #include "ui/gui/transpose-dialog.h"
69 #include "ui/gui/variable-info-dialog.h"
70 #include "ui/gui/weight-cases-dialog.h"
71 #include "ui/syntax-gen.h"
73 #include "gl/c-strcase.h"
74 #include "gl/c-strcasestr.h"
75 #include "gl/xvasprintf.h"
78 #define _(msgid) gettext (msgid)
79 #define N_(msgid) msgid
81 struct session *the_session;
82 struct ll_list all_data_windows = LL_INITIALIZER (all_data_windows);
84 static void psppire_data_window_class_init (PsppireDataWindowClass *class);
85 static void psppire_data_window_init (PsppireDataWindow *data_editor);
88 static void psppire_data_window_iface_init (PsppireWindowIface *iface);
90 static void psppire_data_window_dispose (GObject *object);
91 static void psppire_data_window_set_property (GObject *object,
95 static void psppire_data_window_get_property (GObject *object,
101 psppire_data_window_get_type (void)
103 static GType psppire_data_window_type = 0;
105 if (!psppire_data_window_type)
107 static const GTypeInfo psppire_data_window_info =
109 sizeof (PsppireDataWindowClass),
112 (GClassInitFunc)psppire_data_window_class_init,
113 (GClassFinalizeFunc) NULL,
115 sizeof (PsppireDataWindow),
117 (GInstanceInitFunc) psppire_data_window_init,
120 static const GInterfaceInfo window_interface_info =
122 (GInterfaceInitFunc) psppire_data_window_iface_init,
127 psppire_data_window_type =
128 g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireDataWindow",
129 &psppire_data_window_info, 0);
132 g_type_add_interface_static (psppire_data_window_type,
133 PSPPIRE_TYPE_WINDOW_MODEL,
134 &window_interface_info);
137 return psppire_data_window_type;
140 static GObjectClass *parent_class ;
147 psppire_data_window_class_init (PsppireDataWindowClass *class)
149 GObjectClass *object_class = G_OBJECT_CLASS (class);
151 parent_class = g_type_class_peek_parent (class);
153 object_class->dispose = psppire_data_window_dispose;
154 object_class->set_property = psppire_data_window_set_property;
155 object_class->get_property = psppire_data_window_get_property;
157 g_object_class_install_property (
158 object_class, PROP_DATASET,
159 g_param_spec_pointer ("dataset", "Dataset",
160 "'struct datset *' represented by the window",
161 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
165 set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
167 GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
169 gtk_action_set_sensitive (edit_paste, x);
173 set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
175 GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
176 GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
178 gtk_action_set_sensitive (edit_copy, x);
179 gtk_action_set_sensitive (edit_cut, x);
182 /* Run the EXECUTE command. */
184 execute (PsppireDataWindow *dw)
186 execute_const_syntax_string (dw, "EXECUTE.");
190 transformation_change_callback (bool transformations_pending,
193 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
195 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
197 GtkWidget *menuitem =
198 gtk_ui_manager_get_widget (uim,"/ui/menubar/transform/transform_run-pending");
200 GtkWidget *status_label =
201 get_widget_assert (de->builder, "case-counter-area");
203 gtk_widget_set_sensitive (menuitem, transformations_pending);
206 if ( transformations_pending)
207 gtk_label_set_text (GTK_LABEL (status_label),
208 _("Transformations Pending"));
210 gtk_label_set_text (GTK_LABEL (status_label), "");
213 /* Callback for when the dictionary changes its filter variable */
215 on_filter_change (GObject *o, gint filter_index, gpointer data)
217 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
219 GtkWidget *filter_status_area =
220 get_widget_assert (de->builder, "filter-use-status-area");
222 if ( filter_index == -1 )
224 gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
228 PsppireVarStore *vs = NULL;
229 PsppireDict *dict = NULL;
230 struct variable *var ;
233 g_object_get (de->data_editor, "var-store", &vs, NULL);
234 g_object_get (vs, "dictionary", &dict, NULL);
236 var = psppire_dict_get_variable (dict, filter_index);
238 text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
240 gtk_label_set_text (GTK_LABEL (filter_status_area), text);
246 /* Callback for when the dictionary changes its split variables */
248 on_split_change (PsppireDict *dict, gpointer data)
250 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
252 size_t n_split_vars = dict_get_split_cnt (dict->dict);
254 GtkWidget *split_status_area =
255 get_widget_assert (de->builder, "split-file-status-area");
257 if ( n_split_vars == 0 )
259 gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
265 const struct variable *const * split_vars =
266 dict_get_split_vars (dict->dict);
268 text = g_string_new (_("Split by "));
270 for (i = 0 ; i < n_split_vars - 1; ++i )
272 g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
274 g_string_append (text, var_get_name (split_vars[i]));
276 gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
278 g_string_free (text, TRUE);
285 /* Callback for when the dictionary changes its weights */
287 on_weight_change (GObject *o, gint weight_index, gpointer data)
289 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
291 GtkWidget *weight_status_area =
292 get_widget_assert (de->builder, "weight-status-area");
294 if ( weight_index == -1 )
296 gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
300 struct variable *var ;
301 PsppireVarStore *vs = NULL;
302 PsppireDict *dict = NULL;
305 g_object_get (de->data_editor, "var-store", &vs, NULL);
306 g_object_get (vs, "dictionary", &dict, NULL);
308 var = psppire_dict_get_variable (dict, weight_index);
310 text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
312 gtk_label_set_text (GTK_LABEL (weight_status_area), text);
320 dump_rm (GtkRecentManager *rm)
322 GList *items = gtk_recent_manager_get_items (rm);
326 g_print ("Recent Items:\n");
327 for (i = items; i; i = i->next)
329 GtkRecentInfo *ri = i->data;
331 g_print ("Item: %s (Mime: %s) (Desc: %s) (URI: %s)\n",
332 gtk_recent_info_get_short_name (ri),
333 gtk_recent_info_get_mime_type (ri),
334 gtk_recent_info_get_description (ri),
335 gtk_recent_info_get_uri (ri)
339 gtk_recent_info_unref (ri);
347 name_has_por_suffix (const gchar *name)
349 size_t length = strlen (name);
350 return length > 4 && !c_strcasecmp (&name[length - 4], ".por");
354 name_has_sav_suffix (const gchar *name)
356 size_t length = strlen (name);
357 return length > 4 && !c_strcasecmp (&name[length - 4], ".sav");
360 /* Returns true if NAME has a suffix which might denote a PSPP file */
362 name_has_suffix (const gchar *name)
364 return name_has_por_suffix (name) || name_has_sav_suffix (name);
368 load_file (PsppireWindow *de, const gchar *file_name)
370 struct string filename;
371 gchar *utf8_file_name;
372 const char *mime_type;
376 ds_init_empty (&filename);
378 utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
380 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
382 g_free (utf8_file_name);
384 syntax = g_strdup_printf ("GET FILE=%s.", ds_cstr (&filename));
385 ds_destroy (&filename);
387 ok = execute_syntax (PSPPIRE_DATA_WINDOW (de),
388 lex_reader_for_string (syntax));
391 mime_type = (name_has_por_suffix (file_name)
392 ? "application/x-spss-por"
393 : "application/x-spss-sav");
395 add_most_recent (file_name, mime_type);
400 /* Save DE to file */
402 save_file (PsppireWindow *w)
404 const gchar *file_name = NULL;
405 gchar *utf8_file_name = NULL;
407 struct string filename ;
408 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (w);
411 file_name = psppire_window_get_filename (w);
413 fnx = g_string_new (file_name);
415 if ( ! name_has_suffix (fnx->str))
417 if ( de->save_as_portable)
418 g_string_append (fnx, ".por");
420 g_string_append (fnx, ".sav");
423 ds_init_empty (&filename);
425 utf8_file_name = g_filename_to_utf8 (fnx->str, -1, NULL, NULL, NULL);
427 g_string_free (fnx, TRUE);
429 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
430 g_free (utf8_file_name);
432 syntax = g_strdup_printf ("%s OUTFILE=%s.",
433 de->save_as_portable ? "EXPORT" : "SAVE",
434 ds_cstr (&filename));
436 ds_destroy (&filename);
438 g_free (execute_syntax_string (de, syntax));
443 insert_case (PsppireDataWindow *dw)
445 psppire_data_editor_insert_case (dw->data_editor);
449 on_insert_variable (PsppireDataWindow *dw)
451 psppire_data_editor_insert_variable (dw->data_editor);
456 display_dict (PsppireDataWindow *de)
458 execute_const_syntax_string (de, "DISPLAY DICTIONARY.");
462 sysfile_info (PsppireDataWindow *de)
464 GtkWidget *dialog = psppire_window_file_chooser_dialog (PSPPIRE_WINDOW (de));
466 if ( GTK_RESPONSE_ACCEPT == gtk_dialog_run (GTK_DIALOG (dialog)))
468 struct string filename;
470 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
472 gchar *utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL,
477 ds_init_empty (&filename);
479 syntax_gen_string (&filename, ss_cstr (utf8_file_name));
481 g_free (utf8_file_name);
483 syntax = g_strdup_printf ("SYSFILE INFO %s.", ds_cstr (&filename));
484 g_free (execute_syntax_string (de, syntax));
487 gtk_widget_destroy (dialog);
491 /* PsppireWindow 'pick_filename' callback: prompt for a filename to save as. */
493 data_pick_filename (PsppireWindow *window)
495 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
496 GtkFileFilter *filter = gtk_file_filter_new ();
497 GtkWidget *button_sys;
499 gtk_file_chooser_dialog_new (_("Save"),
501 GTK_FILE_CHOOSER_ACTION_SAVE,
502 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
503 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
506 g_object_set (dialog, "local-only", FALSE, NULL);
508 gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
509 gtk_file_filter_add_pattern (filter, "*.sav");
510 gtk_file_filter_add_pattern (filter, "*.SAV");
511 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
513 filter = gtk_file_filter_new ();
514 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
515 gtk_file_filter_add_pattern (filter, "*.por");
516 gtk_file_filter_add_pattern (filter, "*.POR");
517 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
519 filter = gtk_file_filter_new ();
520 gtk_file_filter_set_name (filter, _("All Files"));
521 gtk_file_filter_add_pattern (filter, "*");
522 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
525 GtkWidget *button_por;
526 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
528 gtk_radio_button_new_with_label (NULL, _("System File"));
531 gtk_radio_button_new_with_label
532 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
535 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
536 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
538 gtk_widget_show_all (vbox);
540 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
543 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
546 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
548 case GTK_RESPONSE_ACCEPT:
553 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
556 de->save_as_portable =
557 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
559 if ( ! name_has_suffix (filename->str))
561 if ( de->save_as_portable)
562 g_string_append (filename, ".por");
564 g_string_append (filename, ".sav");
567 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
569 g_string_free (filename, TRUE);
576 gtk_widget_destroy (dialog);
580 confirm_delete_dataset (PsppireDataWindow *de,
581 const char *old_dataset,
582 const char *new_dataset,
583 const char *existing_dataset)
588 dialog = gtk_message_dialog_new (
589 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
590 _("Delete Existing Dataset?"));
592 gtk_message_dialog_format_secondary_text (
593 GTK_MESSAGE_DIALOG (dialog),
594 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
595 "dataset named \"%s\". Are you sure that you want to do this?"),
596 old_dataset, new_dataset, existing_dataset);
598 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
599 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
600 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
603 g_object_set (dialog, "icon-name", "psppicon", NULL);
605 result = gtk_dialog_run (GTK_DIALOG (dialog));
607 gtk_widget_destroy (dialog);
609 return result == GTK_RESPONSE_OK;
613 on_rename_dataset (PsppireDataWindow *de)
615 struct dataset *ds = de->dataset;
616 struct session *session = dataset_session (ds);
617 const char *old_name = dataset_name (ds);
618 struct dataset *existing_dataset;
622 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
624 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
628 if (new_name == NULL)
631 existing_dataset = session_lookup_dataset (session, new_name);
632 if (existing_dataset == NULL || existing_dataset == ds
633 || confirm_delete_dataset (de, old_name, new_name,
634 dataset_name (existing_dataset)))
635 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
642 on_edit_paste (PsppireDataWindow *de)
644 psppire_data_editor_clip_paste (de->data_editor);
648 on_edit_copy (PsppireDataWindow *de)
650 psppire_data_editor_clip_copy (de->data_editor);
656 on_edit_cut (PsppireDataWindow *de)
658 psppire_data_editor_clip_cut (de->data_editor);
663 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
665 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
667 if ( gtk_toggle_action_get_active (action))
668 gtk_widget_show (statusbar);
670 gtk_widget_hide (statusbar);
675 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
677 const gboolean grid_visible = gtk_toggle_action_get_active (action);
679 psppire_data_editor_show_grid (de->data_editor, grid_visible);
683 data_view_activate (PsppireDataWindow *de)
685 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
690 variable_view_activate (PsppireDataWindow *de)
692 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
697 fonts_activate (PsppireDataWindow *de)
699 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
700 PangoFontDescription *current_font;
703 gtk_font_selection_dialog_new (_("Font Selection"));
706 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
707 font_name = pango_font_description_to_string (current_font);
709 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
713 gtk_window_set_transient_for (GTK_WINDOW (dialog),
714 GTK_WINDOW (toplevel));
716 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
718 const gchar *font = gtk_font_selection_dialog_get_font_name
719 (GTK_FONT_SELECTION_DIALOG (dialog));
721 PangoFontDescription* font_desc =
722 pango_font_description_from_string (font);
724 psppire_data_editor_set_font (de->data_editor, font_desc);
727 gtk_widget_hide (dialog);
732 /* Callback for the value labels action */
734 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
736 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
740 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
742 psppire_data_editor_split_window (de->data_editor,
743 gtk_toggle_action_get_active (ta));
748 file_quit (PsppireDataWindow *de)
750 /* FIXME: Need to be more intelligent here.
751 Give the user the opportunity to save any unsaved data.
758 on_recent_data_select (GtkMenuShell *menushell,
759 PsppireWindow *window)
764 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
766 file = g_filename_from_uri (uri, NULL, NULL);
770 open_data_window (window, file);
776 charset_from_mime_type (const char *mime_type)
782 if (mime_type == NULL)
785 charset = c_strcasestr (mime_type, "charset=");
793 /* Parse a "quoted-string" as defined by RFC 822. */
794 for (p++; *p != '\0' && *p != '"'; p++)
797 ds_put_byte (&s, *p);
798 else if (*++p != '\0')
799 ds_put_byte (&s, *p);
804 /* Parse a "token" as defined by RFC 2045. */
805 while (*p > 32 && *p < 127 && strchr ("()<>@,;:\\\"/[]?=", *p) == NULL)
806 ds_put_byte (&s, *p++);
808 if (!ds_is_empty (&s))
809 return ds_steal_cstr (&s);
816 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
823 /* Get the file name and its encoding. */
824 item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (menushell));
825 file = g_filename_from_uri (gtk_recent_info_get_uri (item), NULL, NULL);
826 encoding = charset_from_mime_type (gtk_recent_info_get_mime_type (item));
827 gtk_recent_info_unref (item);
829 se = psppire_syntax_window_new (encoding);
833 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
834 gtk_widget_show (se);
836 gtk_widget_destroy (se);
843 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
845 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
847 gtk_action_set_visible (de->delete_cases, case_num != -1);
852 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
854 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
856 gtk_action_set_visible (de->delete_variables, var != -1);
859 /* Callback for when the datasheet/varsheet is selected */
861 on_switch_sheet (GtkNotebook *notebook,
862 GtkNotebookPage *page,
866 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
868 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
870 GtkWidget *view_data =
871 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
873 GtkWidget *view_variables =
874 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
878 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
879 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
881 gtk_action_set_sensitive (de->insert_variable, TRUE);
882 gtk_action_set_sensitive (de->insert_case, FALSE);
883 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
885 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
886 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
887 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
888 gtk_action_set_sensitive (de->insert_case, TRUE);
891 g_assert_not_reached ();
896 update_paste_menuitem (de, page_num);
903 set_unsaved (gpointer w)
905 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
909 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
910 Returns a pointer to the action
913 connect_action (PsppireDataWindow *dw, const char *action_name,
916 GtkAction *action = get_action_assert (dw->builder, action_name);
918 g_signal_connect_swapped (action, "activate", handler, dw);
923 /* Initializes as much of a PsppireDataWindow as we can and must before the
924 dataset has been set.
926 In particular, the 'menu' member is required in case the "filename" property
927 is set before the "dataset" property: otherwise PsppireWindow will try to
928 modify the menu as part of the "filename" property_set() function and end up
929 with a Gtk-CRITICAL since 'menu' is NULL. */
931 psppire_data_window_init (PsppireDataWindow *de)
935 de->builder = builder_new ("data-editor.ui");
937 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
939 PSPPIRE_WINDOW (de)->menu =
940 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
944 psppire_data_window_finish_init (PsppireDataWindow *de,
947 static const struct dataset_callbacks cbs =
949 set_unsaved, /* changed */
950 transformation_change_callback, /* transformations_changed */
959 GtkWidget *box = gtk_vbox_new (FALSE, 0);
962 dict = psppire_dict_new_from_dict (dataset_dict (ds));
963 de->var_store = psppire_var_store_new (dict);
964 de->data_store = psppire_data_store_new (dict);
965 psppire_data_store_set_reader (de->data_store, NULL);
967 menubar = get_widget_assert (de->builder, "menubar");
968 hb = get_widget_assert (de->builder, "handlebox1");
969 sb = get_widget_assert (de->builder, "status-bar");
972 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
975 g_signal_connect_swapped (de->data_store, "case-changed",
976 G_CALLBACK (set_unsaved), de);
978 g_signal_connect_swapped (de->data_store, "case-inserted",
979 G_CALLBACK (set_unsaved), de);
981 g_signal_connect_swapped (de->data_store, "cases-deleted",
982 G_CALLBACK (set_unsaved), de);
984 dataset_set_callbacks (de->dataset, &cbs, de);
986 connect_help (de->builder);
988 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
989 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
990 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
991 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
993 gtk_container_add (GTK_CONTAINER (de), box);
995 set_cut_copy_menuitem_sensitivity (de, FALSE);
997 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
998 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
1001 set_paste_menuitem_sensitivity (de, FALSE);
1003 g_signal_connect_swapped (de->data_editor, "data-available-changed",
1004 G_CALLBACK (set_paste_menuitem_sensitivity), de);
1006 g_signal_connect (dict, "weight-changed",
1007 G_CALLBACK (on_weight_change),
1010 g_signal_connect (dict, "filter-changed",
1011 G_CALLBACK (on_filter_change),
1014 g_signal_connect (dict, "split-changed",
1015 G_CALLBACK (on_split_change),
1019 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
1021 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
1023 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
1025 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
1027 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
1029 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
1031 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
1033 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
1035 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
1037 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
1039 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
1041 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
1043 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
1045 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
1047 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
1050 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
1052 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
1054 gtk_action_set_visible (de->delete_cases, FALSE);
1059 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1061 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1063 gtk_action_set_visible (de->delete_variables, FALSE);
1067 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1069 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1071 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1073 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1075 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1077 connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog));
1079 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1081 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1083 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1086 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1088 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1090 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1092 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1094 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1096 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1098 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1100 connect_action (de, "transform_count", G_CALLBACK (count_dialog));
1102 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1104 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1106 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1108 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1110 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1112 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1114 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1116 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1118 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1120 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1122 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1124 connect_action (de, "k-means", G_CALLBACK (k_means_dialog));
1126 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1127 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1128 connect_action (de, "runs", G_CALLBACK (runs_dialog));
1129 connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog));
1130 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1131 connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
1135 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1137 GtkWidget *recent_data =
1138 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1140 GtkWidget *recent_files =
1141 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1144 GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
1145 gtk_recent_manager_get_default ());
1147 GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
1148 gtk_recent_manager_get_default ());
1150 g_object_set (menu_data, "show-tips", TRUE, NULL);
1151 g_object_set (menu_files, "show-tips", TRUE, NULL);
1154 GtkRecentFilter *filter = gtk_recent_filter_new ();
1156 gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
1157 gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
1159 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1161 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1164 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1167 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1170 GtkRecentFilter *filter = gtk_recent_filter_new ();
1172 gtk_recent_filter_add_pattern (filter, "*.sps");
1173 gtk_recent_filter_add_pattern (filter, "*.SPS");
1175 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1177 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1180 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1182 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1186 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1189 g_signal_connect (de->data_editor,
1191 G_CALLBACK (enable_delete_cases),
1194 g_signal_connect (de->data_editor,
1195 "variables-selected",
1196 G_CALLBACK (enable_delete_variables),
1200 g_signal_connect (de->data_editor,
1202 G_CALLBACK (on_switch_sheet), de);
1204 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1205 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1207 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1209 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1211 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1213 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1215 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1217 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1219 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1221 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1223 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1226 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1228 merge_help_menu (uim);
1232 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1233 "datasheet-cases-popup");
1235 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1236 "varsheet-variable-popup");
1238 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1239 "datasheet-variable-popup");
1241 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1242 G_CALLBACK (psppire_data_editor_sort_ascending),
1245 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1246 G_CALLBACK (psppire_data_editor_sort_descending),
1249 g_object_set (de->data_editor,
1250 "datasheet-column-menu", data_sheet_variable_popup_menu,
1251 "datasheet-row-menu", data_sheet_cases_popup_menu,
1252 "varsheet-row-menu", var_sheet_variable_popup_menu,
1256 gtk_widget_show (GTK_WIDGET (de->data_editor));
1257 gtk_widget_show (box);
1259 ll_push_head (&all_data_windows, &de->ll);
1263 psppire_data_window_dispose (GObject *object)
1265 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1267 if (dw->builder != NULL)
1269 g_object_unref (dw->builder);
1275 g_object_unref (dw->var_store);
1276 dw->var_store = NULL;
1281 g_object_unref (dw->data_store);
1282 dw->data_store = NULL;
1285 if (dw->ll.next != NULL)
1287 ll_remove (&dw->ll);
1291 if (G_OBJECT_CLASS (parent_class)->dispose)
1292 G_OBJECT_CLASS (parent_class)->dispose (object);
1296 psppire_data_window_set_property (GObject *object,
1298 const GValue *value,
1301 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1306 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1309 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1315 psppire_data_window_get_property (GObject *object,
1320 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1325 g_value_set_pointer (value, window->dataset);
1328 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1334 psppire_data_window_new (struct dataset *ds)
1338 if (the_session == NULL)
1339 the_session = session_create ();
1343 static int n_datasets;
1346 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1347 ds = dataset_create (the_session, dataset_name);
1348 free (dataset_name);
1350 assert (dataset_session (ds) == the_session);
1354 psppire_data_window_get_type (),
1355 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1356 "description", _("Data Editor"),
1360 if (dataset_name (ds) != NULL)
1361 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1367 psppire_data_window_is_empty (PsppireDataWindow *dw)
1369 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1373 psppire_data_window_iface_init (PsppireWindowIface *iface)
1375 iface->save = save_file;
1376 iface->pick_filename = data_pick_filename;
1377 iface->load = load_file;
1381 psppire_default_data_window (void)
1383 if (ll_is_empty (&all_data_windows))
1384 create_data_window ();
1385 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1389 psppire_data_window_set_default (PsppireDataWindow *pdw)
1391 ll_remove (&pdw->ll);
1392 ll_push_head (&all_data_windows, &pdw->ll);
1396 psppire_data_window_undefault (PsppireDataWindow *pdw)
1398 ll_remove (&pdw->ll);
1399 ll_push_tail (&all_data_windows, &pdw->ll);
1403 psppire_data_window_for_dataset (struct dataset *ds)
1405 PsppireDataWindow *pdw;
1407 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1408 if (pdw->dataset == ds)
1415 create_data_window (void)
1417 gtk_widget_show (psppire_data_window_new (NULL));
1421 open_data_window (PsppireWindow *victim, const char *file_name)
1425 if (PSPPIRE_IS_DATA_WINDOW (victim)
1426 && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
1427 window = GTK_WIDGET (victim);
1429 window = psppire_data_window_new (NULL);
1431 psppire_window_load (PSPPIRE_WINDOW (window), file_name);
1432 gtk_widget_show (window);