[gnumeric] Add some sheet object support to ODF export.
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnumeric] Add some sheet object support to ODF export.
- Date: Fri, 10 Jul 2009 01:50:41 +0000 (UTC)
commit a327b4a2564c458e7e0a4c3fe58349a936c93e2f
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date: Thu Jul 9 19:49:36 2009 -0600
Add some sheet object support to ODF export.
2009-07-09 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-read.c (od_draw_frame): we can only match
once
(openoffice_file_open): g_free can handle NULL
* openoffice-write.c (odf_write_frame): new
(odf_write_objects): new
(odf_write_empty_cell): rather than calling
odf_write_comment, call odf_write_objects
(odf_write_covered_cell): change argument, and
change all callers
(odf_sheet_objects_get): new
(odf_write_content_rows): handle all sheet objects,
not just comments
(odf_write_content): hash graphs
(odf_write_graphs): new stub
(openoffice_file_save_real): initialize graph hash
and create include chart documents
2009-07-09 Andreas J. Guelzow <aguelzow pyrshep ca>
* src/sheet-object.h (sheet_object_anchor_to_offset_pts): new
* src/sheet-object.c (sheet_object_anchor_to_offset_pts): new
ChangeLog | 5 +
NEWS | 1 +
plugins/openoffice/ChangeLog | 19 ++++
plugins/openoffice/openoffice-read.c | 12 +--
plugins/openoffice/openoffice-write.c | 160 +++++++++++++++++++++++++++++----
src/sheet-object.c | 20 ++++
src/sheet-object.h | 2 +
7 files changed, 195 insertions(+), 24 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d61d6d7..57ae3bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-07-09 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * src/sheet-object.h (sheet_object_anchor_to_offset_pts): new
+ * src/sheet-object.c (sheet_object_anchor_to_offset_pts): new
+
2009-07-09 Morten Welinder <terra gnome org>
* src/gnm-plugin.c (plugin_service_function_group_read_xml):
diff --git a/NEWS b/NEWS
index 9443e3f..b49635e 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ Andreas:
* Add an initialy hidden long format toolbar.
* Fix std error for intercept in non-affine case of LINEST. [#550933]
* Fix loading of charts from MS generated ODF files. [#588107]
+ * Add some sheet object support to ODF export.
Morten:
* Make SUMIF/COUNTIF and the D* functions understand pattern. [#586215]
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index 9a7a585..e392148 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,22 @@
+2009-07-09 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * openoffice-read.c (od_draw_frame): we can only match
+ once
+ (openoffice_file_open): g_free can handle NULL
+ * openoffice-write.c (odf_write_frame): new
+ (odf_write_objects): new
+ (odf_write_empty_cell): rather than calling
+ odf_write_comment, call odf_write_objects
+ (odf_write_covered_cell): change argument, and
+ change all callers
+ (odf_sheet_objects_get): new
+ (odf_write_content_rows): handle all sheet objects,
+ not just comments
+ (odf_write_content): hash graphs
+ (odf_write_graphs): new stub
+ (openoffice_file_save_real): initialize graph hash
+ and create include chart documents
+
2009-07-08 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-read.c: split styles.col_row into
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 3fbd5b8..3cb3749 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -3108,11 +3108,11 @@ od_draw_frame (GsfXMLIn *xin, xmlChar const **attrs)
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2){
if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "width"))
aux = oo_parse_distance (xin, attrs[1], "width", &width);
- if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "height"))
+ else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "height"))
aux = oo_parse_distance (xin, attrs[1], "height", &height);
- if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "x"))
+ else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "x"))
aux = oo_parse_distance (xin, attrs[1], "x", &x);
- if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "y"))
+ else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_SVG, "y"))
aux = oo_parse_distance (xin, attrs[1], "y", &y);
}
cell_base.start.col = cell_base.end.col = state->pos.eval.col;
@@ -4942,10 +4942,8 @@ openoffice_file_open (GOFileOpener const *fo, IOContext *io_context,
if (state.default_style.cells)
gnm_style_unref (state.default_style.cells);
- if (state.default_style.rows)
- g_free (state.default_style.rows);
- if (state.default_style.columns)
- g_free (state.default_style.columns);
+ g_free (state.default_style.rows);
+ g_free (state.default_style.columns);
g_hash_table_destroy (state.styles.sheet);
g_hash_table_destroy (state.styles.col);
g_hash_table_destroy (state.styles.row);
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 9955912..944766b 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -56,7 +56,6 @@
#include <hlink.h>
#include <solver.h>
#include <sheet-filter.h>
-#include <sheet-object-cell-comment.h>
#include <print-info.h>
#include <parse-util.h>
#include <tools/scenarios.h>
@@ -64,6 +63,10 @@
#include <xml-io.h>
#include <style-conditions.h>
+#include <sheet-object.h>
+#include <sheet-object-graph.h>
+#include <sheet-object-cell-comment.h>
+
#include <gsf/gsf-libxml.h>
#include <gsf/gsf-output.h>
#include <gsf/gsf-outfile.h>
@@ -85,10 +88,13 @@
#define DUBLINCORE "dc:"
#define FOSTYLE "fo:"
#define NUMBER "number:"
+#define DRAW "draw:"
+#define SVG "svg:"
#define GNMSTYLE "gnm:" /* We use this for attributes and elements not supported by ODF */
typedef struct {
GsfXMLOut *xml;
+ GsfOutfile *outfile;
IOContext *ioc;
WorkbookView const *wbv;
Workbook const *wb;
@@ -105,6 +111,7 @@ typedef struct {
GnmStyle *default_style;
ColRowInfo const *row_default;
ColRowInfo const *column_default;
+ GHashTable *objects;
gboolean with_extension;
} GnmOOExport;
@@ -2077,7 +2084,69 @@ odf_write_comment (GnmOOExport *state, GnmComment const *cc)
}
static void
-odf_write_empty_cell (GnmOOExport *state, int num, GnmStyle const *style, GnmComment const *cc)
+odf_write_frame (GnmOOExport *state, SheetObject const *so)
+{
+ SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
+ double res_pts[4] = {0.,0.,0.,0.};
+ GnmCellRef ref;
+ GnmRange const *r = &anchor->cell_bound;
+ GnmExprTop const *texpr;
+ GnmParsePos pp;
+ char *formula, *closing;
+
+ sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
+
+ gsf_xml_out_start_element (state->xml, DRAW "frame");
+ odf_add_pt (state->xml, SVG "x", res_pts[0]);
+ odf_add_pt (state->xml, SVG "y", res_pts[1]);
+ odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
+ odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
+
+ /* The next 3 lines should not be needed, but older versions of Gnumeric used the */
+ /* width and height. */
+ sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
+ odf_add_pt (state->xml, SVG "width", res_pts[2] - res_pts[0]);
+ odf_add_pt (state->xml, SVG "height", res_pts[3] - res_pts[1]);
+
+ gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
+ texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
+ parse_pos_init_sheet (&pp, state->sheet);
+ formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
+ /* While this should be enough, ODF doesn't want the same format here as in formulas: */
+ closing = strrchr(formula, ']');
+ if (closing != NULL)
+ *closing = '\0';
+ gnm_expr_top_unref (texpr);
+ gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
+ (*formula == '[') ? (formula + 1) : formula);
+
+ gsf_xml_out_start_element (state->xml, DRAW "text-box");
+ gsf_xml_out_simple_element (state->xml, TEXT "p", "Missing Sheet Object");
+ gsf_xml_out_end_element (state->xml); /* DRAW "textbox" */
+
+ gsf_xml_out_end_element (state->xml); /* DRAW "frame" */
+}
+
+static void
+odf_write_objects (GnmOOExport *state, GSList *objects)
+{
+ GSList *l;
+
+ for (l = objects; l != NULL; l = l->next) {
+ SheetObject *so = l->data;
+ if (so == NULL) {
+ g_warning ("NULL sheet object encountered.");
+ continue;
+ }
+ if (IS_CELL_COMMENT (so))
+ odf_write_comment (state, CELL_COMMENT (so));
+ else
+ odf_write_frame (state, so);
+ }
+}
+
+static void
+odf_write_empty_cell (GnmOOExport *state, int num, GnmStyle const *style, GSList *objects)
{
if (num > 0) {
gsf_xml_out_start_element (state->xml, TABLE "table-cell");
@@ -2091,8 +2160,7 @@ odf_write_empty_cell (GnmOOExport *state, int num, GnmStyle const *style, GnmCom
gsf_xml_out_add_cstr (state->xml,
TABLE "style-name", name);
}
- if (cc != NULL)
- odf_write_comment (state, cc);
+ odf_write_objects (state, objects);
gsf_xml_out_end_element (state->xml); /* table-cell */
}
}
@@ -2113,7 +2181,7 @@ odf_write_covered_cell (GnmOOExport *state, int *num)
static void
odf_write_cell (GnmOOExport *state, GnmCell *cell, GnmRange const *merge_range,
- GnmComment const *cc)
+ GSList *objects)
{
int rows_spanned = 0, cols_spanned = 0;
gboolean pp = TRUE;
@@ -2211,8 +2279,7 @@ odf_write_cell (GnmOOExport *state, GnmCell *cell, GnmRange const *merge_range,
}
}
- if (cc != NULL)
- odf_write_comment (state, cc);
+ odf_write_objects (state, objects);
if (cell != NULL && cell->value != NULL) {
g_object_set (G_OBJECT (state->xml), "pretty-print", FALSE, NULL);
@@ -2428,6 +2495,23 @@ odf_write_styled_empty_rows (GnmOOExport *state, Sheet const *sheet,
style_list_free (list);
}
+static GSList *
+odf_sheet_objects_get (Sheet const *sheet, GnmCellPos const *pos)
+{
+ GSList *res = NULL;
+ GSList *ptr;
+
+ g_return_val_if_fail (IS_SHEET (sheet), NULL);
+
+ for (ptr = sheet->sheet_objects; ptr != NULL ; ptr = ptr->next ) {
+ SheetObject *so = SHEET_OBJECT (ptr->data);
+ SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
+ if (gnm_cellpos_equal (&anchor->cell_bound.start, pos))
+ res = g_slist_prepend (res, so);
+ }
+ return res;
+}
+
static void
odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to,
G_GNUC_UNUSED int col_from, G_GNUC_UNUSED int col_to, int row_length,
@@ -2455,10 +2539,9 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
for (col = 0; col < row_length; col++) {
GnmCell *current_cell = sheet_cell_get (sheet, col, row);
GnmRange const *merge_range;
- GnmComment const *cc;
+ GSList *objects;
pos.col = col;
- cc = sheet_get_comment (sheet, &pos);
merge_range = gnm_sheet_merge_is_corner (sheet, &pos);
if (odf_cell_is_covered (sheet, current_cell, col, row,
@@ -2468,7 +2551,10 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
covered_cell++;
continue;
}
- if ((merge_range == NULL) && (cc == NULL) &&
+
+ objects = odf_sheet_objects_get (sheet, &pos);
+
+ if ((merge_range == NULL) && (objects == NULL) &&
gnm_cell_is_empty (current_cell)) {
GnmStyle const *this_style= sheet_style_get (sheet, pos.col, pos.row);
@@ -2489,7 +2575,9 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
null_cell = 0;
if (covered_cell > 0)
odf_write_covered_cell (state, &covered_cell);
- odf_write_cell (state, current_cell, merge_range, cc);
+ odf_write_cell (state, current_cell, merge_range, objects);
+
+ g_slist_free (objects);
}
odf_write_empty_cell (state, null_cell, null_style, NULL);
@@ -2666,6 +2754,7 @@ static void
odf_write_content (GnmOOExport *state, GsfOutput *child)
{
int i;
+ int graph_n = 1;
gboolean has_autofilters = FALSE;
state->xml = gsf_xml_out_new (child);
@@ -2699,9 +2788,16 @@ odf_write_content (GnmOOExport *state, GsfOutput *child)
Sheet *sheet = workbook_sheet_by_index (state->wb, i);
char *style_name;
GnmRange *p_area;
+ GSList *l, *graphs;
state->sheet = sheet;
+ graphs = sheet_objects_get (sheet, NULL, SHEET_OBJECT_GRAPH_TYPE);
+ for (l = graphs; l != NULL; l = l->next)
+ g_hash_table_insert (state->objects, l->data,
+ g_strdup_printf ("Object %i", graph_n++));
+ g_slist_free (graphs);
+
gsf_xml_out_start_element (state->xml, TABLE "table");
gsf_xml_out_add_cstr (state->xml, TABLE "name", sheet->name_unquoted);
@@ -2954,6 +3050,32 @@ odf_write_manifest (GnmOOExport *state, GsfOutput *child)
/**********************************************************************************/
static void
+odf_write_graphs (SheetObject *graph, char const *name, GnmOOExport *state)
+{
+ GsfOutput *child, *sec_child;
+ char *fullname = g_strdup_printf ("%s/content.xml", name);
+
+ child = gsf_outfile_new_child_full (state->outfile, name, TRUE,
+ "compression-level", GSF_ZIP_DEFLATED,
+ NULL);
+ if (NULL != child) {
+ sec_child = gsf_outfile_new_child_full (state->outfile, fullname, FALSE,
+ "compression-level", GSF_ZIP_DEFLATED,
+ NULL);
+ gsf_output_close (child);
+ g_object_unref (G_OBJECT (child));
+ if (NULL != sec_child) {
+ gsf_output_close (sec_child);
+ g_object_unref (G_OBJECT (sec_child));
+ }
+ }
+ g_free (fullname);
+}
+
+
+/**********************************************************************************/
+
+static void
openoffice_file_save_real (GOFileSaver const *fs, IOContext *ioc,
WorkbookView const *wbv, GsfOutput *output, gboolean with_extension)
{
@@ -2972,8 +3094,6 @@ openoffice_file_save_real (GOFileSaver const *fs, IOContext *ioc,
};
GnmOOExport state;
- GsfOutfile *outfile = NULL;
- GsfOutput *child;
GnmLocale *locale;
GError *err;
unsigned i;
@@ -2981,13 +3101,15 @@ openoffice_file_save_real (GOFileSaver const *fs, IOContext *ioc,
locale = gnm_push_C_locale ();
- outfile = gsf_outfile_zip_new (output, &err);
+ state.outfile = gsf_outfile_zip_new (output, &err);
state.with_extension = with_extension;
state.ioc = ioc;
state.wbv = wbv;
state.wb = wb_view_get_workbook (wbv);
state.conv = odf_expr_conventions_new ();
+ state.objects = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_free);
state.named_cell_styles = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) g_free);
state.cell_styles = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@@ -3013,7 +3135,8 @@ openoffice_file_save_real (GOFileSaver const *fs, IOContext *ioc,
odf_store_this_named_style (state.default_style, "Gnumeric-default", &state);
for (i = 0 ; i < G_N_ELEMENTS (streams); i++) {
- child = gsf_outfile_new_child_full (outfile, streams[i].name, FALSE,
+ GsfOutput *child;
+ child = gsf_outfile_new_child_full (state.outfile, streams[i].name, FALSE,
/* do not compress the mimetype */
"compression-level", ((0 == i) ? GSF_ZIP_STORED : GSF_ZIP_DEFLATED),
NULL);
@@ -3024,12 +3147,15 @@ openoffice_file_save_real (GOFileSaver const *fs, IOContext *ioc,
}
}
+ g_hash_table_foreach (state.objects, (GHFunc) odf_write_graphs, &state);
+
g_free (state.conv);
- gsf_output_close (GSF_OUTPUT (outfile));
- g_object_unref (G_OBJECT (outfile));
+ gsf_output_close (GSF_OUTPUT (state.outfile));
+ g_object_unref (G_OBJECT (state.outfile));
gnm_pop_C_locale (locale);
+ g_hash_table_unref (state.objects);
g_hash_table_unref (state.named_cell_styles);
g_hash_table_unref (state.cell_styles);
g_hash_table_unref (state.xl_styles);
diff --git a/src/sheet-object.c b/src/sheet-object.c
index e76a0b5..ad5d23b 100644
--- a/src/sheet-object.c
+++ b/src/sheet-object.c
@@ -691,6 +691,26 @@ sheet_object_anchor_to_pts (SheetObjectAnchor const *anchor,
FALSE, anchor->offset [3]);
}
+void
+sheet_object_anchor_to_offset_pts (SheetObjectAnchor const *anchor,
+ Sheet const *sheet, double *res_pts)
+{
+ GnmRange const *r;
+
+ g_return_if_fail (res_pts != NULL);
+
+ r = &anchor->cell_bound;
+
+ res_pts [0] = cell_offset_calc_pt (sheet, r->start.col,
+ TRUE, anchor->offset [0]);
+ res_pts [1] = cell_offset_calc_pt (sheet, r->start.row,
+ FALSE, anchor->offset [1]);
+ res_pts [2] = cell_offset_calc_pt (sheet, r->end.col,
+ TRUE, anchor->offset [2]);
+ res_pts [3] = cell_offset_calc_pt (sheet, r->end.row,
+ FALSE, anchor->offset [3]);
+}
+
static void
clear_sheet (SheetObject *so, GOUndo **pundo)
{
diff --git a/src/sheet-object.h b/src/sheet-object.h
index cbfa9be..c166ada 100644
--- a/src/sheet-object.h
+++ b/src/sheet-object.h
@@ -106,6 +106,8 @@ gboolean sheet_object_rubber_band_directly (SheetObject const *so);
/* Anchor utilities */
void sheet_object_anchor_to_pts (SheetObjectAnchor const *anchor,
Sheet const *sheet, double *res_pts);
+void sheet_object_anchor_to_offset_pts (SheetObjectAnchor const *anchor,
+ Sheet const *sheet, double *res_pts);
void sheet_object_anchor_init (SheetObjectAnchor *anchor,
GnmRange const *cell_bound,
float const *offset,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]