Make sure finalizers are called properly
[pspp-builds.git] / src / ui / gui / psppire-data-window.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2008  Free Software Foundation
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include <gtk/gtksignal.h>
20 #include <gtk/gtkbox.h>
21 #include <glade/glade.h>
22 #include "helper.h"
23
24 #include "text-data-import-dialog.h"
25
26
27 #include <ui/syntax-gen.h>
28 #include <language/syntax-string-source.h>
29 #include <libpspp/message.h>
30 #include <stdlib.h>
31
32 #include <data/procedure.h>
33
34 #include "psppire-data-window.h"
35 #include "psppire-syntax-window.h"
36
37 #include "about.h"
38
39 #include "goto-case-dialog.h"
40 #include "weight-cases-dialog.h"
41 #include "split-file-dialog.h"
42 #include "transpose-dialog.h"
43 #include "sort-cases-dialog.h"
44 #include "select-cases-dialog.h"
45 #include "compute-dialog.h"
46 #include "find-dialog.h"
47 #include "rank-dialog.h"
48 #include "recode-dialog.h"
49 #include "comments-dialog.h"
50 #include "variable-info-dialog.h"
51 #include "descriptives-dialog.h"
52 #include "crosstabs-dialog.h"
53 #include "frequencies-dialog.h"
54 #include "examine-dialog.h"
55 #include "dict-display.h"
56 #include "regression-dialog.h"
57 #include "oneway-anova-dialog.h"
58 #include "t-test-independent-samples-dialog.h"
59 #include "t-test-one-sample.h"
60 #include "t-test-paired-samples.h"
61
62
63 #include <gettext.h>
64 #define _(msgid) gettext (msgid)
65 #define N_(msgid) msgid
66
67
68
69 static void psppire_data_window_base_finalize (PsppireDataWindowClass *, gpointer);
70 static void psppire_data_window_base_init     (PsppireDataWindowClass *class);
71 static void psppire_data_window_class_init    (PsppireDataWindowClass *class);
72 static void psppire_data_window_init          (PsppireDataWindow      *data_editor);
73
74
75 GType
76 psppire_data_window_get_type (void)
77 {
78   static GType psppire_data_window_type = 0;
79
80   if (!psppire_data_window_type)
81     {
82       static const GTypeInfo psppire_data_window_info =
83       {
84         sizeof (PsppireDataWindowClass),
85         (GBaseInitFunc) psppire_data_window_base_init,
86         (GBaseFinalizeFunc) psppire_data_window_base_finalize,
87         (GClassInitFunc)psppire_data_window_class_init,
88         (GClassFinalizeFunc) NULL,
89         NULL,
90         sizeof (PsppireDataWindow),
91         0,
92         (GInstanceInitFunc) psppire_data_window_init,
93       };
94
95       psppire_data_window_type =
96         g_type_register_static (PSPPIRE_WINDOW_TYPE, "PsppireDataWindow",
97                                 &psppire_data_window_info, 0);
98     }
99
100   return psppire_data_window_type;
101 }
102
103 static GObjectClass *parent_class ;
104
105 static void
106 psppire_data_window_finalize (GObject *object)
107 {
108   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (object);
109
110   g_object_unref (de->xml);
111
112   if (G_OBJECT_CLASS (parent_class)->finalize)
113     (*G_OBJECT_CLASS (parent_class)->finalize) (object);
114 }
115
116
117 static void
118 psppire_data_window_class_init (PsppireDataWindowClass *class)
119 {
120   parent_class = g_type_class_peek_parent (class);
121 }
122
123
124 static void
125 psppire_data_window_base_init (PsppireDataWindowClass *class)
126 {
127   GObjectClass *object_class = G_OBJECT_CLASS (class);
128
129   object_class->finalize = psppire_data_window_finalize;
130 }
131
132
133
134 static void
135 psppire_data_window_base_finalize (PsppireDataWindowClass *class,
136                                      gpointer class_data)
137 {
138 }
139
140
141 \f
142
143
144 extern PsppireVarStore *the_var_store;
145 extern struct dataset *the_dataset;
146 extern PsppireDataStore *the_data_store ;
147
148
149 static void
150 update_paste_menuitems (GtkWidget *w, gboolean x, gpointer data)
151 {
152   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
153
154   GtkWidget * edit_paste = get_widget_assert (de->xml, "edit_paste");
155
156   gtk_widget_set_sensitive (edit_paste, x);
157 }
158
159 static void
160 update_cut_copy_menuitems (GtkWidget *w, gboolean x, gpointer data)
161 {
162   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
163
164   GtkWidget * edit_copy = get_widget_assert (de->xml, "edit_copy");
165   GtkWidget * edit_cut = get_widget_assert (de->xml, "edit_cut");
166
167   gtk_widget_set_sensitive (edit_copy, x);
168   gtk_widget_set_sensitive (edit_cut, x);
169 }
170
171 /* Run the EXECUTE command. */
172 static void
173 execute (GtkMenuItem *mi, gpointer data)
174 {
175   struct getl_interface *sss = create_syntax_string_source ("EXECUTE.");
176
177   execute_syntax (sss);
178 }
179
180 static void
181 transformation_change_callback (bool transformations_pending,
182                                 gpointer data)
183 {
184   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
185
186   GtkWidget *menuitem =
187     get_widget_assert (de->xml, "transform_run-pending");
188   GtkWidget *status_label  =
189     get_widget_assert (de->xml, "case-counter-area");
190
191   gtk_widget_set_sensitive (menuitem, transformations_pending);
192
193
194   if ( transformations_pending)
195     gtk_label_set_text (GTK_LABEL (status_label),
196                         _("Transformations Pending"));
197   else
198     gtk_label_set_text (GTK_LABEL (status_label), "");
199 }
200
201 /* Callback for when the dictionary changes its filter variable */
202 static void
203 on_filter_change (GObject *o, gint filter_index, gpointer data)
204 {
205   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
206
207   GtkWidget *filter_status_area =
208     get_widget_assert (de->xml, "filter-use-status-area");
209
210   if ( filter_index == -1 )
211     {
212       gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
213     }
214   else
215     {
216       PsppireVarStore *vs = NULL;
217       struct variable *var ;
218       gchar *text ;
219
220       g_object_get (de->data_editor, "var-store", &vs, NULL);
221
222       var = psppire_dict_get_variable (vs->dict, filter_index);
223
224       text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
225
226       gtk_label_set_text (GTK_LABEL (filter_status_area), text);
227
228       g_free (text);
229     }
230 }
231
232 /* Callback for when the dictionary changes its split variables */
233 static void
234 on_split_change (PsppireDict *dict, gpointer data)
235 {
236   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
237
238   size_t n_split_vars = dict_get_split_cnt (dict->dict);
239
240   GtkWidget *split_status_area =
241     get_widget_assert (de->xml, "split-file-status-area");
242
243   if ( n_split_vars == 0 )
244     {
245       gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
246     }
247   else
248     {
249       gint i;
250       GString *text;
251       const struct variable *const * split_vars =
252         dict_get_split_vars (dict->dict);
253
254       text = g_string_new (_("Split by "));
255
256       for (i = 0 ; i < n_split_vars - 1; ++i )
257         {
258           g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
259         }
260       g_string_append (text, var_get_name (split_vars[i]));
261
262       gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
263
264       g_string_free (text, TRUE);
265     }
266 }
267
268
269
270
271 /* Callback for when the dictionary changes its weights */
272 static void
273 on_weight_change (GObject *o, gint weight_index, gpointer data)
274 {
275   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
276
277   GtkWidget *weight_status_area =
278     get_widget_assert (de->xml, "weight-status-area");
279
280   if ( weight_index == -1 )
281     {
282       gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
283     }
284   else
285     {
286       struct variable *var ;
287       PsppireVarStore *vs = NULL;
288       gchar *text;
289
290       g_object_get (de->data_editor, "var-store", &vs, NULL);
291
292       var = psppire_dict_get_variable (vs->dict, weight_index);
293
294       text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
295
296       gtk_label_set_text (GTK_LABEL (weight_status_area), text);
297
298       g_free (text);
299     }
300 }
301
302 /* Puts FILE_NAME into the recent list.
303    If it's already in the list, it moves it to the top
304 */
305 static void
306 add_most_recent (const char *file_name)
307 {
308 #if RECENT_LISTS_AVAILABLE
309
310   GtkRecentManager *manager = gtk_recent_manager_get_default();
311   gchar *uri = g_filename_to_uri (file_name, NULL, NULL);
312
313   gtk_recent_manager_remove_item (manager, uri, NULL);
314
315   if ( ! gtk_recent_manager_add_item (manager, uri))
316     g_warning ("Could not add item %s to recent list\n",uri);
317
318   g_free (uri);
319 #endif
320 }
321
322 static void
323 open_data_file (const gchar *file_name, PsppireDataWindow *de)
324 {
325   struct getl_interface *sss;
326   struct string filename;
327
328   ds_init_empty (&filename);
329   syntax_gen_string (&filename, ss_cstr (file_name));
330
331   sss = create_syntax_string_source ("GET FILE=%s.",
332                                      ds_cstr (&filename));
333   ds_destroy (&filename);
334
335   if (execute_syntax (sss) )
336   {
337     psppire_window_set_filename (PSPPIRE_WINDOW (de), file_name);
338     add_most_recent (file_name);
339   }
340 }
341
342
343 /* Callback for the data_open action.
344    Prompts for a filename and opens it */
345 static void
346 open_data_dialog (GtkAction *action, PsppireDataWindow *de)
347 {
348   GtkWidget *dialog =
349     gtk_file_chooser_dialog_new (_("Open"),
350                                  GTK_WINDOW (de),
351                                  GTK_FILE_CHOOSER_ACTION_OPEN,
352                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
353                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
354                                  NULL);
355
356   GtkFileFilter *filter = gtk_file_filter_new ();
357   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
358   gtk_file_filter_add_pattern (filter, "*.sav");
359   gtk_file_filter_add_pattern (filter, "*.SAV");
360   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
361
362   filter = gtk_file_filter_new ();
363   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
364   gtk_file_filter_add_pattern (filter, "*.por");
365   gtk_file_filter_add_pattern (filter, "*.POR");
366   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
367
368   filter = gtk_file_filter_new ();
369   gtk_file_filter_set_name (filter, _("All Files"));
370   gtk_file_filter_add_pattern (filter, "*");
371   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
372
373
374   if (de->file_name)
375     {
376       gchar *dir_name = g_path_get_dirname (de->file_name);
377       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
378                                            dir_name);
379       free (dir_name);
380     }
381
382   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
383     {
384     case GTK_RESPONSE_ACCEPT:
385       {
386         g_free (de->file_name);
387         de->file_name =
388           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
389
390         open_data_file (de->file_name, de);
391       }
392       break;
393     default:
394       break;
395     }
396
397   gtk_widget_destroy (dialog);
398 }
399
400 /* Returns true if NAME has a suffix which might denote a PSPP file */
401 static gboolean
402 name_has_suffix (const gchar *name)
403 {
404   if ( g_str_has_suffix (name, ".sav"))
405     return TRUE;
406   if ( g_str_has_suffix (name, ".SAV"))
407     return TRUE;
408   if ( g_str_has_suffix (name, ".por"))
409     return TRUE;
410   if ( g_str_has_suffix (name, ".POR"))
411     return TRUE;
412
413   return FALSE;
414 }
415
416
417 /* Append SUFFIX to the filename of DE */
418 static void
419 append_filename_suffix (PsppireDataWindow *de, const gchar *suffix)
420 {
421   if ( ! name_has_suffix (de->file_name))
422     {
423       gchar *s = de->file_name;
424       de->file_name = g_strconcat (de->file_name, suffix, NULL);
425       g_free (s);
426     }
427 }
428
429 /* Save DE to file */
430 static void
431 save_file (PsppireDataWindow *de)
432 {
433   struct getl_interface *sss;
434   struct string file_name ;
435
436   g_assert (de->file_name);
437
438   ds_init_empty (&file_name);
439   syntax_gen_string (&file_name, ss_cstr (de->file_name));
440
441   if ( de->save_as_portable )
442     {
443       append_filename_suffix (de, ".por");
444       sss = create_syntax_string_source ("EXPORT OUTFILE=%s.",
445                                          ds_cstr (&file_name));
446     }
447   else
448     {
449       append_filename_suffix (de, ".sav");
450       sss = create_syntax_string_source ("SAVE OUTFILE=%s.",
451                                          ds_cstr (&file_name));
452     }
453
454   ds_destroy (&file_name);
455
456   execute_syntax (sss);
457 }
458
459
460 static void
461 insert_case (GtkAction *action, gpointer data)
462 {
463   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (data);
464
465   psppire_data_editor_insert_case (dw->data_editor);
466 }
467
468 static void
469 on_insert_variable (GtkAction *action, gpointer data)
470 {
471   PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
472   psppire_data_editor_insert_variable (de);
473 }
474
475
476 /* Callback for data_save_as action. Prompt for a filename and save */
477 static void
478 data_save_as_dialog (GtkAction *action, PsppireDataWindow *de)
479 {
480   GtkWidget *button_sys;
481   GtkWidget *dialog =
482     gtk_file_chooser_dialog_new (_("Save"),
483                                  GTK_WINDOW (de),
484                                  GTK_FILE_CHOOSER_ACTION_SAVE,
485                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
486                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
487                                  NULL);
488
489   GtkFileFilter *filter = gtk_file_filter_new ();
490   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
491   gtk_file_filter_add_pattern (filter, "*.sav");
492   gtk_file_filter_add_pattern (filter, "*.SAV");
493   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
494
495   filter = gtk_file_filter_new ();
496   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
497   gtk_file_filter_add_pattern (filter, "*.por");
498   gtk_file_filter_add_pattern (filter, "*.POR");
499   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
500
501   filter = gtk_file_filter_new ();
502   gtk_file_filter_set_name (filter, _("All Files"));
503   gtk_file_filter_add_pattern (filter, "*");
504   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
505
506   {
507     GtkWidget *button_por;
508     GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
509     button_sys =
510       gtk_radio_button_new_with_label (NULL, _("System File"));
511
512     button_por =
513       gtk_radio_button_new_with_label
514       (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
515        _("Portable File"));
516
517     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
518     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_por);
519
520     gtk_widget_show_all (vbox);
521
522     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
523   }
524
525   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
526     {
527     case GTK_RESPONSE_ACCEPT:
528       {
529         g_free (de->file_name);
530
531         de->file_name =
532           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
533
534         de->save_as_portable =
535           ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
536
537         if ( de->save_as_portable)
538           append_filename_suffix (de, ".por");
539         else
540           append_filename_suffix (de, ".sav");
541
542         save_file (de);
543
544         psppire_window_set_filename (PSPPIRE_WINDOW (de), de->file_name);
545       }
546       break;
547     default:
548       break;
549     }
550
551   gtk_widget_destroy (dialog);
552 }
553
554
555 /* Callback for data_save action.
556    If there's an existing file name, then just save,
557    otherwise prompt for a file name, then save */
558 static void
559 data_save (GtkAction *action, PsppireDataWindow *de)
560 {
561   if ( de->file_name)
562     save_file (de);
563   else
564     data_save_as_dialog (action, de);
565 }
566
567
568 /* Callback for data_new action.
569    Performs the NEW FILE command */
570 static void
571 new_file (GtkAction *action, PsppireDataWindow *de)
572 {
573   struct getl_interface *sss =
574     create_syntax_string_source ("NEW FILE.");
575
576   execute_syntax (sss);
577
578   g_free (de->file_name);
579   de->file_name = NULL;
580
581   psppire_window_set_filename (PSPPIRE_WINDOW (de), NULL);
582 }
583
584
585
586 /* Create the GtkActions and connect to their signals */
587 static void
588 register_data_editor_actions (PsppireDataWindow *de)
589 {
590   de->action_data_open =
591     gtk_action_new ("data-open-dialog",
592                     _("Open"),
593                     _("Open a data file"),
594                     "gtk-open");
595
596   g_signal_connect (de->action_data_open, "activate",
597                     G_CALLBACK (open_data_dialog), de);
598
599
600   de->action_data_save = gtk_action_new ("data-save",
601                                             _("Save"),
602                                             _("Save data to file"),
603                                             "gtk-save");
604
605   g_signal_connect (de->action_data_save, "activate",
606                     G_CALLBACK (data_save), de);
607
608
609   de->action_data_save_as = gtk_action_new ("data-save-as-dialog",
610                                             _("Save As"),
611                                             _("Save data to file"),
612                                             "gtk-save");
613
614   g_signal_connect (de->action_data_save_as, "activate",
615                     G_CALLBACK (data_save_as_dialog), de);
616
617   de->action_data_new =
618     gtk_action_new ("data-new",
619                     _("New"),
620                     _("New data file"),
621                     NULL);
622
623   g_signal_connect (de->action_data_new, "activate",
624                     G_CALLBACK (new_file), de);
625
626   de->invoke_text_import_assistant =
627     gtk_action_new ("file_import-text",
628                     _("_Import Text Data"),
629                     _("Import text data file"),
630                     "");
631
632   g_signal_connect (de->invoke_text_import_assistant, "activate",
633                     G_CALLBACK (text_data_import_assistant), de);
634 }
635
636 static void
637 on_edit_paste (GtkAction *a, gpointer data)
638 {
639   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
640
641   psppire_data_editor_clip_paste (de->data_editor);
642 }
643
644 static void
645 on_edit_copy (GtkMenuItem *m, gpointer data)
646 {
647   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
648
649   psppire_data_editor_clip_copy (de->data_editor);
650 }
651
652
653
654 static void
655 on_edit_cut (GtkMenuItem *m, gpointer data)
656 {
657   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
658
659   psppire_data_editor_clip_cut (de->data_editor);
660 }
661
662
663 static void
664 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
665 {
666   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
667   GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
668
669   if ( gtk_check_menu_item_get_active (menuitem) )
670     gtk_widget_show (statusbar);
671   else
672     gtk_widget_hide (statusbar);
673 }
674
675
676 static void
677 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
678 {
679   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
680   const gboolean grid_visible = gtk_check_menu_item_get_active (menuitem);
681
682   psppire_data_editor_show_grid (de->data_editor, grid_visible);
683 }
684
685
686
687 static void
688 data_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
689 {
690   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
691
692   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
693 }
694
695
696 static void
697 variable_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
698 {
699   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
700
701   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
702 }
703
704
705 static void
706 fonts_activate (GtkMenuItem *menuitem, gpointer data)
707 {
708   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
709   PangoFontDescription *current_font;
710   gchar *font_name;
711   GtkWidget *dialog =
712     gtk_font_selection_dialog_new (_("Font Selection"));
713
714
715   current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
716   font_name = pango_font_description_to_string (current_font);
717
718   gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
719
720   g_free (font_name);
721
722   gtk_window_set_transient_for (GTK_WINDOW (dialog),
723                                 GTK_WINDOW (get_widget_assert (de->xml,
724                                                                "data_editor")));
725   if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
726     {
727       const gchar *font = gtk_font_selection_dialog_get_font_name
728         (GTK_FONT_SELECTION_DIALOG (dialog));
729
730       PangoFontDescription* font_desc =
731         pango_font_description_from_string (font);
732
733       psppire_data_editor_set_font (de->data_editor, font_desc);
734     }
735
736   gtk_widget_hide (dialog);
737 }
738
739
740
741 /* Callback for the value labels action */
742 static void
743 toggle_value_labels (GtkToggleAction *ta, gpointer data)
744 {
745   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
746
747   g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
748 }
749
750 static void
751 toggle_split_window (GtkToggleAction *ta, gpointer data)
752 {
753   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
754
755   psppire_data_editor_split_window (de->data_editor,
756                                     gtk_toggle_action_get_active (ta));
757 }
758
759
760 static void
761 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
762 {
763   /* FIXME: Need to be more intelligent here.
764      Give the user the opportunity to save any unsaved data.
765   */
766   g_object_unref (the_data_store);
767   gtk_main_quit ();
768 }
769
770
771
772 static GtkWidget *
773 create_data_sheet_variable_popup_menu (PsppireDataWindow *de)
774 {
775   GtkWidget *menu = gtk_menu_new ();
776
777   GtkWidget *sort_ascending =
778     gtk_menu_item_new_with_label (_("Sort Ascending"));
779
780   GtkWidget *sort_descending =
781     gtk_menu_item_new_with_label (_("Sort Descending"));
782
783   GtkWidget *insert_variable =
784     gtk_menu_item_new_with_label (_("Insert Variable"));
785
786   GtkWidget *clear_variable =
787     gtk_menu_item_new_with_label (_("Clear"));
788
789
790   gtk_action_connect_proxy (de->delete_variables,
791                             clear_variable );
792
793
794   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
795
796
797   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
798                          gtk_separator_menu_item_new ());
799
800
801   gtk_menu_shell_append (GTK_MENU_SHELL (menu), clear_variable);
802
803
804   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
805                          gtk_separator_menu_item_new ());
806
807
808   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_ascending);
809
810
811   g_signal_connect_swapped (G_OBJECT (sort_ascending), "activate",
812                             G_CALLBACK (psppire_data_editor_sort_ascending),
813                             de->data_editor);
814
815   g_signal_connect_swapped (G_OBJECT (sort_descending), "activate",
816                             G_CALLBACK (psppire_data_editor_sort_descending),
817                             de->data_editor);
818
819   g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
820                             G_CALLBACK (gtk_action_activate),
821                             de->insert_variable);
822
823
824   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_descending);
825
826   gtk_widget_show_all (menu);
827
828   return menu;
829 }
830
831
832 static GtkWidget *
833 create_data_sheet_cases_popup_menu (PsppireDataWindow *de)
834 {
835   GtkWidget *menu = gtk_menu_new ();
836
837   GtkWidget *insert_case =
838     gtk_menu_item_new_with_label (_("Insert Case"));
839
840   GtkWidget *delete_case =
841     gtk_menu_item_new_with_label (_("Clear"));
842
843
844   gtk_action_connect_proxy (de->delete_cases,
845                             delete_case);
846
847
848   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_case);
849
850   g_signal_connect_swapped (G_OBJECT (insert_case), "activate",
851                             G_CALLBACK (gtk_action_activate),
852                             de->insert_case);
853
854
855   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
856                          gtk_separator_menu_item_new ());
857
858
859   gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_case);
860
861
862   gtk_widget_show_all (menu);
863
864   return menu;
865 }
866
867
868 static GtkWidget *
869 create_var_sheet_variable_popup_menu (PsppireDataWindow *de)
870 {
871   GtkWidget *menu = gtk_menu_new ();
872
873   GtkWidget *insert_variable =
874     gtk_menu_item_new_with_label (_("Insert Variable"));
875
876   GtkWidget *delete_variable =
877     gtk_menu_item_new_with_label (_("Clear"));
878
879
880   gtk_action_connect_proxy (de->delete_variables,
881                             delete_variable);
882
883
884   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
885
886   g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
887                             G_CALLBACK (gtk_action_activate),
888                             de->insert_variable);
889
890
891   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
892                          gtk_separator_menu_item_new ());
893
894
895   gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_variable);
896
897
898   gtk_widget_show_all (menu);
899
900   return menu;
901 }
902
903
904 #if RECENT_LISTS_AVAILABLE
905
906 static void
907 on_recent_data_select (GtkMenuShell *menushell,   gpointer user_data)
908 {
909   gchar *file;
910   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (user_data);
911
912   gchar *uri =
913     gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
914
915   file = g_filename_from_uri (uri, NULL, NULL);
916
917   g_free (uri);
918
919   open_data_file (file, de);
920
921   g_free (file);
922 }
923
924 static void
925 on_recent_files_select (GtkMenuShell *menushell,   gpointer user_data)
926 {
927   gchar *file;
928
929   GtkWidget *se ;
930
931   gchar *uri =
932     gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
933
934   file = g_filename_from_uri (uri, NULL, NULL);
935
936   g_free (uri);
937
938   se = psppire_syntax_window_new ();
939
940   psppire_syntax_window_load_from_file (PSPPIRE_SYNTAX_WINDOW (se), file, NULL);
941   gtk_widget_show (se);
942
943   g_free (file);
944 }
945
946 #endif
947
948 static void
949 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
950 {
951   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
952
953   gtk_action_set_visible (de->delete_cases, case_num != -1);
954 }
955
956
957 static void
958 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
959 {
960   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
961
962   gtk_action_set_visible (de->delete_variables, var != -1);
963 }
964
965 /* Callback for when the datasheet/varsheet is selected */
966 static void
967 on_switch_sheet (GtkNotebook *notebook,
968                 GtkNotebookPage *page,
969                 guint page_num,
970                 gpointer user_data)
971 {
972   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
973
974   GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
975   GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables");
976
977   switch (page_num)
978     {
979     case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
980       gtk_widget_hide (view_variables);
981       gtk_widget_show (view_data);
982       gtk_action_set_sensitive (de->insert_variable, TRUE);
983       gtk_action_set_sensitive (de->insert_case, FALSE);
984       gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
985       break;
986     case PSPPIRE_DATA_EDITOR_DATA_VIEW:
987       gtk_widget_show (view_variables);
988       gtk_widget_hide (view_data);
989       gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
990       gtk_action_set_sensitive (de->insert_case, TRUE);
991       break;
992     default:
993       g_assert_not_reached ();
994       break;
995     }
996
997 #if 0
998   update_paste_menuitem (de, page_num);
999 #endif
1000 }
1001
1002
1003
1004
1005 static void
1006 psppire_data_window_init (PsppireDataWindow *de)
1007 {
1008   PsppireVarStore *vs;
1009
1010   GtkWidget *menubar;
1011   GtkWidget *hb ;
1012   GtkWidget *sb ;
1013
1014   GtkWidget *box = gtk_vbox_new (FALSE, 0);
1015   de->xml = XML_NEW ("data-editor.glade");
1016
1017   menubar = get_widget_assert (de->xml, "menubar");
1018   hb = get_widget_assert (de->xml, "handlebox1");
1019   sb = get_widget_assert (de->xml, "status-bar");
1020
1021   de->data_editor =
1022     PSPPIRE_DATA_EDITOR (psppire_data_editor_new (the_var_store, the_data_store));
1023
1024   connect_help (de->xml);
1025
1026   g_object_ref (menubar);
1027   gtk_widget_unparent (menubar);
1028
1029   g_object_ref (hb);
1030   gtk_widget_unparent (hb);
1031
1032   g_object_ref (sb);
1033   gtk_widget_unparent (sb);
1034
1035   gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
1036   gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
1037   gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
1038   gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
1039
1040   gtk_container_add (GTK_CONTAINER (de), box);
1041
1042   g_signal_connect (de->data_editor, "data-selection-changed",
1043                     G_CALLBACK (update_cut_copy_menuitems), de);
1044
1045   g_signal_connect (de->data_editor, "data-available-changed",
1046                     G_CALLBACK (update_paste_menuitems), de);
1047
1048   dataset_add_transform_change_callback (the_dataset,
1049                                          transformation_change_callback,
1050                                          de);
1051
1052
1053   vs = the_var_store;
1054
1055   g_assert(vs); /* Traps a possible bug in w32 build */
1056
1057   g_signal_connect (vs->dict, "weight-changed",
1058                     G_CALLBACK (on_weight_change),
1059                     de);
1060
1061   g_signal_connect (vs->dict, "filter-changed",
1062                     G_CALLBACK (on_filter_change),
1063                     de);
1064
1065   g_signal_connect (vs->dict, "split-changed",
1066                     G_CALLBACK (on_split_change),
1067                     de);
1068
1069
1070   g_signal_connect (get_widget_assert (de->xml, "edit_copy"),
1071                     "activate",
1072                     G_CALLBACK (on_edit_copy), de);
1073
1074   g_signal_connect (get_widget_assert (de->xml, "edit_cut"),
1075                     "activate",
1076                     G_CALLBACK (on_edit_cut), de);
1077
1078
1079   register_data_editor_actions (de);
1080
1081   de->toggle_value_labels =
1082     gtk_toggle_action_new ("toggle-value-labels",
1083                            _("_Labels"),
1084                            _("Show/hide value labels"),
1085                            "pspp-value-labels");
1086
1087   g_signal_connect (de->toggle_value_labels, "toggled",
1088                     G_CALLBACK (toggle_value_labels), de);
1089
1090
1091   gtk_action_connect_proxy (GTK_ACTION (de->toggle_value_labels),
1092                             get_widget_assert (de->xml,
1093                                                "togglebutton-value-labels"));
1094
1095
1096   gtk_action_connect_proxy (GTK_ACTION (de->toggle_value_labels),
1097                             get_widget_assert (de->xml,
1098                                                "view_value-labels"));
1099
1100
1101
1102   de->delete_cases =
1103     gtk_action_new ("clear-cases",
1104                     _("Clear"),
1105                     _("Delete the cases at the selected position(s)"),
1106                     "pspp-clear-cases");
1107
1108   g_signal_connect_swapped (de->delete_cases, "activate",
1109                     G_CALLBACK (psppire_data_editor_delete_cases),
1110                     de->data_editor);
1111
1112   gtk_action_connect_proxy (de->delete_cases,
1113                             get_widget_assert (de->xml, "edit_clear-cases"));
1114
1115   g_signal_connect (get_widget_assert (de->xml, "edit_paste"), "activate",
1116                     G_CALLBACK (on_edit_paste),
1117                     de);
1118
1119   gtk_action_set_visible (de->delete_cases, FALSE);
1120
1121   de->delete_variables =
1122     gtk_action_new ("clear-variables",
1123                     _("Clear"),
1124                     _("Delete the variables at the selected position(s)"),
1125                     "pspp-clear-variables");
1126
1127   g_signal_connect_swapped (de->delete_variables, "activate",
1128                             G_CALLBACK (psppire_data_editor_delete_variables),
1129                             de->data_editor);
1130
1131   gtk_action_connect_proxy (de->delete_variables,
1132                             get_widget_assert (de->xml, "edit_clear-variables")
1133                             );
1134
1135   gtk_action_set_visible (de->delete_variables, FALSE);
1136
1137   de->insert_variable =
1138     gtk_action_new ("insert-variable",
1139                     _("Insert _Variable"),
1140                     _("Create a new variable at the current position"),
1141                     "pspp-insert-variable");
1142
1143   g_signal_connect (de->insert_variable, "activate",
1144                     G_CALLBACK (on_insert_variable), de->data_editor);
1145
1146
1147   gtk_action_connect_proxy (de->insert_variable,
1148                             get_widget_assert (de->xml, "button-insert-variable")
1149                             );
1150
1151   gtk_action_connect_proxy (de->insert_variable,
1152                             get_widget_assert (de->xml, "edit_insert-variable")
1153                             );
1154
1155
1156   de->insert_case =
1157     gtk_action_new ("insert-case",
1158                     _("Insert Ca_se"),
1159                     _("Create a new case at the current position"),
1160                     "pspp-insert-case");
1161
1162   g_signal_connect (de->insert_case, "activate",
1163                     G_CALLBACK (insert_case), de);
1164
1165
1166   gtk_action_connect_proxy (de->insert_case,
1167                             get_widget_assert (de->xml, "button-insert-case")
1168                             );
1169
1170
1171   gtk_action_connect_proxy (de->insert_case,
1172                             get_widget_assert (de->xml, "edit_insert-case")
1173                             );
1174
1175
1176   de->invoke_goto_dialog =
1177     gtk_action_new ("goto-case-dialog",
1178                     _("_Goto Case"),
1179                     _("Jump to a Case in the Data Sheet"),
1180                     "gtk-jump-to");
1181
1182
1183   gtk_action_connect_proxy (de->invoke_goto_dialog,
1184                             get_widget_assert (de->xml, "button-goto-case")
1185                             );
1186
1187   gtk_action_connect_proxy (de->invoke_goto_dialog,
1188                             get_widget_assert (de->xml, "edit_goto-case")
1189                             );
1190
1191
1192   g_signal_connect (de->invoke_goto_dialog, "activate",
1193                     G_CALLBACK (goto_case_dialog), de);
1194
1195   de->invoke_weight_cases_dialog =
1196     gtk_action_new ("weight-cases-dialog",
1197                     _("_Weights"),
1198                     _("Weight cases by variable"),
1199                     "pspp-weight-cases");
1200
1201   g_signal_connect (de->invoke_weight_cases_dialog, "activate",
1202                     G_CALLBACK (weight_cases_dialog), de);
1203
1204
1205   de->invoke_transpose_dialog =
1206     gtk_action_new ("transpose-dialog",
1207                     _("_Transpose"),
1208                     _("Transpose the cases with the variables"),
1209                     NULL);
1210
1211
1212   g_signal_connect (de->invoke_transpose_dialog, "activate",
1213                     G_CALLBACK (transpose_dialog), de);
1214
1215
1216
1217   de->invoke_split_file_dialog =
1218     gtk_action_new ("split-file-dialog",
1219                     _("S_plit"),
1220                     _("Split the active file"),
1221                     "pspp-split-file");
1222
1223   g_signal_connect (de->invoke_split_file_dialog, "activate",
1224                     G_CALLBACK (split_file_dialog), de);
1225
1226
1227
1228   de->invoke_sort_cases_dialog =
1229     gtk_action_new ("sort-cases-dialog",
1230                     _("_Sort"),
1231                     _("Sort cases in the active file"),
1232                     "pspp-sort-cases");
1233
1234   g_signal_connect (de->invoke_sort_cases_dialog, "activate",
1235                     G_CALLBACK (sort_cases_dialog), de);
1236
1237   de->invoke_select_cases_dialog =
1238     gtk_action_new ("select-cases-dialog",
1239                     _("Select _Cases"),
1240                     _("Select cases from the active file"),
1241                     "pspp-select-cases");
1242
1243   g_signal_connect (de->invoke_select_cases_dialog, "activate",
1244                     G_CALLBACK (select_cases_dialog), de);
1245
1246
1247   de->invoke_compute_dialog =
1248     gtk_action_new ("compute-dialog",
1249                     _("_Compute"),
1250                     _("Compute new values for a variable"),
1251                     "pspp-compute");
1252
1253   g_signal_connect (de->invoke_compute_dialog, "activate",
1254                     G_CALLBACK (compute_dialog), de);
1255
1256   de->invoke_oneway_anova_dialog =
1257     gtk_action_new ("oneway-anova",
1258                     _("Oneway _ANOVA"),
1259                     _("Perform one way analysis of variance"),
1260                     NULL);
1261
1262   g_signal_connect (de->invoke_oneway_anova_dialog, "activate",
1263                     G_CALLBACK (oneway_anova_dialog), de);
1264
1265   de->invoke_t_test_independent_samples_dialog =
1266     gtk_action_new ("t-test-independent-samples",
1267                     _("_Independent Samples T Test"),
1268                     _("Calculate T Test for samples from independent groups"),
1269                     NULL);
1270
1271   g_signal_connect (de->invoke_t_test_independent_samples_dialog, "activate",
1272                     G_CALLBACK (t_test_independent_samples_dialog), de);
1273
1274
1275   de->invoke_t_test_paired_samples_dialog =
1276     gtk_action_new ("t-test-paired-samples",
1277                     _("_Paired Samples T Test"),
1278                     _("Calculate T Test for paired samples"),
1279                     NULL);
1280
1281   g_signal_connect (de->invoke_t_test_paired_samples_dialog, "activate",
1282                     G_CALLBACK (t_test_paired_samples_dialog), de);
1283
1284
1285   de->invoke_t_test_one_sample_dialog =
1286     gtk_action_new ("t-test-one-sample",
1287                     _("One _Sample T Test"),
1288                     _("Calculate T Test for sample from a single distribution"),
1289                     NULL);
1290
1291   g_signal_connect (de->invoke_t_test_one_sample_dialog, "activate",
1292                     G_CALLBACK (t_test_one_sample_dialog), de);
1293
1294
1295   de->invoke_comments_dialog =
1296     gtk_action_new ("commments-dialog",
1297                     _("Data File _Comments"),
1298                     _("Commentary text for the data file"),
1299                     NULL);
1300
1301   g_signal_connect (de->invoke_comments_dialog, "activate",
1302                     G_CALLBACK (comments_dialog), de);
1303
1304   de->invoke_find_dialog  =
1305     gtk_action_new ("find-dialog",
1306                     _("_Find"),
1307                     _("Find Case"),
1308                     "gtk-find");
1309
1310   g_signal_connect (de->invoke_find_dialog, "activate",
1311                     G_CALLBACK (find_dialog), de);
1312
1313
1314   de->invoke_rank_dialog  =
1315     gtk_action_new ("rank-dialog",
1316                     _("Ran_k Cases"),
1317                     _("Rank Cases"),
1318                     "pspp-rank-cases");
1319
1320   g_signal_connect (de->invoke_rank_dialog, "activate",
1321                     G_CALLBACK (rank_dialog), de);
1322
1323
1324   de->invoke_recode_same_dialog  =
1325     gtk_action_new ("recode-same-dialog",
1326                     _("Recode into _Same Variables"),
1327                     _("Recode values into the same Variables"),
1328                     "pspp-recode-same");
1329
1330   g_signal_connect (de->invoke_recode_same_dialog, "activate",
1331                     G_CALLBACK (recode_same_dialog), de);
1332
1333
1334   de->invoke_recode_different_dialog  =
1335     gtk_action_new ("recode-different-dialog",
1336                     _("Recode into _Different Variables"),
1337                     _("Recode values into different Variables"),
1338                     "pspp-recode-different");
1339
1340   g_signal_connect (de->invoke_recode_different_dialog, "activate",
1341                     G_CALLBACK (recode_different_dialog), de);
1342
1343
1344   de->invoke_variable_info_dialog  =
1345     gtk_action_new ("variable-info-dialog",
1346                     _("_Variables"),
1347                     _("Jump to Variable"),
1348                     "pspp-goto-variable");
1349
1350   g_signal_connect (de->invoke_variable_info_dialog, "activate",
1351                     G_CALLBACK (variable_info_dialog), de);
1352
1353   de->invoke_descriptives_dialog =
1354     gtk_action_new ("descriptives-dialog",
1355                     _("_Descriptives"),
1356                     _("Calculate descriptive statistics (mean, variance, ...)"),
1357                     "pspp-descriptives");
1358
1359   g_signal_connect (de->invoke_descriptives_dialog, "activate",
1360                     G_CALLBACK (descriptives_dialog), de);
1361
1362
1363   de->invoke_frequencies_dialog =
1364     gtk_action_new ("frequencies-dialog",
1365                     _("_Frequencies"),
1366                     _("Generate frequency statistics"),
1367                     "pspp-frequencies");
1368
1369   g_signal_connect (de->invoke_frequencies_dialog, "activate",
1370                     G_CALLBACK (frequencies_dialog), de);
1371
1372   de->invoke_crosstabs_dialog =
1373     gtk_action_new ("crosstabs-dialog",
1374                     _("_Crosstabs"),
1375                     _("Generate crosstabulations"),
1376                     "pspp-crosstabs");
1377
1378   g_signal_connect (de->invoke_crosstabs_dialog, "activate",
1379                     G_CALLBACK (crosstabs_dialog), de);
1380
1381
1382   de->invoke_examine_dialog =
1383     gtk_action_new ("examine-dialog",
1384                     _("_Explore"),
1385                     _("Examine Data by Factors"),
1386                     "pspp-examine");
1387
1388   g_signal_connect (de->invoke_examine_dialog, "activate",
1389                     G_CALLBACK (examine_dialog), de);
1390
1391
1392   de->invoke_regression_dialog =
1393     gtk_action_new ("regression-dialog",
1394                     _("Linear _Regression"),
1395                     _("Estimate parameters of the linear model"),
1396                     "pspp-regression");
1397
1398   g_signal_connect (de->invoke_regression_dialog, "activate",
1399                     G_CALLBACK (regression_dialog), de);
1400
1401   g_signal_connect_swapped (get_widget_assert (de->xml,"file_new_data"),
1402                             "activate",
1403                             G_CALLBACK (gtk_action_activate),
1404                             de->action_data_new);
1405
1406   g_signal_connect_swapped (get_widget_assert (de->xml,"file_open_data"),
1407                             "activate",
1408                             G_CALLBACK (gtk_action_activate),
1409                             de->action_data_open);
1410
1411 #if RECENT_LISTS_AVAILABLE
1412   {
1413     GtkRecentManager *rm = gtk_recent_manager_get_default ();
1414     GtkWidget *recent_data = get_widget_assert (de->xml, "file_recent-data");
1415     GtkWidget *recent_files = get_widget_assert (de->xml, "file_recent-files");
1416     GtkWidget *recent_separator = get_widget_assert (de->xml, "file_separator1");
1417
1418     GtkWidget *menu = gtk_recent_chooser_menu_new_for_manager (rm);
1419
1420     GtkRecentFilter *filter = gtk_recent_filter_new ();
1421
1422     gtk_widget_show (recent_data);
1423     gtk_widget_show (recent_files);
1424     gtk_widget_show (recent_separator);
1425
1426     gtk_recent_filter_add_pattern (filter, "*.sav");
1427     gtk_recent_filter_add_pattern (filter, "*.SAV");
1428
1429     gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1430
1431     gtk_widget_set_sensitive (recent_data, TRUE);
1432     g_signal_connect (menu, "selection-done",
1433                       G_CALLBACK (on_recent_data_select), de);
1434
1435     gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu);
1436
1437
1438     filter = gtk_recent_filter_new ();
1439     menu = gtk_recent_chooser_menu_new_for_manager (rm);
1440
1441     gtk_recent_filter_add_pattern (filter, "*.sps");
1442     gtk_recent_filter_add_pattern (filter, "*.SPS");
1443
1444     gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1445
1446     gtk_widget_set_sensitive (recent_files, TRUE);
1447     g_signal_connect (menu, "selection-done",
1448                       G_CALLBACK (on_recent_files_select), de);
1449
1450     gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu);
1451   }
1452 #endif
1453
1454   g_signal_connect (get_widget_assert (de->xml,"file_new_syntax"),
1455                     "activate",
1456                     G_CALLBACK (create_syntax_window),
1457                     NULL);
1458
1459   g_signal_connect (get_widget_assert (de->xml,"file_open_syntax"),
1460                     "activate",
1461                     G_CALLBACK (open_syntax_window),
1462                     de);
1463
1464   g_signal_connect_swapped (get_widget_assert (de->xml,"file_import-text"),
1465                             "activate",
1466                             G_CALLBACK (gtk_action_activate),
1467                             de->invoke_text_import_assistant);
1468
1469   g_signal_connect_swapped (get_widget_assert (de->xml,"file_save"),
1470                             "activate",
1471                             G_CALLBACK (gtk_action_activate),
1472                             de->action_data_save);
1473
1474   g_signal_connect_swapped (get_widget_assert (de->xml,"file_save_as"),
1475                             "activate",
1476                             G_CALLBACK (gtk_action_activate),
1477                             de->action_data_save_as);
1478
1479   gtk_action_connect_proxy (de->invoke_find_dialog,
1480                             get_widget_assert (de->xml, "edit_find")
1481                             );
1482
1483   gtk_action_connect_proxy (de->invoke_find_dialog,
1484                             get_widget_assert (de->xml, "button-find")
1485                             );
1486
1487   gtk_action_connect_proxy (de->invoke_rank_dialog,
1488                             get_widget_assert (de->xml, "transform_rank")
1489                             );
1490
1491   gtk_action_connect_proxy (de->invoke_recode_same_dialog,
1492                             get_widget_assert (de->xml,
1493                                                "transform_recode-same")
1494                             );
1495
1496   gtk_action_connect_proxy (de->invoke_recode_different_dialog,
1497                             get_widget_assert (de->xml,
1498                                                "transform_recode-different")
1499                             );
1500
1501   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
1502                             get_widget_assert (de->xml, "data_weight-cases")
1503                             );
1504
1505   gtk_action_connect_proxy (de->invoke_transpose_dialog,
1506                             get_widget_assert (de->xml, "data_transpose")
1507                             );
1508
1509   gtk_action_connect_proxy (de->invoke_split_file_dialog,
1510                             get_widget_assert (de->xml, "data_split-file")
1511                             );
1512
1513   gtk_action_connect_proxy (de->invoke_sort_cases_dialog,
1514                             get_widget_assert (de->xml, "data_sort-cases")
1515                             );
1516
1517   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
1518                             get_widget_assert (de->xml, "data_select-cases")
1519                             );
1520
1521   gtk_action_connect_proxy (de->invoke_compute_dialog,
1522                             get_widget_assert (de->xml, "transform_compute")
1523                             );
1524
1525   gtk_action_connect_proxy (de->invoke_t_test_independent_samples_dialog,
1526                             get_widget_assert (de->xml,
1527                                                "indep-t-test")
1528                             );
1529
1530
1531   gtk_action_connect_proxy (de->invoke_t_test_paired_samples_dialog,
1532                             get_widget_assert (de->xml,
1533                                                "paired-t-test")
1534                             );
1535
1536
1537   gtk_action_connect_proxy (de->invoke_t_test_one_sample_dialog,
1538                             get_widget_assert (de->xml,
1539                                                "one-sample-t-test")
1540                             );
1541
1542
1543   gtk_action_connect_proxy (de->invoke_oneway_anova_dialog,
1544                             get_widget_assert (de->xml,
1545                                                "oneway-anova")
1546                             );
1547
1548
1549   gtk_action_connect_proxy (de->invoke_comments_dialog,
1550                             get_widget_assert (de->xml, "utilities_comments")
1551                             );
1552
1553   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
1554                             get_widget_assert (de->xml, "utilities_variables")
1555                             );
1556
1557   gtk_action_connect_proxy (de->invoke_descriptives_dialog,
1558                             get_widget_assert (de->xml, "analyze_descriptives")
1559                             );
1560
1561   gtk_action_connect_proxy (de->invoke_crosstabs_dialog,
1562                             get_widget_assert (de->xml, "crosstabs")
1563                             );
1564
1565   gtk_action_connect_proxy (de->invoke_frequencies_dialog,
1566                             get_widget_assert (de->xml, "analyze_frequencies")
1567                             );
1568
1569
1570   gtk_action_connect_proxy (de->invoke_examine_dialog,
1571                             get_widget_assert (de->xml, "analyze_explore")
1572                             );
1573
1574   gtk_action_connect_proxy (de->invoke_regression_dialog,
1575                             get_widget_assert (de->xml, "linear-regression")
1576                             );
1577
1578   g_signal_connect (get_widget_assert (de->xml,"help_about"),
1579                     "activate",
1580                     G_CALLBACK (about_new),
1581                     de);
1582
1583
1584   g_signal_connect (get_widget_assert (de->xml,"help_reference"),
1585                     "activate",
1586                     G_CALLBACK (reference_manual),
1587                     de);
1588
1589
1590   g_signal_connect (de->data_editor,
1591                     "cases-selected",
1592                     G_CALLBACK (enable_delete_cases),
1593                     de);
1594
1595   g_signal_connect (de->data_editor,
1596                     "variables-selected",
1597                     G_CALLBACK (enable_delete_variables),
1598                     de);
1599
1600
1601   g_signal_connect (GTK_NOTEBOOK (de->data_editor),
1602                     "switch-page",
1603                     G_CALLBACK (on_switch_sheet), de);
1604
1605   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1606   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1607
1608   g_signal_connect (get_widget_assert (de->xml, "view_statusbar"),
1609                     "activate",
1610                     G_CALLBACK (status_bar_activate), de);
1611
1612
1613   g_signal_connect (get_widget_assert (de->xml, "view_gridlines"),
1614                     "activate",
1615                     G_CALLBACK (grid_lines_activate), de);
1616
1617
1618
1619   g_signal_connect (get_widget_assert (de->xml, "view_data"),
1620                     "activate",
1621                     G_CALLBACK (data_view_activate), de);
1622
1623   g_signal_connect (get_widget_assert (de->xml, "view_variables"),
1624                     "activate",
1625                     G_CALLBACK (variable_view_activate), de);
1626
1627
1628
1629   g_signal_connect (get_widget_assert (de->xml, "view_fonts"),
1630                     "activate",
1631                     G_CALLBACK (fonts_activate), de);
1632
1633
1634
1635
1636   gtk_action_connect_proxy (de->action_data_open,
1637                             get_widget_assert (de->xml, "button-open")
1638                             );
1639
1640   gtk_action_connect_proxy (de->action_data_save,
1641                             get_widget_assert (de->xml, "button-save")
1642                             );
1643
1644   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
1645                             get_widget_assert (de->xml, "button-goto-variable")
1646                             );
1647
1648   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
1649                             get_widget_assert (de->xml, "button-weight-cases")
1650                             );
1651
1652   gtk_action_connect_proxy (de->invoke_split_file_dialog,
1653                             get_widget_assert (de->xml, "button-split-file")
1654                             );
1655
1656   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
1657                             get_widget_assert (de->xml, "button-select-cases")
1658                             );
1659
1660
1661   g_signal_connect (get_widget_assert (de->xml, "file_quit"),
1662                     "activate",
1663                     G_CALLBACK (file_quit), de);
1664
1665   g_signal_connect (get_widget_assert (de->xml, "transform_run-pending"),
1666                     "activate",
1667                     G_CALLBACK (execute), de);
1668
1669
1670   g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
1671                     "activate",
1672                     G_CALLBACK (psppire_window_minimise_all), NULL);
1673
1674   de->toggle_split_window =
1675     gtk_toggle_action_new ("toggle-split-window",
1676                            _("_Split Window"),
1677                            _("Split the window vertically and horizontally"),
1678                            "pspp-split-window");
1679
1680   g_signal_connect (de->toggle_split_window, "toggled",
1681                     G_CALLBACK (toggle_split_window),
1682                     de);
1683
1684   gtk_action_connect_proxy (GTK_ACTION (de->toggle_split_window),
1685                             get_widget_assert (de->xml,
1686                                                "windows_split"));
1687
1688   de->data_sheet_variable_popup_menu =
1689     GTK_MENU (create_data_sheet_variable_popup_menu (de));
1690
1691   de->var_sheet_variable_popup_menu =
1692     GTK_MENU (create_var_sheet_variable_popup_menu (de));
1693
1694   de->data_sheet_cases_popup_menu =
1695     GTK_MENU (create_data_sheet_cases_popup_menu (de));
1696
1697   PSPPIRE_WINDOW (de)->menu = GTK_MENU_SHELL (get_widget_assert (de->xml,"Windows_menu"));
1698
1699   g_object_set (de->data_editor,
1700                 "datasheet-column-menu", de->data_sheet_variable_popup_menu,
1701                 "datasheet-row-menu", de->data_sheet_cases_popup_menu,
1702                 "varsheet-row-menu", de->var_sheet_variable_popup_menu,
1703                 NULL);
1704
1705   gtk_widget_show (GTK_WIDGET (de->data_editor));
1706   gtk_widget_show (box);
1707 }
1708
1709
1710 GtkWidget*
1711 psppire_data_window_new (void)
1712 {
1713   return GTK_WIDGET (g_object_new (psppire_data_window_get_type (),
1714                                    "usage", PSPPIRE_WINDOW_USAGE_DATA,
1715                                    NULL));
1716 }
1717