[network-manager-applet] libnm-gtk: new 'NMAMobileProvidersDatabase' object



commit fb7164fba63e0a2dc768c7e9d8d11e46c83a9e23
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 |  450 ++++++++++++++++++++++++++++------
 src/libnm-gtk/nm-mobile-providers.h |   59 ++++-
 src/libnm-gtk/nm-mobile-wizard.c    |   24 ++-
 5 files changed, 459 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 13067cc..97e35bd 100644
--- a/src/libnm-gtk/nm-mobile-providers.c
+++ b/src/libnm-gtk/nm-mobile-providers.c
@@ -473,11 +473,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;
 
@@ -485,28 +486,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;
 }
 
@@ -903,51 +905,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;
@@ -956,26 +935,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);
@@ -994,11 +978,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)
 {
@@ -1085,23 +1101,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;
@@ -1109,6 +1190,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 */
@@ -1116,7 +1198,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;
@@ -1188,24 +1270,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;
@@ -1233,6 +1315,214 @@ nma_mobile_providers_find_for_cdma_sid (GHashTable *country_infos,
 	return NULL;
 }
 
+/**********************************/
+
+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;
+}
+
+/**********************************/
+
+/**
+ * nma_mobile_providers_database_new:
+ * @country_codes: (allow-none): Path to the country codes file.
+ * @service_providers: (allow-none): Path to the service providers file.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ */
+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);
+}
+
+/**
+ * nma_mobile_providers_database_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to nma_mobile_providers_database_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Returns: (transfer full) (type NMAMobileProvidersDatabase): The constructed object or %NULL if @error is set.
+ */
+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;
+}
+
+/**
+ * nma_mobile_providers_database_new_sync:
+ * @country_codes: (allow-none): Path to the country codes file.
+ * @service_providers: (allow-none): Path to the service providers file.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Returns: (transfer full) (type NMAMobileProvidersDatabase): The constructed object or %NULL if @error is set.
+ */
+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)
+{
+	/* Just use defaults (run sync init() in a thread) */
+}
+
+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]