A yet another gentle reminder :D<br><br>Thanks and Regards,<br>Ajay<br><br><br><div class="gmail_quote">On Wed, Aug 1, 2012 at 1:44 AM, Ajay Garg <span dir="ltr"><<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all.<br><br>Just a gentle reminder :)<br>Or, at least a status update will be highly appreciated :)<br>
<br>Thanks and Regards,<br>Ajay<div class="HOEnZb"><div class="h5"><br><br><div class="gmail_quote">On Sun, Jul 29, 2012 at 2:49 PM, Ajay Garg <span dir="ltr"><<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all.<br><br>Kindly review the patch, so that progress may be made in pushing this :)<br><br><br>
Thanks and Regards,<br>
Ajay<div><div><br><br><br><div class="gmail_quote">On Fri, Jul 20, 2012 at 5:02 PM, Ajay Garg <span dir="ltr"><<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
First of all, please note that the first, major part of adding the database support<br>
has been done by ::<br>
<br>
              Andres Ambrois <<a href="mailto:andresambrois@gmail.com" target="_blank">andresambrois@gmail.com</a>><br>
<br>
Details of Andres's work are present at <a href="http://bugs.sugarlabs.org/ticket/1630" target="_blank">http://bugs.sugarlabs.org/ticket/1630</a><br>
<br>
<br>
===============================================================================<br>
<br>
<br>
So, this patch ::<br>
<br>
   a)<br>
   Ports Andres's patch from Sugar-0.88 to Sugar-0.98.<br>
<br>
   b)<br>
   Adds the functionality, to keep the "Country, Provider, Plan" settings<br>
   persisted as well.<br>
<br>
   c)<br>
   Also, some refactoring has been done, to avoid duplicate code as much as possible.<br>
<br>
<br>
================================================================================<br>
<br>
<br>
Other relevant literature/discussions/logs at ::<br>
<br>
   a) Wiki Feature Page ::<br>
   <a href="http://wiki.sugarlabs.org/go/Features/3G_Support/Database_Support" target="_blank">http://wiki.sugarlabs.org/go/Features/3G_Support/Database_Support</a><br>
<br>
   b)<br>
   Feature Design ML ::<br>
   <a href="http://lists.sugarlabs.org/archive/sugar-devel/2012-July/038429.html" target="_blank">http://lists.sugarlabs.org/archive/sugar-devel/2012-July/038429.html</a><br>
<br>
   c)<br>
   Brain-storming / Go-ahead meeting logs ::<br>
   <a href="http://meeting.sugarlabs.org/sugar-meeting/meetings/2012-07-18T15:00:17" target="_blank">http://meeting.sugarlabs.org/sugar-meeting/meetings/2012-07-18T15:00:17</a><br>
<br>
<br>
================================================================================<br>
<br>
<br>
This patch has been tested to work on NM 0.9.<br>
<br>
The 3G modem gets connected, only and only when the correct entries are entered<br>
(by choosing the correct plan, amongst the vast number of available plans).<br>
<br>
<br>
================================================================================<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
 .../cpsection/modemconfiguration/Makefile.am       |    2 +<br>
 extensions/cpsection/modemconfiguration/config.py  |   25 +++<br>
 extensions/cpsection/modemconfiguration/model.py   |  163 ++++++++++++++++<br>
 extensions/cpsection/modemconfiguration/view.py    |  198 +++++++++++++++++---<br>
 4 files changed, 365 insertions(+), 23 deletions(-)<br>
 create mode 100644 extensions/cpsection/modemconfiguration/config.py<br>
<br>
diff --git a/extensions/cpsection/modemconfiguration/Makefile.am b/extensions/cpsection/modemconfiguration/Makefile.am<br>
index 3e2613e..525e02e 100644<br>
--- a/extensions/cpsection/modemconfiguration/Makefile.am<br>
+++ b/extensions/cpsection/modemconfiguration/Makefile.am<br>
@@ -4,3 +4,5 @@ sugar_PYTHON =          \<br>
        __init__.py     \<br>
        model.py        \<br>
        view.py<br>
+<br>
+nodist_sugar_PYTHON = config.py<br>
diff --git a/extensions/cpsection/modemconfiguration/config.py b/extensions/cpsection/modemconfiguration/config.py<br>
new file mode 100644<br>
index 0000000..963616d<br>
--- /dev/null<br>
+++ b/extensions/cpsection/modemconfiguration/config.py<br>
@@ -0,0 +1,25 @@<br>
+# -*- encoding: utf-8 -*-<br>
+# Copyright (C) 2010 Andres Ambrois<br>
+#<br>
+# This program is free software; you can redistribute it and/or modify<br>
+# it under the terms of the GNU General Public License as published by<br>
+# the Free Software Foundation; either version 2 of the License, or<br>
+# (at your option) any later version.<br>
+#<br>
+# This program is distributed in the hope that it will be useful,<br>
+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
+# GNU General Public License for more details.<br>
+#<br>
+# You should have received a copy of the GNU General Public License<br>
+# along with this program; if not, write to the Free Software<br>
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US<br>
+<br>
+<br>
+PROVIDERS_PATH = "/usr/share/mobile-broadband-provider-info/serviceproviders.xml"<br>
+PROVIDERS_FORMAT_SUPPORTED = "2.0"<br>
+COUNTRY_CODES_PATH = "/usr/share/zoneinfo/iso3166.tab"<br>
+<br>
+GSM_COUNTRY_PATH = '/desktop/sugar/network/gsm/country'<br>
+GSM_PROVIDERS_PATH = '/desktop/sugar/network/gsm/providers'<br>
+GSM_PLAN_PATH = '/desktop/sugar/network/gsm/plan'<br>
diff --git a/extensions/cpsection/modemconfiguration/model.py b/extensions/cpsection/modemconfiguration/model.py<br>
index 969b5d9..2e4cd7d 100755<br>
--- a/extensions/cpsection/modemconfiguration/model.py<br>
+++ b/extensions/cpsection/modemconfiguration/model.py<br>
@@ -1,4 +1,8 @@<br>
 # Copyright (C) 2009 Paraguay Educa, Martin Abente<br>
+# Copyright (C) 2010 Andres Ambrois <<a href="mailto:andresambrois@gmail.com" target="_blank">andresambrois@gmail.com</a>><br>
+# Copyright (C) 2010 Anish Mangal   <<a href="mailto:anish@activitycentral.com" target="_blank">anish@activitycentral.com</a>><br>
+# Copyright (C) 2012 Ajay Garg      <<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>><br>
+<br>
 #<br>
 # This program is free software; you can redistribute it and/or modify<br>
 # it under the terms of the GNU General Public License as published by<br>
@@ -18,10 +22,22 @@ import logging<br>
<br>
 import dbus<br>
 import gtk<br>
+import os<br>
+import locale<br>
+import logging<br>
+import gconf<br>
+<br>
+from xml.etree.cElementTree import ElementTree<br>
+from gettext import gettext as _<br>
<br>
 from jarabe.model import network<br>
<br>
<br>
+from cpsection.modemconfiguration.config import PROVIDERS_PATH, \<br>
+                                                PROVIDERS_FORMAT_SUPPORTED, \<br>
+                                                COUNTRY_CODES_PATH<br>
+<br>
+<br>
 def get_connection():<br>
     return network.find_gsm_connection()<br>
<br>
@@ -98,3 +114,150 @@ def set_modem_settings(modem_settings):<br>
     _set_or_clear(gsm_settings, 'apn', apn)<br>
     _set_or_clear(gsm_settings, 'pin', pin)<br>
     connection.update_settings(settings)<br>
+<br>
+<br>
+def has_providers_db():<br>
+    if not os.path.isfile(COUNTRY_CODES_PATH):<br>
+        logging.debug("Mobile broadband provider database: Country " \<br>
+                          "codes path %s not found.", COUNTRY_CODES_PATH)<br>
+        return False<br>
+    try:<br>
+        tree = ElementTree(file=PROVIDERS_PATH)<br>
+    except (IOError, SyntaxError), e:<br>
+        logging.debug("Mobile broadband provider database: Could not read " \<br>
+                          "provider information %s error=%s", PROVIDERS_PATH)<br>
+        return False<br>
+    else:<br>
+        elem = tree.getroot()<br>
+        if elem is None or elem.get('format') != PROVIDERS_FORMAT_SUPPORTED:<br>
+            logging.debug("Mobile broadband provider database: Could not " \<br>
+                          "read provider information. %s is wrong format.",<br>
+                          elem.get('format'))<br>
+            return False<br>
+        return True<br>
+<br>
+<br>
+class CountryListStore(gtk.ListStore):<br>
+    COUNTRY_CODE = locale.getdefaultlocale()[0][3:5].lower()<br>
+<br>
+    def __init__(self):<br>
+        gtk.ListStore.__init__(self, str, object)<br>
+        codes = {}<br>
+        with open(COUNTRY_CODES_PATH) as codes_file:<br>
+            for line in codes_file:<br>
+                if line.startswith('#'):<br>
+                    continue<br>
+                code, name = line.split('\t')[:2]<br>
+                codes[code.lower()] = name.strip()<br>
+        etree = ElementTree(file=PROVIDERS_PATH).getroot()<br>
+        self._country_idx = None<br>
+        i = 0<br>
+        for elem in etree.findall('.//country'):<br>
+            code = elem.attrib['code']<br>
+            if code == self.COUNTRY_CODE:<br>
+                self._country_idx = i<br>
+            else:<br>
+                i += 1<br>
+            if code in codes:<br>
+                self.append((codes[code], elem))<br>
+            else:<br>
+                self.append((code, elem))<br>
+<br>
+    def get_row_providers(self, row):<br>
+        return self[row][1]<br>
+<br>
+    def guess_country_row(self):<br>
+        if self._country_idx is not None:<br>
+            return self._country_idx<br>
+        else:<br>
+            return 0<br>
+<br>
+    def search_index_by_code(self, code):<br>
+        for index in range(0, len(self)):<br>
+            if self[index][0] == code:<br>
+                return index<br>
+        return -1<br>
+<br>
+<br>
+class ProviderListStore(gtk.ListStore):<br>
+    def __init__(self, elem):<br>
+        gtk.ListStore.__init__(self, str, object)<br>
+        for provider_elem in elem.findall('.//provider'):<br>
+            apns = provider_elem.findall('.//apn')<br>
+            if not apns:<br>
+                # Skip carriers with CDMA entries only<br>
+                continue<br>
+            self.append((provider_elem.find('.//name').text, apns))<br>
+<br>
+    def get_row_plans(self, row):<br>
+        return self[row][1]<br>
+<br>
+    def guess_providers_row(self):<br>
+        # Simply return the first entry as the default.<br>
+        return 0<br>
+<br>
+    def search_index_by_code(self, code):<br>
+        for index in range(0, len(self)):<br>
+            if self[index][0] == code:<br>
+                return index<br>
+        return -1<br>
+<br>
+<br>
+class PlanListStore(gtk.ListStore):<br>
+    LANG_NS_ATTR = '{<a href="http://www.w3.org/XML/1998/namespace%7Dlang" target="_blank">http://www.w3.org/XML/1998/namespace}lang</a>'<br>
+    LANG = locale.getdefaultlocale()[0][:2]<br>
+    DEFAULT_NUMBER = '*99#'<br>
+<br>
+    def __init__(self, elems):<br>
+        gtk.ListStore.__init__(self, str, object)<br>
+        for apn_elem in elems:<br>
+            plan = {}<br>
+            names = apn_elem.findall('.//name')<br>
+            if names:<br>
+                for name in names:<br>
+                    if name.get(self.LANG_NS_ATTR) is None:<br>
+                        # serviceproviders.xml default value<br>
+                        plan['name'] = name.text<br>
+                    elif name.get(self.LANG_NS_ATTR) == self.LANG:<br>
+                        # Great! We found a name value for our locale!<br>
+                        plan['name'] = name.text<br>
+                        break<br>
+            else:<br>
+                plan['name'] = _('Default')<br>
+            plan['apn'] = apn_elem.get('value')<br>
+            user = apn_elem.find('.//username')<br>
+            if user is not None:<br>
+                plan['username'] = user.text<br>
+            else:<br>
+                plan['username'] = ''<br>
+            passwd = apn_elem.find('.//password')<br>
+            if passwd is not None:<br>
+                plan['password'] = passwd.text<br>
+            else:<br>
+                plan['password'] = ''<br>
+<br>
+            plan['number'] = self.DEFAULT_NUMBER<br>
+<br>
+            self.append((plan['name'], plan))<br>
+<br>
+    def get_row_plan(self, row):<br>
+        return self[row][1]<br>
+<br>
+    def guess_plan_row(self):<br>
+        # Simply return the first entry as the default.<br>
+        return 0<br>
+<br>
+    def search_index_by_code(self, code):<br>
+        for index in range(0, len(self)):<br>
+            if self[index][0] == code:<br>
+                return index<br>
+        return -1<br>
+<br>
+<br>
+def get_gconf_setting_string(gconf_key):<br>
+    client = gconf.client_get_default()<br>
+    return client.get_string(gconf_key) or ''<br>
+<br>
+def set_gconf_setting_string(gconf_key, gconf_setting_string_value):<br>
+    client = gconf.client_get_default()<br>
+    client.set_string(gconf_key, gconf_setting_string_value)<br>
diff --git a/extensions/cpsection/modemconfiguration/view.py b/extensions/cpsection/modemconfiguration/view.py<br>
index 4ce6c0d..68a4b3d 100644<br>
--- a/extensions/cpsection/modemconfiguration/view.py<br>
+++ b/extensions/cpsection/modemconfiguration/view.py<br>
@@ -1,4 +1,7 @@<br>
 # Copyright (C) 2009 Paraguay Educa, Martin Abente<br>
+# Copyright (C) 2010 Andres Ambrois <<a href="mailto:andresambrois@gmail.com" target="_blank">andresambrois@gmail.com</a>><br>
+# Copyright (C) 2010 Anish Mangal   <<a href="mailto:anish@activitycentral.com" target="_blank">anish@activitycentral.com</a>><br>
+# Copyright (C) 2012 Ajay Garg      <<a href="mailto:ajay@activitycentral.com" target="_blank">ajay@activitycentral.com</a>><br>
 #<br>
 # This program is free software; you can redistribute it and/or modify<br>
 # it under the terms of the GNU General Public License as published by<br>
@@ -24,6 +27,11 @@ from sugar.graphics import style<br>
<br>
 from jarabe.controlpanel.sectionview import SectionView<br>
<br>
+from cpsection.modemconfiguration.config import GSM_COUNTRY_PATH, \<br>
+                                                GSM_PROVIDERS_PATH, \<br>
+                                                GSM_PLAN_PATH<br>
+<br>
+<br>
<br>
 APPLY_TIMEOUT = 1000<br>
<br>
@@ -63,6 +71,17 @@ class ModemConfiguration(SectionView):<br>
         self.set_border_width(style.DEFAULT_SPACING)<br>
         self.set_spacing(style.DEFAULT_SPACING)<br>
         self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)<br>
+        self._combo_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)<br>
+<br>
+        scrolled_win = gtk.ScrolledWindow()<br>
+        scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)<br>
+        scrolled_win.show()<br>
+        self.add(scrolled_win)<br>
+<br>
+        main_box = gtk.VBox(spacing=style.DEFAULT_SPACING)<br>
+        main_box.set_border_width(style.DEFAULT_SPACING)<br>
+        main_box.show()<br>
+        scrolled_win.add_with_viewport(main_box)<br>
<br>
         explanation = _('You will need to provide the following information'<br>
                         ' to set up a mobile broadband connection to a'<br>
@@ -71,41 +90,85 @@ class ModemConfiguration(SectionView):<br>
         self._text.set_width_chars(100)<br>
         self._text.set_line_wrap(True)<br>
         self._text.set_alignment(0, 0)<br>
-        self.pack_start(self._text, False)<br>
+        main_box.pack_start(self._text, False)<br>
         self._text.show()<br>
<br>
+<br>
+<br>
+        if model.has_providers_db():<br>
+            self._upper_box = gtk.VBox(spacing=style.DEFAULT_SPACING)<br>
+            self._upper_box.set_border_width(style.DEFAULT_SPACING)<br>
+            main_box.pack_start(self._upper_box, expand=False)<br>
+            self._upper_box.show()<br>
+<br>
+            # Do not attach any 'change'-handlers for now.<br>
+            # They will be attached (once per combobox), once the<br>
+            # individual combobox is processed at startup.<br>
+            self._country_store = model.CountryListStore()<br>
+            self._country_combo = gtk.ComboBox(self._country_store)<br>
+            self._attach_combobox_widget(_('Country:'),<br>
+                                         self._country_combo)<br>
+<br>
+            self._providers_combo = gtk.ComboBox()<br>
+            self._attach_combobox_widget(_('Provider:'),<br>
+                                         self._providers_combo)<br>
+<br>
+            self._plan_combo = gtk.ComboBox()<br>
+            self._attach_combobox_widget(_('Plan:'),<br>
+                                         self._plan_combo)<br>
+<br>
+            separator = gtk.HSeparator()<br>
+            main_box.pack_start(separator, False)<br>
+            separator.show()<br>
+<br>
+        self._lower_box = gtk.VBox(spacing=style.DEFAULT_SPACING)<br>
+        self._lower_box.set_border_width(style.DEFAULT_SPACING)<br>
+        main_box.pack_start(self._lower_box, expand=False)<br>
+        self._lower_box.show()<br>
+<br>
         self._username_entry = EntryWithLabel(_('Username:'))<br>
-        self._username_entry.entry.connect('changed', self.__entry_changed_cb)<br>
-        self._group.add_widget(self._username_entry.label)<br>
-        self.pack_start(self._username_entry, expand=False)<br>
-        self._username_entry.show()<br>
+        self._attach_entry_widget(self._username_entry)<br>
<br>
         self._password_entry = EntryWithLabel(_('Password:'))<br>
-        self._password_entry.entry.connect('changed', self.__entry_changed_cb)<br>
-        self._group.add_widget(self._password_entry.label)<br>
-        self.pack_start(self._password_entry, expand=False)<br>
-        self._password_entry.show()<br>
+        self._attach_entry_widget(self._password_entry)<br>
<br>
         self._number_entry = EntryWithLabel(_('Number:'))<br>
-        self._number_entry.entry.connect('changed', self.__entry_changed_cb)<br>
-        self._group.add_widget(self._number_entry.label)<br>
-        self.pack_start(self._number_entry, expand=False)<br>
-        self._number_entry.show()<br>
+        self._attach_entry_widget(self._number_entry)<br>
<br>
         self._apn_entry = EntryWithLabel(_('Access Point Name (APN):'))<br>
-        self._apn_entry.entry.connect('changed', self.__entry_changed_cb)<br>
-        self._group.add_widget(self._apn_entry.label)<br>
-        self.pack_start(self._apn_entry, expand=False)<br>
-        self._apn_entry.show()<br>
+        self._attach_entry_widget(self._apn_entry)<br>
<br>
         self._pin_entry = EntryWithLabel(_('Personal Identity Number (PIN):'))<br>
-        self._pin_entry.entry.connect('changed', self.__entry_changed_cb)<br>
-        self._group.add_widget(self._pin_entry.label)<br>
-        self.pack_start(self._pin_entry, expand=False)<br>
-        self._pin_entry.show()<br>
+        self._attach_entry_widget(self._pin_entry)<br>
<br>
         self.setup()<br>
<br>
+    def _attach_combobox_widget(self, label_text, combobox_obj):<br>
+        box = gtk.HBox(spacing=style.DEFAULT_SPACING)<br>
+        label = gtk.Label(label_text)<br>
+        self._group.add_widget(label)<br>
+        label.set_alignment(1, 0.5)<br>
+        box.pack_start(label, False)<br>
+        label.show()<br>
+<br>
+        self._combo_group.add_widget(combobox_obj)<br>
+        cell = gtk.CellRendererText()<br>
+        cell.props.xalign = 0.5<br>
+        cell.set_property('width-chars', 25)<br>
+        combobox_obj.pack_start(cell)<br>
+        combobox_obj.add_attribute(cell, 'text', 0)<br>
+<br>
+        box.pack_start(combobox_obj, False)<br>
+        combobox_obj.show()<br>
+        self._upper_box.pack_start(box, False)<br>
+        box.show()<br>
+<br>
+    def _attach_entry_widget(self, entry_with_label_obj):<br>
+        entry_with_label_obj.entry.connect('changed', self.__entry_changed_cb)<br>
+        self._group.add_widget(entry_with_label_obj.label)<br>
+        self._lower_box.pack_start(entry_with_label_obj, expand=False)<br>
+        entry_with_label_obj.show()<br>
+<br>
     def undo(self):<br>
         self._model.undo()<br>
<br>
@@ -113,11 +176,28 @@ class ModemConfiguration(SectionView):<br>
         """Populate an entry with text, without triggering its 'changed'<br>
         handler."""<br>
         entry = entrywithlabel.entry<br>
-        entry.handler_block_by_func(self.__entry_changed_cb)<br>
+<br>
+        # Do not block/unblock the callback functions.<br>
+        #<br>
+        # Thus, the savings will be persisted to the NM settings,<br>
+        # whenever any setting on the UI changes (by user-intervention,<br>
+        # or otherwise).<br>
+        #entry.handler_block_by_func(self.__entry_changed_cb)<br>
         entry.set_text(text)<br>
-        entry.handler_unblock_by_func(self.__entry_changed_cb)<br>
+        #entry.handler_unblock_by_func(self.__entry_changed_cb)<br>
<br>
     def setup(self):<br>
+        if self._model.has_providers_db():<br>
+            persisted_country = self._model.get_gconf_setting_string(GSM_COUNTRY_PATH)<br>
+            if (self._model.has_providers_db()) and (persisted_country != ''):<br>
+                self._country_combo.set_active(self._country_store.search_index_by_code(persisted_country))<br>
+            else:<br>
+                self._country_combo.set_active(self._country_store.guess_country_row())<br>
+<br>
+            # Call the selected callback anyway, so as to chain-set the<br>
+            # default values for providers and the plans.<br>
+            self.__country_selected_cb(self._country_combo, setup=True)<br>
+<br>
         settings = self._model.get_modem_settings()<br>
         self._populate_entry(self._username_entry,<br>
             settings.get('username', ''))<br>
@@ -133,6 +213,78 @@ class ModemConfiguration(SectionView):<br>
         self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT,<br>
                                                 self.__timeout_cb)<br>
<br>
+    def _get_selected_text(self, combo):<br>
+        active_iter = combo.get_active_iter()<br>
+        return combo.get_model().get(active_iter, 0)[0]<br>
+<br>
+    def __country_selected_cb(self, combo, setup=False):<br>
+        country = self._get_selected_text(combo)<br>
+        self._model.set_gconf_setting_string(GSM_COUNTRY_PATH, country)<br>
+<br>
+        model = combo.get_model()<br>
+        providers = model.get_row_providers(combo.get_active())<br>
+        self._providers_liststore = self._model.ProviderListStore(providers)<br>
+        self._providers_combo.set_model(self._providers_liststore)<br>
+<br>
+        # Set the default provider as well.<br>
+        if setup:<br>
+            persisted_provider = self._model.get_gconf_setting_string(GSM_PROVIDERS_PATH)<br>
+            if persisted_provider == '':<br>
+                self._providers_combo.set_active(self._providers_liststore.guess_providers_row())<br>
+            else:<br>
+                self._providers_combo.set_active(self._providers_liststore.search_index_by_code(persisted_provider))<br>
+        else:<br>
+            self._providers_combo.set_active(self._providers_liststore.guess_providers_row())<br>
+<br>
+        # Country-combobox processed once at startip; now, attach the<br>
+        # change-handler.<br>
+        self._country_combo.connect('changed', self.__country_selected_cb, False)<br>
+<br>
+        # Call the callback, so that default provider may be set.<br>
+        self.__provider_selected_cb(self._providers_combo, setup)<br>
+<br>
+    def __provider_selected_cb(self, combo, setup=False):<br>
+        provider = self._get_selected_text(combo)<br>
+        self._model.set_gconf_setting_string(GSM_PROVIDERS_PATH,  provider)<br>
+<br>
+        model = combo.get_model()<br>
+        plans = model.get_row_plans(combo.get_active())<br>
+        self._plan_liststore = self._model.PlanListStore(plans)<br>
+        self._plan_combo.set_model(self._plan_liststore)<br>
+<br>
+        # Set the default plan as well.<br>
+        if setup:<br>
+            persisted_plan = self._model.get_gconf_setting_string(GSM_PLAN_PATH)<br>
+            if persisted_plan == '':<br>
+                self._plan_combo.set_active(self._plan_liststore.guess_plan_row())<br>
+            else:<br>
+                self._plan_combo.set_active(self._plan_liststore.search_index_by_code(persisted_plan))<br>
+        else:<br>
+            self._plan_combo.set_active(self._plan_liststore.guess_plan_row())<br>
+<br>
+        # Providers-combobox processed once at startip; now, attach the<br>
+        # change-handler.<br>
+        self._providers_combo.connect('changed', self.__provider_selected_cb, False)<br>
+<br>
+        # Call the callback, so that the default plan is set.<br>
+        self.__plan_selected_cb(self._plan_combo, setup)<br>
+<br>
+    def __plan_selected_cb(self, combo, setup=False):<br>
+        plan = self._get_selected_text(combo)<br>
+        self._model.set_gconf_setting_string(GSM_PLAN_PATH, plan)<br>
+<br>
+        # Plan-combobox processed once at startip; now, attach the<br>
+        # change-handler.<br>
+        self._plan_combo.connect('changed', self.__plan_selected_cb, False)<br>
+<br>
+        model = combo.get_model()<br>
+        plan = model.get_row_plan(combo.get_active())<br>
+<br>
+        self._populate_entry(self._username_entry, plan['username'])<br>
+        self._populate_entry(self._password_entry, plan['password'])<br>
+        self._populate_entry(self._apn_entry, plan['apn'])<br>
+        self._populate_entry(self._number_entry, plan['number'])<br>
+<br>
     def __timeout_cb(self):<br>
         self._timeout_sid = 0<br>
         settings = {}<br>
<span><font color="#888888">--<br>
1.7.10.2<br>
<br>
</font></span></blockquote></div><br>
</div></div></blockquote></div><br>
</div></div></blockquote></div><br>