[Dextrose] [PATCH] Sharing 3G connection
Martin Abente
martin.abente.lahaye at gmail.com
Mon Nov 1 09:13:06 EDT 2010
Add a new toggle button to gsm palette, which allow users
to share the gsm connection with one click.
---
extensions/deviceicon/network.py | 178 +++++++++++++++++++++++++++++++++++--
1 files changed, 168 insertions(+), 10 deletions(-)
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index 0789f9c..1510abd 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -23,6 +23,7 @@ import logging
import hashlib
import socket
import struct
+import random
import re
import datetime
import time
@@ -61,6 +62,7 @@ _NM_SERIAL_IFACE = 'org.freedesktop.NetworkManager.Device.Serial'
_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
+_NM_OBJ_PROPERTIES = 'org.freedesktop.DBus.Properties'
_GSM_STATE_NOT_READY = 0
_GSM_STATE_DISCONNECTED = 1
@@ -68,6 +70,11 @@ _GSM_STATE_CONNECTING = 2
_GSM_STATE_CONNECTED = 3
_GSM_STATE_FAILED = 4
+_GSM_SHARING_PRIVATE = 0
+_GSM_SHARING_TRYING = 1
+_GSM_SHARING_NEIGHBORHOOD = 2
+
+_GSM_SHARING_CHANNELS = [2,3,4,5,7,8,9,10,12,13]
class WirelessPalette(Palette):
__gtype_name__ = 'SugarWirelessPalette'
@@ -207,6 +214,10 @@ class GsmPalette(Palette):
gobject.TYPE_NONE, ([])),
'gsm-disconnect' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
+ 'gsm-private' : (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, ([])),
+ 'gsm-neighborhood' : (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, ([]))
}
def __init__(self):
@@ -215,12 +226,17 @@ class GsmPalette(Palette):
self._current_state = None
self._failed_connection = False
+ self._sharing_state = _GSM_SHARING_PRIVATE
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._sharing_toggle_item = MenuItem('')
+ self._sharing_toggle_item.connect('activate', self.__sharing_toggle_cb)
+ self.menu.append(self._sharing_toggle_item)
+
self.info_box = gtk.VBox()
self.error_title_label = gtk.Label("")
@@ -302,6 +318,10 @@ class GsmPalette(Palette):
icon = Icon(icon_name='media-eject', \
icon_size=gtk.ICON_SIZE_MENU)
self._toggle_state_item.set_image(icon)
+
+ self.sharing_update_text()
+ self._sharing_toggle_item.show()
+ return
elif self._current_state == _GSM_STATE_FAILED:
message_error = self._get_error_by_nm_reason(reason)
@@ -310,6 +330,8 @@ class GsmPalette(Palette):
raise ValueError('Invalid GSM state while updating label and ' \
'text, %s' % str(self._current_state))
+ self._sharing_toggle_item.hide()
+
def __toggle_state_cb(self, menuitem):
if self._current_state == _GSM_STATE_NOT_READY:
pass
@@ -325,6 +347,38 @@ class GsmPalette(Palette):
raise ValueError('Invalid GSM state while emitting signal, %s' % \
str(self._current_state))
+ def sharing_update_text(self):
+ if self._sharing_state == _GSM_SHARING_PRIVATE:
+ self._sharing_toggle_item.get_child().set_label(_('Private'))
+ icon = Icon(icon_name='zoom-home', icon_size=gtk.ICON_SIZE_MENU)
+ self._sharing_toggle_item.set_image(icon)
+
+ elif self._sharing_state == _GSM_SHARING_TRYING:
+ self._sharing_toggle_item.get_child().set_label(_('Please wait...'))
+
+ elif self._sharing_state == _GSM_SHARING_NEIGHBORHOOD:
+ self._sharing_toggle_item.get_child().set_label(_('My Neighborhood'))
+ icon = Icon(icon_name='zoom-neighborhood', icon_size=gtk.ICON_SIZE_MENU)
+ self._sharing_toggle_item.set_image(icon)
+
+ else:
+ raise ValueError('Invalid GSM sharing state while updating, %s' % \
+ str(self._sharing_state))
+
+ def __sharing_toggle_cb(self, menuitem):
+ if self._sharing_state == _GSM_SHARING_PRIVATE:
+ self.emit('gsm-neighborhood')
+
+ elif self._sharing_state == _GSM_SHARING_TRYING:
+ pass
+
+ elif self._sharing_state == _GSM_SHARING_NEIGHBORHOOD:
+ self.emit('gsm-private')
+
+ else:
+ raise ValueError('Invalid GSM sharing state, %s' % \
+ str(self._sharing_state))
+
def add_alert(self, error, suggestion):
self._failed_connection = True
self._toggle_state_item.get_child().set_label(_('Try connection again'))
@@ -525,8 +579,16 @@ class WirelessDeviceView(ToolButton):
else:
state = network.DEVICE_STATE_UNKNOWN
- if self._mode != network.NM_802_11_MODE_ADHOC and \
- network.is_sugar_adhoc_network(self._name) == False:
+ if self._mode == network.NM_802_11_MODE_ADHOC and \
+ network.is_sugar_adhoc_network(self._name):
+ 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()
+ else:
if state == network.DEVICE_STATE_ACTIVATED:
icon_name = '%s-connected' % 'network-wireless'
else:
@@ -535,14 +597,6 @@ class WirelessDeviceView(ToolButton):
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 \
@@ -730,6 +784,8 @@ class GsmDeviceView(TrayIcon):
def __init__(self, device):
self._connection_time_handler = None
self._connection_timestamp = 0
+ self._shared_connection = None
+ self._target_dev_path = None
client = gconf.client_get_default()
color = xocolor.XoColor(client.get_string('/desktop/sugar/user/color'))
@@ -755,6 +811,8 @@ class GsmDeviceView(TrayIcon):
palette.set_group_id('frame')
palette.connect('gsm-connect', self.__gsm_connect_cb)
palette.connect('gsm-disconnect', self.__gsm_disconnect_cb)
+ palette.connect('gsm-neighborhood', self.__gsm_start_sharing_cb)
+ palette.connect('gsm-private', self.__gsm_stop_sharing_cb)
self._palette = palette
@@ -785,6 +843,106 @@ class GsmDeviceView(TrayIcon):
logging.debug('Connected successfully to gsm device, %s',
active_connection)
+ def __gsm_start_sharing_cb(self, palette):
+ if self._palette._sharing_state == _GSM_SHARING_PRIVATE:
+ logging.debug('GSM will start sharing now')
+ self._palette._sharing_state = _GSM_SHARING_TRYING
+ self._palette.sharing_update_text()
+
+ nm_obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+ nm_iface = dbus.Interface(nm_obj, _NM_IFACE)
+ devs_paths = nm_iface.GetDevices()
+
+ target_dev_path = None
+ for dev_path in devs_paths:
+ dev_obj = self._bus.get_object(_NM_SERVICE, dev_path)
+ dev_props = dbus.Interface(dev_obj, _NM_OBJ_PROPERTIES)
+ device_type = dev_props.Get(_NM_DEVICE_IFACE, 'DeviceType')
+ if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
+ target_dev_path = dev_path
+ break
+
+ if target_dev_path == None:
+ self._gsm_sharing_reset()
+ raise RuntimeError('No device for sharing')
+ self._target_dev_path = target_dev_path
+
+ client = gconf.client_get_default()
+ nick = client.get_string('/desktop/sugar/user/nick')
+ nick = re.sub('\W', '', nick)
+
+ name_format = '%s network'
+ format_length = len(name_format) - len('%s')
+ nick_length = 31 - format_length
+ name = name_format % nick[:nick_length]
+
+ connection = network.find_connection_by_ssid(name)
+ if connection == None:
+ settings = Settings()
+ settings.connection.id = name
+ settings.connection.uuid = unique_id()
+ settings.connection.type = '802-11-wireless'
+ settings.wireless.ssid = dbus.ByteArray(name)
+ settings.wireless.mode = 'adhoc'
+ settings.wireless.band = 'bg'
+ chosen_channel = random.randrange(len(_GSM_SHARING_CHANNELS))
+ settings.wireless.channel = _GSM_SHARING_CHANNELS[chosen_channel]
+ settings.ip4_config = IP4Config()
+ settings.ip4_config.method = 'shared'
+ connection = network.add_connection(name, settings)
+
+ nm_iface.ActivateConnection(network.SETTINGS_SERVICE,
+ connection.path,
+ target_dev_path,
+ '/',
+ reply_handler=self.__gsm_sharing_ok_cb,
+ error_handler=self.__gsm_sharing_error_cb)
+
+ def __gsm_sharing_ok_cb(self, connection):
+ logging.debug('GSM sharing is enabled')
+ self._shared_connection = connection
+ self._bus.add_signal_receiver(self.__gsm_sharing_changed_cb,
+ signal_name='StateChanged',
+ path=self._target_dev_path,
+ dbus_interface=_NM_DEVICE_IFACE)
+ self._palette._sharing_state = _GSM_SHARING_NEIGHBORHOOD
+ self._palette.sharing_update_text()
+
+ def __gsm_sharing_changed_cb(self, new_state, old_state, reason):
+ if new_state == network.DEVICE_STATE_DISCONNECTED:
+ self._gsm_sharing_reset()
+
+ def _gsm_sharing_reset(self):
+ logging.debug('GSM sharing is disabled')
+ if self._target_dev_path != None:
+ self._bus.remove_signal_receiver(self.__gsm_sharing_changed_cb,
+ signal_name='StateChanged',
+ path=self._target_dev_path,
+ dbus_interface=_NM_DEVICE_IFACE)
+ self._shared_connection = None
+ self._target_dev_path = None
+ self._palette._sharing_state = _GSM_SHARING_PRIVATE
+ self._palette.sharing_update_text()
+
+ def __gsm_sharing_error_cb(self, error):
+ logging.debug('GSM sharing could not start: %s' % str(error))
+ self._gsm_sharing_reset()
+
+ def __gsm_stop_sharing_cb(self, palette):
+ logging.debug('GSM will stop sharing now')
+ nm_obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+ nm_iface = dbus.Interface(nm_obj, _NM_IFACE)
+ nm_iface.DeactivateConnection(
+ self._shared_connection,
+ reply_handler=self.__gsm_stop_sharing_ok_cb,
+ error_handler=self.__gsm_stop_sharing_error_cb)
+
+ def __gsm_stop_sharing_ok_cb(self):
+ self._gsm_sharing_reset()
+
+ def __gsm_stop_sharing_error_cb(self):
+ logging.debug('GSM sharing could not stop')
+
def __connect_error_cb(self, error):
raise RuntimeError('Error when connecting to gsm device, %s' % error)
--
1.7.1
More information about the Dextrose
mailing list