2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 * Copyright (C) 2009, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Created by Quy Tonthat <qtonthat@gmail.com>
33 #include <glib/gstdio.h>
34 #include <glib/gprintf.h>
35 #include <glib/gi18n.h>
39 #include "vikgotoxmltool.h"
42 static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass );
43 static void _goto_xml_tool_init ( VikGotoXmlTool *self );
45 static void _goto_xml_tool_finalize ( GObject *gob );
47 static gchar *_goto_xml_tool_get_url_format ( VikGotoTool *self );
48 static gboolean _goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct LatLon *ll);
50 typedef struct _VikGotoXmlToolPrivate VikGotoXmlToolPrivate;
52 struct _VikGotoXmlToolPrivate
63 #define GOTO_XML_TOOL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
64 VIK_GOTO_XML_TOOL_TYPE, \
65 VikGotoXmlToolPrivate))
67 GType vik_goto_xml_tool_get_type()
69 static GType w_type = 0;
73 static const GTypeInfo w_info =
75 sizeof (VikGotoXmlToolClass),
77 NULL, /* base_finalize */
78 (GClassInitFunc) _goto_xml_tool_class_init,
79 NULL, /* class_finalize */
80 NULL, /* class_data */
81 sizeof (VikGotoXmlTool),
83 (GInstanceInitFunc) _goto_xml_tool_init,
85 w_type = g_type_register_static ( VIK_GOTO_TOOL_TYPE, "VikGotoXmlTool", &w_info, 0 );
103 _goto_xml_tool_set_property (GObject *object,
108 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
109 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
113 case PROP_URL_FORMAT:
114 g_free (priv->url_format);
115 priv->url_format = g_value_dup_string (value);
119 g_free (priv->lat_path);
120 priv->lat_path = g_value_dup_string (value);
124 g_free (priv->lat_attr);
125 priv->lat_attr = g_value_dup_string (value);
129 g_free (priv->lon_path);
130 priv->lon_path = g_value_dup_string (value);
134 g_free (priv->lon_attr);
135 priv->lon_attr = g_value_dup_string (value);
139 /* We don't have any other property... */
140 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
146 _goto_xml_tool_get_property (GObject *object,
151 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
152 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
156 case PROP_URL_FORMAT:
157 g_value_set_string (value, priv->url_format);
161 g_value_set_string (value, priv->lat_path);
165 g_value_set_string (value, priv->lat_attr);
169 g_value_set_string (value, priv->lon_path);
173 g_value_set_string (value, priv->lon_attr);
177 /* We don't have any other property... */
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
183 static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
185 GObjectClass *object_class;
186 VikGotoToolClass *parent_class;
189 object_class = G_OBJECT_CLASS (klass);
191 object_class->finalize = _goto_xml_tool_finalize;
192 object_class->set_property = _goto_xml_tool_set_property;
193 object_class->get_property = _goto_xml_tool_get_property;
196 pspec = g_param_spec_string ("url-format",
198 "The format of the URL",
199 "<no-set>" /* default value */,
200 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
201 g_object_class_install_property (object_class,
205 pspec = g_param_spec_string ("lat-path",
207 "XPath of the latitude",
208 "<no-set>" /* default value */,
209 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
210 g_object_class_install_property (object_class,
214 pspec = g_param_spec_string ("lat-attr",
215 "Latitude attribute",
216 "XML attribute of the latitude",
217 NULL /* default value */,
218 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
219 g_object_class_install_property (object_class,
223 pspec = g_param_spec_string ("lon-path",
225 "XPath of the longitude",
226 "<no-set>" /* default value */,
227 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
228 g_object_class_install_property (object_class,
232 pspec = g_param_spec_string ("lon-attr",
233 "Longitude attribute",
234 "XML attribute of the longitude",
235 NULL /* default value */,
236 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
237 g_object_class_install_property (object_class,
241 parent_class = VIK_GOTO_TOOL_CLASS (klass);
243 parent_class->get_url_format = _goto_xml_tool_get_url_format;
244 parent_class->parse_file_for_latlon = _goto_xml_tool_parse_file_for_latlon;
246 g_type_class_add_private (klass, sizeof (VikGotoXmlToolPrivate));
249 VikGotoXmlTool *vik_goto_xml_tool_new ()
251 return VIK_GOTO_XML_TOOL ( g_object_new ( VIK_GOTO_XML_TOOL_TYPE, "label", "Google", NULL ) );
254 static void _goto_xml_tool_init ( VikGotoXmlTool *self )
256 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
257 priv->url_format = NULL;
258 priv->lat_path = NULL;
259 priv->lat_attr = NULL;
260 priv->lon_path = NULL;
261 priv->lon_attr = NULL;
267 static void _goto_xml_tool_finalize ( GObject *gob )
269 G_OBJECT_GET_CLASS(gob)->finalize(gob);
273 stack_is_path (const GSList *stack,
276 gboolean equal = TRUE;
277 int stack_len = g_list_length((GList *)stack);
280 while (equal == TRUE && i >= 0)
286 const gchar *current = g_list_nth_data((GList *)stack, i);
287 size_t len = strlen(current);
288 if (strncmp(path, current, len) != 0 )
301 /* Called for open tags <foo bar="baz"> */
303 _start_element (GMarkupParseContext *context,
304 const gchar *element_name,
305 const gchar **attribute_names,
306 const gchar **attribute_values,
310 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (user_data);
311 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
312 const GSList *stack = g_markup_parse_context_get_element_stack (context);
314 if (priv->lon_attr != NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
317 while (attribute_names[i] != NULL)
319 if (strcmp (attribute_names[i], priv->lon_attr) == 0)
321 priv->ll.lon = g_ascii_strtod(attribute_values[i], NULL);
327 if (priv->lat_attr != NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
330 while (attribute_names[i] != NULL)
332 if (strcmp (attribute_names[i], priv->lat_attr) == 0)
334 priv->ll.lat = g_ascii_strtod(attribute_values[i], NULL);
341 /* Called for character data */
342 /* text is not nul-terminated */
344 _text (GMarkupParseContext *context,
350 VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (user_data);
351 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
352 const GSList *stack = g_markup_parse_context_get_element_stack (context);
353 gchar *textl = g_strndup(text, text_len);
354 /* Store only first result */
355 if (priv->lat_attr == NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
357 priv->ll.lat = g_ascii_strtod(textl, NULL);
359 if (priv->lon_attr == NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
361 priv->ll.lon = g_ascii_strtod(textl, NULL);
367 _goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct LatLon *ll)
369 GMarkupParser xml_parser;
370 GMarkupParseContext *xml_context;
372 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
373 g_return_val_if_fail(priv != NULL, FALSE);
375 FILE *file = g_fopen (filename, "r");
377 /* TODO emit warning */
380 /* setup context parse (ie callbacks) */
381 if (priv->lat_attr != NULL || priv->lon_attr != NULL)
382 // At least one coordinate uses an attribute
383 xml_parser.start_element = &_start_element;
385 xml_parser.start_element = NULL;
386 xml_parser.end_element = NULL;
387 if (priv->lat_attr == NULL || priv->lon_attr == NULL)
388 // At least one coordinate uses a raw element
389 xml_parser.text = &_text;
391 xml_parser.text = NULL;
392 xml_parser.passthrough = NULL;
393 xml_parser.error = NULL;
395 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
403 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
405 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
406 fprintf(stderr, "%s: parsing error.\n", __FUNCTION__);
409 if (!g_markup_parse_context_end_parse(xml_context, &error))
410 fprintf(stderr, "%s: errors occurred reading file.\n", __FUNCTION__);
412 g_markup_parse_context_free(xml_context);
420 if (isnan(priv->ll.lat) || isnan(priv->ll.lat))
421 /* At least one coordinate not found */
428 _goto_xml_tool_get_url_format ( VikGotoTool *self )
430 VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
431 g_return_val_if_fail(priv != NULL, NULL);
432 return priv->url_format;