[gnumeric] ssconvert: handle sheet selection in one place.



commit 22ac6f52955f5e3e42c4dd7e433c48f74fb92070
Author: Morten Welinder <terra gnome org>
Date:   Fri May 11 15:13:34 2018 -0400

    ssconvert: handle sheet selection in one place.
    
    This makes sheet selection (-O 'sheet=Sheet1 sheet=Sheet2') work in more
    contexts.

 NEWS             |    3 +-
 src/gutils.c     |   54 +++++++++++-
 src/gutils.h     |    6 ++
 src/print-info.c |   54 ++++--------
 src/ssconvert.c  |  261 +++++++++++++++++++++++++++++++++++------------------
 src/stf-export.c |   34 ++++----
 6 files changed, 266 insertions(+), 146 deletions(-)
---
diff --git a/NEWS b/NEWS
index b63b7b7..2b21967 100644
--- a/NEWS
+++ b/NEWS
@@ -5,8 +5,9 @@ Morten:
        * Introspection fixes.
        * Work around gtk+ breakage re. link colors.
        * Fix problems with ssconvert --export-file-per-sheet.  [#694408]
-       * Enable --export-file-per-sheet for html, latex, and pdf.
+       * Enable ssconvert --export-file-per-sheet for html, latex, and pdf.
        * Test suite improvements.
+       * ssconvert improvements.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.41
diff --git a/src/gutils.c b/src/gutils.c
index c17278f..2657a3e 100644
--- a/src/gutils.c
+++ b/src/gutils.c
@@ -34,6 +34,7 @@
 #include <gsf/gsf-timestamp.h>
 
 #define SHEET_SELECTION_KEY "sheet-selection"
+#define SSCONVERT_SHEET_SET_KEY "ssconvert-sheets"
 
 static char *gnumeric_lib_dir;
 static char *gnumeric_data_dir;
@@ -904,7 +905,7 @@ gnm_file_saver_get_sheets (GOFileSaver const *fs,
                           gboolean default_all)
 {
        Workbook *wb;
-       GPtrArray *sel;
+       GPtrArray *sel, *sheets;
 
        g_return_val_if_fail (GO_IS_FILE_SAVER (fs), NULL);
        g_return_val_if_fail (go_file_saver_get_save_scope (fs) ==
@@ -913,8 +914,11 @@ gnm_file_saver_get_sheets (GOFileSaver const *fs,
 
        wb = wb_view_get_workbook (wbv);
        sel = g_object_get_data (G_OBJECT (wb), SHEET_SELECTION_KEY);
+       sheets = g_object_get_data (G_OBJECT (wb), SSCONVERT_SHEET_SET_KEY);
        if (sel)
                g_ptr_array_ref (sel);
+       else if (sheets)
+               sel = g_ptr_array_ref (sheets);
        else if (default_all) {
                int i;
                sel = g_ptr_array_new ();
@@ -926,3 +930,51 @@ gnm_file_saver_get_sheets (GOFileSaver const *fs,
 
        return sel;
 }
+
+gboolean
+gnm_file_saver_common_export_option (GOFileSaver const *fs,
+                                    Workbook const *wb,
+                                    const char *key, const char *value,
+                                    GError **err)
+{
+       if (err)
+               *err = NULL;
+
+       g_return_val_if_fail (GO_IS_FILE_SAVER (fs), FALSE);
+       g_return_val_if_fail (GNM_IS_WORKBOOK (wb), FALSE);
+       g_return_val_if_fail (key != NULL, FALSE);
+       g_return_val_if_fail (value != NULL, FALSE);
+
+       if (strcmp (key, "sheet") == 0) {
+               GPtrArray *sheets;
+               Sheet *sheet = workbook_sheet_by_name (wb, value);
+
+               if (!sheet) {
+                       if (err)
+                               *err = g_error_new (go_error_invalid (), 0,
+                                                   _("Unknown sheet \"%s\""),
+                                                   value);
+                       return TRUE;
+               }
+
+               sheets = g_object_get_data (G_OBJECT (wb), SSCONVERT_SHEET_SET_KEY);
+               if (!sheets) {
+                       sheets = g_ptr_array_new ();
+                       g_object_set_data_full (G_OBJECT (wb),
+                                               SSCONVERT_SHEET_SET_KEY,
+                                               sheets,
+                                               (GDestroyNotify)g_ptr_array_unref);
+               }
+               g_ptr_array_add (sheets, sheet);
+
+               return FALSE;
+       }
+
+       if (err)
+               *err = g_error_new (go_error_invalid (), 0,
+                                   _("Invalid export option \"%s\" for format %s"),
+                                   key,
+                                   go_file_saver_get_id (fs));
+
+       return TRUE;
+}
diff --git a/src/gutils.h b/src/gutils.h
index 8940413..904911f 100644
--- a/src/gutils.h
+++ b/src/gutils.h
@@ -68,6 +68,12 @@ GPtrArray *gnm_file_saver_get_sheets (GOFileSaver const *fs,
                                      WorkbookView const *wbv,
                                      gboolean default_all);
 
+gboolean gnm_file_saver_common_export_option (GOFileSaver const *fs,
+                                             Workbook const *wb,
+                                             const char *key,
+                                             const char *value,
+                                             GError **err);
+
 G_END_DECLS
 
 #endif /* _GNM_GUTILS_H_ */
diff --git a/src/print-info.c b/src/print-info.c
index d143b25..54b3ac9 100644
--- a/src/print-info.c
+++ b/src/print-info.c
@@ -833,13 +833,7 @@ pdf_write_workbook (G_GNUC_UNUSED GOFileSaver const *fs,
                    WorkbookView const *wbv, GsfOutput *output)
 {
        Workbook const *wb = wb_view_get_workbook (wbv);
-       GPtrArray *sheets;
-
-       sheets = g_object_get_data (G_OBJECT (wb), "pdf-sheets");
-       if (sheets)
-               g_ptr_array_ref (sheets);
-       else
-               sheets = gnm_file_saver_get_sheets (fs, wbv, FALSE);
+       GPtrArray *sheets = gnm_file_saver_get_sheets (fs, wbv, FALSE);
 
        if (sheets) {
                int i;
@@ -885,33 +879,17 @@ pdf_export (GOFileSaver const *fs, GOIOContext *context,
                pdf_write_workbook (fs, context, wbv, output);
 }
 
+struct cb_set_pdf_option {
+       GOFileSaver *fs;
+       Workbook const *wb;
+};
+
 static gboolean
 cb_set_pdf_option (const char *key, const char *value,
-                  GError **err, gpointer user)
+                  GError **err, gpointer user_)
 {
-       Workbook *wb = user;
-
-       if (strcmp (key, "sheet") == 0) {
-               Sheet *sheet = workbook_sheet_by_name (wb, value);
-               GPtrArray *sheets;
-
-               if (!sheet) {
-                       *err = g_error_new (go_error_invalid (), 0,
-                                           _("There is no such sheet"));
-                       return TRUE;
-               }
-
-               sheets = g_object_get_data (G_OBJECT (wb), "pdf-sheets");
-               if (!sheets) {
-                       sheets = g_ptr_array_new ();
-                       g_object_set_data_full (G_OBJECT (wb),
-                                               "pdf-sheets", sheets,
-                                               (GDestroyNotify)g_ptr_array_unref);
-               }
-               g_ptr_array_add (sheets, sheet);
-
-               return FALSE;
-       }
+       struct cb_set_pdf_option *user = user_;
+       Workbook const *wb = user->wb;
 
        if (strcmp (key, "object") == 0) {
                GPtrArray *objects = g_object_get_data (G_OBJECT (wb), "pdf-objects");
@@ -965,21 +943,21 @@ cb_set_pdf_option (const char *key, const char *value,
                return FALSE;
        }
 
-       if (err)
-               *err = g_error_new (go_error_invalid (), 0,
-                                   _("Invalid option for pdf exporter"));
-
-       return TRUE;
+       return gnm_file_saver_common_export_option (user->fs, wb,
+                                                   key, value, err);
 }
 
 static gboolean
-pdf_set_export_options (G_GNUC_UNUSED GOFileSaver *fs,
+pdf_set_export_options (GOFileSaver *fs,
                        GODoc *doc,
                        const char *options,
                        GError **err,
                        G_GNUC_UNUSED gpointer user)
 {
-       return go_parse_key_value (options, err, cb_set_pdf_option, doc);
+       struct cb_set_pdf_option data;
+       data.fs = fs;
+       data.wb = WORKBOOK (doc);
+       return go_parse_key_value (options, err, cb_set_pdf_option, &data);
 }
 
 /**
diff --git a/src/ssconvert.c b/src/ssconvert.c
index 3d09cd8..41ec540 100644
--- a/src/ssconvert.c
+++ b/src/ssconvert.c
@@ -1,4 +1,3 @@
-/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * ssconvert.c: A wrapper application to convert spreadsheet formats
  *
@@ -40,8 +39,11 @@
 #include <sys/resource.h>
 #endif
 
+// Sheets that an exporter should export.
 #define SHEET_SELECTION_KEY "sheet-selection"
 
+// Sheets user has specified as export options
+#define SSCONVERT_SHEET_SET_KEY "ssconvert-sheets"
 
 static gboolean ssconvert_show_version = FALSE;
 static gboolean ssconvert_verbose = FALSE;
@@ -210,36 +212,109 @@ setup_range (GObject *obj, const char *key, Workbook *wb, const char *rtxt)
        return rrc;
 }
 
+struct cb_handle_export_options {
+       GOFileSaver *fs;
+       Workbook const *wb;
+};
+
+static gboolean
+cb_handle_export_options (const char *key, const char *value,
+                         GError **err, gpointer user_)
+{
+       struct cb_handle_export_options *user = user_;
+       return gnm_file_saver_common_export_option (user->fs, user->wb,
+                                                   key, value, err);
+}
+
 static int
-handle_export_options (GOFileSaver *fs, GODoc *doc)
+handle_export_options (GOFileSaver *fs, Workbook *wb)
 {
-       guint sig = g_signal_lookup ("set-export-options",
-                                    G_TYPE_FROM_INSTANCE (fs));
+       GError *err = NULL;
+       gboolean fail;
+       guint sig;
 
        if (!ssconvert_export_options)
                return 0;
 
+       sig = g_signal_lookup ("set-export-options", G_TYPE_FROM_INSTANCE (fs));
        if (g_signal_handler_find (fs, G_SIGNAL_MATCH_ID,
-                                  sig, 0, NULL, NULL, NULL)) {
-               GError *err = NULL;
-               gboolean fail =
-                       go_file_saver_set_export_options
-                       (fs, doc,
+                                  sig, 0, NULL, NULL, NULL))
+               fail = go_file_saver_set_export_options
+                       (fs, GO_DOC (wb),
                         ssconvert_export_options,
                         &err);
+       else {
+               struct cb_handle_export_options data;
+               data.fs = fs;
+               data.wb = wb;
+               fail = go_parse_key_value (ssconvert_export_options, &err,
+                                          cb_handle_export_options, &data);
+       }
+
+       if (fail) {
+               g_printerr ("ssconvert: %s\n", err
+                           ? err->message
+                           : _("Cannot parse export options."));
+               return 1;
+       }
+
+       return 0;
+}
+
+// Check that the sheet selection, if any, matches the file saver's
+// capabilities.
+static int
+validate_sheet_selection (GOFileSaver *fs, Workbook *wb)
+{
+       GOFileSaveScope fsscope = go_file_saver_get_save_scope (fs);
+       gboolean fs_sheet_selection;
+
+       g_object_get (G_OBJECT (fs),
+                     "sheet-selection", &fs_sheet_selection, NULL);
 
-               if (fail) {
-                       g_printerr ("ssconvert: %s\n", err
-                                   ? err->message
-                                   : _("Cannot parse export options."));
+       if (ssconvert_one_file_per_sheet) {
+               gboolean ok;
+               switch (fsscope) {
+               case GO_FILE_SAVE_WORKBOOK:
+                       ok = fs_sheet_selection;
+                       break;
+               case GO_FILE_SAVE_SHEET:
+                       ok = TRUE;
+                       break;
+               case GO_FILE_SAVE_RANGE:
+               default:
+                       ok = FALSE;
+                       break;
+               }
+               if (!ok) {
+                       g_printerr (_("Selected exporter (%s) does not have the ability to split a workbook 
into sheets.\n"),
+                                   go_file_saver_get_id (fs));
                        return 1;
                }
-
-               return 0;
        } else {
-               g_printerr (_("The file saver does not take options\n"));
-               return 1;
+               GPtrArray *sheets = g_object_get_data (G_OBJECT (wb),
+                                                      SSCONVERT_SHEET_SET_KEY);
+               switch (fsscope) {
+               case GO_FILE_SAVE_WORKBOOK:
+               case GO_FILE_SAVE_RANGE:
+               default:
+                       if (sheets && !fs_sheet_selection) {
+                               g_printerr (_("Selected exporter (%s) does not have the ability to export a 
subset of sheets.\n"),
+                                           go_file_saver_get_id (fs));
+                               return 1;
+                       }
+                       break;
+               case GO_FILE_SAVE_SHEET:
+                       if (sheets && sheets->len != 1) {
+                               g_printerr (_("Selected exporter (%s) can only export one sheet at a 
time.\n"),
+                                           go_file_saver_get_id (fs));
+                               return 1;
+                       }
+                       break;
+               }
        }
+
+       return 0;
 }
 
 
@@ -490,7 +565,7 @@ merge (Workbook *wb, char const *inputs[],
 }
 
 static char *
-resolve_template (const char *template, Sheet *sheet)
+resolve_template (const char *template, Sheet *sheet, unsigned n)
 {
        GString *s = g_string_new (NULL);
        while (1) {
@@ -507,7 +582,7 @@ resolve_template (const char *template, Sheet *sheet)
                        case 0:
                                goto done;
                        case 'n':
-                               g_string_append_printf (s, "%d", sheet->index_in_wb);
+                               g_string_append_printf (s, "%u", n);
                                break;
                        case 's':
                                g_string_append (s, sheet->name_unquoted);
@@ -683,6 +758,76 @@ run_tool_test (const char *tool, char **argv, WorkbookView *wbv)
 #undef RANGE_LISTARG
 #undef SHEET_ARG
 
+
+static int
+do_split_save (GOFileSaver *fs, WorkbookView *wbv,
+              const char *outarg, GOCmdContext *cc)
+{
+       Workbook *wb = wb_view_get_workbook (wbv);
+       char *template;
+       GPtrArray *sheets;
+       unsigned ui;
+       int res = 0;
+       GPtrArray *sheet_sel =
+               g_object_get_data (G_OBJECT (wb), SHEET_SELECTION_KEY);
+       gboolean fs_sheet_selection;
+
+       g_object_get (G_OBJECT (fs), "sheet-selection", &fs_sheet_selection, NULL);
+
+       template = strchr (outarg, '%')
+               ? g_strdup (outarg)
+               : g_strconcat (outarg, ".%n", NULL);
+
+       sheets = g_object_get_data (G_OBJECT (wb),
+                                   SSCONVERT_SHEET_SET_KEY);
+       if (sheets)
+               g_ptr_array_ref (sheets);
+       else {
+               int i;
+               sheets = g_ptr_array_new ();
+               for (i = 0; i < workbook_sheet_count (wb); i++) {
+                       Sheet *sheet = workbook_sheet_by_index (wb, i);
+                       g_ptr_array_add (sheets, sheet);
+               }
+       }
+
+       for (ui = 0; ui < sheets->len; ui++) {
+               Sheet *sheet = g_ptr_array_index (sheets, ui);
+               char *tmpfile = resolve_template (template, sheet, ui);
+               int oldn = sheet->index_in_wb;
+
+               g_ptr_array_set_size (sheet_sel, 0);
+               g_ptr_array_add (sheet_sel, sheet);
+
+               if (!fs_sheet_selection) {
+                       /*
+                        * HACK: (bug 694408).
+                        *
+                        * We don't have a good way of specifying the
+                        * sheet.  Move it to the front and select
+                        * it.  That will at least make cvs and txt
+                        * exporters reliably find it.
+                        */
+                       workbook_sheet_move (sheet, -oldn);
+                       wb_view_sheet_focus (wbv, sheet);
+               }
+
+               res = !workbook_view_save_as (wbv, fs, tmpfile, cc);
+
+               if (!fs_sheet_selection)
+                       workbook_sheet_move (sheet, +oldn);
+
+               g_free (tmpfile);
+               if (res)
+                       break;
+       }
+
+       g_free (template);
+       g_ptr_array_unref (sheets);
+
+       return res;
+}
+
 static int
 convert (char const *inarg, char const *outarg, char const *mergeargs[],
         GOCmdContext *cc)
@@ -696,7 +841,6 @@ convert (char const *inarg, char const *outarg, char const *mergeargs[],
        GOIOContext *io_context = NULL;
        Workbook *wb = NULL;
        GOFileSaveScope fsscope;
-       gboolean fs_sheet_selection;
        GPtrArray *sheet_sel = NULL;
        GnmRangeRef const *range = NULL;
 
@@ -756,35 +900,12 @@ convert (char const *inarg, char const *outarg, char const *mergeargs[],
        if (!fs)
                goto out;
        fsscope = go_file_saver_get_save_scope (fs);
-       g_object_get (G_OBJECT (fs), "sheet-selection", &fs_sheet_selection, NULL);
-
-       if (ssconvert_one_file_per_sheet) {
-               gboolean ok;
-               switch (fsscope) {
-               case GO_FILE_SAVE_WORKBOOK:
-                       ok = fs_sheet_selection;
-                       break;
-               case GO_FILE_SAVE_SHEET:
-                       ok = TRUE;
-                       break;
-               case GO_FILE_SAVE_RANGE:
-               default:
-                       ok = FALSE;
-                       break;
-               }
-               if (!ok) {
-                       g_printerr (_("Selected exporter (%s) does not have the ability to split a workbook 
into sheets.\n"),
-                                   go_file_saver_get_id (fs));
-                       res = 1;
-                       goto out;
-               }
-       }
 
        io_context = go_io_context_new (cc);
        if (mergeargs == NULL) {
                wbv = workbook_view_new_from_uri (infile, fo,
-                                           io_context,
-                                           ssconvert_import_encoding);
+                                                 io_context,
+                                                 ssconvert_import_encoding);
        } else {
                wbv = workbook_view_new (NULL);
        }
@@ -801,7 +922,11 @@ convert (char const *inarg, char const *outarg, char const *mergeargs[],
 
        wb = wb_view_get_workbook (wbv);
 
-       res = handle_export_options (fs, GO_DOC (wb));
+       res = handle_export_options (fs, wb);
+       if (res)
+               goto out;
+
+       res = validate_sheet_selection (fs, wb);
        if (res)
                goto out;
 
@@ -886,49 +1011,7 @@ convert (char const *inarg, char const *outarg, char const *mergeargs[],
        }
 
        if (ssconvert_one_file_per_sheet) {
-               GSList *ptr, *sheets;
-               char *template;
-
-               res = 0;
-
-               template = strchr (outarg, '%')
-                       ? g_strdup (outarg)
-                       : g_strconcat (outarg, ".%n", NULL);
-
-               sheets = workbook_sheets (wb);
-               for (ptr = sheets; ptr; ptr = ptr->next) {
-                       Sheet *sheet = ptr->data;
-                       char *tmpfile = resolve_template (template, sheet);
-                       int oldn = sheet->index_in_wb;
-
-                       g_ptr_array_set_size (sheet_sel, 0);
-                       g_ptr_array_add (sheet_sel, sheet);
-
-                       if (!fs_sheet_selection) {
-                               /*
-                                * HACK: (bug 694408).
-                                *
-                                * We don't have a good way of specifying the
-                                * sheet.  Move it to the front and select
-                                * it.  That will at least make cvs and txt
-                                * exporters reliably find it.
-                                */
-                               workbook_sheet_move (sheet, -oldn);
-                               wb_view_sheet_focus (wbv, sheet);
-                       }
-
-                       res = !workbook_view_save_as (wbv, fs, tmpfile, cc);
-
-                       if (!fs_sheet_selection)
-                               workbook_sheet_move (sheet, +oldn);
-
-                       g_free (tmpfile);
-                       if (res)
-                               break;
-               }
-
-               g_free (template);
-               g_slist_free (sheets);
+               res = do_split_save (fs, wbv, outarg, cc);
        } else {
                res = !workbook_view_save_as (wbv, fs, outfile, cc);
        }
diff --git a/src/stf-export.c b/src/stf-export.c
index a1166f4..0dceb93 100644
--- a/src/stf-export.c
+++ b/src/stf-export.c
@@ -685,6 +685,7 @@ gnm_stf_file_saver_save (G_GNUC_UNUSED GOFileSaver const *fs,
                for (ui = 0; ui < sel->len; ui++)
                        gnm_stf_export_options_sheet_list_add
                                (stfe, g_ptr_array_index (sel, ui));
+               g_ptr_array_unref (sel);
        }
 
        g_object_set (G_OBJECT (stfe), "sink", output, NULL);
@@ -701,26 +702,20 @@ gnm_stf_file_saver_save (G_GNUC_UNUSED GOFileSaver const *fs,
                gnm_stf_export_options_sheet_list_clear (stfe);
 }
 
+struct cb_set_export_option {
+       GOFileSaver *fs;
+       Workbook const *wb;
+};
+
 static gboolean
 cb_set_export_option (const char *key, const char *value,
-                     GError **err, gpointer user)
+                     GError **err, gpointer user_)
 {
-       Workbook *wb = user;
+       struct cb_set_export_option *user = user_;
+       Workbook const *wb = user->wb;
        GnmStfExport *stfe = gnm_stf_get_stfe (G_OBJECT (wb));
        const char *errtxt;
 
-       if (strcmp (key, "sheet") == 0) {
-               Sheet *sheet = workbook_sheet_by_name (wb, value);
-               if (!sheet) {
-                       errtxt = _("There is no such sheet");
-                       goto error;
-               }
-
-               gnm_stf_export_options_sheet_list_add (stfe, sheet);
-
-               return FALSE;
-       }
-
        if (strcmp (key, "eol") == 0) {
                const char *eol;
                if (g_ascii_strcasecmp ("unix", value) == 0)
@@ -752,7 +747,9 @@ cb_set_export_option (const char *key, const char *value,
                         err,
                         (_("Invalid value for option %s: \"%s\"")));
 
-       errtxt = _("Invalid option for stf exporter");
+       return gnm_file_saver_common_export_option (user->fs, wb,
+                                                   key, value, err);
+
 error:
        if (err)
                *err = g_error_new (go_error_invalid (), 0, "%s", errtxt);
@@ -761,15 +758,18 @@ error:
 }
 
 static gboolean
-gnm_stf_fs_set_export_options (G_GNUC_UNUSED GOFileSaver *fs,
+gnm_stf_fs_set_export_options (GOFileSaver *fs,
                               GODoc *doc,
                               const char *options,
                               GError **err,
                               G_GNUC_UNUSED gpointer user)
 {
        GnmStfExport *stfe = gnm_stf_get_stfe (G_OBJECT (doc));
+       struct cb_set_export_option data;
+       data.fs = fs;
+       data.wb = WORKBOOK (doc);
        gnm_stf_export_options_sheet_list_clear (stfe);
-       return go_parse_key_value (options, err, cb_set_export_option, doc);
+       return go_parse_key_value (options, err, cb_set_export_option, &data);
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]