From: John Darrington Date: Sun, 13 Jan 2013 15:01:45 +0000 (+0100) Subject: Started polymorphism of ODS X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c210c96542db2a357cf1aa6b690ef2ea88a54b1;p=pspp Started polymorphism of ODS --- diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index 85d3bc7dc1..2ce4e7eb9b 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -336,55 +336,104 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, } -struct casereader * -ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts, - struct dictionary **dict) +/* Try to find out how many sheets there are in the "workbook" */ +static int +get_sheet_count (struct zip_reader *zreader) { - int ret = 0; - xmlChar *type = NULL; - unsigned long int vstart = 0; - casenumber n_cases = CASENUMBER_MAX; - int i; - struct var_spec *var_spec = NULL; - int n_var_specs = 0; + xmlTextReaderPtr mxtr; + struct zip_member *meta = NULL; + meta = zip_member_open (zreader, "meta.xml"); + + if ( meta == NULL) + return -1; + + mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, + (xmlInputCloseCallback) zip_member_finish, + meta, NULL, NULL, XML_PARSE_RECOVER); + + while (1 == xmlTextReaderRead (mxtr)) + { + xmlChar *name = xmlTextReaderName (mxtr); + if ( 0 == xmlStrcmp (name, _xml("meta:document-statistic"))) + { + xmlChar *attr = xmlTextReaderGetAttribute (mxtr, _xml ("meta:table-count")); + + if ( attr != NULL) + { + int s = _xmlchar_to_int (attr); + return s; + } + } + } + return -1; +} - struct ods_reader *r = xzalloc (sizeof *r); +struct spreadsheet *ods_probe (const char *filename) +{ + struct ods_reader *r; + struct string errs; + xmlTextReaderPtr xtr ; + int sheet_count; struct zip_member *content = NULL; - struct zip_reader *zreader ; - xmlChar *val_string = NULL; - r->read_names = gri->read_names; - ds_init_empty (&r->ods_errs); + struct zip_reader *zreader = NULL; - zreader = zip_reader_create (gri->file_name, &r->ods_errs); + ds_init_empty (&errs); - if ( NULL == zreader) - { - msg (ME, _("Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."), - gri->file_name, ds_cstr (&r->ods_errs)); + zreader = zip_reader_create (filename, &errs); - goto error; - } + if (zreader == NULL) + return NULL; content = zip_member_open (zreader, "content.xml"); - if ( NULL == content) - { - msg (ME, _("Could not extract OpenDocument spreadsheet from file `%s': %s."), - gri->file_name, ds_cstr (&r->ods_errs)); - goto error; - } + if ( content == NULL) + goto error; zip_member_ref (content); - r->xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, + sheet_count = get_sheet_count (zreader); + + xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, (xmlInputCloseCallback) zip_member_finish, content, NULL, NULL, XML_PARSE_RECOVER); - if ( r->xtr == NULL) - { - goto error; - } + if ( xtr == NULL) + goto error; + + r = xzalloc (sizeof *r); + r->xtr = xtr; + r->spreadsheet.type = SPREADSHEET_ODS; + r->spreadsheet.sheets = sheet_count; + + ds_destroy (&errs); + + return &r->spreadsheet; + + error: + zip_reader_destroy (zreader); + ds_destroy (&errs); + return NULL; +} + +struct casereader * +ods_make_reader (struct spreadsheet *spreadsheet, + const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts) +{ + intf ret = 0; + xmlChar *type = NULL; + unsigned long int vstart = 0; + casenumber n_cases = CASENUMBER_MAX; + int i; + struct var_spec *var_spec = NULL; + int n_var_specs = 0; + + struct ods_reader *r = (struct ods_reader *) spreadsheet; + xmlChar *val_string = NULL; + + assert (r); + r->read_names = gri->read_names; + ds_init_empty (&r->ods_errs); if ( opts->cell_range ) { @@ -517,7 +566,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea } /* Create the dictionary and populate it */ - *dict = r->dict = dict_create ( + r->spreadsheet.dict = r->dict = dict_create ( CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr))); for (i = 0 ; i < n_var_specs ; ++i ) @@ -564,7 +613,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea convert_xml_to_value (r->first_case, var, &var_spec[i].firstval); } - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -584,7 +633,7 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea error: - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -596,7 +645,8 @@ ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_rea free (var_spec); - dict_destroy (r->dict); + dict_destroy (r->spreadsheet.dict); + r->spreadsheet.dict = NULL; ods_file_casereader_destroy (NULL, r); @@ -623,7 +673,6 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_) return r->first_case; } - if ( r->state > STATE_INIT) { c = case_create (r->proto); diff --git a/src/data/ods-reader.h b/src/data/ods-reader.h index b26997cfc1..18eb65bc90 100644 --- a/src/data/ods-reader.h +++ b/src/data/ods-reader.h @@ -23,9 +23,11 @@ struct spreadsheet_read_info; struct spreadsheet_read_options; -struct casereader * ods_open_reader (const struct spreadsheet_read_info *, - struct spreadsheet_read_options *, - struct dictionary **); +struct spreadsheet *ods_probe (const char *filename); + +struct casereader * ods_make_reader (struct spreadsheet *spreadsheet, + const struct spreadsheet_read_info *gri, + struct spreadsheet_read_options *opts); #endif diff --git a/src/data/spreadsheet-reader.h b/src/data/spreadsheet-reader.h index 3fbbde1d21..77ed5ab9db 100644 --- a/src/data/spreadsheet-reader.h +++ b/src/data/spreadsheet-reader.h @@ -54,6 +54,7 @@ bool convert_cell_ref (const char *ref, enum spreadsheet_type { + SPREADSHEET_NONE, SPREADSHEET_GNUMERIC, SPREADSHEET_ODS }; diff --git a/src/language/data-io/get-data.c b/src/language/data-io/get-data.c index 723a16c8d1..cca86a2bd8 100644 --- a/src/language/data-io/get-data.c +++ b/src/language/data-io/get-data.c @@ -93,7 +93,9 @@ cmd_get_data (struct lexer *lexer, struct dataset *ds) } else if (0 == strncasecmp (tok, "ODS", 3)) { - reader = ods_open_reader (&sri, &opts, &dict); + struct spreadsheet *spreadsheet = ods_probe (sri.file_name); + reader = ods_make_reader (spreadsheet, &sri, &opts); + dict = spreadsheet->dict; } if (reader) diff --git a/src/ui/gui/page-assistant.c b/src/ui/gui/page-assistant.c index 9ef5782a30..0d43248bac 100644 --- a/src/ui/gui/page-assistant.c +++ b/src/ui/gui/page-assistant.c @@ -148,9 +148,11 @@ static void on_prepare (GtkAssistant *assistant, GtkWidget *page, struct import_assistant *ia) { + struct sheet_spec_page *ssp = &ia->sheet_spec; + int pn = gtk_assistant_get_current_page (assistant); - if (pn == 1 && ia->file.type != FTYPE_TEXT) + if (pn == 1 && ssp->spreadsheet) post_sheet_spec_page (ia); if (gtk_assistant_get_page_type (assistant, page) @@ -165,8 +167,10 @@ on_prepare (GtkAssistant *assistant, GtkWidget *page, prepare_separators_page (ia); else if (page == ia->formats.page) prepare_formats_page (ia); - else if (page == ia->sheet_spec.page) - prepare_sheet_spec_page (ia); + else if (page == ia->sheet_spec.page && ssp->spreadsheet) + { + prepare_sheet_spec_page (ia); + } diff --git a/src/ui/gui/page-file.c b/src/ui/gui/page-file.c index ac751e8f97..9ac69e8685 100644 --- a/src/ui/gui/page-file.c +++ b/src/ui/gui/page-file.c @@ -86,6 +86,7 @@ update_assistant (struct import_assistant *ia) struct ccase *c; int col; + sepp->column_cnt = dict_get_var_cnt (ssp->dict); sepp->columns = xcalloc (sepp->column_cnt, sizeof (*sepp->columns)); for (col = 0; col < sepp->column_cnt ; ++col) @@ -121,8 +122,6 @@ update_assistant (struct import_assistant *ia) } file->line_cnt = rows; - casereader_destroy (ssp->reader); - ssp->reader = NULL; } @@ -154,37 +153,25 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) sri.read_names = true; sri.asw = -1; - ssp->spreadsheet = gnumeric_probe (sri.file_name); + if (ssp->spreadsheet == NULL) + ssp->spreadsheet = gnumeric_probe (sri.file_name); + + printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type); + + if (ssp->spreadsheet == NULL) + ssp->spreadsheet = ods_probe (sri.file_name); + + printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type); if (ssp->spreadsheet) { - struct casereader *creader = NULL; - struct dictionary *dict = NULL; - - if (ssp->spreadsheet->type == SPREADSHEET_GNUMERIC) - { - ia->file.type = FTYPE_GNUMERIC; - } - else if (ssp->spreadsheet->type == SPREADSHEET_ODS) - { - ia->file.type = FTYPE_ODS; - } - else - { - assert (0); - } - - { - struct sheet_spec_page *ssp = &ia->sheet_spec; - ssp->dict = dict; - ssp->reader = creader; - - update_assistant (ia); - } - + + // update_assistant (ia); } else { + printf ("%s:%d %p\n", __FILE__, __LINE__, ssp->spreadsheet); + struct string input; struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY); if (reader == NULL) @@ -246,7 +233,6 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) } line_reader_close (reader); - ia->file.type = FTYPE_TEXT; } return true; diff --git a/src/ui/gui/page-sheet-spec.c b/src/ui/gui/page-sheet-spec.c index f87bce21f6..560a73dd43 100644 --- a/src/ui/gui/page-sheet-spec.c +++ b/src/ui/gui/page-sheet-spec.c @@ -145,12 +145,15 @@ post_sheet_spec_page (struct import_assistant *ia) ssp->sri.read_names = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (readnames_checkbox)); ssp->sri.asw = -1; - switch (ia->file.type) + switch (ssp->spreadsheet->type) { - case FTYPE_ODS: - creader = ods_open_reader (&ssp->sri, &ssp->opts, &dict); + case SPREADSHEET_ODS: + { + creader = ods_make_reader (ssp->spreadsheet, &ssp->sri, &ssp->opts); + dict = ssp->spreadsheet->dict; + } break; - case FTYPE_GNUMERIC: + case SPREADSHEET_GNUMERIC: { creader = gnumeric_make_reader (ssp->spreadsheet, &ssp->sri, &ssp->opts); dict = ssp->spreadsheet->dict; diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c index df6e5ec995..385af3e2bd 100644 --- a/src/ui/gui/text-data-import-dialog.c +++ b/src/ui/gui/text-data-import-dialog.c @@ -72,6 +72,7 @@ text_data_import_assistant (PsppireDataWindow *dw) { GtkWindow *parent_window = GTK_WINDOW (dw); struct import_assistant *ia; + struct sheet_spec_page *ssp ; ia = xzalloc (sizeof *ia); if (!init_file (ia, parent_window)) @@ -81,7 +82,8 @@ text_data_import_assistant (PsppireDataWindow *dw) } init_assistant (ia, parent_window); - if ( ia->file.type == FTYPE_TEXT) + ssp = &ia->sheet_spec; + if (ssp->spreadsheet == NULL) { init_intro_page (ia); init_first_line_page (ia); @@ -112,7 +114,7 @@ text_data_import_assistant (PsppireDataWindow *dw) break; } - if ( ia->file.type == FTYPE_TEXT) + if (ssp->spreadsheet == NULL) { destroy_formats_page (ia); destroy_separators_page (ia); @@ -211,111 +213,104 @@ apply_dict (const struct dictionary *dict, struct string *s) static char * generate_syntax (const struct import_assistant *ia) { + struct sheet_spec_page *ssp = &ia->sheet_spec; + struct string s = DS_EMPTY_INITIALIZER; - switch (ia->file.type) + if (ssp->spreadsheet == NULL) { - case FTYPE_TEXT: - { - size_t var_cnt; - size_t i; - syntax_gen_pspp (&s, - "GET DATA" - "\n /TYPE=TXT" - "\n /FILE=%sq\n", - ia->file.file_name); - if (ia->file.encoding && strcmp (ia->file.encoding, "Auto")) - syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ( - ia->intro.n_cases_button))) - ds_put_format (&s, " /IMPORTCASES=FIRST %d\n", - gtk_spin_button_get_value_as_int ( - GTK_SPIN_BUTTON (ia->intro.n_cases_spin))); - else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ( - ia->intro.percent_button))) - ds_put_format (&s, " /IMPORTCASES=PERCENT %d\n", - gtk_spin_button_get_value_as_int ( - GTK_SPIN_BUTTON (ia->intro.percent_spin))); - else - ds_put_cstr (&s, " /IMPORTCASES=ALL\n"); - ds_put_cstr (&s, - " /ARRANGEMENT=DELIMITED\n" - " /DELCASE=LINE\n"); - if (ia->first_line.skip_lines > 0) - ds_put_format (&s, " /FIRSTCASE=%d\n", ia->first_line.skip_lines + 1); - ds_put_cstr (&s, " /DELIMITERS=\""); - if (ds_find_byte (&ia->separators.separators, '\t') != SIZE_MAX) - ds_put_cstr (&s, "\\t"); - if (ds_find_byte (&ia->separators.separators, '\\') != SIZE_MAX) - ds_put_cstr (&s, "\\\\"); - for (i = 0; i < ds_length (&ia->separators.separators); i++) - { - char c = ds_at (&ia->separators.separators, i); - if (c == '"') - ds_put_cstr (&s, "\"\""); - else if (c != '\t' && c != '\\') - ds_put_byte (&s, c); - } - ds_put_cstr (&s, "\"\n"); - if (!ds_is_empty (&ia->separators.quotes)) - syntax_gen_pspp (&s, " /QUALIFIER=%sq\n", ds_cstr (&ia->separators.quotes)); - if (!ds_is_empty (&ia->separators.quotes) && ia->separators.escape) - ds_put_cstr (&s, " /ESCAPE\n"); - ds_put_cstr (&s, " /VARIABLES=\n"); - - var_cnt = dict_get_var_cnt (ia->formats.dict); - for (i = 0; i < var_cnt; i++) - { - struct variable *var = dict_get_var (ia->formats.dict, i); - char format_string[FMT_STRING_LEN_MAX + 1]; - fmt_to_string (var_get_print_format (var), format_string); - ds_put_format (&s, " %s %s%s\n", - var_get_name (var), format_string, - i == var_cnt - 1 ? "." : ""); - } - - apply_dict (ia->formats.dict, &s); - } - break; - case FTYPE_GNUMERIC: - case FTYPE_ODS: - { - const struct sheet_spec_page *ssp = &ia->sheet_spec; - - syntax_gen_pspp (&s, - "GET DATA" - "\n /TYPE=%ss" - "\n /FILE=%sq" - "\n /SHEET=index %d" - "\n /READNAMES=%ss", - (ia->file.type == FTYPE_GNUMERIC) ? "GNM" : "ODS", - ia->file.file_name, - ssp->opts.sheet_index, - ssp->sri.read_names ? "ON" : "OFF"); - - - if ( ssp->opts.cell_range) - { - syntax_gen_pspp (&s, - "\n /CELLRANGE=RANGE %sq", - ssp->opts.cell_range); - } - else - { - syntax_gen_pspp (&s, - "\n /CELLRANGE=FULL"); - } - - - syntax_gen_pspp (&s, "."); - - } - break; - - default: - g_assert_not_reached (); + size_t var_cnt; + size_t i; + syntax_gen_pspp (&s, + "GET DATA" + "\n /TYPE=TXT" + "\n /FILE=%sq\n", + ia->file.file_name); + if (ia->file.encoding && strcmp (ia->file.encoding, "Auto")) + syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ( + ia->intro.n_cases_button))) + ds_put_format (&s, " /IMPORTCASES=FIRST %d\n", + gtk_spin_button_get_value_as_int ( + GTK_SPIN_BUTTON (ia->intro.n_cases_spin))); + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ( + ia->intro.percent_button))) + ds_put_format (&s, " /IMPORTCASES=PERCENT %d\n", + gtk_spin_button_get_value_as_int ( + GTK_SPIN_BUTTON (ia->intro.percent_spin))); + else + ds_put_cstr (&s, " /IMPORTCASES=ALL\n"); + ds_put_cstr (&s, + " /ARRANGEMENT=DELIMITED\n" + " /DELCASE=LINE\n"); + if (ia->first_line.skip_lines > 0) + ds_put_format (&s, " /FIRSTCASE=%d\n", ia->first_line.skip_lines + 1); + ds_put_cstr (&s, " /DELIMITERS=\""); + if (ds_find_byte (&ia->separators.separators, '\t') != SIZE_MAX) + ds_put_cstr (&s, "\\t"); + if (ds_find_byte (&ia->separators.separators, '\\') != SIZE_MAX) + ds_put_cstr (&s, "\\\\"); + for (i = 0; i < ds_length (&ia->separators.separators); i++) + { + char c = ds_at (&ia->separators.separators, i); + if (c == '"') + ds_put_cstr (&s, "\"\""); + else if (c != '\t' && c != '\\') + ds_put_byte (&s, c); + } + ds_put_cstr (&s, "\"\n"); + if (!ds_is_empty (&ia->separators.quotes)) + syntax_gen_pspp (&s, " /QUALIFIER=%sq\n", ds_cstr (&ia->separators.quotes)); + if (!ds_is_empty (&ia->separators.quotes) && ia->separators.escape) + ds_put_cstr (&s, " /ESCAPE\n"); + ds_put_cstr (&s, " /VARIABLES=\n"); + + var_cnt = dict_get_var_cnt (ia->formats.dict); + for (i = 0; i < var_cnt; i++) + { + struct variable *var = dict_get_var (ia->formats.dict, i); + char format_string[FMT_STRING_LEN_MAX + 1]; + fmt_to_string (var_get_print_format (var), format_string); + ds_put_format (&s, " %s %s%s\n", + var_get_name (var), format_string, + i == var_cnt - 1 ? "." : ""); + } + + apply_dict (ia->formats.dict, &s); + } + else + { + const struct sheet_spec_page *ssp = &ia->sheet_spec; + + printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type); + + syntax_gen_pspp (&s, + "GET DATA" + "\n /TYPE=%ss" + "\n /FILE=%sq" + "\n /SHEET=index %d" + "\n /READNAMES=%ss", + (ssp->spreadsheet->type == SPREADSHEET_GNUMERIC) ? "GNM" : "ODS", + ia->file.file_name, + ssp->opts.sheet_index, + ssp->sri.read_names ? "ON" : "OFF"); + + + if ( ssp->opts.cell_range) + { + syntax_gen_pspp (&s, + "\n /CELLRANGE=RANGE %sq", + ssp->opts.cell_range); + } + else + { + syntax_gen_pspp (&s, + "\n /CELLRANGE=FULL"); + } + + + syntax_gen_pspp (&s, "."); } - return ds_cstr (&s); } diff --git a/src/ui/gui/text-data-import-dialog.h b/src/ui/gui/text-data-import-dialog.h index 55064574f1..561c0405bf 100644 --- a/src/ui/gui/text-data-import-dialog.h +++ b/src/ui/gui/text-data-import-dialog.h @@ -23,20 +23,11 @@ #include "libpspp/str.h" -enum file_type - { - FTYPE_TEXT, - FTYPE_GNUMERIC, - FTYPE_ODS - }; - /* The file to be imported. */ struct file { char *file_name; /* File name. */ - enum file_type type; - /* Relevant only for text files */ gchar *encoding; /* Encoding. */