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