Made a start at canonicalising the interface
authorJohn Darrington <john@darrington.wattle.id.au>
Sun, 13 Jan 2013 09:27:28 +0000 (10:27 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 16 Feb 2013 14:03:04 +0000 (15:03 +0100)
src/data/gnumeric-reader.c
src/data/gnumeric-reader.h
src/data/ods-reader.c
src/data/spreadsheet-reader.c
src/data/spreadsheet-reader.h
src/ui/gui/page-assistant.c
src/ui/gui/page-file.c
src/ui/gui/page-sheet-spec.c
src/ui/gui/text-data-import-dialog.h
src/ui/gui/text-data-import.ui

index 6cc7b3e1c254c0d920a93f2a1e1275b95a3b20d4..cfdd45424d455481ecbd671777b7c4ef28eca8f9 100644 (file)
@@ -75,7 +75,9 @@ static const struct casereader_class gnm_file_casereader_class =
 
 enum reader_state
   {
-    STATE_INIT = 0,        /* Initial state */
+    STATE_PRE_INIT = 0,        /* Initial state */
+    STATE_SHEET_COUNT,      /* Found the sheet index */
+    STATE_INIT ,           /* Other Initial state */
     STATE_SHEET_START,     /* Found the start of a sheet */
     STATE_SHEET_NAME,      /* Found the sheet name */
     STATE_MAXROW,
@@ -87,9 +89,15 @@ enum reader_state
 
 struct gnumeric_reader
 {
+  struct spreadsheet spreadsheet;
+
   xmlTextReaderPtr xtr;
 
   enum reader_state state;
+
+  /* The total number of sheets in the "workbook" */
+  int sheet_total ;
+
   int row;
   int col;
   int min_col;
@@ -144,6 +152,28 @@ process_node (struct gnumeric_reader *r)
 
   switch ( r->state)
     {
+    case STATE_PRE_INIT:
+      if (0 == xmlStrcasecmp (name, _xml("gnm:SheetNameIndex")) &&
+         XML_READER_TYPE_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_SHEET_COUNT;
+         r->sheet_total = 0;
+       }
+      break;
+
+    case STATE_SHEET_COUNT:
+      if (0 == xmlStrcasecmp (name, _xml("gnm:SheetName")) &&
+         XML_READER_TYPE_ELEMENT  == r->node_type)
+       {
+         r->sheet_total++;
+       }
+      else if (0 == xmlStrcasecmp (name, _xml("gnm:SheetNameIndex")) &&
+         XML_READER_TYPE_END_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_INIT;
+       }
+      break;
+
     case STATE_INIT:
       if (0 == xmlStrcasecmp (name, _xml("gnm:Sheet")) &&
          XML_READER_TYPE_ELEMENT  == r->node_type)
@@ -275,6 +305,58 @@ struct var_spec
   xmlChar *first_value;
 };
 
+struct spreadsheet *
+gnumeric_probe (const char *filename)
+{
+  int ret;
+  struct gnumeric_reader *r = NULL;
+  xmlTextReaderPtr xtr;
+
+  gzFile gz = gzopen (filename, "r");
+
+  if (NULL == gz)
+    return NULL;
+
+  xtr = xmlReaderForIO ((xmlInputReadCallback) gzread,
+                           (xmlInputCloseCallback) gzclose, gz,
+                          NULL, NULL, 0);
+
+  if (xtr == NULL)
+    return NULL;
+
+  r = xzalloc (sizeof *r);
+  
+  r->xtr = xtr;
+  r->sheet_total = -1;
+  r->state = STATE_PRE_INIT;
+
+
+  /* Advance to the start of the workbook.
+     This gives us some confidence that we are actually dealing with a gnumeric
+     spreadsheet.
+   */
+  while ( (r->state != STATE_INIT )
+         && 1 == (ret = xmlTextReaderRead (r->xtr)))
+    {
+      process_node (r);
+    }
+
+  if (ret != 1)
+    {
+      /* Not a gnumeric spreadsheet */
+      free (r);
+      gzclose (gz);
+      return NULL;
+    }
+    
+  r->spreadsheet.type = SPREADSHEET_GNUMERIC;
+  r->spreadsheet.sheets = r->sheet_total;
+  r->spreadsheet.make_reader = NULL;
+  
+  
+  return &r->spreadsheet;
+}
+
 struct casereader *
 gnumeric_open_reader (const struct spreadsheet_read_info *gri, 
                      struct spreadsheet_read_options *opts,
@@ -287,27 +369,16 @@ gnumeric_open_reader (const struct spreadsheet_read_info *gri,
   struct var_spec *var_spec = NULL;
   int n_var_specs = 0;
 
+  struct spreadsheet * spreadsheet = NULL;
   struct gnumeric_reader *r = NULL;
 
-  gzFile gz = gzopen (gri->file_name, "r");
-
-  if ( NULL == gz)
-    {
-      msg (ME, _("Error opening `%s' for reading as a Gnumeric file: %s."),
-           gri->file_name, strerror (errno));
-
-      goto error;
-    }
-
-  r = xzalloc (sizeof *r);
+  spreadsheet = gnumeric_probe (gri->file_name);
 
-  r->xtr = xmlReaderForIO ((xmlInputReadCallback) gzread,
-                           (xmlInputCloseCallback) gzclose, gz,
-                          NULL, NULL, 0);
-
-  if ( r->xtr == NULL )
+  if (spreadsheet == NULL)
     goto error;
 
+  r = (struct gnumeric_reader *) (spreadsheet);
+
   if ( opts->cell_range )
     {
       if ( ! convert_cell_ref (opts->cell_range,
@@ -327,7 +398,7 @@ gnumeric_open_reader (const struct spreadsheet_read_info *gri,
       r->stop_row = -1;
     }
 
-  r->state = STATE_INIT;
+
   r->target_sheet = BAD_CAST opts->sheet_name;
   r->target_sheet_index = opts->sheet_index;
   r->row = r->col = -1;
index f1af5e56ee9bcb2b9738538b87694ef3dc8ae1ae..529670e35cfefed38db13d1edb7e1a0803693b33 100644 (file)
@@ -24,6 +24,9 @@ struct dictionary;
 struct spreadsheet_read_info;
 struct spreadsheet_read_options;
 
+
+struct spreadsheet *gnumeric_probe (const char *filename);
+
 struct casereader * gnumeric_open_reader (const struct spreadsheet_read_info *, 
                                          struct spreadsheet_read_options *,
                                          struct dictionary **);
index 097c245d179403380e755ceae9e6d66962921886..85d3bc7dc10b47133ffe943fb0e408b5f419bfb7 100644 (file)
@@ -88,6 +88,8 @@ enum reader_state
 
 struct ods_reader
 {
+  struct spreadsheet spreadsheet;
+
   xmlTextReaderPtr xtr;
 
   enum reader_state state;
index 11e8cf593ac44476664aab6ac2d8fef688121cf0..3572a03ce49bdac5e27fc320d3afa980dba89601 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+
+struct spreadsheet * 
+spreadsheet_open (const char *filename)
+{
+  struct spreadsheet *ss = NULL;
+
+  ss = gnumeric_probe (filename);
+  
+  return ss;
+}
+
+void 
+spreadsheet_close (struct spreadsheet *spreadsheet)
+{
+}
+
+
+
 /* Convert a string, which is an integer encoded in base26
    IE, A=0, B=1, ... Z=25 to the integer it represents.
    ... except that in this scheme, digits with an exponent
index 6ea0bde4a436403330186cba95c8adda6d24f6bb..d25aaf32f6a11c11760c20fd97ace5d64b820662 100644 (file)
@@ -52,5 +52,39 @@ bool convert_cell_ref (const char *ref,
 
 #define _xmlchar_to_int(X) (atoi(CHAR_CAST (const char *, X)))
 
+enum spreadsheet_type
+  {
+    SPREADSHEET_GNUMERIC,
+    SPREADSHEET_ODS
+  };
+
+struct spreadsheet
+{
+  enum spreadsheet_type type;
+
+  struct casereader * (*make_reader) (struct spreadsheet *);
+
+  /* The total number of sheets in the "workbook" */
+  int sheets;
+
+  /* The dictionary */
+  struct dictionary *dict;
+};
+
+/* 
+   Attempt to open the file called FILENAME as a spreadsheet.
+   It is not known a priori, what type of spreadsheet FILENAME is, or
+   even if it is a spreadsheet at all.
+   If it fails to open, then it will return NULL without any error or
+   warning messages.
+ */
+struct spreadsheet * spreadsheet_open (const char *filename);
+void spreadsheet_close (struct spreadsheet *);
+
+struct casereeader;
+struct casereader * spreadsheet_make_reader (struct spreadsheet *s);
+
+
+#define SPREADSHEET_CAST(X) ((struct spreadsheet *)(X))
 
 #endif
index 70c658d371e04c7957b9745de63f2a52b22964a0..9ef5782a30f003fd0a1a84c707f2b37471e40e73 100644 (file)
@@ -159,11 +159,17 @@ on_prepare (GtkAssistant *assistant, GtkWidget *page,
   else
     gtk_widget_grab_focus (assistant->forward);
 
+
+  /* Prepare .... */
   if (page == ia->separators.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);
+
 
+  
   gtk_widget_show (ia->asst.reset_button);
   if (page == ia->formats.page)
     gtk_widget_show (ia->asst.paste_button);
index a3aaf03749995da85ec84fd9f81d88cddaab57f5..ac751e8f97e7581a0846e470d4a8552329e050cd 100644 (file)
@@ -137,8 +137,7 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window)
 {
   enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
   struct file *file = &ia->file;
-  struct casereader *creader = NULL;
-  struct dictionary *dict = NULL;
+  struct sheet_spec_page *ssp = &ia->sheet_spec;
   struct spreadsheet_read_info sri;
   struct spreadsheet_read_options opts;
 
@@ -155,25 +154,34 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window)
   sri.read_names = true;
   sri.asw = -1;
 
-  if (!creader) 
-    {
-      creader = gnumeric_open_reader (&sri, &opts, &dict);
-      ia->file.type = FTYPE_GNUMERIC;
-    }
-       
-  if (!creader) 
+  ssp->spreadsheet = gnumeric_probe (sri.file_name);
+
+  if (ssp->spreadsheet)
     {
-      creader = ods_open_reader (&sri, &opts, &dict);
-      ia->file.type = FTYPE_ODS;
-    }
+      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);
+       }
     
-  if (creader && dict)
-    {
-      struct sheet_spec_page *ssp = &ia->sheet_spec;
-      ssp->dict = dict;
-      ssp->reader = creader;
+      {
+       struct sheet_spec_page *ssp = &ia->sheet_spec;
+       ssp->dict = dict;
+       ssp->reader = creader;
+       
+       update_assistant (ia);
+      }
 
-      update_assistant (ia);
     }
   else
     {
index 1c72e830e0e1ab7c51cc8715ab7ba9ef5630d423..8f8bb381cc2b75e76ed4098f2da90323b96fd8e4 100644 (file)
@@ -80,6 +80,22 @@ init_sheet_spec_page (struct import_assistant *ia)
 
 }
 
+/* Prepares IA's sheet_spec page. */
+void
+prepare_sheet_spec_page (struct import_assistant *ia)
+{
+  struct sheet_spec_page *p = &ia->sheet_spec;
+
+  GtkBuilder *builder = ia->asst.builder;
+  GtkWidget *sheet_entry = get_widget_assert (builder, "sheet-entry");
+
+  printf ("%s %d\n", __FUNCTION__, p->spreadsheet->sheets);
+
+  gtk_spin_button_set_digits (GTK_SPIN_BUTTON (sheet_entry), 0);
+  gtk_spin_button_set_range (GTK_SPIN_BUTTON (sheet_entry), 1, p->spreadsheet->sheets);
+}
+
+
 /* Resets IA's sheet_spec page to its initial state. */
 void
 reset_sheet_spec_page (struct import_assistant *ia)
@@ -109,16 +125,15 @@ post_sheet_spec_page (struct import_assistant *ia)
   GtkWidget *range_entry = get_widget_assert (builder, "cell-range-entry");
   GtkWidget *readnames_checkbox = get_widget_assert (builder, "readnames-checkbox");
 
-  gint num = atoi (gtk_entry_get_text (GTK_ENTRY (sheet_entry)));
+  gint num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (sheet_entry));
 
   const gchar *range = gtk_entry_get_text (GTK_ENTRY (range_entry));
 
-
   if ( num < 1 )
     num = 1;
   
   ssp->opts.sheet_name = NULL;
-  ssp->opts.cell_range = range;
+  ssp->opts.cell_range = NULL;
   ssp->opts.sheet_index = num;
 
   if ( convert_cell_ref (range, &col_start, &row_start, &col_stop, &row_stop))
index b465d04ddf9ec646b8f333cc622ba46833a661cc..55064574f1aa31a1c5f08fb6c17ef84529cc7164 100644 (file)
@@ -70,7 +70,8 @@ struct sheet_spec_page
     GtkWidget *page;
     struct casereader *reader;
     struct dictionary *dict;
-
+    struct spreadsheet *spreadsheet;
+    
     struct spreadsheet_read_info sri;
     struct spreadsheet_read_options opts;
   };
@@ -213,6 +214,7 @@ void init_intro_page (struct import_assistant *);
 void reset_intro_page (struct import_assistant *);
 
 void init_sheet_spec_page (struct import_assistant *);
+void prepare_sheet_spec_page (struct import_assistant *ia);
 void reset_sheet_spec_page (struct import_assistant *);
 void post_sheet_spec_page (struct import_assistant *ia);
 
index d05296a7d739eb1ec25b6a47ac58feaad143734e..62bdf94717121a5ef7412cd358bd0c465249d1bb 100644 (file)
@@ -666,6 +666,12 @@ The selected file contains N lines of text.  Only the first M of these will be s
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkAdjustment" id="adjustment3">
+    <property name="value">1</property>
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkWindow" id="Sheet">
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">12</property>
@@ -721,10 +727,11 @@ The selected file contains N lines of text.  Only the first M of these will be s
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkEntry" id="sheet-entry">
+                          <object class="GtkSpinButton" id="sheet-entry">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="invisible_char">&#x25CF;</property>
+                            <property name="adjustment">adjustment3</property>
                           </object>
                           <packing>
                             <property name="left_attach">1</property>