[geocode-glib/gnome-maps: 8/9] lib: Report accuracy of IP-based location search result



commit 7d2851a2e662a901ae45c3993022635b7a2b7d13
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Sun Mar 24 03:01:11 2013 +0200

    lib: Report accuracy of IP-based location search result
    
    https://bugzilla.gnome.org/show_bug.cgi?id=696527

 geocode-glib/geocode-glib.symbols |    1 +
 geocode-glib/geocode-ipclient.c   |   70 +++++++++++++++++++++++++++++++++----
 geocode-glib/geocode-ipclient.h   |   30 +++++++++++++---
 geocode-glib/test-geoip.c         |    7 +++-
 4 files changed, 94 insertions(+), 14 deletions(-)
---
diff --git a/geocode-glib/geocode-glib.symbols b/geocode-glib/geocode-glib.symbols
index 9dfb37e..b6b62df 100644
--- a/geocode-glib/geocode-glib.symbols
+++ b/geocode-glib/geocode-glib.symbols
@@ -4,6 +4,7 @@ geocode_location_new_with_description
 geocode_location_free
 geocode_location_get_distance_from
 geocode_location_set_description
+geocode_location_accuracy_get_type
 geocode_forward_get_type
 geocode_forward_new_for_string
 geocode_forward_new_for_params
diff --git a/geocode-glib/geocode-ipclient.c b/geocode-glib/geocode-ipclient.c
index d2704dc..3ec071e 100644
--- a/geocode-glib/geocode-ipclient.c
+++ b/geocode-glib/geocode-ipclient.c
@@ -26,6 +26,7 @@
 #include <json-glib/json-glib.h>
 #include "geocode-ipclient.h"
 #include "geocode-error.h"
+#include "geocode-enum-types.h"
 #include "geocode-ip-server/geoip-server.h"
 
 /**
@@ -315,8 +316,56 @@ parse_server_error (JsonObject *object, GError **error) {
         return TRUE;
 }
 
+/* Modified copy of gvir_config_genum_get_value from libvirt-glib */
+static int
+get_enum_value_by_nick (GType       enum_type,
+                        const char *nick,
+                        gint        default_value)
+{
+        GEnumClass *enum_class;
+        GEnumValue *enum_value;
+
+        g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), default_value);
+        g_return_val_if_fail (nick != NULL, default_value);
+
+        enum_class = g_type_class_ref (enum_type);
+        enum_value = g_enum_get_value_by_nick (enum_class, nick);
+        g_type_class_unref (enum_class);
+
+        if (enum_value != NULL)
+                return enum_value->value;
+
+        g_return_val_if_reached (default_value);
+}
+
+static GeocodeLocationAccuracy
+get_accuracy_from_json_location (JsonObject *object)
+{
+        if (json_object_has_member (object, "accuracy")) {
+                const char *str;
+
+                str = json_object_get_string_member (object, "accuracy");
+                return get_enum_value_by_nick (GEOCODE_TYPE_LOCATION_ACCURACY,
+                                               str,
+                                               GEOCODE_LOCATION_ACCURACY_UNKNOWN);
+        } else if (json_object_has_member (object, "street"))
+                return GEOCODE_LOCATION_ACCURACY_STREET;
+        else if (json_object_has_member (object, "city"))
+                return GEOCODE_LOCATION_ACCURACY_CITY;
+        else if (json_object_has_member (object, "region_name"))
+                return GEOCODE_LOCATION_ACCURACY_REGION;
+        else if (json_object_has_member (object, "country_name"))
+                return GEOCODE_LOCATION_ACCURACY_COUNTRY;
+        else if (json_object_has_member (object, "continent"))
+                return GEOCODE_LOCATION_ACCURACY_CONTINENT;
+        else
+                return GEOCODE_LOCATION_ACCURACY_UNKNOWN;
+}
+
 static GeocodeLocation *
-json_to_location (const char *json, GError **error) {
+json_to_location (const char              *json,
+                  GeocodeLocationAccuracy *accuracy,
+                  GError                 **error) {
         JsonParser *parser;
         JsonNode *node;
         JsonObject *object;
@@ -356,6 +405,9 @@ json_to_location (const char *json, GError **error) {
             g_free (desc);
         }
 
+        if (accuracy != NULL)
+                *accuracy = get_accuracy_from_json_location (object);
+
         g_object_unref (parser);
 
         return location;
@@ -365,6 +417,7 @@ json_to_location (const char *json, GError **error) {
  * geocode_ipclient_search_finish:
  * @ipclient: a #GeocodeIpclient representing a query
  * @res: a #GAsyncResult
+ * @accuracy: (out): place-holder for accuracy of the returned location or %NULL
  * @error: a #GError
  *
  * Finishes a geolocation search operation. See geocode_ipclient_search_async().
@@ -373,9 +426,10 @@ json_to_location (const char *json, GError **error) {
  * errors. Free the returned object with g_object_unref() when done.
  **/
 GeocodeLocation *
-geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
-                                GAsyncResult    *res,
-                                GError          **error)
+geocode_ipclient_search_finish (GeocodeIpclient         *ipclient,
+                                GAsyncResult            *res,
+                                GeocodeLocationAccuracy *accuracy,
+                                GError                 **error)
 {
         GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
         char *contents = NULL;
@@ -389,7 +443,7 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
                 return NULL;
 
         contents = g_simple_async_result_get_op_res_gpointer (simple);
-        location = json_to_location (contents, error);
+        location = json_to_location (contents, accuracy, error);
         g_free (contents);
 
         return location;
@@ -398,6 +452,7 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
 /**
  * geocode_ipclient_search:
  * @ipclient: a #GeocodeIpclient representing a query
+ * @accuracy: (out): place-holder for accuracy of the returned location or %NULL
  * @error: a #GError
  *
  * Gets the geolocation data for an IP address from the server.
@@ -406,7 +461,8 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
  * errors. Free the returned object with g_object_unref() when done.
  **/
 GeocodeLocation *
-geocode_ipclient_search (GeocodeIpclient        *ipclient,
+geocode_ipclient_search (GeocodeIpclient         *ipclient,
+                         GeocodeLocationAccuracy *accuracy,
                          GError                 **error)
 {
         char *contents;
@@ -431,7 +487,7 @@ geocode_ipclient_search (GeocodeIpclient        *ipclient,
         }
         g_object_unref (query);
 
-        location = json_to_location (contents, error);
+        location = json_to_location (contents, accuracy, error);
         g_free (contents);
 
         return location;
diff --git a/geocode-glib/geocode-ipclient.h b/geocode-glib/geocode-ipclient.h
index 7bd26da..b21d304 100644
--- a/geocode-glib/geocode-ipclient.h
+++ b/geocode-glib/geocode-ipclient.h
@@ -63,6 +63,24 @@ struct _GeocodeIpclientClass {
         GObjectClass parent_class;
 };
 
+/**
+ * GeocodeLocationAccuracy:
+ * GEOCODE_LOCATION_ACCURACY_UNKNOWN: accuracy is unknown.
+ * GEOCODE_LOCATION_ACCURACY_STREET: Street-level accuracy.
+ * GEOCODE_LOCATION_ACCURACY_CITY: City-level accuracy.
+ * GEOCODE_LOCATION_ACCURACY_REGION: Region-level accuracy.
+ * GEOCODE_LOCATION_ACCURACY_COUNTRY: Country-level accuracy.
+ * GEOCODE_LOCATION_ACCURACY_CONTINENT: Continent-level accuracy.
+ **/
+typedef enum {
+        GEOCODE_LOCATION_ACCURACY_UNKNOWN = -1,
+        GEOCODE_LOCATION_ACCURACY_STREET,
+        GEOCODE_LOCATION_ACCURACY_CITY,
+        GEOCODE_LOCATION_ACCURACY_REGION,
+        GEOCODE_LOCATION_ACCURACY_COUNTRY,
+        GEOCODE_LOCATION_ACCURACY_CONTINENT
+} GeocodeLocationAccuracy;
+
 GeocodeIpclient *geocode_ipclient_new           (void);
 GeocodeIpclient *geocode_ipclient_new_for_ip    (const char *str);
 
@@ -72,12 +90,14 @@ void geocode_ipclient_search_async  (GeocodeIpclient       *ipclient,
                                      GAsyncReadyCallback    callback,
                                      gpointer               user_data);
 
-GeocodeLocation *geocode_ipclient_search_finish (GeocodeIpclient   *ipclient,
-                                                 GAsyncResult      *res,
-                                                 GError            **error);
+GeocodeLocation *geocode_ipclient_search_finish (GeocodeIpclient         *ipclient,
+                                                 GAsyncResult            *res,
+                                                 GeocodeLocationAccuracy *accuracy,
+                                                 GError                 **error);
 
-GeocodeLocation *geocode_ipclient_search (GeocodeIpclient *ipclient,
-                                          GError          **error);
+GeocodeLocation *geocode_ipclient_search (GeocodeIpclient         *ipclient,
+                                          GeocodeLocationAccuracy *accuracy,
+                                          GError                 **error);
 
 G_END_DECLS
 
diff --git a/geocode-glib/test-geoip.c b/geocode-glib/test-geoip.c
index 895e643..4b5902d 100644
--- a/geocode-glib/test-geoip.c
+++ b/geocode-glib/test-geoip.c
@@ -24,13 +24,14 @@ test_search (gconstpointer data)
         GError *error = NULL;
         GeocodeLocation *location;
         TestData *test_data = (TestData *) data;
+        GeocodeLocationAccuracy accuracy = GEOCODE_LOCATION_ACCURACY_UNKNOWN;
 
         if (test_data->ip)
                 ipclient = geocode_ipclient_new_for_ip (test_data->ip);
         else {
                 ipclient = geocode_ipclient_new ();
         }
-        location = geocode_ipclient_search (ipclient, &error);
+        location = geocode_ipclient_search (ipclient, &accuracy, &error);
         if (!location) {
                 g_warning ("Failed at getting the geolocation information: %s", error->message);
                 g_error_free (error);
@@ -40,6 +41,7 @@ test_search (gconstpointer data)
         g_assert (location->longitude == test_data->expected_longitude);
         g_assert (location->description != NULL &&
                   strcmp(location->description, test_data->expected_description) == 0);
+        g_assert (accuracy != GEOCODE_LOCATION_ACCURACY_UNKNOWN);
         geocode_location_free (location);
         g_object_unref (ipclient);
 }
@@ -52,8 +54,9 @@ print_geolocation_info_cb (GObject          *source_object,
         GeocodeIpclient *object = (GeocodeIpclient *) source_object;
         GError *error = NULL;
         GeocodeLocation *location;
+        GeocodeLocationAccuracy accuracy = GEOCODE_LOCATION_ACCURACY_UNKNOWN;
 
-        location = geocode_ipclient_search_finish (object, res, &error);
+        location = geocode_ipclient_search_finish (object, res, &accuracy, &error);
         if (location == NULL) {
                 g_message ("Failed to search the geolocation info: %s", error->message);
                 g_error_free (error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]