From 834d8070102ffceae5b4e002a502257d784f25a7 Mon Sep 17 00:00:00 2001
From: latu <latu@localhost.localdomain>
Date: Fri, 26 Feb 2010 16:48:23 -0200
Subject: [PATCH 2/2] Showing Errors - Palette Mockup

---
 extensions/deviceicon/network.py |  176 +++++++++++++++++++++++++-------------
 src/jarabe/model/network.py      |   70 +++++++++++++---
 2 files changed, 176 insertions(+), 70 deletions(-)

diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index fc72b6d..b4296d1 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -39,6 +39,9 @@ from sugar.graphics.tray import TrayIcon
 from sugar.graphics import xocolor
 from sugar.util import unique_id
 from sugar import profile
+from sugar.graphics.icon import Icon
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics.alert import NotifyAlert
 
 from jarabe.model import network
 from jarabe.model.network import Settings
@@ -63,7 +66,7 @@ _GSM_STATE_NOT_READY = 0
 _GSM_STATE_DISCONNECTED = 1
 _GSM_STATE_CONNECTING = 2
 _GSM_STATE_CONNECTED = 3
-_GSM_STATE_NEED_AUTH = 4
+_GSM_STATE_FAILED = 4
 
 def frequency_to_channel(frequency):
     ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
@@ -214,6 +217,7 @@ class WiredPalette(Palette):
             ip_address_text = ""
         self._ip_address_label.set_text(ip_address_text)
 
+
 class GsmPalette(Palette):
     __gtype_name__ = 'SugarGsmPalette'
 
@@ -225,38 +229,51 @@ class GsmPalette(Palette):
     }
 
     def __init__(self):
-
+        
         Palette.__init__(self, label=_('Wireless modem'))
-
         self._current_state = None
-
-        self._toggle_state_item = gtk.MenuItem('')
+        self._alert = None
+        
+        self._toggle_state_item = MenuItem('')
         self._toggle_state_item.connect('activate', self.__toggle_state_cb)
         self.menu.append(self._toggle_state_item)
         self._toggle_state_item.show()
 
-        self.set_state(_GSM_STATE_NOT_READY)
-
         self.info_box = gtk.VBox()
-
-        self.data_label = gtk.Label()
-        self.data_label.props.xalign = 0.0
-        label_alignment = self._add_widget_with_padding(self.data_label)
-        self.info_box.pack_start(label_alignment)
-        self.data_label.show()
+        self.conn_info_box = gtk.HBox() 
+        
+        icon = Icon(icon_name='go-up', icon_size=gtk.ICON_SIZE_MENU)
+        self.conn_info_box.pack_start(icon)
+        icon.show()
+        self._data_label_up = gtk.Label()
+        self._data_label_up.props.xalign = 0.0
+        label_alignment = self._add_widget_with_padding(self._data_label_up) 
+        self.conn_info_box.pack_start(label_alignment)
+        self._data_label_up.show()
         label_alignment.show()
 
-        self.connection_time_label = gtk.Label()
-        self.connection_time_label.props.xalign = 0.0
-        label_alignment = self._add_widget_with_padding( \
-                self.connection_time_label)
-        self.info_box.pack_start(label_alignment)
-        self.connection_time_label.show()
+        icon = Icon(icon_name='go-down', icon_size=gtk.ICON_SIZE_MENU)
+        self.conn_info_box.pack_start(icon)
+        icon.show()
+        self._data_label_down = gtk.Label()
+        self._data_label_down.props.xalign = 0.0
+        label_alignment = self._add_widget_with_padding(self._data_label_down) 
+        self.conn_info_box.pack_start(label_alignment)
+        self._data_label_down.show()
         label_alignment.show()
-
+        
+        self.conn_info_box.show()
+        self.info_box.pack_start(self.conn_info_box)
+
+        self._error_accept_item = MenuItem('')
+        self._error_accept_item.connect('activate', self.__error_accept_cb)
+        self.menu.append(self._error_accept_item)
+        
         self.info_box.show()
         self.set_content(self.info_box)
 
+        self.set_state(_GSM_STATE_NOT_READY)
+
     def _add_widget_with_padding(self, child, xalign=0, yalign=0.5):
         alignment = gtk.Alignment(xalign=xalign, yalign=yalign,
                                   xscale=1, yscale=0.33)
@@ -267,35 +284,79 @@ class GsmPalette(Palette):
         alignment.add(child)
         return alignment
 
-    def set_state(self, state):
+    def set_state(self, state, reason=0):
         self._current_state = state
-        self._update_label_and_text()
+        self._update_label_and_text(reason)
 
-    def _update_label_and_text(self):
+    def _update_label_and_text(self, reason=0):
+        
         if self._current_state == _GSM_STATE_NOT_READY:
             self._toggle_state_item.get_child().set_label('...')
             self.props.secondary_text = _('Please wait...')
-
+    
         elif self._current_state == _GSM_STATE_DISCONNECTED:
             self._toggle_state_item.get_child().set_label(_('Connect'))
             self.props.secondary_text = _('Disconnected')
-
+            icon = Icon(icon_name='media-playback-start', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)
+         
         elif self._current_state == _GSM_STATE_CONNECTING:
             self._toggle_state_item.get_child().set_label(_('Cancel'))
             self.props.secondary_text = _('Connecting...')
+            icon = Icon(icon_name='media-playback-stop', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)            
 
         elif self._current_state == _GSM_STATE_CONNECTED:
             self._toggle_state_item.get_child().set_label(_('Disconnect'))
-            self.props.secondary_text = _('Connected')
-            
-        elif self._current_state == _GSM_STATE_NEED_AUTH:
-            self._toggle_state_item.get_child().set_label(_('Sim requires Pin/Puk'))
-            self.props.secondary_text = _('Authentication Error')
+            self.update_connection_time()
+            icon = Icon(icon_name='media-eject', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)
+                        
+        elif self._current_state == _GSM_STATE_FAILED:
+            self.add_alert(_('Error'), \
+                            self._get_connection_errors_by_nm_reason(reason))
             
         else:
             raise ValueError('Invalid GSM state while updating label and ' \
                              'text, %s' % str(self._current_state))
-
+    
+    def add_alert(self, title, message):
+            self._error_accept_item.get_child().set_label(title + ' : ' + message)
+            self._error_accept_item.show()
+            self._toggle_state_item.set_sensitive(False)
+                      
+    def __error_accept_cb(self, alert):
+            self._update_label_and_text()
+            self._error_accept_item.get_child().set_label('')
+            self._error_accept_item.hide()
+            self._toggle_state_item.set_sensitive(True)
+                      
+    def update_connection_time(self, connection_time=None):
+        if (connection_time is not None):
+            self.props.secondary_text = _('Connected for ' + \
+                                      connection_time.strftime('%H:%M:%S'))
+        else:
+            self.props.secondary_text = _('Connected for ' \
+                                          + '00:00:00')
+             
+    def update_stats(self, in_bytes, out_bytes):
+        in_KBytes = in_bytes / 1024
+        out_KBytes = out_bytes / 1024
+        self._data_label_up.set_text(_("%d KB") % (out_KBytes))
+        self._data_label_down.set_text(_("%d KB") % (in_KBytes))
+        
+    def _get_connection_errors_by_nm_reason(self, reason):
+        if reason in [network.NM_DEVICE_STATE_REASON_NO_SECRETS]:
+            message = _('The Pin/Puk configuration is not valid')
+        elif reason in [network.NM_DEVICE_STATE_REASON_PPP_DISCONNECT]:
+             message = _('Check the connection configuration')
+        else:
+            message = _('Check the connection configuration')
+        return message
+    
     def __toggle_state_cb(self, menuitem):
         if self._current_state == _GSM_STATE_NOT_READY:
             pass
@@ -305,12 +366,10 @@ class GsmPalette(Palette):
             self.emit('gsm-disconnect')
         elif self._current_state == _GSM_STATE_CONNECTED:
             self.emit('gsm-disconnect')
-        elif self._current_state == _GSM_STATE_NEED_AUTH:
-            self.emit('gsm-disconnect')
         else:
             raise ValueError('Invalid GSM state while emitting signal, %s' % \
                              str(self._current_state))
-
+            
 
 class WirelessDeviceView(ToolButton):
 
@@ -747,6 +806,7 @@ class GsmDeviceView(TrayIcon):
                                       signal_name='PppStats',
                                       path=self._device.object_path,
                                       dbus_interface=_NM_SERIAL_IFACE)
+        
     def create_palette(self):
         palette = GsmPalette()
 
@@ -775,7 +835,8 @@ class GsmDeviceView(TrayIcon):
                                         reply_handler=self.__connect_cb,
                                         error_handler=self.__connect_error_cb)
         else:
-            raise RuntimeError('There is no gsm connection available')
+            self._palette.add_alert(_('Error'), \
+                                    _('There is no gsm connection available'))
 
     def __connect_cb(self, active_connection):
         logging.debug('Connected successfully to gsm device, %s',
@@ -809,15 +870,15 @@ class GsmDeviceView(TrayIcon):
 
     def __state_changed_cb(self, new_state, old_state, reason):
         logging.debug('State: %s to %s, reason %s', old_state, new_state, reason)
-        self._update_state(int(new_state))
+        self._update_state(int(new_state), int(old_state), int(reason))
 
     def __current_state_check_cb(self, properties):
-        self._update_state(int(properties['State']))
+        self._update_state(int(properties['State']), 0, 0)
 
     def __current_state_check_error_cb(self, error):
         raise RuntimeError('Error when checking gsm device state, %s' % error)
 
-    def _update_state(self, state):
+    def _update_state(self, state, old_state, reason):
         gsm_state = None
 
         if state is network.DEVICE_STATE_ACTIVATED:
@@ -829,16 +890,18 @@ class GsmDeviceView(TrayIcon):
                         connection.get_settings().connection.timestamp
                 self._connection_time_handler = gobject.timeout_add_seconds( \
                         1, self.__connection_timecount_cb)
-                self._update_stats(0, 0)
-                self._update_connection_time()                
-                self._palette.info_box.show() 
+                self._palette.update_connection_time()                
+                self._palette.update_stats(0, 0)
+                if self._palette is not None:     
+                    self._palette.conn_info_box.show() 
 
         elif state is network.DEVICE_STATE_DISCONNECTED:
             gsm_state = _GSM_STATE_DISCONNECTED
             self._connection_timestamp = 0
             if self._connection_time_handler is not None:
                 gobject.source_remove(self._connection_time_handler)
-            self._palette.info_box.hide() 
+            if self._palette is not None:
+                self._palette.conn_info_box.hide() 
 
         elif state in [network.DEVICE_STATE_UNMANAGED,
                        network.DEVICE_STATE_UNAVAILABLE,
@@ -847,14 +910,15 @@ class GsmDeviceView(TrayIcon):
 
         elif state in [network.DEVICE_STATE_PREPARE,
                        network.DEVICE_STATE_CONFIG,
-                       network.DEVICE_STATE_IP_CONFIG]:
+                       network.DEVICE_STATE_IP_CONFIG,
+                       network.DEVICE_STATE_NEED_AUTH]:
             gsm_state = _GSM_STATE_CONNECTING
-            
-        elif state in [network.DEVICE_STATE_NEED_AUTH]:
-            gsm_state = _GSM_STATE_NEED_AUTH
+
+        elif state == network.DEVICE_STATE_FAILED:
+            gsm_state = _GSM_STATE_FAILED
             
         if self._palette is not None:
-            self._palette.set_state(gsm_state)
+            self._palette.set_state(gsm_state, reason)
 
     def disconnect(self):
         self._bus.remove_signal_receiver(self.__state_changed_cb,
@@ -863,25 +927,18 @@ class GsmDeviceView(TrayIcon):
                                          dbus_interface=_NM_DEVICE_IFACE)
 
     def __ppp_stats_changed_cb(self, in_bytes, out_bytes):
-        self._update_stats(in_bytes, out_bytes)
+        self._palette.update_stats(in_bytes, out_bytes)
 
-    def _update_stats(self, in_bytes, out_bytes):
-        in_KBytes = in_bytes / 1024
-        out_KBytes = out_bytes / 1024
-        text = _("Data sent %d KB / received %d KB") % (out_KBytes, in_KBytes)
-        self._palette.data_label.set_text(text)
 
     def __connection_timecount_cb(self):
         self._connection_timestamp = self._connection_timestamp + 1
-        self._update_connection_time()
+        connection_time = \
+            datetime.datetime.fromtimestamp(self._connection_timestamp)
+        self._palette.update_connection_time(connection_time)
         return True
 
-    def _update_connection_time(self):
-        connection_time = datetime.datetime.fromtimestamp( \
-                self._connection_timestamp)
-        text = _("Connection time ") + connection_time.strftime('%H : %M : %S')
-        self._palette.connection_time_label.set_text(text)
 
+    
 class WirelessDeviceObserver(object):
     def __init__(self, device, tray, device_type):
         self._device = device
@@ -952,6 +1009,7 @@ class WiredDeviceObserver(object):
                 del self._device_view
                 self._device_view = None
 
+
 class GsmDeviceObserver(object):
     def __init__(self, device, tray):
         self._device = device
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index 03d48c4..9a32897 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -18,6 +18,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+from gettext import gettext as _
 import logging
 import os
 import time
@@ -54,6 +55,48 @@ NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0
 NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1
 NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2
 
+NM_DEVICE_STATE_REASON_UNKNOWN = 0
+NM_DEVICE_STATE_REASON_NONE = 1
+NM_DEVICE_STATE_REASON_NOW_MANAGED = 2
+NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3
+NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4 
+NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE = 5
+NM_DEVICE_STATE_REASON_CONFIG_EXPIRED = 6
+NM_DEVICE_STATE_REASON_NO_SECRETS = 7
+NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8
+NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9
+NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10
+NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11
+NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12
+NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13
+NM_DEVICE_STATE_REASON_PPP_FAILED = 14
+NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15
+NM_DEVICE_STATE_REASON_DHCP_ERROR = 16
+NM_DEVICE_STATE_REASON_DHCP_FAILED = 17
+NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18 
+NM_DEVICE_STATE_REASON_SHARED_FAILED = 19
+NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20
+NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21
+NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22
+NM_DEVICE_STATE_REASON_MODEM_BUSY = 23
+NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24
+NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25
+NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26
+NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27
+NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28
+NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33 
+NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34
+NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35
+NM_DEVICE_STATE_REASON_REMOVED = 36
+NM_DEVICE_STATE_REASON_SLEEPING = 37
+NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38
+NM_DEVICE_STATE_REASON_USER_REQUESTED = 39
+NM_DEVICE_STATE_REASON_CARRIER = 40
+
 NM_802_11_AP_FLAGS_NONE = 0x00000000
 NM_802_11_AP_FLAGS_PRIVACY = 0x00000001
 
@@ -444,17 +487,22 @@ class NMSettingsConnection(dbus.service.Object):
     def GetSecrets(self, setting_name, hints, request_new, reply, error):
         logging.debug('Secrets requested for connection %s request_new=%s',
             self.path, request_new)
-        if request_new or self._secrets is None:
-            # request_new is for example the case when the pw on the AP changes
-            response = SecretsResponse(self, reply, error)
-            try:
-                self.secrets_request.send(self, response=response)
-            except Exception:
-                logging.exception('Error requesting the secrets via dialog')
-        else:
-            reply(self._secrets.get_dict())
-
-
+        if self._settings.connection.type is not 'gsm':
+                if request_new or self._secrets is None:
+                    # request_new is for example the case when the pw on the AP changes
+                    response = SecretsResponse(self, reply, error)
+                    try:
+                        self.secrets_request.send(self, response=response)
+                    except Exception:
+                        logging.exception('Error requesting the secrets via dialog')
+                else:
+                    reply(self._secrets.get_dict())
+        else: 
+                if not request_new:
+                     reply(self._secrets.get_dict())
+                else:
+                    raise Exception('The stored GSM secret has already been supplied ')
+                    
 class AccessPoint(gobject.GObject):
     __gsignals__ = {
         'props-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-- 
1.6.2.5

