X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fmaemo%2Feasysetup%2Fmodest-easysetup-country-combo-box.c;h=bac8fb864f04120487fb8438251454e1f783b722;hb=247b5f9e1d7a9557e94b96ac6d50adcef6beb5bd;hp=ce9f823027f19d26ae83316e278934a1388f59ab;hpb=f213c6daa765f3de742ba2a2475a5ecf4c181d94;p=modest diff --git a/src/maemo/easysetup/modest-easysetup-country-combo-box.c b/src/maemo/easysetup/modest-easysetup-country-combo-box.c index ce9f823..bac8fb8 100644 --- a/src/maemo/easysetup/modest-easysetup-country-combo-box.c +++ b/src/maemo/easysetup/modest-easysetup-country-combo-box.c @@ -33,6 +33,7 @@ #include +#include #include "modest-easysetup-country-combo-box.h" #include #include @@ -40,7 +41,8 @@ #include #include /* For memcpy() */ - +#include +#include #include /* For dgettext(). */ /* Include config.h so that _() works: */ @@ -48,17 +50,23 @@ #include #endif -G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, GTK_TYPE_COMBO_BOX); - -#define COUNTRY_COMBO_BOX_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_COUNTRY_COMBO_BOX, EasysetupCountryComboBoxPrivate)) +#define MAX_LINE_LEN 128 /* max length of a line in MCC file */ -typedef struct _EasysetupCountryComboBoxPrivate EasysetupCountryComboBoxPrivate; +#if MODEST_HILDON_API < 2 +G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, GTK_TYPE_COMBO_BOX); +#else +G_DEFINE_TYPE (EasysetupCountryComboBox, easysetup_country_combo_box, HILDON_TYPE_PICKER_BUTTON); +#endif -struct _EasysetupCountryComboBoxPrivate +typedef struct { - GtkTreeModel *model; -}; + gint locale_mcc; +/* GtkTreeModel *model; */ +} ModestEasysetupCountryComboBoxPrivate; + +#define MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, \ + ModestEasysetupCountryComboBoxPrivate)) static void easysetup_country_combo_box_get_property (GObject *object, guint property_id, @@ -89,29 +97,13 @@ easysetup_country_combo_box_dispose (GObject *object) enum MODEL_COLS { MODEL_COL_NAME = 0, /* string */ - MODEL_COL_IDS = 1 /* A GSList* of guints. */ + MODEL_COL_MCC = 1 /* the 'effective mcc' for this country */ }; -static gboolean -on_model_foreach_release (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) -{ - GSList *list = NULL; - gtk_tree_model_get (model, iter, MODEL_COL_IDS, &list, -1); - if (list) - g_slist_free (list); - - return FALSE; /* keep walking. */ -} static void easysetup_country_combo_box_finalize (GObject *object) { - EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (object); - - gtk_tree_model_foreach (priv->model, on_model_foreach_release, NULL); - g_object_unref (G_OBJECT (priv->model)); - G_OBJECT_CLASS (easysetup_country_combo_box_parent_class)->finalize (object); } @@ -120,7 +112,7 @@ easysetup_country_combo_box_class_init (EasysetupCountryComboBoxClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (EasysetupCountryComboBoxPrivate)); + g_type_class_add_private (klass, sizeof (ModestEasysetupCountryComboBoxPrivate)); object_class->get_property = easysetup_country_combo_box_get_property; object_class->set_property = easysetup_country_combo_box_set_property; @@ -128,290 +120,137 @@ easysetup_country_combo_box_class_init (EasysetupCountryComboBoxClass *klass) object_class->finalize = easysetup_country_combo_box_finalize; } -/** id and country must be freed. - */ -static void parse_mcc_mapping_line (const char* line, char** id, char** country) -{ - /* Initialize output parameters: */ - *id = NULL; - *country = NULL; - - g_assert(line); - - const gboolean is_valid_utf8 = g_utf8_validate (line, -1, NULL); - if(!is_valid_utf8) { - g_warning("UTF8 validation failed."); - return; - } - - /* Look at each character, to find the whitespace between the ID and name: */ - char* result_id = NULL; - char* result_country = NULL; - - const char* p = line; - const char* p_start_of_country = NULL; - while (p && *p) - { - p = g_utf8_next_char(p); - gunichar ch = g_utf8_get_char(p); - if (g_unichar_isspace(ch)) { /* Note: This checks for any whitespace, not just space. */ - if(!result_id) { - /* The text before this must be the ID: */ - const int length = p - line; - result_id = g_malloc (length + 1); /* 1 for null-termination. */ - memcpy(result_id, line, length); - result_id[length] = 0; /* Null-termination. */ - } - else if(p_start_of_country) - { - /* This whitespace is probably the newline after the country. */ - - /* The text after the whitespace, after the ID, must be the country: */ - int length = p - p_start_of_country; - result_country = g_malloc(length + 1); - memcpy(result_country, p_start_of_country, length); - result_country[length] = 0; /* Null-termination. */ - break; - } - } - else if(result_id && !p_start_of_country) { - p_start_of_country = p; - } - } - - *id = result_id; - *country = result_country; -} -/** Note that the mcc_mapping file is installed - * by the operator-wizard-settings package. - */ -static void load_from_file (EasysetupCountryComboBox *self) +static void +easysetup_country_combo_box_init (EasysetupCountryComboBox *self) { - EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); - - /* Load the file one line at a time: */ -#ifndef MODEST_HILDON_VERSION_0 - const gchar* filepath = PROVIDER_DATA_DIR "/mcc_mapping"; -#else - /* This is the official version, in the 'operator-wizard-settings' package */ - const gchar* filepath = "/usr/share/operator-wizard/mcc_mapping"; -#endif /*MODEST_HILDON_VERSION_0*/ - /* printf ("DEBUG: %s: filepath=%s\n", __FUNCTION__, filepath); */ - FILE *file = fopen(filepath, "r"); - if (!file) - { - const gchar* filepath_hack = HACK_TOP_SRCDIR "src/maemo/easysetup/mcc_mapping"; - g_warning ("Could not locate the official mcc_mapping countries list file from %s, " - "so attempting to load it instead from %s", filepath, filepath_hack); - file = fopen(filepath_hack, "r"); - } - - if (!file) { - g_warning("Could not open mcc_mapping file"); - return; - } - - GtkListStore *liststore = GTK_LIST_STORE (priv->model); - - /* We use the getline() GNU extension, - * because it reads per line, which simplifies our code, - * and it doesn't require us to hard-code a buffer length. - * TODO: Could we make this faster? - */ - unsigned int len = 0; - char *line = NULL; - guint previous_id = 0; - gchar* previous_country = NULL; - GSList *list = NULL; - while (getline (&line, &len, file) > 0) { /* getline will realloc line if necessary. */ - /* printf ("DBEUG: len=%d, line: %s\n", len, line); */ - - char *id_str = NULL; - char *country = NULL; - parse_mcc_mapping_line (line, &id_str, &country); - /* printf("DEBUG: parsed: id=%s, country=%s\n", id_str, country); */ - - if(id_str && country) { - - if (previous_country) { - /* printf (" debug: storing id=%d for country=%s\n", previous_id, previous_country); */ - list = g_slist_append (list, GUINT_TO_POINTER (previous_id)); - } - - /* Group multiple MMC IDs for the same country together: - * This assumes that they are in sequence. - * We don't know why some countries, such as the USA, have several MMC IDs. - * If they are regions in the country, and we need to show them separately, then - * we would need to have that information in the file to distinguish them. - */ - if (!previous_country || - (previous_country && strcmp (previous_country, country) != 0)) { - - /* Get the translation for the country name: - * Note that the osso_countries_1.0 translation domain files are installed - * by the operator-wizard-settings package. */ - /* For post-Bora, there is a separate (meta)package osso-countries-l10n-mr0 */ - - /* Note: Even when the untranslated names are different, there may still be - * duplicate translated names. They would be translation bugs. - */ - const gchar *name_translated = dgettext ("osso-countries", previous_country); - if(!name_translated) - name_translated = previous_country; - - /* Add the row to the model: */ - GtkTreeIter iter; - gtk_list_store_append (liststore, &iter); - gtk_list_store_set(liststore, &iter, MODEL_COL_IDS, list, MODEL_COL_NAME, name_translated, -1); - - /* The list will be freed in our finalize(). */ - list = NULL; - } - - g_free (previous_country); - previous_country = g_strdup (country); - - const guint id = (guint)g_ascii_strtod(id_str, NULL); /* Note that this parses locale-independent text. */ - previous_id = id; - } - - g_free (id_str); - g_free (country); - } - - /* Deal with the last country: */ - const gchar *name_translated = dgettext ("osso-countries", previous_country); - if(!name_translated) - name_translated = previous_country; - - /* Add the row to the model: */ - GtkTreeIter iter; - gtk_list_store_append (liststore, &iter); - gtk_list_store_set(liststore, &iter, MODEL_COL_IDS, list, MODEL_COL_NAME, name_translated, -1); - - if (list) { - g_slist_free (list); - list = NULL; - } - - - if (line) - free (line); - - fclose (file); - - /* Sort the items: */ - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore), - MODEL_COL_NAME, GTK_SORT_ASCENDING); + ModestEasysetupCountryComboBoxPrivate *priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self); + priv->locale_mcc = 0; } -static void -easysetup_country_combo_box_init (EasysetupCountryComboBox *self) +void +easysetup_country_combo_box_load_data(EasysetupCountryComboBox *self) { - EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + ModestEasysetupCountryComboBoxPrivate *priv; + GtkTreeModel *model; + priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self); /* Create a tree model for the combo box, * with a string for the name, and an int for the MCC ID. * This must match our MODEL_COLS enum constants. */ - priv->model = GTK_TREE_MODEL (gtk_list_store_new (2, - G_TYPE_STRING, - G_TYPE_POINTER)); - - /* Setup the combo box: */ - GtkComboBox *combobox = GTK_COMBO_BOX (self); - gtk_combo_box_set_model (combobox, priv->model); - + model = modest_utils_create_country_model (); + /* Country column: * The ID model column in not shown in the view. */ GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combobox), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, - "text", MODEL_COL_NAME, NULL); - - /* Fill the model with rows: */ - load_from_file (self); + g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); + +#if MODEST_HILDON_API < 2 + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (self), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), renderer, + "text", MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, NULL); +#else + GtkWidget *selector = hildon_touch_selector_new (); + hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (self), HILDON_TOUCH_SELECTOR (selector)); + hildon_touch_selector_append_column (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (self)), + model, + renderer, "text", MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, NULL); +#endif + + modest_utils_fill_country_model (model, &(priv->locale_mcc)); + + /* Set this _after_ loading from file, it makes loading faster */ +#if MODEST_HILDON_API < 2 + gtk_combo_box_set_model (GTK_COMBO_BOX (self), model); +#else + hildon_touch_selector_set_model (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (self)), + 0, model); +#endif } EasysetupCountryComboBox* easysetup_country_combo_box_new (void) { - return g_object_new (EASYSETUP_TYPE_COUNTRY_COMBO_BOX, NULL); +#if MODEST_HILDON_API >= 2 + return g_object_new (MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, + "arrangement", HILDON_BUTTON_ARRANGEMENT_VERTICAL, + "size", HILDON_SIZE_AUTO, + NULL); +#else + return g_object_new (MODEST_EASYSETUP_TYPE_COUNTRY_COMBO_BOX, + NULL); +#endif } /** * Returns the MCC number of the selected country, or 0 if no country was selected. - * The list should not be freed. */ -GSList * -easysetup_country_combo_box_get_active_country_ids (EasysetupCountryComboBox *self) +gint +easysetup_country_combo_box_get_active_country_mcc (EasysetupCountryComboBox *self) { GtkTreeIter active; - const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &active); - if (found) { - EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); + gboolean found; - GSList *list = NULL; - gtk_tree_model_get (priv->model, &active, MODEL_COL_IDS, &list, -1); - return list; +#if MODEST_HILDON_API < 2 + found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &active); +#else + found = hildon_touch_selector_get_selected (hildon_picker_button_get_selector + (HILDON_PICKER_BUTTON (self)), 0, &active); +#endif + if (found) { + gint mcc = 0; +#if MODEST_HILDON_API < 2 + gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (self)), + &active, MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, &mcc, -1); +#else + gtk_tree_model_get (hildon_touch_selector_get_model (hildon_picker_button_get_selector + (HILDON_PICKER_BUTTON (self)), + 0), + &active, MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, &mcc, -1); +#endif + return mcc; } - - return NULL; /* Failed. */ + return 0; /* Failed. */ } -/* This allows us to pass more than one piece of data to the signal handler, - * and get a result: */ -typedef struct -{ - EasysetupCountryComboBox* self; - guint mcc_id; - gboolean found; -} ForEachData; - -static gboolean -on_model_foreach_select_id(GtkTreeModel *model, - GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) -{ - ForEachData *state = (ForEachData*)(user_data); - - /* Select the item if it has the matching ID: */ - GSList *list = NULL; - gtk_tree_model_get (model, iter, MODEL_COL_IDS, &list, -1); - if(list && g_slist_find (list, GUINT_TO_POINTER (state->mcc_id))) { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (state->self), iter); - - state->found = TRUE; - return TRUE; /* Stop walking the tree. */ - } - - return FALSE; /* Keep walking the tree. */ -} - /** * Selects the MCC number of the selected country. * Specify 0 to select no country. */ gboolean -easysetup_country_combo_box_set_active_country_id (EasysetupCountryComboBox *self, guint mcc_id) +easysetup_country_combo_box_set_active_country_locale (EasysetupCountryComboBox *self) { - EasysetupCountryComboBoxPrivate *priv = COUNTRY_COMBO_BOX_GET_PRIVATE (self); - - /* Create a state instance so we can send two items of data to the signal handler: */ - ForEachData *state = g_new0 (ForEachData, 1); - state->self = self; - state->mcc_id = mcc_id; - state->found = FALSE; - - /* Look at each item, and select the one with the correct ID: */ - gtk_tree_model_foreach (priv->model, &on_model_foreach_select_id, state); + ModestEasysetupCountryComboBoxPrivate *priv = MODEST_EASYSETUP_COUNTRY_COMBO_BOX_GET_PRIVATE (self); + GtkTreeIter iter; + gint current_mcc; + GtkTreeModel *model; - const gboolean result = state->found; - - /* Free the state instance: */ - g_free(state); +#if MODEST_HILDON_API < 2 + model = gtk_combo_box_get_model (GTK_COMBO_BOX (self)); + g_debug ("%s: HILDON < 2", __FUNCTION__); +#else + model = hildon_touch_selector_get_model (hildon_picker_button_get_selector + (HILDON_PICKER_BUTTON (self)), 0); + g_debug ("%s: HILDON >= 2", __FUNCTION__); +#endif + if (!gtk_tree_model_get_iter_first (model, &iter)) + return FALSE; + do { + gtk_tree_model_get (model, &iter, MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, ¤t_mcc, -1); + if (priv->locale_mcc == current_mcc) { +#if MODEST_HILDON_API < 2 + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter); +#else + hildon_touch_selector_select_iter (hildon_picker_button_get_selector + (HILDON_PICKER_BUTTON (self)), 0, + &iter, TRUE); +#endif + return TRUE; + } + } while (gtk_tree_model_iter_next (model, &iter)); - return result; + return FALSE; /* not found */ }