diff options
author | Simon Schampijer <simon@schampijer.de> | 2010-09-22 10:40:38 (GMT) |
---|---|---|
committer | Simon Schampijer <simon@schampijer.de> | 2010-09-22 10:40:38 (GMT) |
commit | 824ac2a6a6dddf36c9f795cf0249eb5bebe60f54 (patch) | |
tree | 165a6a7519226c210d302225576bad26d3d599cf | |
parent | f76678cbbbaa91a83575b59fdfd31abd74610fab (diff) |
Add default Ad-hoc networks #9845
This patch adds three default Ad-hoc networks, for channel 1, 6 and 11. They
are represented with designated icons in the neighborhood view. This will
mimic the mesh behavior on devices where mesh hardware is not available
and make the "under a tree"-scenario possible in those cases. If Sugar sees
no "known" network when it starts, it does autoconnect to an Ad-hoc network.
-rw-r--r-- | data/sugar.schemas.in | 13 | ||||
-rw-r--r-- | extensions/deviceicon/network.py | 119 | ||||
-rw-r--r-- | src/jarabe/desktop/meshbox.py | 298 | ||||
-rw-r--r-- | src/jarabe/model/Makefile.am | 1 | ||||
-rw-r--r-- | src/jarabe/model/network.py | 40 |
5 files changed, 339 insertions, 132 deletions
diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in index e5b1e88..454375a 100644 --- a/data/sugar.schemas.in +++ b/data/sugar.schemas.in @@ -271,6 +271,19 @@ </locale> </schema> + <schema> + <key>/schemas/desktop/sugar/network/adhoc</key> + <applyto>/desktop/sugar/network/adhoc</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Show Sugar Ad-hoc networks</short> + <long>If TRUE, Sugar will show default Ad-hoc networks for + channel 1,6 and 11. If Sugar sees no "known" network when + it starts, it does autoconnect to an Ad-hoc network.</long> + </locale> + </schema> </schemalist> </gconfschemafile> diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py index f194a19..12ea9f6 100644 --- a/extensions/deviceicon/network.py +++ b/extensions/deviceicon/network.py @@ -64,24 +64,15 @@ _GSM_STATE_CONNECTING = 2 _GSM_STATE_CONNECTED = 3 _GSM_STATE_NEED_AUTH = 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, ([])), + 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 @@ -112,12 +103,6 @@ class WirelessPalette(Palette): 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...') @@ -144,12 +129,9 @@ 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) + channel = network.frequency_to_channel(frequency) except KeyError: channel = 0 self._set_channel(channel) @@ -312,7 +294,6 @@ class GsmPalette(Palette): class WirelessDeviceView(ToolButton): - _ICON_NAME = 'network-wireless' FRAME_POSITION_RELATIVE = 302 def __init__(self, device): @@ -331,7 +312,7 @@ class WirelessDeviceView(ToolButton): self._active_ap_op = None self._icon = PulsingIcon() - self._icon.props.icon_name = get_icon_state(self._ICON_NAME, 0) + 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())) @@ -345,8 +326,6 @@ 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') @@ -415,11 +394,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'] @@ -435,11 +409,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 \ + self._name.startswith('Ad-hoc Network'): + self._color = profile.get_color() else: sh = sha.new() data = self._name + hex(self._flags) @@ -475,14 +447,27 @@ 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 \ + self._name.startswith('Ad-hoc Network') == 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: + try: + channel = network.frequency_to_channel(self._frequency) + except KeyError: + channel = 1 + 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 \ @@ -526,54 +511,6 @@ class WirelessDeviceView(ToolButton): 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) - - 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) - def __activate_reply_cb(self, connection): logging.debug('Network created: %s', connection) @@ -604,7 +541,7 @@ class OlpcMeshDeviceView(ToolButton): self._icon.show() self.set_palette_invoker(FrameWidgetInvoker(self)) - self._palette = WirelessPalette(_("Mesh Network"), can_create=False) + self._palette = WirelessPalette(_("Mesh Network")) self._palette.connect('deactivate-connection', self.__deactivate_connection) self.set_palette(self._palette) diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py index a3965f7..764aa2e 100644 --- a/src/jarabe/desktop/meshbox.py +++ b/src/jarabe/desktop/meshbox.py @@ -1,6 +1,6 @@ # Copyright (C) 2006-2007 Red Hat, Inc. # Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer -# Copyright (C) 2009 One Laptop per Child +# Copyright (C) 2009-2010 One Laptop per Child # # 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 @@ -24,6 +24,7 @@ import dbus import hippo import gobject import gtk +import gconf from sugar.graphics.icon import CanvasIcon, Icon from sugar.graphics.xocolor import XoColor @@ -54,6 +55,7 @@ from jarabe.model.network import WirelessSecurity from jarabe.model.network import AccessPoint from jarabe.model.network import OlpcMesh as OlpcMeshSettings from jarabe.model.olpcmesh import OlpcMeshManager +from jarabe.model.adhoc import get_adhoc_manager_instance _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' @@ -89,11 +91,9 @@ class WirelessNetworkView(CanvasPulsingIcon): self._device_state = None 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: sh = sha.new() data = self._name + hex(self._flags) @@ -137,11 +137,6 @@ class WirelessNetworkView(CanvasPulsingIcon): path=self._device.object_path, dbus_interface=_NM_WIRELESS_IFACE) - 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 _create_palette(self): icon_name = get_icon_state(_AP_ICON_NAME, self._strength) self._palette_icon = Icon(icon_name=icon_name, @@ -214,21 +209,32 @@ class WirelessNetworkView(CanvasPulsingIcon): else: state = network.DEVICE_STATE_UNKNOWN - if state == network.DEVICE_STATE_ACTIVATED: - connection = network.find_connection_by_ssid(self._name) - if connection: - if self._mode == network.NM_802_11_MODE_INFRA: - connection.set_connected() - - icon_name = '%s-connected' % _AP_ICON_NAME - else: - icon_name = _AP_ICON_NAME - - icon_name = get_icon_state(icon_name, self._strength) - if icon_name: + if self._mode == network.NM_802_11_MODE_ADHOC and \ + network.is_sugar_adhoc_network(self._name): + channel = max([1] + [ap.channel for ap in + self._access_points.values()]) + if state == network.DEVICE_STATE_ACTIVATED: + icon_name = 'network-adhoc-%s-connected' % channel + else: + icon_name = 'network-adhoc-%s' % channel self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name + else: + if state == network.DEVICE_STATE_ACTIVATED: + connection = network.find_connection_by_ssid(self._name) + if connection: + if self._mode == network.NM_802_11_MODE_INFRA: + connection.set_connected() + icon_name = '%s-connected' % _AP_ICON_NAME + else: + icon_name = _AP_ICON_NAME + + icon_name = get_icon_state(icon_name, self._strength) + if icon_name: + self.props.icon_name = icon_name + icon = self._palette.props.icon + icon.props.icon_name = icon_name if state == network.DEVICE_STATE_PREPARE or \ state == network.DEVICE_STATE_CONFIG or \ @@ -260,12 +266,16 @@ class WirelessNetworkView(CanvasPulsingIcon): self.props.base_color = self._color def _update_badge(self): - if network.find_connection_by_ssid(self._name) is not None: - self.props.badge_name = "emblem-favorite" - self._palette_icon.props.badge_name = "emblem-favorite" - elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: - self.props.badge_name = "emblem-locked" - self._palette_icon.props.badge_name = "emblem-locked" + if self._mode != network.NM_802_11_MODE_ADHOC: + if network.find_connection_by_ssid(self._name) is not None: + self.props.badge_name = "emblem-favorite" + self._palette_icon.props.badge_name = "emblem-favorite" + elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: + self.props.badge_name = "emblem-locked" + self._palette_icon.props.badge_name = "emblem-locked" + else: + self.props.badge_name = None + self._palette_icon.props.badge_name = None else: self.props.badge_name = None self._palette_icon.props.badge_name = None @@ -469,6 +479,140 @@ class WirelessNetworkView(CanvasPulsingIcon): dbus_interface=_NM_WIRELESS_IFACE) +class SugarAdhocView(CanvasPulsingIcon): + """To mimic the mesh behavior on devices where mesh hardware is + not available we support the creation of an Ad-hoc network on + three channels 1, 6, 11. This is the class for an icon + representing a channel in the neighborhood view. + + """ + + _ICON_NAME = 'network-adhoc-' + _NAME = 'Ad-hoc Network ' + + def __init__(self, channel): + CanvasPulsingIcon.__init__(self, + icon_name=self._ICON_NAME + str(channel), + size=style.STANDARD_ICON_SIZE, cache=True) + self._bus = dbus.SystemBus() + self._channel = channel + self._disconnect_item = None + self._connect_item = None + self._palette_icon = None + self._greyed_out = False + + get_adhoc_manager_instance().connect('members-changed', + self.__members_changed_cb) + get_adhoc_manager_instance().connect('state-changed', + self.__state_changed_cb) + + self.connect('button-release-event', self.__button_release_event_cb) + + pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), + style.COLOR_TRANSPARENT.get_svg())) + self.props.pulse_color = pulse_color + self._state_color = XoColor('%s,%s' % \ + (profile.get_color().get_stroke_color(), + style.COLOR_TRANSPARENT.get_svg())) + self.props.base_color = self._state_color + self._palette = self._create_palette() + self.set_palette(self._palette) + self._palette_icon.props.xo_color = self._state_color + + def _create_palette(self): + self._palette_icon = Icon( \ + icon_name=self._ICON_NAME + str(self._channel), + icon_size=style.STANDARD_ICON_SIZE) + + palette_ = palette.Palette(_("Ad-hoc Network %d") % self._channel, + icon=self._palette_icon) + + self._connect_item = MenuItem(_('Connect'), 'dialog-ok') + self._connect_item.connect('activate', self.__connect_activate_cb) + palette_.menu.append(self._connect_item) + + self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') + self._disconnect_item.connect('activate', + self.__disconnect_activate_cb) + palette_.menu.append(self._disconnect_item) + + return palette_ + + def __button_release_event_cb(self, icon, event): + get_adhoc_manager_instance().activate_channel(self._channel) + + def __connect_activate_cb(self, icon): + get_adhoc_manager_instance().activate_channel(self._channel) + + def __disconnect_activate_cb(self, icon): + get_adhoc_manager_instance().deactivate_active_channel() + + def __state_changed_cb(self, adhoc_manager, channel, device_state): + if self._channel == channel: + state = device_state + else: + state = network.DEVICE_STATE_UNKNOWN + + if state == network.DEVICE_STATE_ACTIVATED: + icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel)) + else: + icon_name = self._ICON_NAME + str(self._channel) + + self.props.base_color = self._state_color + self._palette_icon.props.xo_color = self._state_color + + if icon_name is not None: + self.props.icon_name = icon_name + icon = self._palette.props.icon + icon.props.icon_name = icon_name + + if state in [network.DEVICE_STATE_PREPARE, + network.DEVICE_STATE_CONFIG, + network.DEVICE_STATE_NEED_AUTH, + network.DEVICE_STATE_IP_CONFIG]: + if self._disconnect_item: + self._disconnect_item.show() + self._connect_item.hide() + self._palette.props.secondary_text = _('Connecting...') + self.props.pulsing = True + elif state == network.DEVICE_STATE_ACTIVATED: + if self._disconnect_item: + self._disconnect_item.show() + self._connect_item.hide() + self._palette.props.secondary_text = _('Connected') + self.props.pulsing = False + else: + if self._disconnect_item: + self._disconnect_item.hide() + self._connect_item.show() + self._palette.props.secondary_text = None + self.props.pulsing = False + + def _update_color(self): + if self._greyed_out: + self.props.base_color = XoColor('#D5D5D5,#D5D5D5') + else: + self.props.base_color = self._state_color + + def __members_changed_cb(self, adhoc_manager, channel, has_members): + if channel == self._channel: + if has_members == True: + self._state_color = profile.get_color() + self.props.base_color = self._state_color + self._palette_icon.props.xo_color = self._state_color + else: + color = '%s,%s' % (profile.get_color().get_stroke_color(), + style.COLOR_TRANSPARENT.get_svg()) + self._state_color = XoColor(color) + self.props.base_color = self._state_color + self._palette_icon.props.xo_color = self._state_color + + def set_filter(self, query): + name = self._NAME + str(self._channel) + self._greyed_out = name.lower().find(query) == -1 + self._update_color() + + class OlpcMeshView(CanvasPulsingIcon): def __init__(self, mesh_mgr, channel): CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME, @@ -797,13 +941,19 @@ class MeshToolbar(gtk.Toolbar): return False -class DeviceObserver(object): - def __init__(self, box, device): - self._box = box +class DeviceObserver(gobject.GObject): + __gsignals__ = { + 'access-point-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'access-point-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + def __init__(self, device): + gobject.GObject.__init__(self) self._bus = dbus.SystemBus() - self._device = device + self.device = device - wireless = dbus.Interface(self._device, _NM_WIRELESS_IFACE) + wireless = dbus.Interface(device, _NM_WIRELESS_IFACE) wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb, error_handler=self._get_access_points_error_cb) @@ -819,30 +969,33 @@ class DeviceObserver(object): def _get_access_points_reply_cb(self, access_points_o): for ap_o in access_points_o: ap = self._bus.get_object(_NM_SERVICE, ap_o) - self._box.add_access_point(self._device, ap) + self.emit('access-point-added', ap) def _get_access_points_error_cb(self, err): logging.error('Failed to get access points: %s', err) def __access_point_added_cb(self, access_point_o): ap = self._bus.get_object(_NM_SERVICE, access_point_o) - self._box.add_access_point(self._device, ap) + self.emit('access-point-added', ap) def __access_point_removed_cb(self, access_point_o): - self._box.remove_access_point(access_point_o) + self.emit('access-point-removed', access_point_o) def disconnect(self): self._bus.remove_signal_receiver(self.__access_point_added_cb, signal_name='AccessPointAdded', - path=self._device.object_path, + path=self.device.object_path, dbus_interface=_NM_WIRELESS_IFACE) self._bus.remove_signal_receiver(self.__access_point_removed_cb, signal_name='AccessPointRemoved', - path=self._device.object_path, + path=self.device.object_path, dbus_interface=_NM_WIRELESS_IFACE) class NetworkManagerObserver(object): + + _SHOW_ADHOC_GCONF_KEY = '/desktop/sugar/network/adhoc' + def __init__(self, box): self._box = box self._bus = dbus.SystemBus() @@ -850,6 +1003,9 @@ class NetworkManagerObserver(object): self._netmgr = None self._olpc_mesh_device_o = None + client = gconf.client_get_default() + self._have_adhoc_networks = client.get_bool(self._SHOW_ADHOC_GCONF_KEY) + def listen(self): try: obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) @@ -867,6 +1023,9 @@ class NetworkManagerObserver(object): self._bus.add_signal_receiver(self.__device_removed_cb, signal_name='DeviceRemoved', dbus_interface=_NM_IFACE) + self._bus.add_signal_receiver(self.__properties_changed_cb, + signal_name='PropertiesChanged', + dbus_interface=_NM_IFACE) settings = network.get_settings() if settings is not None: @@ -909,7 +1068,13 @@ class NetworkManagerObserver(object): device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') if device_type == network.DEVICE_TYPE_802_11_WIRELESS: - self._devices[device_o] = DeviceObserver(self._box, device) + self._devices[device_o] = DeviceObserver(device) + self._devices[device_o].connect('access-point-added', + self.__ap_added_cb) + self._devices[device_o].connect('access-point-removed', + self.__ap_removed_cb) + if self._have_adhoc_networks: + self._box.add_adhoc_networks(device) elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: self._olpc_mesh_device_o = device_o self._box.enable_olpc_mesh(device) @@ -925,11 +1090,29 @@ class NetworkManagerObserver(object): observer = self._devices[device_o] observer.disconnect() del self._devices[device_o] + if self._have_adhoc_networks: + self._box.remove_adhoc_networks() return if self._olpc_mesh_device_o == device_o: self._box.disable_olpc_mesh(device_o) + def __ap_added_cb(self, device_observer, access_point): + self._box.add_access_point(device_observer.device, access_point) + + def __ap_removed_cb(self, device_observer, access_point_o): + self._box.remove_access_point(access_point_o) + + def __properties_changed_cb(self, properties): + if 'WirelessHardwareEnabled' in properties: + if properties['WirelessHardwareEnabled']: + if not self._have_adhoc_networks: + self._box.remove_adhoc_networks() + elif properties['WirelessHardwareEnabled']: + for device in self._devices: + if self._have_adhoc_networks: + self._box.add_adhoc_networks(device) + class MeshBox(gtk.VBox): __gtype_name__ = 'SugarMeshBox' @@ -940,6 +1123,8 @@ class MeshBox(gtk.VBox): gobject.GObject.__init__(self) self.wireless_networks = {} + self._adhoc_manager = None + self._adhoc_networks = [] self._model = neighborhood.get_model() self._buddies = {} @@ -1097,6 +1282,15 @@ class MeshBox(gtk.VBox): ap.disconnect() return + if self._adhoc_manager is not None and \ + network.is_sugar_adhoc_network(ap.name) and \ + ap.mode == network.NM_802_11_MODE_ADHOC: + if old_hash is None: # new Ad-hoc network finished initializing + self._adhoc_manager.add_access_point(ap) + # we are called as well in other cases but we do not need to + # act here as we don't display signal strength for Ad-hoc networks + return + if old_hash is None: # new AP finished initializing self._add_ap_to_network(ap) return @@ -1119,6 +1313,11 @@ class MeshBox(gtk.VBox): ap.initialize() def remove_access_point(self, ap_o): + if self._adhoc_manager is not None: + if self._adhoc_manager.is_sugar_adhoc_access_point(ap_o): + self._adhoc_manager.remove_access_point(ap_o) + return + # we don't keep an index of ap object path to network, but since # we'll only ever have a handful of networks, just try them all... for net in self.wireless_networks.values(): @@ -1135,6 +1334,25 @@ class MeshBox(gtk.VBox): # it (e.g. olpc-mesh adhoc network) logging.debug('Can not remove access point %s' % ap_o) + def add_adhoc_networks(self, device): + if self._adhoc_manager is None: + self._adhoc_manager = get_adhoc_manager_instance() + self._adhoc_manager.start_listening(device) + self._add_adhoc_network_icon(1) + self._add_adhoc_network_icon(6) + self._add_adhoc_network_icon(11) + self._adhoc_manager.autoconnect() + + def remove_adhoc_networks(self): + for icon in self._adhoc_networks: + self._layout.remove(icon) + self._adhoc_networks = [] + + def _add_adhoc_network_icon(self, channel): + icon = SugarAdhocView(channel) + self._layout.add(icon) + self._adhoc_networks.append(icon) + def _add_olpc_mesh_icon(self, mesh_mgr, channel): icon = OlpcMeshView(mesh_mgr, channel) self._layout.add(icon) diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am index 18d44da..1df2cde 100644 --- a/src/jarabe/model/Makefile.am +++ b/src/jarabe/model/Makefile.am @@ -1,5 +1,6 @@ sugardir = $(pythondir)/jarabe/model sugar_PYTHON = \ + adhoc.py \ __init__.py \ buddy.py \ bundleregistry.py \ diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py index 8af2591..f0297c9 100644 --- a/src/jarabe/model/network.py +++ b/src/jarabe/model/network.py @@ -1,6 +1,6 @@ # Copyright (C) 2008 Red Hat, Inc. # Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer -# Copyright (C) 2009 One Laptop per Child +# Copyright (C) 2009-2010 One Laptop per Child # Copyright (C) 2009 Paraguay Educa, Martin Abente # # This program is free software; you can redistribute it and/or modify @@ -100,6 +100,38 @@ GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk' _nm_settings = None _conn_counter = 0 +def frequency_to_channel(frequency): + """Returns the channel matching a given radio channel frequency. If a + frequency is not in the dictionary channel 1 will be returned. + + Keyword arguments: + frequency -- The radio channel frequency in MHz. + + Return: Channel + + """ + 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} + if frequency not in ftoc: + logging.warning("The frequency %s can not be mapped to a channel, " \ + "defaulting to channel 1.", frequency) + return 1 + return ftoc[frequency] + +def is_sugar_adhoc_network(ssid): + """Checks whether an access point is a sugar Ad-hoc network. + + Keyword arguments: + ssid -- Ssid of the access point. + + Return: Boolean + + """ + return ssid.startswith('Ad-hoc Network') + + class WirelessSecurity(object): def __init__(self): self.key_mgmt = None @@ -127,6 +159,7 @@ class Wireless(object): self.security = None self.mode = None self.band = None + self.channel = None def get_dict(self): wireless = {'ssid': self.ssid} @@ -136,6 +169,8 @@ class Wireless(object): wireless['mode'] = self.mode if self.band: wireless['band'] = self.band + if self.channel: + wireless['channel'] = self.channel return wireless class OlpcMesh(object): @@ -509,6 +544,7 @@ class AccessPoint(gobject.GObject): self.wpa_flags = 0 self.rsn_flags = 0 self.mode = 0 + self.channel = 0 def initialize(self): model_props = dbus.Interface(self.model, dbus.PROPERTIES_IFACE) @@ -577,6 +613,8 @@ class AccessPoint(gobject.GObject): self.rsn_flags = properties['RsnFlags'] if 'Mode' in properties: self.mode = properties['Mode'] + if 'Frequency' in properties: + self.channel = frequency_to_channel(properties['Frequency']) self._initialized = True self.emit('props-changed', old_hash) |