Fixed a lot of internationalisation issues.
[pspp-builds.git] / src / ui / gui / menu-actions.c
1 /* 
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2004, 2005  Free Software Foundation
4     Written by John Darrington
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19     02110-1301, USA. */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <gettext.h>
24 #define _(msgid) gettext (msgid)
25 #define N_(msgid) msgid
26
27
28 #include <data/file-handle-def.h>
29 #include <data/sys-file-reader.h>
30 #include <data/case.h>
31
32 #include <glade/glade.h>
33 #include <gtk/gtk.h>
34
35 #include <gtksheet/gtksheet.h>
36 #include "helper.h"
37 #include "menu-actions.h"
38 #include "psppire-variable.h"
39 #include "psppire-dict.h"
40
41 #include "var-sheet.h"
42 #include "data-sheet.h"
43
44 #include "psppire-var-store.h"
45 #include "psppire-data-store.h"
46
47
48
49 extern GladeXML *xml;
50
51
52 extern PsppireDict *the_dictionary ;
53 extern PsppireCaseArray *the_cases ;
54
55
56 static struct file_handle *psppire_handle = 0;
57
58 static const gchar handle_name[] = "psppire_handle";
59
60 static const gchar untitled[] = N_("Untitled");
61
62 static const gchar window_title[] = N_("PSPP Data Editor");
63
64
65 static void
66 psppire_set_window_title(const gchar *text)
67 {
68   GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
69   
70   gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title));
71
72   gtk_window_set_title(GTK_WINDOW(data_editor), title);
73
74   g_free(title);
75 }
76
77 void
78 on_new1_activate                       (GtkMenuItem     *menuitem,
79                                         gpointer         user_data)
80 {
81   GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
82   GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
83  
84   gtk_sheet_set_active_cell(GTK_SHEET(data_sheet), -1, -1);
85
86   gtk_sheet_set_active_cell(GTK_SHEET(var_sheet), 0, 0);
87
88   psppire_dict_clear(the_dictionary);
89   psppire_case_array_clear(the_cases);
90   
91   psppire_set_window_title(gettext(untitled));
92
93   if (psppire_handle)
94     fh_free(psppire_handle);
95   psppire_handle = 0 ;
96 }
97
98
99 static gboolean
100 populate_case_from_reader(struct ccase *c, gpointer aux)
101 {
102   struct sfm_reader *reader = aux;
103
104   return sfm_read_case(reader, c);
105 }
106
107
108 /* Load a system file.
109    Return TRUE if successfull
110 */
111 gboolean
112 load_system_file(const gchar *file_name)
113 {
114   int ni ;
115   gint case_num;
116
117   PsppireVarStore *var_store ;
118   PsppireDataStore *data_store ;
119   struct dictionary *new_dict;
120   struct sfm_read_info ri;
121   struct sfm_reader *reader ; 
122
123   GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
124   GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
125
126
127   g_assert(data_sheet);
128   g_assert(var_sheet);
129
130   if ( psppire_handle ) 
131     fh_free(psppire_handle);
132
133   psppire_handle = 
134     fh_create_file (handle_name, file_name, fh_default_properties());
135
136   if ( !psppire_handle ) 
137     {
138       g_warning("Cannot read handle for reading system file \"%s\"\n", 
139                 file_name);
140       return FALSE;
141     }
142
143
144   reader = sfm_open_reader (psppire_handle, &new_dict, &ri);
145       
146   if ( ! reader ) 
147     return FALSE;
148
149   /* FIXME: We need a better way of updating a dictionary than this */
150   the_dictionary = psppire_dict_new_from_dict(new_dict);
151
152   var_store = 
153     PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet)));
154         
155   psppire_var_store_set_dictionary(var_store, the_dictionary);
156
157
158   data_store = 
159     PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet)));
160         
161   psppire_data_store_set_dictionary(data_store,
162                                     the_dictionary);
163
164   psppire_case_array_clear(data_store->cases);
165
166
167   psppire_set_window_title(basename(file_name));
168
169   ni = dict_get_next_value_idx(the_dictionary->dict);
170   if ( ni == 0 ) 
171     return FALSE;
172
173   for(case_num=0;;case_num++)
174     {
175       if (!psppire_case_array_append_case(the_cases, 
176                                           populate_case_from_reader, 
177                                           reader))
178         break;
179     }
180
181
182   sfm_close_reader(reader);
183
184   return TRUE;
185 }
186
187
188 void
189 on_open1_activate                      (GtkMenuItem     *menuitem,
190                                         gpointer         user_data)
191 {
192   bool finished = FALSE;
193
194   GtkWidget *dialog;
195   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
196   GtkFileFilter *filter ;
197  
198   dialog = gtk_file_chooser_dialog_new (_("Open"),
199                                         GTK_WINDOW(data_editor),
200                                         GTK_FILE_CHOOSER_ACTION_OPEN,
201                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
202                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
203                                         NULL);
204
205   filter = gtk_file_filter_new();
206   gtk_file_filter_set_name(filter, _("System Files (*.sav)"));
207   gtk_file_filter_add_pattern(filter, "*.sav");
208   gtk_file_filter_add_pattern(filter, "*.SAV");
209   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
210
211   filter = gtk_file_filter_new();
212   gtk_file_filter_set_name(filter, _("Portable Files (*.por) "));
213   gtk_file_filter_add_pattern(filter, "*.por");
214   gtk_file_filter_add_pattern(filter, "*.POR");
215   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
216
217   filter = gtk_file_filter_new();
218   gtk_file_filter_set_name(filter, _("All Files"));
219   gtk_file_filter_add_pattern(filter, "*");
220   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
221
222   do {
223
224     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
225       {
226         gchar *file_name = 
227           gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
228         
229         finished =  load_system_file(file_name) ;
230
231         g_free(file_name);
232       }
233     else
234       finished = TRUE;
235
236   } while ( ! finished ) ;
237
238   gtk_widget_destroy (dialog);
239 }
240
241
242 /* Re initialise HANDLE, by interrogating the user for a new file name */
243 static void
244 recreate_save_handle(struct file_handle **handle)
245 {
246   GtkWidget *dialog;
247
248   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
249
250   dialog = gtk_file_chooser_dialog_new (_("Save Data As"),
251                                         GTK_WINDOW(data_editor),
252                                         GTK_FILE_CHOOSER_ACTION_SAVE,
253                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
254                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
255                                         NULL);
256
257   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
258     {
259       char *file_name = gtk_file_chooser_get_filename
260         (GTK_FILE_CHOOSER (dialog));
261
262 #if 0
263       if ( *handle ) 
264         destroy_file_handle(*handle, 0);
265 #endif
266       *handle = fh_create_file (handle_name, file_name, fh_default_properties());
267
268       psppire_set_window_title(basename(file_name));
269
270       g_free (file_name);
271     }
272
273   gtk_widget_destroy (dialog);
274 }
275
276 void
277 on_save1_activate                      (GtkMenuItem     *menuitem,
278                                         gpointer         user_data)
279 {
280   GtkSheet *data_sheet ;
281   PsppireDataStore *data_store ;
282
283   if ( ! psppire_handle ) 
284     recreate_save_handle(&psppire_handle);
285   
286   data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
287   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
288   
289   if ( psppire_handle ) 
290     psppire_data_store_create_system_file(data_store,
291                                        psppire_handle);
292 }
293
294
295 void
296 on_save_as1_activate                   (GtkMenuItem     *menuitem,
297                                         gpointer         user_data)
298 {
299   GtkSheet *data_sheet ;
300   PsppireDataStore *data_store ;
301
302   recreate_save_handle(&psppire_handle);
303   if ( ! psppire_handle ) 
304     return ;
305
306   data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
307   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
308
309   if ( psppire_handle ) 
310     psppire_data_store_create_system_file(data_store,
311                                        psppire_handle);
312 }
313
314
315 void
316 on_quit1_activate                      (GtkMenuItem     *menuitem,
317                                         gpointer         user_data)
318 {
319   gtk_main_quit();
320 }
321
322
323 void
324 on_cut1_activate                       (GtkMenuItem     *menuitem,
325                                         gpointer         user_data)
326 {
327
328 }
329
330
331 void
332 on_copy1_activate                      (GtkMenuItem     *menuitem,
333                                         gpointer         user_data)
334 {
335
336 }
337
338
339 void
340 on_paste1_activate                     (GtkMenuItem     *menuitem,
341                                         gpointer         user_data)
342 {
343
344 }
345
346 /* Fill a case with SYSMIS for numeric and whitespace for string
347    variables respectively */ 
348 static gboolean 
349 blank_case(struct ccase *cc, gpointer _dict)
350 {
351   gint i;
352   PsppireDict *dict = _dict;
353
354   for(i = 0 ; i < psppire_dict_get_var_cnt(dict); ++i ) 
355     {
356       union value *val ;
357
358       const struct PsppireVariable *var = psppire_dict_get_variable(dict, i);
359       
360       gint idx = psppire_variable_get_index(var);
361
362       val = case_data_rw(cc, idx) ;
363
364       if ( psppire_variable_get_type(var) == ALPHA ) 
365         memset(val->s, ' ', psppire_variable_get_width(var));
366       else
367         val->f = SYSMIS;
368
369       case_unshare(cc);
370     }
371
372   return TRUE;
373 }
374
375
376 void
377 on_insert1_activate                    (GtkMenuItem     *menuitem,
378                                         gpointer         user_data)
379 {
380   GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
381   gint page = -1;
382
383   page = gtk_notebook_get_current_page(notebook);
384
385   switch (page) 
386     {
387     case PAGE_DATA_SHEET:
388       {
389         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
390         PsppireDataStore *data_store = 
391           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
392
393         psppire_case_array_insert_case(data_store->cases, 
394                                        data_sheet->range.row0, 
395                                        blank_case, the_dictionary);
396       }
397       break;
398     case PAGE_VAR_SHEET:
399       {
400         GtkSheet *var_sheet = 
401           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
402
403         PsppireVarStore *var_store = 
404           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
405
406         psppire_dict_insert_variable(var_store->dict, var_sheet->range.row0, 0);
407       }
408       break;
409     }
410 }
411
412 void
413 on_delete1_activate                    (GtkMenuItem     *menuitem,
414                                         gpointer         user_data)
415 {
416   gint page = -1;
417   GtkWidget *notebook = get_widget_assert(xml, "notebook1");
418
419   page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
420   switch ( page) 
421     {
422     case PAGE_DATA_SHEET:
423       {
424         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
425         PsppireDataStore *data_store = 
426           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
427
428         psppire_case_array_delete_cases(data_store->cases, 
429                                     data_sheet->range.row0, 
430                                     1 + data_sheet->range.rowi 
431                                     - data_sheet->range.row0  );
432       }
433       break;
434     case PAGE_VAR_SHEET:
435       {
436         GtkSheet *var_sheet = 
437           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
438
439         PsppireVarStore *var_store = 
440           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
441
442         psppire_dict_delete_variables(var_store->dict, 
443                                    var_sheet->range.row0,
444                                    1 + var_sheet->range.rowi 
445                                    - var_sheet->range.row0  );
446       }
447       break;
448     }
449 }
450
451
452 void
453 on_about1_activate(GtkMenuItem     *menuitem,
454                    gpointer         user_data)
455 {
456   GtkWidget *about =  get_widget_assert(xml, "aboutdialog1");
457   
458   
459   GdkPixbuf *pb  = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0);
460
461   gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb);
462
463   gtk_widget_show(about);
464
465   gtk_window_set_transient_for(GTK_WINDOW(about), 
466                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
467 }
468
469
470
471 void
472 on_toolbars1_activate
473                      (GtkMenuItem     *menuitem,
474                                         gpointer         user_data)
475 {
476
477
478 }
479
480 void
481 on_value_labels1_activate(GtkCheckMenuItem     *menuitem,
482                           gpointer         user_data)
483 {
484   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
485   PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
486                 
487   psppire_data_store_show_labels(ds, 
488                               gtk_check_menu_item_get_active(menuitem));
489 }
490
491 void
492 on_status_bar1_activate(GtkCheckMenuItem     *menuitem,
493  gpointer         user_data)
494 {
495
496   if ( gtk_check_menu_item_get_active(menuitem) ) 
497     gtk_widget_show(get_widget_assert(xml, "statusbar1"));
498   else
499     gtk_widget_hide(get_widget_assert(xml, "statusbar1"));
500 }
501
502 void
503 on_grid_lines1_activate(GtkCheckMenuItem     *menuitem,
504  gpointer         user_data)
505 {
506
507   const bool grid_visible = gtk_check_menu_item_get_active(menuitem); 
508
509   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")),
510                       grid_visible);
511
512   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "data_sheet")),
513                       grid_visible);
514 }
515
516
517 void
518 on_fonts1_activate(GtkMenuItem     *menuitem,
519  gpointer         user_data)
520 {
521   static GtkWidget *dialog = 0 ; 
522   if ( !dialog ) 
523     dialog   = gtk_font_selection_dialog_new(_("Font Selection"));
524
525   gtk_window_set_transient_for(GTK_WINDOW(dialog), 
526                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
527
528
529   if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) ) 
530     {
531       GtkSheet *data_sheet = 
532         GTK_SHEET(get_widget_assert(xml, "data_sheet"));
533
534       GtkSheet *var_sheet = 
535         GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
536
537       PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
538       PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
539
540       const gchar *font = gtk_font_selection_dialog_get_font_name 
541         (GTK_FONT_SELECTION_DIALOG(dialog));
542
543       PangoFontDescription* font_desc = 
544         pango_font_description_from_string(font);
545
546       psppire_var_store_set_font(vs, font_desc);
547       psppire_data_store_set_font(ds, font_desc);
548     }
549   
550   gtk_widget_hide(dialog);
551
552 }
553
554
555 static GtkWidget *menuitems[2];
556 static GtkNotebook *notebook = 0;
557
558 static void
559 switch_menus(gint page)
560 {
561   switch (page) 
562     {
563     case PAGE_VAR_SHEET:
564       gtk_widget_hide(menuitems[PAGE_VAR_SHEET]);
565       gtk_widget_show(menuitems[PAGE_DATA_SHEET]);
566       break;
567     case PAGE_DATA_SHEET:
568       gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
569       gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
570       break;
571     default:
572       g_assert_not_reached();
573       break;
574     }
575 }
576
577
578 void
579 select_sheet(gint page)
580 {
581   gtk_notebook_set_current_page(notebook, page);
582   switch_menus(page);
583 }
584
585
586
587 static void
588 data_var_select(GtkNotebook *notebook,
589                 GtkNotebookPage *page,
590                 guint page_num,
591                 gpointer user_data)
592 {
593   switch_menus(page_num);
594 }
595
596 static void
597 var_data_selection_init()
598 {
599   notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
600   menuitems[PAGE_DATA_SHEET] = get_widget_assert(xml, "data1");
601   menuitems[PAGE_VAR_SHEET] = get_widget_assert(xml, "variables1");
602
603   gtk_notebook_set_current_page(notebook, PAGE_DATA_SHEET);
604   gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
605   gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
606
607
608   g_signal_connect(G_OBJECT(notebook), "switch-page",
609                    G_CALLBACK(data_var_select), 0);
610
611 }
612
613
614 void
615 on_data1_activate(GtkMenuItem     *menuitem,
616                   gpointer         user_data)
617 {
618   select_sheet(PAGE_DATA_SHEET);
619 }
620
621
622 void
623 on_variables1_activate(GtkMenuItem     *menuitem,
624                   gpointer         user_data)
625 {
626   select_sheet(PAGE_VAR_SHEET);
627 }
628
629
630 /* Callback which occurs when gtk_main is entered */
631 gboolean
632 callbacks_on_init(gpointer data)
633 {
634   psppire_set_window_title(gettext(untitled));
635
636   var_data_selection_init();
637
638   return FALSE;
639 }