[Dextrose] [PATCH] Database support for 3G control panel

Anish Mangal anishmangal2002 at gmail.com
Wed Feb 2 10:52:57 EST 2011


committed to dx/mainline

http://git.sugarlabs.org/dextrose/mainline/commit/c6d7845fce52a9b0c345aea103e2d3672426dd61


On Tue, Jan 11, 2011 at 11:52, Martin Abente
<martin.abente.lahaye at gmail.com> wrote:
> From: Andrés Ambrois <andresambrois at gmail.com>
>
> For more information please look at #1630
>
> ---
>  configure.ac                                       |    1 +
>  .../cpsection/modemconfiguration/Makefile.am       |    2 +
>  .../cpsection/modemconfiguration/config.py.in      |   20 ++
>  extensions/cpsection/modemconfiguration/model.py   |  119 +++++++++++++
>  extensions/cpsection/modemconfiguration/view.py    |  184 ++++++++++++++++----
>  5 files changed, 292 insertions(+), 34 deletions(-)
>  create mode 100644 extensions/cpsection/modemconfiguration/config.py.in
>  mode change 100755 => 100644 extensions/cpsection/modemconfiguration/model.py
>
> diff --git a/configure.ac b/configure.ac
> index 13a2f09..68a8bf3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -56,6 +56,7 @@ extensions/cpsection/frame/Makefile
>  extensions/cpsection/keyboard/Makefile
>  extensions/cpsection/language/Makefile
>  extensions/cpsection/modemconfiguration/Makefile
> +extensions/cpsection/modemconfiguration/config.py
>  extensions/cpsection/Makefile
>  extensions/cpsection/network/Makefile
>  extensions/cpsection/power/Makefile
> diff --git a/extensions/cpsection/modemconfiguration/Makefile.am b/extensions/cpsection/modemconfiguration/Makefile.am
> index 3e2613e..525e02e 100644
> --- a/extensions/cpsection/modemconfiguration/Makefile.am
> +++ b/extensions/cpsection/modemconfiguration/Makefile.am
> @@ -4,3 +4,5 @@ sugar_PYTHON =          \
>        __init__.py     \
>        model.py        \
>        view.py
> +
> +nodist_sugar_PYTHON = config.py
> diff --git a/extensions/cpsection/modemconfiguration/config.py.in b/extensions/cpsection/modemconfiguration/config.py.in
> new file mode 100644
> index 0000000..6fa688e
> --- /dev/null
> +++ b/extensions/cpsection/modemconfiguration/config.py.in
> @@ -0,0 +1,20 @@
> +# -*- encoding: utf-8 -*-
> +# Copyright (C) 2010 Andrés Ambrois
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
> +
> +PROVIDERS_PATH = "@prefix@/share/mobile-broadband-provider-info/serviceproviders.xml"
> +PROVIDERS_FORMAT_SUPPORTED = "2.0"
> +COUNTRY_CODES_PATH = "@prefix@/share/zoneinfo/iso3166.tab"
> diff --git a/extensions/cpsection/modemconfiguration/model.py b/extensions/cpsection/modemconfiguration/model.py
> old mode 100755
> new mode 100644
> index 2545ce1..dbec47d
> --- a/extensions/cpsection/modemconfiguration/model.py
> +++ b/extensions/cpsection/modemconfiguration/model.py
> @@ -15,11 +15,22 @@
>  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
>
>  import gconf
> +import gtk
> +import os
> +import locale
> +import logging
> +
> +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, GSM_PIN_PATH, \
>                                  GSM_PUK_PATH
>
> +from cpsection.modemconfiguration.config import PROVIDERS_PATH, \
> +                                                PROVIDERS_FORMAT_SUPPORTED, \
> +                                                COUNTRY_CODES_PATH
> +
>  def get_username():
>     client = gconf.client_get_default()
>     return client.get_string(GSM_USERNAME_PATH) or ''
> @@ -68,3 +79,111 @@ def set_puk(puk):
>     client = gconf.client_get_default()
>     client.set_string(GSM_PUK_PATH, puk)
>
> +def has_providers_db():
> +    if not os.path.isfile(COUNTRY_CODES_PATH):
> +        logging.debug("Mobile broadband provider database: Country " \
> +                          "codes path %s not found.", COUNTRY_CODES_PATH)
> +        return False
> +    try:
> +        tree = ElementTree(file=PROVIDERS_PATH)
> +    except (IOError, SyntaxError), e:
> +        logging.debug("Mobile broadband provider database: Could not read " \
> +                          "provider information %s error=%s", PROVIDERS_PATH)
> +        return False
> +    else:
> +        elem = tree.getroot()
> +        if elem is None or elem.get('format') != PROVIDERS_FORMAT_SUPPORTED:
> +            logging.debug("Mobile broadband provider database: Could not " \
> +                          "read provider information. %s is wrong format.",
> +                          elem.get('format'))
> +            return False
> +        return True
> +
> +
> +class CountryListStore(gtk.ListStore):
> +    COUNTRY_CODE = locale.getdefaultlocale()[0][3:5].lower()
> +
> +    def __init__(self):
> +        gtk.ListStore.__init__(self, str, object)
> +        codes = {}
> +        with open(COUNTRY_CODES_PATH) as codes_file:
> +            for line in codes_file:
> +                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, row):
> +        return self[row][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, row):
> +        return self[row][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, row):
> +        return self[row][1]
> diff --git a/extensions/cpsection/modemconfiguration/view.py b/extensions/cpsection/modemconfiguration/view.py
> index b236f3f..3b03b3d 100644
> --- a/extensions/cpsection/modemconfiguration/view.py
> +++ b/extensions/cpsection/modemconfiguration/view.py
> @@ -14,8 +14,6 @@
>  # along with this program; if not, write to the Free Software
>  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
>
> -import os
> -import logging
>  from gettext import gettext as _
>
>  import gtk
> @@ -31,7 +29,7 @@ class EntryWithLabel(gtk.HBox):
>     __gtype_name__ = "SugarEntryWithLabel"
>
>     def __init__(self, label_text):
> -        gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING)
> +        gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING * 2)
>
>         self._timeout_sid = 0
>         self._changed_handler = None
> @@ -44,11 +42,11 @@ class EntryWithLabel(gtk.HBox):
>         self.pack_start(self.label, expand=False)
>         self.label.show()
>
> -        self._entry = gtk.Entry(25)
> -        self._entry.connect('changed', self.__entry_changed_cb)
> -        self._entry.set_width_chars(25)
> -        self.pack_start(self._entry, expand=False)
> -        self._entry.show()
> +        self.entry = gtk.Entry(25)
> +        self.entry.connect('changed', self.__entry_changed_cb)
> +        self.entry.set_width_chars(25)
> +        self.pack_start(self.entry, expand=False)
> +        self.entry.show()
>
>     def __entry_changed_cb(self, widget, data=None):
>         if self._timeout_sid:
> @@ -59,11 +57,11 @@ class EntryWithLabel(gtk.HBox):
>     def __timeout_cb(self):
>         self._timeout_sid = 0
>
> -        if self._entry.get_text() == self.get_value():
> +        if self.entry.get_text() == self.get_value():
>             return False
>
>         try:
> -            self.set_value(self._entry.get_text())
> +            self.set_value(self.entry.get_text())
>         except ValueError:
>             self._is_valid = False
>         else:
> @@ -74,18 +72,20 @@ class EntryWithLabel(gtk.HBox):
>         return False
>
>     def set_text_from_model(self):
> -        self._entry.set_text(self.get_value())
> +        self.entry.set_text(self.get_value())
>
>     def get_value(self):
>         raise NotImplementedError
>
> -    def set_value(self):
> +    def set_value(self, value):
>         raise NotImplementedError
>
>     def _get_is_valid(self):
>         return self._is_valid
> +
>     is_valid = gobject.property(type=bool, getter=_get_is_valid, default=True)
>
> +
>  class UsernameEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Username:'))
> @@ -97,6 +97,7 @@ class UsernameEntry(EntryWithLabel):
>     def set_value(self, username):
>         self._model.set_username(username)
>
> +
>  class PasswordEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Password:'))
> @@ -108,6 +109,7 @@ class PasswordEntry(EntryWithLabel):
>     def set_value(self, password):
>         self._model.set_password(password)
>
> +
>  class NumberEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Number:'))
> @@ -119,6 +121,7 @@ class NumberEntry(EntryWithLabel):
>     def set_value(self, number):
>         self._model.set_number(number)
>
> +
>  class ApnEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Access Point Name (APN):'))
> @@ -130,6 +133,7 @@ class ApnEntry(EntryWithLabel):
>     def set_value(self, apn):
>         self._model.set_apn(apn)
>
> +
>  class PinEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Personal Identity Number (PIN):'))
> @@ -141,6 +145,7 @@ class PinEntry(EntryWithLabel):
>     def set_value(self, pin):
>         self._model.set_pin(pin)
>
> +
>  class PukEntry(EntryWithLabel):
>     def __init__(self, model):
>         EntryWithLabel.__init__(self, _('Personal Unblocking Key (PUK):'))
> @@ -160,61 +165,150 @@ class ModemConfiguration(SectionView):
>         self._model = model
>         self.restart_alerts = alerts
>
> -        self.set_border_width(style.DEFAULT_SPACING)
>         self.set_spacing(style.DEFAULT_SPACING)
> -        self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
> +
> +        label_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
> +        combo_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
> +
> +        scrolled_win = gtk.ScrolledWindow()
> +        scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
> +        scrolled_win.show()
> +        self.add(scrolled_win)
> +
> +        main_box = gtk.VBox(spacing=style.DEFAULT_SPACING)
> +        main_box.set_border_width(style.DEFAULT_SPACING)
> +        main_box.show()
> +        scrolled_win.add_with_viewport(main_box)
>
>         explanation = _("You will need to provide the following " \
>                             "information to set up a mobile " \
>                             "broadband connection to a cellular "\
>                             "(3G) network.")
>         self._text = gtk.Label(explanation)
> -        self._text.set_width_chars(100)
>         self._text.set_line_wrap(True)
>         self._text.set_alignment(0, 0)
> -        self.pack_start(self._text, False)
> +        main_box.pack_start(self._text, False)
>         self._text.show()
>
> +        if model.has_providers_db():
> +            self._upper_box = gtk.VBox(spacing=style.DEFAULT_SPACING)
> +            self._upper_box.set_border_width(style.DEFAULT_SPACING)
> +            main_box.pack_start(self._upper_box, expand=False)
> +            self._upper_box.show()
> +
> +
> +            box = gtk.HBox(spacing=style.DEFAULT_SPACING * 2)
> +            label = gtk.Label(_('Country:'))
> +            label.set_alignment(1, 0.5)
> +            label_group.add_widget(label)
> +            box.pack_start(label, False)
> +            label.show()
> +            country_store = model.CountryListStore()
> +            country_combo = gtk.ComboBox(country_store)
> +            combo_group.add_widget(country_combo)
> +            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_cb)
> +            box.pack_start(country_combo, False)
> +            country_combo.show()
> +            self._upper_box.pack_start(box, False)
> +            box.show()
> +
> +            box = gtk.HBox(spacing=style.DEFAULT_SPACING * 2)
> +            label = gtk.Label(_('Provider:'))
> +            label.set_alignment(1, 0.5)
> +            label_group.add_widget(label)
> +            box.pack_start(label, False)
> +            label.show()
> +            self._providers_combo = gtk.ComboBox()
> +            combo_group.add_widget(self._providers_combo)
> +            cell = gtk.CellRendererText()
> +            cell.props.xalign = 0.5
> +            self._providers_combo.pack_start(cell)
> +            self._providers_combo.add_attribute(cell, 'text', 0)
> +            self._providers_combo.connect('changed',
> +                                          self.__provider_selected_cb)
> +            box.pack_start(self._providers_combo, False)
> +            self._providers_combo.show()
> +            self._upper_box.pack_start(box, False)
> +            box.show()
> +
> +            box = gtk.HBox(spacing=style.DEFAULT_SPACING*2)
> +            label = gtk.Label(_('Plan:'))
> +            label.set_alignment(1, 0.5)
> +            label_group.add_widget(label)
> +            box.pack_start(label, False)
> +            label.show()
> +            self._plan_combo = gtk.ComboBox()
> +            combo_group.add_widget(self._plan_combo)
> +            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_cb)
> +            box.pack_start(self._plan_combo, False)
> +            self._plan_combo.show()
> +            self._upper_box.pack_start(box, False)
> +            box.show()
> +
> +            country_combo.set_active(country_store.guess_country_row())
> +
> +            separator = gtk.HSeparator()
> +            main_box.pack_start(separator, False)
> +            separator.show()
> +
> +        self._lower_box = gtk.VBox(spacing=style.DEFAULT_SPACING)
> +        self._lower_box.set_border_width(style.DEFAULT_SPACING)
> +        main_box.pack_start(self._lower_box, expand=False)
> +        self._lower_box.show()
> +
>         self._username_entry = UsernameEntry(model)
>         self._username_entry.connect('notify::is-valid',
>                                      self.__notify_is_valid_cb)
> -        self._group.add_widget(self._username_entry.label)
> -        self.pack_start(self._username_entry, expand=False)
> +        label_group.add_widget(self._username_entry.label)
> +        combo_group.add_widget(self._username_entry.entry)
> +        self._lower_box.pack_start(self._username_entry, fill=False)
>         self._username_entry.show()
>
>         self._password_entry = PasswordEntry(model)
>         self._password_entry.connect('notify::is-valid',
>                                      self.__notify_is_valid_cb)
> -        self._group.add_widget(self._password_entry.label)
> -        self.pack_start(self._password_entry, expand=False)
> +        label_group.add_widget(self._password_entry.label)
> +        combo_group.add_widget(self._password_entry.entry)
> +        self._lower_box.pack_start(self._password_entry, fill=False)
>         self._password_entry.show()
>
>         self._number_entry = NumberEntry(model)
>         self._number_entry.connect('notify::is-valid',
>                                    self.__notify_is_valid_cb)
> -        self._group.add_widget(self._number_entry.label)
> -        self.pack_start(self._number_entry, expand=False)
> +        label_group.add_widget(self._number_entry.label)
> +        combo_group.add_widget(self._number_entry.entry)
> +        self._lower_box.pack_start(self._number_entry, fill=False)
>         self._number_entry.show()
>
>         self._apn_entry = ApnEntry(model)
>         self._apn_entry.connect('notify::is-valid',
>                                 self.__notify_is_valid_cb)
> -        self._group.add_widget(self._apn_entry.label)
> -        self.pack_start(self._apn_entry, expand=False)
> +        label_group.add_widget(self._apn_entry.label)
> +        combo_group.add_widget(self._apn_entry.entry)
> +        self._lower_box.pack_start(self._apn_entry, fill=False)
>         self._apn_entry.show()
>
>         self._pin_entry = PinEntry(model)
>         self._pin_entry.connect('notify::is-valid',
>                                 self.__notify_is_valid_cb)
> -        self._group.add_widget(self._pin_entry.label)
> -        self.pack_start(self._pin_entry, expand=False)
> +        label_group.add_widget(self._pin_entry.label)
> +        self._lower_box.pack_start(self._pin_entry, fill=False)
>         self._pin_entry.show()
>
>         self._puk_entry = PukEntry(model)
>         self._puk_entry.connect('notify::is-valid',
>                                 self.__notify_is_valid_cb)
> -        self._group.add_widget(self._puk_entry.label)
> -        self.pack_start(self._puk_entry, expand=False)
> +        label_group.add_widget(self._puk_entry.label)
> +        combo_group.add_widget(self._puk_entry.entry)
> +        self._lower_box.pack_start(self._puk_entry, fill=False)
>         self._puk_entry.show()
>
>         self.setup()
> @@ -232,14 +326,37 @@ class ModemConfiguration(SectionView):
>     def undo(self):
>         self._model.undo()
>
> +    def __country_selected_cb(self, combo):
> +        model = combo.get_model()
> +        providers = model.get_row_providers(combo.get_active())
> +        self._providers_combo.set_model(
> +            self._model.ProviderListStore(providers))
> +
> +    def __provider_selected_cb(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_cb(self, combo):
> +        model = combo.get_model()
> +        plan = model.get_row_plan(combo.get_active())
> +        self._username_entry.set_value(plan['username'])
> +        self._username_entry.set_text_from_model()
> +        self._password_entry.set_value(plan['password'])
> +        self._password_entry.set_text_from_model()
> +        self._number_entry.set_value(plan['number'])
> +        self._number_entry.set_text_from_model()
> +        self._apn_entry.set_value(plan['apn'])
> +        self._apn_entry.set_text_from_model()
> +
>     def _validate(self):
>         if self._username_entry.is_valid and \
> -            self._password_entry.is_valid and \
> +                self._password_entry.is_valid and \
>                 self._number_entry.is_valid and \
> -                    self._apn_entry.is_valid and \
> -                        self._pin_entry.is_valid and \
> -                            self._puk_entry.is_valid:
> -                                self.props.is_valid = True
> +                self._apn_entry.is_valid and \
> +                self._pin_entry.is_valid and \
> +                self._puk_entry.is_valid:
> +            self.props.is_valid = True
>         else:
>             self.props.is_valid = False
>
> @@ -247,4 +364,3 @@ class ModemConfiguration(SectionView):
>         if entry.is_valid:
>             self.needs_restart = True
>         self._validate()
> -
> --
> 1.7.1
>
>
> _______________________________________________
> Dextrose mailing list
> Dextrose at lists.sugarlabs.org
> http://lists.sugarlabs.org/listinfo/dextrose
>
>



-- 
Anish


More information about the Dextrose mailing list