[gnumeric] xlsx: initial export of sheet widgets.



commit 9e48bfff141f3a6aef0175a5c93ffff6606ef55f
Author: Morten Welinder <terra gnome org>
Date:   Fri Feb 6 22:11:59 2015 -0500

    xlsx: initial export of sheet widgets.

 NEWS                               |    1 +
 plugins/excel/ChangeLog            |    5 +
 plugins/excel/xlsx-write-drawing.c |  166 +++++++++++++++++++++++++++++------
 plugins/excel/xlsx-write.c         |   43 +++++++---
 4 files changed, 175 insertions(+), 40 deletions(-)
---
diff --git a/NEWS b/NEWS
index 211c0dd..da6256e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.12.21
 
 Morten:
        * Initial xlsx import of sheet widgets.
+       * Initial xlsx export of sheet widgets.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.20
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index 9a84d24..f3bf8fc 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,5 +1,10 @@
 2015-02-06  Morten Welinder  <terra gnome org>
 
+       * xlsx-write.c (xlsx_write_sheet): Handle sheet widgets.
+
+       * xlsx-write-drawing.c (xlsx_write_legacy_drawing_objects): First
+       cut at writing sheet widgets.
+
        * xlsx-read-drawing.c (xlsx_vml_client_data_start)
        (xlsx_vml_client_data_end): First attempt at reading scrollbars,
        radio buttons, checkboxes, buttons, and spin buttons.
diff --git a/plugins/excel/xlsx-write-drawing.c b/plugins/excel/xlsx-write-drawing.c
index 52ae7a5..ecef44b 100644
--- a/plugins/excel/xlsx-write-drawing.c
+++ b/plugins/excel/xlsx-write-drawing.c
@@ -949,16 +949,14 @@ xlsx_write_object_anchor (GsfXMLOut *xml, GnmCellPos const *pos, char const *ele
 }
 
 static char const *
-xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *objects)
+xlsx_write_drawing_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *objects)
 {
-       GSList *obj, *chart_id, *chart_ids = NULL;
-       char *name, *tmp;
-       char const *rId, *rId1;
+       GSList *obj, *rId_ptr, *rIds = NULL;
+       char *name;
+       char const *rId;
        int count = 1;
-       GsfOutput *drawing_part, *chart_part;
+       GsfOutput *drawing_part;
        GsfXMLOut *xml;
-       SheetObjectAnchor const *anchor;
-       double res_pts[4] = {0.,0.,0.,0.};
 
        if (NULL == state->drawing.dir)
                state->drawing.dir = (GsfOutfile *)gsf_outfile_new_child (state->xl_dir, "drawings", TRUE);
@@ -972,33 +970,53 @@ xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *object
        g_free (name);
 
        rId = gsf_outfile_open_pkg_relate (GSF_OUTFILE_OPEN_PKG (drawing_part),
-               GSF_OUTFILE_OPEN_PKG (sheet_part), ns_rel_draw);
+                                          GSF_OUTFILE_OPEN_PKG (sheet_part),
+                                          ns_rel_draw);
 
-       objects = sheet_objects_get (state->sheet, NULL, SHEET_OBJECT_GRAPH_TYPE);
        for (obj = objects ; obj != NULL ; obj = obj->next) {
-               char *name = g_strdup_printf ("chart%u.xml", ++state->chart.count);
-               chart_part = gsf_outfile_new_child_full (state->chart.dir, name, FALSE,
-                       "content-type", "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
-                       NULL);
-               g_free (name);
-               rId1 = gsf_outfile_open_pkg_relate (GSF_OUTFILE_OPEN_PKG (chart_part),
-                       GSF_OUTFILE_OPEN_PKG (drawing_part), ns_rel_chart);
+               SheetObject *so = obj->data;
+               const char *rId1;
+
+               if (IS_SHEET_OBJECT_GRAPH (so)) {
+                       char *name = g_strdup_printf ("chart%u.xml", ++state->chart.count);
+                       GsfOutput *chart_part = gsf_outfile_new_child_full
+                               (state->chart.dir, name, FALSE,
+                                "content-type",
+                                "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
+                                NULL);
+                       g_free (name);
+                       rId1 = gsf_outfile_open_pkg_relate (GSF_OUTFILE_OPEN_PKG (chart_part),
+                                                           GSF_OUTFILE_OPEN_PKG (drawing_part),
+                                                           ns_rel_chart);
 
-               chart_ids = g_slist_prepend (chart_ids, (gpointer)rId1);
+                       xlsx_write_chart (state, chart_part, so);
+                       gsf_output_close (chart_part);
+                       g_object_unref (chart_part);
+               } else {
+                       rId1 = NULL;
+               }
 
-               xlsx_write_chart (state, chart_part, obj->data);
-               gsf_output_close (chart_part);
-               g_object_unref (chart_part);
+               rIds = g_slist_prepend (rIds, (gpointer)rId1);
        }
+       rIds = g_slist_reverse (rIds);
 
        xml = gsf_xml_out_new (drawing_part);
        gsf_xml_out_start_element (xml, "xdr:wsDr");
        gsf_xml_out_add_cstr_unchecked (xml, "xmlns:xdr", ns_ss_drawing);
        gsf_xml_out_add_cstr_unchecked (xml, "xmlns:a", ns_drawing);
 
-       chart_id = g_slist_reverse (chart_ids);
-       for (obj = objects; obj != NULL ; obj = obj->next, chart_id = chart_id->next) {
-               anchor = sheet_object_get_anchor (obj->data);
+       for (obj = objects, rId_ptr = rIds;
+            obj != NULL ;
+            obj = obj->next, rId_ptr = rId_ptr->next) {
+               SheetObject *so = obj->data;
+               const char *rId1 = rId_ptr->data;
+               SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
+               double res_pts[4] = {0.,0.,0.,0.};
+               char *tmp;
+
+               if (!rId1)
+                       continue;
+
                sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
 
                gsf_xml_out_start_element (xml, "xdr:twoCellAnchor");
@@ -1014,10 +1032,9 @@ xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *object
 
                gsf_xml_out_start_element (xml, "xdr:cNvPr");
                gsf_xml_out_add_int (xml, "id",  count+1);
-               gsf_xml_out_add_cstr_unchecked (xml, "name",
-                       (tmp = g_strdup_printf ("Chart %d", count)));
+               tmp = g_strdup_printf ("Chart %d", count++);
+               gsf_xml_out_add_cstr_unchecked (xml, "name", tmp);
                g_free (tmp);
-               count++;
                gsf_xml_out_end_element (xml);
 
                gsf_xml_out_simple_element (xml, "xdr:cNvGraphicFramePr", NULL);
@@ -1044,7 +1061,7 @@ xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *object
                gsf_xml_out_add_cstr_unchecked (xml, "xmlns:c", ns_chart);
                gsf_xml_out_add_cstr_unchecked (xml, "xmlns:r", ns_rel);
 
-               gsf_xml_out_add_cstr_unchecked (xml, "r:id", chart_id->data);
+               gsf_xml_out_add_cstr_unchecked (xml, "r:id", rId1);
                gsf_xml_out_end_element (xml); /* </c:chart> */
                gsf_xml_out_end_element (xml); /* </a:graphicData> */
                gsf_xml_out_end_element (xml); /* </a:graphic> */
@@ -1052,8 +1069,7 @@ xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *object
                gsf_xml_out_simple_element (xml, "xdr:clientData", NULL);
                gsf_xml_out_end_element (xml); /* </xdr:twoCellAnchor> */
        }
-       g_slist_free (objects);
-       g_slist_free (chart_ids);
+       g_slist_free (rIds);
 
        gsf_xml_out_end_element (xml); /* </wsDr> */
        g_object_unref (xml);
@@ -1062,3 +1078,95 @@ xlsx_write_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *object
 
        return rId;
 }
+
+static char const *
+xlsx_write_legacy_drawing_objects (XLSXWriteState *state, GsfOutput *sheet_part, GSList *objects)
+{
+       GSList *obj;
+       char *name;
+       char const *rId;
+       GsfOutput *drawing_part;
+       GsfXMLOut *xml;
+       GnmParsePos pp0;
+
+       parse_pos_init_sheet (&pp0, state->sheet);
+
+       /* Note: we use drawing.dir here.  */
+       if (NULL == state->drawing.dir)
+               state->drawing.dir = (GsfOutfile *)gsf_outfile_new_child (state->xl_dir, "drawings", TRUE);
+
+       name = g_strdup_printf ("vmlDrawing%u.vml", ++state->legacy_drawing.count);
+       drawing_part = gsf_outfile_new_child_full (state->drawing.dir, name, FALSE, NULL);
+       g_free (name);
+
+       rId = gsf_outfile_open_pkg_relate (GSF_OUTFILE_OPEN_PKG (drawing_part),
+                                          GSF_OUTFILE_OPEN_PKG (sheet_part),
+                                          ns_rel_leg_draw);
+
+       xml = gsf_xml_out_new (drawing_part);
+       gsf_xml_out_start_element (xml, "xml");
+       gsf_xml_out_add_cstr_unchecked (xml, "xmlns:v", ns_vml);
+       gsf_xml_out_add_cstr_unchecked (xml, "xmlns:o", ns_leg_office);
+       gsf_xml_out_add_cstr_unchecked (xml, "xmlns:x", ns_leg_excel);
+
+       for (obj = objects ; obj != NULL ; obj = obj->next) {
+               SheetObject *so = obj->data;
+               const char *otype = NULL;
+               GnmExprTop const *tlink = NULL;
+               double res_pts[4] = {0.,0.,0.,0.};
+               GtkAdjustment *adj = NULL;
+               sheet_object_position_pts_get (so, res_pts);
+
+               gsf_xml_out_start_element (xml, "v:shape");
+               {
+                       GString *str = g_string_new (NULL);
+                       g_string_append (str, "position:absolute;");
+                       g_string_append_printf (str, "margin-left:%.2fpt;", res_pts[0]);
+                       g_string_append_printf (str, "margin-top:%.2fpt;", res_pts[1]);
+                       g_string_append_printf (str, "width:%.2fpt;", res_pts[2] - res_pts[0]);
+                       g_string_append_printf (str, "height:%.2fpt;", res_pts[3] - res_pts[1]);
+                       gsf_xml_out_add_cstr (xml, "style", str->str);
+                       g_string_free (str, TRUE);
+               }
+
+               gsf_xml_out_start_element (xml, "x:ClientData");
+               if (GNM_IS_SOW_SCROLLBAR (so)) {
+                       otype = "Scroll";
+                       tlink = sheet_widget_adjustment_get_link (so);
+                       adj = sheet_widget_adjustment_get_adjustment (so);
+               }
+               gsf_xml_out_add_cstr_unchecked (xml, "ObjectType", otype);
+               gsf_xml_out_start_element (xml, "x:Anchor");
+               gsf_xml_out_end_element (xml);  /* </x:Anchor> */
+               if (tlink) {
+                       char *s = gnm_expr_top_as_string (tlink, &pp0, state->convs);
+                       gsf_xml_out_start_element (xml, "x:FmlaLink");
+                       gsf_xml_out_add_cstr (xml, NULL, s);
+                       gsf_xml_out_end_element (xml);  /* </x:FmlaLink> */
+                       g_free (s);
+                       gnm_expr_top_unref (tlink);
+               }
+               if (adj) {
+                       gsf_xml_out_simple_float_element (xml, "x:Val",
+                                                         gtk_adjustment_get_value (adj), -1);
+                       gsf_xml_out_simple_float_element (xml, "x:Min",
+                                                         gtk_adjustment_get_lower (adj), -1);
+                       gsf_xml_out_simple_float_element (xml, "x:Max",
+                                                         gtk_adjustment_get_upper (adj), -1);
+                       gsf_xml_out_simple_float_element (xml, "x:Inc",
+                                                         gtk_adjustment_get_step_increment (adj), -1);
+                       gsf_xml_out_simple_float_element (xml, "x:Page",
+                                                         gtk_adjustment_get_page_increment (adj), -1);
+               }
+               gsf_xml_out_end_element (xml);  /* </x:ClientData> */
+
+               gsf_xml_out_end_element (xml);  /* </v:shape> */
+       }
+
+       gsf_xml_out_end_element (xml);  /* </xml> */
+       g_object_unref (xml);
+       gsf_output_close (drawing_part);
+       g_object_unref (drawing_part);
+
+       return rId;
+}
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index be56468..4e87b8c 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -52,6 +52,7 @@
 #include "sheet-object.h"
 #include "sheet-object-cell-comment.h"
 #include "sheet-object-graph.h"
+#include "sheet-object-widget.h"
 #include "graph.h"
 #include "style-border.h"
 #include "style-conditions.h"
@@ -93,9 +94,14 @@ static char const *ns_docprops_extended_vt   = "http://schemas.openxmlformats.or
 static char const *ns_docprops_custom        = 
"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";;
 static char const *ns_drawing   = "http://schemas.openxmlformats.org/drawingml/2006/main";;
 static char const *ns_chart     = "http://schemas.openxmlformats.org/drawingml/2006/chart";;
+static char const *ns_vml       = "urn:schemas-microsoft-com:vml";
+static char const *ns_leg_office = "urn:schemas-microsoft-com:office:office";
+static char const *ns_leg_excel         = "urn:schemas-microsoft-com:office:excel";
+
 static char const *ns_rel       = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";;
 static char const *ns_rel_hlink         = 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";;
 static char const *ns_rel_draw  = 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";;
+static char const *ns_rel_leg_draw = 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";;
 static char const *ns_rel_chart         = 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";;
 static char const *ns_rel_com   = 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";;
 
@@ -119,7 +125,7 @@ typedef struct {
        struct {
                unsigned int    count;
                GsfOutfile      *dir;
-       } chart, drawing, pivotCache, pivotTable;
+       } chart, drawing, legacy_drawing, pivotCache, pivotTable;
        unsigned comment;
        GOFormat *date_fmt;
 
@@ -2683,8 +2689,9 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";);
        GsfXMLOut *xml;
        GnmRange  extent, cell_extent;
-       GSList   *charts, *comments, *others, *objects, *p;
+       GSList   *drawing_objs, *legacy_drawing_objs, *comments, *others, *objects, *p;
        char const *chart_drawing_rel_id = NULL;
+       char const *legacy_drawing_rel_id = NULL;
        GnmStyle **col_styles;
        PrintInformation *pi = NULL;
 
@@ -2696,13 +2703,15 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
        extent = range_union (&extent, &cell_extent);
 
        objects = sheet_objects_get (state->sheet, NULL, G_TYPE_NONE);
-       charts = comments = others = NULL;
+       drawing_objs = legacy_drawing_objs = comments = others = NULL;
        for (p = objects; p; p = p->next) {
                SheetObject *so = p->data;
                if (IS_CELL_COMMENT (so))
                        comments = g_slist_prepend (comments, so);
                else if (IS_SHEET_OBJECT_GRAPH (so))
-                       charts = g_slist_prepend (charts, so);
+                       drawing_objs = g_slist_prepend (drawing_objs, so);
+               else if (GNM_IS_SOW_SCROLLBAR (so))
+                       legacy_drawing_objs = g_slist_prepend (legacy_drawing_objs, so);
                else if (IS_GNM_FILTER_COMBO (so))
                        ; /* Nothing here */
                else
@@ -2710,16 +2719,22 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
        }
        g_slist_free (objects);
 
-       comments = g_slist_reverse (comments);
        if (comments) {
+               comments = g_slist_reverse (comments);
                xlsx_write_comments (state, sheet_part, comments);
                g_slist_free (comments);
        }
 
-       charts = g_slist_reverse (charts);
-       if (charts) {
-               chart_drawing_rel_id = xlsx_write_objects (state, sheet_part, charts);
-               g_slist_free (charts);
+       if (drawing_objs) {
+               drawing_objs = g_slist_reverse (drawing_objs);
+               chart_drawing_rel_id = xlsx_write_drawing_objects (state, sheet_part, drawing_objs);
+               g_slist_free (drawing_objs);
+       }
+
+       if (legacy_drawing_objs) {
+               legacy_drawing_objs = g_slist_reverse (legacy_drawing_objs);
+               legacy_drawing_rel_id = xlsx_write_legacy_drawing_objects (state, sheet_part, 
legacy_drawing_objs);
+               g_slist_free (legacy_drawing_objs);
        }
 
        for (p = others; p; p = p->next) {
@@ -2817,6 +2832,11 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
                gsf_xml_out_end_element (xml);  /* </drawing> */
        }
 /*   element legacyDrawing { CT_LegacyDrawing }?,  Deleted in edition 2   */
+       if (NULL != legacy_drawing_rel_id) {
+               gsf_xml_out_start_element (xml, "legacyDrawing");
+               gsf_xml_out_add_cstr_unchecked (xml, "r:id", legacy_drawing_rel_id);
+               gsf_xml_out_end_element (xml);  /* </legacyDrawing> */
+       }
 /*   element legacyDrawingHF { CT_LegacyDrawing }?,  Deleted in edition 2   */
 /*   element picture { CT_SheetBackgroundPicture }?,     */
 /*   element oleObjects { CT_OleObjects }?,     */
@@ -2951,8 +2971,8 @@ xlsx_write_workbook (XLSXWriteState *state, GsfOutfile *root_part)
        gnm_style_unref (style);
 
        state->convs     = xlsx_conventions_new (TRUE);
-       state->chart.dir   = state->drawing.dir   = NULL;
-       state->chart.count = state->drawing.count = 0;
+       state->chart.dir   = state->drawing.dir   = state->legacy_drawing.dir = NULL;
+       state->chart.count = state->drawing.count = state->legacy_drawing.count = 0;
 
        g_ptr_array_set_size (sheetIds, workbook_sheet_count (state->base.wb));
        for (i = 0 ; i < workbook_sheet_count (state->base.wb); i++)
@@ -3049,6 +3069,7 @@ xlsx_write_workbook (XLSXWriteState *state, GsfOutfile *root_part)
                gsf_output_close (GSF_OUTPUT (state->chart.dir));
        if (NULL != state->drawing.dir)
                gsf_output_close (GSF_OUTPUT (state->drawing.dir));
+       /* legacy_drawing.dir is unused */
        gsf_output_close (GSF_OUTPUT (wb_part));
        g_ptr_array_free (sheetIds, TRUE);
        gsf_output_close (GSF_OUTPUT (sheet_dir));


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