d10cd5153adee192c945bc7c10bd57a187f2b0de
[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
24 #include <data/file-handle-def.h>
25 #include <data/sys-file-reader.h>
26 #include <data/case.h>
27
28 #include <glade/glade.h>
29 #include <gtk/gtk.h>
30
31 #include <gtksheet/gtksheet.h>
32 #include "helper.h"
33 #include "menu-actions.h"
34 #include "psppire-variable.h"
35 #include "psppire-dict.h"
36
37 #include "var-sheet.h"
38 #include "data-sheet.h"
39
40 #include "psppire-var-store.h"
41 #include "psppire-data-store.h"
42
43 #define _(A) A
44 #define N_(A) A
45
46
47 extern GladeXML *xml;
48
49
50 extern PsppireDict *the_dictionary ;
51 extern PsppireCaseArray *the_cases ;
52
53
54 static struct file_handle *psppire_handle = 0;
55
56 static const gchar handle_name[] = "psppire_handle";
57
58 static const gchar untitled[] = _("Untitled");
59
60 static const gchar window_title[]=_("PSPP Data Editor");
61
62
63 static void
64 psppire_set_window_title(const gchar *text)
65 {
66   GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
67   
68   gchar *title = g_strdup_printf("%s --- %s", text, window_title);
69
70   gtk_window_set_title(GTK_WINDOW(data_editor), title);
71
72   g_free(title);
73 }
74
75 void
76 on_new1_activate                       (GtkMenuItem     *menuitem,
77                                         gpointer         user_data)
78 {
79   psppire_dict_clear(the_dictionary);
80   psppire_case_array_clear(the_cases);
81
82   psppire_set_window_title(untitled);
83
84   if (psppire_handle)
85     fh_free(psppire_handle);
86   psppire_handle = 0 ;
87 }
88
89 static gboolean
90 populate_case_from_reader(struct ccase *c, gpointer aux)
91 {
92   struct sfm_reader *reader = aux;
93
94   return sfm_read_case(reader, c);
95 }
96
97
98 void
99 on_open1_activate                      (GtkMenuItem     *menuitem,
100                                         gpointer         user_data)
101 {
102   GtkWidget *dialog;
103   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
104  
105   dialog = gtk_file_chooser_dialog_new (_("Open"),
106                                         GTK_WINDOW(data_editor),
107                                         GTK_FILE_CHOOSER_ACTION_OPEN,
108                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
109                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
110                                         NULL);
111   GtkFileFilter *filter ;
112
113   filter = gtk_file_filter_new();
114   gtk_file_filter_set_name(filter, _("System Files (*.sav)"));
115   gtk_file_filter_add_pattern(filter, "*.sav");
116   gtk_file_filter_add_pattern(filter, "*.SAV");
117   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
118
119   filter = gtk_file_filter_new();
120   gtk_file_filter_set_name(filter, _("Portable Files (*.por) "));
121   gtk_file_filter_add_pattern(filter, "*.por");
122   gtk_file_filter_add_pattern(filter, "*.POR");
123   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
124
125   filter = gtk_file_filter_new();
126   gtk_file_filter_set_name(filter, _("All Files"));
127   gtk_file_filter_add_pattern(filter, "*");
128   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
129
130
131   bool finished = FALSE;
132   do {
133
134     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
135       {
136         GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
137         g_assert(data_sheet);
138
139         GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
140         g_assert(var_sheet);
141
142         char *filename = gtk_file_chooser_get_filename
143           (GTK_FILE_CHOOSER (dialog));
144
145         if ( psppire_handle ) 
146           fh_free(psppire_handle);
147
148         psppire_handle = 
149           fh_create_file (handle_name, filename, fh_default_properties());
150
151         if ( !psppire_handle ) 
152           {
153             g_warning("Cannot read handle for reading system file \"%s\"\n", 
154                       filename);
155             continue;
156           }
157
158         struct dictionary *new_dict;
159         struct sfm_read_info ri;
160         struct sfm_reader *reader ; 
161
162         reader = sfm_open_reader (psppire_handle, &new_dict, &ri);
163       
164         if ( ! reader ) 
165           continue;
166
167         the_dictionary = psppire_dict_new_from_dict(new_dict);
168
169         PsppireVarStore *var_store = 
170           PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet)));
171         
172         psppire_var_store_set_dictionary(var_store, the_dictionary);
173
174
175         PsppireDataStore *data_store = 
176           PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet)));
177         
178
179         psppire_data_store_set_dictionary(data_store,
180                                           the_dictionary);
181
182         psppire_case_array_clear(data_store->cases);
183
184
185         psppire_set_window_title(basename(filename));
186
187         g_free (filename);
188
189         const int ni = dict_get_next_value_idx(the_dictionary->dict);
190         if ( ni == 0 ) 
191           goto done;
192       
193         gint case_num;
194         for(case_num=0;;case_num++)
195           {
196             if (!psppire_case_array_add_case(the_cases, 
197                                      populate_case_from_reader, reader))
198               break;
199           }
200
201         sfm_close_reader(reader);
202         finished = TRUE;
203       }
204     else
205       {
206         finished = TRUE;
207       }
208   } while ( ! finished ) ;
209
210  done:
211   gtk_widget_destroy (dialog);
212 }
213
214
215 /* Re initialise HANDLE, by interrogating the user for a new file name */
216 static void
217 recreate_save_handle(struct file_handle **handle)
218 {
219   GtkWidget *dialog;
220
221   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
222
223   dialog = gtk_file_chooser_dialog_new (_("Save Data As"),
224                                         GTK_WINDOW(data_editor),
225                                         GTK_FILE_CHOOSER_ACTION_SAVE,
226                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
227                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
228                                         NULL);
229
230   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
231     {
232       char *filename = gtk_file_chooser_get_filename
233         (GTK_FILE_CHOOSER (dialog));
234
235 #if 0
236       if ( *handle ) 
237         destroy_file_handle(*handle, 0);
238 #endif
239       *handle = fh_create_file (handle_name, filename, fh_default_properties());
240
241       psppire_set_window_title(basename(filename));
242
243       g_free (filename);
244     }
245
246   gtk_widget_destroy (dialog);
247 }
248
249 void
250 on_save1_activate                      (GtkMenuItem     *menuitem,
251                                         gpointer         user_data)
252 {
253   if ( ! psppire_handle ) 
254     recreate_save_handle(&psppire_handle);
255   
256   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
257   PsppireDataStore *data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
258   
259   if ( psppire_handle ) 
260     psppire_data_store_create_system_file(data_store,
261                                        psppire_handle);
262 }
263
264
265 void
266 on_save_as1_activate                   (GtkMenuItem     *menuitem,
267                                         gpointer         user_data)
268 {
269   recreate_save_handle(&psppire_handle);
270   if ( ! psppire_handle ) 
271     return ;
272
273   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
274   PsppireDataStore *data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
275
276   if ( psppire_handle ) 
277     psppire_data_store_create_system_file(data_store,
278                                        psppire_handle);
279 }
280
281
282 void
283 on_quit1_activate                      (GtkMenuItem     *menuitem,
284                                         gpointer         user_data)
285 {
286   gtk_main_quit();
287 }
288
289
290 void
291 on_cut1_activate                       (GtkMenuItem     *menuitem,
292                                         gpointer         user_data)
293 {
294
295 }
296
297
298 void
299 on_copy1_activate                      (GtkMenuItem     *menuitem,
300                                         gpointer         user_data)
301 {
302
303 }
304
305
306 void
307 on_paste1_activate                     (GtkMenuItem     *menuitem,
308                                         gpointer         user_data)
309 {
310
311 }
312
313
314 void
315 on_insert1_activate                    (GtkMenuItem     *menuitem,
316                                         gpointer         user_data)
317 {
318   GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
319   gint page = -1;
320
321   page = gtk_notebook_get_current_page(notebook);
322
323   switch (page) 
324     {
325     case PAGE_DATA_SHEET:
326       {
327         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
328         PsppireDataStore *data_store = 
329           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
330
331         psppire_case_array_insert_case(data_store->cases, data_sheet->range.row0);
332       }
333       break;
334     case PAGE_VAR_SHEET:
335       {
336         GtkSheet *var_sheet = 
337           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
338
339         PsppireVarStore *var_store = 
340           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
341
342         psppire_dict_insert_variable(var_store->dict, var_sheet->range.row0, 0);
343       }
344       break;
345     }
346 }
347
348 void
349 on_delete1_activate                    (GtkMenuItem     *menuitem,
350                                         gpointer         user_data)
351 {
352   gint page = -1;
353   GtkWidget *notebook = get_widget_assert(xml, "notebook1");
354
355   page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
356   switch ( page) 
357     {
358     case PAGE_DATA_SHEET:
359       {
360         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
361         PsppireDataStore *data_store = 
362           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
363
364         psppire_case_array_delete_cases(data_store->cases, 
365                                     data_sheet->range.row0, 
366                                     1 + data_sheet->range.rowi 
367                                     - data_sheet->range.row0  );
368       }
369       break;
370     case PAGE_VAR_SHEET:
371       {
372         GtkSheet *var_sheet = 
373           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
374
375         PsppireVarStore *var_store = 
376           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
377
378         psppire_dict_delete_variables(var_store->dict, 
379                                    var_sheet->range.row0,
380                                    1 + var_sheet->range.rowi 
381                                    - var_sheet->range.row0  );
382       }
383       break;
384     }
385 }
386
387
388 void
389 on_about1_activate(GtkMenuItem     *menuitem,
390                    gpointer         user_data)
391 {
392   GtkWidget *about =  get_widget_assert(xml, "aboutdialog1");
393   
394   
395   GdkPixbuf *pb  = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0);
396
397   gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb);
398
399   gtk_widget_show(about);
400
401   gtk_window_set_transient_for(GTK_WINDOW(about), 
402                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
403 }
404
405
406
407 void
408 on_toolbars1_activate
409                      (GtkMenuItem     *menuitem,
410                                         gpointer         user_data)
411 {
412
413
414 }
415
416 void
417 on_value_labels1_activate(GtkCheckMenuItem     *menuitem,
418                           gpointer         user_data)
419 {
420   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
421   PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
422                 
423   psppire_data_store_show_labels(ds, 
424                               gtk_check_menu_item_get_active(menuitem));
425 }
426
427 void
428 on_status_bar1_activate(GtkCheckMenuItem     *menuitem,
429  gpointer         user_data)
430 {
431
432   if ( gtk_check_menu_item_get_active(menuitem) ) 
433     gtk_widget_show(get_widget_assert(xml, "statusbar1"));
434   else
435     gtk_widget_hide(get_widget_assert(xml, "statusbar1"));
436 }
437
438 void
439 on_grid_lines1_activate(GtkCheckMenuItem     *menuitem,
440  gpointer         user_data)
441 {
442
443   const bool grid_visible = gtk_check_menu_item_get_active(menuitem); 
444
445   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")),
446                       grid_visible);
447
448   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "data_sheet")),
449                       grid_visible);
450 }
451
452
453 void
454 on_fonts1_activate(GtkMenuItem     *menuitem,
455  gpointer         user_data)
456 {
457   static GtkWidget *dialog = 0 ; 
458   if ( !dialog ) 
459     dialog   = gtk_font_selection_dialog_new(_("Font Selection"));
460
461   gtk_window_set_transient_for(GTK_WINDOW(dialog), 
462                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
463
464
465   if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) ) 
466     {
467       GtkSheet *data_sheet = 
468         GTK_SHEET(get_widget_assert(xml, "data_sheet"));
469
470       GtkSheet *var_sheet = 
471         GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
472
473       PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
474       PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
475
476       const gchar *font = gtk_font_selection_dialog_get_font_name 
477         (GTK_FONT_SELECTION_DIALOG(dialog));
478
479       PangoFontDescription* font_desc = 
480         pango_font_description_from_string(font);
481
482       psppire_var_store_set_font(vs, font_desc);
483       psppire_data_store_set_font(ds, font_desc);
484     }
485   
486   gtk_widget_hide(dialog);
487
488 }
489
490
491 static GtkWidget *menuitems[2];
492 static GtkNotebook *notebook = 0;
493
494 static void
495 switch_menus(gint page)
496 {
497   switch (page) 
498     {
499     case PAGE_VAR_SHEET:
500       gtk_widget_hide(menuitems[PAGE_VAR_SHEET]);
501       gtk_widget_show(menuitems[PAGE_DATA_SHEET]);
502       break;
503     case PAGE_DATA_SHEET:
504       gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
505       gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
506       break;
507     default:
508       g_assert_not_reached();
509       break;
510     }
511 }
512
513
514 void
515 select_sheet(gint page)
516 {
517   gtk_notebook_set_current_page(notebook, page);
518   switch_menus(page);
519 }
520
521
522
523 static void
524 data_var_select(GtkNotebook *notebook,
525                 GtkNotebookPage *page,
526                 guint page_num,
527                 gpointer user_data)
528 {
529   switch_menus(page_num);
530 }
531
532 static void
533 var_data_selection_init()
534 {
535   notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
536   menuitems[PAGE_DATA_SHEET] = get_widget_assert(xml, "data1");
537   menuitems[PAGE_VAR_SHEET] = get_widget_assert(xml, "variables1");
538
539   gtk_notebook_set_current_page(notebook, PAGE_DATA_SHEET);
540   gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
541   gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
542
543
544   g_signal_connect(G_OBJECT(notebook), "switch-page",
545                    G_CALLBACK(data_var_select), 0);
546
547 }
548
549
550 void
551 on_data1_activate(GtkMenuItem     *menuitem,
552                   gpointer         user_data)
553 {
554   select_sheet(PAGE_DATA_SHEET);
555 }
556
557
558 void
559 on_variables1_activate(GtkMenuItem     *menuitem,
560                   gpointer         user_data)
561 {
562   select_sheet(PAGE_VAR_SHEET);
563 }
564
565
566 /* Callback which occurs when gtk_main is entered */
567 gboolean
568 callbacks_on_init(gpointer data)
569 {
570   psppire_set_window_title(untitled);
571
572   var_data_selection_init();
573
574   return FALSE;
575 }