Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/cpsection/Makefile.am3
-rw-r--r--extensions/cpsection/aboutcomputer/view.py2
-rw-r--r--extensions/cpsection/modemconfiguration/Makefile.am6
-rw-r--r--extensions/cpsection/modemconfiguration/__init__.py22
-rw-r--r--extensions/cpsection/modemconfiguration/model.py70
-rw-r--r--extensions/cpsection/modemconfiguration/view.py250
-rw-r--r--extensions/cpsection/network/model.py115
-rw-r--r--extensions/cpsection/network/view.py8
-rw-r--r--extensions/cpsection/power/model.py31
-rw-r--r--extensions/cpsection/power/view.py58
-rw-r--r--extensions/deviceicon/network.py628
11 files changed, 967 insertions, 226 deletions
diff --git a/extensions/cpsection/Makefile.am b/extensions/cpsection/Makefile.am
index 73e5164..90d36ea 100644
--- a/extensions/cpsection/Makefile.am
+++ b/extensions/cpsection/Makefile.am
@@ -1,4 +1,5 @@
-SUBDIRS = aboutme aboutcomputer datetime frame language network power
+SUBDIRS = aboutme aboutcomputer datetime frame language \
+ modemconfiguration network power
sugardir = $(pkgdatadir)/extensions/cpsection
sugar_PYTHON = __init__.py
diff --git a/extensions/cpsection/aboutcomputer/view.py b/extensions/cpsection/aboutcomputer/view.py
index dd4f8f3..4b638ff 100644
--- a/extensions/cpsection/aboutcomputer/view.py
+++ b/extensions/cpsection/aboutcomputer/view.py
@@ -174,7 +174,7 @@ class AboutComputer(SectionView):
vbox_copyright.set_border_width(style.DEFAULT_SPACING * 2)
vbox_copyright.set_spacing(style.DEFAULT_SPACING)
- label_copyright = gtk.Label("© 2006-2009 One Laptop per Child "
+ label_copyright = gtk.Label("© 2006-2010 One Laptop per Child "
"Association Inc; Red Hat Inc; Collabora Ltd; "
"and Contributors.")
label_copyright.set_alignment(0, 0)
diff --git a/extensions/cpsection/modemconfiguration/Makefile.am b/extensions/cpsection/modemconfiguration/Makefile.am
new file mode 100644
index 0000000..3e2613e
--- /dev/null
+++ b/extensions/cpsection/modemconfiguration/Makefile.am
@@ -0,0 +1,6 @@
+sugardir = $(pkgdatadir)/extensions/cpsection/modemconfiguration
+
+sugar_PYTHON = \
+ __init__.py \
+ model.py \
+ view.py
diff --git a/extensions/cpsection/modemconfiguration/__init__.py b/extensions/cpsection/modemconfiguration/__init__.py
new file mode 100644
index 0000000..8a219dc
--- /dev/null
+++ b/extensions/cpsection/modemconfiguration/__init__.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2009 Paraguay Educa, Martin Abente
+#
+# 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
+
+from gettext import gettext as _
+
+CLASS = 'ModemConfiguration'
+ICON = 'module-modemconfiguration'
+TITLE = _('Modem Configuration')
+
diff --git a/extensions/cpsection/modemconfiguration/model.py b/extensions/cpsection/modemconfiguration/model.py
new file mode 100644
index 0000000..2545ce1
--- /dev/null
+++ b/extensions/cpsection/modemconfiguration/model.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2009 Paraguay Educa, Martin Abente
+#
+# 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
+
+import gconf
+
+from jarabe.model.network import GSM_USERNAME_PATH, GSM_PASSWORD_PATH, \
+ GSM_NUMBER_PATH, GSM_APN_PATH, GSM_PIN_PATH, \
+ GSM_PUK_PATH
+
+def get_username():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_USERNAME_PATH) or ''
+
+def get_password():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_PASSWORD_PATH) or ''
+
+def get_number():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_NUMBER_PATH) or ''
+
+def get_apn():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_APN_PATH) or ''
+
+def get_pin():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_PIN_PATH) or ''
+
+def get_puk():
+ client = gconf.client_get_default()
+ return client.get_string(GSM_PUK_PATH) or ''
+
+def set_username(username):
+ client = gconf.client_get_default()
+ client.set_string(GSM_USERNAME_PATH, username)
+
+def set_password(password):
+ client = gconf.client_get_default()
+ client.set_string(GSM_PASSWORD_PATH, password)
+
+def set_number(number):
+ client = gconf.client_get_default()
+ client.set_string(GSM_NUMBER_PATH, number)
+
+def set_apn(apn):
+ client = gconf.client_get_default()
+ client.set_string(GSM_APN_PATH, apn)
+
+def set_pin(pin):
+ client = gconf.client_get_default()
+ client.set_string(GSM_PIN_PATH, pin)
+
+def set_puk(puk):
+ client = gconf.client_get_default()
+ client.set_string(GSM_PUK_PATH, puk)
+
diff --git a/extensions/cpsection/modemconfiguration/view.py b/extensions/cpsection/modemconfiguration/view.py
new file mode 100644
index 0000000..b236f3f
--- /dev/null
+++ b/extensions/cpsection/modemconfiguration/view.py
@@ -0,0 +1,250 @@
+# Copyright (C) 2009 Paraguay Educa, Martin Abente
+#
+# 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
+
+import os
+import logging
+from gettext import gettext as _
+
+import gtk
+import gobject
+
+from sugar.graphics import style
+
+from jarabe.controlpanel.sectionview import SectionView
+
+APPLY_TIMEOUT = 1000
+
+class EntryWithLabel(gtk.HBox):
+ __gtype_name__ = "SugarEntryWithLabel"
+
+ def __init__(self, label_text):
+ gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING)
+
+ self._timeout_sid = 0
+ self._changed_handler = None
+ self._is_valid = True
+
+ self.label = gtk.Label(label_text)
+ self.label.modify_fg(gtk.STATE_NORMAL,
+ style.COLOR_SELECTION_GREY.get_gdk_color())
+ self.label.set_alignment(1, 0.5)
+ 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()
+
+ def __entry_changed_cb(self, widget, data=None):
+ if self._timeout_sid:
+ gobject.source_remove(self._timeout_sid)
+ self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT,
+ self.__timeout_cb)
+
+ def __timeout_cb(self):
+ self._timeout_sid = 0
+
+ if self._entry.get_text() == self.get_value():
+ return False
+
+ try:
+ self.set_value(self._entry.get_text())
+ except ValueError:
+ self._is_valid = False
+ else:
+ self._is_valid = True
+
+ self.notify('is-valid')
+
+ return False
+
+ def set_text_from_model(self):
+ self._entry.set_text(self.get_value())
+
+ def get_value(self):
+ raise NotImplementedError
+
+ def set_value(self):
+ 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:'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_username()
+
+ def set_value(self, username):
+ self._model.set_username(username)
+
+class PasswordEntry(EntryWithLabel):
+ def __init__(self, model):
+ EntryWithLabel.__init__(self, _('Password:'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_password()
+
+ def set_value(self, password):
+ self._model.set_password(password)
+
+class NumberEntry(EntryWithLabel):
+ def __init__(self, model):
+ EntryWithLabel.__init__(self, _('Number:'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_number()
+
+ def set_value(self, number):
+ self._model.set_number(number)
+
+class ApnEntry(EntryWithLabel):
+ def __init__(self, model):
+ EntryWithLabel.__init__(self, _('Access Point Name (APN):'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_apn()
+
+ def set_value(self, apn):
+ self._model.set_apn(apn)
+
+class PinEntry(EntryWithLabel):
+ def __init__(self, model):
+ EntryWithLabel.__init__(self, _('Personal Identity Number (PIN):'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_pin()
+
+ def set_value(self, pin):
+ self._model.set_pin(pin)
+
+class PukEntry(EntryWithLabel):
+ def __init__(self, model):
+ EntryWithLabel.__init__(self, _('Personal Unblocking Key (PUK):'))
+ self._model = model
+
+ def get_value(self):
+ return self._model.get_puk()
+
+ def set_value(self, puk):
+ self._model.set_puk(puk)
+
+
+class ModemConfiguration(SectionView):
+ def __init__(self, model, alerts=None):
+ SectionView.__init__(self)
+
+ 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)
+
+ 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)
+ self._text.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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ self._puk_entry.show()
+
+ self.setup()
+
+ def setup(self):
+ self._username_entry.set_text_from_model()
+ self._password_entry.set_text_from_model()
+ self._number_entry.set_text_from_model()
+ self._apn_entry.set_text_from_model()
+ self._pin_entry.set_text_from_model()
+ self._puk_entry.set_text_from_model()
+
+ self.needs_restart = False
+
+ def undo(self):
+ self._model.undo()
+
+ def _validate(self):
+ if self._username_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
+ else:
+ self.props.is_valid = False
+
+ def __notify_is_valid_cb(self, entry, pspec):
+ if entry.is_valid:
+ self.needs_restart = True
+ self._validate()
+
diff --git a/extensions/cpsection/network/model.py b/extensions/cpsection/network/model.py
index 87db6d9..945254a 100644
--- a/extensions/cpsection/network/model.py
+++ b/extensions/cpsection/network/model.py
@@ -15,9 +15,14 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
+import logging
import dbus
from gettext import gettext as _
+from jarabe.model import network
import gconf
+import os
+
+_logger = logging.getLogger('ControlPanel - Network')
_NM_SERVICE = 'org.freedesktop.NetworkManager'
_NM_PATH = '/org/freedesktop/NetworkManager'
@@ -62,50 +67,107 @@ def _restart_jabber():
_PS_INTERFACE)
except dbus.DBusException:
raise ReadError('%s service not available' % _PS_SERVICE)
- ps.RestartServerConnection()
+ ps.RetryConnections()
-def get_radio():
+def print_radio():
+ print ('off', 'on')[get_radio()]
+
+def get_radio_nm():
+ """ Get the state of NetworkManager
+ The user can enable/disable wireless and/or networking
+ return true only if wireless and network are enabled
+ """
bus = dbus.SystemBus()
try:
obj = bus.get_object(_NM_SERVICE, _NM_PATH)
- nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+ nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
except dbus.DBusException:
raise ReadError('%s service not available' % _NM_SERVICE)
- state = nm_props.Get(_NM_IFACE, 'WirelessEnabled')
- if state in (0, 1):
- return state
+ state = nm_props.Get(_NM_IFACE, 'NetworkingEnabled')
+ wireless_state = nm_props.Get(_NM_IFACE, 'WirelessEnabled')
+ _logger.debug('nm state: %s' % state)
+ _logger.debug('nm wireless_state: %s' % wireless_state)
+ if state in (0, 1) and wireless_state in (0, 1):
+ return (state == 1) and (wireless_state == 1)
else:
raise ReadError(_('State is unknown.'))
-def print_radio():
- print ('off', 'on')[get_radio()]
-
-def set_radio(state):
+def set_radio_nm(state):
+ """Enable/disable NetworkManager
+ state : 'on/off'
+ """
+ if not state in ('on', 1, 'off', 0):
+ raise ValueError(_("Error in specified radio argument use on/off."))
+
+ bus = dbus.SystemBus()
+ try:
+ obj = bus.get_object(_NM_SERVICE, _NM_PATH)
+ nm_props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
+ nm = dbus.Interface(obj, _NM_IFACE)
+ except dbus.DBusException:
+ raise ReadError('%s service not available' % _NM_SERVICE)
+
+ if state == 'on' or state == 1:
+ new_state = True
+ else:
+ new_state = False
+
+ prev_state = nm_props.Get(_NM_IFACE, 'NetworkingEnabled')
+ if prev_state != new_state:
+ nm.Enable(new_state)
+ nm_props.Set(_NM_IFACE, 'WirelessEnabled', new_state)
+
+ return 0
+
+def get_radio_rfkill():
+ pipe_stdout = os.popen('/sbin/rfkill list wifi', 'r')
+ try:
+ output = pipe_stdout.read()
+ _logger.debug('rfkill said: %s' % output)
+ blocked = " blocked: yes" in output
+ # if not soft- or hard-blocked, radio is on
+ return not blocked
+
+ finally:
+ pipe_stdout.close()
+
+RFKILL_STATE_FILE = '/home/olpc/.rfkill_block_wifi'
+
+def set_radio_rfkill(state):
"""Turn Radio 'on' or 'off'
state : 'on/off'
- """
+ """
if state == 'on' or state == 1:
- bus = dbus.SystemBus()
+ os.spawnl(os.P_WAIT, "/sbin/rfkill", "rfkill", "unblock", "wifi")
+ # remove the flag file (checked at boot)
try:
- obj = bus.get_object(_NM_SERVICE, _NM_PATH)
- nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
- except dbus.DBusException:
- raise ReadError('%s service not available' % _NM_SERVICE)
- nm_props.Set(_NM_IFACE, 'WirelessEnabled', True)
+ os.unlink(RFKILL_STATE_FILE)
+ except:
+ _logger.debug('File %s was not unlinked' % RFKILL_STATE_FILE)
elif state == 'off' or state == 0:
- bus = dbus.SystemBus()
+ os.spawnl(os.P_WAIT, "/sbin/rfkill", "rfkill", "block", "wifi")
+ # touch the flag file
try:
- obj = bus.get_object(_NM_SERVICE, _NM_PATH)
- nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
- except dbus.DBusException:
- raise ReadError('%s service not available' % _NM_SERVICE)
- nm_props.Set(_NM_IFACE, 'WirelessEnabled', False)
+ fd = open(RFKILL_STATE_FILE, 'w')
+ except IOError:
+ _logger.debug('File %s is not writeable' % RFKILL_STATE_FILE)
+ else:
+ fd.close()
else:
raise ValueError(_("Error in specified radio argument use on/off."))
return 0
+def get_radio():
+ """Get status from rfkill and nm"""
+ return get_radio_rfkill() and get_radio_nm()
+
+def set_radio(state):
+ """ Set status to dot-file and rfkill, and nm"""
+ set_radio_rfkill(state)
+ set_radio_nm(state)
+
def clear_registration():
"""Clear the registration with the schoolserver
"""
@@ -116,13 +178,16 @@ def clear_registration():
def clear_networks():
"""Clear saved passwords and network configurations.
"""
- pass
+ network.clear_connections()
+
+def count_networks():
+ return network.count_connections()
def get_publish_information():
client = gconf.client_get_default()
publish = client.get_bool('/desktop/sugar/collaboration/publish_gadget')
return publish
-
+
def print_publish_information():
print get_publish_information()
diff --git a/extensions/cpsection/network/view.py b/extensions/cpsection/network/view.py
index ef28f00..c387667 100644
--- a/extensions/cpsection/network/view.py
+++ b/extensions/cpsection/network/view.py
@@ -101,6 +101,8 @@ class Network(SectionView):
self._clear_history_button = gtk.Button()
self._clear_history_button.set_label(_('Discard network history'))
box_clear_history.pack_start(self._clear_history_button, expand=False)
+ if self._model.count_networks() == 0:
+ self._clear_history_button.set_sensitive(False)
self._clear_history_button.show()
box_wireless.pack_start(box_clear_history, expand=False)
box_clear_history.show()
@@ -208,7 +210,9 @@ class Network(SectionView):
self._radio_alert.props.msg = detail
self._radio_valid = False
else:
- self._radio_valid = True
+ self._radio_valid = True
+ if self._model.count_networks() != 0:
+ self._clear_history_button.set_sensitive(True)
self._validate()
return False
@@ -239,3 +243,5 @@ class Network(SectionView):
def __network_configuration_reset_cb(self, widget):
self._model.clear_networks()
+ if self._model.count_networks() == 0:
+ self._clear_history_button.set_sensitive(False)
diff --git a/extensions/cpsection/power/model.py b/extensions/cpsection/power/model.py
index 33ec905..c580439 100644
--- a/extensions/cpsection/power/model.py
+++ b/extensions/cpsection/power/model.py
@@ -66,7 +66,10 @@ def set_automatic_pm(enabled):
else:
fd.close()
else:
- os.unlink(POWERD_INHIBIT_FLAG)
+ try:
+ os.unlink(POWERD_INHIBIT_FLAG)
+ except:
+ _logger.debug('File %s was not unlinked' % POWERD_INHIBIT_FLAG)
return 0
# ohmd
@@ -87,29 +90,3 @@ def set_automatic_pm(enabled):
client.set_bool('/desktop/sugar/power/automatic', enabled)
return 0
-def get_extreme_pm():
- client = gconf.client_get_default()
- return client.get_bool('/desktop/sugar/power/extreme')
-
-def print_extreme_pm():
- print ('off', 'on')[get_extreme_pm()]
-
-def set_extreme_pm(enabled):
- """Extreme power management on/off."""
-
- bus = dbus.SystemBus()
- proxy = bus.get_object(OHM_SERVICE_NAME, OHM_SERVICE_PATH)
- keystore = dbus.Interface(proxy, OHM_SERVICE_IFACE)
-
- if enabled == 'on' or enabled == 1:
- keystore.SetKey("suspend.extreme_pm", 1)
- enabled = True
- elif enabled == 'off' or enabled == 0:
- keystore.SetKey("suspend.extreme_pm", 0)
- enabled = False
- else:
- raise ValueError(_("Error in extreme pm argument, use on/off."))
-
- client = gconf.client_get_default()
- client.set_bool('/desktop/sugar/power/extreme', enabled)
- return 0
diff --git a/extensions/cpsection/power/view.py b/extensions/cpsection/power/view.py
index 8f1ed56..d6e2b8c 100644
--- a/extensions/cpsection/power/view.py
+++ b/extensions/cpsection/power/view.py
@@ -29,8 +29,6 @@ class Power(SectionView):
self._model = model
self.restart_alerts = alerts
self._automatic_pm_valid = True
- self._extreme_pm_valid = True
- self._extreme_pm_change_handler = None
self._automatic_pm_change_handler = None
self.set_border_width(style.DEFAULT_SPACING * 2)
@@ -38,7 +36,6 @@ class Power(SectionView):
group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
self._automatic_pm_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING)
- self._extreme_pm_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING)
separator_pm = gtk.HSeparator()
self.pack_start(separator_pm, expand=False)
@@ -80,35 +77,6 @@ class Power(SectionView):
self._automatic_pm_alert.props.msg = self.restart_msg
self._automatic_pm_alert.show()
- box_extreme_pm = gtk.HBox(spacing=style.DEFAULT_SPACING)
- label_extreme_pm = gtk.Label(
- _('Extreme power management (disables' \
- 'wireless radio, increases battery life)'))
- label_extreme_pm.set_alignment(0, 0.5)
- self._extreme_button = gtk.CheckButton()
- self._extreme_button.set_alignment(0, 0)
- box_extreme_pm.pack_start(self._extreme_button, expand=False)
- self._extreme_button.show()
- box_extreme_pm.pack_start(label_extreme_pm, expand=False)
- group.add_widget(label_extreme_pm)
- label_extreme_pm.show()
- box_pm.pack_start(box_extreme_pm, expand=False)
- box_extreme_pm.show()
-
- self._extreme_pm_alert = InlineAlert()
- label_extreme_pm_error = gtk.Label()
- group.add_widget(label_extreme_pm_error)
- self._extreme_pm_alert_box.pack_start(label_extreme_pm_error,
- expand=False)
- label_extreme_pm_error.show()
- self._extreme_pm_alert_box.pack_start(self._extreme_pm_alert,
- expand=False)
- box_pm.pack_end(self._extreme_pm_alert_box, expand=False)
- self._extreme_pm_alert_box.show()
- if 'extreme_pm' in self.restart_alerts:
- self._extreme_pm_alert.props.msg = self.restart_msg
- self._extreme_pm_alert.show()
-
self.pack_start(box_pm, expand=False)
box_pm.show()
@@ -117,38 +85,26 @@ class Power(SectionView):
def setup(self):
try:
automatic_state = self._model.get_automatic_pm()
- extreme_state = self._model.get_extreme_pm()
except Exception, detail:
self._automatic_pm_alert.props.msg = detail
self._automatic_pm_alert.show()
- self._extreme_pm_alert.props.msg = detail
- self._extreme_pm_alert.show()
else:
self._automatic_button.set_active(automatic_state)
- self._extreme_button.set_active(extreme_state)
- self._extreme_pm_valid = True
self._automatic_pm_valid = True
self.needs_restart = False
self._automatic_pm_change_handler = self._automatic_button.connect( \
'toggled', self.__automatic_pm_toggled_cb)
- self._extreme_pm_change_handler = self._extreme_button.connect( \
- 'toggled', self.__extreme_pm_toggled_cb)
def undo(self):
self._automatic_button.disconnect(self._automatic_pm_change_handler)
- self._extreme_button.disconnect(self._extreme_pm_change_handler)
self._model.undo()
- self._extreme_pm_alert.hide()
self._automatic_pm_alert.hide()
def _validate(self):
- if self._extreme_pm_valid and self._automatic_pm_valid:
- self.props.is_valid = True
- else:
- self.props.is_valid = False
+ self.props.is_valid = self._automatic_pm_valid
def __automatic_pm_toggled_cb(self, widget, data=None):
state = widget.get_active()
@@ -163,15 +119,3 @@ class Power(SectionView):
self._validate()
return False
- def __extreme_pm_toggled_cb(self, widget, data=None):
- state = widget.get_active()
- try:
- self._model.set_extreme_pm(state)
- except Exception, detail:
- print detail
- self._extreme_pm_alert.props.msg = detail
- else:
- self._extreme_pm_valid = True
-
- self._validate()
- return False
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index dc14f9c..12ea9f6 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -1,6 +1,7 @@
#
-# Copyright (C) 2008 One Laptop Per Child
+# Copyright (C) 2008-2010 One Laptop Per Child
# Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer
+# Copyright (C) 2009 Paraguay Educa, Martin Abente
#
# 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
@@ -22,7 +23,8 @@ import sha
import socket
import struct
import re
-
+import datetime
+import time
import gtk
import gobject
import gconf
@@ -35,6 +37,7 @@ from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.tray import TrayIcon
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
@@ -50,35 +53,23 @@ _NM_PATH = '/org/freedesktop/NetworkManager'
_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
_NM_WIRED_IFACE = 'org.freedesktop.NetworkManager.Device.Wired'
_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
+_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
+_NM_SERIAL_IFACE = 'org.freedesktop.NetworkManager.Device.Serial'
_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
-_NM_DEVICE_STATE_UNKNOWN = 0
-_NM_DEVICE_STATE_UNMANAGED = 1
-_NM_DEVICE_STATE_UNAVAILABLE = 2
-_NM_DEVICE_STATE_DISCONNECTED = 3
-_NM_DEVICE_STATE_PREPARE = 4
-_NM_DEVICE_STATE_CONFIG = 5
-_NM_DEVICE_STATE_NEED_AUTH = 6
-_NM_DEVICE_STATE_IP_CONFIG = 7
-_NM_DEVICE_STATE_ACTIVATED = 8
-_NM_DEVICE_STATE_FAILED = 9
-
-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]
+_GSM_STATE_NOT_READY = 0
+_GSM_STATE_DISCONNECTED = 1
+_GSM_STATE_CONNECTING = 2
+_GSM_STATE_CONNECTED = 3
+_GSM_STATE_NEED_AUTH = 4
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):
@@ -112,21 +103,23 @@ class WirelessPalette(Palette):
self._disconnect_item.connect('activate', self.__disconnect_activate_cb)
self.menu.append(self._disconnect_item)
- 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...')
- def set_connected(self, frequency, iaddress):
+ def _set_connected(self, iaddress):
self.set_content(self._info)
self.props.secondary_text = _('Connected')
- self._set_channel(frequency)
self._set_ip_address(iaddress)
self._disconnect_item.show()
+ def set_connected_with_frequency(self, frequency, iaddress):
+ self._set_connected(iaddress)
+ self._set_frequency(frequency)
+
+ def set_connected_with_channel(self, channel, iaddress):
+ self._set_connected(iaddress)
+ self._set_channel(channel)
+
def set_disconnected(self):
self.props.primary_text = ''
self.props.secondary_text = ''
@@ -136,14 +129,14 @@ 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_channel(self, frequency):
+ 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)
+
+ def _set_channel(self, channel):
self._channel_label.set_text("%s: %d" % (_("Channel"), channel))
def _set_ip_address(self, ip_address):
@@ -202,10 +195,105 @@ 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, ([])),
+ }
+
+ def __init__(self):
+ Palette.__init__(self, label=_('Wireless modem'))
+
+ self._current_state = None
+
+ self._toggle_state_item = gtk.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_gsm_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()
+ 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()
+ label_alignment.show()
+
+ self.info_box.show()
+ self.set_content(self.info_box)
+
+ def _add_widget_with_padding(self, child, xalign=0, yalign=0.5):
+ alignment = gtk.Alignment(xalign=xalign, yalign=yalign,
+ xscale=1, yscale=0.33)
+ alignment.set_padding(style.DEFAULT_SPACING,
+ style.DEFAULT_SPACING,
+ style.DEFAULT_SPACING,
+ style.DEFAULT_SPACING)
+ alignment.add(child)
+ return alignment
+
+ def set_gsm_state(self, state):
+ self._current_state = state
+ self._update_label_and_text()
+
+ def _update_label_and_text(self):
+ 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')
+
+ elif self._current_state == _GSM_STATE_CONNECTING:
+ self._toggle_state_item.get_child().set_label(_('Cancel'))
+ self.props.secondary_text = _('Connecting...')
+
+ 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')
+
+ else:
+ raise ValueError('Invalid GSM state while updating label and ' \
+ 'text, %s' % str(self._current_state))
+
+ def __toggle_state_cb(self, menuitem):
+ if self._current_state == _GSM_STATE_NOT_READY:
+ pass
+ elif self._current_state == _GSM_STATE_DISCONNECTED:
+ 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))
+
class WirelessDeviceView(ToolButton):
- _ICON_NAME = 'network-wireless'
FRAME_POSITION_RELATIVE = 302
def __init__(self, device):
@@ -224,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()))
@@ -238,13 +326,10 @@ 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 = 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)
@@ -285,7 +370,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,
@@ -309,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']
@@ -329,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)
@@ -369,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 \
@@ -386,7 +477,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(self._frequency, address)
+ self._palette.set_connected_with_frequency(self._frequency,
+ address)
self._icon.props.pulsing = False
else:
self._icon.props.badge_name = None
@@ -399,75 +491,146 @@ class WirelessDeviceView(ToolButton):
self._icon.props.base_color = self._color
def __deactivate_connection_cb(self, palette, data=None):
+ connection = network.find_connection_by_ssid(self._name)
+ if connection:
+ if self._mode == network.NM_802_11_MODE_INFRA:
+ connection.set_disconnected()
+
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')
+ 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)
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]
- nick = re.sub("([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$", '', nick)
-
- connection_name = format % nick
- connection_name += color_suffix
-
- connection = network.find_connection(connection_name)
- if connection is None:
- settings = Settings()
- settings.connection.id = 'Auto ' + connection_name
- 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(connection_name, 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)
def __activate_error_cb(self, err):
logging.debug('Failed to create network: %s', err)
+class OlpcMeshDeviceView(ToolButton):
+ _ICON_NAME = 'network-mesh'
+ FRAME_POSITION_RELATIVE = 302
+
+ def __init__(self, device, state):
+ ToolButton.__init__(self)
+
+ self._bus = dbus.SystemBus()
+ self._device = device
+ self._device_props = None
+ self._device_state = None
+ self._channel = 0
+
+ self._icon = PulsingIcon(icon_name=self._ICON_NAME)
+ self._inactive_color = xocolor.XoColor( \
+ "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
+ style.COLOR_TRANSPARENT.get_svg()))
+ 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.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.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.__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.__wireless_properties_changed_cb,
+ signal_name='PropertiesChanged',
+ path=self._device.object_path,
+ dbus_interface=_NM_OLPC_MESH_IFACE)
+
+ def __get_active_channel_reply_cb(self, channel):
+ self._channel = channel
+ self._update_text()
+
+ def __get_active_channel_error_cb(self, err):
+ logging.error('Error getting the active channel: %s', err)
+
+ def __state_changed_cb(self, new_state, old_state, reason):
+ self._device_state = new_state
+ self._update()
+
+ def __wireless_properties_changed_cb(self, properties):
+ if 'ActiveChannel' in properties:
+ self._channel = properties['ActiveChannel']
+ self._update_text()
+
+ def _update_text(self):
+ text = _("Mesh Network") + " " + str(self._channel)
+ self._palette.props.primary_text = text
+
+ def _update(self):
+ state = self._device_state
+
+ if state in [network.DEVICE_STATE_PREPARE,
+ 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')
+ 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')
+ 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:
+ netmgr.DeactivateConnection(conn_o)
+ break
+ except dbus.exceptions.DBusException:
+ pass
+
class WiredDeviceView(TrayIcon):
_ICON_NAME = 'network-wired'
@@ -486,12 +649,172 @@ class WiredDeviceView(TrayIcon):
self._palette.set_connected(speed, address)
+class GsmDeviceView(TrayIcon):
+
+ _ICON_NAME = 'network-gsm'
+ FRAME_POSITION_RELATIVE = 303
+
+ def __init__(self, device):
+ self._connection_time_handler = None
+ self._connection_timestamp = 0
+
+ client = gconf.client_get_default()
+ color = xocolor.XoColor(client.get_string('/desktop/sugar/user/color'))
+
+ TrayIcon.__init__(self, icon_name=self._ICON_NAME, xo_color=color)
+
+ self._bus = dbus.SystemBus()
+ self._device = device
+
+ self.set_palette_invoker(FrameWidgetInvoker(self))
+ self._palette = self._create_gsm_palette()
+ self.set_palette(self._palette)
+
+ 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.__ppp_stats_changed_cb,
+ signal_name='PppStats',
+ path=self._device.object_path,
+ dbus_interface=_NM_SERIAL_IFACE)
+
+ def _create_gsm_palette(self):
+ palette = GsmPalette()
+
+ palette.set_group_id('frame')
+ palette.connect('gsm-connect', self.__gsm_connect_cb)
+ palette.connect('gsm-disconnect', self.__gsm_disconnect_cb)
+
+ props = dbus.Interface(self._device, 'org.freedesktop.DBus.Properties')
+ props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True,
+ reply_handler=self.__current_state_check_cb,
+ error_handler=self.__current_state_check_error_cb)
+
+ return palette
+
+ def __gsm_connect_cb(self, palette, data=None):
+ connection = network.find_gsm_connection()
+ if connection is not None:
+ 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.__connect_cb,
+ error_handler=self.__connect_error_cb)
+
+ def __connect_cb(self, active_connection):
+ logging.debug('Connected successfully to gsm device, %s',
+ active_connection)
+
+ def __connect_error_cb(self, error):
+ raise RuntimeError('Error when connecting to gsm device, %s' % error)
+
+ 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')
+ 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')
+ devices = props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices')
+ if self._device.object_path in devices:
+ netmgr.DeactivateConnection(
+ conn_o,
+ reply_handler=self.__disconnect_cb,
+ error_handler=self.__disconnect_error_cb)
+ break
+
+ def __disconnect_cb(self):
+ logging.debug('Disconnected successfully gsm device')
+
+ def __disconnect_error_cb(self, error):
+ raise RuntimeError('Error when disconnecting gsm device, %s' % error)
+
+ def __state_changed_cb(self, new_state, old_state, reason):
+ logging.debug('GSM State: %s to %s, reason %s', old_state, new_state, reason)
+ self._update_state(int(new_state))
+
+ def __current_state_check_cb(self, properties):
+ self._update_state(int(properties['State']))
+
+ def __current_state_check_error_cb(self, error):
+ raise RuntimeError('Error when checking gsm device state, %s' % error)
+
+ def _update_state(self, state):
+ gsm_state = None
+
+ if state == network.DEVICE_STATE_ACTIVATED:
+ gsm_state = _GSM_STATE_CONNECTED
+ connection = network.find_gsm_connection()
+ if connection is not None:
+ connection.set_connected()
+ self._connection_timestamp = time.time() - \
+ connection.get_settings().connection.timestamp
+ self._connection_time_handler = gobject.timeout_add( \
+ 1000, self.__connection_timecount_cb)
+ self._update_stats(0, 0)
+ self._update_connection_time()
+ self._palette.info_box.show()
+
+ if state == 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()
+
+ elif state in [network.DEVICE_STATE_UNMANAGED,
+ network.DEVICE_STATE_UNAVAILABLE,
+ network.DEVICE_STATE_UNKNOWN]:
+ gsm_state = _GSM_STATE_NOT_READY
+
+ elif state in [network.DEVICE_STATE_PREPARE,
+ network.DEVICE_STATE_CONFIG,
+ network.DEVICE_STATE_IP_CONFIG]:
+ gsm_state = _GSM_STATE_CONNECTING
+
+ elif state in [network.DEVICE_STATE_NEED_AUTH]:
+ gsm_state = _GSM_STATE_NEED_AUTH
+
+ if self._palette is not None:
+ self._palette.set_gsm_state(gsm_state)
+
+ 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)
+
+ 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)
+
+ def __connection_timecount_cb(self):
+ self._connection_timestamp = self._connection_timestamp + 1
+ self._update_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):
self._device = device
self._device_view = None
self._tray = tray
-
self._device_view = WirelessDeviceView(self._device)
self._tray.add_device(self._device_view)
@@ -502,6 +825,65 @@ 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()
@@ -510,7 +892,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)
@@ -538,8 +920,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)
@@ -550,6 +931,19 @@ class WiredDeviceObserver(object):
del self._device_view
self._device_view = None
+class GsmDeviceObserver(object):
+ def __init__(self, device, tray):
+ self._device = device
+ self._device_view = None
+ self._tray = tray
+
+ self._device_view = GsmDeviceView(device)
+ self._tray.add_device(self._device_view)
+
+ def disconnect(self):
+ self._device_view.disconnect()
+ self._tray.remove_device(self._device_view)
+ self._device_view = None
class NetworkManagerObserver(object):
def __init__(self, tray):
@@ -584,7 +978,7 @@ 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:
@@ -593,6 +987,12 @@ class NetworkManagerObserver(object):
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)
+ self._devices[device_op] = device
def __device_added_cb(self, device_op):
self._check_device(device_op)