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