[network-manager-applet/aleksander/mobile-providers: 17/19] libnm-gtk: new 'NMAMobileProvidersDatabase' object



commit 85c020444e75eeabf24fbc79661c4001f54b7a90
Author: Aleksander Morgado <aleksander lanedo com>
Date:   Tue Nov 27 20:16:03 2012 +0100

    libnm-gtk: new 'NMAMobileProvidersDatabase' object
    
    Instead of returning a GHashTable and exposing utility methods to play with it,
    create a new GObject which provides access to the same logic through new methods
    but which also allows to asynchronously load it.

 src/applet-device-cdma.c            |   16 +-
 src/applet-device-gsm.c             |   22 +-
 src/libnm-gtk/nm-mobile-providers.c |  489 +++++++++++++++++++++++++++++------
 src/libnm-gtk/nm-mobile-providers.h |   59 ++++-
 src/libnm-gtk/nm-mobile-wizard.c    |   24 ++-
 5 files changed, 498 insertions(+), 112 deletions(-)
---
diff --git a/src/applet-device-cdma.c b/src/applet-device-cdma.c
index fb304fe..f9710b0 100644
--- a/src/applet-device-cdma.c
+++ b/src/applet-device-cdma.c
@@ -61,7 +61,7 @@ typedef struct {
 	guint32 sid;
 	gboolean modem_enabled;
 
-	GHashTable *country_infos;
+	NMAMobileProvidersDatabase *mobile_providers_database;
 	char *provider_name;
 
 	guint32 poll_id;
@@ -624,8 +624,8 @@ cdma_device_info_free (gpointer data)
 		dbus_g_connection_unref (info->bus);
 	if (info->poll_id)
 		g_source_remove (info->poll_id);
-	if (info->country_infos)
-		g_hash_table_destroy (info->country_infos);
+	if (info->mobile_providers_database)
+		g_object_unref (info->mobile_providers_database);
 	g_free (info->provider_name);
 	memset (info, 0, sizeof (CdmaDeviceInfo));
 	g_free (info);
@@ -730,12 +730,12 @@ serving_system_reply (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_dat
 
 	if (new_sid && (new_sid != info->sid)) {
 		info->sid = new_sid;
-		if (info->country_infos) {
+		if (info->mobile_providers_database) {
 			NMAMobileProvider *provider;
 
 			g_free (info->provider_name);
 
-			provider = nma_mobile_providers_find_for_cdma_sid (info->country_infos, new_sid);
+			provider = nma_mobile_providers_database_lookup_cdma_sid (info->mobile_providers_database, new_sid);
 			info->provider_name = (provider ?
 			                       g_strdup (nma_mobile_provider_get_name (provider)) :
 			                       NULL);
@@ -915,7 +915,11 @@ cdma_device_added (NMDevice *device, NMApplet *applet)
 	info->bus = bus;
 	info->quality_valid = FALSE;
 
-	info->country_infos = nma_mobile_providers_parse (NULL, NULL);
+	info->mobile_providers_database = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
+	if (!info->mobile_providers_database) {
+		g_warning ("Couldn't read database: %s", error->message);
+		g_clear_error (&error);
+	}
 
 	info->props_proxy = dbus_g_proxy_new_for_name (bus,
 	                                               "org.freedesktop.ModemManager",
diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
index ff841e2..00ab125 100644
--- a/src/applet-device-gsm.c
+++ b/src/applet-device-gsm.c
@@ -88,7 +88,7 @@ typedef struct {
 	guint reg_state;
 	char *op_code;
 	char *op_name;
-	GHashTable *country_infos;
+	NMAMobileProvidersDatabase *mobile_providers_database;
 
 	guint32 poll_id;
 	gboolean skip_reg_poll;
@@ -1061,8 +1061,8 @@ gsm_device_info_free (gpointer data)
 	if (info->keyring_id)
 		gnome_keyring_cancel_request (info->keyring_id);
 
-	if (info->country_infos)
-		g_hash_table_destroy (info->country_infos);
+	if (info->mobile_providers_database)
+		g_object_unref (info->mobile_providers_database);
 
 	if (info->poll_id)
 		g_source_remove (info->poll_id);
@@ -1128,12 +1128,18 @@ parse_op_name (GsmDeviceInfo *info, const char *orig, const char *op_code)
 	 * probably an MCC/MNC.  Look that up.
 	 */
 
-	if (!info->country_infos)
-		info->country_infos = nma_mobile_providers_parse (NULL, NULL);
-	if (!info->country_infos)
-		return strdup (orig);
+	if (!info->mobile_providers_database) {
+		GError *error = NULL;
 
-	provider = nma_mobile_providers_find_for_3gpp_mcc_mnc (info->country_infos, orig);
+		info->mobile_providers_database = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
+		if (!info->mobile_providers_database) {
+			g_warning ("Couldn't read database: %s", error->message);
+			g_error_free (error);
+			return strdup (orig);
+		}
+	}
+
+	provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (info->mobile_providers_database, orig);
 	return (provider ? g_strdup (nma_mobile_provider_get_name (provider)) : NULL);
 }
 
diff --git a/src/libnm-gtk/nm-mobile-providers.c b/src/libnm-gtk/nm-mobile-providers.c
index e825008..947a039 100644
--- a/src/libnm-gtk/nm-mobile-providers.c
+++ b/src/libnm-gtk/nm-mobile-providers.c
@@ -483,11 +483,12 @@ static const GMarkupParser iso_3166_parser = {
 };
 
 static GHashTable *
-read_country_codes (const gchar *country_codes_file)
+read_country_codes (const gchar *country_codes_file,
+                    GCancellable *cancellable,
+                    GError **error)
 {
 	GHashTable *table = NULL;
 	GMarkupParseContext *ctx;
-	GError *error = NULL;
 	char *buf;
 	gsize buf_len;
 
@@ -495,28 +496,29 @@ read_country_codes (const gchar *country_codes_file)
 	bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
 	bind_textdomain_codeset ("iso_3166", "UTF-8");
 
-	if (g_file_get_contents (country_codes_file, &buf, &buf_len, &error)) {
-		table = g_hash_table_new_full (g_str_hash,
-		                               g_str_equal,
-		                               g_free,
-		                               (GDestroyNotify)nma_country_info_unref);
-		ctx = g_markup_parse_context_new (&iso_3166_parser, 0, table, NULL);
-
-		if (!g_markup_parse_context_parse (ctx, buf, buf_len, &error)) {
-			g_warning ("Failed to parse '%s': %s\n", country_codes_file, error->message);
-			g_error_free (error);
-			g_hash_table_destroy (table);
-			table = NULL;
-		}
+	if (!g_file_get_contents (country_codes_file, &buf, &buf_len, error)) {
+		g_prefix_error (error,
+		                "Failed to load '%s' from 'iso-codes': ",
+		                country_codes_file);
+		return NULL;
+	}
 
-		g_markup_parse_context_free (ctx);
-		g_free (buf);
-	} else {
-		g_warning ("Failed to load '%s': %s\n Consider installing 'iso-codes'\n",
-		           country_codes_file, error->message);
-		g_error_free (error);
+	table = g_hash_table_new_full (g_str_hash,
+	                               g_str_equal,
+	                               g_free,
+	                               (GDestroyNotify)nma_country_info_unref);
+
+	ctx = g_markup_parse_context_new (&iso_3166_parser, 0, table, NULL);
+	if (!g_markup_parse_context_parse (ctx, buf, buf_len, error)) {
+		g_prefix_error (error,
+		                "Failed to parse '%s' from 'iso-codes': ",
+		                country_codes_file);
+		g_hash_table_destroy (table);
+		return NULL;
 	}
 
+	g_markup_parse_context_free (ctx);
+	g_free (buf);
 	return table;
 }
 
@@ -904,51 +906,28 @@ static const GMarkupParser mobile_parser = {
 	NULL /* error */
 };
 
-/******************************************************************************/
-/* Parser interface */
-
-/**
- * nma_mobile_providers_parse:
- * @country_codes: (allow-none) File with the list of country codes.
- * @service_providers: (allow-none) File with the list of service providers.
- *
- * Returns: (element-type utf8 NMGtk.CountryInfo) (transfer full): a
- *	 hash table where keys are country names #gchar and values are #NMACountryInfo.
- *	 Everything is destroyed with g_hash_table_destroy().
- */
-GHashTable *
-nma_mobile_providers_parse (const gchar *country_codes,
-                            const gchar *service_providers)
+static gboolean
+read_service_providers (GHashTable *countries,
+                        const gchar *service_providers,
+                        GCancellable *cancellable,
+                        GError **error)
 {
 	GMarkupParseContext *ctx;
 	GIOChannel *channel;
 	MobileParser parser;
-	GError *error = NULL;
 	char buffer[4096];
 	GIOStatus status;
 	gsize len = 0;
 
-	/* Use default paths if none given */
-	if (!country_codes)
-		country_codes = ISO_3166_COUNTRY_CODES;
-	if (!service_providers)
-		service_providers = MOBILE_BROADBAND_PROVIDER_INFO;
-
 	memset (&parser, 0, sizeof (MobileParser));
+    parser.table = countries;
 
-	parser.table = read_country_codes (country_codes);
-	if (!parser.table)
-		goto out;
-
-	channel = g_io_channel_new_file (service_providers, "r", &error);
+	channel = g_io_channel_new_file (service_providers, "r", error);
 	if (!channel) {
-		if (error) {
-			g_warning ("Could not read %s: %s", service_providers, error->message);
-			g_error_free (error);
-		} else
-			g_warning ("Could not read %s: Unknown error", service_providers);
-
-		goto out;
+		g_prefix_error (error,
+		                "Could not read '%s': ",
+		                service_providers);
+		return FALSE;
 	}
 
 	parser.state = PARSER_TOPLEVEL;
@@ -957,26 +936,31 @@ nma_mobile_providers_parse (const gchar *country_codes,
 
 	status = G_IO_STATUS_NORMAL;
 	while (status == G_IO_STATUS_NORMAL) {
-		status = g_io_channel_read_chars (channel, buffer, sizeof (buffer), &len, &error);
+		status = g_io_channel_read_chars (channel, buffer, sizeof (buffer), &len, error);
 
 		switch (status) {
 		case G_IO_STATUS_NORMAL:
-			if (!g_markup_parse_context_parse (ctx, buffer, len, &error)) {
+			if (!g_markup_parse_context_parse (ctx, buffer, len, error)) {
 				status = G_IO_STATUS_ERROR;
-				g_warning ("Error while parsing XML: %s", error->message);
-				g_error_free (error);;
+				g_prefix_error (error,
+				                "Error while parsing XML at '%s': ",
+				                service_providers);
 			}
 			break;
 		case G_IO_STATUS_EOF:
 			break;
 		case G_IO_STATUS_ERROR:
-			g_warning ("Error while reading: %s", error->message);
-			g_error_free (error);
+			g_prefix_error (error,
+			                "Error while reading '%s': ",
+			                service_providers);
 			break;
 		case G_IO_STATUS_AGAIN:
 			/* FIXME: Try again a few times, but really, it never happens, right? */
 			break;
 		}
+
+		if (g_cancellable_set_error_if_cancelled (cancellable, error))
+			status = G_IO_STATUS_ERROR;
 	}
 
 	g_io_channel_unref (channel);
@@ -995,11 +979,43 @@ nma_mobile_providers_parse (const gchar *country_codes,
 	g_free (parser.current_country);
 	g_free (parser.text_buffer);
 
-out:
+	return (status == G_IO_STATUS_EOF);
+}
+
+static GHashTable *
+mobile_providers_parse_sync (const gchar *country_codes,
+                             const gchar *service_providers,
+                             GCancellable *cancellable,
+                             GError **error)
+{
+	GHashTable *countries;
+
+	/* Use default paths if none given */
+	if (!country_codes)
+		country_codes = ISO_3166_COUNTRY_CODES;
+	if (!service_providers)
+		service_providers = MOBILE_BROADBAND_PROVIDER_INFO;
+
+	countries = read_country_codes (country_codes,
+	                                cancellable,
+	                                error);
+	if (!countries)
+		return NULL;
+
+	if (!read_service_providers (countries,
+	                             service_providers,
+	                             cancellable,
+	                             error)) {
+		g_hash_table_unref (countries);
+		return NULL;
+	}
 
-	return parser.table;
+	return countries;
 }
 
+/******************************************************************************/
+/* Dump to stdout contents */
+
 static void
 dump_generic (NMAMobileAccessMethod *method)
 {
@@ -1082,23 +1098,88 @@ dump_country (gpointer key, gpointer value, gpointer user_data)
 	}
 }
 
+/******************************************************************************/
+/* Mobile providers database type */
+
+static void initable_iface_init       (GInitableIface      *iface);
+static void async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (NMAMobileProvidersDatabase, nma_mobile_providers_database, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
+                        G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init))
+
+enum {
+    PROP_0,
+    PROP_COUNTRY_CODES_PATH,
+    PROP_SERVICE_PROVIDERS_PATH,
+    PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
+
+struct _NMAMobileProvidersDatabasePrivate {
+	/* Paths to input files */
+	gchar *country_codes_path;
+	gchar *service_providers_path;
+
+	/* The HT with country code as key and NMACountryInfo as value. */
+	GHashTable *countries;
+};
+
+/**********************************/
+
+/**
+ * nma_mobile_providers_database_get_countries:
+ * @self: a #NMAMobileProvidersDatabase.
+ *
+ * Returns: (element-type utf8 NMGtk.CountryInfo) (transfer none): a
+ *	 hash table where keys are country names #gchar and values are #NMACountryInfos.
+ */
+GHashTable *
+nma_mobile_providers_database_get_countries (NMAMobileProvidersDatabase *self)
+{
+	g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
+
+	return self->priv->countries;
+}
+
+/**
+ * nma_mobile_providers_database_dump:
+ * @self: a #NMAMobileProvidersDatabase.
+ *
+ */
 void
-nma_mobile_providers_dump (GHashTable *country_infos)
+nma_mobile_providers_database_dump (NMAMobileProvidersDatabase *self)
+{
+	g_return_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self));
+
+	g_hash_table_foreach (self->priv->countries, dump_country, NULL);
+}
+
+/**
+ * nma_mobile_providers_database_lookup_country:
+ * @self: a #NMAMobileProvidersDatabase.
+ * @country_code: the country code string to look for.
+ *
+ * Returns: (transfer none): a #NMACountryInfo or %NULL if not found.
+ */
+NMACountryInfo *
+nma_mobile_providers_database_lookup_country (NMAMobileProvidersDatabase *self,
+                                              const gchar *country_code)
 {
-	g_return_if_fail (country_infos != NULL);
-	g_hash_table_foreach (country_infos, dump_country, NULL);
+	return (NMACountryInfo *) g_hash_table_lookup (self->priv->countries, country_code);
 }
 
 /**
- * nma_mobile_providers_find_for_3gpp_mcc_mnc:
- * @country_infos: (element-type utf8 NMGtk.CountryInfo) (transfer none): the table of country infos.
+ * nma_mobile_providers_database_lookup_3gpp_mcc_mnc:
+ * @self: a #NMAMobileProvidersDatabase.
  * @mccmnc: the MCC/MNC string to look for.
  *
- * Returns: (transfer none): a #NMAMobileProvider.
+ * Returns: (transfer none): a #NMAMobileProvider or %NULL if not found.
  */
 NMAMobileProvider *
-nma_mobile_providers_find_for_3gpp_mcc_mnc (GHashTable	*country_infos,
-                                            const gchar *mccmnc)
+nma_mobile_providers_database_lookup_3gpp_mcc_mnc (NMAMobileProvidersDatabase *self,
+                                                   const gchar *mccmnc)
 {
 	GHashTableIter iter;
 	gpointer value;
@@ -1106,6 +1187,7 @@ nma_mobile_providers_find_for_3gpp_mcc_mnc (GHashTable	*country_infos,
 	NMAMobileProvider *provider_match_2mnc = NULL;
 	guint mccmnc_len;
 
+	g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
 	g_return_val_if_fail (mccmnc != NULL, NULL);
 
 	/* Expect only 5 or 6 digit MCCMNC strings */
@@ -1113,7 +1195,7 @@ nma_mobile_providers_find_for_3gpp_mcc_mnc (GHashTable	*country_infos,
 	if (mccmnc_len != 5 && mccmnc_len != 6)
 		return NULL;
 
-	g_hash_table_iter_init (&iter, country_infos);
+	g_hash_table_iter_init (&iter, self->priv->countries);
 	/* Search through each country */
 	while (g_hash_table_iter_next (&iter, NULL, &value)) {
 		NMACountryInfo *country_info = value;
@@ -1185,24 +1267,24 @@ nma_mobile_providers_find_for_3gpp_mcc_mnc (GHashTable	*country_infos,
 }
 
 /**
- * nma_mobile_providers_find_for_cdma_sid:
- * @country_infos: (element-type utf8 NMGtk.CountryInfo) (transfer none): the table of country infos.
+ * nma_mobile_providers_database_lookup_cdma_sid:
+ * @self: a #NMAMobileProvidersDatabase.
  * @sid: the SID to look for.
  *
- * Returns: (transfer none): a #NMAMobileProvider.
+ * Returns: (transfer none): a #NMAMobileProvider, or %NULL if not found.
  */
 NMAMobileProvider *
-nma_mobile_providers_find_for_cdma_sid (GHashTable *country_infos,
-                                        guint32 sid)
+nma_mobile_providers_database_lookup_cdma_sid (NMAMobileProvidersDatabase *self,
+                                               guint32 sid)
 {
 	GHashTableIter iter;
 	gpointer value;
 	GSList *piter;
 
-	if (sid == 0)
-		return NULL;
+	g_return_val_if_fail (NMA_IS_MOBILE_PROVIDERS_DATABASE (self), NULL);
+	g_return_val_if_fail (sid > 0, NULL);
 
-	g_hash_table_iter_init (&iter, country_infos);
+	g_hash_table_iter_init (&iter, self->priv->countries);
 	/* Search through each country */
 	while (g_hash_table_iter_next (&iter, NULL, &value)) {
 		NMACountryInfo *country_info = value;
@@ -1230,6 +1312,253 @@ nma_mobile_providers_find_for_cdma_sid (GHashTable *country_infos,
 	return NULL;
 }
 
+/**********************************/
+
+static gboolean
+initable_init_finish (GAsyncInitable  *initable,
+                      GAsyncResult    *result,
+                      GError         **error)
+{
+	NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (initable);
+
+    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+        return FALSE;
+
+    self->priv->countries = g_hash_table_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result)));
+
+    return TRUE;
+}
+
+static void
+initable_init_async_in_thread (GSimpleAsyncResult *result,
+                               NMAMobileProvidersDatabase *self,
+                               GCancellable *cancellable)
+{
+	GHashTable *countries;
+	GError *error = NULL;
+
+	/* paths are not expected to be modified once set during construct, so
+	 * it's actually safe to read them from another thread. */
+
+	countries = mobile_providers_parse_sync (self->priv->country_codes_path,
+	                                         self->priv->service_providers_path,
+	                                         cancellable,
+	                                         &error);
+	if (!countries)
+		g_simple_async_result_take_error (result, error);
+	else
+		g_simple_async_result_set_op_res_gpointer (result,
+		                                           countries,
+		                                           (GDestroyNotify)g_hash_table_unref);
+}
+
+static void
+initable_init_async (GAsyncInitable      *initable,
+                     int                  io_priority,
+                     GCancellable        *cancellable,
+                     GAsyncReadyCallback  callback,
+                     gpointer             user_data)
+{
+	GSimpleAsyncResult *result;
+
+	result = g_simple_async_result_new (G_OBJECT (initable),
+	                                    callback,
+	                                    user_data,
+	                                    initable_init_async);
+
+    g_simple_async_result_run_in_thread (
+	    result,
+	    (GSimpleAsyncThreadFunc)initable_init_async_in_thread,
+	    io_priority,
+	    cancellable);
+
+    g_object_unref (result);
+}
+
+/**********************************/
+
+static gboolean
+initable_init_sync (GInitable     *initable,
+                    GCancellable  *cancellable,
+                    GError       **error)
+{
+	NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (initable);
+
+	/* Parse the files */
+	self->priv->countries = mobile_providers_parse_sync (self->priv->country_codes_path,
+	                                                     self->priv->service_providers_path,
+	                                                     cancellable,
+	                                                     error);
+	if (!self->priv->countries)
+		return FALSE;
+
+    /* All good */
+	return TRUE;
+}
+
+/**********************************/
+
+void
+nma_mobile_providers_database_new (const gchar *country_codes,
+                                   const gchar *service_providers,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+    g_async_initable_new_async (NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
+                                G_PRIORITY_DEFAULT,
+                                cancellable,
+                                callback,
+                                user_data,
+                                "country-codes",     country_codes,
+                                "service-providers", service_providers,
+                                NULL);
+}
+
+NMAMobileProvidersDatabase *
+nma_mobile_providers_database_new_finish (GAsyncResult *res,
+                                          GError **error)
+{
+	GObject *initable;
+	GObject *out;
+
+	initable = g_async_result_get_source_object (res);
+	out = g_async_initable_new_finish (G_ASYNC_INITABLE (initable), res, error);
+	g_object_unref (initable);
+
+	return out ? NMA_MOBILE_PROVIDERS_DATABASE (out) : NULL;
+}
+
+NMAMobileProvidersDatabase *
+nma_mobile_providers_database_new_sync (const gchar *country_codes,
+                                        const gchar *service_providers,
+                                        GCancellable *cancellable,
+                                        GError **error)
+{
+	GObject *out;
+
+	out = g_initable_new (NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
+	                      cancellable,
+	                      error,
+	                      "country-codes",     country_codes,
+	                      "service-providers", service_providers,
+	                      NULL);
+
+	return out ? NMA_MOBILE_PROVIDERS_DATABASE (out) : NULL;
+}
+
+/**********************************/
+
+static void
+set_property (GObject *object,
+              guint prop_id,
+              const GValue *value,
+              GParamSpec *pspec)
+{
+	NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
+
+    switch (prop_id) {
+    case PROP_COUNTRY_CODES_PATH:
+	    self->priv->country_codes_path = g_value_dup_string (value);
+	    break;
+    case PROP_SERVICE_PROVIDERS_PATH:
+	    self->priv->service_providers_path = g_value_dup_string (value);
+	    break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
+
+    switch (prop_id) {
+    case PROP_COUNTRY_CODES_PATH:
+	    g_value_set_string (value, self->priv->country_codes_path);
+	    break;
+    case PROP_SERVICE_PROVIDERS_PATH:
+	    g_value_set_string (value, self->priv->service_providers_path);
+	    break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+nma_mobile_providers_database_init (NMAMobileProvidersDatabase *self)
+{
+    /* Setup private data */
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+	                                          NMA_TYPE_MOBILE_PROVIDERS_DATABASE,
+	                                          NMAMobileProvidersDatabasePrivate);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMAMobileProvidersDatabase *self = NMA_MOBILE_PROVIDERS_DATABASE (object);
+
+	g_free (self->priv->country_codes_path);
+	g_free (self->priv->service_providers_path);
+
+	if (self->priv->countries)
+		g_hash_table_unref (self->priv->countries);
+
+    G_OBJECT_CLASS (nma_mobile_providers_database_parent_class)->finalize (object);
+}
+
+static void
+initable_iface_init (GInitableIface *iface)
+{
+	iface->init = initable_init_sync;
+}
+
+static void
+async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	iface->init_async = initable_init_async;
+	iface->init_finish = initable_init_finish;
+}
+
+static void
+nma_mobile_providers_database_class_init (NMAMobileProvidersDatabaseClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (NMAMobileProvidersDatabasePrivate));
+
+    /* Virtual methods */
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+    object_class->finalize = finalize;
+
+    properties[PROP_COUNTRY_CODES_PATH] =
+	    g_param_spec_string ("country-codes",
+                             "Country Codes",
+                             "Path to the country codes file",
+	                         NULL,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (object_class, PROP_COUNTRY_CODES_PATH, properties[PROP_COUNTRY_CODES_PATH]);
+
+    properties[PROP_SERVICE_PROVIDERS_PATH] =
+	    g_param_spec_string ("service-providers",
+	                         "Service Providers",
+	                         "Path to the service providers file",
+	                         NULL,
+	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+    g_object_class_install_property (object_class, PROP_SERVICE_PROVIDERS_PATH, properties[PROP_SERVICE_PROVIDERS_PATH]);
+}
+
+/******************************************************************************/
+/* Utils */
+
 /**
  * nma_mobile_providers_split_3gpp_mcc_mnc:
  * @mccmnc: input MCCMNC string.
diff --git a/src/libnm-gtk/nm-mobile-providers.h b/src/libnm-gtk/nm-mobile-providers.h
index b1524f8..4442d7f 100644
--- a/src/libnm-gtk/nm-mobile-providers.h
+++ b/src/libnm-gtk/nm-mobile-providers.h
@@ -31,6 +31,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <gio/gio.h>
 
 /******************************************************************************/
 /* Access method type */
@@ -86,17 +87,55 @@ const gchar    *nma_country_info_get_country_name (NMACountryInfo *country_info)
 GSList         *nma_country_info_get_providers    (NMACountryInfo *country_info);
 
 /******************************************************************************/
-/* Utils */
+/* Mobile providers database type */
+
+#define NMA_TYPE_MOBILE_PROVIDERS_DATABASE            (nma_mobile_providers_database_get_type ())
+#define NMA_MOBILE_PROVIDERS_DATABASE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_MOBILE_PROVIDERS_DATABASE, NMAMobileProvidersDatabase))
+#define NMA_MOBILE_PROVIDERS_DATABASE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_MOBILE_PROVIDERS_DATABASE, NMAMobileProvidersDatabaseClass))
+#define NMA_IS_MOBILE_PROVIDERS_DATABASE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_MOBILE_PROVIDERS_DATABASE))
+#define NMA_IS_MOBILE_PROVIDERS_DATABASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_MOBILE_PROVIDERS_DATABASE))
+#define NMA_MOBILE_PROVIDERS_DATABASE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_MOBILE_PROVIDERS_DATABASE, NMAMobileProvidersDatabaseClass))
+
+typedef struct _NMAMobileProvidersDatabase NMAMobileProvidersDatabase;
+typedef struct _NMAMobileProvidersDatabaseClass NMAMobileProvidersDatabaseClass;
+typedef struct _NMAMobileProvidersDatabasePrivate NMAMobileProvidersDatabasePrivate;
+
+struct _NMAMobileProvidersDatabase {
+	GObject parent;
+	NMAMobileProvidersDatabasePrivate *priv;
+};
+
+struct _NMAMobileProvidersDatabaseClass {
+	GObjectClass parent;
+};
+
+GType nma_mobile_providers_database_get_type (void);
+
+void                        nma_mobile_providers_database_new        (const gchar *country_codes,
+                                                                      const gchar *service_providers,
+                                                                      GCancellable *cancellable,
+                                                                      GAsyncReadyCallback callback,
+                                                                      gpointer user_data);
+NMAMobileProvidersDatabase *nma_mobile_providers_database_new_finish (GAsyncResult *res,
+                                                                      GError **error);
+NMAMobileProvidersDatabase *nma_mobile_providers_database_new_sync   (const gchar *country_codes,
+                                                                      const gchar *service_providers,
+                                                                      GCancellable *cancellable,
+                                                                      GError **error);
+
+GHashTable        *nma_mobile_providers_database_get_countries       (NMAMobileProvidersDatabase *self);
+
+void               nma_mobile_providers_database_dump                (NMAMobileProvidersDatabase *self);
+
+NMACountryInfo    *nma_mobile_providers_database_lookup_country      (NMAMobileProvidersDatabase *self,
+                                                                      const gchar *country_code);
+NMAMobileProvider *nma_mobile_providers_database_lookup_3gpp_mcc_mnc (NMAMobileProvidersDatabase *self,
+                                                                      const gchar *mccmnc);
+NMAMobileProvider *nma_mobile_providers_database_lookup_cdma_sid     (NMAMobileProvidersDatabase *self,
+                                                                      guint32 sid);
 
-/* Returns a table where keys are country codes and values are NMACountryInfo
- * values */
-GHashTable        *nma_mobile_providers_parse                 (const gchar *country_codes,
-                                                               const gchar *service_providers);
-void               nma_mobile_providers_dump                  (GHashTable *country_infos);
-NMAMobileProvider *nma_mobile_providers_find_for_3gpp_mcc_mnc (GHashTable  *country_infos,
-                                                               const gchar *mccmnc);
-NMAMobileProvider *nma_mobile_providers_find_for_cdma_sid     (GHashTable  *country_infos,
-                                                               guint32      sid);
+/******************************************************************************/
+/* Utils */
 
 gboolean nma_mobile_providers_split_3gpp_mcc_mnc (const gchar *mccmnc,
                                                   gchar **mcc,
diff --git a/src/libnm-gtk/nm-mobile-wizard.c b/src/libnm-gtk/nm-mobile-wizard.c
index 4d86f18..a29d4b5 100644
--- a/src/libnm-gtk/nm-mobile-wizard.c
+++ b/src/libnm-gtk/nm-mobile-wizard.c
@@ -52,7 +52,7 @@ struct NMAMobileWizard {
 	GtkWidget *assistant;
 	NMAMobileWizardCallback callback;
 	gpointer user_data;
-	GHashTable *country_infos;
+	NMAMobileProvidersDatabase *mobile_providers_database;
 	NMAMobileFamily family;
 	gboolean initial_family;
 	gboolean will_connect_after;
@@ -1130,8 +1130,12 @@ country_setup (NMAMobileWizard *self)
 	                                 NULL);
 
 	/* Add the rest of the providers */
-	if (self->country_infos)
-		g_hash_table_foreach (self->country_infos, add_one_country, self);
+	if (self->mobile_providers_database) {
+		GHashTable *countries;
+
+		countries = nma_mobile_providers_database_get_countries (self->mobile_providers_database);
+		g_hash_table_foreach (countries, add_one_country, self);
+	}
 	g_object_set (G_OBJECT (self->country_view), "enable-search", TRUE, NULL);
 
 	/* If no row has focus yet, focus the first row so that the user can start
@@ -1622,19 +1626,23 @@ nma_mobile_wizard_new (GtkWindow *parent,
 {
 	NMAMobileWizard *self;
 	char *cc;
+	GError *error = NULL;
 
 	self = g_malloc0 (sizeof (NMAMobileWizard));
 	g_return_val_if_fail (self != NULL, NULL);
 
-	self->country_infos = nma_mobile_providers_parse (NULL, NULL);
-	if (!self->country_infos) {
+	self->mobile_providers_database = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
+	if (!self->mobile_providers_database) {
+		g_warning ("Cannot create mobile providers database: %s",
+		           error->message);
+		g_error_free (error);
 		nma_mobile_wizard_destroy (self);
 		return NULL;
 	}
 
 	cc = get_country_from_locale ();
 	if (cc) {
-		self->country = g_hash_table_lookup (self->country_infos, cc);
+		self->country = nma_mobile_providers_database_lookup_country (self->mobile_providers_database, cc);
 		g_free (cc);
 	}
 
@@ -1704,8 +1712,8 @@ nma_mobile_wizard_destroy (NMAMobileWizard *self)
 	remove_provider_focus_idle (self);
 	remove_country_focus_idle (self);
 
-	if (self->country_infos)
-		g_hash_table_destroy (self->country_infos);
+	if (self->mobile_providers_database)
+		g_object_unref (self->mobile_providers_database);
 
 	g_free (self);
 }



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