#include <glib/gi18n.h>
#include "viking.h"
-#include "util.h"
-#include "curl_download.h"
#include "vikgotoxmltool.h"
-static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass );
-static void vik_goto_xml_tool_init ( VikGotoXmlTool *vwd );
+static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass );
+static void _goto_xml_tool_init ( VikGotoXmlTool *self );
-static void vik_goto_xml_tool_finalize ( GObject *gob );
+static void _goto_xml_tool_finalize ( GObject *gob );
-static int vik_goto_xml_tool_get_coord ( VikGotoTool *self, VikWindow *vw, VikViewport *vvp, gchar *srch_str, VikCoord *coord );
+static gchar *_goto_xml_tool_get_url_format ( VikGotoTool *self );
+static gboolean _goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct LatLon *ll);
typedef struct _VikGotoXmlToolPrivate VikGotoXmlToolPrivate;
{
gchar *url_format;
gchar *lat_path;
+ gchar *lat_attr;
gchar *lon_path;
+ gchar *lon_attr;
struct LatLon ll;
};
sizeof (VikGotoXmlToolClass),
NULL, /* base_init */
NULL, /* base_finalize */
- (GClassInitFunc) vik_goto_xml_tool_class_init,
+ (GClassInitFunc) _goto_xml_tool_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (VikGotoXmlTool),
0,
- (GInstanceInitFunc) vik_goto_xml_tool_init,
+ (GInstanceInitFunc) _goto_xml_tool_init,
};
w_type = g_type_register_static ( VIK_GOTO_TOOL_TYPE, "VikGotoXmlTool", &w_info, 0 );
}
PROP_URL_FORMAT,
PROP_LAT_PATH,
+ PROP_LAT_ATTR,
PROP_LON_PATH,
+ PROP_LON_ATTR,
};
static void
-xml_goto_tool_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+_goto_xml_tool_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
+ gchar **splitted = NULL;
switch (property_id)
{
break;
case PROP_LAT_PATH:
+ splitted = g_strsplit (g_value_get_string (value), "@", 2);
g_free (priv->lat_path);
- priv->lat_path = g_value_dup_string (value);
+ priv->lat_path = splitted[0];
+ if (splitted[1])
+ {
+ g_object_set (object, "lat-attr", splitted[1], NULL);
+ g_free (splitted[1]);
+ }
+ /* only free the tab, not the strings */
+ g_free (splitted);
+ splitted = NULL;
+ break;
+
+ case PROP_LAT_ATTR:
+ /* Avoid to overwrite XPATH value */
+ /* NB: This disable future overwriting,
+ but as property is CONSTRUCT_ONLY there is no matter */
+ if (!priv->lat_attr || g_value_get_string (value))
+ {
+ g_free (priv->lat_attr);
+ priv->lat_attr = g_value_dup_string (value);
+ }
break;
case PROP_LON_PATH:
+ splitted = g_strsplit (g_value_get_string (value), "@", 2);
g_free (priv->lon_path);
- priv->lon_path = g_value_dup_string (value);
+ priv->lon_path = splitted[0];
+ if (splitted[1])
+ {
+ g_object_set (object, "lon-attr", splitted[1], NULL);
+ g_free (splitted[1]);
+ }
+ /* only free the tab, not the strings */
+ g_free (splitted);
+ splitted = NULL;
+ break;
+
+ case PROP_LON_ATTR:
+ /* Avoid to overwrite XPATH value */
+ /* NB: This disable future overwriting,
+ but as property is CONSTRUCT_ONLY there is no matter */
+ if (!priv->lon_attr || g_value_get_string (value))
+ {
+ g_free (priv->lon_attr);
+ priv->lon_attr = g_value_dup_string (value);
+ }
break;
default:
}
static void
-xml_goto_tool_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+_goto_xml_tool_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
g_value_set_string (value, priv->lat_path);
break;
+ case PROP_LAT_ATTR:
+ g_value_set_string (value, priv->lat_attr);
+ break;
+
case PROP_LON_PATH:
g_value_set_string (value, priv->lon_path);
break;
+ case PROP_LON_ATTR:
+ g_value_set_string (value, priv->lon_attr);
+ break;
+
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
-static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
+static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
{
GObjectClass *object_class;
VikGotoToolClass *parent_class;
object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = vik_goto_xml_tool_finalize;
- object_class->set_property = xml_goto_tool_set_property;
- object_class->get_property = xml_goto_tool_get_property;
+ object_class->finalize = _goto_xml_tool_finalize;
+ object_class->set_property = _goto_xml_tool_set_property;
+ object_class->get_property = _goto_xml_tool_get_property;
pspec = g_param_spec_string ("url-format",
pspec);
pspec = g_param_spec_string ("lat-path",
- "Lat path",
+ "Latitude path",
"XPath of the latitude",
"<no-set>" /* default value */,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
PROP_LAT_PATH,
pspec);
+ pspec = g_param_spec_string ("lat-attr",
+ "Latitude attribute",
+ "XML attribute of the latitude",
+ NULL /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ PROP_LAT_ATTR,
+ pspec);
+
pspec = g_param_spec_string ("lon-path",
- "Lon path",
+ "Longitude path",
"XPath of the longitude",
"<no-set>" /* default value */,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
PROP_LON_PATH,
pspec);
+ pspec = g_param_spec_string ("lon-attr",
+ "Longitude attribute",
+ "XML attribute of the longitude",
+ NULL /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ PROP_LON_ATTR,
+ pspec);
+
parent_class = VIK_GOTO_TOOL_CLASS (klass);
- parent_class->get_coord = vik_goto_xml_tool_get_coord;
+ parent_class->get_url_format = _goto_xml_tool_get_url_format;
+ parent_class->parse_file_for_latlon = _goto_xml_tool_parse_file_for_latlon;
g_type_class_add_private (klass, sizeof (VikGotoXmlToolPrivate));
}
return VIK_GOTO_XML_TOOL ( g_object_new ( VIK_GOTO_XML_TOOL_TYPE, "label", "Google", NULL ) );
}
-static void vik_goto_xml_tool_init ( VikGotoXmlTool *self )
+static void _goto_xml_tool_init ( VikGotoXmlTool *self )
{
VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
priv->url_format = NULL;
priv->lat_path = NULL;
+ priv->lat_attr = NULL;
priv->lon_path = NULL;
+ priv->lon_attr = NULL;
//
priv->ll.lat = NAN;
priv->ll.lon = NAN;
}
-static void vik_goto_xml_tool_finalize ( GObject *gob )
+static void _goto_xml_tool_finalize ( GObject *gob )
{
G_OBJECT_GET_CLASS(gob)->finalize(gob);
}
return equal;
}
+/* Called for open tags <foo bar="baz"> */
+static void
+_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (user_data);
+ VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
+ const GSList *stack = g_markup_parse_context_get_element_stack (context);
+ /* Longitude */
+ if (priv->lon_attr != NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
+ {
+ int i=0;
+ while (attribute_names[i] != NULL)
+ {
+ if (strcmp (attribute_names[i], priv->lon_attr) == 0)
+ {
+ priv->ll.lon = g_ascii_strtod(attribute_values[i], NULL);
+ }
+ i++;
+ }
+ }
+ /* Latitude */
+ if (priv->lat_attr != NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
+ {
+ int i=0;
+ while (attribute_names[i] != NULL)
+ {
+ if (strcmp (attribute_names[i], priv->lat_attr) == 0)
+ {
+ priv->ll.lat = g_ascii_strtod(attribute_values[i], NULL);
+ }
+ i++;
+ }
+ }
+}
+
/* Called for character data */
/* text is not nul-terminated */
static void
const GSList *stack = g_markup_parse_context_get_element_stack (context);
gchar *textl = g_strndup(text, text_len);
/* Store only first result */
- if (isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
+ if (priv->lat_attr == NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path))
{
priv->ll.lat = g_ascii_strtod(textl, NULL);
}
- if (isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
+ if (priv->lon_attr == NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path))
{
priv->ll.lon = g_ascii_strtod(textl, NULL);
}
}
static gboolean
-parse_file_for_latlon(VikGotoXmlTool *self, gchar *filename, struct LatLon *ll)
+_goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct LatLon *ll)
{
GMarkupParser xml_parser;
- GMarkupParseContext *xml_context;
- GError *error;
+ GMarkupParseContext *xml_context = NULL;
+ GError *error = NULL;
VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
+ g_return_val_if_fail(priv != NULL, FALSE);
+
+ g_debug ("%s: %s@%s, %s@%s",
+ __FUNCTION__,
+ priv->lat_path, priv->lat_attr,
+ priv->lon_path, priv->lon_attr);
FILE *file = g_fopen (filename, "r");
if (file == NULL)
return FALSE;
/* setup context parse (ie callbacks) */
- xml_parser.start_element = NULL;
+ if (priv->lat_attr != NULL || priv->lon_attr != NULL)
+ // At least one coordinate uses an attribute
+ xml_parser.start_element = &_start_element;
+ else
+ xml_parser.start_element = NULL;
xml_parser.end_element = NULL;
- xml_parser.text = &_text;
+ if (priv->lat_attr == NULL || priv->lon_attr == NULL)
+ // At least one coordinate uses a raw element
+ xml_parser.text = &_text;
+ else
+ xml_parser.text = NULL;
xml_parser.passthrough = NULL;
xml_parser.error = NULL;
gchar buff[BUFSIZ];
size_t nb;
- while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
+ while (xml_context &&
+ (nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
{
if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
- fprintf(stderr, "%s: parsing error.\n", __FUNCTION__);
+ {
+ fprintf(stderr, "%s: parsing error: %s.\n",
+ __FUNCTION__, error->message);
+ g_markup_parse_context_free(xml_context);
+ xml_context = NULL;
+ }
+ g_clear_error (&error);
}
/* cleanup */
- if (!g_markup_parse_context_end_parse(xml_context, &error))
- fprintf(stderr, "%s: errors occurred reading file.\n", __FUNCTION__);
+ if (xml_context &&
+ !g_markup_parse_context_end_parse(xml_context, &error))
+ fprintf(stderr, "%s: errors occurred while reading file: %s.\n",
+ __FUNCTION__, error->message);
+ g_clear_error (&error);
- g_markup_parse_context_free(xml_context);
+ if (xml_context)
+ g_markup_parse_context_free(xml_context);
+ xml_context = NULL;
fclose (file);
if (ll != NULL)
return TRUE;
}
-static int vik_goto_xml_tool_get_coord ( VikGotoTool *object, VikWindow *vw, VikViewport *vvp, gchar *srch_str, VikCoord *coord )
+static gchar *
+_goto_xml_tool_get_url_format ( VikGotoTool *self )
{
- FILE *tmp_file;
- int tmp_fd;
- gchar *tmpname;
- gchar *uri;
- gchar *escaped_srch_str;
- int ret = 0; /* OK */
- struct LatLon ll;
-
- g_debug("%s: raw goto: %s", __FUNCTION__, srch_str);
-
- escaped_srch_str = uri_escape(srch_str);
-
- g_debug("%s: escaped goto: %s", __FUNCTION__, escaped_srch_str);
-
- if ((tmp_fd = g_file_open_tmp ("GOTO.XXXXXX", &tmpname, NULL)) == -1) {
- g_critical(_("couldn't open temp file"));
- exit(1);
- }
-
- VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object);
VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self);
-
- tmp_file = fdopen(tmp_fd, "r+");
- uri = g_strdup_printf(priv->url_format, escaped_srch_str);
-
- /* TODO: curl may not be available */
- if (curl_download_uri(uri, tmp_file, NULL)) { /* error */
- fclose(tmp_file);
- tmp_file = NULL;
- ret = -1;
- goto done;
- }
-
- fclose(tmp_file);
- tmp_file = NULL;
- g_debug("%s: %s", __FILE__, tmpname);
- if (!parse_file_for_latlon(self, tmpname, &ll)) {
- ret = -1;
- goto done;
- }
- vik_coord_load_from_latlon ( coord, vik_viewport_get_coord_mode(vvp), &ll );
-
-done:
- g_free(escaped_srch_str);
- g_free(uri);
- g_remove(tmpname);
- g_free(tmpname);
- return ret;
+ g_return_val_if_fail(priv != NULL, NULL);
+ return priv->url_format;
}