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