1 /* Copyright (c) 2008, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */
36 #include "modest-maemo-utils.h"
37 #include "modest-country-picker.h"
38 #include <gtk/gtkliststore.h>
39 #include <gtk/gtkcelllayout.h>
40 #include <gtk/gtkcellrenderertext.h>
43 #include <string.h> /* For memcpy() */
46 #include <libintl.h> /* For dgettext(). */
48 /* Include config.h so that _() works: */
53 #define MAX_LINE_LEN 128 /* max length of a line in MCC file */
55 G_DEFINE_TYPE (ModestCountryPicker, modest_country_picker, HILDON_TYPE_PICKER_BUTTON);
60 /* GtkTreeModel *model; */
61 } ModestCountryPickerPrivate;
63 #define MODEST_COUNTRY_PICKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
64 MODEST_TYPE_COUNTRY_PICKER, \
65 ModestCountryPickerPrivate))
68 modest_country_picker_get_property (GObject *object, guint property_id,
69 GValue *value, GParamSpec *pspec)
71 switch (property_id) {
73 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
78 modest_country_picker_set_property (GObject *object, guint property_id,
79 const GValue *value, GParamSpec *pspec)
81 switch (property_id) {
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
88 modest_country_picker_dispose (GObject *object)
90 if (G_OBJECT_CLASS (modest_country_picker_parent_class)->dispose)
91 G_OBJECT_CLASS (modest_country_picker_parent_class)->dispose (object);
95 MODEL_COL_NAME = 0, /* string */
96 MODEL_COL_MCC = 1 /* the 'effective mcc' for this country */
101 modest_country_picker_finalize (GObject *object)
103 G_OBJECT_CLASS (modest_country_picker_parent_class)->finalize (object);
107 modest_country_picker_class_init (ModestCountryPickerClass *klass)
109 GObjectClass *object_class = G_OBJECT_CLASS (klass);
111 g_type_class_add_private (klass, sizeof (ModestCountryPickerPrivate));
113 object_class->get_property = modest_country_picker_get_property;
114 object_class->set_property = modest_country_picker_set_property;
115 object_class->dispose = modest_country_picker_dispose;
116 object_class->finalize = modest_country_picker_finalize;
122 /* cluster mcc's, based on the list
123 * http://en.wikipedia.org/wiki/Mobile_country_code
126 effective_mcc (gint mcc)
129 case 405: return 404; /* india */
130 case 441: return 440; /* japan */
131 case 235: return 234; /* united kingdom */
137 case 316: return 310; /* united states */
143 /* each line is of the form:
146 NOTE: this function is NOT re-entrant, the out-param country
147 are static strings that should NOT be freed. and will change when
148 calling this function again
150 also note, this function will return the "effective mcc", which
151 is the normalized mcc for a country - ie. even if the there
152 are multiple entries for the United States with various mccs,
153 this function will always return 310, even if the real mcc parsed
154 would be 314. see the 'effective_mcc' function above.
157 parse_mcc_mapping_line (const char* line, char** country)
160 char mcc[4]; /* the mcc code, always 3 bytes*/
161 static char my_country[128];
168 for (i = 3, j = 0; i < 128; ++i) {
175 my_country [j++] = kar;
177 my_country[j] = '\0';
184 *country = my_country;
186 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
189 /** Note that the mcc_mapping file is installed
190 * by the operator-wizard-settings package.
193 load_from_file (ModestCountryPicker *self, GtkListStore *liststore)
195 ModestCountryPickerPrivate *priv = MODEST_COUNTRY_PICKER_GET_PRIVATE (self);
197 char line[MAX_LINE_LEN];
198 guint previous_mcc = 0;
199 gchar *territory, *fallback = NULL;
200 gchar *current_locale;
202 /* Get the territory specified for the current locale */
203 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
205 /* Tricky stuff, the translations of the OSSO countries does
206 not always correspond to the country names in locale
207 databases. Add all these cases here. sergio */
208 if (!strcmp (territory, "United Kingdom"))
209 fallback = g_strdup ("UK");
211 current_locale = setlocale (LC_ALL ,NULL);
213 FILE *file = modest_maemo_open_mcc_mapping_file ();
215 g_warning("Could not open mcc_mapping file");
219 while (fgets (line, MAX_LINE_LEN, file) != NULL) {
222 char *country = NULL;
223 const gchar *name_translated, *english_translation;
225 mcc = parse_mcc_mapping_line (line, &country);
226 if (!country || mcc == 0) {
227 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
231 if (mcc == previous_mcc) {
232 /* g_warning ("already seen: %s", line); */
237 if (!priv->locale_mcc) {
238 english_translation = dgettext ("osso-countries", country);
239 if (!strcmp (english_translation, territory) ||
240 (fallback && !strcmp (english_translation, fallback)))
241 priv->locale_mcc = mcc;
243 name_translated = dgettext ("osso-countries", country);
245 /* Add the row to the model: */
247 gtk_list_store_append (liststore, &iter);
248 gtk_list_store_set(liststore, &iter, MODEL_COL_MCC, mcc, MODEL_COL_NAME, name_translated, -1);
252 /* Sort the items: */
253 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore),
254 MODEL_COL_NAME, GTK_SORT_ASCENDING);
260 modest_country_picker_init (ModestCountryPicker *self)
262 ModestCountryPickerPrivate *priv = MODEST_COUNTRY_PICKER_GET_PRIVATE (self);
263 priv->locale_mcc = 0;
267 modest_country_picker_load_data(ModestCountryPicker *self)
269 GtkCellRenderer *renderer;
273 /* Create a tree model for the combo box,
274 * with a string for the name, and an int for the MCC ID.
275 * This must match our MODEL_COLS enum constants.
277 model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
280 * The ID model column in not shown in the view. */
281 renderer = gtk_cell_renderer_text_new ();
282 g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
284 selector = hildon_touch_selector_new ();
285 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (self), HILDON_TOUCH_SELECTOR (selector));
286 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), GTK_TREE_MODEL (model),
287 renderer, "text", MODEL_COL_NAME, NULL);
289 /* Fill the model with rows: */
290 load_from_file (self, model);
292 /* Set this _after_ loading from file, it makes loading faster */
293 hildon_touch_selector_set_model (HILDON_TOUCH_SELECTOR (selector),
294 0, GTK_TREE_MODEL (model));
295 g_object_unref (model);
299 modest_country_picker_new (HildonSizeType size,
300 HildonButtonArrangement arrangement)
302 return g_object_new (MODEST_TYPE_COUNTRY_PICKER,
303 "arrangement", arrangement,
309 * Returns the MCC number of the selected country, or 0 if no country was selected.
312 modest_country_picker_get_active_country_mcc (ModestCountryPicker *self)
317 found = hildon_touch_selector_get_selected (hildon_picker_button_get_selector
318 (HILDON_PICKER_BUTTON (self)), 0, &active);
321 gtk_tree_model_get (hildon_touch_selector_get_model (hildon_picker_button_get_selector
322 (HILDON_PICKER_BUTTON (self)),
324 &active, MODEL_COL_MCC, &mcc, -1);
327 return 0; /* Failed. */
332 * Selects the MCC number of the selected country.
333 * Specify 0 to select no country.
336 modest_country_picker_set_active_country_locale (ModestCountryPicker *self)
338 ModestCountryPickerPrivate *priv = MODEST_COUNTRY_PICKER_GET_PRIVATE (self);
344 selector = GTK_WIDGET (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (self)));
345 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
346 if (!gtk_tree_model_get_iter_first (model, &iter))
349 gtk_tree_model_get (model, &iter, MODEL_COL_MCC, ¤t_mcc, -1);
350 if (priv->locale_mcc == current_mcc) {
351 hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), 0,
353 hildon_button_set_value (HILDON_BUTTON (self),
354 hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)));
357 } while (gtk_tree_model_iter_next (model, &iter));
359 return FALSE; /* not found */