2 PSPPIRE --- A Graphical User Interface for PSPP
3 Copyright (C) 2004, 2005 Free Software Foundation
4 Written by John Darrington
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.
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.
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
24 #define _(msgid) gettext (msgid)
25 #define N_(msgid) msgid
28 #include <data/casefile.h>
29 #include <data/file-handle-def.h>
30 #include <data/sys-file-reader.h>
31 #include <data/case.h>
33 #include <glade/glade.h>
36 #include <gtksheet/gtksheet.h>
38 #include "menu-actions.h"
39 #include "psppire-variable.h"
40 #include "psppire-dict.h"
42 #include "var-sheet.h"
43 #include "data-sheet.h"
45 #include "psppire-var-store.h"
46 #include "psppire-data-store.h"
53 extern PsppireDict *the_dictionary ;
55 static struct file_handle *psppire_handle = 0;
57 static const gchar handle_name[] = "psppire_handle";
59 static const gchar untitled[] = N_("Untitled");
61 static const gchar window_title[] = N_("PSPP Data Editor");
64 /* Sets the title bar to TEXT */
66 psppire_set_window_title(const gchar *text)
68 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
70 gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title));
72 gtk_window_set_title(GTK_WINDOW(data_editor), title);
77 /* Clear the active file and set the data and var sheets to
83 PsppireDataStore *data_store ;
84 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
85 GtkSheet *var_sheet = GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
87 gtk_sheet_set_active_cell(data_sheet, -1, -1);
88 gtk_sheet_set_active_cell(var_sheet, 0, 0);
90 if ( GTK_WIDGET_REALIZED(GTK_WIDGET(data_sheet)))
91 gtk_sheet_unselect_range(data_sheet);
93 if ( GTK_WIDGET_REALIZED(GTK_WIDGET(var_sheet)))
94 gtk_sheet_unselect_range(var_sheet);
96 gtk_sheet_moveto(data_sheet, 0, 0, 0.0, 0.0);
97 gtk_sheet_moveto(var_sheet, 0, 0, 0.0, 0.0);
99 data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
101 psppire_data_store_clear(data_store);
103 psppire_set_window_title(gettext(untitled));
106 fh_free(psppire_handle);
113 on_new1_activate (GtkMenuItem *menuitem,
121 /* Load a system file.
122 Return TRUE if successfull
125 load_system_file(const gchar *file_name)
129 PsppireVarStore *var_store ;
130 PsppireDataStore *data_store ;
131 struct dictionary *new_dict;
132 struct sfm_read_info ri;
133 struct sfm_reader *reader ;
135 GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
136 GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
138 g_assert(data_sheet);
144 fh_create_file (handle_name, file_name, fh_default_properties());
146 if ( !psppire_handle )
148 g_warning("Cannot read handle for reading system file \"%s\"\n",
153 reader = sfm_open_reader (psppire_handle, &new_dict, &ri);
158 /* FIXME: We need a better way of updating a dictionary than this */
159 the_dictionary = psppire_dict_new_from_dict(new_dict);
162 PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet)));
164 psppire_var_store_set_dictionary(var_store, the_dictionary);
168 PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet)));
170 psppire_data_store_set_dictionary(data_store,
173 psppire_set_window_title(basename(file_name));
175 var_cnt = dict_get_next_value_idx(the_dictionary->dict);
183 case_create(&c, var_cnt);
184 if ( 0 == sfm_read_case (reader, &c) )
190 if ( !psppire_case_file_append_case(data_store->case_file, &c) )
192 g_warning("Cannot write case to casefile\n");
200 sfm_close_reader(reader);
202 psppire_case_file_get_case_count(data_store->case_file);
209 on_open1_activate (GtkMenuItem *menuitem,
212 bool finished = FALSE;
215 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
216 GtkFileFilter *filter ;
218 dialog = gtk_file_chooser_dialog_new (_("Open"),
219 GTK_WINDOW(data_editor),
220 GTK_FILE_CHOOSER_ACTION_OPEN,
221 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
222 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
225 filter = gtk_file_filter_new();
226 gtk_file_filter_set_name(filter, _("System Files (*.sav)"));
227 gtk_file_filter_add_pattern(filter, "*.sav");
228 gtk_file_filter_add_pattern(filter, "*.SAV");
229 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
231 filter = gtk_file_filter_new();
232 gtk_file_filter_set_name(filter, _("Portable Files (*.por) "));
233 gtk_file_filter_add_pattern(filter, "*.por");
234 gtk_file_filter_add_pattern(filter, "*.POR");
235 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
237 filter = gtk_file_filter_new();
238 gtk_file_filter_set_name(filter, _("All Files"));
239 gtk_file_filter_add_pattern(filter, "*");
240 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
244 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
247 gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
249 finished = load_system_file(file_name) ;
256 } while ( ! finished ) ;
258 gtk_widget_destroy (dialog);
262 /* Re initialise HANDLE, by interrogating the user for a new file name */
264 recreate_save_handle(struct file_handle **handle)
268 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
270 dialog = gtk_file_chooser_dialog_new (_("Save Data As"),
271 GTK_WINDOW(data_editor),
272 GTK_FILE_CHOOSER_ACTION_SAVE,
273 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
274 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
277 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
279 char *file_name = gtk_file_chooser_get_filename
280 (GTK_FILE_CHOOSER (dialog));
284 destroy_file_handle(*handle, 0);
286 *handle = fh_create_file (handle_name, file_name, fh_default_properties());
288 psppire_set_window_title(basename(file_name));
293 gtk_widget_destroy (dialog);
297 on_save1_activate (GtkMenuItem *menuitem,
300 GtkSheet *data_sheet ;
301 PsppireDataStore *data_store ;
303 if ( ! psppire_handle )
304 recreate_save_handle(&psppire_handle);
306 data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
307 data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
309 if ( psppire_handle )
310 psppire_data_store_create_system_file(data_store,
316 on_save_as1_activate (GtkMenuItem *menuitem,
319 GtkSheet *data_sheet ;
320 PsppireDataStore *data_store ;
322 recreate_save_handle(&psppire_handle);
323 if ( ! psppire_handle )
326 data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
327 data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
329 if ( psppire_handle )
330 psppire_data_store_create_system_file(data_store,
336 on_quit1_activate (GtkMenuItem *menuitem,
344 on_cut1_activate (GtkMenuItem *menuitem,
352 on_copy1_activate (GtkMenuItem *menuitem,
360 on_paste1_activate (GtkMenuItem *menuitem,
366 /* Fill a case with SYSMIS for numeric and whitespace for string
367 variables respectively */
369 blank_case(struct ccase *cc, gpointer _dict)
372 PsppireDict *dict = _dict;
374 for(i = 0 ; i < psppire_dict_get_var_cnt(dict); ++i )
378 const struct PsppireVariable *var = psppire_dict_get_variable(dict, i);
380 gint idx = psppire_variable_get_index(var);
382 val = case_data_rw(cc, idx) ;
384 if ( psppire_variable_get_type(var) == ALPHA )
385 memset(val->s, ' ', psppire_variable_get_width(var));
397 on_insert1_activate (GtkMenuItem *menuitem,
400 GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
403 page = gtk_notebook_get_current_page(notebook);
407 case PAGE_DATA_SHEET:
410 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
411 PsppireDataStore *data_store =
412 PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
414 psppire_case_array_insert_case(data_store->cases,
415 data_sheet->range.row0,
416 blank_case, the_dictionary);
422 GtkSheet *var_sheet =
423 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
425 PsppireVarStore *var_store =
426 PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
428 psppire_dict_insert_variable(var_store->dict, var_sheet->range.row0, 0);
435 on_delete1_activate (GtkMenuItem *menuitem,
439 GtkWidget *notebook = get_widget_assert(xml, "notebook1");
441 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
445 case PAGE_DATA_SHEET:
447 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
448 PsppireDataStore *data_store =
449 PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
451 psppire_case_array_delete_cases(data_store->cases,
452 data_sheet->range.row0,
453 1 + data_sheet->range.rowi
454 - data_sheet->range.row0 );
460 GtkSheet *var_sheet =
461 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
463 PsppireVarStore *var_store =
464 PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
466 psppire_dict_delete_variables(var_store->dict,
467 var_sheet->range.row0,
468 1 + var_sheet->range.rowi
469 - var_sheet->range.row0 );
477 on_about1_activate(GtkMenuItem *menuitem,
480 GtkWidget *about = get_widget_assert(xml, "aboutdialog1");
483 GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0);
485 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb);
487 gtk_widget_show(about);
489 gtk_window_set_transient_for(GTK_WINDOW(about),
490 GTK_WINDOW(get_widget_assert(xml, "data_editor")));
496 on_toolbars1_activate
497 (GtkMenuItem *menuitem,
505 on_value_labels1_activate(GtkCheckMenuItem *menuitem,
508 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
509 PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
511 psppire_data_store_show_labels(ds,
512 gtk_check_menu_item_get_active(menuitem));
516 on_status_bar1_activate(GtkCheckMenuItem *menuitem,
520 if ( gtk_check_menu_item_get_active(menuitem) )
521 gtk_widget_show(get_widget_assert(xml, "statusbar1"));
523 gtk_widget_hide(get_widget_assert(xml, "statusbar1"));
527 on_grid_lines1_activate(GtkCheckMenuItem *menuitem,
531 const bool grid_visible = gtk_check_menu_item_get_active(menuitem);
533 gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")),
536 gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "data_sheet")),
542 on_fonts1_activate(GtkMenuItem *menuitem,
545 static GtkWidget *dialog = 0 ;
547 dialog = gtk_font_selection_dialog_new(_("Font Selection"));
549 gtk_window_set_transient_for(GTK_WINDOW(dialog),
550 GTK_WINDOW(get_widget_assert(xml, "data_editor")));
553 if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) )
555 GtkSheet *data_sheet =
556 GTK_SHEET(get_widget_assert(xml, "data_sheet"));
558 GtkSheet *var_sheet =
559 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
561 PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
562 PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
564 const gchar *font = gtk_font_selection_dialog_get_font_name
565 (GTK_FONT_SELECTION_DIALOG(dialog));
567 PangoFontDescription* font_desc =
568 pango_font_description_from_string(font);
570 psppire_var_store_set_font(vs, font_desc);
571 psppire_data_store_set_font(ds, font_desc);
574 gtk_widget_hide(dialog);
579 static GtkWidget *menuitems[2];
580 static GtkNotebook *notebook = 0;
583 switch_menus(gint page)
588 gtk_widget_hide(menuitems[PAGE_VAR_SHEET]);
589 gtk_widget_show(menuitems[PAGE_DATA_SHEET]);
591 case PAGE_DATA_SHEET:
592 gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
593 gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
596 g_assert_not_reached();
603 select_sheet(gint page)
605 gtk_notebook_set_current_page(notebook, page);
612 data_var_select(GtkNotebook *notebook,
613 GtkNotebookPage *page,
617 switch_menus(page_num);
621 /* Initialised things on the variable sheet */
623 var_data_selection_init(void)
625 notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
626 menuitems[PAGE_DATA_SHEET] = get_widget_assert(xml, "data1");
627 menuitems[PAGE_VAR_SHEET] = get_widget_assert(xml, "variables1");
629 gtk_notebook_set_current_page(notebook, PAGE_DATA_SHEET);
630 gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
631 gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
634 g_signal_connect(G_OBJECT(notebook), "switch-page",
635 G_CALLBACK(data_var_select), 0);
641 on_data1_activate(GtkMenuItem *menuitem,
644 select_sheet(PAGE_DATA_SHEET);
649 on_variables1_activate(GtkMenuItem *menuitem,
652 select_sheet(PAGE_VAR_SHEET);