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