Unsaved indicator for data files.
[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   psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
342 }
343
344
345 /* Callback for the data_open action.
346    Prompts for a filename and opens it */
347 static void
348 open_data_dialog (GtkAction *action, PsppireDataWindow *de)
349 {
350   GtkWidget *dialog =
351     gtk_file_chooser_dialog_new (_("Open"),
352                                  GTK_WINDOW (de),
353                                  GTK_FILE_CHOOSER_ACTION_OPEN,
354                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
355                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
356                                  NULL);
357
358   GtkFileFilter *filter = gtk_file_filter_new ();
359   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
360   gtk_file_filter_add_pattern (filter, "*.sav");
361   gtk_file_filter_add_pattern (filter, "*.SAV");
362   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
363
364   filter = gtk_file_filter_new ();
365   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
366   gtk_file_filter_add_pattern (filter, "*.por");
367   gtk_file_filter_add_pattern (filter, "*.POR");
368   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
369
370   filter = gtk_file_filter_new ();
371   gtk_file_filter_set_name (filter, _("All Files"));
372   gtk_file_filter_add_pattern (filter, "*");
373   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
374
375
376   if (de->file_name)
377     {
378       gchar *dir_name = g_path_get_dirname (de->file_name);
379       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
380                                            dir_name);
381       free (dir_name);
382     }
383
384   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
385     {
386     case GTK_RESPONSE_ACCEPT:
387       {
388         g_free (de->file_name);
389         de->file_name =
390           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
391
392         open_data_file (de->file_name, de);
393       }
394       break;
395     default:
396       break;
397     }
398
399   gtk_widget_destroy (dialog);
400 }
401
402 /* Returns true if NAME has a suffix which might denote a PSPP file */
403 static gboolean
404 name_has_suffix (const gchar *name)
405 {
406   if ( g_str_has_suffix (name, ".sav"))
407     return TRUE;
408   if ( g_str_has_suffix (name, ".SAV"))
409     return TRUE;
410   if ( g_str_has_suffix (name, ".por"))
411     return TRUE;
412   if ( g_str_has_suffix (name, ".POR"))
413     return TRUE;
414
415   return FALSE;
416 }
417
418
419 /* Append SUFFIX to the filename of DE */
420 static void
421 append_filename_suffix (PsppireDataWindow *de, const gchar *suffix)
422 {
423   if ( ! name_has_suffix (de->file_name))
424     {
425       gchar *s = de->file_name;
426       de->file_name = g_strconcat (de->file_name, suffix, NULL);
427       g_free (s);
428     }
429 }
430
431 /* Save DE to file */
432 static void
433 save_file (PsppireDataWindow *de)
434 {
435   struct getl_interface *sss;
436   struct string file_name ;
437
438   g_assert (de->file_name);
439
440   ds_init_empty (&file_name);
441   syntax_gen_string (&file_name, ss_cstr (de->file_name));
442
443   if ( de->save_as_portable )
444     {
445       append_filename_suffix (de, ".por");
446       sss = create_syntax_string_source ("EXPORT OUTFILE=%s.",
447                                          ds_cstr (&file_name));
448     }
449   else
450     {
451       append_filename_suffix (de, ".sav");
452       sss = create_syntax_string_source ("SAVE OUTFILE=%s.",
453                                          ds_cstr (&file_name));
454     }
455
456   ds_destroy (&file_name);
457
458   execute_syntax (sss);
459
460   psppire_window_set_unsaved (PSPPIRE_WINDOW (de), FALSE);
461 }
462
463
464 static void
465 insert_case (GtkAction *action, gpointer data)
466 {
467   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (data);
468
469   psppire_data_editor_insert_case (dw->data_editor);
470 }
471
472 static void
473 on_insert_variable (GtkAction *action, gpointer data)
474 {
475   PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
476   psppire_data_editor_insert_variable (de);
477 }
478
479
480 /* Callback for data_save_as action. Prompt for a filename and save */
481 static void
482 data_save_as_dialog (GtkAction *action, PsppireDataWindow *de)
483 {
484   GtkWidget *button_sys;
485   GtkWidget *dialog =
486     gtk_file_chooser_dialog_new (_("Save"),
487                                  GTK_WINDOW (de),
488                                  GTK_FILE_CHOOSER_ACTION_SAVE,
489                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
490                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
491                                  NULL);
492
493   GtkFileFilter *filter = gtk_file_filter_new ();
494   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
495   gtk_file_filter_add_pattern (filter, "*.sav");
496   gtk_file_filter_add_pattern (filter, "*.SAV");
497   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
498
499   filter = gtk_file_filter_new ();
500   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
501   gtk_file_filter_add_pattern (filter, "*.por");
502   gtk_file_filter_add_pattern (filter, "*.POR");
503   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
504
505   filter = gtk_file_filter_new ();
506   gtk_file_filter_set_name (filter, _("All Files"));
507   gtk_file_filter_add_pattern (filter, "*");
508   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
509
510   {
511     GtkWidget *button_por;
512     GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
513     button_sys =
514       gtk_radio_button_new_with_label (NULL, _("System File"));
515
516     button_por =
517       gtk_radio_button_new_with_label
518       (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
519        _("Portable File"));
520
521     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
522     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_por);
523
524     gtk_widget_show_all (vbox);
525
526     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
527   }
528
529   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
530     {
531     case GTK_RESPONSE_ACCEPT:
532       {
533         g_free (de->file_name);
534
535         de->file_name =
536           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
537
538         de->save_as_portable =
539           ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
540
541         if ( de->save_as_portable)
542           append_filename_suffix (de, ".por");
543         else
544           append_filename_suffix (de, ".sav");
545
546         save_file (de);
547
548         psppire_window_set_filename (PSPPIRE_WINDOW (de), de->file_name);
549       }
550       break;
551     default:
552       break;
553     }
554
555   gtk_widget_destroy (dialog);
556 }
557
558
559 /* Callback for data_save action.
560    If there's an existing file name, then just save,
561    otherwise prompt for a file name, then save */
562 static void
563 data_save (GtkAction *action, PsppireDataWindow *de)
564 {
565   if ( de->file_name)
566     save_file (de);
567   else
568     data_save_as_dialog (action, de);
569 }
570
571
572 /* Callback for data_new action.
573    Performs the NEW FILE command */
574 static void
575 new_file (GtkAction *action, PsppireDataWindow *de)
576 {
577   struct getl_interface *sss =
578     create_syntax_string_source ("NEW FILE.");
579
580   execute_syntax (sss);
581
582   g_free (de->file_name);
583   de->file_name = NULL;
584
585   psppire_window_set_filename (PSPPIRE_WINDOW (de), NULL);
586 }
587
588
589
590 /* Create the GtkActions and connect to their signals */
591 static void
592 register_data_editor_actions (PsppireDataWindow *de)
593 {
594   de->action_data_open =
595     gtk_action_new ("data-open-dialog",
596                     _("Open"),
597                     _("Open a data file"),
598                     "gtk-open");
599
600   g_signal_connect (de->action_data_open, "activate",
601                     G_CALLBACK (open_data_dialog), de);
602
603
604   de->action_data_save = gtk_action_new ("data-save",
605                                             _("Save"),
606                                             _("Save data to file"),
607                                             "gtk-save");
608
609   g_signal_connect (de->action_data_save, "activate",
610                     G_CALLBACK (data_save), de);
611
612
613   de->action_data_save_as = gtk_action_new ("data-save-as-dialog",
614                                             _("Save As"),
615                                             _("Save data to file"),
616                                             "gtk-save");
617
618   g_signal_connect (de->action_data_save_as, "activate",
619                     G_CALLBACK (data_save_as_dialog), de);
620
621   de->action_data_new =
622     gtk_action_new ("data-new",
623                     _("New"),
624                     _("New data file"),
625                     NULL);
626
627   g_signal_connect (de->action_data_new, "activate",
628                     G_CALLBACK (new_file), de);
629
630   de->invoke_text_import_assistant =
631     gtk_action_new ("file_import-text",
632                     _("_Import Text Data"),
633                     _("Import text data file"),
634                     "");
635
636   g_signal_connect (de->invoke_text_import_assistant, "activate",
637                     G_CALLBACK (text_data_import_assistant), de);
638 }
639
640 static void
641 on_edit_paste (GtkAction *a, gpointer data)
642 {
643   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
644
645   psppire_data_editor_clip_paste (de->data_editor);
646 }
647
648 static void
649 on_edit_copy (GtkMenuItem *m, gpointer data)
650 {
651   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
652
653   psppire_data_editor_clip_copy (de->data_editor);
654 }
655
656
657
658 static void
659 on_edit_cut (GtkMenuItem *m, gpointer data)
660 {
661   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
662
663   psppire_data_editor_clip_cut (de->data_editor);
664 }
665
666
667 static void
668 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
669 {
670   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
671   GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
672
673   if ( gtk_check_menu_item_get_active (menuitem) )
674     gtk_widget_show (statusbar);
675   else
676     gtk_widget_hide (statusbar);
677 }
678
679
680 static void
681 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
682 {
683   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
684   const gboolean grid_visible = gtk_check_menu_item_get_active (menuitem);
685
686   psppire_data_editor_show_grid (de->data_editor, grid_visible);
687 }
688
689
690
691 static void
692 data_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
693 {
694   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
695
696   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
697 }
698
699
700 static void
701 variable_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
702 {
703   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
704
705   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
706 }
707
708
709 static void
710 fonts_activate (GtkMenuItem *menuitem, gpointer data)
711 {
712   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
713   PangoFontDescription *current_font;
714   gchar *font_name;
715   GtkWidget *dialog =
716     gtk_font_selection_dialog_new (_("Font Selection"));
717
718
719   current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
720   font_name = pango_font_description_to_string (current_font);
721
722   gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
723
724   g_free (font_name);
725
726   gtk_window_set_transient_for (GTK_WINDOW (dialog),
727                                 GTK_WINDOW (get_widget_assert (de->xml,
728                                                                "data_editor")));
729   if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
730     {
731       const gchar *font = gtk_font_selection_dialog_get_font_name
732         (GTK_FONT_SELECTION_DIALOG (dialog));
733
734       PangoFontDescription* font_desc =
735         pango_font_description_from_string (font);
736
737       psppire_data_editor_set_font (de->data_editor, font_desc);
738     }
739
740   gtk_widget_hide (dialog);
741 }
742
743
744
745 /* Callback for the value labels action */
746 static void
747 toggle_value_labels (GtkToggleAction *ta, gpointer data)
748 {
749   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
750
751   g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
752 }
753
754 static void
755 toggle_split_window (GtkToggleAction *ta, gpointer data)
756 {
757   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (data);
758
759   psppire_data_editor_split_window (de->data_editor,
760                                     gtk_toggle_action_get_active (ta));
761 }
762
763
764 static void
765 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
766 {
767   /* FIXME: Need to be more intelligent here.
768      Give the user the opportunity to save any unsaved data.
769   */
770   g_object_unref (the_data_store);
771   gtk_main_quit ();
772 }
773
774
775
776 static GtkWidget *
777 create_data_sheet_variable_popup_menu (PsppireDataWindow *de)
778 {
779   GtkWidget *menu = gtk_menu_new ();
780
781   GtkWidget *sort_ascending =
782     gtk_menu_item_new_with_label (_("Sort Ascending"));
783
784   GtkWidget *sort_descending =
785     gtk_menu_item_new_with_label (_("Sort Descending"));
786
787   GtkWidget *insert_variable =
788     gtk_menu_item_new_with_label (_("Insert Variable"));
789
790   GtkWidget *clear_variable =
791     gtk_menu_item_new_with_label (_("Clear"));
792
793
794   gtk_action_connect_proxy (de->delete_variables,
795                             clear_variable );
796
797
798   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
799
800
801   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
802                          gtk_separator_menu_item_new ());
803
804
805   gtk_menu_shell_append (GTK_MENU_SHELL (menu), clear_variable);
806
807
808   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
809                          gtk_separator_menu_item_new ());
810
811
812   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_ascending);
813
814
815   g_signal_connect_swapped (G_OBJECT (sort_ascending), "activate",
816                             G_CALLBACK (psppire_data_editor_sort_ascending),
817                             de->data_editor);
818
819   g_signal_connect_swapped (G_OBJECT (sort_descending), "activate",
820                             G_CALLBACK (psppire_data_editor_sort_descending),
821                             de->data_editor);
822
823   g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
824                             G_CALLBACK (gtk_action_activate),
825                             de->insert_variable);
826
827
828   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_descending);
829
830   gtk_widget_show_all (menu);
831
832   return menu;
833 }
834
835
836 static GtkWidget *
837 create_data_sheet_cases_popup_menu (PsppireDataWindow *de)
838 {
839   GtkWidget *menu = gtk_menu_new ();
840
841   GtkWidget *insert_case =
842     gtk_menu_item_new_with_label (_("Insert Case"));
843
844   GtkWidget *delete_case =
845     gtk_menu_item_new_with_label (_("Clear"));
846
847
848   gtk_action_connect_proxy (de->delete_cases,
849                             delete_case);
850
851
852   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_case);
853
854   g_signal_connect_swapped (G_OBJECT (insert_case), "activate",
855                             G_CALLBACK (gtk_action_activate),
856                             de->insert_case);
857
858
859   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
860                          gtk_separator_menu_item_new ());
861
862
863   gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_case);
864
865
866   gtk_widget_show_all (menu);
867
868   return menu;
869 }
870
871
872 static GtkWidget *
873 create_var_sheet_variable_popup_menu (PsppireDataWindow *de)
874 {
875   GtkWidget *menu = gtk_menu_new ();
876
877   GtkWidget *insert_variable =
878     gtk_menu_item_new_with_label (_("Insert Variable"));
879
880   GtkWidget *delete_variable =
881     gtk_menu_item_new_with_label (_("Clear"));
882
883
884   gtk_action_connect_proxy (de->delete_variables,
885                             delete_variable);
886
887
888   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
889
890   g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
891                             G_CALLBACK (gtk_action_activate),
892                             de->insert_variable);
893
894
895   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
896                          gtk_separator_menu_item_new ());
897
898
899   gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_variable);
900
901
902   gtk_widget_show_all (menu);
903
904   return menu;
905 }
906
907
908 #if RECENT_LISTS_AVAILABLE
909
910 static void
911 on_recent_data_select (GtkMenuShell *menushell,   gpointer user_data)
912 {
913   gchar *file;
914   PsppireDataWindow  *de = PSPPIRE_DATA_WINDOW (user_data);
915
916   gchar *uri =
917     gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
918
919   file = g_filename_from_uri (uri, NULL, NULL);
920
921   g_free (uri);
922
923   open_data_file (file, de);
924
925   g_free (file);
926 }
927
928 static void
929 on_recent_files_select (GtkMenuShell *menushell,   gpointer user_data)
930 {
931   gchar *file;
932
933   GtkWidget *se ;
934
935   gchar *uri =
936     gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (menushell));
937
938   file = g_filename_from_uri (uri, NULL, NULL);
939
940   g_free (uri);
941
942   se = psppire_syntax_window_new ();
943
944   psppire_syntax_window_load_from_file (PSPPIRE_SYNTAX_WINDOW (se), file, NULL);
945   gtk_widget_show (se);
946
947   g_free (file);
948 }
949
950 #endif
951
952 static void
953 enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
954 {
955   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
956
957   gtk_action_set_visible (de->delete_cases, case_num != -1);
958 }
959
960
961 static void
962 enable_delete_variables (GtkWidget *w, gint var, gpointer data)
963 {
964   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
965
966   gtk_action_set_visible (de->delete_variables, var != -1);
967 }
968
969 /* Callback for when the datasheet/varsheet is selected */
970 static void
971 on_switch_sheet (GtkNotebook *notebook,
972                 GtkNotebookPage *page,
973                 guint page_num,
974                 gpointer user_data)
975 {
976   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
977
978   GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
979   GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables");
980
981   switch (page_num)
982     {
983     case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
984       gtk_widget_hide (view_variables);
985       gtk_widget_show (view_data);
986       gtk_action_set_sensitive (de->insert_variable, TRUE);
987       gtk_action_set_sensitive (de->insert_case, FALSE);
988       gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
989       break;
990     case PSPPIRE_DATA_EDITOR_DATA_VIEW:
991       gtk_widget_show (view_variables);
992       gtk_widget_hide (view_data);
993       gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
994       gtk_action_set_sensitive (de->insert_case, TRUE);
995       break;
996     default:
997       g_assert_not_reached ();
998       break;
999     }
1000
1001 #if 0
1002   update_paste_menuitem (de, page_num);
1003 #endif
1004 }
1005
1006
1007 static void
1008 set_unsaved (gpointer w)
1009 {
1010   psppire_window_set_unsaved (PSPPIRE_WINDOW (w), TRUE);
1011 }
1012
1013 static void
1014 psppire_data_window_init (PsppireDataWindow *de)
1015 {
1016   PsppireVarStore *vs;
1017
1018   GtkWidget *menubar;
1019   GtkWidget *hb ;
1020   GtkWidget *sb ;
1021
1022   GtkWidget *box = gtk_vbox_new (FALSE, 0);
1023   de->xml = XML_NEW ("data-editor.glade");
1024
1025   menubar = get_widget_assert (de->xml, "menubar");
1026   hb = get_widget_assert (de->xml, "handlebox1");
1027   sb = get_widget_assert (de->xml, "status-bar");
1028
1029   de->data_editor =
1030     PSPPIRE_DATA_EDITOR (psppire_data_editor_new (the_var_store, the_data_store));
1031
1032   g_signal_connect_swapped (the_data_store, "case-changed",
1033                     G_CALLBACK (set_unsaved), de);
1034
1035   g_signal_connect_swapped (the_data_store, "case-inserted",
1036                     G_CALLBACK (set_unsaved), de);
1037
1038   g_signal_connect_swapped (the_data_store, "cases-deleted",
1039                     G_CALLBACK (set_unsaved), de);
1040
1041   dataset_set_callback (the_dataset, set_unsaved, de);
1042
1043   connect_help (de->xml);
1044
1045   g_object_ref (menubar);
1046   gtk_widget_unparent (menubar);
1047
1048   g_object_ref (hb);
1049   gtk_widget_unparent (hb);
1050
1051   g_object_ref (sb);
1052   gtk_widget_unparent (sb);
1053
1054   gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
1055   gtk_box_pack_start (GTK_BOX (box), hb, FALSE, TRUE, 0);
1056   gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (de->data_editor), TRUE, TRUE, 0);
1057   gtk_box_pack_start (GTK_BOX (box), sb, FALSE, TRUE, 0);
1058
1059   gtk_container_add (GTK_CONTAINER (de), box);
1060
1061   g_signal_connect (de->data_editor, "data-selection-changed",
1062                     G_CALLBACK (update_cut_copy_menuitems), de);
1063
1064   g_signal_connect (de->data_editor, "data-available-changed",
1065                     G_CALLBACK (update_paste_menuitems), de);
1066
1067   dataset_add_transform_change_callback (the_dataset,
1068                                          transformation_change_callback,
1069                                          de);
1070
1071
1072   vs = the_var_store;
1073
1074   g_assert(vs); /* Traps a possible bug in w32 build */
1075
1076   g_signal_connect (vs->dict, "weight-changed",
1077                     G_CALLBACK (on_weight_change),
1078                     de);
1079
1080   g_signal_connect (vs->dict, "filter-changed",
1081                     G_CALLBACK (on_filter_change),
1082                     de);
1083
1084   g_signal_connect (vs->dict, "split-changed",
1085                     G_CALLBACK (on_split_change),
1086                     de);
1087
1088
1089   g_signal_connect (get_widget_assert (de->xml, "edit_copy"),
1090                     "activate",
1091                     G_CALLBACK (on_edit_copy), de);
1092
1093   g_signal_connect (get_widget_assert (de->xml, "edit_cut"),
1094                     "activate",
1095                     G_CALLBACK (on_edit_cut), de);
1096
1097
1098   register_data_editor_actions (de);
1099
1100   de->toggle_value_labels =
1101     gtk_toggle_action_new ("toggle-value-labels",
1102                            _("_Labels"),
1103                            _("Show/hide value labels"),
1104                            "pspp-value-labels");
1105
1106   g_signal_connect (de->toggle_value_labels, "toggled",
1107                     G_CALLBACK (toggle_value_labels), de);
1108
1109
1110   gtk_action_connect_proxy (GTK_ACTION (de->toggle_value_labels),
1111                             get_widget_assert (de->xml,
1112                                                "togglebutton-value-labels"));
1113
1114
1115   gtk_action_connect_proxy (GTK_ACTION (de->toggle_value_labels),
1116                             get_widget_assert (de->xml,
1117                                                "view_value-labels"));
1118
1119
1120
1121   de->delete_cases =
1122     gtk_action_new ("clear-cases",
1123                     _("Clear"),
1124                     _("Delete the cases at the selected position(s)"),
1125                     "pspp-clear-cases");
1126
1127   g_signal_connect_swapped (de->delete_cases, "activate",
1128                     G_CALLBACK (psppire_data_editor_delete_cases),
1129                     de->data_editor);
1130
1131   gtk_action_connect_proxy (de->delete_cases,
1132                             get_widget_assert (de->xml, "edit_clear-cases"));
1133
1134   g_signal_connect (get_widget_assert (de->xml, "edit_paste"), "activate",
1135                     G_CALLBACK (on_edit_paste),
1136                     de);
1137
1138   gtk_action_set_visible (de->delete_cases, FALSE);
1139
1140   de->delete_variables =
1141     gtk_action_new ("clear-variables",
1142                     _("Clear"),
1143                     _("Delete the variables at the selected position(s)"),
1144                     "pspp-clear-variables");
1145
1146   g_signal_connect_swapped (de->delete_variables, "activate",
1147                             G_CALLBACK (psppire_data_editor_delete_variables),
1148                             de->data_editor);
1149
1150   gtk_action_connect_proxy (de->delete_variables,
1151                             get_widget_assert (de->xml, "edit_clear-variables")
1152                             );
1153
1154   gtk_action_set_visible (de->delete_variables, FALSE);
1155
1156   de->insert_variable =
1157     gtk_action_new ("insert-variable",
1158                     _("Insert _Variable"),
1159                     _("Create a new variable at the current position"),
1160                     "pspp-insert-variable");
1161
1162   g_signal_connect (de->insert_variable, "activate",
1163                     G_CALLBACK (on_insert_variable), de->data_editor);
1164
1165
1166   gtk_action_connect_proxy (de->insert_variable,
1167                             get_widget_assert (de->xml, "button-insert-variable")
1168                             );
1169
1170   gtk_action_connect_proxy (de->insert_variable,
1171                             get_widget_assert (de->xml, "edit_insert-variable")
1172                             );
1173
1174
1175   de->insert_case =
1176     gtk_action_new ("insert-case",
1177                     _("Insert Ca_se"),
1178                     _("Create a new case at the current position"),
1179                     "pspp-insert-case");
1180
1181   g_signal_connect (de->insert_case, "activate",
1182                     G_CALLBACK (insert_case), de);
1183
1184
1185   gtk_action_connect_proxy (de->insert_case,
1186                             get_widget_assert (de->xml, "button-insert-case")
1187                             );
1188
1189
1190   gtk_action_connect_proxy (de->insert_case,
1191                             get_widget_assert (de->xml, "edit_insert-case")
1192                             );
1193
1194
1195   de->invoke_goto_dialog =
1196     gtk_action_new ("goto-case-dialog",
1197                     _("_Goto Case"),
1198                     _("Jump to a Case in the Data Sheet"),
1199                     "gtk-jump-to");
1200
1201
1202   gtk_action_connect_proxy (de->invoke_goto_dialog,
1203                             get_widget_assert (de->xml, "button-goto-case")
1204                             );
1205
1206   gtk_action_connect_proxy (de->invoke_goto_dialog,
1207                             get_widget_assert (de->xml, "edit_goto-case")
1208                             );
1209
1210
1211   g_signal_connect (de->invoke_goto_dialog, "activate",
1212                     G_CALLBACK (goto_case_dialog), de);
1213
1214   de->invoke_weight_cases_dialog =
1215     gtk_action_new ("weight-cases-dialog",
1216                     _("_Weights"),
1217                     _("Weight cases by variable"),
1218                     "pspp-weight-cases");
1219
1220   g_signal_connect (de->invoke_weight_cases_dialog, "activate",
1221                     G_CALLBACK (weight_cases_dialog), de);
1222
1223
1224   de->invoke_transpose_dialog =
1225     gtk_action_new ("transpose-dialog",
1226                     _("_Transpose"),
1227                     _("Transpose the cases with the variables"),
1228                     NULL);
1229
1230
1231   g_signal_connect (de->invoke_transpose_dialog, "activate",
1232                     G_CALLBACK (transpose_dialog), de);
1233
1234
1235
1236   de->invoke_split_file_dialog =
1237     gtk_action_new ("split-file-dialog",
1238                     _("S_plit"),
1239                     _("Split the active file"),
1240                     "pspp-split-file");
1241
1242   g_signal_connect (de->invoke_split_file_dialog, "activate",
1243                     G_CALLBACK (split_file_dialog), de);
1244
1245
1246
1247   de->invoke_sort_cases_dialog =
1248     gtk_action_new ("sort-cases-dialog",
1249                     _("_Sort"),
1250                     _("Sort cases in the active file"),
1251                     "pspp-sort-cases");
1252
1253   g_signal_connect (de->invoke_sort_cases_dialog, "activate",
1254                     G_CALLBACK (sort_cases_dialog), de);
1255
1256   de->invoke_select_cases_dialog =
1257     gtk_action_new ("select-cases-dialog",
1258                     _("Select _Cases"),
1259                     _("Select cases from the active file"),
1260                     "pspp-select-cases");
1261
1262   g_signal_connect (de->invoke_select_cases_dialog, "activate",
1263                     G_CALLBACK (select_cases_dialog), de);
1264
1265
1266   de->invoke_compute_dialog =
1267     gtk_action_new ("compute-dialog",
1268                     _("_Compute"),
1269                     _("Compute new values for a variable"),
1270                     "pspp-compute");
1271
1272   g_signal_connect (de->invoke_compute_dialog, "activate",
1273                     G_CALLBACK (compute_dialog), de);
1274
1275   de->invoke_oneway_anova_dialog =
1276     gtk_action_new ("oneway-anova",
1277                     _("Oneway _ANOVA"),
1278                     _("Perform one way analysis of variance"),
1279                     NULL);
1280
1281   g_signal_connect (de->invoke_oneway_anova_dialog, "activate",
1282                     G_CALLBACK (oneway_anova_dialog), de);
1283
1284   de->invoke_t_test_independent_samples_dialog =
1285     gtk_action_new ("t-test-independent-samples",
1286                     _("_Independent Samples T Test"),
1287                     _("Calculate T Test for samples from independent groups"),
1288                     NULL);
1289
1290   g_signal_connect (de->invoke_t_test_independent_samples_dialog, "activate",
1291                     G_CALLBACK (t_test_independent_samples_dialog), de);
1292
1293
1294   de->invoke_t_test_paired_samples_dialog =
1295     gtk_action_new ("t-test-paired-samples",
1296                     _("_Paired Samples T Test"),
1297                     _("Calculate T Test for paired samples"),
1298                     NULL);
1299
1300   g_signal_connect (de->invoke_t_test_paired_samples_dialog, "activate",
1301                     G_CALLBACK (t_test_paired_samples_dialog), de);
1302
1303
1304   de->invoke_t_test_one_sample_dialog =
1305     gtk_action_new ("t-test-one-sample",
1306                     _("One _Sample T Test"),
1307                     _("Calculate T Test for sample from a single distribution"),
1308                     NULL);
1309
1310   g_signal_connect (de->invoke_t_test_one_sample_dialog, "activate",
1311                     G_CALLBACK (t_test_one_sample_dialog), de);
1312
1313
1314   de->invoke_comments_dialog =
1315     gtk_action_new ("commments-dialog",
1316                     _("Data File _Comments"),
1317                     _("Commentary text for the data file"),
1318                     NULL);
1319
1320   g_signal_connect (de->invoke_comments_dialog, "activate",
1321                     G_CALLBACK (comments_dialog), de);
1322
1323   de->invoke_find_dialog  =
1324     gtk_action_new ("find-dialog",
1325                     _("_Find"),
1326                     _("Find Case"),
1327                     "gtk-find");
1328
1329   g_signal_connect (de->invoke_find_dialog, "activate",
1330                     G_CALLBACK (find_dialog), de);
1331
1332
1333   de->invoke_rank_dialog  =
1334     gtk_action_new ("rank-dialog",
1335                     _("Ran_k Cases"),
1336                     _("Rank Cases"),
1337                     "pspp-rank-cases");
1338
1339   g_signal_connect (de->invoke_rank_dialog, "activate",
1340                     G_CALLBACK (rank_dialog), de);
1341
1342
1343   de->invoke_recode_same_dialog  =
1344     gtk_action_new ("recode-same-dialog",
1345                     _("Recode into _Same Variables"),
1346                     _("Recode values into the same Variables"),
1347                     "pspp-recode-same");
1348
1349   g_signal_connect (de->invoke_recode_same_dialog, "activate",
1350                     G_CALLBACK (recode_same_dialog), de);
1351
1352
1353   de->invoke_recode_different_dialog  =
1354     gtk_action_new ("recode-different-dialog",
1355                     _("Recode into _Different Variables"),
1356                     _("Recode values into different Variables"),
1357                     "pspp-recode-different");
1358
1359   g_signal_connect (de->invoke_recode_different_dialog, "activate",
1360                     G_CALLBACK (recode_different_dialog), de);
1361
1362
1363   de->invoke_variable_info_dialog  =
1364     gtk_action_new ("variable-info-dialog",
1365                     _("_Variables"),
1366                     _("Jump to Variable"),
1367                     "pspp-goto-variable");
1368
1369   g_signal_connect (de->invoke_variable_info_dialog, "activate",
1370                     G_CALLBACK (variable_info_dialog), de);
1371
1372   de->invoke_descriptives_dialog =
1373     gtk_action_new ("descriptives-dialog",
1374                     _("_Descriptives"),
1375                     _("Calculate descriptive statistics (mean, variance, ...)"),
1376                     "pspp-descriptives");
1377
1378   g_signal_connect (de->invoke_descriptives_dialog, "activate",
1379                     G_CALLBACK (descriptives_dialog), de);
1380
1381
1382   de->invoke_frequencies_dialog =
1383     gtk_action_new ("frequencies-dialog",
1384                     _("_Frequencies"),
1385                     _("Generate frequency statistics"),
1386                     "pspp-frequencies");
1387
1388   g_signal_connect (de->invoke_frequencies_dialog, "activate",
1389                     G_CALLBACK (frequencies_dialog), de);
1390
1391   de->invoke_crosstabs_dialog =
1392     gtk_action_new ("crosstabs-dialog",
1393                     _("_Crosstabs"),
1394                     _("Generate crosstabulations"),
1395                     "pspp-crosstabs");
1396
1397   g_signal_connect (de->invoke_crosstabs_dialog, "activate",
1398                     G_CALLBACK (crosstabs_dialog), de);
1399
1400
1401   de->invoke_examine_dialog =
1402     gtk_action_new ("examine-dialog",
1403                     _("_Explore"),
1404                     _("Examine Data by Factors"),
1405                     "pspp-examine");
1406
1407   g_signal_connect (de->invoke_examine_dialog, "activate",
1408                     G_CALLBACK (examine_dialog), de);
1409
1410
1411   de->invoke_regression_dialog =
1412     gtk_action_new ("regression-dialog",
1413                     _("Linear _Regression"),
1414                     _("Estimate parameters of the linear model"),
1415                     "pspp-regression");
1416
1417   g_signal_connect (de->invoke_regression_dialog, "activate",
1418                     G_CALLBACK (regression_dialog), de);
1419
1420   g_signal_connect_swapped (get_widget_assert (de->xml,"file_new_data"),
1421                             "activate",
1422                             G_CALLBACK (gtk_action_activate),
1423                             de->action_data_new);
1424
1425   g_signal_connect_swapped (get_widget_assert (de->xml,"file_open_data"),
1426                             "activate",
1427                             G_CALLBACK (gtk_action_activate),
1428                             de->action_data_open);
1429
1430 #if RECENT_LISTS_AVAILABLE
1431   {
1432     GtkRecentManager *rm = gtk_recent_manager_get_default ();
1433     GtkWidget *recent_data = get_widget_assert (de->xml, "file_recent-data");
1434     GtkWidget *recent_files = get_widget_assert (de->xml, "file_recent-files");
1435     GtkWidget *recent_separator = get_widget_assert (de->xml, "file_separator1");
1436
1437     GtkWidget *menu = gtk_recent_chooser_menu_new_for_manager (rm);
1438
1439     GtkRecentFilter *filter = gtk_recent_filter_new ();
1440
1441     gtk_widget_show (recent_data);
1442     gtk_widget_show (recent_files);
1443     gtk_widget_show (recent_separator);
1444
1445     gtk_recent_filter_add_pattern (filter, "*.sav");
1446     gtk_recent_filter_add_pattern (filter, "*.SAV");
1447
1448     gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1449
1450     gtk_widget_set_sensitive (recent_data, TRUE);
1451     g_signal_connect (menu, "selection-done",
1452                       G_CALLBACK (on_recent_data_select), de);
1453
1454     gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_data), menu);
1455
1456
1457     filter = gtk_recent_filter_new ();
1458     menu = gtk_recent_chooser_menu_new_for_manager (rm);
1459
1460     gtk_recent_filter_add_pattern (filter, "*.sps");
1461     gtk_recent_filter_add_pattern (filter, "*.SPS");
1462
1463     gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
1464
1465     gtk_widget_set_sensitive (recent_files, TRUE);
1466     g_signal_connect (menu, "selection-done",
1467                       G_CALLBACK (on_recent_files_select), de);
1468
1469     gtk_menu_item_set_submenu (GTK_MENU_ITEM (recent_files), menu);
1470   }
1471 #endif
1472
1473   g_signal_connect (get_widget_assert (de->xml,"file_new_syntax"),
1474                     "activate",
1475                     G_CALLBACK (create_syntax_window),
1476                     NULL);
1477
1478   g_signal_connect (get_widget_assert (de->xml,"file_open_syntax"),
1479                     "activate",
1480                     G_CALLBACK (open_syntax_window),
1481                     de);
1482
1483   g_signal_connect_swapped (get_widget_assert (de->xml,"file_import-text"),
1484                             "activate",
1485                             G_CALLBACK (gtk_action_activate),
1486                             de->invoke_text_import_assistant);
1487
1488   g_signal_connect_swapped (get_widget_assert (de->xml,"file_save"),
1489                             "activate",
1490                             G_CALLBACK (gtk_action_activate),
1491                             de->action_data_save);
1492
1493   g_signal_connect_swapped (get_widget_assert (de->xml,"file_save_as"),
1494                             "activate",
1495                             G_CALLBACK (gtk_action_activate),
1496                             de->action_data_save_as);
1497
1498   gtk_action_connect_proxy (de->invoke_find_dialog,
1499                             get_widget_assert (de->xml, "edit_find")
1500                             );
1501
1502   gtk_action_connect_proxy (de->invoke_find_dialog,
1503                             get_widget_assert (de->xml, "button-find")
1504                             );
1505
1506   gtk_action_connect_proxy (de->invoke_rank_dialog,
1507                             get_widget_assert (de->xml, "transform_rank")
1508                             );
1509
1510   gtk_action_connect_proxy (de->invoke_recode_same_dialog,
1511                             get_widget_assert (de->xml,
1512                                                "transform_recode-same")
1513                             );
1514
1515   gtk_action_connect_proxy (de->invoke_recode_different_dialog,
1516                             get_widget_assert (de->xml,
1517                                                "transform_recode-different")
1518                             );
1519
1520   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
1521                             get_widget_assert (de->xml, "data_weight-cases")
1522                             );
1523
1524   gtk_action_connect_proxy (de->invoke_transpose_dialog,
1525                             get_widget_assert (de->xml, "data_transpose")
1526                             );
1527
1528   gtk_action_connect_proxy (de->invoke_split_file_dialog,
1529                             get_widget_assert (de->xml, "data_split-file")
1530                             );
1531
1532   gtk_action_connect_proxy (de->invoke_sort_cases_dialog,
1533                             get_widget_assert (de->xml, "data_sort-cases")
1534                             );
1535
1536   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
1537                             get_widget_assert (de->xml, "data_select-cases")
1538                             );
1539
1540   gtk_action_connect_proxy (de->invoke_compute_dialog,
1541                             get_widget_assert (de->xml, "transform_compute")
1542                             );
1543
1544   gtk_action_connect_proxy (de->invoke_t_test_independent_samples_dialog,
1545                             get_widget_assert (de->xml,
1546                                                "indep-t-test")
1547                             );
1548
1549
1550   gtk_action_connect_proxy (de->invoke_t_test_paired_samples_dialog,
1551                             get_widget_assert (de->xml,
1552                                                "paired-t-test")
1553                             );
1554
1555
1556   gtk_action_connect_proxy (de->invoke_t_test_one_sample_dialog,
1557                             get_widget_assert (de->xml,
1558                                                "one-sample-t-test")
1559                             );
1560
1561
1562   gtk_action_connect_proxy (de->invoke_oneway_anova_dialog,
1563                             get_widget_assert (de->xml,
1564                                                "oneway-anova")
1565                             );
1566
1567
1568   gtk_action_connect_proxy (de->invoke_comments_dialog,
1569                             get_widget_assert (de->xml, "utilities_comments")
1570                             );
1571
1572   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
1573                             get_widget_assert (de->xml, "utilities_variables")
1574                             );
1575
1576   gtk_action_connect_proxy (de->invoke_descriptives_dialog,
1577                             get_widget_assert (de->xml, "analyze_descriptives")
1578                             );
1579
1580   gtk_action_connect_proxy (de->invoke_crosstabs_dialog,
1581                             get_widget_assert (de->xml, "crosstabs")
1582                             );
1583
1584   gtk_action_connect_proxy (de->invoke_frequencies_dialog,
1585                             get_widget_assert (de->xml, "analyze_frequencies")
1586                             );
1587
1588
1589   gtk_action_connect_proxy (de->invoke_examine_dialog,
1590                             get_widget_assert (de->xml, "analyze_explore")
1591                             );
1592
1593   gtk_action_connect_proxy (de->invoke_regression_dialog,
1594                             get_widget_assert (de->xml, "linear-regression")
1595                             );
1596
1597   g_signal_connect (get_widget_assert (de->xml,"help_about"),
1598                     "activate",
1599                     G_CALLBACK (about_new),
1600                     de);
1601
1602
1603   g_signal_connect (get_widget_assert (de->xml,"help_reference"),
1604                     "activate",
1605                     G_CALLBACK (reference_manual),
1606                     de);
1607
1608
1609   g_signal_connect (de->data_editor,
1610                     "cases-selected",
1611                     G_CALLBACK (enable_delete_cases),
1612                     de);
1613
1614   g_signal_connect (de->data_editor,
1615                     "variables-selected",
1616                     G_CALLBACK (enable_delete_variables),
1617                     de);
1618
1619
1620   g_signal_connect (GTK_NOTEBOOK (de->data_editor),
1621                     "switch-page",
1622                     G_CALLBACK (on_switch_sheet), de);
1623
1624   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1625   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1626
1627   g_signal_connect (get_widget_assert (de->xml, "view_statusbar"),
1628                     "activate",
1629                     G_CALLBACK (status_bar_activate), de);
1630
1631
1632   g_signal_connect (get_widget_assert (de->xml, "view_gridlines"),
1633                     "activate",
1634                     G_CALLBACK (grid_lines_activate), de);
1635
1636
1637
1638   g_signal_connect (get_widget_assert (de->xml, "view_data"),
1639                     "activate",
1640                     G_CALLBACK (data_view_activate), de);
1641
1642   g_signal_connect (get_widget_assert (de->xml, "view_variables"),
1643                     "activate",
1644                     G_CALLBACK (variable_view_activate), de);
1645
1646
1647
1648   g_signal_connect (get_widget_assert (de->xml, "view_fonts"),
1649                     "activate",
1650                     G_CALLBACK (fonts_activate), de);
1651
1652
1653
1654
1655   gtk_action_connect_proxy (de->action_data_open,
1656                             get_widget_assert (de->xml, "button-open")
1657                             );
1658
1659   gtk_action_connect_proxy (de->action_data_save,
1660                             get_widget_assert (de->xml, "button-save")
1661                             );
1662
1663   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
1664                             get_widget_assert (de->xml, "button-goto-variable")
1665                             );
1666
1667   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
1668                             get_widget_assert (de->xml, "button-weight-cases")
1669                             );
1670
1671   gtk_action_connect_proxy (de->invoke_split_file_dialog,
1672                             get_widget_assert (de->xml, "button-split-file")
1673                             );
1674
1675   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
1676                             get_widget_assert (de->xml, "button-select-cases")
1677                             );
1678
1679
1680   g_signal_connect (get_widget_assert (de->xml, "file_quit"),
1681                     "activate",
1682                     G_CALLBACK (file_quit), de);
1683
1684   g_signal_connect (get_widget_assert (de->xml, "transform_run-pending"),
1685                     "activate",
1686                     G_CALLBACK (execute), de);
1687
1688
1689   g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
1690                     "activate",
1691                     G_CALLBACK (psppire_window_minimise_all), NULL);
1692
1693   de->toggle_split_window =
1694     gtk_toggle_action_new ("toggle-split-window",
1695                            _("_Split Window"),
1696                            _("Split the window vertically and horizontally"),
1697                            "pspp-split-window");
1698
1699   g_signal_connect (de->toggle_split_window, "toggled",
1700                     G_CALLBACK (toggle_split_window),
1701                     de);
1702
1703   gtk_action_connect_proxy (GTK_ACTION (de->toggle_split_window),
1704                             get_widget_assert (de->xml,
1705                                                "windows_split"));
1706
1707   de->data_sheet_variable_popup_menu =
1708     GTK_MENU (create_data_sheet_variable_popup_menu (de));
1709
1710   de->var_sheet_variable_popup_menu =
1711     GTK_MENU (create_var_sheet_variable_popup_menu (de));
1712
1713   de->data_sheet_cases_popup_menu =
1714     GTK_MENU (create_data_sheet_cases_popup_menu (de));
1715
1716   PSPPIRE_WINDOW (de)->menu = GTK_MENU_SHELL (get_widget_assert (de->xml,"Windows_menu"));
1717
1718   g_object_set (de->data_editor,
1719                 "datasheet-column-menu", de->data_sheet_variable_popup_menu,
1720                 "datasheet-row-menu", de->data_sheet_cases_popup_menu,
1721                 "varsheet-row-menu", de->var_sheet_variable_popup_menu,
1722                 NULL);
1723
1724   gtk_widget_show (GTK_WIDGET (de->data_editor));
1725   gtk_widget_show (box);
1726 }
1727
1728
1729 GtkWidget*
1730 psppire_data_window_new (void)
1731 {
1732   return GTK_WIDGET (g_object_new (psppire_data_window_get_type (),
1733                                    "description", _("Data Editor"),
1734                                    NULL));
1735 }
1736