diff options
author | Marco Pesenti Gritti <mpgritti@gmail.com> | 2008-10-04 01:52:36 (GMT) |
---|---|---|
committer | Marco Pesenti Gritti <mpgritti@gmail.com> | 2008-10-04 01:52:36 (GMT) |
commit | 90b23a07560d4edf173764c3a3ff62507c759814 (patch) | |
tree | 56867225f1512c77f2784c4bdd13bec32772823f | |
parent | 8ca1368eec29f1378ac1d81e3494c6d503355d04 (diff) |
Rework devices to be actually self contained plugins. A lot
of work is left to cleanup and simplify the code. I'm sorry
for the large changes but the old design didn't really make
any sense.
27 files changed, 754 insertions, 1061 deletions
diff --git a/configure.ac b/configure.ac index a5c630f..64d1cb2 100644 --- a/configure.ac +++ b/configure.ac @@ -50,17 +50,16 @@ extensions/cpsection/frame/Makefile extensions/cpsection/language/Makefile extensions/cpsection/network/Makefile extensions/cpsection/power/Makefile +extensions/deviceicon/Makefile service/Makefile src/Makefile src/jarabe/Makefile src/jarabe/controlpanel/Makefile src/jarabe/desktop/Makefile src/jarabe/frame/Makefile -src/jarabe/frame/devices/Makefile src/jarabe/intro/Makefile src/jarabe/journal/Makefile src/jarabe/view/Makefile src/jarabe/model/Makefile -src/jarabe/model/devices/Makefile po/Makefile.in ]) diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 464800b..d402374 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -1 +1 @@ -SUBDIRS = cpsection +SUBDIRS = cpsection deviceicon diff --git a/extensions/deviceicon/Makefile.am b/extensions/deviceicon/Makefile.am new file mode 100644 index 0000000..66268fd --- /dev/null +++ b/extensions/deviceicon/Makefile.am @@ -0,0 +1,7 @@ +sugardir = $(pkgdatadir)/extensions/deviceicon + +sugar_PYTHON = \ + __init__.py \ + wireless.py \ + battery.py \ + speaker.py diff --git a/extensions/deviceicon/__init__.py b/extensions/deviceicon/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/extensions/deviceicon/__init__.py diff --git a/extensions/deviceicon/battery.py b/extensions/deviceicon/battery.py new file mode 100644 index 0000000..37691b4 --- /dev/null +++ b/extensions/deviceicon/battery.py @@ -0,0 +1,220 @@ +# Copyright (C) 2006-2007, Red Hat, Inc. +# +# 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 USA + +import logging +from gettext import gettext as _ + +import gobject +import gtk +import dbus + +from sugar import profile +from sugar.graphics import style +from sugar.graphics.icon import get_icon_state +from sugar.graphics.tray import TrayIcon +from sugar.graphics.palette import Palette +from sugar.graphics.xocolor import XoColor + +from jarabe.frame.frameinvoker import FrameWidgetInvoker + +_ICON_NAME = 'battery' + +_STATUS_CHARGING = 0 +_STATUS_DISCHARGING = 1 +_STATUS_FULLY_CHARGED = 2 + +_LEVEL_PROP = 'battery.charge_level.percentage' +_CHARGING_PROP = 'battery.rechargeable.is_charging' +_DISCHARGING_PROP = 'battery.rechargeable.is_discharging' + +class DeviceView(TrayIcon): + + FRAME_POSITION_RELATIVE = 1000 + + def __init__(self, udi): + TrayIcon.__init__(self, icon_name=_ICON_NAME, + xo_color=profile.get_color()) + + self._model = DeviceModel(udi) + self.palette = BatteryPalette(_('My Battery')) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + + self._model.connect('notify::level', + self._battery_status_changed_cb) + self._model.connect('notify::charging', + self._battery_status_changed_cb) + self._model.connect('notify::discharging', + self._battery_status_changed_cb) + self._update_info() + + def _update_info(self): + name = _ICON_NAME + current_level = self._model.props.level + xo_color = profile.get_color() + badge_name = None + + if self._model.props.charging: + status = _STATUS_CHARGING + name += '-charging' + xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), + style.COLOR_WHITE.get_svg())) + elif self._model.props.discharging: + status = _STATUS_DISCHARGING + if current_level <= 15: + badge_name = 'emblem-warning' + else: + status = _STATUS_FULLY_CHARGED + + self.icon.props.icon_name = get_icon_state(name, current_level, step=-5) + self.icon.props.xo_color = xo_color + self.icon.props.badge_name = badge_name + + self.palette.set_level(current_level) + self.palette.set_status(status) + + def _battery_status_changed_cb(self, pspec, param): + self._update_info() + +class BatteryPalette(Palette): + + def __init__(self, primary_text): + Palette.__init__(self, primary_text) + + self._level = 0 + self._progress_bar = gtk.ProgressBar() + self._progress_bar.set_size_request( + style.zoom(style.GRID_CELL_SIZE * 4), -1) + self._progress_bar.show() + self._status_label = gtk.Label() + self._status_label.show() + + vbox = gtk.VBox() + vbox.pack_start(self._progress_bar) + vbox.pack_start(self._status_label) + vbox.show() + + self.set_content(vbox) + + def set_level(self, percent): + self._level = percent + fraction = percent / 100.0 + self._progress_bar.set_fraction(fraction) + + def set_status(self, status): + current_level = self._level + secondary_text = '' + status_text = '%s%%' % current_level + + if status == _STATUS_CHARGING: + secondary_text = _('Charging') + elif status == _STATUS_DISCHARGING: + if current_level <= 15: + secondary_text = _('Very little power remaining') + else: + #TODO: make this less of an wild/educated guess + minutes_remaining = int(current_level / 0.59) + remaining_hourpart = minutes_remaining / 60 + remaining_minpart = minutes_remaining % 60 + secondary_text = _('%(hour)d:%(min).2d remaining' + % { 'hour': remaining_hourpart, + 'min': remaining_minpart}) + else: + secondary_text = _('Charged') + + self.props.secondary_text = secondary_text + self._status_label.set_text(status_text) + +class DeviceModel(gobject.GObject): + __gproperties__ = { + 'level' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'charging' : (bool, None, None, False, + gobject.PARAM_READABLE), + 'discharging' : (bool, None, None, False, + gobject.PARAM_READABLE) + } + + def __init__(self, udi): + gobject.GObject.__init__(self) + + bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) + proxy = bus.get_object('org.freedesktop.Hal', udi, + follow_name_owner_changes=True) + self._battery = dbus.Interface(proxy, 'org.freedesktop.Hal.Device') + bus.add_signal_receiver(self._battery_changed, + 'PropertyModified', + 'org.freedesktop.Hal.Device', + 'org.freedesktop.Hal', + udi) + + self._level = self._get_level() + self._charging = self._get_charging() + self._discharging = self._get_discharging() + + def _get_level(self): + try: + return self._battery.GetProperty(_LEVEL_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _LEVEL_PROP) + return 0 + + def _get_charging(self): + try: + return self._battery.GetProperty(_CHARGING_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _CHARGING_PROP) + return False + + def _get_discharging(self): + try: + return self._battery.GetProperty(_DISCHARGING_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _DISCHARGING_PROP) + return False + + def do_get_property(self, pspec): + if pspec.name == 'level': + return self._level + if pspec.name == 'charging': + return self._charging + if pspec.name == 'discharging': + return self._discharging + + def get_type(self): + return 'battery' + + def _battery_changed(self, num_changes, changes_list): + for change in changes_list: + if change[0] == _LEVEL_PROP: + self._level = self._get_level() + self.notify('level') + elif change[0] == _CHARGING_PROP: + self._charging = self._get_charging() + self.notify('charging') + elif change[0] == _DISCHARGING_PROP: + self._discharging = self._get_discharging() + self.notify('discharging') + +def setup(tray): + bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) + proxy = bus.get_object('org.freedesktop.Hal', + '/org/freedesktop/Hal/Manager') + hal_manager = dbus.Interface(proxy, 'org.freedesktop.Hal.Manager') + + for udi in hal_manager.FindDeviceByCapability('battery'): + tray.add_device(DeviceView(udi)) diff --git a/src/jarabe/frame/devices/speaker.py b/extensions/deviceicon/speaker.py index 3070d7b..70cd3dc 100644 --- a/src/jarabe/frame/devices/speaker.py +++ b/extensions/deviceicon/speaker.py @@ -16,6 +16,7 @@ from gettext import gettext as _ +import gobject import gtk from sugar import profile @@ -35,18 +36,19 @@ class DeviceView(TrayIcon): FRAME_POSITION_RELATIVE = 800 - def __init__(self, model): + def __init__(self): TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=profile.get_color()) - self._model = model - self.palette = SpeakerPalette(_('My Speakers'), model=model) + self._model = DeviceModel() + self.palette = SpeakerPalette(_('My Speakers'), model=self._model) self.palette.props.invoker = FrameWidgetInvoker(self) self.palette.set_group_id('frame') - model.connect('notify::level', self.__speaker_status_changed_cb) - model.connect('notify::muted', self.__speaker_status_changed_cb) + self._model.connect('notify::level', self.__speaker_status_changed_cb) + self._model.connect('notify::muted', self.__speaker_status_changed_cb) + self.connect('expose-event', self.__expose_event_cb) self._icon_widget.connect('button-press-event', @@ -158,3 +160,51 @@ class SpeakerPalette(Palette): def __popup_cb(self, palette_): self._update_level() self._update_muted() + +class DeviceModel(gobject.GObject): + __gproperties__ = { + 'level' : (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), + 'muted' : (bool, None, None, False, gobject.PARAM_READWRITE), + } + + def __init__(self): + gobject.GObject.__init__(self) + + sound.muted_changed.connect(self.__muted_changed_cb) + sound.volume_changed.connect(self.__volume_changed_cb) + + def __muted_changed_cb(self): + self.notify('muted') + + def __volume_changed_cb(self): + self.notify('level') + + def _get_level(self): + return sound.get_volume() + + def _set_level(self, new_volume): + sound.set_volume(new_volume) + + def _get_muted(self): + return sound.get_muted() + + def _set_muted(self, mute): + sound.set_muted(mute) + + def get_type(self): + return 'speaker' + + def do_get_property(self, pspec): + if pspec.name == "level": + return self._get_level() + elif pspec.name == "muted": + return self._get_muted() + + def do_set_property(self, pspec, value): + if pspec.name == "level": + self._set_level(value) + elif pspec.name == "muted": + self._set_muted(value) + +def setup(tray): + tray.add_device(DeviceView()) diff --git a/extensions/deviceicon/wireless.py b/extensions/deviceicon/wireless.py new file mode 100644 index 0000000..1544526 --- /dev/null +++ b/extensions/deviceicon/wireless.py @@ -0,0 +1,429 @@ +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 USA + +import logging +from gettext import gettext as _ + +import gobject +import gtk + +from sugar.graphics.icon import get_icon_state +from sugar.graphics.tray import TrayIcon +from sugar.graphics import style +from sugar.graphics.palette import Palette +from sugar import profile + +from jarabe.model import network +from jarabe.frame.frameinvoker import FrameWidgetInvoker + +_ICON_NAME = 'network-wireless' + +STATE_ACTIVATING = 0 +STATE_ACTIVATED = 1 +STATE_INACTIVE = 2 + +nm_state_to_state = { + network.DEVICE_STATE_ACTIVATING : STATE_ACTIVATING, + network.DEVICE_STATE_ACTIVATED : STATE_ACTIVATED, + network.DEVICE_STATE_INACTIVE : STATE_INACTIVE +} + +class WirelessDeviceView(TrayIcon): + + FRAME_POSITION_RELATIVE = 300 + + def __init__(self, nm_device): + TrayIcon.__init__(self, icon_name=_ICON_NAME) + + self.model = WirelessDeviceModel(nm_device) + + meshdev = None + network_manager = network.get_manager() + for dev in network_manager.get_devices(): + if dev.get_type() == network.DEVICE_TYPE_802_11_MESH_OLPC: + meshdev = dev + break + + self._counter = 0 + self.palette = WirelessPalette(self._get_palette_primary_text(), + meshdev) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + self.palette.set_frequency(self._model.props.frequency) + + self._model.connect('notify::name', self._name_changed_cb) + self._model.connect('notify::strength', self._strength_changed_cb) + self._model.connect('notify::state', self._state_changed_cb) + + self._update_icon() + self._update_state() + + def _get_palette_primary_text(self): + if self._model.props.state == STATE_INACTIVE: + return _("Disconnected") + return self._model.props.name + + def _strength_changed_cb(self, model, pspec): + self._update_icon() + # Only update frequency periodically + if self._counter % 4 == 0: + self.palette.set_frequency(self._model.props.frequency) + self._counter += 1 + + def _name_changed_cb(self, model, pspec): + self.palette.set_primary_text(self._get_palette_primary_text()) + + def _state_changed_cb(self, model, pspec): + self._update_icon() + self._update_state() + self.palette.set_primary_text(self._get_palette_primary_text()) + + def _update_icon(self): + # keep this code in sync with view/home/MeshBox.py + strength = self._model.props.strength + if self._model.props.state == STATE_INACTIVE: + strength = 0 + if self._model.props.state == STATE_ACTIVATED: + icon_name = '%s-connected' % _ICON_NAME + else: + icon_name = _ICON_NAME + icon_name = get_icon_state(icon_name, strength) + if icon_name: + self.icon.props.icon_name = icon_name + + def _update_state(self): + # FIXME Change icon colors once we have real icons + state = self._model.props.state + if state == STATE_ACTIVATING: + self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() + self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() + elif state == STATE_ACTIVATED: + (stroke, fill) = self._model.get_active_network_colors() + self.icon.props.stroke_color = stroke + self.icon.props.fill_color = fill + elif state == STATE_INACTIVE: + self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() + self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() + +class WirelessPalette(Palette): + def __init__(self, primary_text, meshdev): + Palette.__init__(self, primary_text, menu_after_content=True) + self._meshdev = meshdev + + self._chan_label = gtk.Label() + self._chan_label.show() + + vbox = gtk.VBox() + vbox.pack_start(self._chan_label) + vbox.show() + + if meshdev: + disconnect_item = gtk.MenuItem(_('Disconnect...')) + disconnect_item.connect('activate', self._disconnect_activate_cb) + self.menu.append(disconnect_item) + disconnect_item.show() + + self.set_content(vbox) + + def _disconnect_activate_cb(self, menuitem): + # Disconnection for an AP means activating the default mesh device + network_manager = network.get_manager() + if network_manager and self._meshdev: + network_manager.set_active_device(self._meshdev) + + def set_frequency(self, freq): + try: + chan = network.freq_to_channel(freq) + except KeyError: + chan = 0 + self._chan_label.set_text("%s: %d" % (_("Channel"), chan)) + +class MeshDeviceView(TrayIcon): + + FRAME_POSITION_RELATIVE = 400 + + def __init__(self, nm_device): + TrayIcon.__init__(self, icon_name='network-mesh') + + self.model = MeshDeviceModel(nm_device) + + self.palette = MeshPalette(_("Mesh Network"), self.model) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + + self.model.connect('notify::state', self._state_changed_cb) + self.model.connect('notify::activation-stage', self._state_changed_cb) + self._update_state() + + def _state_changed_cb(self, model, pspec): + self._update_state() + + def _update_state(self): + # FIXME Change icon colors once we have real icons + state = self._model.props.state + self.palette.update_state(state) + + if state == STATE_ACTIVATING: + self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() + self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() + elif state == STATE_ACTIVATED: + self.icon.props.xo_color = profile.get_color() + elif state == STATE_INACTIVE: + self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() + self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() + + if state == STATE_INACTIVE: + self.palette.set_primary_text(_("Mesh Network")) + else: + chan = network.freq_to_channel(self._model.props.frequency) + if chan > 0: + self.palette.set_primary_text(_("Mesh Network") + " %d" % chan) + self.palette.set_mesh_step(self._model.props.mesh_step, state) + +class MeshPalette(Palette): + def __init__(self, primary_text, model): + Palette.__init__(self, primary_text, menu_after_content=True) + self._model = model + + self._step_label = gtk.Label() + self._step_label.show() + + vbox = gtk.VBox() + vbox.pack_start(self._step_label) + vbox.show() + + self.set_content(vbox) + + self._disconnect_item = gtk.MenuItem(_('Disconnect...')) + self._disconnect_item.connect('activate', self._disconnect_activate_cb) + self.menu.append(self._disconnect_item) + + def update_state(self, state): + if state == STATE_ACTIVATED: + self._disconnect_item.show() + else: + self._disconnect_item.hide() + + def _disconnect_activate_cb(self, menuitem): + # Disconnection for an mesh means activating the default mesh device + # again without a channel + network_manager = network.get_manager() + nm_device = self._model.get_nm_device() + if network_manager and nm_device: + network_manager.set_active_device(nm_device) + + def set_mesh_step(self, step, state): + label = "" + if step == 1: + if state == STATE_ACTIVATED: + label = _("Connected to a School Mesh Portal") + elif state == STATE_ACTIVATING: + label = _("Looking for a School Mesh Portal...") + elif step == 3: + if state == STATE_ACTIVATED: + label = _("Connected to an XO Mesh Portal") + elif state == STATE_ACTIVATING: + label = _("Looking for an XO Mesh Portal...") + elif step == 4: + if state == STATE_ACTIVATED: + label = _("Connected to a Simple Mesh") + elif state == STATE_ACTIVATING: + label = _("Starting a Simple Mesh") + + if len(label): + self._step_label.set_text(label) + else: + logging.debug("Unhandled mesh step %d" % step) + self._step_label.set_text(_("Unknown Mesh")) + +class WirelessDeviceModel(gobject.GObject): + __gproperties__ = { + 'strength' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'state' : (int, None, None, STATE_ACTIVATING, + STATE_INACTIVE, 0, gobject.PARAM_READABLE), + 'activation-stage': (int, None, None, 0, 7, 0, gobject.PARAM_READABLE), + 'frequency': (float, None, None, 0, 2.72, 0, gobject.PARAM_READABLE), + 'mesh-step': (int, None, None, 0, 4, 0, gobject.PARAM_READABLE), + } + + def __init__(self, nm_device): + gobject.GObject.__init__(self) + + self._nm_device = nm_device + + self._nm_device.connect('strength-changed', + self._strength_changed_cb) + self._nm_device.connect('state-changed', + self._state_changed_cb) + self._nm_device.connect('activation-stage-changed', + self._activation_stage_changed_cb) + + def _strength_changed_cb(self, nm_device): + self.notify('strength') + + def _state_changed_cb(self, nm_device): + self.notify('state') + + def _activation_stage_changed_cb(self, nm_device): + self.notify('activation-stage') + + def do_get_property(self, pspec): + if pspec.name == 'strength': + return self._nm_device.get_strength() + elif pspec.name == 'state': + nm_state = self._nm_device.get_state() + return nm_state_to_state[nm_state] + elif pspec.name == 'activation-stage': + return self._nm_device.get_activation_stage() + elif pspec.name == 'frequency': + return self._nm_device.get_frequency() + elif pspec.name == 'mesh-step': + return self._nm_device.get_mesh_step() + + def get_type(self): + return 'mesh' + + def get_id(self): + return str(self._nm_device.get_op()) + + def get_nm_device(self): + return self._nm_device + +class MeshDeviceModel(gobject.GObject): + __gproperties__ = { + 'name' : (str, None, None, None, + gobject.PARAM_READABLE), + 'strength' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'state' : (int, None, None, STATE_ACTIVATING, + STATE_INACTIVE, 0, gobject.PARAM_READABLE), + 'frequency': (float, None, None, 0.0, 9999.99, 0.0, + gobject.PARAM_READABLE) + } + + def __init__(self, nm_device): + gobject.GObject.__init__(self) + + self._nm_device = nm_device + + self._nm_device.connect('strength-changed', + self._strength_changed_cb) + self._nm_device.connect('ssid-changed', + self._ssid_changed_cb) + self._nm_device.connect('state-changed', + self._state_changed_cb) + + def _strength_changed_cb(self, nm_device): + self.notify('strength') + + def _ssid_changed_cb(self, nm_device): + self.notify('name') + + def _state_changed_cb(self, nm_device): + self.notify('state') + + def do_get_property(self, pspec): + if pspec.name == 'strength': + return self._nm_device.get_strength() + elif pspec.name == 'name': + logging.debug('wireless.Device.props.name: %s' % + self._nm_device.get_ssid()) + return self._nm_device.get_ssid() + elif pspec.name == 'state': + nm_state = self._nm_device.get_state() + return nm_state_to_state[nm_state] + elif pspec.name == 'frequency': + return self._nm_device.get_frequency() + + def get_type(self): + return 'wireless' + + def get_id(self): + return str(self._nm_device.get_op()) + + def get_active_network_colors(self): + net = self._nm_device.get_active_network() + if not net: + return (None, None) + return net.get_colors() + +_devices = {} +_sigids = {} + +def setup(tray): + network_manager = network.get_manager() + if not network_manager: + return + + for dev in network_manager.get_devices(): + _check_network_device(dev) + + network_manager.connect('device-added', + _network_device_added_cb, tray) + network_manager.connect('device-activating', + _network_device_activating_cb, tray) + network_manager.connect('device-removed', + _network_device_removed_cb, tray) + +def _network_device_added_cb(manager, nm_device, tray): + state = nm_device.get_state() + if state == network.DEVICE_STATE_ACTIVATING or \ + state == network.DEVICE_STATE_ACTIVATED: + _check_network_device(tray, nm_device) + +def _network_device_activating_cb(manager, nm_device, tray): + _check_network_device(tray, nm_device) + +def _network_device_removed_cb(manager, nm_device, tray): + if _devices.has_key(str(nm_device.get_op())): + tray.remove_device(_devices[str(nm_device.get_op())]) + +def _check_network_device(tray, nm_device): + if not nm_device.is_valid(): + logging.debug("Device %s not valid" % nm_device.get_op()) + return + + dtype = nm_device.get_type() + if dtype == network.DEVICE_TYPE_802_11_WIRELESS \ + or dtype == network.DEVICE_TYPE_802_11_MESH_OLPC: + _add_network_device(tray, nm_device) + +def _network_device_state_changed_cb(model, param, tray, dev): + if dev.props.state == STATE_INACTIVE: + tray.remove_device(dev) + +def _add_network_device(tray, nm_device): + if _devices.has_key(str(nm_device.get_op())): + logging.debug("Tried to add device %s twice" % nm_device.get_op()) + return + + dtype = nm_device.get_type() + if dtype == network.DEVICE_TYPE_802_11_WIRELESS: + dev = WirelessDeviceView(nm_device) + tray.add_device(dev) + sigid = dev.model.connect('notify::state', + _network_device_state_changed_cb, tray, dev) + _sigids[dev] = sigid + if dtype == network.DEVICE_TYPE_802_11_MESH_OLPC: + dev = MeshDeviceView(nm_device) + tray.add_device(dev) + sigid = dev.model.connect('notify::state', + _network_device_state_changed_cb, tray, dev) + _sigids[dev] = sigid diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py index 4b56540..f48670b 100644 --- a/src/jarabe/desktop/meshbox.py +++ b/src/jarabe/desktop/meshbox.py @@ -31,7 +31,6 @@ from sugar.graphics.menuitem import MenuItem from sugar import profile from jarabe.model import accesspointmodel -from jarabe.model.devices import wireless from jarabe.model import shellmodel from jarabe.model import network from jarabe.view.buddyicon import BuddyIcon @@ -222,7 +221,7 @@ class MeshDeviceView(CanvasPulsingIcon): p.menu.append(self._disconnect_item) state = self._nm_device.get_state() - chan = wireless.freq_to_channel(self._nm_device.get_frequency()) + chan = network.freq_to_channel(self._nm_device.get_frequency()) if state == network.DEVICE_STATE_ACTIVATED and chan == self.channel: self._disconnect_item.show() return p @@ -235,7 +234,7 @@ class MeshDeviceView(CanvasPulsingIcon): def _activate_cb(self, icon): network_manager = network.get_manager() if network_manager: - freq = wireless.channel_to_freq(self.channel) + freq = network.channel_to_freq(self.channel) network_manager.set_active_device(self._nm_device, mesh_freq=freq) def _state_changed_cb(self, model): @@ -243,7 +242,7 @@ class MeshDeviceView(CanvasPulsingIcon): def _update_state(self): state = self._nm_device.get_state() - chan = wireless.freq_to_channel(self._nm_device.get_frequency()) + chan = network.freq_to_channel(self._nm_device.get_frequency()) if state == network.DEVICE_STATE_ACTIVATING and chan == self.channel: self._disconnect_item.hide() self.props.pulsing = True diff --git a/src/jarabe/frame/Makefile.am b/src/jarabe/frame/Makefile.am index 575685a..ab8bb3c 100644 --- a/src/jarabe/frame/Makefile.am +++ b/src/jarabe/frame/Makefile.am @@ -1,5 +1,3 @@ -SUBDIRS = devices - sugardir = $(pythondir)/jarabe/frame sugar_PYTHON = \ __init__.py \ diff --git a/src/jarabe/frame/devices/Makefile.am b/src/jarabe/frame/devices/Makefile.am deleted file mode 100644 index 26cce8a..0000000 --- a/src/jarabe/frame/devices/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -sugardir = $(pythondir)/jarabe/frame/devices -sugar_PYTHON = \ - __init__.py \ - battery.py \ - deviceview.py \ - speaker.py \ - mesh.py \ - wireless.py diff --git a/src/jarabe/frame/devices/__init__.py b/src/jarabe/frame/devices/__init__.py deleted file mode 100644 index a9dd95a..0000000 --- a/src/jarabe/frame/devices/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 USA - diff --git a/src/jarabe/frame/devices/battery.py b/src/jarabe/frame/devices/battery.py deleted file mode 100644 index 0302ecd..0000000 --- a/src/jarabe/frame/devices/battery.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 USA - -from gettext import gettext as _ - -import gtk - -from sugar import profile -from sugar.graphics import style -from sugar.graphics.icon import get_icon_state -from sugar.graphics.tray import TrayIcon -from sugar.graphics.palette import Palette -from sugar.graphics.xocolor import XoColor - -from jarabe.frame.frameinvoker import FrameWidgetInvoker - -_ICON_NAME = 'battery' - -_STATUS_CHARGING = 0 -_STATUS_DISCHARGING = 1 -_STATUS_FULLY_CHARGED = 2 - -class DeviceView(TrayIcon): - - FRAME_POSITION_RELATIVE = 1000 - - def __init__(self, model): - TrayIcon.__init__(self, icon_name=_ICON_NAME, - xo_color=profile.get_color()) - - self._model = model - self.palette = BatteryPalette(_('My Battery')) - self.set_palette(self.palette) - self.palette.props.invoker = FrameWidgetInvoker(self) - self.palette.set_group_id('frame') - - model.connect('notify::level', self._battery_status_changed_cb) - model.connect('notify::charging', self._battery_status_changed_cb) - model.connect('notify::discharging', self._battery_status_changed_cb) - self._update_info() - - def _update_info(self): - name = _ICON_NAME - current_level = self._model.props.level - xo_color = profile.get_color() - badge_name = None - - if self._model.props.charging: - status = _STATUS_CHARGING - name += '-charging' - xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), - style.COLOR_WHITE.get_svg())) - elif self._model.props.discharging: - status = _STATUS_DISCHARGING - if current_level <= 15: - badge_name = 'emblem-warning' - else: - status = _STATUS_FULLY_CHARGED - - self.icon.props.icon_name = get_icon_state(name, current_level, step=-5) - self.icon.props.xo_color = xo_color - self.icon.props.badge_name = badge_name - - self.palette.set_level(current_level) - self.palette.set_status(status) - - def _battery_status_changed_cb(self, pspec, param): - self._update_info() - -class BatteryPalette(Palette): - - def __init__(self, primary_text): - Palette.__init__(self, primary_text) - - self._level = 0 - self._progress_bar = gtk.ProgressBar() - self._progress_bar.set_size_request( - style.zoom(style.GRID_CELL_SIZE * 4), -1) - self._progress_bar.show() - self._status_label = gtk.Label() - self._status_label.show() - - vbox = gtk.VBox() - vbox.pack_start(self._progress_bar) - vbox.pack_start(self._status_label) - vbox.show() - - self.set_content(vbox) - - def set_level(self, percent): - self._level = percent - fraction = percent / 100.0 - self._progress_bar.set_fraction(fraction) - - def set_status(self, status): - current_level = self._level - secondary_text = '' - status_text = '%s%%' % current_level - - if status == _STATUS_CHARGING: - secondary_text = _('Charging') - elif status == _STATUS_DISCHARGING: - if current_level <= 15: - secondary_text = _('Very little power remaining') - else: - #TODO: make this less of an wild/educated guess - minutes_remaining = int(current_level / 0.59) - remaining_hourpart = minutes_remaining / 60 - remaining_minpart = minutes_remaining % 60 - secondary_text = _('%(hour)d:%(min).2d remaining' - % { 'hour': remaining_hourpart, - 'min': remaining_minpart}) - else: - secondary_text = _('Charged') - - self.props.secondary_text = secondary_text - self._status_label.set_text(status_text) diff --git a/src/jarabe/frame/devices/deviceview.py b/src/jarabe/frame/devices/deviceview.py deleted file mode 100644 index 90ebbf5..0000000 --- a/src/jarabe/frame/devices/deviceview.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 USA - -def create(model): - name = 'view.devices.' + model.get_type() - - mod = __import__(name) - components = name.split('.') - for comp in components[1:]: - mod = getattr(mod, comp) - - return mod.DeviceView(model) - diff --git a/src/jarabe/frame/devices/mesh.py b/src/jarabe/frame/devices/mesh.py deleted file mode 100644 index 9be65eb..0000000 --- a/src/jarabe/frame/devices/mesh.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# Copyright (C) 2008 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 -# 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 USA - -import logging -from gettext import gettext as _ - -import gtk - -from sugar import profile -from sugar.graphics.tray import TrayIcon -from sugar.graphics import style -from sugar.graphics.palette import Palette - -from jarabe.model.devices import device -from jarabe.model.devices import wireless -from jarabe.model import network -from jarabe.frame.frameinvoker import FrameWidgetInvoker - -class DeviceView(TrayIcon): - - FRAME_POSITION_RELATIVE = 400 - - def __init__(self, model): - TrayIcon.__init__(self, icon_name='network-mesh') - - self._model = model - - self.palette = MeshPalette(_("Mesh Network"), model) - self.set_palette(self.palette) - self.palette.props.invoker = FrameWidgetInvoker(self) - self.palette.set_group_id('frame') - - model.connect('notify::state', self._state_changed_cb) - model.connect('notify::activation-stage', self._state_changed_cb) - self._update_state() - - def _state_changed_cb(self, model, pspec): - self._update_state() - - def _update_state(self): - # FIXME Change icon colors once we have real icons - state = self._model.props.state - self.palette.update_state(state) - - if state == device.STATE_ACTIVATING: - self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() - self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() - elif state == device.STATE_ACTIVATED: - self.icon.props.xo_color = profile.get_color() - elif state == device.STATE_INACTIVE: - self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() - self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() - - if state == device.STATE_INACTIVE: - self.palette.set_primary_text(_("Mesh Network")) - else: - chan = wireless.freq_to_channel(self._model.props.frequency) - if chan > 0: - self.palette.set_primary_text(_("Mesh Network") + " %d" % chan) - self.palette.set_mesh_step(self._model.props.mesh_step, state) - -class MeshPalette(Palette): - def __init__(self, primary_text, model): - Palette.__init__(self, primary_text, menu_after_content=True) - self._model = model - - self._step_label = gtk.Label() - self._step_label.show() - - vbox = gtk.VBox() - vbox.pack_start(self._step_label) - vbox.show() - - self.set_content(vbox) - - self._disconnect_item = gtk.MenuItem(_('Disconnect...')) - self._disconnect_item.connect('activate', self._disconnect_activate_cb) - self.menu.append(self._disconnect_item) - - def update_state(self, state): - if state == device.STATE_ACTIVATED: - self._disconnect_item.show() - else: - self._disconnect_item.hide() - - def _disconnect_activate_cb(self, menuitem): - # Disconnection for an mesh means activating the default mesh device - # again without a channel - network_manager = network.get_manager() - nm_device = self._model.get_nm_device() - if network_manager and nm_device: - network_manager.set_active_device(nm_device) - - def set_mesh_step(self, step, state): - label = "" - if step == 1: - if state == device.STATE_ACTIVATED: - label = _("Connected to a School Mesh Portal") - elif state == device.STATE_ACTIVATING: - label = _("Looking for a School Mesh Portal...") - elif step == 3: - if state == device.STATE_ACTIVATED: - label = _("Connected to an XO Mesh Portal") - elif state == device.STATE_ACTIVATING: - label = _("Looking for an XO Mesh Portal...") - elif step == 4: - if state == device.STATE_ACTIVATED: - label = _("Connected to a Simple Mesh") - elif state == device.STATE_ACTIVATING: - label = _("Starting a Simple Mesh") - - if len(label): - self._step_label.set_text(label) - else: - logging.debug("Unhandled mesh step %d" % step) - self._step_label.set_text(_("Unknown Mesh")) - diff --git a/src/jarabe/frame/devices/wireless.py b/src/jarabe/frame/devices/wireless.py deleted file mode 100644 index 8db1984..0000000 --- a/src/jarabe/frame/devices/wireless.py +++ /dev/null @@ -1,143 +0,0 @@ -# -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 USA - -from gettext import gettext as _ - -import gtk - -from sugar.graphics.icon import get_icon_state -from sugar.graphics.tray import TrayIcon -from sugar.graphics import style -from sugar.graphics.palette import Palette - -from jarabe.model.devices import wireless -from jarabe.model.devices import device -from jarabe.model import network -from jarabe.frame.frameinvoker import FrameWidgetInvoker - -_ICON_NAME = 'network-wireless' - -class DeviceView(TrayIcon): - - FRAME_POSITION_RELATIVE = 300 - - def __init__(self, model): - TrayIcon.__init__(self, icon_name=_ICON_NAME) - self._model = model - - meshdev = None - network_manager = network.get_manager() - for dev in network_manager.get_devices(): - if dev.get_type() == network.DEVICE_TYPE_802_11_MESH_OLPC: - meshdev = dev - break - - self._counter = 0 - self.palette = WirelessPalette(self._get_palette_primary_text(), - meshdev) - self.set_palette(self.palette) - self.palette.props.invoker = FrameWidgetInvoker(self) - self.palette.set_group_id('frame') - self.palette.set_frequency(self._model.props.frequency) - - model.connect('notify::name', self._name_changed_cb) - model.connect('notify::strength', self._strength_changed_cb) - model.connect('notify::state', self._state_changed_cb) - - self._update_icon() - self._update_state() - - def _get_palette_primary_text(self): - if self._model.props.state == device.STATE_INACTIVE: - return _("Disconnected") - return self._model.props.name - - def _strength_changed_cb(self, model, pspec): - self._update_icon() - # Only update frequency periodically - if self._counter % 4 == 0: - self.palette.set_frequency(self._model.props.frequency) - self._counter += 1 - - def _name_changed_cb(self, model, pspec): - self.palette.set_primary_text(self._get_palette_primary_text()) - - def _state_changed_cb(self, model, pspec): - self._update_icon() - self._update_state() - self.palette.set_primary_text(self._get_palette_primary_text()) - - def _update_icon(self): - # keep this code in sync with view/home/MeshBox.py - strength = self._model.props.strength - if self._model.props.state == device.STATE_INACTIVE: - strength = 0 - if self._model.props.state == device.STATE_ACTIVATED: - icon_name = '%s-connected' % _ICON_NAME - else: - icon_name = _ICON_NAME - icon_name = get_icon_state(icon_name, strength) - if icon_name: - self.icon.props.icon_name = icon_name - - def _update_state(self): - # FIXME Change icon colors once we have real icons - state = self._model.props.state - if state == device.STATE_ACTIVATING: - self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() - self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() - elif state == device.STATE_ACTIVATED: - (stroke, fill) = self._model.get_active_network_colors() - self.icon.props.stroke_color = stroke - self.icon.props.fill_color = fill - elif state == device.STATE_INACTIVE: - self.icon.props.fill_color = style.COLOR_INACTIVE_FILL.get_svg() - self.icon.props.stroke_color = style.COLOR_INACTIVE_STROKE.get_svg() - -class WirelessPalette(Palette): - def __init__(self, primary_text, meshdev): - Palette.__init__(self, primary_text, menu_after_content=True) - self._meshdev = meshdev - - self._chan_label = gtk.Label() - self._chan_label.show() - - vbox = gtk.VBox() - vbox.pack_start(self._chan_label) - vbox.show() - - if meshdev: - disconnect_item = gtk.MenuItem(_('Disconnect...')) - disconnect_item.connect('activate', self._disconnect_activate_cb) - self.menu.append(disconnect_item) - disconnect_item.show() - - self.set_content(vbox) - - def _disconnect_activate_cb(self, menuitem): - # Disconnection for an AP means activating the default mesh device - network_manager = network.get_manager() - if network_manager and self._meshdev: - network_manager.set_active_device(self._meshdev) - - def set_frequency(self, freq): - try: - chan = wireless.freq_to_channel(freq) - except KeyError: - chan = 0 - self._chan_label.set_text("%s: %d" % (_("Channel"), chan)) - diff --git a/src/jarabe/frame/devicestray.py b/src/jarabe/frame/devicestray.py index 4b7adb0..ba2805d 100644 --- a/src/jarabe/frame/devicestray.py +++ b/src/jarabe/frame/devicestray.py @@ -14,53 +14,33 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import logging +import os from sugar.graphics import tray -from jarabe.frame.devices import deviceview -from jarabe.model import shellmodel - -_logger = logging.getLogger('DevicesTray') +from jarabe import config class DevicesTray(tray.HTray): def __init__(self): tray.HTray.__init__(self, align=tray.ALIGN_TO_END) - self._device_icons = {} - - devices_model = shellmodel.get_instance().get_devices() - - for device in devices_model: - self._add_device(device) - - devices_model.connect('device-appeared', - self.__device_appeared_cb) - devices_model.connect('device-disappeared', - self.__device_disappeared_cb) - - def _add_device(self, device): - try: - view = deviceview.create(device) - index = 0 - for item in self.get_children(): - index = self.get_item_index(item) - view_pos = getattr(view, "FRAME_POSITION_RELATIVE", -1) - item_pos = getattr(item, "FRAME_POSITION_RELATIVE", 0) - if view_pos < item_pos: - break - self.add_item(view, index=index) - view.show() - self._device_icons[device.get_id()] = view - except Exception, message: - _logger.warn("Not able to add icon for device [%r], because of " - "an error (%s). Continuing." % (device, message)) - - def _remove_device(self, device): - self.remove_item(self._device_icons[device.get_id()]) - del self._device_icons[device.get_id()] - - def __device_appeared_cb(self, model, device): - self._add_device(device) - def __device_disappeared_cb(self, model, device): - self._remove_device(device) + for f in os.listdir(os.path.join(config.ext_path, 'deviceicon')): + if f.endswith('.py') and not f.startswith('__'): + module_name = f[:-3] + mod = __import__('deviceicon.' + module_name, globals(), + locals(), [module_name]) + mod.setup(self) + + def add_device(self, view): + index = 0 + for item in self.get_children(): + index = self.get_item_index(item) + view_pos = getattr(view, "FRAME_POSITION_RELATIVE", -1) + item_pos = getattr(item, "FRAME_POSITION_RELATIVE", 0) + if view_pos < item_pos: + break + self.add_item(view, index=index) + view.show() + + def remove_device(self, view): + self.remove_item(view) diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am index 0703c00..da9f73f 100644 --- a/src/jarabe/model/Makefile.am +++ b/src/jarabe/model/Makefile.am @@ -1,5 +1,3 @@ -SUBDIRS = devices - sugardir = $(pythondir)/jarabe/model sugar_PYTHON = \ __init__.py \ diff --git a/src/jarabe/model/devices/Makefile.am b/src/jarabe/model/devices/Makefile.am deleted file mode 100644 index 59de7aa..0000000 --- a/src/jarabe/model/devices/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -sugardir = $(pythondir)/jarabe/model/devices -sugar_PYTHON = \ - __init__.py \ - battery.py \ - device.py \ - devicesmodel.py \ - speaker.py \ - mesh.py \ - wireless.py diff --git a/src/jarabe/model/devices/__init__.py b/src/jarabe/model/devices/__init__.py deleted file mode 100644 index a9dd95a..0000000 --- a/src/jarabe/model/devices/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 USA - diff --git a/src/jarabe/model/devices/battery.py b/src/jarabe/model/devices/battery.py deleted file mode 100644 index d041907..0000000 --- a/src/jarabe/model/devices/battery.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 USA - -import logging - -import gobject -import dbus - -from jarabe.model.devices import device - -_LEVEL_PROP = 'battery.charge_level.percentage' -_CHARGING_PROP = 'battery.rechargeable.is_charging' -_DISCHARGING_PROP = 'battery.rechargeable.is_discharging' - -class Device(device.Device): - __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, - gobject.PARAM_READABLE), - 'charging' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'discharging' : (bool, None, None, False, - gobject.PARAM_READABLE) - } - - def __init__(self, udi): - device.Device.__init__(self, udi) - - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', udi, - follow_name_owner_changes=True) - self._battery = dbus.Interface(proxy, 'org.freedesktop.Hal.Device') - bus.add_signal_receiver(self._battery_changed, - 'PropertyModified', - 'org.freedesktop.Hal.Device', - 'org.freedesktop.Hal', - udi) - - self._level = self._get_level() - self._charging = self._get_charging() - self._discharging = self._get_discharging() - - def _get_level(self): - try: - return self._battery.GetProperty(_LEVEL_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _LEVEL_PROP) - return 0 - - def _get_charging(self): - try: - return self._battery.GetProperty(_CHARGING_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _CHARGING_PROP) - return False - - def _get_discharging(self): - try: - return self._battery.GetProperty(_DISCHARGING_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _DISCHARGING_PROP) - return False - - def do_get_property(self, pspec): - if pspec.name == 'level': - return self._level - if pspec.name == 'charging': - return self._charging - if pspec.name == 'discharging': - return self._discharging - - def get_type(self): - return 'battery' - - def _battery_changed(self, num_changes, changes_list): - for change in changes_list: - if change[0] == _LEVEL_PROP: - self._level = self._get_level() - self.notify('level') - elif change[0] == _CHARGING_PROP: - self._charging = self._get_charging() - self.notify('charging') - elif change[0] == _DISCHARGING_PROP: - self._discharging = self._get_discharging() - self.notify('discharging') diff --git a/src/jarabe/model/devices/device.py b/src/jarabe/model/devices/device.py deleted file mode 100644 index 014a437..0000000 --- a/src/jarabe/model/devices/device.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 USA - -import gobject -from jarabe.model import network - -from sugar import util - -STATE_ACTIVATING = 0 -STATE_ACTIVATED = 1 -STATE_INACTIVE = 2 - -nm_state_to_state = { - network.DEVICE_STATE_ACTIVATING : STATE_ACTIVATING, - network.DEVICE_STATE_ACTIVATED : STATE_ACTIVATED, - network.DEVICE_STATE_INACTIVE : STATE_INACTIVE -} - -class Device(gobject.GObject): - def __init__(self, device_id=None): - gobject.GObject.__init__(self) - if device_id: - self._id = device_id - else: - self._id = util.unique_id() - - def get_type(self): - return 'unknown' - - def get_id(self): - return self._id diff --git a/src/jarabe/model/devices/devicesmodel.py b/src/jarabe/model/devices/devicesmodel.py deleted file mode 100644 index 390199a..0000000 --- a/src/jarabe/model/devices/devicesmodel.py +++ /dev/null @@ -1,143 +0,0 @@ -# -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 USA - -import logging -import gobject -import dbus - -from jarabe.model.devices import device -from jarabe.model.devices import wireless -from jarabe.model.devices import mesh -from jarabe.model.devices import battery -from jarabe.model.devices import speaker -from jarabe.model import network - -class DevicesModel(gobject.GObject): - __gsignals__ = { - 'device-appeared' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'device-disappeared': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self): - gobject.GObject.__init__(self) - - self._devices = {} - self._sigids = {} - - self._observe_hal_manager() - self._observe_network_manager() - - try: - self.add_device(speaker.Device()) - except Exception, speaker_fail_msg: - logging.error("could not initialize speaker device: %s" % - speaker_fail_msg) - - def _observe_hal_manager(self): - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', - '/org/freedesktop/Hal/Manager') - hal_manager = dbus.Interface(proxy, 'org.freedesktop.Hal.Manager') - - for udi in hal_manager.FindDeviceByCapability('battery'): - self.add_device(battery.Device(udi)) - - def _observe_network_manager(self): - network_manager = network.get_manager() - if not network_manager: - return - - for dev in network_manager.get_devices(): - self._check_network_device(dev) - - network_manager.connect('device-added', - self._network_device_added_cb) - network_manager.connect('device-activating', - self._network_device_activating_cb) - network_manager.connect('device-activated', - self._network_device_activated_cb) - network_manager.connect('device-removed', - self._network_device_removed_cb) - - def _network_device_added_cb(self, network_manager, nm_device): - state = nm_device.get_state() - if state == network.DEVICE_STATE_ACTIVATING or \ - state == network.DEVICE_STATE_ACTIVATED: - self._check_network_device(nm_device) - - def _network_device_activating_cb(self, network_manager, nm_device): - self._check_network_device(nm_device) - - def _network_device_activated_cb(self, network_manager, nm_device): - pass - - def _network_device_removed_cb(self, network_manager, nm_device): - if self._devices.has_key(str(nm_device.get_op())): - self.remove_device(self._get_network_device(nm_device)) - - def _check_network_device(self, nm_device): - if not nm_device.is_valid(): - logging.debug("Device %s not valid" % nm_device.get_op()) - return - - dtype = nm_device.get_type() - if dtype == network.DEVICE_TYPE_802_11_WIRELESS \ - or dtype == network.DEVICE_TYPE_802_11_MESH_OLPC: - self._add_network_device(nm_device) - - def _get_network_device(self, nm_device): - return self._devices[str(nm_device.get_op())] - - def _network_device_state_changed_cb(self, dev, param): - if dev.props.state == device.STATE_INACTIVE: - self.remove_device(dev) - - def _add_network_device(self, nm_device): - if self._devices.has_key(str(nm_device.get_op())): - logging.debug("Tried to add device %s twice" % nm_device.get_op()) - return - - dtype = nm_device.get_type() - if dtype == network.DEVICE_TYPE_802_11_WIRELESS: - dev = wireless.Device(nm_device) - self.add_device(dev) - sigid = dev.connect('notify::state', - self._network_device_state_changed_cb) - self._sigids[dev] = sigid - if dtype == network.DEVICE_TYPE_802_11_MESH_OLPC: - dev = mesh.Device(nm_device) - self.add_device(dev) - sigid = dev.connect('notify::state', - self._network_device_state_changed_cb) - self._sigids[dev] = sigid - - def __iter__(self): - return iter(self._devices.values()) - - def add_device(self, dev): - self._devices[dev.get_id()] = dev - self.emit('device-appeared', dev) - - def remove_device(self, dev): - self.emit('device-disappeared', self._devices[dev.get_id()]) - dev.disconnect(self._sigids[dev]) - del self._sigids[dev] - del self._devices[dev.get_id()] diff --git a/src/jarabe/model/devices/mesh.py b/src/jarabe/model/devices/mesh.py deleted file mode 100644 index ca04d7a..0000000 --- a/src/jarabe/model/devices/mesh.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 USA - -import gobject - -from jarabe.model.devices import device - -class Device(device.Device): - __gproperties__ = { - 'strength' : (int, None, None, 0, 100, 0, - gobject.PARAM_READABLE), - 'state' : (int, None, None, device.STATE_ACTIVATING, - device.STATE_INACTIVE, 0, gobject.PARAM_READABLE), - 'activation-stage': (int, None, None, 0, 7, 0, gobject.PARAM_READABLE), - 'frequency': (float, None, None, 0, 2.72, 0, gobject.PARAM_READABLE), - 'mesh-step': (int, None, None, 0, 4, 0, gobject.PARAM_READABLE), - } - - def __init__(self, nm_device): - device.Device.__init__(self) - self._nm_device = nm_device - - self._nm_device.connect('strength-changed', - self._strength_changed_cb) - self._nm_device.connect('state-changed', - self._state_changed_cb) - self._nm_device.connect('activation-stage-changed', - self._activation_stage_changed_cb) - - def _strength_changed_cb(self, nm_device): - self.notify('strength') - - def _state_changed_cb(self, nm_device): - self.notify('state') - - def _activation_stage_changed_cb(self, nm_device): - self.notify('activation-stage') - - def do_get_property(self, pspec): - if pspec.name == 'strength': - return self._nm_device.get_strength() - elif pspec.name == 'state': - nm_state = self._nm_device.get_state() - return device.nm_state_to_state[nm_state] - elif pspec.name == 'activation-stage': - return self._nm_device.get_activation_stage() - elif pspec.name == 'frequency': - return self._nm_device.get_frequency() - elif pspec.name == 'mesh-step': - return self._nm_device.get_mesh_step() - - def get_type(self): - return 'mesh' - - def get_id(self): - return str(self._nm_device.get_op()) - - def get_nm_device(self): - return self._nm_device - diff --git a/src/jarabe/model/devices/speaker.py b/src/jarabe/model/devices/speaker.py deleted file mode 100644 index b073883..0000000 --- a/src/jarabe/model/devices/speaker.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2008 Martin Dengler -# -# 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 USA - -import gobject - -from jarabe.model import sound -from jarabe.model.devices import device - -class Device(device.Device): - __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), - 'muted' : (bool, None, None, False, gobject.PARAM_READWRITE), - } - - def __init__(self): - device.Device.__init__(self) - - sound.muted_changed.connect(self.__muted_changed_cb) - sound.volume_changed.connect(self.__volume_changed_cb) - - def __muted_changed_cb(self): - self.notify('muted') - - def __volume_changed_cb(self): - self.notify('level') - - def _get_level(self): - return sound.get_volume() - - def _set_level(self, new_volume): - self.sound.set_volume(new_volume) - - def _get_muted(self): - return self.sound.get_muted() - - def _set_muted(self, mute): - self.sound.set_muted(mute) - - def get_type(self): - return 'speaker' - - def do_get_property(self, pspec): - if pspec.name == "level": - return self._get_level() - elif pspec.name == "muted": - return self._get_muted() - - def do_set_property(self, pspec, value): - if pspec.name == "level": - self._set_level(value) - elif pspec.name == "muted": - self._set_muted(value) diff --git a/src/jarabe/model/devices/wireless.py b/src/jarabe/model/devices/wireless.py deleted file mode 100644 index c6ed1b7..0000000 --- a/src/jarabe/model/devices/wireless.py +++ /dev/null @@ -1,95 +0,0 @@ -# -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 USA - -import gobject - -from jarabe.model.devices import device - -def freq_to_channel(freq): - ftoc = { 2.412: 1, 2.417: 2, 2.422: 3, 2.427: 4, - 2.432: 5, 2.437: 6, 2.442: 7, 2.447: 8, - 2.452: 9, 2.457: 10, 2.462: 11, 2.467: 12, - 2.472: 13 - } - return ftoc[freq] - -def channel_to_freq(channel): - ctof = { 1: 2.412, 2: 2.417, 3: 2.422, 4: 2.427, - 5: 2.432, 6: 2.437, 7: 2.442, 8: 2.447, - 9: 2.452, 10: 2.457, 11: 2.462, 12: 2.467, - 13: 2.472 - } - return ctof[channel] - -class Device(device.Device): - __gproperties__ = { - 'name' : (str, None, None, None, - gobject.PARAM_READABLE), - 'strength' : (int, None, None, 0, 100, 0, - gobject.PARAM_READABLE), - 'state' : (int, None, None, device.STATE_ACTIVATING, - device.STATE_INACTIVE, 0, gobject.PARAM_READABLE), - 'frequency': (float, None, None, 0.0, 9999.99, 0.0, - gobject.PARAM_READABLE) - } - - def __init__(self, nm_device): - device.Device.__init__(self) - self._nm_device = nm_device - - self._nm_device.connect('strength-changed', - self._strength_changed_cb) - self._nm_device.connect('ssid-changed', - self._ssid_changed_cb) - self._nm_device.connect('state-changed', - self._state_changed_cb) - - def _strength_changed_cb(self, nm_device): - self.notify('strength') - - def _ssid_changed_cb(self, nm_device): - self.notify('name') - - def _state_changed_cb(self, nm_device): - self.notify('state') - - def do_get_property(self, pspec): - if pspec.name == 'strength': - return self._nm_device.get_strength() - elif pspec.name == 'name': - import logging - logging.debug('wireless.Device.props.name: %s' % - self._nm_device.get_ssid()) - return self._nm_device.get_ssid() - elif pspec.name == 'state': - nm_state = self._nm_device.get_state() - return device.nm_state_to_state[nm_state] - elif pspec.name == 'frequency': - return self._nm_device.get_frequency() - - def get_type(self): - return 'wireless' - - def get_id(self): - return str(self._nm_device.get_op()) - - def get_active_network_colors(self): - net = self._nm_device.get_active_network() - if not net: - return (None, None) - return net.get_colors() - diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py index da5c2a7..d8ffd83 100644 --- a/src/jarabe/model/network.py +++ b/src/jarabe/model/network.py @@ -1149,6 +1149,22 @@ class NMClient(gobject.GObject): return self._devices[device].set_carrier(False) +def freq_to_channel(freq): + ftoc = { 2.412: 1, 2.417: 2, 2.422: 3, 2.427: 4, + 2.432: 5, 2.437: 6, 2.442: 7, 2.447: 8, + 2.452: 9, 2.457: 10, 2.462: 11, 2.467: 12, + 2.472: 13 + } + return ftoc[freq] + +def channel_to_freq(channel): + ctof = { 1: 2.412, 2: 2.417, 3: 2.422, 4: 2.427, + 5: 2.432, 6: 2.437, 7: 2.442, 8: 2.447, + 9: 2.452, 10: 2.457, 11: 2.462, 12: 2.467, + 13: 2.472 + } + return ctof[channel] + def get_manager(): return _manager diff --git a/src/jarabe/model/shellmodel.py b/src/jarabe/model/shellmodel.py index 932aca4..f0ddb71 100644 --- a/src/jarabe/model/shellmodel.py +++ b/src/jarabe/model/shellmodel.py @@ -22,7 +22,6 @@ from jarabe.model.friends import Friends from jarabe.model.meshmodel import MeshModel from jarabe.model.homemodel import HomeModel from jarabe.model.owner import ShellOwner -from jarabe.model.devices.devicesmodel import DevicesModel class ShellModel(gobject.GObject): ZOOM_MESH = 0 @@ -50,7 +49,6 @@ class ShellModel(gobject.GObject): self._friends = Friends() self._mesh = MeshModel() self._home = HomeModel() - self._devices = DevicesModel() self._screen = wnck.screen_get_default() self._screen.connect('showing-desktop-changed', @@ -85,9 +83,6 @@ class ShellModel(gobject.GObject): def get_owner(self): return self._owner - def get_devices(self): - return self._devices - def _showing_desktop_changed_cb(self, screen): showing_desktop = self._screen.get_showing_desktop() if self._showing_desktop != showing_desktop: |