Applied patch #6428
[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 #include <gtksheet/gtksheet.h>
26
27 #include "psppire-data-editor.h"
28
29 #include "helper.h"
30 #include "about.h"
31 #include <data/procedure.h>
32 #include "psppire-dialog.h"
33 #include "psppire-selector.h"
34 #include "weight-cases-dialog.h"
35 #include "split-file-dialog.h"
36 #include "transpose-dialog.h"
37 #include "sort-cases-dialog.h"
38 #include "select-cases-dialog.h"
39 #include "compute-dialog.h"
40 #include "goto-case-dialog.h"
41 #include "find-dialog.h"
42 #include "rank-dialog.h"
43 #include "recode-dialog.h"
44 #include "comments-dialog.h"
45 #include "variable-info-dialog.h"
46 #include "descriptives-dialog.h"
47 #include "crosstabs-dialog.h"
48 #include "frequencies-dialog.h"
49 #include "examine-dialog.h"
50 #include "dict-display.h"
51 #include "regression-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 <libpspp/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 Case"),
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                     _("Split"),
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_save"),
707                             "activate",
708                             G_CALLBACK (gtk_action_activate),
709                             de->action_data_save);
710
711   g_signal_connect_swapped (get_widget_assert (de->xml,"file_save_as"),
712                             "activate",
713                             G_CALLBACK (gtk_action_activate),
714                             de->action_data_save_as);
715
716   gtk_action_connect_proxy (de->invoke_find_dialog,
717                             get_widget_assert (de->xml, "edit_find")
718                             );
719
720   gtk_action_connect_proxy (de->invoke_find_dialog,
721                             get_widget_assert (de->xml, "button-find")
722                             );
723
724   gtk_action_connect_proxy (de->invoke_rank_dialog,
725                             get_widget_assert (de->xml, "transform_rank")
726                             );
727
728   gtk_action_connect_proxy (de->invoke_recode_same_dialog,
729                             get_widget_assert (de->xml,
730                                                "transform_recode-same")
731                             );
732
733   gtk_action_connect_proxy (de->invoke_recode_different_dialog,
734                             get_widget_assert (de->xml,
735                                                "transform_recode-different")
736                             );
737
738   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
739                             get_widget_assert (de->xml, "data_weight-cases")
740                             );
741
742   gtk_action_connect_proxy (de->invoke_transpose_dialog,
743                             get_widget_assert (de->xml, "data_transpose")
744                             );
745
746   gtk_action_connect_proxy (de->invoke_split_file_dialog,
747                             get_widget_assert (de->xml, "data_split-file")
748                             );
749
750   gtk_action_connect_proxy (de->invoke_sort_cases_dialog,
751                             get_widget_assert (de->xml, "data_sort-cases")
752                             );
753
754   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
755                             get_widget_assert (de->xml, "data_select-cases")
756                             );
757
758   gtk_action_connect_proxy (de->invoke_compute_dialog,
759                             get_widget_assert (de->xml, "transform_compute")
760                             );
761
762   gtk_action_connect_proxy (de->invoke_t_test_independent_samples_dialog,
763                             get_widget_assert (de->xml,
764                                                "indep-t-test")
765                             );
766
767
768   gtk_action_connect_proxy (de->invoke_t_test_paired_samples_dialog,
769                             get_widget_assert (de->xml,
770                                                "paired-t-test")
771                             );
772
773
774   gtk_action_connect_proxy (de->invoke_t_test_one_sample_dialog,
775                             get_widget_assert (de->xml,
776                                                "one-sample-t-test")
777                             );
778
779
780   gtk_action_connect_proxy (de->invoke_oneway_anova_dialog,
781                             get_widget_assert (de->xml,
782                                                "oneway-anova")
783                             );
784
785
786   gtk_action_connect_proxy (de->invoke_comments_dialog,
787                             get_widget_assert (de->xml, "utilities_comments")
788                             );
789
790   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
791                             get_widget_assert (de->xml, "utilities_variables")
792                             );
793
794   gtk_action_connect_proxy (de->invoke_descriptives_dialog,
795                             get_widget_assert (de->xml, "analyze_descriptives")
796                             );
797
798   gtk_action_connect_proxy (de->invoke_crosstabs_dialog,
799                             get_widget_assert (de->xml, "crosstabs")
800                             );
801
802   gtk_action_connect_proxy (de->invoke_frequencies_dialog,
803                             get_widget_assert (de->xml, "analyze_frequencies")
804                             );
805
806
807   gtk_action_connect_proxy (de->invoke_examine_dialog,
808                             get_widget_assert (de->xml, "analyze_explore")
809                             );
810
811   gtk_action_connect_proxy (de->invoke_regression_dialog,
812                             get_widget_assert (de->xml, "linear-regression")
813                             );
814
815   g_signal_connect (get_widget_assert (de->xml,"help_about"),
816                     "activate",
817                     G_CALLBACK (about_new),
818                     e->window);
819
820
821   g_signal_connect (get_widget_assert (de->xml,"help_reference"),
822                     "activate",
823                     G_CALLBACK (reference_manual),
824                     e->window);
825
826
827   g_signal_connect (de->data_editor,
828                     "cases-selected",
829                     G_CALLBACK (enable_delete_cases),
830                     de);
831
832
833   g_signal_connect (de->data_editor,
834                     "variables-selected",
835                     G_CALLBACK (enable_delete_variables),
836                     de);
837
838
839   g_signal_connect (GTK_NOTEBOOK (de->data_editor),
840                     "switch-page",
841                     G_CALLBACK (on_switch_sheet), de);
842
843   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
844   gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
845
846   g_signal_connect (get_widget_assert (de->xml, "view_statusbar"),
847                     "activate",
848                     G_CALLBACK (status_bar_activate), de);
849
850
851   g_signal_connect (get_widget_assert (de->xml, "view_gridlines"),
852                     "activate",
853                     G_CALLBACK (grid_lines_activate), de);
854
855
856
857   g_signal_connect (get_widget_assert (de->xml, "view_data"),
858                     "activate",
859                     G_CALLBACK (data_view_activate), de);
860
861   g_signal_connect (get_widget_assert (de->xml, "view_variables"),
862                     "activate",
863                     G_CALLBACK (variable_view_activate), de);
864
865
866
867   g_signal_connect (get_widget_assert (de->xml, "view_fonts"),
868                     "activate",
869                     G_CALLBACK (fonts_activate), de);
870
871
872
873
874   gtk_action_connect_proxy (de->action_data_open,
875                             get_widget_assert (de->xml, "button-open")
876                             );
877
878   gtk_action_connect_proxy (de->action_data_save,
879                             get_widget_assert (de->xml, "button-save")
880                             );
881
882   gtk_action_connect_proxy (de->invoke_variable_info_dialog,
883                             get_widget_assert (de->xml, "button-goto-variable")
884                             );
885
886   gtk_action_connect_proxy (de->invoke_weight_cases_dialog,
887                             get_widget_assert (de->xml, "button-weight-cases")
888                             );
889
890   gtk_action_connect_proxy (de->invoke_split_file_dialog,
891                             get_widget_assert (de->xml, "button-split-file")
892                             );
893
894   gtk_action_connect_proxy (de->invoke_select_cases_dialog,
895                             get_widget_assert (de->xml, "button-select-cases")
896                             );
897
898
899   g_signal_connect (get_widget_assert (de->xml, "file_quit"),
900                     "activate",
901                     G_CALLBACK (file_quit), de);
902
903   g_signal_connect (get_widget_assert (de->xml, "transform_run-pending"),
904                     "activate",
905                     G_CALLBACK (execute), de);
906
907
908   g_signal_connect (get_widget_assert (de->xml, "windows_minimise_all"),
909                     "activate",
910                     G_CALLBACK (minimise_all_windows), NULL);
911
912
913   de->data_sheet_variable_popup_menu =
914     GTK_MENU (create_data_sheet_variable_popup_menu (de));
915
916   de->data_sheet_cases_popup_menu =
917     GTK_MENU (create_data_sheet_cases_popup_menu (de));
918
919
920   g_object_set (de->data_editor,
921                 "column-menu", de->data_sheet_variable_popup_menu, NULL);
922
923
924   g_object_set (de->data_editor,
925                 "row-menu", de->data_sheet_cases_popup_menu, NULL);
926
927   return de;
928 }
929
930
931 void
932 new_data_window (GtkMenuItem *menuitem, gpointer parent)
933 {
934   window_create (WINDOW_DATA, NULL);
935 }
936
937 /* Callback for when the datasheet/varsheet is selected */
938 static void
939 on_switch_sheet (GtkNotebook *notebook,
940                 GtkNotebookPage *page,
941                 guint page_num,
942                 gpointer user_data)
943 {
944   struct data_editor *de = user_data;
945
946   GtkWidget *view_data = get_widget_assert (de->xml, "view_data");
947   GtkWidget *view_variables = get_widget_assert (de->xml, "view_variables");
948
949   switch (page_num)
950     {
951     case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
952       gtk_widget_hide (view_variables);
953       gtk_widget_show (view_data);
954       gtk_action_set_sensitive (de->insert_variable, TRUE);
955       gtk_action_set_sensitive (de->insert_case, FALSE);
956       gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
957       break;
958     case PSPPIRE_DATA_EDITOR_DATA_VIEW:
959       gtk_widget_show (view_variables);
960       gtk_widget_hide (view_data);
961       gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
962       gtk_action_set_sensitive (de->insert_case, TRUE);
963       break;
964     default:
965       g_assert_not_reached ();
966       break;
967     }
968
969 #if 0
970   update_paste_menuitem (de, page_num);
971 #endif
972 }
973
974
975 static void
976 status_bar_activate (GtkCheckMenuItem *menuitem, gpointer data)
977 {
978   struct data_editor *de = data;
979   GtkWidget *statusbar = get_widget_assert (de->xml, "status-bar");
980
981   if ( gtk_check_menu_item_get_active (menuitem) )
982     gtk_widget_show (statusbar);
983   else
984     gtk_widget_hide (statusbar);
985 }
986
987
988 static void
989 grid_lines_activate (GtkCheckMenuItem *menuitem, gpointer data)
990 {
991   struct data_editor *de = data;
992   const gboolean grid_visible = gtk_check_menu_item_get_active (menuitem);
993
994   psppire_data_editor_show_grid (de->data_editor, grid_visible);
995 }
996
997
998
999 static void
1000 data_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
1001 {
1002   struct data_editor *de = data;
1003
1004   gtk_notebook_set_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
1005 }
1006
1007
1008 static void
1009 variable_view_activate (GtkCheckMenuItem *menuitem, gpointer data)
1010 {
1011   struct data_editor *de = data;
1012
1013   gtk_notebook_set_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
1014 }
1015
1016
1017 static void
1018 fonts_activate (GtkMenuItem *menuitem, gpointer data)
1019 {
1020   struct data_editor *de = data;
1021   GtkWidget *dialog =
1022     gtk_font_selection_dialog_new (_("Font Selection"));
1023
1024   gtk_window_set_transient_for (GTK_WINDOW (dialog),
1025                                 GTK_WINDOW (get_widget_assert (de->xml,
1026                                                                "data_editor")));
1027   if ( GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (dialog)) )
1028     {
1029       const gchar *font = gtk_font_selection_dialog_get_font_name
1030         (GTK_FONT_SELECTION_DIALOG (dialog));
1031
1032       PangoFontDescription* font_desc =
1033         pango_font_description_from_string (font);
1034
1035       psppire_data_editor_set_font (de->data_editor, font_desc);
1036     }
1037
1038   gtk_widget_hide (dialog);
1039 }
1040
1041
1042
1043 /* Callback for the value labels action */
1044 static void
1045 toggle_value_labels (GtkToggleAction *ta, gpointer data)
1046 {
1047   struct data_editor *de = data;
1048
1049   g_object_set (de->data_editor, "value-labels", gtk_toggle_action_get_active (ta), NULL);
1050 }
1051
1052
1053
1054 static void
1055 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
1056 {
1057   /* FIXME: Need to be more intelligent here.
1058      Give the user the opportunity to save any unsaved data.
1059   */
1060   g_object_unref (the_data_store);
1061   gtk_main_quit ();
1062 }
1063
1064
1065 static void
1066 insert_case (GtkAction *action, gpointer data)
1067 {
1068   struct data_editor *de = data;
1069
1070   psppire_data_editor_insert_case (de->data_editor);
1071 }
1072
1073 static void
1074 on_insert_variable (GtkAction *action, gpointer data)
1075 {
1076   PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
1077   psppire_data_editor_insert_variable (de);
1078 }
1079
1080
1081 /* Callback for when the dictionary changes its split variables */
1082 static void
1083 on_split_change (PsppireDict *dict, gpointer data)
1084 {
1085   struct data_editor *de = data;
1086
1087   size_t n_split_vars = dict_get_split_cnt (dict->dict);
1088
1089   GtkWidget *split_status_area =
1090     get_widget_assert (de->xml, "split-file-status-area");
1091
1092   if ( n_split_vars == 0 )
1093     {
1094       gtk_label_set_text (GTK_LABEL (split_status_area), _("No Split"));
1095     }
1096   else
1097     {
1098       gint i;
1099       GString *text;
1100       const struct variable *const * split_vars =
1101         dict_get_split_vars (dict->dict);
1102
1103       text = g_string_new (_("Split by "));
1104
1105       for (i = 0 ; i < n_split_vars - 1; ++i )
1106         {
1107           g_string_append_printf (text, "%s, ", var_get_name (split_vars[i]));
1108         }
1109       g_string_append (text, var_get_name (split_vars[i]));
1110
1111       gtk_label_set_text (GTK_LABEL (split_status_area), text->str);
1112
1113       g_string_free (text, TRUE);
1114     }
1115 }
1116
1117
1118 /* Callback for when the dictionary changes its filter variable */
1119 static void
1120 on_filter_change (GObject *o, gint filter_index, gpointer data)
1121 {
1122   struct data_editor *de = data;
1123   GtkWidget *filter_status_area =
1124     get_widget_assert (de->xml, "filter-use-status-area");
1125
1126   if ( filter_index == -1 )
1127     {
1128       gtk_label_set_text (GTK_LABEL (filter_status_area), _("Filter off"));
1129     }
1130   else
1131     {
1132       PsppireVarStore *vs = NULL;
1133       struct variable *var ;
1134       gchar *text ;
1135
1136       g_object_get (de->data_editor, "var-store", &vs, NULL);
1137
1138       var = psppire_dict_get_variable (vs->dict, filter_index);
1139
1140       text = g_strdup_printf (_("Filter by %s"), var_get_name (var));
1141
1142       gtk_label_set_text (GTK_LABEL (filter_status_area), text);
1143
1144       g_free (text);
1145     }
1146 }
1147
1148 /* Callback for when the dictionary changes its weights */
1149 static void
1150 on_weight_change (GObject *o, gint weight_index, gpointer data)
1151 {
1152   struct data_editor *de = data;
1153   GtkWidget *weight_status_area =
1154     get_widget_assert (de->xml, "weight-status-area");
1155
1156   if ( weight_index == -1 )
1157     {
1158       gtk_label_set_text (GTK_LABEL (weight_status_area), _("Weights off"));
1159     }
1160   else
1161     {
1162       struct variable *var ;
1163       PsppireVarStore *vs = NULL;
1164       gchar *text;
1165
1166       g_object_get (de->data_editor, "var-store", &vs, NULL);
1167
1168       var = psppire_dict_get_variable (vs->dict, weight_index);
1169
1170       text = g_strdup_printf (_("Weight by %s"), var_get_name (var));
1171
1172       gtk_label_set_text (GTK_LABEL (weight_status_area), text);
1173
1174       g_free (text);
1175     }
1176 }
1177
1178
1179
1180 \f
1181 static void data_save_as_dialog (GtkAction *, struct data_editor *de);
1182 static void new_file (GtkAction *, struct editor_window *de);
1183 static void open_data_dialog (GtkAction *, struct data_editor *de);
1184 static void data_save (GtkAction *action, struct data_editor *e);
1185
1186
1187 /* Create the GtkActions and connect to their signals */
1188 static void
1189 register_data_editor_actions (struct data_editor *de)
1190 {
1191   de->action_data_open =
1192     gtk_action_new ("data-open-dialog",
1193                     _("Open"),
1194                     _("Open a data file"),
1195                     "gtk-open");
1196
1197   g_signal_connect (de->action_data_open, "activate",
1198                     G_CALLBACK (open_data_dialog), de);
1199
1200
1201   de->action_data_save = gtk_action_new ("data-save",
1202                                             _("Save"),
1203                                             _("Save data to file"),
1204                                             "gtk-save");
1205
1206   g_signal_connect (de->action_data_save, "activate",
1207                     G_CALLBACK (data_save), de);
1208
1209
1210
1211   de->action_data_save_as = gtk_action_new ("data-save-as-dialog",
1212                                             _("Save As"),
1213                                             _("Save data to file"),
1214                                             "gtk-save");
1215
1216   g_signal_connect (de->action_data_save_as, "activate",
1217                     G_CALLBACK (data_save_as_dialog), de);
1218
1219   de->action_data_new =
1220     gtk_action_new ("data-new",
1221                     _("New"),
1222                     _("New data file"),
1223                     NULL);
1224
1225   g_signal_connect (de->action_data_new, "activate",
1226                     G_CALLBACK (new_file), de);
1227 }
1228
1229 /* Returns true if NAME has a suffix which might denote a PSPP file */
1230 static gboolean
1231 name_has_suffix (const gchar *name)
1232 {
1233   if ( g_str_has_suffix (name, ".sav"))
1234     return TRUE;
1235   if ( g_str_has_suffix (name, ".SAV"))
1236     return TRUE;
1237   if ( g_str_has_suffix (name, ".por"))
1238     return TRUE;
1239   if ( g_str_has_suffix (name, ".POR"))
1240     return TRUE;
1241
1242   return FALSE;
1243 }
1244
1245 /* Append SUFFIX to the filename of DE */
1246 static void
1247 append_filename_suffix (struct data_editor *de, const gchar *suffix)
1248 {
1249   if ( ! name_has_suffix (de->file_name))
1250     {
1251       gchar *s = de->file_name;
1252       de->file_name = g_strconcat (de->file_name, suffix, NULL);
1253       g_free (s);
1254     }
1255 }
1256
1257 /* Save DE to file */
1258 static void
1259 save_file (struct data_editor *de)
1260 {
1261   struct getl_interface *sss;
1262   struct string file_name ;
1263
1264   g_assert (de->file_name);
1265
1266   ds_init_cstr (&file_name, de->file_name);
1267   gen_quoted_string (&file_name);
1268
1269   if ( de->save_as_portable )
1270     {
1271       append_filename_suffix (de, ".por");
1272       sss = create_syntax_string_source ("EXPORT OUTFILE=%s.",
1273                                          ds_cstr (&file_name));
1274     }
1275   else
1276     {
1277       append_filename_suffix (de, ".sav");
1278       sss = create_syntax_string_source ("SAVE OUTFILE=%s.",
1279                                          ds_cstr (&file_name));
1280     }
1281
1282   ds_destroy (&file_name);
1283
1284   execute_syntax (sss);
1285 }
1286
1287
1288 /* Callback for data_save action.
1289    If there's an existing file name, then just save,
1290    otherwise prompt for a file name, then save */
1291 static void
1292 data_save (GtkAction *action, struct data_editor *de)
1293 {
1294   if ( de->file_name)
1295     save_file (de);
1296   else
1297     data_save_as_dialog (action, de);
1298 }
1299
1300
1301 /* Callback for data_save_as action. Prompt for a filename and save */
1302 static void
1303 data_save_as_dialog (GtkAction *action, struct data_editor *de)
1304 {
1305   struct editor_window *e = (struct editor_window *) de;
1306
1307   GtkWidget *button_sys;
1308   GtkWidget *dialog =
1309     gtk_file_chooser_dialog_new (_("Save"),
1310                                  GTK_WINDOW (e->window),
1311                                  GTK_FILE_CHOOSER_ACTION_SAVE,
1312                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1313                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1314                                  NULL);
1315
1316   GtkFileFilter *filter = gtk_file_filter_new ();
1317   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
1318   gtk_file_filter_add_pattern (filter, "*.sav");
1319   gtk_file_filter_add_pattern (filter, "*.SAV");
1320   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1321
1322   filter = gtk_file_filter_new ();
1323   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
1324   gtk_file_filter_add_pattern (filter, "*.por");
1325   gtk_file_filter_add_pattern (filter, "*.POR");
1326   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1327
1328   filter = gtk_file_filter_new ();
1329   gtk_file_filter_set_name (filter, _("All Files"));
1330   gtk_file_filter_add_pattern (filter, "*");
1331   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1332
1333   {
1334     GtkWidget *button_por;
1335     GtkWidget *vbox = gtk_vbox_new (TRUE, 5);
1336     button_sys =
1337       gtk_radio_button_new_with_label (NULL, _("System File"));
1338
1339     button_por =
1340       gtk_radio_button_new_with_label
1341       (gtk_radio_button_get_group (GTK_RADIO_BUTTON(button_sys)),
1342        _("Portable File"));
1343
1344     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_sys);
1345     gtk_box_pack_start_defaults (GTK_BOX (vbox), button_por);
1346
1347     gtk_widget_show_all (vbox);
1348
1349     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), vbox);
1350   }
1351
1352   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
1353     {
1354     case GTK_RESPONSE_ACCEPT:
1355       {
1356         g_free (de->file_name);
1357
1358         de->file_name =
1359           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1360
1361         de->save_as_portable =
1362           ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_sys));
1363
1364         save_file (de);
1365
1366         window_set_name_from_filename (e, de->file_name);
1367       }
1368       break;
1369     default:
1370       break;
1371     }
1372
1373   gtk_widget_destroy (dialog);
1374 }
1375
1376
1377 /* Callback for data_new action.
1378    Performs the NEW FILE command */
1379 static void
1380 new_file (GtkAction *action, struct editor_window *e)
1381 {
1382   struct data_editor *de = (struct data_editor *) e;
1383
1384   struct getl_interface *sss =
1385     create_syntax_string_source ("NEW FILE.");
1386
1387   execute_syntax (sss);
1388
1389   g_free (de->file_name);
1390   de->file_name = NULL;
1391
1392   default_window_name (e);
1393 }
1394
1395
1396 static void
1397 open_data_file (const gchar *file_name, struct data_editor *de)
1398 {
1399   struct getl_interface *sss;
1400   struct string filename;
1401
1402   ds_init_cstr (&filename, file_name);
1403
1404   gen_quoted_string (&filename);
1405
1406   sss = create_syntax_string_source ("GET FILE=%s.",
1407                                      ds_cstr (&filename));
1408   ds_destroy (&filename);
1409
1410   if (execute_syntax (sss) )
1411   {
1412     window_set_name_from_filename ((struct editor_window *) de, file_name);
1413     add_most_recent (file_name);
1414   }
1415 }
1416
1417
1418
1419 /* Callback for the data_open action.
1420    Prompts for a filename and opens it */
1421 static void
1422 open_data_dialog (GtkAction *action, struct data_editor *de)
1423 {
1424   struct editor_window *e = (struct editor_window *) de;
1425
1426   GtkWidget *dialog =
1427     gtk_file_chooser_dialog_new (_("Open"),
1428                                  GTK_WINDOW (e->window),
1429                                  GTK_FILE_CHOOSER_ACTION_OPEN,
1430                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1431                                  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1432                                  NULL);
1433
1434   GtkFileFilter *filter = gtk_file_filter_new ();
1435   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
1436   gtk_file_filter_add_pattern (filter, "*.sav");
1437   gtk_file_filter_add_pattern (filter, "*.SAV");
1438   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1439
1440   filter = gtk_file_filter_new ();
1441   gtk_file_filter_set_name (filter, _("Portable Files (*.por) "));
1442   gtk_file_filter_add_pattern (filter, "*.por");
1443   gtk_file_filter_add_pattern (filter, "*.POR");
1444   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1445
1446   filter = gtk_file_filter_new ();
1447   gtk_file_filter_set_name (filter, _("All Files"));
1448   gtk_file_filter_add_pattern (filter, "*");
1449   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1450
1451
1452   if ( de->file_name)
1453     {
1454       gchar *dir_name = g_path_get_dirname (de->file_name);
1455       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
1456                                            dir_name);
1457       free (dir_name);
1458     }
1459
1460   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
1461     {
1462     case GTK_RESPONSE_ACCEPT:
1463       {
1464         g_free (de->file_name);
1465         de->file_name =
1466           gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1467
1468         open_data_file (de->file_name, de);
1469       }
1470       break;
1471     default:
1472       break;
1473     }
1474
1475   gtk_widget_destroy (dialog);
1476 }
1477
1478
1479 static GtkWidget *
1480 create_data_sheet_variable_popup_menu (struct data_editor *de)
1481 {
1482   GtkWidget *menu = gtk_menu_new ();
1483
1484   GtkWidget *sort_ascending =
1485     gtk_menu_item_new_with_label (_("Sort Ascending"));
1486
1487   GtkWidget *sort_descending =
1488     gtk_menu_item_new_with_label (_("Sort Descending"));
1489
1490   GtkWidget *insert_variable =
1491     gtk_menu_item_new_with_label (_("Insert Variable"));
1492
1493   GtkWidget *clear_variable =
1494     gtk_menu_item_new_with_label (_("Clear"));
1495
1496   gtk_action_connect_proxy (de->insert_variable,
1497                             insert_variable );
1498
1499
1500   gtk_action_connect_proxy (de->delete_variables,
1501                             clear_variable );
1502
1503
1504   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
1505
1506
1507   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
1508                          gtk_separator_menu_item_new ());
1509
1510
1511   gtk_menu_shell_append (GTK_MENU_SHELL (menu), clear_variable);
1512
1513
1514   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
1515                          gtk_separator_menu_item_new ());
1516
1517
1518   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_ascending);
1519
1520
1521   g_signal_connect_swapped (G_OBJECT (sort_ascending), "activate",
1522                             G_CALLBACK (psppire_data_editor_sort_ascending),
1523                             de->data_editor);
1524
1525   g_signal_connect_swapped (G_OBJECT (sort_descending), "activate",
1526                             G_CALLBACK (psppire_data_editor_sort_descending),
1527                             de->data_editor);
1528
1529   gtk_menu_shell_append (GTK_MENU_SHELL (menu), sort_descending);
1530
1531   gtk_widget_show_all (menu);
1532
1533   return menu;
1534 }
1535
1536
1537 static GtkWidget *
1538 create_data_sheet_cases_popup_menu (struct data_editor *de)
1539 {
1540   GtkWidget *menu = gtk_menu_new ();
1541
1542   GtkWidget *insert_case =
1543     gtk_menu_item_new_with_label (_("Insert Case"));
1544
1545   GtkWidget *delete_case =
1546     gtk_menu_item_new_with_label (_("Clear"));
1547
1548
1549   gtk_action_connect_proxy (de->insert_case,
1550                             insert_case);
1551
1552
1553   gtk_action_connect_proxy (de->delete_cases,
1554                             delete_case);
1555
1556
1557   gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_case);
1558
1559
1560   gtk_menu_shell_append (GTK_MENU_SHELL (menu),
1561                          gtk_separator_menu_item_new ());
1562
1563
1564   gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_case);
1565
1566
1567   gtk_widget_show_all (menu);
1568
1569   return menu;
1570 }
1571
1572
1573 \f
1574
1575 static void
1576 on_edit_paste (GtkAction *a, gpointer data)
1577 {
1578   struct data_editor *de = data;
1579
1580   psppire_data_editor_clip_paste (de->data_editor);
1581 }
1582
1583 static void
1584 on_edit_copy (GtkMenuItem *m, gpointer data)
1585 {
1586   struct data_editor *de = data;
1587
1588   psppire_data_editor_clip_copy (de->data_editor);
1589 }
1590
1591
1592
1593 static void
1594 on_edit_cut (GtkMenuItem *m, gpointer data)
1595 {
1596   struct data_editor *de = data;
1597
1598   psppire_data_editor_clip_cut (de->data_editor);
1599 }