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
);
110 gchar
**splitted
= NULL
;
114 case PROP_URL_FORMAT
:
115 g_free (priv
->url_format
);
116 priv
->url_format
= g_value_dup_string (value
);
120 splitted
= g_strsplit (g_value_get_string (value
), "@", 2);
121 g_free (priv
->lat_path
);
122 priv
->lat_path
= splitted
[0];
125 g_object_set (object
, "lat-attr", splitted
[1], NULL
);
126 g_free (splitted
[1]);
128 /* only free the tab, not the strings */
134 /* Avoid to overwrite XPATH value */
135 /* NB: This disable future overwriting,
136 but as property is CONSTRUCT_ONLY there is no matter */
137 if (!priv
->lat_attr
|| g_value_get_string (value
))
139 g_free (priv
->lat_attr
);
140 priv
->lat_attr
= g_value_dup_string (value
);
145 splitted
= g_strsplit (g_value_get_string (value
), "@", 2);
146 g_free (priv
->lon_path
);
147 priv
->lon_path
= splitted
[0];
150 g_object_set (object
, "lon-attr", splitted
[1], NULL
);
151 g_free (splitted
[1]);
153 /* only free the tab, not the strings */
159 /* Avoid to overwrite XPATH value */
160 /* NB: This disable future overwriting,
161 but as property is CONSTRUCT_ONLY there is no matter */
162 if (!priv
->lon_attr
|| g_value_get_string (value
))
164 g_free (priv
->lon_attr
);
165 priv
->lon_attr
= g_value_dup_string (value
);
170 /* We don't have any other property... */
171 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
177 _goto_xml_tool_get_property (GObject
*object
,
182 VikGotoXmlTool
*self
= VIK_GOTO_XML_TOOL (object
);
183 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
187 case PROP_URL_FORMAT
:
188 g_value_set_string (value
, priv
->url_format
);
192 g_value_set_string (value
, priv
->lat_path
);
196 g_value_set_string (value
, priv
->lat_attr
);
200 g_value_set_string (value
, priv
->lon_path
);
204 g_value_set_string (value
, priv
->lon_attr
);
208 /* We don't have any other property... */
209 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
214 static void _goto_xml_tool_class_init ( VikGotoXmlToolClass
*klass
)
216 GObjectClass
*object_class
;
217 VikGotoToolClass
*parent_class
;
220 object_class
= G_OBJECT_CLASS (klass
);
222 object_class
->finalize
= _goto_xml_tool_finalize
;
223 object_class
->set_property
= _goto_xml_tool_set_property
;
224 object_class
->get_property
= _goto_xml_tool_get_property
;
227 pspec
= g_param_spec_string ("url-format",
229 "The format of the URL",
230 "<no-set>" /* default value */,
231 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
);
232 g_object_class_install_property (object_class
,
236 pspec
= g_param_spec_string ("lat-path",
238 "XPath of the latitude",
239 "<no-set>" /* default value */,
240 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
);
241 g_object_class_install_property (object_class
,
245 pspec
= g_param_spec_string ("lat-attr",
246 "Latitude attribute",
247 "XML attribute of the latitude",
248 NULL
/* default value */,
249 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
);
250 g_object_class_install_property (object_class
,
254 pspec
= g_param_spec_string ("lon-path",
256 "XPath of the longitude",
257 "<no-set>" /* default value */,
258 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
);
259 g_object_class_install_property (object_class
,
263 pspec
= g_param_spec_string ("lon-attr",
264 "Longitude attribute",
265 "XML attribute of the longitude",
266 NULL
/* default value */,
267 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
);
268 g_object_class_install_property (object_class
,
272 parent_class
= VIK_GOTO_TOOL_CLASS (klass
);
274 parent_class
->get_url_format
= _goto_xml_tool_get_url_format
;
275 parent_class
->parse_file_for_latlon
= _goto_xml_tool_parse_file_for_latlon
;
277 g_type_class_add_private (klass
, sizeof (VikGotoXmlToolPrivate
));
280 VikGotoXmlTool
*vik_goto_xml_tool_new ()
282 return VIK_GOTO_XML_TOOL ( g_object_new ( VIK_GOTO_XML_TOOL_TYPE
, "label", "Google", NULL
) );
285 static void _goto_xml_tool_init ( VikGotoXmlTool
*self
)
287 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
288 priv
->url_format
= NULL
;
289 priv
->lat_path
= NULL
;
290 priv
->lat_attr
= NULL
;
291 priv
->lon_path
= NULL
;
292 priv
->lon_attr
= NULL
;
298 static void _goto_xml_tool_finalize ( GObject
*gob
)
300 G_OBJECT_GET_CLASS(gob
)->finalize(gob
);
304 stack_is_path (const GSList
*stack
,
307 gboolean equal
= TRUE
;
308 int stack_len
= g_list_length((GList
*)stack
);
311 while (equal
== TRUE
&& i
>= 0)
317 const gchar
*current
= g_list_nth_data((GList
*)stack
, i
);
318 size_t len
= strlen(current
);
319 if (strncmp(path
, current
, len
) != 0 )
332 /* Called for open tags <foo bar="baz"> */
334 _start_element (GMarkupParseContext
*context
,
335 const gchar
*element_name
,
336 const gchar
**attribute_names
,
337 const gchar
**attribute_values
,
341 VikGotoXmlTool
*self
= VIK_GOTO_XML_TOOL (user_data
);
342 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
343 const GSList
*stack
= g_markup_parse_context_get_element_stack (context
);
345 if (priv
->lon_attr
!= NULL
&& isnan(priv
->ll
.lon
) && stack_is_path (stack
, priv
->lon_path
))
348 while (attribute_names
[i
] != NULL
)
350 if (strcmp (attribute_names
[i
], priv
->lon_attr
) == 0)
352 priv
->ll
.lon
= g_ascii_strtod(attribute_values
[i
], NULL
);
358 if (priv
->lat_attr
!= NULL
&& isnan(priv
->ll
.lat
) && stack_is_path (stack
, priv
->lat_path
))
361 while (attribute_names
[i
] != NULL
)
363 if (strcmp (attribute_names
[i
], priv
->lat_attr
) == 0)
365 priv
->ll
.lat
= g_ascii_strtod(attribute_values
[i
], NULL
);
372 /* Called for character data */
373 /* text is not nul-terminated */
375 _text (GMarkupParseContext
*context
,
381 VikGotoXmlTool
*self
= VIK_GOTO_XML_TOOL (user_data
);
382 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
383 const GSList
*stack
= g_markup_parse_context_get_element_stack (context
);
384 gchar
*textl
= g_strndup(text
, text_len
);
385 /* Store only first result */
386 if (priv
->lat_attr
== NULL
&& isnan(priv
->ll
.lat
) && stack_is_path (stack
, priv
->lat_path
))
388 priv
->ll
.lat
= g_ascii_strtod(textl
, NULL
);
390 if (priv
->lon_attr
== NULL
&& isnan(priv
->ll
.lon
) && stack_is_path (stack
, priv
->lon_path
))
392 priv
->ll
.lon
= g_ascii_strtod(textl
, NULL
);
398 _goto_xml_tool_parse_file_for_latlon(VikGotoTool
*self
, gchar
*filename
, struct LatLon
*ll
)
400 GMarkupParser xml_parser
;
401 GMarkupParseContext
*xml_context
;
403 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
404 g_return_val_if_fail(priv
!= NULL
, FALSE
);
406 g_debug ("%s: %s@%s, %s@%s",
408 priv
->lat_path
, priv
->lat_attr
,
409 priv
->lon_path
, priv
->lon_attr
);
411 FILE *file
= g_fopen (filename
, "r");
413 /* TODO emit warning */
416 /* setup context parse (ie callbacks) */
417 if (priv
->lat_attr
!= NULL
|| priv
->lon_attr
!= NULL
)
418 // At least one coordinate uses an attribute
419 xml_parser
.start_element
= &_start_element
;
421 xml_parser
.start_element
= NULL
;
422 xml_parser
.end_element
= NULL
;
423 if (priv
->lat_attr
== NULL
|| priv
->lon_attr
== NULL
)
424 // At least one coordinate uses a raw element
425 xml_parser
.text
= &_text
;
427 xml_parser
.text
= NULL
;
428 xml_parser
.passthrough
= NULL
;
429 xml_parser
.error
= NULL
;
431 xml_context
= g_markup_parse_context_new(&xml_parser
, 0, self
, NULL
);
439 while ((nb
= fread (buff
, sizeof(gchar
), BUFSIZ
, file
)) > 0)
441 if (!g_markup_parse_context_parse(xml_context
, buff
, nb
, &error
))
442 fprintf(stderr
, "%s: parsing error.\n", __FUNCTION__
);
445 if (!g_markup_parse_context_end_parse(xml_context
, &error
))
446 fprintf(stderr
, "%s: errors occurred reading file.\n", __FUNCTION__
);
448 g_markup_parse_context_free(xml_context
);
456 if (isnan(priv
->ll
.lat
) || isnan(priv
->ll
.lat
))
457 /* At least one coordinate not found */
464 _goto_xml_tool_get_url_format ( VikGotoTool
*self
)
466 VikGotoXmlToolPrivate
*priv
= GOTO_XML_TOOL_GET_PRIVATE (self
);
467 g_return_val_if_fail(priv
!= NULL
, NULL
);
468 return priv
->url_format
;