Index: sugar/extensions/cpsection/modemconfiguration/model.py
===================================================================
--- sugar.orig/extensions/cpsection/modemconfiguration/model.py	2010-01-23 20:12:47.000000000 -0200
+++ sugar/extensions/cpsection/modemconfiguration/model.py	2010-01-23 20:14:13.000000000 -0200
@@ -15,10 +15,19 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
 
 import gconf
+import gtk
+import os
+import locale
+from xml.etree.cElementTree import ElementTree
+from gettext import gettext as _
 
 from jarabe.model.network import GSM_USERNAME_PATH, GSM_PASSWORD_PATH, \
                                  GSM_NUMBER_PATH, GSM_APN_PATH
 
+PROVIDERS_PATH = '/usr/share/mobile-broadband-provider-info/serviceproviders.xml'
+PROVIDERS_FORMAT_SUPPORTED = '2.0'
+COUNTRY_CODES_PATH = '/usr/share/zoneinfo/iso3166.tab'
+
 def get_username():
     client = gconf.client_get_default()
     return client.get_string(GSM_USERNAME_PATH) or ''
@@ -51,3 +60,102 @@
     client = gconf.client_get_default()
     client.set_string(GSM_APN_PATH, apn)
 
+def has_providers_db():
+    if not os.path.isfile(COUNTRY_CODES_PATH):
+	return False
+    try:
+	et = ElementTree(file=PROVIDERS_PATH)
+	elem = et.getroot()
+	if elem is None or elem.get('format') != PROVIDERS_FORMAT_SUPPORTED:
+	    return False
+	return True
+    except IOError:
+	return False
+
+class CountryListStore(gtk.ListStore):
+    COUNTRY_CODE = os.environ['LANG'][3:5].lower()
+
+    def __init__(self):
+	gtk.ListStore.__init__(self, str, object)
+	codes = {}
+	with open(COUNTRY_CODES_PATH) as f:
+	    for line in f:
+		if line.startswith('#'):
+		    continue
+		code, name = line.split('\t')[:2]
+		codes[code.lower()] = name.strip()
+	etree = ElementTree(file=PROVIDERS_PATH).getroot()
+	self._country_idx = None
+	i = 0
+	for elem in etree.findall('.//country'):
+	    code = elem.attrib['code']
+	    if code == self.COUNTRY_CODE:
+		self._country_idx = i
+	    else:
+		i += 1
+            if code in codes:
+	        self.append((codes[code], elem))
+            else:
+                self.append((code, elem))
+
+    def get_row_providers(self, n):
+	return self[n][1]
+
+    def guess_country_row(self):
+	if self._country_idx is not None:
+	    return self._country_idx
+	else:
+	    return -1
+
+class ProviderListStore(gtk.ListStore):
+    def __init__(self, elem):
+	gtk.ListStore.__init__(self, str, object)
+	for provider_elem in elem.findall('.//provider'):
+	    apns = provider_elem.findall('.//apn')
+	    if not apns:
+		# Skip carriers with CDMA entries only
+		continue
+	    self.append((provider_elem.find('.//name').text, apns))
+
+    def get_row_plans(self, n):
+	return self[n][1]
+
+class PlanListStore(gtk.ListStore):
+    LANG_NS_ATTR = '{http://www.w3.org/XML/1998/namespace}lang'
+    LANG = locale.getdefaultlocale()[0][:2]
+    DEFAULT_NUMBER = '*99#'
+
+    def __init__(self, elems):
+	gtk.ListStore.__init__(self, str, object)
+	for apn_elem in elems:
+	    plan = {}
+	    names = apn_elem.findall('.//name')
+	    if names:
+		for name in names:
+		    if name.get(self.LANG_NS_ATTR) is None:
+			# serviceproviders.xml default value
+			plan['name'] = name.text
+		    elif name.get(self.LANG_NS_ATTR) == self.LANG:
+			# Great! We found a name value for our locale!
+			plan['name'] = name.text
+			break
+	    else:
+		plan['name'] = _('Default')
+	    plan['apn'] = apn_elem.get('value')
+	    user = apn_elem.find('.//username')
+	    if user is not None:
+		plan['username'] = user.text
+	    else:
+		plan['username'] = ''
+	    passwd = apn_elem.find('.//password')
+	    if passwd is not None:
+		plan['password'] = passwd.text
+	    else:
+		plan['password'] = ''
+
+	    plan['number'] = self.DEFAULT_NUMBER
+
+	    self.append((plan['name'], plan))
+
+    def get_row_plan(self, n):
+	return self[n][1]
Index: sugar/extensions/cpsection/modemconfiguration/view.py
===================================================================
--- sugar.orig/extensions/cpsection/modemconfiguration/view.py	2010-01-23 20:12:47.000000000 -0200
+++ sugar/extensions/cpsection/modemconfiguration/view.py	2010-01-23 20:35:18.000000000 -0200
@@ -75,6 +75,9 @@
     def set_text_from_model(self):
         self._entry.set_text(self.get_value()) 
 
+    def set_text(self, text):
+        self._entry.set_text(text)
+
     def get_value(self):
         raise NotImplementedError
 
@@ -139,31 +142,77 @@
         self.set_border_width(style.DEFAULT_SPACING)
         self.set_spacing(style.DEFAULT_SPACING)
 
+        if self._model.has_providers_db():
+            self._upper_box = gtk.VBox(spacing=style.DEFAULT_SPACING)
+            self._upper_box.set_border_width(style.DEFAULT_SPACING)
+            self.pack_start(self._upper_box, fill=False)
+
+            # Country
+	    box = gtk.HBox(True)
+	    box.pack_start(gtk.Label(_('Country')), False)
+	    store = self._model.CountryListStore()
+	    country_combo = gtk.ComboBox(store)
+	    cell = gtk.CellRendererText()
+	    cell.props.xalign = 0.5
+	    country_combo.pack_start(cell)
+	    country_combo.add_attribute(cell, 'text', 0)
+	    country_combo.connect('changed', self._country_selected)
+	    box.pack_start(country_combo, False)
+	    self._upper_box.pack_start(box, False)
+
+	    #Provider
+	    box = gtk.HBox(True)
+	    box.pack_start(gtk.Label(_('Provider')), False)
+	    self._prov_combo = gtk.ComboBox()
+	    cell = gtk.CellRendererText()
+	    cell.props.xalign = 0.5
+	    self._prov_combo.pack_start(cell)
+	    self._prov_combo.add_attribute(cell, 'text', 0)
+	    self._prov_combo.connect('changed', self._provider_selected)
+	    box.pack_start(self._prov_combo, False)
+	    self._upper_box.pack_start(box, False)
+
+	    #Plan
+	    box = gtk.HBox(True)
+	    box.pack_start(gtk.Label(_('Plan')), False)
+	    self._plan_combo = gtk.ComboBox()
+	    cell = gtk.CellRendererText()
+	    cell.props.xalign = 0.5
+	    self._plan_combo.pack_start(cell)
+	    self._plan_combo.add_attribute(cell, 'text', 0)
+	    self._plan_combo.connect('changed', self._plan_selected)
+	    box.pack_start(self._plan_combo, False)
+	    self._upper_box.pack_start(box, False)
+
+	    country_combo.set_active(store.guess_country_row())
+
+            self.pack_start(gtk.HSeparator())
+
+        self._lower_box = gtk.VBox(spacing=style.DEFAULT_SPACING)
+        self.pack_start(self._lower_box, fill=False)
+
         self._username_entry = UsernameEntry(model)
         self._username_entry.connect('notify::is-valid',
                                      self.__notify_is_valid_cb)
-        self.pack_start(self._username_entry, expand=False)
-        self._username_entry.show()
+        self._lower_box.pack_start(self._username_entry, expand=False)
 
         self._password_entry = PasswordEntry(model)
         self._password_entry.connect('notify::is-valid',
                                      self.__notify_is_valid_cb)
-        self.pack_start(self._password_entry, expand=False)
-        self._password_entry.show()
+        self._lower_box.pack_start(self._password_entry, expand=False)
 
         self._number_entry = NumberEntry(model)
         self._number_entry.connect('notify::is-valid',
                                    self.__notify_is_valid_cb)
-        self.pack_start(self._number_entry, expand=False)
-        self._number_entry.show()
+        self._lower_box.pack_start(self._number_entry, expand=False)
 
         self._apn_entry = ApnEntry(model)
         self._apn_entry.connect('notify::is-valid',
                                 self.__notify_is_valid_cb)
-        self.pack_start(self._apn_entry, expand=False)
-        self._apn_entry.show()
+        self._lower_box.pack_start(self._apn_entry, expand=False)
 
         self.setup()
+        self.show_all()
 
     def setup(self):
         self._username_entry.set_text_from_model()
@@ -176,6 +225,24 @@
     def undo(self):
         self._model.undo()
 
+    def _country_selected(self, combo):
+	model = combo.get_model()
+	providers = model.get_row_providers(combo.get_active())
+	self._prov_combo.set_model(self._model.ProviderListStore(providers))
+
+    def _provider_selected(self, combo):
+	model = combo.get_model()
+	plans = model.get_row_plans(combo.get_active())
+	self._plan_combo.set_model(self._model.PlanListStore(plans))
+
+    def _plan_selected(self, combo):
+	model = combo.get_model()
+	plan = model.get_row_plan(combo.get_active())
+	self._username_entry.set_text(plan['username'])
+	self._password_entry.set_text(plan['password'])
+	self._number_entry.set_text(plan['number'])
+	self._apn_entry.set_text(plan['apn'])
+
     def _validate(self):
         if self._username_entry.is_valid and \
             self._password_entry.is_valid and \
