diff options
Diffstat (limited to 'extensions/deviceicon/network.py')
-rw-r--r-- | extensions/deviceicon/network.py | 516 |
1 files changed, 281 insertions, 235 deletions
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py index 94a4293..4c4f339 100644 --- a/extensions/deviceicon/network.py +++ b/extensions/deviceicon/network.py @@ -23,10 +23,10 @@ import logging import hashlib import socket import struct -import re import datetime import time import gtk +import glib import gobject import gconf import dbus @@ -36,17 +36,17 @@ from sugar.graphics import style from sugar.graphics.palette import Palette from sugar.graphics.toolbutton import ToolButton from sugar.graphics.tray import TrayIcon +from sugar.graphics.menuitem import MenuItem +from sugar.graphics.icon import Icon from sugar.graphics import xocolor -from sugar.util import unique_id from sugar import profile from jarabe.model import network -from jarabe.model.network import Settings -from jarabe.model.network import IP4Config from jarabe.frame.frameinvoker import FrameWidgetInvoker from jarabe.view.pulsingicon import PulsingIcon -IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s") + +IP_ADDRESS_TEXT_TEMPLATE = _('IP address: %s') _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' @@ -63,26 +63,18 @@ _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, - 2432: 5, 2437: 6, 2442: 7, 2447: 8, - 2452: 9, 2457: 10, 2462: 11, 2467: 12, - 2472: 13} - return ftoc[frequency] class WirelessPalette(Palette): __gtype_name__ = 'SugarWirelessPalette' __gsignals__ = { - 'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'create-connection' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), + 'deactivate-connection': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([])), } - def __init__(self, primary_text, can_create=True): + def __init__(self, primary_text): Palette.__init__(self, label=primary_text) self._disconnect_item = None @@ -109,16 +101,13 @@ class WirelessPalette(Palette): self._info.pack_start(_padded(self._ip_address_label)) self._info.show_all() - self._disconnect_item = gtk.MenuItem(_('Disconnect...')) - self._disconnect_item.connect('activate', self.__disconnect_activate_cb) + self._disconnect_item = MenuItem(_('Disconnect...')) + icon = Icon(icon_size=gtk.ICON_SIZE_MENU, icon_name='media-eject') + self._disconnect_item.set_image(icon) + self._disconnect_item.connect('activate', + self.__disconnect_activate_cb) self.menu.append(self._disconnect_item) - if can_create: - self._adhoc_item = gtk.MenuItem(_('Create new wireless network')) - self._adhoc_item.connect('activate', self.__adhoc_activate_cb) - self.menu.append(self._adhoc_item) - self._adhoc_item.show() - def set_connecting(self): self.props.secondary_text = _('Connecting...') @@ -145,18 +134,12 @@ class WirelessPalette(Palette): def __disconnect_activate_cb(self, menuitem): self.emit('deactivate-connection') - def __adhoc_activate_cb(self, menuitem): - self.emit('create-connection') - def _set_frequency(self, frequency): - try: - channel = frequency_to_channel(frequency) - except KeyError: - channel = 0 + channel = network.frequency_to_channel(frequency) self._set_channel(channel) def _set_channel(self, channel): - self._channel_label.set_text("%s: %d" % (_("Channel"), channel)) + self._channel_label.set_text('%s: %d' % (_('Channel'), channel)) def _set_ip_address(self, ip_address): if ip_address is not None: @@ -204,7 +187,7 @@ class WiredPalette(Palette): def _inet_ntoa(self, iaddress): address = ['%s' % ((iaddress >> i) % 256) for i in [0, 8, 16, 24]] - return ".".join(address) + return '.'.join(address) def _set_ip_address(self, ip_address): if ip_address is not None: @@ -214,14 +197,13 @@ class WiredPalette(Palette): ip_address_text = "" self._ip_address_label.set_text(ip_address_text) + class GsmPalette(Palette): __gtype_name__ = 'SugarGsmPalette' __gsignals__ = { - 'gsm-connect' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'gsm-disconnect' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), + 'gsm-connect': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'gsm-disconnect': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), } def __init__(self): @@ -229,34 +211,53 @@ class GsmPalette(Palette): Palette.__init__(self, label=_('Wireless modem')) self._current_state = None + self._failed_connection = False - self._toggle_state_item = gtk.MenuItem('') + 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.error_title_label = gtk.Label("") + self.error_title_label.set_alignment(0, 0.5) + self.error_title_label.set_line_wrap(True) + self.info_box.pack_start(self.error_title_label) + self.error_description_label = gtk.Label("") + self.error_description_label.set_alignment(0, 0.5) + self.error_description_label.set_line_wrap(True) + self.info_box.pack_start(self.error_description_label) + + self.connection_info_box = gtk.HBox() + icon = Icon(icon_name='data-upload', icon_size=gtk.ICON_SIZE_MENU) + self.connection_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.connection_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='data-download', icon_size=gtk.ICON_SIZE_MENU) + self.connection_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.connection_info_box.pack_start(label_alignment) + self._data_label_down.show() label_alignment.show() + self.info_box.pack_start(self.connection_info_box) + 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,31 +268,41 @@ class GsmPalette(Palette): alignment.add(child) return alignment - def set_state(self, state): + def update_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')) + if not self._failed_connection: + self._toggle_state_item.get_child().set_label(_('Connect')) self.props.secondary_text = _('Disconnected') + icon = Icon(icon_name='dialog-ok', \ + 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='dialog-cancel', \ + icon_size=gtk.ICON_SIZE_MENU) + self._toggle_state_item.set_image(icon) elif self._current_state == _GSM_STATE_CONNECTED: + self._failed_connection = False 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: + message_error = self._get_error_by_nm_reason(reason) + self.add_alert(message_error[0], message_error[1]) else: raise ValueError('Invalid GSM state while updating label and ' \ 'text, %s' % str(self._current_state)) @@ -300,21 +311,64 @@ class GsmPalette(Palette): if self._current_state == _GSM_STATE_NOT_READY: pass elif self._current_state == _GSM_STATE_DISCONNECTED: + self.error_title_label.hide() + self.error_description_label.hide() self.emit('gsm-connect') elif self._current_state == _GSM_STATE_CONNECTING: 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)) + def add_alert(self, error, suggestion): + self._failed_connection = True + action = _('Try connection again') + self._toggle_state_item.get_child().set_label(action) + + title = _('Error: %s') % error + self.error_title_label.set_markup('<b>%s</b>' % title) + self.error_title_label.show() + + message = _('Suggestion: %s') % suggestion + self.error_description_label.set_text(message) + self.error_description_label.show() + + def update_connection_time(self, connection_time=None): + if connection_time is not None: + self.props.secondary_text = _('Connected for %s') % \ + connection_time.strftime('%H:%M:%S') + else: + self.props.secondary_text = _('Connected for %s') % '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_error_by_nm_reason(self, reason): + if reason in [network.NM_DEVICE_STATE_REASON_NO_SECRETS, + network.NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED]: + message = _('Check your Pin/Puk configuration.') + elif reason in [network.NM_DEVICE_STATE_REASON_PPP_DISCONNECT, + network.NM_DEVICE_STATE_REASON_PPP_FAILED]: + message = _('Check your Access Point Name ' \ + '(APN) configuration') + elif reason in [network.NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, + network.NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT]: + message = _('Check the Number configuration.') + elif reason == network.NM_DEVICE_STATE_REASON_CONFIG_FAILED: + message = _('Check your configuration.') + else: + message = '' + message_tuple = (network.get_error_by_reason(reason), message) + return message_tuple + class WirelessDeviceView(ToolButton): - _ICON_NAME = 'network-wireless' FRAME_POSITION_RELATIVE = 302 def __init__(self, device): @@ -333,9 +387,9 @@ class WirelessDeviceView(ToolButton): self._active_ap_op = None self._icon = PulsingIcon() - self._icon.props.icon_name = get_icon_state(self._ICON_NAME, 0) - self._inactive_color = xocolor.XoColor( \ - "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + self._icon.props.icon_name = get_icon_state('network-wireless', 0) + self._inactive_color = xocolor.XoColor( + '%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self._icon.props.pulse_color = self._inactive_color self._icon.props.base_color = self._inactive_color @@ -347,14 +401,12 @@ class WirelessDeviceView(ToolButton): self._palette = WirelessPalette(self._name) self._palette.connect('deactivate-connection', self.__deactivate_connection_cb) - self._palette.connect('create-connection', - self.__create_connection_cb) self.set_palette(self._palette) self._palette.set_group_id('frame') - self._device_props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') - self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + self._device_props = dbus.Interface(self._device, + dbus.PROPERTIES_IFACE) + self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) @@ -394,7 +446,7 @@ class WirelessDeviceView(ToolButton): return self._active_ap_op = active_ap_op active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op) - props = dbus.Interface(active_ap, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE) props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, reply_handler=self.__get_all_ap_props_reply_cb, @@ -418,11 +470,6 @@ class WirelessDeviceView(ToolButton): def __ap_properties_changed_cb(self, properties): self._update_properties(properties) - def _name_encodes_colors(self): - """Match #XXXXXX,#YYYYYY at the end of the network name""" - return self._name[-7] == '#' and self._name[-8] == ',' \ - and self._name[-15] == '#' - def _update_properties(self, properties): if 'Mode' in properties: self._mode = properties['Mode'] @@ -438,11 +485,9 @@ class WirelessDeviceView(ToolButton): self._frequency = properties['Frequency'] if self._color == None: - if self._mode == network.NM_802_11_MODE_ADHOC \ - and self._name_encodes_colors(): - encoded_color = self._name.split("#", 1) - if len(encoded_color) == 2: - self._color = xocolor.XoColor('#' + encoded_color[1]) + if self._mode == network.NM_802_11_MODE_ADHOC and \ + network.is_sugar_adhoc_network(self._name): + self._color = profile.get_color() else: sha_hash = hashlib.sha1() data = self._name + hex(self._flags) @@ -450,7 +495,7 @@ class WirelessDeviceView(ToolButton): digest = hash(sha_hash.digest()) index = digest % len(xocolor.colors) - self._color = xocolor.XoColor('%s,%s' % + self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[index][0], xocolor.colors[index][1])) self._update() @@ -463,11 +508,11 @@ class WirelessDeviceView(ToolButton): def _update(self): if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: - self._icon.props.badge_name = "emblem-locked" + self._icon.props.badge_name = 'emblem-locked' else: self._icon.props.badge_name = None - self._palette.props.primary_text = self._name + self._palette.props.primary_text = glib.markup_escape_text(self._name) self._update_state() self._update_color() @@ -478,14 +523,24 @@ class WirelessDeviceView(ToolButton): else: state = network.DEVICE_STATE_UNKNOWN - if state == network.DEVICE_STATE_ACTIVATED: - icon_name = '%s-connected' % self._ICON_NAME - else: - icon_name = self._ICON_NAME + if self._mode != network.NM_802_11_MODE_ADHOC and \ + network.is_sugar_adhoc_network(self._name) == False: + if state == network.DEVICE_STATE_ACTIVATED: + icon_name = '%s-connected' % 'network-wireless' + else: + icon_name = 'network-wireless' - icon_name = get_icon_state(icon_name, self._strength) - if icon_name: - self._icon.props.icon_name = icon_name + icon_name = get_icon_state(icon_name, self._strength) + if icon_name: + self._icon.props.icon_name = icon_name + else: + channel = network.frequency_to_channel(self._frequency) + if state == network.DEVICE_STATE_ACTIVATED: + self._icon.props.icon_name = 'network-adhoc-%s-connected' \ + % channel + else: + self._icon.props.icon_name = 'network-adhoc-%s' % channel + self._icon.props.base_color = profile.get_color() if state == network.DEVICE_STATE_PREPARE or \ state == network.DEVICE_STATE_CONFIG or \ @@ -495,7 +550,8 @@ class WirelessDeviceView(ToolButton): self._icon.props.pulsing = True elif state == network.DEVICE_STATE_ACTIVATED: address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address') - self._palette.set_connected_with_frequency(self._frequency, address) + self._palette.set_connected_with_frequency(self._frequency, + address) self._icon.props.pulsing = False else: self._icon.props.badge_name = None @@ -508,69 +564,12 @@ class WirelessDeviceView(ToolButton): self._icon.props.base_color = self._color def __deactivate_connection_cb(self, palette, data=None): - if self._active_ap_op is not None: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface( - netmgr, 'org.freedesktop.DBus.Properties') - active_connections_o = netmgr_props.Get(_NM_IFACE, - 'ActiveConnections') - - for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') - if ap_op == self._active_ap_op: - netmgr.DeactivateConnection(conn_o) - break - - def __create_connection_cb(self, palette, data=None): - """Create an 802.11 IBSS network. - - The user's color is encoded at the end of the network name. The network - name is truncated so that it does not exceed the 32 byte SSID limit. - """ - client = gconf.client_get_default() - nick = client.get_string('/desktop/sugar/user/nick').decode('utf-8') - color = client.get_string('/desktop/sugar/user/color') - color_suffix = ' %s' % color - - format = _('%s\'s network').encode('utf-8') - extra_length = (len(format) - len('%s')) + len(color_suffix) - name_limit = 32 - extra_length - - # truncate the nick and use a regex to drop any partial characters - # at the end - nick = nick.encode('utf-8')[:name_limit] - pattern = "([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$" - nick = re.sub(pattern, '', nick) - - connection_name = format % nick - connection_name += color_suffix - - connection = network.find_connection_by_ssid(connection_name) - if connection is None: - settings = Settings() - settings.connection.id = 'Auto ' + connection_name - uuid = settings.connection.uuid = unique_id() - settings.connection.type = '802-11-wireless' - settings.wireless.ssid = dbus.ByteArray(connection_name) - settings.wireless.band = 'bg' - settings.wireless.mode = 'adhoc' - settings.ip4_config = IP4Config() - settings.ip4_config.method = 'link-local' - - connection = network.add_connection(uuid, settings) + if self._mode == network.NM_802_11_MODE_INFRA: + connection = network.find_connection_by_ssid(self._name) + if connection: + connection.disable_autoconnect() - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - - netmgr.ActivateConnection(network.SETTINGS_SERVICE, - connection.path, - self._device.object_path, - '/', - reply_handler=self.__activate_reply_cb, - error_handler=self.__activate_error_cb) + network.disconnect_access_points([self._active_ap_op]) def __activate_reply_cb(self, connection): logging.debug('Network created: %s', connection) @@ -583,7 +582,7 @@ class OlpcMeshDeviceView(ToolButton): _ICON_NAME = 'network-mesh' FRAME_POSITION_RELATIVE = 302 - def __init__(self, device): + def __init__(self, device, state): ToolButton.__init__(self) self._bus = dbus.SystemBus() @@ -593,57 +592,41 @@ class OlpcMeshDeviceView(ToolButton): self._channel = 0 self._icon = PulsingIcon(icon_name=self._ICON_NAME) - self._icon.props.pulse_color = xocolor.XoColor( \ - "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + self._inactive_color = xocolor.XoColor( + '%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) - self._icon.props.base_color = profile.get_color() + self._icon.props.pulse_color = profile.get_color() + self._icon.props.base_color = self._inactive_color self.set_icon_widget(self._icon) self._icon.show() self.set_palette_invoker(FrameWidgetInvoker(self)) - self._palette = WirelessPalette(_("Mesh Network")) + self._palette = WirelessPalette(_('Mesh Network')) self._palette.connect('deactivate-connection', self.__deactivate_connection) self.set_palette(self._palette) self._palette.set_group_id('frame') + self.update_state(state) + self._device_props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') - self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, - reply_handler=self.__get_device_props_reply_cb, - error_handler=self.__get_device_props_error_cb) + dbus.PROPERTIES_IFACE) self._device_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel', reply_handler=self.__get_active_channel_reply_cb, error_handler=self.__get_active_channel_error_cb) - self._bus.add_signal_receiver(self.__state_changed_cb, - signal_name='StateChanged', - path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device.object_path, dbus_interface=_NM_OLPC_MESH_IFACE) def disconnect(self): - self._bus.remove_signal_receiver(self.__state_changed_cb, - signal_name='StateChanged', - path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=_NM_OLPC_MESH_IFACE) - def __get_device_props_reply_cb(self, properties): - if 'State' in properties: - self._device_state = properties['State'] - self._update() - - def __get_device_props_error_cb(self, err): - logging.error('Error getting the device properties: %s', err) - def __get_active_channel_reply_cb(self, channel): self._channel = channel self._update_text() @@ -661,7 +644,8 @@ class OlpcMeshDeviceView(ToolButton): self._update_text() def _update_text(self): - text = _("Mesh Network") + " " + str(self._channel) + channel = str(self._channel) + text = _('Mesh Network %s') % glib.markup_escape_text(channel) self._palette.props.primary_text = text def _update(self): @@ -671,31 +655,39 @@ class OlpcMeshDeviceView(ToolButton): network.DEVICE_STATE_CONFIG, network.DEVICE_STATE_NEED_AUTH, network.DEVICE_STATE_IP_CONFIG]: + self._icon.props.base_color = self._inactive_color + self._icon.props.pulse_color = profile.get_color() self._palette.set_connecting() self._icon.props.pulsing = True elif state == network.DEVICE_STATE_ACTIVATED: address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address') self._palette.set_connected_with_channel(self._channel, address) + self._icon.props.base_color = profile.get_color() self._icon.props.pulsing = False + self._update_text() + + def update_state(self, state): + self._device_state = state + self._update() def __deactivate_connection(self, palette, data=None): obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface(netmgr, 'org.freedesktop.DBus.Properties') + netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: # The connection path for a mesh connection is the device itself. obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') try: obj = self._bus.get_object(_NM_IFACE, ap_op) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if type == network.DEVICE_TYPE_802_11_OLPC_MESH: + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) + device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') + if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: netmgr.DeactivateConnection(conn_o) break except dbus.exceptions.DBusException: @@ -747,6 +739,7 @@ class GsmDeviceView(TrayIcon): signal_name='PppStats', path=self._device.object_path, dbus_interface=_NM_SERIAL_IFACE) + def create_palette(self): palette = GsmPalette() @@ -756,7 +749,7 @@ class GsmDeviceView(TrayIcon): self._palette = palette - props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__current_state_check_cb, error_handler=self.__current_state_check_error_cb) @@ -774,6 +767,10 @@ class GsmDeviceView(TrayIcon): '/', reply_handler=self.__connect_cb, error_handler=self.__connect_error_cb) + else: + self._palette.add_alert(_('No GSM connection available.'), \ + _('Create a connection in the ' \ + 'control panel.')) def __connect_cb(self, active_connection): logging.debug('Connected successfully to gsm device, %s', @@ -785,12 +782,12 @@ class GsmDeviceView(TrayIcon): def __gsm_disconnect_cb(self, palette, data=None): obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface(netmgr, 'org.freedesktop.DBus.Properties') + netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) devices = props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices') if self._device.object_path in devices: netmgr.DeactivateConnection( @@ -806,16 +803,17 @@ class GsmDeviceView(TrayIcon): raise RuntimeError('Error when disconnecting gsm device, %s' % error) 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)) + logging.debug('State: %s to %s, reason %s', old_state, + new_state, reason) + 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: @@ -823,20 +821,22 @@ class GsmDeviceView(TrayIcon): connection = network.find_gsm_connection() if connection is not None: connection.set_connected() - self._connection_timestamp = time.time() - \ + self._connection_timestamp = time.time() - \ 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.connection_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.connection_info_box.hide() elif state in [network.DEVICE_STATE_UNMANAGED, network.DEVICE_STATE_UNAVAILABLE, @@ -845,14 +845,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.update_state(gsm_state, reason) def disconnect(self): self._bus.remove_signal_receiver(self.__state_changed_cb, @@ -861,38 +862,22 @@ 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) - - 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) + self._palette.update_stats(in_bytes, out_bytes) 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): + def __init__(self, device, tray): self._device = device self._device_view = None self._tray = tray - - if device_type == network.DEVICE_TYPE_802_11_WIRELESS: - self._device_view = WirelessDeviceView(self._device) - elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: - self._device_view = OlpcMeshDeviceView(self._device) - else: - raise ValueError('Unimplemented device type %d' % device_type) - + self._device_view = WirelessDeviceView(self._device) self._tray.add_device(self._device_view) def disconnect(self): @@ -902,6 +887,63 @@ class WirelessDeviceObserver(object): self._device_view = None +class MeshDeviceObserver(object): + def __init__(self, device, tray): + self._bus = dbus.SystemBus() + self._device = device + self._device_view = None + self._tray = tray + + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) + props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + reply_handler=self.__get_device_props_reply_cb, + error_handler=self.__get_device_props_error_cb) + + self._bus.add_signal_receiver(self.__state_changed_cb, + signal_name='StateChanged', + path=self._device.object_path, + dbus_interface=_NM_DEVICE_IFACE) + + def _remove_device_view(self): + self._device_view.disconnect() + self._tray.remove_device(self._device_view) + self._device_view = None + + def disconnect(self): + if self._device_view is not None: + self._remove_device_view() + + self._bus.remove_signal_receiver(self.__state_changed_cb, + signal_name='StateChanged', + path=self._device.object_path, + dbus_interface=_NM_DEVICE_IFACE) + + def __get_device_props_reply_cb(self, properties): + if 'State' in properties: + self._update_state(properties['State']) + + def __get_device_props_error_cb(self, err): + logging.error('Error getting the device properties: %s', err) + + def __state_changed_cb(self, new_state, old_state, reason): + self._update_state(new_state) + + def _update_state(self, state): + if state in (network.DEVICE_STATE_PREPARE, network.DEVICE_STATE_CONFIG, + network.DEVICE_STATE_NEED_AUTH, + network.DEVICE_STATE_IP_CONFIG, + network.DEVICE_STATE_ACTIVATED): + if self._device_view is not None: + self._device_view.update_state(state) + return + + self._device_view = OlpcMeshDeviceView(self._device, state) + self._tray.add_device(self._device_view) + else: + if self._device_view is not None: + self._remove_device_view() + + class WiredDeviceObserver(object): def __init__(self, device, tray): self._bus = dbus.SystemBus() @@ -910,7 +952,7 @@ class WiredDeviceObserver(object): self._device_view = None self._tray = tray - props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) @@ -938,8 +980,7 @@ class WiredDeviceObserver(object): def _update_state(self, state): if state == network.DEVICE_STATE_ACTIVATED: - props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address') speed = props.Get(_NM_WIRED_IFACE, 'Speed') self._device_view = WiredDeviceView(speed, address) @@ -950,6 +991,7 @@ class WiredDeviceObserver(object): del self._device_view self._device_view = None + class GsmDeviceObserver(object): def __init__(self, device, tray): self._device = device @@ -964,6 +1006,7 @@ class GsmDeviceObserver(object): self._tray.remove_device(self._device_view) self._device_view = None + class NetworkManagerObserver(object): def __init__(self, tray): self._bus = dbus.SystemBus() @@ -997,15 +1040,17 @@ class NetworkManagerObserver(object): def _check_device(self, device_op): nm_device = self._bus.get_object(_NM_SERVICE, device_op) - props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(nm_device, dbus.PROPERTIES_IFACE) device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') if device_type == network.DEVICE_TYPE_802_3_ETHERNET: device = WiredDeviceObserver(nm_device, self._tray) self._devices[device_op] = device - elif device_type in [network.DEVICE_TYPE_802_11_WIRELESS, - network.DEVICE_TYPE_802_11_OLPC_MESH]: - device = WirelessDeviceObserver(nm_device, self._tray, device_type) + elif device_type == network.DEVICE_TYPE_802_11_WIRELESS: + device = WirelessDeviceObserver(nm_device, self._tray) + self._devices[device_op] = device + elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: + device = MeshDeviceObserver(nm_device, self._tray) self._devices[device_op] = device elif device_type == network.DEVICE_TYPE_GSM_MODEM: device = GsmDeviceObserver(nm_device, self._tray) @@ -1020,5 +1065,6 @@ class NetworkManagerObserver(object): device.disconnect() del self._devices[device_op] + def setup(tray): device_observer = NetworkManagerObserver(tray) |