[goffice] Serialize color maps
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Serialize color maps
- Date: Sat, 3 Nov 2012 17:24:01 +0000 (UTC)
commit d39aab4dc8d25e300bbdbcbe9db61f50a785144a
Author: Jean Brefort <jean brefort normalesup org>
Date: Sat Nov 3 18:23:07 2012 +0100
Serialize color maps
ChangeLog | 23 +++
docs/reference/goffice-0.10-sections.txt | 13 +-
goffice/Makefile.am | 5 +-
goffice/app/go-doc.c | 68 ++++----
goffice/app/go-doc.h | 6 +-
goffice/graph/gog-axis-color-map.c | 263 ++++++++++++++++++++++--------
goffice/graph/gog-axis-color-map.h | 7 +-
goffice/graph/gog-axis.c | 46 ++++--
goffice/utils/goffice-utils.c | 104 ++++++++++++
goffice/utils/goffice-utils.h | 2 +
10 files changed, 409 insertions(+), 128 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f990b48..c0605c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2012-11-03 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/Makefile.am: add goffice-utils.c.
+ * goffice/app/go-doc.c (go_doc_finalize), (go_doc_write),
+ (load_color_map), (go_doc_read), (go_doc_save_color_map): save and load
+ used color maps.
+ * goffice/app/go-doc.h: ditto.
+ * goffice/graph/gog-axis-color-map.c (gog_axis_color_map_finalize),
+ (gog_axis_color_map_init), (gog_axis_color_map_get_id),
+ (gog_axis_color_map_from_colors), (save_name_cb),
+ (gog_axis_color_map_write), (color_stop_start), (map_start),
+ (name_start), (name_end), (color_map_loaded),
+ (color_map_load_from_uri), (parse_done_cb),
+ (gog_axis_color_map_sax_push_parser),
+ (gog_axis_color_map_get_from_id), (_gog_axis_color_maps_init): ditto.
+ * goffice/graph/gog-axis-color-map.h: ditto.
+ * goffice/graph/gog-axis.c (gog_axis_prep_sax),
+ (gog_axis_sax_save), (gog_axis_set_property),
+ (gog_axis_get_property), (gog_axis_persist_init): ditto.
+ * goffice/utils/goffice-utils.h: new uuid generator copied from
+ telepathy-gabble.
+ * goffice/utils/goffice-utils.c: new file.
+
2012-11-01 Jean Brefort <jean brefort normalesup org>
* goffice/Makefile.am: add new ui file.
diff --git a/docs/reference/goffice-0.10-sections.txt b/docs/reference/goffice-0.10-sections.txt
index 8f53a72..e0dd922 100644
--- a/docs/reference/goffice-0.10-sections.txt
+++ b/docs/reference/goffice-0.10-sections.txt
@@ -843,8 +843,6 @@ go_distribution_get_type
GODoc
go_doc_add_image
go_doc_end_read
-go_doc_foreach_color_map
-go_doc_get_color_map
go_doc_get_dirty_time
go_doc_get_image
go_doc_get_images
@@ -856,6 +854,7 @@ go_doc_init_write
go_doc_is_dirty
go_doc_is_pristine
go_doc_read
+go_doc_save_color_map
go_doc_save_image
go_doc_set_dirty
go_doc_set_dirty_time
@@ -2748,10 +2747,13 @@ GogAxisColorMapHandler
gog_axis_color_map_foreach
gog_axis_color_map_from_colors
gog_axis_color_map_get_color
-gog_axis_color_map_get_from_name
+gog_axis_color_map_get_from_id
gog_axis_color_map_get_max
+gog_axis_color_map_get_id
gog_axis_color_map_get_name
gog_axis_color_map_get_snapshot
+gog_axis_color_map_sax_push_parser
+gog_axis_color_map_write
<SUBSECTION Standard>
GOG_AXIS_COLOR_MAP
GOG_IS_AXIS_COLOR_MAP
@@ -3554,3 +3556,8 @@ GO_TYPE_SEARCH_REPLACE
go_search_replace_get_type
</SECTION>
+<SECTION>
+<FILE>go-utils</FILE>
+<TITLE>Miscellaneous</TITLE>
+go_uuid
+</SECTION>
diff --git a/goffice/Makefile.am b/goffice/Makefile.am
index 9c8d744..979773d 100644
--- a/goffice/Makefile.am
+++ b/goffice/Makefile.am
@@ -360,6 +360,7 @@ math_HEADERS = \
utils_SOURCES = \
utils/go-marshalers.list \
\
+ utils/goffice-utils.c \
utils/go-color.c \
utils/go-file.c \
utils/go-font.c \
@@ -397,7 +398,7 @@ utils_SOURCES = \
utilsdir = $(goffice_include_dir)/utils
utils_HEADERS = \
- utils/goffice-utils.h \
+ utils/goffice-utils.h \
utils/go-cairo.h \
utils/go-color.h \
utils/go-file.h \
@@ -423,7 +424,7 @@ utils_HEADERS = \
utils/go-glib-extras.h \
utils/go-libxml-extras.h \
utils/go-pango-extras.h \
- utils/go-gdk-pixbuf.h \
+ utils/go-gdk-pixbuf.h \
utils/go-persist.h \
utils/go-bezier.h \
utils/go-editor.h \
diff --git a/goffice/app/go-doc.c b/goffice/app/go-doc.c
index 25997fd..971800f 100644
--- a/goffice/app/go-doc.c
+++ b/goffice/app/go-doc.c
@@ -35,7 +35,6 @@ struct _GODocPrivate {
GHashTable *imagebuf; /* used when loading/saving images */
/* color maps */
- GSList *colormaps; /* document graph axis color maps */
GSList *colormapsbuf; /* used when loading/saving color maps */
};
@@ -136,7 +135,6 @@ go_doc_finalize (GObject *obj)
if (doc->images)
g_hash_table_destroy (doc->images);
doc->images = NULL;
- g_slist_free_full (doc->priv->colormaps, g_object_unref);
g_free (doc->priv);
doc->priv = NULL;
@@ -506,15 +504,29 @@ save_image_cb (gpointer key, gpointer img_, gpointer user)
void
go_doc_write (GODoc *doc, GsfXMLOut *output)
{
- if (g_hash_table_size (doc->priv->imagebuf) > 0) {
+ GSList *ptr;
+ if (g_hash_table_size (doc->priv->imagebuf) > 0 ||
+ doc->priv->colormapsbuf != NULL) {
gsf_xml_out_start_element (output, "GODoc");
g_hash_table_foreach (doc->priv->imagebuf, save_image_cb, output);
+ for (ptr = doc->priv->colormapsbuf; ptr; ptr = ptr->next)
+ gog_axis_color_map_write (GOG_AXIS_COLOR_MAP (ptr->data), output);
+ g_slist_free (doc->priv->colormapsbuf);
+ doc->priv->colormapsbuf = NULL;
gsf_xml_out_end_element (output);
}
g_hash_table_destroy (doc->priv->imagebuf);
doc->priv->imagebuf = NULL;
}
+/**
+ * go_doc_save_image:
+ * @doc: a #GODoc
+ * @id: the Id of the #GOImage to save
+ *
+ * Saves the image with the document. Each image will be saved only
+ * once.
+ **/
void
go_doc_save_image (GODoc *doc, char const *id)
{
@@ -578,6 +590,12 @@ load_image_data (GsfXMLIn *xin, GsfXMLBlob *unknown)
g_object_set_data (G_OBJECT (doc), "new image", NULL);
}
+static void
+load_color_map (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ gog_axis_color_map_sax_push_parser (xin, attrs);
+}
+
void
go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs)
{
@@ -589,6 +607,10 @@ go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs)
-1, "GOImage",
GSF_XML_CONTENT,
&load_image, &load_image_data),
+ GSF_XML_IN_NODE (DOC, COLOR_MAP,
+ -1, "GogAxisColorMap",
+ GSF_XML_NO_CONTENT,
+ &load_color_map, NULL),
GSF_XML_IN_NODE_END
};
static GsfXMLInDoc *xmldoc = NULL;
@@ -634,39 +656,19 @@ go_doc_image_fetch (GODoc *doc, char const *id, GType type)
}
/**
- * go_doc_get_color_map:
- * @doc: a #GODoc
- * @name: the color map name to search for
- *
- * Retrieves the color map whose name is @name. The difference with
- * gog_axis_color_map_get_from_name() is that color maps specific to the
- * document are searched first if any.
- * Returns: (transfer none): the found color map or %NULL.
- **/
-GogAxisColorMap const *
-go_doc_get_color_map (GODoc *doc, char const *name)
-{
- g_return_val_if_fail (GO_IS_DOC (doc) && name && *name, NULL);
-#if 0
- if (doc->priv->colormaps == NULL)
- return NULL;
- return g_hash_table_lookup (doc->priv->colormaps, name);
-#endif
- return gog_axis_color_map_get_from_name (name);
-}
-
-/**
- * go_doc_foreach_color_map:
+ * go_doc_save_color_map:
* @doc: a #GODoc
- * @handler: (scope call): a #GogAxisColorMapHandler
- * @user_data: data to pass to @handler
+ * @map: the #GogAxisColorMap to save
*
- * Executes @handler to each color map installed on the system or specific to
- * @doc. This function calls gog_axis_color_map_foreach() but don't execute the
- * handler if a color map with the same name exists in the document.
+ * Saves the color map with the document. Each color map will be saved only
+ * once.
**/
void
-go_doc_foreach_color_map (GODoc *doc, GogAxisColorMapHandler handler, gpointer user_data)
+go_doc_save_color_map (GODoc *doc, GogAxisColorMap const *map)
{
- gog_axis_color_map_foreach (handler, user_data);
+ GSList *ptr;
+ for (ptr = doc->priv->colormapsbuf; ptr; ptr = ptr->next)
+ if (ptr->data == map) /* already marked for saving */
+ return;
+ doc->priv->colormapsbuf = g_slist_prepend (doc->priv->colormapsbuf, (void *) map);
}
diff --git a/goffice/app/go-doc.h b/goffice/app/go-doc.h
index 1c1a14b..82be494 100644
--- a/goffice/app/go-doc.h
+++ b/goffice/app/go-doc.h
@@ -61,11 +61,7 @@ void go_doc_init_read (GODoc *doc, GsfInput *input);
void go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs);
void go_doc_end_read (GODoc *doc);
GOImage *go_doc_image_fetch (GODoc *doc, char const *id, GType type);
-
-GogAxisColorMap const *go_doc_get_color_map (GODoc *doc, char const *name);
-void go_doc_foreach_color_map (GODoc *doc,
- GogAxisColorMapHandler handler,
- gpointer user_data);
+void go_doc_save_color_map (GODoc *doc, GogAxisColorMap const *map);
G_END_DECLS
diff --git a/goffice/graph/gog-axis-color-map.c b/goffice/graph/gog-axis-color-map.c
index 9bf7a86..3016036 100644
--- a/goffice/graph/gog-axis-color-map.c
+++ b/goffice/graph/gog-axis-color-map.c
@@ -23,6 +23,7 @@
#include <goffice/goffice.h>
#include <goffice/goffice-priv.h>
+#include <gsf/gsf-input.h>
#include <gsf/gsf-impl-utils.h>
#include <glib/gi18n-lib.h>
#include <string.h>
@@ -45,7 +46,7 @@
**/
struct _GogAxisColorMap {
GObject base;
- char *name, *local_name;
+ char *id, *name;
GHashTable *names;
unsigned size; /* colors number */
unsigned *limits;
@@ -59,10 +60,10 @@ static void
gog_axis_color_map_finalize (GObject *obj)
{
GogAxisColorMap *map = GOG_AXIS_COLOR_MAP (obj);
+ g_free (map->id);
+ map->id = NULL;
g_free (map->name);
map->name = NULL;
- g_free (map->local_name);
- map->local_name = NULL;
g_free (map->limits);
map->limits = NULL;
g_free (map->colors);
@@ -84,6 +85,7 @@ gog_axis_color_map_class_init (GObjectClass *gobject_klass)
static void
gog_axis_color_map_init (GogAxisColorMap *map)
{
+ map->names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
GSF_CLASS (GogAxisColorMap, gog_axis_color_map,
@@ -132,13 +134,27 @@ gog_axis_color_map_get_max (GogAxisColorMap const *map)
}
/**
- * gog_axis_color_map_get_snapshot:
+ * gog_axis_color_map_get_id:
* @map: a #GogAxisMap
*
* Retrieves the color map name.
* Returns: (transfer none): the map name.
**/
char const *
+gog_axis_color_map_get_id (GogAxisColorMap const *map)
+{
+ g_return_val_if_fail (GOG_IS_AXIS_COLOR_MAP (map), NULL);
+ return map->id;
+}
+
+/**
+ * gog_axis_color_map_get_name:
+ * @map: a #GogAxisMap
+ *
+ * Retrieves the color map localized name.
+ * Returns: (transfer none): the map name.
+ **/
+char const *
gog_axis_color_map_get_name (GogAxisColorMap const *map)
{
g_return_val_if_fail (GOG_IS_AXIS_COLOR_MAP (map), NULL);
@@ -264,6 +280,7 @@ gog_axis_color_map_from_colors (char const *name, unsigned nb, GOColor const *co
{
unsigned i;
GogAxisColorMap *color_map = g_object_new (GOG_TYPE_AXIS_COLOR_MAP, NULL);
+ color_map->id = g_strdup (name);
color_map->name = g_strdup (name);
color_map->size = nb;
color_map->limits = g_new (unsigned, nb);
@@ -303,6 +320,44 @@ gog_axis_color_map_registry_add (GogAxisColorMap *map)
color_maps = g_slist_append (color_maps, map);
}
+static void
+save_name_cb (char const *lang, char const *name, GsfXMLOut *output)
+{
+ gsf_xml_out_start_element (output, "name");
+ if (strcmp (lang, "C"))
+ gsf_xml_out_add_cstr_unchecked (output, "xml:lang", lang);
+ gsf_xml_out_add_cstr_unchecked (output, NULL, name);
+ gsf_xml_out_end_element (output);
+}
+
+/**
+ * gog_axis_color_map_write:
+ * @map: a #GogAxisColorMap
+ * @output: a #GsfXMLOut
+ *
+ * Writes the color map as an XML node to @output.
+ **/
+void
+gog_axis_color_map_write (GogAxisColorMap const *map, GsfXMLOut *output)
+{
+ unsigned i;
+ char *buf;
+ g_return_if_fail (GOG_IS_AXIS_COLOR_MAP (map));
+
+ gsf_xml_out_start_element (output, "GogAxisColorMap");
+ gsf_xml_out_add_cstr_unchecked (output, "id", map->id);
+ g_hash_table_foreach (map->names, (GHFunc) save_name_cb, output);
+ for (i = 0; i < map->size; i++) {
+ gsf_xml_out_start_element (output, "color-stop");
+ gsf_xml_out_add_uint (output, "bin", map->limits[i]);
+ buf = go_color_as_str (map->colors[i]);
+ gsf_xml_out_add_cstr_unchecked (output, "color", buf);
+ g_free (buf);
+ gsf_xml_out_end_element (output);
+ }
+ gsf_xml_out_end_element (output);
+}
+
struct _color_stop {
unsigned bin;
GOColor color;
@@ -310,7 +365,7 @@ struct _color_stop {
struct color_map_load_state {
GogAxisColorMap *map;
- char *lang, *local_name;
+ char *lang, *name;
unsigned name_lang_score;
char const * const *langs;
GSList *color_stops;
@@ -326,6 +381,8 @@ color_stop_start (GsfXMLIn *xin, xmlChar const **attrs)
gboolean color_found = FALSE;
gboolean bin_found = FALSE;
+ if (state->map->name)
+ return;
for (; attrs != NULL && *attrs ; attrs += 2)
if (0 == strcmp (*attrs, "bin")) {
bin = strtoul (attrs[1], &end, 10);
@@ -340,7 +397,20 @@ color_stop_start (GsfXMLIn *xin, xmlChar const **attrs)
state->color_stops = g_slist_append (state->color_stops, stop);
} else
g_warning ("[GogAxisColorMap]: Invalid color stop");
-
+}
+
+static void
+map_start (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ struct color_map_load_state *state = (struct color_map_load_state *) xin->user_state;
+ if (state->map == NULL) {
+ state->map = g_object_new (GOG_TYPE_AXIS_COLOR_MAP, NULL);
+ for (; attrs && *attrs; attrs +=2)
+ if (!strcmp ((char const *) *attrs, "id")) {
+ state->map->id = g_strdup ((char const *) attrs[1]);
+ break;
+ }
+ }
}
static void
@@ -348,6 +418,8 @@ name_start (GsfXMLIn *xin, xmlChar const **attrs)
{
struct color_map_load_state *state = (struct color_map_load_state *) xin->user_state;
unsigned i;
+ if (state->map->name)
+ return;
for (i = 0; attrs != NULL && attrs[i] && attrs[i+1] ; i += 2)
if (0 == strcmp (attrs[i], "xml:lang"))
state->lang = g_strdup (attrs[i+1]);
@@ -358,30 +430,25 @@ name_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
{
struct color_map_load_state *state = (struct color_map_load_state *) xin->user_state;
char *name = NULL;
+ if (state->map->name)
+ return;
if (xin->content->str == NULL)
return;
name = g_strdup (xin->content->str);
- if (state->map == NULL) {
- state->map = g_object_new (GOG_TYPE_AXIS_COLOR_MAP, NULL);
- state->map->names = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- }
- if (state->lang == NULL) {
- state->map->name = name;
- } else {
- if (state->name_lang_score > 0 && state->langs[0] != NULL) {
- unsigned i;
- for (i = 0; i < state->name_lang_score && state->langs[i] != NULL; i++) {
- if (strcmp (state->langs[i], state->lang) == 0) {
- g_free (state->local_name);
- state->local_name = g_strdup (name);
- state->name_lang_score = i;
- }
+ if (state->lang == NULL)
+ state->lang = g_strdup ("C");
+ if (state->name_lang_score > 0 && state->langs[0] != NULL) {
+ unsigned i;
+ for (i = 0; i < state->name_lang_score && state->langs[i] != NULL; i++) {
+ if (strcmp (state->langs[i], state->lang) == 0) {
+ g_free (state->name);
+ state->name = g_strdup (name);
+ state->name_lang_score = i;
}
}
- g_hash_table_replace (state->map->names, state->lang, name);
- state->lang = NULL;
}
+ g_hash_table_replace (state->map->names, state->lang, name);
+ state->lang = NULL;
}
static int
@@ -390,18 +457,52 @@ color_stops_cmp (struct _color_stop *first, struct _color_stop *second)
return (first->bin < second->bin)? -1: (int) (first->bin - second->bin);
}
+static GsfXMLInNode const color_map_dtd[] = {
+ GSF_XML_IN_NODE (THEME, THEME, -1, "GogAxisColorMap", GSF_XML_NO_CONTENT, map_start, NULL),
+ GSF_XML_IN_NODE (THEME, NAME, -1, "name", GSF_XML_CONTENT, name_start, name_end),
+ GSF_XML_IN_NODE (THEME, UNAME, -1, "_name", GSF_XML_CONTENT, name_start, name_end),
+ GSF_XML_IN_NODE (THEME, STOP, -1, "color-stop", GSF_XML_CONTENT, color_stop_start, NULL),
+ GSF_XML_IN_NODE_END
+};
+static GsfXMLInDoc *xml = NULL;
+
+static void
+color_map_loaded (struct color_map_load_state *state, char const *uri, gboolean delete_invalid)
+{
+ GSList *ptr;
+ if (state->map && state->map->name)
+ return;
+ state->map->name = state->name;
+ /* populates the colors */
+ /* first sort the color list according to bins */
+ ptr = state->color_stops = g_slist_sort (state->color_stops, (GCompareFunc) color_stops_cmp);
+ if (state->map->id == NULL || ((struct _color_stop *) ptr->data)->bin != 0) {
+ g_warning ("[GogAxisColorMap]: Invalid color map in %s", uri);
+ if (delete_invalid) {
+ g_object_unref (state->map);
+ state->map = NULL;
+ }
+ } else {
+ unsigned cur_bin, n = 0;
+ state->map->size = g_slist_length (state->color_stops);
+ state->map->limits = g_new (unsigned, state->map->size);
+ state->map->colors = g_new (GOColor, state->map->size);
+ while (ptr) {
+ cur_bin = state->map->limits[n] = ((struct _color_stop *) ptr->data)->bin;
+ state->map->colors[n++] = ((struct _color_stop *) ptr->data)->color;
+ do (ptr = ptr->next);
+ while (ptr && ((struct _color_stop *) ptr->data)->bin == cur_bin);
+ }
+ state->map->size = n; /* we drop duplicate bins */
+ }
+ g_slist_free_full (state->color_stops, g_free);
+ g_free (state->lang);
+}
+
static void
color_map_load_from_uri (char const *uri)
{
- static GsfXMLInNode const color_map_dtd[] = {
- GSF_XML_IN_NODE (THEME, THEME, -1, "GogAxisColorMap", GSF_XML_NO_CONTENT, NULL, NULL),
- GSF_XML_IN_NODE (THEME, NAME, -1, "name", GSF_XML_CONTENT, name_start, name_end),
- GSF_XML_IN_NODE (THEME, UNAME, -1, "_name", GSF_XML_CONTENT, name_start, name_end),
- GSF_XML_IN_NODE (THEME, STOP, -1, "color-stop", GSF_XML_CONTENT, color_stop_start, NULL),
- GSF_XML_IN_NODE_END
- };
- struct color_map_load_state state;
- GsfXMLInDoc *xml;
+ struct color_map_load_state state;
GsfInput *input = go_file_open (uri, NULL);
if (input == NULL) {
@@ -409,45 +510,59 @@ color_map_load_from_uri (char const *uri)
return;
}
state.map = NULL;
- state.lang = state.local_name = NULL;
+ state.name = NULL;
+ state.lang = NULL;
state.langs = g_get_language_names ();
state.name_lang_score = G_MAXINT;
state.color_stops = NULL;
- xml = gsf_xml_in_doc_new (color_map_dtd, NULL);
+ if (!xml)
+ xml = gsf_xml_in_doc_new (color_map_dtd, NULL);
if (!gsf_xml_in_doc_parse (xml, input, &state))
g_warning ("[GogAxisColorMap]: Could not parse %s", uri);
if (state.map != NULL) {
- GSList *ptr;
- state.map->local_name = state.local_name;
- /* populates the colors */
- /* first sort the color list according to bins */
- ptr = state.color_stops = g_slist_sort (state.color_stops, (GCompareFunc) color_stops_cmp);
- if (((struct _color_stop *) ptr->data)->bin != 0) {
- g_warning ("[GogAxisColorMap]: Invalid color map in %s", uri);
- g_object_unref (state.map);
- } else {
- unsigned cur_bin, n = 0;
- state.map->size = g_slist_length (state.color_stops);
- state.map->limits = g_new (unsigned, state.map->size);
- state.map->colors = g_new (GOColor, state.map->size);
- while (ptr) {
- cur_bin = state.map->limits[n] = ((struct _color_stop *) ptr->data)->bin;
- state.map->colors[n++] = ((struct _color_stop *) ptr->data)->color;
- do (ptr = ptr->next);
- while (ptr && ((struct _color_stop *) ptr->data)->bin == cur_bin);
- }
- state.map->size = n; /* we drop duplicate bins */
+ color_map_loaded (&state, uri, TRUE);
+ if (state.map)
gog_axis_color_map_registry_add (state.map);
- }
} else
- g_free (state.local_name);
- g_slist_free_full (state.color_stops, g_free);
- g_free (state.lang);
- gsf_xml_in_doc_free (xml);
+ g_free (state.name);
g_object_unref (input);
}
static void
+parse_done_cb (GsfXMLIn *xin, struct color_map_load_state *state)
+{
+ color_map_loaded (state, gsf_input_name (gsf_xml_in_get_input (xin)), FALSE);
+ g_free (state);
+}
+
+/**
+ * gog_axis_color_map_sax_push_parser:
+ * @xin: a #GsfXMLIn
+ * @attrs: the node attributes.
+ *
+ * Reads a colormap from the XML stream.
+ **/
+void
+gog_axis_color_map_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ struct color_map_load_state *state = g_new (struct color_map_load_state, 1);
+ state->map = NULL;
+ state->name = NULL;
+ state->lang = NULL;
+ state->langs = g_get_language_names ();
+ state->name_lang_score = G_MAXINT;
+ state->color_stops = NULL;
+ if (!xml)
+ xml = gsf_xml_in_doc_new (color_map_dtd, NULL);
+ for (; attrs && *attrs; attrs +=2)
+ if (!strcmp ((char const *) *attrs, "id")) {
+ state->map = GOG_AXIS_COLOR_MAP (gog_axis_color_map_get_from_id ((char const *) attrs[1]));
+ break;
+ }
+ gsf_xml_in_push_state (xin, xml, state, (GsfXMLInExtDtor) parse_done_cb, attrs);
+}
+
+static void
color_maps_load_from_dir (char const *path)
{
GDir *dir = g_dir_open (path, 0, NULL);
@@ -473,8 +588,8 @@ color_maps_load_from_dir (char const *path)
* @map: a #GogAxisColorMap
* @user_data: user data
*
- * Type of the callback to pass to gog_axis_color_map_foreach() and
- * go_doc_foreach_color_map() to iterate through color maps.
+ * Type of the callback to pass to gog_axis_color_map_foreach()
+ * to iterate through color maps.
**/
/**
@@ -482,8 +597,8 @@ color_maps_load_from_dir (char const *path)
* @handler: (scope call): a #GogAxisColorMapHandler
* @user_data: data to pass to @handler
*
- * Executes @handler to each color map installed on the system. This function
- * should not be called directly, call go_doc_foreach_color_map() instead.
+ * Executes @handler to each color map installed on the system or loaded from
+ * a document.
**/
void
gog_axis_color_map_foreach (GogAxisColorMapHandler handler, gpointer user_data)
@@ -494,20 +609,25 @@ gog_axis_color_map_foreach (GogAxisColorMapHandler handler, gpointer user_data)
}
/**
- * gog_axis_color_map_get_from_name:
- * @name: the color map name to search for
+ * gog_axis_color_map_get_from_id:
+ * @id: the color map identifier to search for
*
- * Retrieves the color map whose name is @name.
- * Returns: (transfer none): the found color map or %NULL.
+ * Retrieves the color map whose identifier is @id.
+ * Returns: (transfer none): the found color map.
**/
GogAxisColorMap const *
-gog_axis_color_map_get_from_name (char const *name)
+gog_axis_color_map_get_from_id (char const *id)
{
GSList *ptr;
+ GogAxisColorMap *map;
for (ptr = color_maps; ptr; ptr = ptr->next)
- if (!strcmp (((GogAxisColorMap *) (ptr->data))->name, name))
+ if (!strcmp (((GogAxisColorMap *) (ptr->data))->id, id))
return (GogAxisColorMap *) ptr->data;
- return NULL;
+ /* create an empty new one */
+ map = g_object_new (GOG_TYPE_AXIS_COLOR_MAP, NULL);
+ map->id = g_strdup (id);
+ gog_axis_color_map_registry_add (map);
+ return map;
}
void
@@ -517,6 +637,7 @@ _gog_axis_color_maps_init (void)
/* Default color map */
color_map = g_object_new (GOG_TYPE_AXIS_COLOR_MAP, NULL);
+ color_map->id = g_strdup ("Default");
color_map->name = g_strdup (N_("Default"));
color_map->size = 5;
color_map->limits = g_new (unsigned, 5);
diff --git a/goffice/graph/gog-axis-color-map.h b/goffice/graph/gog-axis-color-map.h
index 093f4eb..5955d7a 100644
--- a/goffice/graph/gog-axis-color-map.h
+++ b/goffice/graph/gog-axis-color-map.h
@@ -23,6 +23,7 @@
#define GOG_AXIS_COLOR_MAP_H
#include <goffice/goffice.h>
+#include <gsf/gsf-libxml.h>
G_BEGIN_DECLS
@@ -40,14 +41,16 @@ GdkPixbuf *gog_axis_color_map_get_snapshot (GogAxisColorMap const *map,
gboolean horizontal,
unsigned width,
unsigned height);
+char const *gog_axis_color_map_get_id (GogAxisColorMap const *map);
char const *gog_axis_color_map_get_name (GogAxisColorMap const *map);
#ifdef GOFFICE_WITH_GTK
GogAxisColorMap *gog_axis_color_map_edit (GogAxisColorMap *map, GOCmdContext *cc);
#endif
typedef void (*GogAxisColorMapHandler) (GogAxisColorMap const *map, gpointer user_data);
void gog_axis_color_map_foreach (GogAxisColorMapHandler handler, gpointer user_data);
-GogAxisColorMap const *gog_axis_color_map_get_from_name (char const *name);
-
+GogAxisColorMap const *gog_axis_color_map_get_from_id (char const *id);
+void gog_axis_color_map_write (GogAxisColorMap const *map, GsfXMLOut *output);
+void gog_axis_color_map_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs);
/* private */
GogAxisColorMap const *_gog_axis_color_map_get_default (void);
diff --git a/goffice/graph/gog-axis.c b/goffice/graph/gog-axis.c
index c488c7e..a23d638 100644
--- a/goffice/graph/gog-axis.c
+++ b/goffice/graph/gog-axis.c
@@ -2194,7 +2194,27 @@ gog_axis_get_atype (GogAxis const *axis)
return axis->type;
}
+static void
+gog_axis_prep_sax (GOPersist *gp, GsfXMLIn *xin, xmlChar const **attrs)
+{
+ /* Nothing to do */
+}
+static void
+gog_axis_sax_save (GOPersist const *gp, GsfXMLOut *output)
+{
+ GogAxis const *axis;
+ GogGraph *graph;
+
+ g_return_if_fail (GOG_IS_AXIS (gp));
+ axis = (GogAxis const*) gp;
+ if (axis->auto_color_map)
+ return;
+ graph = gog_object_get_graph (GOG_OBJECT (gp));
+ if (gog_theme_get_color_map (gog_graph_get_theme (graph), FALSE) == axis->color_map)
+ return;
+ go_doc_save_color_map (gog_graph_get_document (graph), axis->color_map);
+}
static void
gog_axis_set_property (GObject *obj, guint param_id,
@@ -2266,15 +2286,8 @@ gog_axis_set_property (GObject *obj, guint param_id,
case AXIS_PROP_COLOR_MAP: {
char const *str = g_value_get_string (value);
GogAxisColorMap const *map = NULL;
- if (strcmp (str, "default")) {
- map = go_doc_get_color_map (gog_graph_get_document (gog_object_get_graph (GOG_OBJECT (axis))), str);
- if (!map) {
- /* might be the continuous theme color map */
- map = gog_theme_get_color_map (gog_graph_get_theme (gog_object_get_graph (GOG_OBJECT (axis))), FALSE);
- if (strcmp (gog_axis_color_map_get_name (map), str))
- map = NULL;
- }
- }
+ if (strcmp (str, "default"))
+ map = gog_axis_color_map_get_from_id (str);
if (map) {
axis->color_map = map;
axis->auto_color_map = FALSE;
@@ -2331,7 +2344,7 @@ gog_axis_get_property (GObject *obj, guint param_id,
g_value_set_double (value, axis->span_end);
break;
case AXIS_PROP_COLOR_MAP:
- g_value_set_string (value, (axis->auto_color_map)? "default": gog_axis_color_map_get_name (axis->color_map));
+ g_value_set_string (value, (axis->auto_color_map)? "default": gog_axis_color_map_get_id (axis->color_map));
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
@@ -3045,7 +3058,7 @@ gog_axis_class_init (GObjectClass *gobject_klass)
gog_object_register_roles (gog_klass, roles, G_N_ELEMENTS (roles));
- gog_klass->update = gog_axis_update;
+ gog_klass->update = gog_axis_update;
#ifdef GOFFICE_WITH_GTK
gog_klass->populate_editor = gog_axis_populate_editor;
#endif
@@ -3116,10 +3129,18 @@ gog_axis_dataset_init (GogDatasetClass *iface)
iface->dim_changed = gog_axis_dim_changed;
}
+static void
+gog_axis_persist_init (GOPersistClass *iface)
+{
+ iface->sax_save = gog_axis_sax_save;
+ iface->prep_sax = gog_axis_prep_sax;
+}
+
GSF_CLASS_FULL (GogAxis, gog_axis,
NULL, NULL, gog_axis_class_init, NULL,
gog_axis_init, GOG_TYPE_AXIS_BASE, 0,
- GSF_INTERFACE (gog_axis_dataset_init, GOG_TYPE_DATASET))
+ GSF_INTERFACE (gog_axis_dataset_init, GOG_TYPE_DATASET) \
+ GSF_INTERFACE (gog_axis_persist_init, GO_TYPE_PERSIST))
/**
@@ -3471,6 +3492,7 @@ gog_axis_get_circular_rotation (GogAxis *axis)
* gog_axis_get_color_map:
* @axis: a #GogAxis
*
+ * Retrieves the #GogAxisColorMap associated to the axis or %NULL.
* Returns: (transfer none): the color map used by the axis if any.
**/
GogAxisColorMap const *
diff --git a/goffice/utils/goffice-utils.c b/goffice/utils/goffice-utils.c
new file mode 100644
index 0000000..1542141
--- /dev/null
+++ b/goffice/utils/goffice-utils.c
@@ -0,0 +1,104 @@
+/*
+ * goffice-utils.c:
+ *
+ * Copyright (C) 2012 Jean Brefort (jean brefort normalesup org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include <goffice/goffice.h>
+
+/* This code was copied from telepathy/telepathy-gabble/tree/src/util.c.
+ * Original copyright is:
+ *
+ * Copyright (C) 2006-2007 Collabora Ltd.
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * @author Robert McQueen <robert mcqueen collabora co uk>
+ * @author Simon McVittie <simon mcvittie collabora co uk>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * go_uuid:
+ *
+ * RFC4122 version 4 compliant random UUIDs generator.
+ *
+ * Returns: (transfer full): A string with RFC41122 version 4 random UUID,
+ * must be freed with _free().
+ **/
+char *
+go_uuid (void)
+{
+ GRand *grand;
+ gchar *str;
+ struct {
+ guint32 time_low;
+ guint16 time_mid;
+ guint16 time_hi_and_version;
+ guint8 clock_seq_hi_and_rsv;
+ guint8 clock_seq_low;
+ guint16 node_hi;
+ guint32 node_low;
+ } uuid;
+
+ /* Fill with random. Every new GRand are seede with 128 bit read from
+ * /dev/urandom (or the current time on non-unix systems). This makes the
+ * random source good enough for our usage, but may not be suitable for all
+ * situation outside Gabble. */
+ grand = g_rand_new ();
+ uuid.time_low = g_rand_int (grand);
+ uuid.time_mid = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.time_hi_and_version = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.clock_seq_hi_and_rsv = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8);
+ uuid.clock_seq_low = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8);
+ uuid.node_hi = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16);
+ uuid.node_low = g_rand_int (grand);
+ g_rand_free (grand);
+
+ /* Set the two most significant bits (bits 6 and 7) of the
+ * clock_seq_hi_and_rsv to zero and one, respectively. */
+ uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
+
+ /* Set the four most significant bits (bits 12 through 15) of the
+ * time_hi_and_version field to 4 */
+ uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
+
+ str = g_strdup_printf ("%08x-%04x-%04x-%02x%02x-%04x%08x",
+ uuid.time_low,
+ uuid.time_mid,
+ uuid.time_hi_and_version,
+ uuid.clock_seq_hi_and_rsv,
+ uuid.clock_seq_low,
+ uuid.node_hi,
+ uuid.node_low);
+
+ return str;
+}
diff --git a/goffice/utils/goffice-utils.h b/goffice/utils/goffice-utils.h
index 3fd313b..531326f 100644
--- a/goffice/utils/goffice-utils.h
+++ b/goffice/utils/goffice-utils.h
@@ -165,4 +165,6 @@ G_END_DECLS
#include <goffice/utils/go-units.h>
#include <goffice/utils/regutf8.h>
+char *go_uuid (void);
+
#endif /* GOFFICE_UTILS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]