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_mime_type (filter, "application/x-spss-sav");
510 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
512 filter = gtk_file_filter_new ();
513 gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
514 gtk_file_filter_add_mime_type (filter, "application/x-spss-por");
515 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
517 filter = gtk_file_filter_new ();
518 gtk_file_filter_set_name (filter, _("All Files"));
519 gtk_file_filter_add_pattern (filter, "*");
520 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
523 GtkWidget *button_por;
524 GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
526 gtk_radio_button_new_with_label (NULL, _("System File"));
529 gtk_radio_button_new_with_label
530 (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
533 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
534 psppire_box_pack_start_defaults (GTK_BOX (vbox), button_por);
536 gtk_widget_show_all (vbox);
538 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
541 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
544 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
546 case GTK_RESPONSE_ACCEPT:
551 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog))
554 de->save_as_portable =
555 ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
557 if ( ! name_has_suffix (filename->str))
559 if ( de->save_as_portable)
560 g_string_append (filename, ".por");
562 g_string_append (filename, ".sav");
565 psppire_window_set_filename (PSPPIRE_WINDOW (de), filename->str);
567 g_string_free (filename, TRUE);
574 gtk_widget_destroy (dialog);
578 confirm_delete_dataset (PsppireDataWindow *de,
579 const char *old_dataset,
580 const char *new_dataset,
581 const char *existing_dataset)
586 dialog = gtk_message_dialog_new (
587 GTK_WINDOW (de), 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s",
588 _("Delete Existing Dataset?"));
590 gtk_message_dialog_format_secondary_text (
591 GTK_MESSAGE_DIALOG (dialog),
592 _("Renaming \"%s\" to \"%s\" will delete destroy the existing "
593 "dataset named \"%s\". Are you sure that you want to do this?"),
594 old_dataset, new_dataset, existing_dataset);
596 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
597 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
598 GTK_STOCK_DELETE, GTK_RESPONSE_OK,
601 g_object_set (dialog, "icon-name", "pspp", NULL);
603 result = gtk_dialog_run (GTK_DIALOG (dialog));
605 gtk_widget_destroy (dialog);
607 return result == GTK_RESPONSE_OK;
611 on_rename_dataset (PsppireDataWindow *de)
613 struct dataset *ds = de->dataset;
614 struct session *session = dataset_session (ds);
615 const char *old_name = dataset_name (ds);
616 struct dataset *existing_dataset;
620 prompt = xasprintf (_("Please enter a new name for dataset \"%s\":"),
622 new_name = entry_dialog_run (GTK_WINDOW (de), _("Rename Dataset"), prompt,
626 if (new_name == NULL)
629 existing_dataset = session_lookup_dataset (session, new_name);
630 if (existing_dataset == NULL || existing_dataset == ds
631 || confirm_delete_dataset (de, old_name, new_name,
632 dataset_name (existing_dataset)))
633 g_free (execute_syntax_string (de, g_strdup_printf ("DATASET NAME %s.",
640 on_edit_paste (PsppireDataWindow *de)
642 psppire_data_editor_clip_paste (de->data_editor);
646 on_edit_copy (PsppireDataWindow *de)
648 psppire_data_editor_clip_copy (de->data_editor);
654 on_edit_cut (PsppireDataWindow *de)
656 psppire_data_editor_clip_cut (de->data_editor);
661 status_bar_activate (PsppireDataWindow *de, GtkToggleAction *action)
663 GtkWidget *statusbar = get_widget_assert (de->builder, "status-bar");
665 if ( gtk_toggle_action_get_active (action))
666 gtk_widget_show (statusbar);
668 gtk_widget_hide (statusbar);
673 grid_lines_activate (PsppireDataWindow *de, GtkToggleAction *action)
675 const gboolean grid_visible = gtk_toggle_action_get_active (action);
677 psppire_data_editor_show_grid (de->data_editor, grid_visible);
681 data_view_activate (PsppireDataWindow *de)
683 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
688 variable_view_activate (PsppireDataWindow *de)
690 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
695 fonts_activate (PsppireDataWindow *de)
697 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (de));
698 PangoFontDescription *current_font;
701 gtk_font_selection_dialog_new (_("Font Selection"));
704 current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
705 font_name = pango_font_description_to_string (current_font);
707 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
711 gtk_window_set_transient_for (GTK_WINDOW (dialog),
712 GTK_WINDOW (toplevel));
714 if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
716 const gchar *font = gtk_font_selection_dialog_get_font_name
717 (GTK_FONT_SELECTION_DIALOG (dialog));
719 PangoFontDescription* font_desc =
720 pango_font_description_from_string (font);
722 psppire_data_editor_set_font (de->data_editor, font_desc);
725 gtk_widget_hide (dialog);
730 /* Callback for the value labels action */
732 toggle_value_labels (PsppireDataWindow *de, GtkToggleAction *ta)
734 g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
738 toggle_split_window (PsppireDataWindow *de, GtkToggleAction *ta)
740 psppire_data_editor_split_window (de->data_editor,
741 gtk_toggle_action_get_active (ta));
746 file_quit (PsppireDataWindow *de)
748 /* FIXME: Need to be more intelligent here.
749 Give the user the opportunity to save any unsaved data.
756 on_recent_data_select (GtkMenuShell *menushell,
757 PsppireWindow *window)
762 gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
764 file = g_filename_from_uri (uri, NULL, NULL);
768 open_data_window (window, file);
774 charset_from_mime_type (const char *mime_type)
780 if (mime_type == NULL)
783 charset = c_strcasestr (mime_type, "charset=");
791 /* Parse a "quoted-string" as defined by RFC 822. */
792 for (p++; *p != '\0' && *p != '"'; p++)
795 ds_put_byte (&s, *p);
796 else if (*++p != '\0')
797 ds_put_byte (&s, *p);
802 /* Parse a "token" as defined by RFC 2045. */
803 while (*p > 32 && *p < 127 && strchr ("()<>@,;:\\\"/[]?=", *p) == NULL)
804 ds_put_byte (&s, *p++);
806 if (!ds_is_empty (&s))
807 return ds_steal_cstr (&s);
814 on_recent_files_select (GtkMenuShell *menushell, gpointer user_data)
821 /* Get the file name and its encoding. */
822 item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (menushell));
823 file = g_filename_from_uri (gtk_recent_info_get_uri (item), NULL, NULL);
824 encoding = charset_from_mime_type (gtk_recent_info_get_mime_type (item));
825 gtk_recent_info_unref (item);
827 se = psppire_syntax_window_new (encoding);
831 if ( psppire_window_load (PSPPIRE_WINDOW (se), file) )
832 gtk_widget_show (se);
834 gtk_widget_destroy (se);
842 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
844 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
846 gtk_action_set_visible (de->delete_cases, case_num != -1);
851 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
853 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
855 gtk_action_set_visible (de->delete_variables, var != -1);
858 /* Callback for when the datasheet/varsheet is selected */
860 on_switch_sheet (GtkNotebook *notebook,
861 GtkNotebookPage *page,
865 PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
867 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
869 GtkWidget *view_data =
870 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
872 GtkWidget *view_variables =
873 gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
877 case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
878 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
880 gtk_action_set_sensitive (de->insert_variable, TRUE);
881 gtk_action_set_sensitive (de->insert_case, FALSE);
882 gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
884 case PSPPIRE_DATA_EDITOR_DATA_VIEW:
885 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
886 gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
887 gtk_action_set_sensitive (de->insert_case, TRUE);
890 g_assert_not_reached ();
895 update_paste_menuitem (de, page_num);
902 set_unsaved (gpointer w)
904 psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
908 /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
909 Returns a pointer to the action
912 connect_action (PsppireDataWindow *dw, const char *action_name,
915 GtkAction *action = get_action_assert (dw->builder, action_name);
917 g_signal_connect_swapped (action, "activate", handler, dw);
922 /* Initializes as much of a PsppireDataWindow as we can and must before the
923 dataset has been set.
925 In particular, the 'menu' member is required in case the "filename" property
926 is set before the "dataset" property: otherwise PsppireWindow will try to
927 modify the menu as part of the "filename" property_set() function and end up
928 with a Gtk-CRITICAL since 'menu' is NULL. */
930 psppire_data_window_init (PsppireDataWindow *de)
934 de->builder = builder_new ("data-editor.ui");
936 uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
938 PSPPIRE_WINDOW (de)->menu =
939 GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
943 psppire_data_window_finish_init (PsppireDataWindow *de,
946 static const struct dataset_callbacks cbs =
948 set_unsaved, /* changed */
949 transformation_change_callback, /* transformations_changed */
958 GtkWidget *box = gtk_vbox_new (FALSE, 0);
961 dict = psppire_dict_new_from_dict (dataset_dict (ds));
962 de->var_store = psppire_var_store_new (dict);
963 de->data_store = psppire_data_store_new (dict);
964 psppire_data_store_set_reader (de->data_store, NULL);
966 menubar = get_widget_assert (de->builder, "menubar");
967 hb = get_widget_assert (de->builder, "handlebox1");
968 sb = get_widget_assert (de->builder, "status-bar");
971 PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
974 g_signal_connect_swapped (de->data_store, "case-changed",
975 G_CALLBACK (set_unsaved), de);
977 g_signal_connect_swapped (de->data_store, "case-inserted",
978 G_CALLBACK (set_unsaved), de);
980 g_signal_connect_swapped (de->data_store, "cases-deleted",
981 G_CALLBACK (set_unsaved), de);
983 dataset_set_callbacks (de->dataset, &cbs, de);
985 connect_help (de->builder);
987 gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
988 gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
989 gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
990 gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
992 gtk_container_add (GTK_CONTAINER (de), box);
994 set_cut_copy_menuitem_sensitivity (de, FALSE);
996 g_signal_connect_swapped (de->data_editor, "data-selection-changed",
997 G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
1000 set_paste_menuitem_sensitivity (de, FALSE);
1002 g_signal_connect_swapped (de->data_editor, "data-available-changed",
1003 G_CALLBACK (set_paste_menuitem_sensitivity), de);
1005 g_signal_connect (dict, "weight-changed",
1006 G_CALLBACK (on_weight_change),
1009 g_signal_connect (dict, "filter-changed",
1010 G_CALLBACK (on_filter_change),
1013 g_signal_connect (dict, "split-changed",
1014 G_CALLBACK (on_split_change),
1018 connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
1020 connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
1022 connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
1024 connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
1026 connect_action (de, "file_save", G_CALLBACK (psppire_window_save));
1028 connect_action (de, "file_open", G_CALLBACK (psppire_window_open));
1030 connect_action (de, "file_save_as", G_CALLBACK (psppire_window_save_as));
1032 connect_action (de, "rename_dataset", G_CALLBACK (on_rename_dataset));
1034 connect_action (de, "file_information_working-file", G_CALLBACK (display_dict));
1036 connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
1038 connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
1040 de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
1042 de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
1044 de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
1046 g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
1049 de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
1051 g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
1053 gtk_action_set_visible (de->delete_cases, FALSE);
1058 de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
1060 g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
1062 gtk_action_set_visible (de->delete_variables, FALSE);
1066 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1068 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1070 connect_action (de, "data_sort-cases", G_CALLBACK (sort_cases_dialog));
1072 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1074 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1076 connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog));
1078 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1080 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1082 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1085 connect_action (de, "utilities_variables", G_CALLBACK (variable_info_dialog));
1087 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1089 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1091 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1093 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1095 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1097 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1099 connect_action (de, "transform_count", G_CALLBACK (count_dialog));
1101 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1103 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1105 connect_action (de, "analyze_descriptives", G_CALLBACK (descriptives_dialog));
1107 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1109 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1111 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1113 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1115 connect_action (de, "reliability", G_CALLBACK (reliability_dialog));
1117 connect_action (de, "roc-curve", G_CALLBACK (roc_dialog));
1119 connect_action (de, "correlation", G_CALLBACK (correlation_dialog));
1121 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1123 connect_action (de, "k-means", G_CALLBACK (k_means_dialog));
1125 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
1126 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
1127 connect_action (de, "runs", G_CALLBACK (runs_dialog));
1128 connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog));
1129 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
1130 connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
1134 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1136 GtkWidget *recent_data =
1137 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
1139 GtkWidget *recent_files =
1140 gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
1143 GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
1144 gtk_recent_manager_get_default ());
1146 GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
1147 gtk_recent_manager_get_default ());
1149 g_object_set (menu_data, "show-tips", TRUE, NULL);
1150 g_object_set (menu_files, "show-tips", TRUE, NULL);
1153 GtkRecentFilter *filter = gtk_recent_filter_new ();
1155 gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
1156 gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
1158 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
1160 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
1163 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu_data);
1166 g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), de);
1169 GtkRecentFilter *filter = gtk_recent_filter_new ();
1171 gtk_recent_filter_add_pattern (filter, "*.sps");
1172 gtk_recent_filter_add_pattern (filter, "*.SPS");
1174 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
1176 gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
1179 gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu_files);
1181 g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), de);
1185 connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
1188 g_signal_connect (de->data_editor,
1190 G_CALLBACK (enable_delete_cases),
1193 g_signal_connect (de->data_editor,
1194 "variables-selected",
1195 G_CALLBACK (enable_delete_variables),
1199 g_signal_connect (de->data_editor,
1201 G_CALLBACK (on_switch_sheet), de);
1203 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1204 gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1206 connect_action (de, "view_statusbar", G_CALLBACK (status_bar_activate));
1208 connect_action (de, "view_gridlines", G_CALLBACK (grid_lines_activate));
1210 connect_action (de, "view_data", G_CALLBACK (data_view_activate));
1212 connect_action (de, "view_variables", G_CALLBACK (variable_view_activate));
1214 connect_action (de, "view_fonts", G_CALLBACK (fonts_activate));
1216 connect_action (de, "file_quit", G_CALLBACK (file_quit));
1218 connect_action (de, "transform_run-pending", G_CALLBACK (execute));
1220 connect_action (de, "windows_minimise_all", G_CALLBACK (psppire_window_minimise_all));
1222 g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
1225 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
1227 merge_help_menu (uim);
1231 GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
1232 "datasheet-cases-popup");
1234 GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
1235 "varsheet-variable-popup");
1237 GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
1238 "datasheet-variable-popup");
1240 g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
1241 G_CALLBACK (psppire_data_editor_sort_ascending),
1244 g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
1245 G_CALLBACK (psppire_data_editor_sort_descending),
1248 g_object_set (de->data_editor,
1249 "datasheet-column-menu", data_sheet_variable_popup_menu,
1250 "datasheet-row-menu", data_sheet_cases_popup_menu,
1251 "varsheet-row-menu", var_sheet_variable_popup_menu,
1255 gtk_widget_show (GTK_WIDGET (de->data_editor));
1256 gtk_widget_show (box);
1258 ll_push_head (&all_data_windows, &de->ll);
1262 psppire_data_window_dispose (GObject *object)
1264 PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
1266 if (dw->builder != NULL)
1268 g_object_unref (dw->builder);
1274 g_object_unref (dw->var_store);
1275 dw->var_store = NULL;
1280 g_object_unref (dw->data_store);
1281 dw->data_store = NULL;
1284 if (dw->ll.next != NULL)
1286 ll_remove (&dw->ll);
1290 if (G_OBJECT_CLASS (parent_class)->dispose)
1291 G_OBJECT_CLASS (parent_class)->dispose (object);
1295 psppire_data_window_set_property (GObject *object,
1297 const GValue *value,
1300 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1305 psppire_data_window_finish_init (window, g_value_get_pointer (value));
1308 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1314 psppire_data_window_get_property (GObject *object,
1319 PsppireDataWindow *window = PSPPIRE_DATA_WINDOW (object);
1324 g_value_set_pointer (value, window->dataset);
1327 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1333 psppire_data_window_new (struct dataset *ds)
1337 if (the_session == NULL)
1338 the_session = session_create ();
1342 static int n_datasets;
1345 dataset_name = xasprintf ("DataSet%d", ++n_datasets);
1346 ds = dataset_create (the_session, dataset_name);
1347 free (dataset_name);
1349 assert (dataset_session (ds) == the_session);
1353 psppire_data_window_get_type (),
1354 /* TRANSLATORS: This will form a filename. Please avoid whitespace. */
1355 "description", _("Data Editor"),
1359 if (dataset_name (ds) != NULL)
1360 g_object_set (dw, "id", dataset_name (ds), (void *) NULL);
1366 psppire_data_window_is_empty (PsppireDataWindow *dw)
1368 return psppire_var_store_get_var_cnt (dw->var_store) == 0;
1372 psppire_data_window_iface_init (PsppireWindowIface *iface)
1374 iface->save = save_file;
1375 iface->pick_filename = data_pick_filename;
1376 iface->load = load_file;
1380 psppire_default_data_window (void)
1382 if (ll_is_empty (&all_data_windows))
1383 create_data_window ();
1384 return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
1388 psppire_data_window_set_default (PsppireDataWindow *pdw)
1390 ll_remove (&pdw->ll);
1391 ll_push_head (&all_data_windows, &pdw->ll);
1395 psppire_data_window_undefault (PsppireDataWindow *pdw)
1397 ll_remove (&pdw->ll);
1398 ll_push_tail (&all_data_windows, &pdw->ll);
1402 psppire_data_window_for_dataset (struct dataset *ds)
1404 PsppireDataWindow *pdw;
1406 ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
1407 if (pdw->dataset == ds)
1414 create_data_window (void)
1416 gtk_widget_show (psppire_data_window_new (NULL));
1420 open_data_window (PsppireWindow *victim, const char *file_name)
1424 if (PSPPIRE_IS_DATA_WINDOW (victim)
1425 && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
1426 window = GTK_WIDGET (victim);
1428 window = psppire_data_window_new (NULL);
1430 psppire_window_load (PSPPIRE_WINDOW (window), file_name);
1431 gtk_widget_show (window);