]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikgotoxmltool.c
gtk_object_sink has been deprecated since gtk version 2.10, use g_object_ref_sink...
[andy/viking.git] / src / vikgotoxmltool.c
index 06767f5810dabac7bd4348f53fb4621e2e398afe..e4db4d66cdfa33e307fd9afdc8099cb6c97475a1 100644 (file)
@@ -18,7 +18,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Created by Quy Tonthat <qtonthat@gmail.com>
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #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;
 
@@ -54,7 +52,9 @@ struct _VikGotoXmlToolPrivate
 {
   gchar *url_format;
   gchar *lat_path;
+  gchar *lat_attr;
   gchar *lon_path;
+  gchar *lon_attr;
   
   struct LatLon ll;
 };
@@ -74,12 +74,12 @@ GType vik_goto_xml_tool_get_type()
       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 );
   }
@@ -93,17 +93,20 @@ enum
 
   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)
     {
@@ -113,13 +116,53 @@ xml_goto_tool_set_property (GObject      *object,
       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:
@@ -130,10 +173,10 @@ xml_goto_tool_set_property (GObject      *object,
 }
 
 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);
@@ -148,10 +191,18 @@ xml_goto_tool_get_property (GObject    *object,
       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);
@@ -159,7 +210,7 @@ xml_goto_tool_get_property (GObject    *object,
     }
 }
 
-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;
@@ -167,9 +218,9 @@ static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
 
   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",
@@ -182,7 +233,7 @@ static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
                                    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);
@@ -190,8 +241,17 @@ static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
                                    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);
@@ -199,9 +259,19 @@ static void vik_goto_xml_tool_class_init ( VikGotoXmlToolClass *klass )
                                    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));
 }
@@ -211,18 +281,20 @@ VikGotoXmlTool *vik_goto_xml_tool_new ()
   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);
 }
@@ -256,6 +328,46 @@ stack_is_path (const GSList *stack,
   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
@@ -270,11 +382,11 @@ _text (GMarkupParseContext *context,
   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);
        }
@@ -282,12 +394,18 @@ _text (GMarkupParseContext *context,
 }
 
 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)
@@ -295,9 +413,17 @@ parse_file_for_latlon(VikGotoXmlTool *self, gchar *filename, struct LatLon *ll)
                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;
        
@@ -309,16 +435,28 @@ parse_file_for_latlon(VikGotoXmlTool *self, gchar *filename, struct LatLon *ll)
        
        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)
@@ -333,54 +471,10 @@ parse_file_for_latlon(VikGotoXmlTool *self, gchar *filename, struct LatLon *ll)
                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;
 }