b027b5a6aee9f234e4d0552355eaf989024c02b0
[pspp-builds.git] / src / ui / gui / menu-actions.c
1 /* 
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2004, 2005, 2006  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 #include <math/sort.h>
28
29 #include <data/casefile.h>
30 #include <data/file-handle-def.h>
31 #include <data/sys-file-reader.h>
32 #include <data/case.h>
33
34 #include <glade/glade.h>
35 #include <gtk/gtk.h>
36
37 #include <libpspp/str.h>
38
39 #include <gtksheet/gtksheet.h>
40 #include "helper.h"
41 #include "menu-actions.h"
42 #include "psppire-variable.h"
43 #include "psppire-dict.h"
44
45 #include "var-sheet.h"
46 #include "data-sheet.h"
47
48 #include "psppire-var-store.h"
49 #include "psppire-data-store.h"
50
51 #include "sort-cases-dialog.h"
52
53
54 extern GladeXML *xml;
55
56
57 extern PsppireDict *the_dictionary ;
58
59 static struct file_handle *psppire_handle = 0;
60
61 static const gchar handle_name[] = "psppire_handle";
62
63 static const gchar untitled[] = N_("Untitled");
64
65 static const gchar window_title[] = N_("PSPP Data Editor");
66
67
68 /* Sets the title bar to TEXT */
69 static void
70 psppire_set_window_title(const gchar *text)
71 {
72   GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
73   
74   gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title));
75
76   gtk_window_set_title(GTK_WINDOW(data_editor), title);
77
78   g_free(title);
79 }
80
81 /* Clear the active file and set the data and var sheets to 
82    reflect this.
83  */
84 gboolean
85 clear_file(void)
86 {
87   PsppireDataStore *data_store ;
88   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
89   GtkSheet *var_sheet = GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
90
91   gtk_sheet_set_active_cell(data_sheet, -1, -1);
92   gtk_sheet_set_active_cell(var_sheet, 0, 0);
93
94   if ( GTK_WIDGET_REALIZED(GTK_WIDGET(data_sheet)))
95     gtk_sheet_unselect_range(data_sheet);
96
97   if ( GTK_WIDGET_REALIZED(GTK_WIDGET(var_sheet)))
98     gtk_sheet_unselect_range(var_sheet);
99
100   gtk_sheet_moveto(data_sheet, 0, 0, 0.0, 0.0);
101   gtk_sheet_moveto(var_sheet,  0, 0, 0.0, 0.0);
102
103   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
104
105   psppire_data_store_clear(data_store);
106
107   psppire_set_window_title(gettext(untitled));
108
109   if (psppire_handle)
110     fh_free(psppire_handle);
111   psppire_handle = 0 ;
112
113   return TRUE;
114 }
115
116 void
117 on_new1_activate                       (GtkMenuItem     *menuitem,
118                                         gpointer         user_data)
119 {
120   clear_file();
121 }
122
123
124
125 /* Load a system file.
126    Return TRUE if successfull
127 */
128 gboolean
129 load_system_file(const gchar *file_name)
130 {
131   int var_cnt ;
132
133   PsppireVarStore *var_store ;
134   PsppireDataStore *data_store ;
135   struct dictionary *new_dict;
136   struct sfm_read_info ri;
137   struct sfm_reader *reader ; 
138
139   GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
140   GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
141
142   g_assert(data_sheet);
143   g_assert(var_sheet);
144
145   clear_file();
146
147   psppire_handle = 
148     fh_create_file (handle_name, file_name, fh_default_properties());
149
150   if ( !psppire_handle ) 
151     {
152       g_warning("Cannot read handle for reading system file \"%s\"\n", 
153                 file_name);
154       return FALSE;
155     }
156
157   reader = sfm_open_reader (psppire_handle, &new_dict, &ri);
158       
159   if ( ! reader ) 
160     return FALSE;
161
162   /* FIXME: We need a better way of updating a dictionary than this */
163   the_dictionary = psppire_dict_new_from_dict(new_dict);
164
165   var_store = 
166     PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet)));
167         
168   psppire_var_store_set_dictionary(var_store, the_dictionary);
169
170
171   data_store = 
172     PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet)));
173         
174   psppire_data_store_set_dictionary(data_store,
175                                     the_dictionary);
176
177   psppire_set_window_title(basename(file_name));
178
179   var_cnt = dict_get_next_value_idx(the_dictionary->dict);
180   if ( var_cnt == 0 ) 
181     return FALSE;
182
183
184   for(;;)
185     {
186       struct ccase c;
187       case_create(&c, var_cnt);
188       if ( 0 == sfm_read_case (reader, &c) )
189         {
190           case_destroy(&c);
191           break;
192         }
193
194       if ( !psppire_case_file_append_case(data_store->case_file, &c) ) 
195         {
196           g_warning("Cannot write case to casefile\n");
197           break;
198         }
199       case_destroy(&c);
200     }
201   
202   sfm_close_reader(reader);      
203
204   psppire_case_file_get_case_count(data_store->case_file);
205
206   return TRUE;
207 }
208
209
210 void
211 on_open1_activate                      (GtkMenuItem     *menuitem,
212                                         gpointer         user_data)
213 {
214   bool finished = FALSE;
215
216   GtkWidget *dialog;
217   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
218   GtkFileFilter *filter ;
219  
220   dialog = gtk_file_chooser_dialog_new (_("Open"),
221                                         GTK_WINDOW(data_editor),
222                                         GTK_FILE_CHOOSER_ACTION_OPEN,
223                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
224                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
225                                         NULL);
226
227   filter = gtk_file_filter_new();
228   gtk_file_filter_set_name(filter, _("System Files (*.sav)"));
229   gtk_file_filter_add_pattern(filter, "*.sav");
230   gtk_file_filter_add_pattern(filter, "*.SAV");
231   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
232
233   filter = gtk_file_filter_new();
234   gtk_file_filter_set_name(filter, _("Portable Files (*.por) "));
235   gtk_file_filter_add_pattern(filter, "*.por");
236   gtk_file_filter_add_pattern(filter, "*.POR");
237   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
238
239   filter = gtk_file_filter_new();
240   gtk_file_filter_set_name(filter, _("All Files"));
241   gtk_file_filter_add_pattern(filter, "*");
242   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
243
244   do {
245
246     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
247       {
248         gchar *file_name = 
249           gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
250         
251         finished =  load_system_file(file_name) ;
252
253         g_free(file_name);
254       }
255     else
256       finished = TRUE;
257
258   } while ( ! finished ) ;
259
260   gtk_widget_destroy (dialog);
261 }
262
263
264 /* Re initialise HANDLE, by interrogating the user for a new file name */
265 static gboolean
266 recreate_save_handle(struct file_handle **handle)
267 {
268   gint response;
269   GtkWidget *dialog;
270
271   GtkWidget *data_editor  = get_widget_assert(xml, "data_editor");
272
273   dialog = gtk_file_chooser_dialog_new (_("Save Data As"),
274                                         GTK_WINDOW(data_editor),
275                                         GTK_FILE_CHOOSER_ACTION_SAVE,
276                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
277                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
278                                         NULL);
279
280   response = gtk_dialog_run (GTK_DIALOG (dialog));
281
282   if (response == GTK_RESPONSE_ACCEPT)
283     {
284       char *file_name = gtk_file_chooser_get_filename
285         (GTK_FILE_CHOOSER (dialog));
286
287
288       if ( *handle ) 
289         fh_free(*handle);
290
291       *handle = fh_create_file (handle_name, file_name, 
292                         fh_default_properties());
293
294       psppire_set_window_title(basename(file_name));
295
296       g_free (file_name);
297     }
298
299   gtk_widget_destroy (dialog);
300
301   return ( response == GTK_RESPONSE_ACCEPT ) ;
302 }
303
304 void
305 on_save1_activate                      (GtkMenuItem     *menuitem,
306                                         gpointer         user_data)
307 {
308   GtkSheet *data_sheet ;
309   PsppireDataStore *data_store ;
310
311   if ( ! psppire_handle ) 
312     {
313       if ( ! recreate_save_handle(&psppire_handle) ) 
314         return;
315     }
316   
317   data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
318   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
319   
320   if ( psppire_handle ) 
321     psppire_data_store_create_system_file(data_store,
322                                        psppire_handle);
323 }
324
325
326 void
327 on_save_as1_activate                   (GtkMenuItem     *menuitem,
328                                         gpointer         user_data)
329 {
330   GtkSheet *data_sheet ;
331   PsppireDataStore *data_store ;
332
333   if ( ! recreate_save_handle(&psppire_handle) ) 
334     return ;
335
336   if ( ! psppire_handle ) 
337     return ;
338
339   data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
340   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
341
342   if ( psppire_handle ) 
343     psppire_data_store_create_system_file(data_store,
344                                        psppire_handle);
345 }
346
347
348 void
349 on_quit1_activate                      (GtkMenuItem     *menuitem,
350                                         gpointer         user_data)
351 {
352   gtk_main_quit();
353 }
354
355
356 void
357 on_clear_activate                    (GtkMenuItem     *menuitem,
358                                       gpointer         user_data)
359 {
360   GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
361   gint page = -1;
362
363   page = gtk_notebook_get_current_page(notebook);
364
365   switch (page) 
366     {
367     case PAGE_DATA_SHEET:
368       {
369         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
370         PsppireDataStore *data_store = 
371           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
372         
373
374         switch ( data_sheet->state ) 
375           {
376           case GTK_SHEET_ROW_SELECTED:
377             psppire_case_file_delete_cases(data_store->case_file,
378                                            data_sheet->range.rowi 
379                                            - data_sheet->range.row0 + 1,
380                                            data_sheet->range.row0);
381             break;
382           case GTK_SHEET_COLUMN_SELECTED:
383             {
384               gint fv;
385               struct PsppireVariable *pv = 
386                 psppire_dict_get_variable(the_dictionary, 
387                                           data_sheet->range.col0);
388               fv = psppire_variable_get_fv(pv);
389               
390               
391               psppire_dict_delete_variables(the_dictionary, 
392                                             data_sheet->range.col0,
393                                             1);
394
395               psppire_case_file_insert_values(data_store->case_file, 
396                                               -1, fv);
397             }
398             break;
399           default:
400             gtk_sheet_cell_clear(data_sheet, 
401                                  data_sheet->active_cell.row,
402                                  data_sheet->active_cell.col);
403             break;
404           }
405
406       }
407       break;
408     }
409
410 }
411
412 void
413 on_insert1_activate                    (GtkMenuItem     *menuitem,
414                                         gpointer         user_data)
415 {
416   GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
417   gint page = -1;
418
419   page = gtk_notebook_get_current_page(notebook);
420
421   switch (page) 
422     {
423     case PAGE_DATA_SHEET:
424 #if 0
425       {
426         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
427         PsppireDataStore *data_store = 
428           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
429
430         psppire_case_array_insert_case(data_store->cases, 
431                                        data_sheet->range.row0, 
432                                        blank_case, the_dictionary);
433       }
434       break;
435 #endif
436     case PAGE_VAR_SHEET:
437       {
438         GtkSheet *var_sheet = 
439           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
440
441         PsppireVarStore *var_store = 
442           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
443
444         psppire_dict_insert_variable(var_store->dict, var_sheet->range.row0, 0);
445       }
446       break;
447     }
448 }
449
450 #if 0
451 void
452 on_delete1_activate                    (GtkMenuItem     *menuitem,
453                                         gpointer         user_data)
454 {
455   gint page = -1;
456   GtkWidget *notebook = get_widget_assert(xml, "notebook1");
457
458   page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
459   switch ( page) 
460     {
461 #if 0
462     case PAGE_DATA_SHEET:
463       {
464         GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
465         PsppireDataStore *data_store = 
466           PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
467
468         psppire_case_array_delete_cases(data_store->cases, 
469                                     data_sheet->range.row0, 
470                                     1 + data_sheet->range.rowi 
471                                     - data_sheet->range.row0  );
472       }
473       break;
474 #endif
475     case PAGE_VAR_SHEET:
476       {
477         GtkSheet *var_sheet = 
478           GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
479
480         PsppireVarStore *var_store = 
481           PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
482
483         psppire_dict_delete_variables(var_store->dict, 
484                                    var_sheet->range.row0,
485                                    1 + var_sheet->range.rowi 
486                                    - var_sheet->range.row0  );
487       }
488       break;
489     }
490 }
491 #endif
492
493 void
494 on_about1_activate(GtkMenuItem     *menuitem,
495                    gpointer         user_data)
496 {
497   GtkWidget *about =  get_widget_assert(xml, "aboutdialog1");
498   
499   
500   GdkPixbuf *pb  = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0);
501
502   gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb);
503
504   gtk_widget_show(about);
505
506   gtk_window_set_transient_for(GTK_WINDOW(about), 
507                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
508 }
509
510
511 /* Set the value labels state from the toolbar's toggle button */
512 void
513 on_togglebutton_value_labels_toggled(GtkToggleToolButton *toggle_tool_button,
514                                      gpointer             user_data)
515 {
516   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
517   GtkCheckMenuItem *item = 
518     GTK_CHECK_MENU_ITEM(get_widget_assert(xml, "menuitem-value-labels"));
519
520   PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
521
522   gboolean show_value_labels = gtk_toggle_tool_button_get_active(toggle_tool_button);
523   
524   gtk_check_menu_item_set_active(item, show_value_labels);
525
526   psppire_data_store_show_labels(ds, show_value_labels);
527 }
528
529 /* Set the value labels state from the view menu */
530 void
531 on_value_labels_activate(GtkCheckMenuItem     *menuitem,
532                           gpointer         user_data)
533 {
534   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
535   GtkToggleToolButton *tb = 
536    GTK_TOGGLE_TOOL_BUTTON(get_widget_assert(xml, "togglebutton-value-labels"));
537
538   PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
539
540   gboolean show_value_labels = gtk_check_menu_item_get_active(menuitem);
541
542   gtk_toggle_tool_button_set_active(tb, show_value_labels);
543
544   psppire_data_store_show_labels(ds, show_value_labels);
545 }
546
547 void
548 on_status_bar1_activate(GtkCheckMenuItem     *menuitem,
549  gpointer         user_data)
550 {
551
552   if ( gtk_check_menu_item_get_active(menuitem) ) 
553     gtk_widget_show(get_widget_assert(xml, "statusbar1"));
554   else
555     gtk_widget_hide(get_widget_assert(xml, "statusbar1"));
556 }
557
558 void
559 on_grid_lines1_activate(GtkCheckMenuItem     *menuitem,
560  gpointer         user_data)
561 {
562
563   const bool grid_visible = gtk_check_menu_item_get_active(menuitem); 
564
565   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")),
566                       grid_visible);
567
568   gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "data_sheet")),
569                       grid_visible);
570 }
571
572
573 void
574 on_fonts1_activate(GtkMenuItem     *menuitem,
575  gpointer         user_data)
576 {
577   static GtkWidget *dialog = 0 ; 
578   if ( !dialog ) 
579     dialog   = gtk_font_selection_dialog_new(_("Font Selection"));
580
581   gtk_window_set_transient_for(GTK_WINDOW(dialog), 
582                                GTK_WINDOW(get_widget_assert(xml, "data_editor")));
583
584
585   if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) ) 
586     {
587       GtkSheet *data_sheet = 
588         GTK_SHEET(get_widget_assert(xml, "data_sheet"));
589
590       GtkSheet *var_sheet = 
591         GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
592
593       PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
594       PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
595
596       const gchar *font = gtk_font_selection_dialog_get_font_name 
597         (GTK_FONT_SELECTION_DIALOG(dialog));
598
599       PangoFontDescription* font_desc = 
600         pango_font_description_from_string(font);
601
602       psppire_var_store_set_font(vs, font_desc);
603       psppire_data_store_set_font(ds, font_desc);
604     }
605   
606   gtk_widget_hide(dialog);
607
608 }
609
610
611 static GtkWidget *menuitems[2];
612 static GtkNotebook *notebook = 0;
613
614 static void
615 switch_menus(gint page)
616 {
617   GtkWidget *insert_variable = get_widget_assert(xml, "insert-variable");
618   GtkWidget *insert_cases = get_widget_assert(xml, "insert-cases");
619
620   switch (page) 
621     {
622     case PAGE_VAR_SHEET:
623       gtk_widget_hide(menuitems[PAGE_VAR_SHEET]);
624       gtk_widget_show(menuitems[PAGE_DATA_SHEET]);
625       gtk_widget_set_sensitive(insert_variable, TRUE);
626       gtk_widget_set_sensitive(insert_cases, FALSE);
627       break;
628     case PAGE_DATA_SHEET:
629       gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
630       gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
631       gtk_widget_set_sensitive(insert_variable, FALSE);
632       gtk_widget_set_sensitive(insert_cases, TRUE);
633       break;
634     default:
635       g_assert_not_reached();
636       break;
637     }
638 }
639
640
641 void
642 select_sheet(gint page)
643 {
644   gtk_notebook_set_current_page(notebook, page);
645   switch_menus(page);
646 }
647
648
649
650 static void
651 data_var_select(GtkNotebook *notebook,
652                 GtkNotebookPage *page,
653                 guint page_num,
654                 gpointer user_data)
655 {
656   switch_menus(page_num);
657 }
658
659
660 /* Initialised things on the variable sheet */
661 void
662 var_data_selection_init(void)
663 {
664   notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
665   menuitems[PAGE_DATA_SHEET] = get_widget_assert(xml, "data1");
666   menuitems[PAGE_VAR_SHEET] = get_widget_assert(xml, "variables1");
667
668   gtk_notebook_set_current_page(notebook, PAGE_DATA_SHEET);
669   gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
670   gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
671
672
673   g_signal_connect(G_OBJECT(notebook), "switch-page",
674                    G_CALLBACK(data_var_select), 0);
675
676 }
677
678
679 void
680 on_data1_activate(GtkMenuItem     *menuitem,
681                   gpointer         user_data)
682 {
683   select_sheet(PAGE_DATA_SHEET);
684 }
685
686
687 void
688 on_variables1_activate(GtkMenuItem     *menuitem,
689                   gpointer         user_data)
690 {
691   select_sheet(PAGE_VAR_SHEET);
692 }
693
694
695
696 void
697 on_go_to_case_activate(GtkMenuItem     *menuitem,
698                        gpointer         user_data)
699 {
700   GtkWidget *dialog = get_widget_assert(xml, "go_to_case_dialog");
701   GtkEntry *entry = GTK_ENTRY(get_widget_assert(xml, "entry_go_to_case"));
702   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
703   
704   gint result = gtk_dialog_run(GTK_DIALOG(dialog));
705   
706
707   
708   switch (result)
709     {
710     case GTK_RESPONSE_OK:
711       {
712         gint row, column;
713         const gchar *text = gtk_entry_get_text(entry);
714         gint casenum = g_strtod(text, NULL);
715
716         gtk_sheet_get_active_cell(data_sheet, &row, &column);
717         if ( column < 0 ) column = 0;
718         if ( row < 0 ) row = 0;
719         
720         gtk_sheet_set_active_cell(data_sheet, casenum, column);
721       }
722       break;
723     default:
724       break;
725     }
726
727   gtk_widget_hide(dialog);
728   gtk_entry_set_text(entry, "");
729 }
730
731
732
733 void
734 on_sort_cases_activate (GtkMenuItem     *menuitem,
735                         gpointer         user_data)
736 {
737   gint response;
738   PsppireDataStore *data_store ;
739
740   struct sort_criteria criteria;
741   static struct sort_cases_dialog *dialog ;
742
743   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
744
745   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
746
747   if ( NULL == dialog) 
748     dialog = sort_cases_dialog_create(xml);
749
750   response = sort_cases_dialog_run(dialog, the_dictionary, &criteria);
751
752   switch ( response) 
753     {
754     case GTK_RESPONSE_OK:
755       psppire_case_file_sort(data_store->case_file, &criteria);
756       break;
757     }
758 }
759
760
761 static void 
762 insert_case(void)
763 {
764   gint row, col;
765   PsppireDataStore *data_store ;
766   GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
767
768   data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
769
770   gtk_sheet_get_active_cell(data_sheet, &row, &col);
771
772   psppire_case_file_insert_case(data_store->case_file, row);
773 }
774
775 void
776 on_insert_case_clicked (GtkButton *button, gpointer user_data)      
777 {
778   insert_case();
779 }
780
781 void
782 on_insert_cases (GtkMenuItem *menuitem, gpointer user_data)
783 {
784   insert_case();
785 }
786
787
788 void
789 on_insert_variable (GtkMenuItem *menuitem, gpointer user_data)
790 {
791   gint row, col;
792   GtkSheet *var_sheet = GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
793
794   gtk_sheet_get_active_cell(var_sheet, &row, &col);
795
796   psppire_dict_insert_variable(the_dictionary, row, NULL);
797 }
798
799