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<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">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">andresambrois@gmail.com</a>><br>
+# Copyright (C) 2010 Anish Mangal <<a href="mailto:anish@activitycentral.com">anish@activitycentral.com</a>><br>
+# Copyright (C) 2012 Ajay Garg <<a href="mailto:ajay@activitycentral.com">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">andresambrois@gmail.com</a>><br>
+# Copyright (C) 2010 Anish Mangal <<a href="mailto:anish@activitycentral.com">anish@activitycentral.com</a>><br>
+# Copyright (C) 2012 Ajay Garg <<a href="mailto:ajay@activitycentral.com">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 class="HOEnZb"><font color="#888888">--<br>
1.7.10.2<br>
<br>
</font></span></blockquote></div><br>