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/file-handle-def.h>
29 #include <data/sys-file-reader.h>
30 #include <data/case.h>
32 #include <glade/glade.h>
35 #include <gtksheet/gtksheet.h>
37 #include "menu-actions.h"
38 #include "psppire-variable.h"
39 #include "psppire-dict.h"
41 #include "var-sheet.h"
42 #include "data-sheet.h"
44 #include "psppire-var-store.h"
45 #include "psppire-data-store.h"
52 extern PsppireDict *the_dictionary ;
53 extern PsppireCaseArray *the_cases ;
56 static struct file_handle *psppire_handle = 0;
58 static const gchar handle_name[] = "psppire_handle";
60 static const gchar untitled[] = N_("Untitled");
62 static const gchar window_title[] = N_("PSPP Data Editor");
65 /* Sets the title bar to TEXT */
67 psppire_set_window_title(const gchar *text)
69 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
71 gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title));
73 gtk_window_set_title(GTK_WINDOW(data_editor), title);
82 GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
83 GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
85 gtk_sheet_set_active_cell(GTK_SHEET(data_sheet), -1, -1);
87 gtk_sheet_set_active_cell(GTK_SHEET(var_sheet), 0, 0);
89 psppire_dict_clear(the_dictionary);
90 psppire_case_array_clear(the_cases);
92 psppire_set_window_title(gettext(untitled));
95 fh_free(psppire_handle);
102 on_new1_activate (GtkMenuItem *menuitem,
111 populate_case_from_reader(struct ccase *c, gpointer aux)
113 struct sfm_reader *reader = aux;
115 return sfm_read_case(reader, c);
119 /* Load a system file.
120 Return TRUE if successfull
123 load_system_file(const gchar *file_name)
128 PsppireVarStore *var_store ;
129 PsppireDataStore *data_store ;
130 struct dictionary *new_dict;
131 struct sfm_read_info ri;
132 struct sfm_reader *reader ;
134 GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
135 GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet");
138 g_assert(data_sheet);
141 if ( psppire_handle )
142 fh_free(psppire_handle);
145 fh_create_file (handle_name, file_name, fh_default_properties());
147 if ( !psppire_handle )
149 g_warning("Cannot read handle for reading system file \"%s\"\n",
155 reader = sfm_open_reader (psppire_handle, &new_dict, &ri);
160 /* FIXME: We need a better way of updating a dictionary than this */
161 the_dictionary = psppire_dict_new_from_dict(new_dict);
164 PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet)));
166 psppire_var_store_set_dictionary(var_store, the_dictionary);
170 PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet)));
172 psppire_data_store_set_dictionary(data_store,
175 psppire_case_array_clear(data_store->cases);
178 psppire_set_window_title(basename(file_name));
180 ni = dict_get_next_value_idx(the_dictionary->dict);
184 for(case_num=0;;case_num++)
186 if (!psppire_case_array_append_case(the_cases,
187 populate_case_from_reader,
193 sfm_close_reader(reader);
200 on_open1_activate (GtkMenuItem *menuitem,
203 bool finished = FALSE;
206 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
207 GtkFileFilter *filter ;
209 dialog = gtk_file_chooser_dialog_new (_("Open"),
210 GTK_WINDOW(data_editor),
211 GTK_FILE_CHOOSER_ACTION_OPEN,
212 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
213 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
216 filter = gtk_file_filter_new();
217 gtk_file_filter_set_name(filter, _("System Files (*.sav)"));
218 gtk_file_filter_add_pattern(filter, "*.sav");
219 gtk_file_filter_add_pattern(filter, "*.SAV");
220 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
222 filter = gtk_file_filter_new();
223 gtk_file_filter_set_name(filter, _("Portable Files (*.por) "));
224 gtk_file_filter_add_pattern(filter, "*.por");
225 gtk_file_filter_add_pattern(filter, "*.POR");
226 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
228 filter = gtk_file_filter_new();
229 gtk_file_filter_set_name(filter, _("All Files"));
230 gtk_file_filter_add_pattern(filter, "*");
231 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
235 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
238 gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
240 finished = load_system_file(file_name) ;
247 } while ( ! finished ) ;
249 gtk_widget_destroy (dialog);
253 /* Re initialise HANDLE, by interrogating the user for a new file name */
255 recreate_save_handle(struct file_handle **handle)
259 GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
261 dialog = gtk_file_chooser_dialog_new (_("Save Data As"),
262 GTK_WINDOW(data_editor),
263 GTK_FILE_CHOOSER_ACTION_SAVE,
264 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
265 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
268 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
270 char *file_name = gtk_file_chooser_get_filename
271 (GTK_FILE_CHOOSER (dialog));
275 destroy_file_handle(*handle, 0);
277 *handle = fh_create_file (handle_name, file_name, fh_default_properties());
279 psppire_set_window_title(basename(file_name));
284 gtk_widget_destroy (dialog);
288 on_save1_activate (GtkMenuItem *menuitem,
291 GtkSheet *data_sheet ;
292 PsppireDataStore *data_store ;
294 if ( ! psppire_handle )
295 recreate_save_handle(&psppire_handle);
297 data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
298 data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
300 if ( psppire_handle )
301 psppire_data_store_create_system_file(data_store,
307 on_save_as1_activate (GtkMenuItem *menuitem,
310 GtkSheet *data_sheet ;
311 PsppireDataStore *data_store ;
313 recreate_save_handle(&psppire_handle);
314 if ( ! psppire_handle )
317 data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
318 data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
320 if ( psppire_handle )
321 psppire_data_store_create_system_file(data_store,
327 on_quit1_activate (GtkMenuItem *menuitem,
335 on_cut1_activate (GtkMenuItem *menuitem,
343 on_copy1_activate (GtkMenuItem *menuitem,
351 on_paste1_activate (GtkMenuItem *menuitem,
357 /* Fill a case with SYSMIS for numeric and whitespace for string
358 variables respectively */
360 blank_case(struct ccase *cc, gpointer _dict)
363 PsppireDict *dict = _dict;
365 for(i = 0 ; i < psppire_dict_get_var_cnt(dict); ++i )
369 const struct PsppireVariable *var = psppire_dict_get_variable(dict, i);
371 gint idx = psppire_variable_get_index(var);
373 val = case_data_rw(cc, idx) ;
375 if ( psppire_variable_get_type(var) == ALPHA )
376 memset(val->s, ' ', psppire_variable_get_width(var));
388 on_insert1_activate (GtkMenuItem *menuitem,
391 GtkNotebook *notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
394 page = gtk_notebook_get_current_page(notebook);
398 case PAGE_DATA_SHEET:
400 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
401 PsppireDataStore *data_store =
402 PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
404 psppire_case_array_insert_case(data_store->cases,
405 data_sheet->range.row0,
406 blank_case, the_dictionary);
411 GtkSheet *var_sheet =
412 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
414 PsppireVarStore *var_store =
415 PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
417 psppire_dict_insert_variable(var_store->dict, var_sheet->range.row0, 0);
424 on_delete1_activate (GtkMenuItem *menuitem,
428 GtkWidget *notebook = get_widget_assert(xml, "notebook1");
430 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
433 case PAGE_DATA_SHEET:
435 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
436 PsppireDataStore *data_store =
437 PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
439 psppire_case_array_delete_cases(data_store->cases,
440 data_sheet->range.row0,
441 1 + data_sheet->range.rowi
442 - data_sheet->range.row0 );
447 GtkSheet *var_sheet =
448 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
450 PsppireVarStore *var_store =
451 PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
453 psppire_dict_delete_variables(var_store->dict,
454 var_sheet->range.row0,
455 1 + var_sheet->range.rowi
456 - var_sheet->range.row0 );
464 on_about1_activate(GtkMenuItem *menuitem,
467 GtkWidget *about = get_widget_assert(xml, "aboutdialog1");
470 GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0);
472 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb);
474 gtk_widget_show(about);
476 gtk_window_set_transient_for(GTK_WINDOW(about),
477 GTK_WINDOW(get_widget_assert(xml, "data_editor")));
483 on_toolbars1_activate
484 (GtkMenuItem *menuitem,
492 on_value_labels1_activate(GtkCheckMenuItem *menuitem,
495 GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
496 PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
498 psppire_data_store_show_labels(ds,
499 gtk_check_menu_item_get_active(menuitem));
503 on_status_bar1_activate(GtkCheckMenuItem *menuitem,
507 if ( gtk_check_menu_item_get_active(menuitem) )
508 gtk_widget_show(get_widget_assert(xml, "statusbar1"));
510 gtk_widget_hide(get_widget_assert(xml, "statusbar1"));
514 on_grid_lines1_activate(GtkCheckMenuItem *menuitem,
518 const bool grid_visible = gtk_check_menu_item_get_active(menuitem);
520 gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")),
523 gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "data_sheet")),
529 on_fonts1_activate(GtkMenuItem *menuitem,
532 static GtkWidget *dialog = 0 ;
534 dialog = gtk_font_selection_dialog_new(_("Font Selection"));
536 gtk_window_set_transient_for(GTK_WINDOW(dialog),
537 GTK_WINDOW(get_widget_assert(xml, "data_editor")));
540 if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) )
542 GtkSheet *data_sheet =
543 GTK_SHEET(get_widget_assert(xml, "data_sheet"));
545 GtkSheet *var_sheet =
546 GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
548 PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet));
549 PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet));
551 const gchar *font = gtk_font_selection_dialog_get_font_name
552 (GTK_FONT_SELECTION_DIALOG(dialog));
554 PangoFontDescription* font_desc =
555 pango_font_description_from_string(font);
557 psppire_var_store_set_font(vs, font_desc);
558 psppire_data_store_set_font(ds, font_desc);
561 gtk_widget_hide(dialog);
566 static GtkWidget *menuitems[2];
567 static GtkNotebook *notebook = 0;
570 switch_menus(gint page)
575 gtk_widget_hide(menuitems[PAGE_VAR_SHEET]);
576 gtk_widget_show(menuitems[PAGE_DATA_SHEET]);
578 case PAGE_DATA_SHEET:
579 gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
580 gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
583 g_assert_not_reached();
590 select_sheet(gint page)
592 gtk_notebook_set_current_page(notebook, page);
599 data_var_select(GtkNotebook *notebook,
600 GtkNotebookPage *page,
604 switch_menus(page_num);
608 /* Initialised things on the variable sheet */
610 var_data_selection_init(void)
612 notebook = GTK_NOTEBOOK(get_widget_assert(xml, "notebook1"));
613 menuitems[PAGE_DATA_SHEET] = get_widget_assert(xml, "data1");
614 menuitems[PAGE_VAR_SHEET] = get_widget_assert(xml, "variables1");
616 gtk_notebook_set_current_page(notebook, PAGE_DATA_SHEET);
617 gtk_widget_hide(menuitems[PAGE_DATA_SHEET]);
618 gtk_widget_show(menuitems[PAGE_VAR_SHEET]);
621 g_signal_connect(G_OBJECT(notebook), "switch-page",
622 G_CALLBACK(data_var_select), 0);
628 on_data1_activate(GtkMenuItem *menuitem,
631 select_sheet(PAGE_DATA_SHEET);
636 on_variables1_activate(GtkMenuItem *menuitem,
639 select_sheet(PAGE_VAR_SHEET);