class WirelessPalette(Palette): __gtype_name__ = 'SugarWirelessPalette' __gsignals__ = { 'deactivate-connection': (GObject.SignalFlags.RUN_FIRST, None, ([])), } def __init__(self, primary_text): Palette.__init__(self, label=primary_text) self._disconnect_item = None self._channel_label = Gtk.Label() self._channel_label.props.xalign = 0.0 self._channel_label.show() self._ip_address_label = Gtk.Label() self._ip_address_label.props.xalign = 0.0 self._ip_address_label.show() self._info = Gtk.VBox() self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect('activate', self.__disconnect_activate_cb) self._info.add(self._disconnect_item) separator = PaletteMenuItemSeparator() self._info.pack_start(separator, True, True, 0) def _padded(child, xalign=0, yalign=0.5): padder = Gtk.Alignment.new(xalign=xalign, yalign=yalign, xscale=1, yscale=0.33) padder.set_padding(style.DEFAULT_SPACING, style.DEFAULT_SPACING, style.DEFAULT_SPACING, style.DEFAULT_SPACING) padder.add(child) return padder self._info.pack_start(_padded(self._channel_label), True, True, 0) self._info.pack_start(_padded(self._ip_address_label), True, True, 0) self._info.show_all() def set_connecting(self): self.props.secondary_text = _('Connecting...') def _set_connected(self, iaddress): self.set_content(self._info) self.props.secondary_text = _('Connected') 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 = _('No wireless connection') self.props.secondary_text = '' self._disconnect_item.hide() self.set_content(None) def __disconnect_activate_cb(self, menuitem): self.emit('deactivate-connection') def _set_frequency(self, frequency): channel = network.frequency_to_channel(frequency) self._set_channel(channel) def _set_channel(self, channel): if channel == 0: self._channel_label.set_text('%s: %s' % (_('Channel'), _('Unknown'))) else: self._channel_label.set_text('%s: %d' % (_('Channel'), channel)) def _set_ip_address(self, ip_address): if ip_address is not None: ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % ip_address else: ip_address_text = "" self._ip_address_label.set_text(ip_address_text)
class WirelessNetworkView(EventPulsingIcon): def __init__(self, initial_ap): EventPulsingIcon.__init__(self, pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._access_points = {initial_ap.model.object_path: initial_ap} self._active_ap = None self._device = initial_ap.device self._palette_icon = None self._disconnect_item = None self._connect_item = None self._filtered = False self._ssid = initial_ap.ssid self._display_name = network.ssid_to_display_name(self._ssid) self._mode = initial_ap.mode self._strength = initial_ap.strength self._flags = initial_ap.flags self._wpa_flags = initial_ap.wpa_flags self._rsn_flags = initial_ap.rsn_flags self._device_caps = 0 self._device_state = None self._color = None self._removed_hid = None if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): self._color = profile.get_color() else: sha_hash = hashlib.sha1() data = self._ssid + hex(self._flags) sha_hash.update(data) digest = hash(sha_hash.digest()) index = digest % len(xocolor.colors) self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[index][0], xocolor.colors[index][1])) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self.props.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) self._palette_icon.props.xo_color = self._color self._update_badge() interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_WIRELESS_IFACE, 'WirelessCapabilities', reply_handler=self.__get_device_caps_reply_cb, error_handler=self.__get_device_caps_error_cb) interface_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def _create_palette(self): icon_name = get_icon_state(_AP_ICON_NAME, self._strength) self._palette_icon = Icon(icon_name=icon_name, pixel_size=style.STANDARD_ICON_SIZE, badge_name=self.props.badge_name) p = palette.Palette(primary_text=self._display_name, icon=self._palette_icon) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect( 'activate', self.__disconnect_activate_cb) self.menu_box.add(self._disconnect_item) self._forget_item = PaletteMenuItem(_('Forget')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='list-remove') self._forget_item.set_image(icon) self._forget_item.connect('activate', self.__forget_activate_cb) self.menu_box.add(self._forget_item) p.set_content(self.menu_box) self.menu_box.show_all() self.connect_to_palette_pop_events(p) return p def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update_state() self._update_icon() self._update_badge() self._update_color() def __update_active_ap(self, ap_path): if ap_path in self._access_points: # save reference to active AP, so that we always display the # strength of that one self._active_ap = self._access_points[ap_path] self.update_strength() elif self._active_ap is not None: # revert to showing state of strongest AP again self._active_ap = None self.update_strength() def __wireless_properties_changed_cb(self, properties): if 'ActiveAccessPoint' in properties: self.__update_active_ap(properties['ActiveAccessPoint']) def __get_active_ap_reply_cb(self, ap_path): self.__update_active_ap(ap_path) interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) def __get_active_ap_error_cb(self, err): logging.error('Error getting the active access point: %s', err) def __get_device_caps_reply_cb(self, caps): self._device_caps = caps def __get_device_caps_error_cb(self, err): logging.error('Error getting the wireless device properties: %s', err) def __get_device_state_reply_cb(self, state): self._device_state = state self._update_state() self._update_color() self._update_icon() self._update_badge() def __get_device_state_error_cb(self, err): logging.error('Error getting the device state: %s', err) def _update_icon(self): if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): channel = max([1] + [ap.channel for ap in self._access_points.values()]) if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = 'network-adhoc-%s-connected' % channel else: icon_name = 'network-adhoc-%s' % channel self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name else: if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = '%s-connected' % _AP_ICON_NAME else: icon_name = _AP_ICON_NAME icon_name = get_icon_state(icon_name, self._strength) if icon_name: self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name def _update_badge(self): badge = None favorite = False if self._mode != network.NM_802_11_MODE_ADHOC: locked = (self._flags == network.NM_802_11_AP_FLAGS_PRIVACY) connection = network.find_connection_by_ssid(self._ssid) if connection is not None: favorite = True self._connect_removed(connection) if locked: badge = 'emblem-favorite-locked' else: badge = 'emblem-favorite' elif locked: badge = 'emblem-locked' self.props.badge_name = self._palette_icon.props.badge_name = badge self._forget_item.set_visible(favorite) def _connect_removed(self, connection): if self._removed_hid is not None: return self._removed_hid = connection.connect('removed', self._connection_removed_cb) def _disconnect_removed(self, connection): connection.disconnect(self._removed_hid) self._removed_hid = None def _connection_removed_cb(self, connection): self._update_badge() self._disconnect_removed(connection) def _update_state(self): if self._active_ap is not None: state = self._device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state == network.NM_DEVICE_STATE_PREPARE or \ state == network.NM_DEVICE_STATE_CONFIG or \ state == network.NM_DEVICE_STATE_NEED_AUTH or \ state == network.NM_DEVICE_STATE_IP_CONFIG: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: network.set_connected() if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False def _update_color(self): self.props.base_color = self._color if self._filtered: self.props.pulsing = False self.props.alpha = _FILTERED_ALPHA else: self.props.alpha = 1.0 def __disconnect_activate_cb(self, item): ap_paths = self._access_points.keys() network.disconnect_access_points(ap_paths) def __forget_activate_cb(self, item): network.forget_wireless_network(self._ssid) def _add_ciphers_from_flags(self, flags, pairwise): ciphers = [] if pairwise: if flags & network.NM_802_11_AP_SEC_PAIR_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_PAIR_CCMP: ciphers.append('ccmp') else: if flags & network.NM_802_11_AP_SEC_GROUP_WEP40: ciphers.append('wep40') if flags & network.NM_802_11_AP_SEC_GROUP_WEP104: ciphers.append('wep104') if flags & network.NM_802_11_AP_SEC_GROUP_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_GROUP_CCMP: ciphers.append('ccmp') return ciphers def _get_security(self): if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # No security return None if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # Static WEP, Dynamic WEP, or LEAP wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'none' return wireless_security if (self._mode != network.NM_802_11_MODE_INFRA): # Stuff after this point requires infrastructure logging.error('The infrastructure mode is not supoorted' ' by your wireless device.') return None if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_RSN): # WPA2 PSK first pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) group = self._add_ciphers_from_flags(self._rsn_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'rsn' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_WPA): # WPA PSK pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) group = self._add_ciphers_from_flags(self._wpa_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'wpa' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security def __connect_activate_cb(self, icon): self._connect() def _connect(self): # Activate existing connection, if there is one connection = network.find_connection_by_ssid(self._ssid) if connection: logging.debug('Activating existing connection for SSID %r', self._ssid) connection.activate(self._device) return # Otherwise, create new connection and activate it logging.debug('Creating new connection for SSID %r', self._ssid) settings = Settings() settings.connection.id = self._display_name settings.connection.uuid = str(uuid.uuid4()) settings.connection.type = '802-11-wireless' settings.wireless.ssid = self._ssid if self._mode == network.NM_802_11_MODE_INFRA: settings.wireless.mode = 'infrastructure' settings.connection.autoconnect = True elif self._mode == network.NM_802_11_MODE_ADHOC: settings.wireless.mode = 'adhoc' settings.wireless.band = 'bg' settings.ip4_config = IP4Config() settings.ip4_config.method = 'link-local' wireless_security = self._get_security() settings.wireless_security = wireless_security if wireless_security is not None: settings.wireless.security = '802-11-wireless-security' network.add_and_activate_connection(self._device, settings, self.get_first_ap().model) def set_filter(self, query): normalized_name = normalize_string(self._display_name.decode('utf-8')) self._filtered = normalized_name.find(query) == -1 self._update_icon() self._update_color() def create_keydialog(self, response): keydialog.create(self._ssid, self._flags, self._wpa_flags, self._rsn_flags, self._device_caps, response) def update_strength(self): if self._active_ap is not None: # display strength of AP that we are connected to new_strength = self._active_ap.strength else: # display the strength of the strongest AP that makes up this # network, also considering that there may be no APs new_strength = max([0] + [ap.strength for ap in self._access_points.values()]) if new_strength != self._strength: self._strength = new_strength self._update_icon() def add_ap(self, ap): self._access_points[ap.model.object_path] = ap self.update_strength() def remove_ap(self, ap): path = ap.model.object_path if path not in self._access_points: return del self._access_points[path] if self._active_ap == ap: self._active_ap = None self.update_strength() def num_aps(self): return len(self._access_points) def find_ap(self, ap_path): if ap_path not in self._access_points: return None return self._access_points[ap_path] def get_first_ap(self): return self._access_points.values()[0] def is_olpc_mesh(self): return self._mode == network.NM_802_11_MODE_ADHOC \ and self._ssid == 'olpc-mesh' def remove_all_aps(self): for ap in self._access_points.values(): ap.disconnect() self._access_points = {} self._active_ap = None self.update_strength() def disconnect(self): self._bus.remove_signal_receiver( self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def get_positioning_data(self): return str(self.get_first_ap().network_hash())
class OlpcMeshView(EventPulsingIcon): def __init__(self, mesh_mgr, channel): EventPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME, pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._channel = channel self._mesh_mgr = mesh_mgr self._disconnect_item = None self._connect_item = None self._filtered = False self._device_state = None self._active = False device = mesh_mgr.mesh_device interface_props = dbus.Interface(device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) interface_props.Get(network.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.__device_state_changed_cb, signal_name='StateChanged', path=device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device.object_path, dbus_interface=network.NM_OLPC_MESH_IFACE) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self.props.base_color = profile.get_color() self.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) def _create_palette(self): _palette = palette.Palette(_('Mesh Network %d') % (self._channel, )) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) _palette.set_content(self.menu_box) self.menu_box.show_all() return _palette def __get_device_state_reply_cb(self, state): self._device_state = state self._update() def __get_device_state_error_cb(self, err): logging.error('Error getting the device state: %s', err) def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update() self._update_color() def __get_active_channel_reply_cb(self, channel): self._active = (channel == self._channel) self._update() def __get_active_channel_error_cb(self, err): logging.error('Error getting the active channel: %s', err) def __wireless_properties_changed_cb(self, properties): if 'ActiveChannel' in properties: channel = properties['ActiveChannel'] self._active = (channel == self._channel) self._update() def _update(self): if self._active: state = self._device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state in [network.NM_DEVICE_STATE_PREPARE, network.NM_DEVICE_STATE_CONFIG, network.NM_DEVICE_STATE_NEED_AUTH, network.NM_DEVICE_STATE_IP_CONFIG]: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False def _update_color(self): self.props.base_color = profile.get_color() if self._filtered: self.alpha = _FILTERED_ALPHA else: self.alpha = 1.0 def __connect_activate_cb(self, icon): self._connect() def _connect(self): self._mesh_mgr.user_activate_channel(self._channel) def set_filter(self, query): self._filtered = (query != '') self._update_color() def disconnect(self): device_object_path = self._mesh_mgr.mesh_device.object_path self._bus.remove_signal_receiver( self.__device_state_changed_cb, signal_name='StateChanged', path=device_object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device_object_path, dbus_interface=network.NM_OLPC_MESH_IFACE) def get_positioning_data(self): return str(type(self)) + str(self._channel)
class BuddyMenu(Palette): def __init__(self, buddy): self._buddy = buddy buddy_icon = Icon(icon_name='computer-xo', xo_color=buddy.get_color(), icon_size=Gtk.IconSize.LARGE_TOOLBAR) nick = buddy.get_nick() Palette.__init__(self, None, primary_text=glib.markup_escape_text(nick), icon=buddy_icon) self.menu_box = Gtk.VBox() self.set_content(self.menu_box) self.menu_box.show_all() self._invite_menu = None self._active_activity_changed_hid = None # Fixme: we need to make the widget accessible through the Palette API self._widget.connect('destroy', self.__destroy_cb) self._buddy.connect('notify::nick', self.__buddy_notify_nick_cb) if buddy.is_owner(): self._add_my_items() else: self._add_buddy_items() def __destroy_cb(self, menu): if self._active_activity_changed_hid is not None: home_model = shell.get_model() home_model.disconnect(self._active_activity_changed_hid) self._buddy.disconnect_by_func(self.__buddy_notify_nick_cb) def _add_buddy_items(self): menu_item = None if friends.get_model().has_buddy(self._buddy): menu_item = PaletteMenuItem(_('Remove friend'), 'list-remove') menu_item.connect('activate', self._remove_friend_cb) else: menu_item = PaletteMenuItem(_('Make friend'), 'list-add') menu_item.connect('activate', self._make_friend_cb) self.menu_box.pack_start(menu_item, True, True, 0) self._invite_menu = PaletteMenuItem('') self._invite_menu.connect('activate', self._invite_friend_cb) self.menu_box.pack_start(self._invite_menu, True, True, 0) home_model = shell.get_model() self._active_activity_changed_hid = home_model.connect( 'active-activity-changed', self._cur_activity_changed_cb) activity = home_model.get_active_activity() self._update_invite_menu(activity) def _add_my_items(self): item = PaletteMenuItem(_('Shutdown'), 'system-shutdown') item.connect('activate', self.__shutdown_activate_cb) self.menu_box.pack_start(item, True, True, 0) client = GConf.Client.get_default() if client.get_bool('/desktop/sugar/show_restart'): item = PaletteMenuItem(_('Restart'), 'system-restart') item.connect('activate', self.__reboot_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() if client.get_bool('/desktop/sugar/show_logout'): item = PaletteMenuItem(_('Logout'), 'system-logout') item.connect('activate', self.__logout_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() item = PaletteMenuItem(_('My Settings'), 'preferences-system') item.connect('activate', self.__controlpanel_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() def _quit(self, action): home_window = jarabe.desktop.homewindow.get_instance() home_window.busy_during_delayed_action(action) def __logout_activate_cb(self, menu_item): self._quit(get_session_manager().logout) def __reboot_activate_cb(self, menu_item): self._quit(get_session_manager().reboot) def __shutdown_activate_cb(self, menu_item): self._quit(get_session_manager().shutdown) def __controlpanel_activate_cb(self, menu_item): panel = ControlPanel() panel.set_transient_for(self._widget.get_toplevel()) panel.show() def _update_invite_menu(self, activity): buddy_activity = self._buddy.props.current_activity if buddy_activity is not None: buddy_activity_id = buddy_activity.activity_id else: buddy_activity_id = None if activity is None or activity.is_journal() or \ activity.get_activity_id() == buddy_activity_id: self._invite_menu.hide() else: title = activity.get_title() self._invite_menu.set_label(_('Invite to %s') % title) icon = Icon(file=activity.get_icon_path(), icon_size=Gtk.IconSize.SMALL_TOOLBAR) icon.props.xo_color = activity.get_icon_color() self._invite_menu.set_image(icon) icon.show() self._invite_menu.show() def _cur_activity_changed_cb(self, home_model, activity_model): self._update_invite_menu(activity_model) def __buddy_notify_nick_cb(self, buddy, pspec): self.set_primary_text(glib.markup_escape_text(buddy.props.nick)) def _make_friend_cb(self, menuitem): friends.get_model().make_friend(self._buddy) def _remove_friend_cb(self, menuitem): friends.get_model().remove(self._buddy) def _invite_friend_cb(self, menuitem): activity = shell.get_model().get_active_activity() service = activity.get_service() if service: try: service.InviteContact(self._buddy.props.account, self._buddy.props.contact_id) except dbus.DBusException, e: expected_exceptions = [ 'org.freedesktop.DBus.Error.UnknownMethod', 'org.freedesktop.DBus.Python.NotImplementedError'] if e.get_dbus_name() in expected_exceptions: logging.warning('Trying deprecated Activity.Invite') service.Invite(self._buddy.props.key) else: raise else:
class SugarAdhocView(EventPulsingIcon): """To mimic the mesh behavior on devices where mesh hardware is not available we support the creation of an Ad-hoc network on three channels 1, 6, 11. This is the class for an icon representing a channel in the neighborhood view. """ _ICON_NAME = 'network-adhoc-' _NAME = 'Ad-hoc Network ' def __init__(self, channel): EventPulsingIcon.__init__(self, icon_name=self._ICON_NAME + str(channel), pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._channel = channel self._disconnect_item = None self._connect_item = None self._palette_icon = None self._filtered = False get_adhoc_manager_instance().connect('members-changed', self.__members_changed_cb) get_adhoc_manager_instance().connect('state-changed', self.__state_changed_cb) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self._state_color = XoColor('%s,%s' % (profile.get_color().get_stroke_color(), style.COLOR_TRANSPARENT.get_svg())) self.props.base_color = self._state_color self.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) self._palette_icon.props.xo_color = self._state_color def _create_palette(self): self._palette_icon = Icon( icon_name=self._ICON_NAME + str(self._channel), pixel_size=style.STANDARD_ICON_SIZE) palette_ = palette.Palette(_('Ad-hoc Network %d') % (self._channel, ), icon=self._palette_icon) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect( 'activate', self.__disconnect_activate_cb) self.menu_box.add(self._disconnect_item) palette_.set_content(self.menu_box) self.menu_box.show_all() self._disconnect_item.hide() self.connect_to_palette_pop_events(palette_) return palette_ def __connect_activate_cb(self, icon): get_adhoc_manager_instance().activate_channel(self._channel) def __disconnect_activate_cb(self, icon): get_adhoc_manager_instance().deactivate_active_channel() def __state_changed_cb(self, adhoc_manager, channel, device_state): if self._channel == channel: state = device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state == network.NM_DEVICE_STATE_ACTIVATED: icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel)) else: icon_name = self._ICON_NAME + str(self._channel) if icon_name is not None: self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name if (state >= network.NM_DEVICE_STATE_PREPARE) and \ (state <= network.NM_DEVICE_STATE_IP_CONFIG): if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False self._update_color() def _update_color(self): self.props.base_color = self._state_color if self._filtered: self.props.pulsing = False self.alpha = _FILTERED_ALPHA else: self.alpha = 1.0 def __members_changed_cb(self, adhoc_manager, channel, has_members): if channel == self._channel: if has_members is True: self._state_color = profile.get_color() else: color = '%s,%s' % (profile.get_color().get_stroke_color(), style.COLOR_TRANSPARENT.get_svg()) self._state_color = XoColor(color) if not self._filtered: self.props.base_color = self._state_color self._palette_icon.props.xo_color = self._state_color self.alpha = 1.0 else: self.alpha = _FILTERED_ALPHA def set_filter(self, query): name = self._NAME + str(self._channel) self._filtered = name.lower().find(query) == -1 self._update_color() def get_positioning_data(self): return str(type(self)) + str(self._channel)
class BuddyMenu(Palette): def __init__(self, buddy): self._buddy = buddy buddy_icon = Icon(icon_name="computer-xo", xo_color=buddy.get_color(), pixel_size=style.STANDARD_ICON_SIZE) nick = buddy.get_nick() Palette.__init__(self, None, primary_text=nick, icon=buddy_icon) self.menu_box = Gtk.VBox() self.set_content(self.menu_box) self.menu_box.show_all() self._invite_menu = None self._active_activity_changed_hid = None # Fixme: we need to make the widget accessible through the Palette API self._widget.connect("destroy", self.__destroy_cb) self._buddy.connect("notify::nick", self.__buddy_notify_nick_cb) if buddy.is_owner(): self._add_my_items() else: self._add_buddy_items() def __destroy_cb(self, menu): if self._active_activity_changed_hid is not None: home_model = shell.get_model() home_model.disconnect(self._active_activity_changed_hid) self._buddy.disconnect_by_func(self.__buddy_notify_nick_cb) def _add_buddy_items(self): menu_item = None if friends.get_model().has_buddy(self._buddy): menu_item = PaletteMenuItem(_("Remove friend"), "list-remove") menu_item.connect("activate", self._remove_friend_cb) else: menu_item = PaletteMenuItem(_("Make friend"), "list-add") menu_item.connect("activate", self._make_friend_cb) self.menu_box.pack_start(menu_item, True, True, 0) self._invite_menu = PaletteMenuItem("") self._invite_menu.connect("activate", self._invite_friend_cb) self.menu_box.pack_start(self._invite_menu, True, True, 0) home_model = shell.get_model() self._active_activity_changed_hid = home_model.connect("active-activity-changed", self._cur_activity_changed_cb) activity = home_model.get_active_activity() self._update_invite_menu(activity) def _add_my_items(self): settings = Gio.Settings("org.sugarlabs") show_shutdown = settings.get_boolean("show-shutdown") show_restart = settings.get_boolean("show-restart") show_logout = settings.get_boolean("show-logout") if "SUGAR_SHOW_SHUTDOWN" in os.environ: show_shutdown = os.environ["SUGAR_SHOW_SHUTDOWN"] == "yes" if "SUGAR_SHOW_RESTART" in os.environ: show_restart = os.environ["SUGAR_SHOW_RESTART"] == "yes" if "SUGAR_SHOW_LOGOUT" in os.environ: show_logout = os.environ["SUGAR_SHOW_LOGOUT"] == "yes" if show_shutdown: item = PaletteMenuItem(_("Shutdown"), "system-shutdown") item.connect("activate", self.__shutdown_activate_cb) self.menu_box.pack_start(item, True, True, 0) if show_restart: item = PaletteMenuItem(_("Restart"), "system-restart") item.connect("activate", self.__reboot_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() if show_logout: item = PaletteMenuItem(_("Logout"), "system-logout") item.connect("activate", self.__logout_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() item = PaletteMenuItem(_("My Settings"), "preferences-system") item.connect("activate", self.__controlpanel_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() def _quit(self, action): jarabe.desktop.homewindow.get_instance().busy() action() GObject.timeout_add_seconds(3, self.__quit_timeout_cb) def __quit_timeout_cb(self): jarabe.desktop.homewindow.get_instance().unbusy() alert = TimeoutAlert(30) alert.props.title = _("An activity is not responding.") alert.props.msg = _("You may lose unsaved work if you continue.") alert.connect("response", self.__quit_accept_cb) jarabe.desktop.homewindow.get_instance().add_alert(alert) alert.show() def __quit_accept_cb(self, alert, response_id): jarabe.desktop.homewindow.get_instance().remove_alert(alert) if response_id is Gtk.ResponseType.CANCEL: get_session_manager().cancel_shutdown() else: jarabe.desktop.homewindow.get_instance().busy() get_session_manager().shutdown_completed() def __logout_activate_cb(self, menu_item): self._quit(get_session_manager().logout) def __reboot_activate_cb(self, menu_item): self._quit(get_session_manager().reboot) def __shutdown_activate_cb(self, menu_item): self._quit(get_session_manager().shutdown) def __controlpanel_activate_cb(self, menu_item): # hide the frame when control panel is shown import jarabe.frame frame = jarabe.frame.get_view() frame.hide() # show the control panel panel = ControlPanel() panel.show() def _update_invite_menu(self, activity): buddy_activity = self._buddy.props.current_activity if buddy_activity is not None: buddy_activity_id = buddy_activity.activity_id else: buddy_activity_id = None if activity is None or activity.is_journal() or activity.get_activity_id() == buddy_activity_id: self._invite_menu.hide() else: title = activity.get_title() self._invite_menu.set_label(_("Invite to %s") % title) icon = Icon(file=activity.get_icon_path(), pixel_size=style.SMALL_ICON_SIZE) icon.props.xo_color = activity.get_icon_color() self._invite_menu.set_image(icon) icon.show() self._invite_menu.show() def _cur_activity_changed_cb(self, home_model, activity_model): self._update_invite_menu(activity_model) def __buddy_notify_nick_cb(self, buddy, pspec): self.set_primary_text(buddy.props.nick) def _make_friend_cb(self, menuitem): friends.get_model().make_friend(self._buddy) def _remove_friend_cb(self, menuitem): friends.get_model().remove(self._buddy) def _invite_friend_cb(self, menuitem): activity = shell.get_model().get_active_activity() service = activity.get_service() if service: try: service.InviteContact(self._buddy.props.account, self._buddy.props.contact_id) except dbus.DBusException, e: expected_exceptions = [ "org.freedesktop.DBus.Error.UnknownMethod", "org.freedesktop.DBus.Python.NotImplementedError", ] if e.get_dbus_name() in expected_exceptions: logging.warning("Trying deprecated Activity.Invite") service.Invite(self._buddy.props.key) else: raise else:
class BuddyMenu(Palette): def __init__(self, buddy): self._buddy = buddy buddy_icon = Icon(icon_name='computer-xo', xo_color=buddy.get_color(), pixel_size=style.STANDARD_ICON_SIZE) nick = buddy.get_nick() Palette.__init__(self, None, primary_text=nick, icon=buddy_icon) self.menu_box = Gtk.VBox() self.set_content(self.menu_box) self.menu_box.show_all() self._invite_menu = None self._active_activity_changed_hid = None # Fixme: we need to make the widget accessible through the Palette API self._widget.connect('destroy', self.__destroy_cb) self._buddy.connect('notify::nick', self.__buddy_notify_nick_cb) if buddy.is_owner(): self._add_my_items() else: self._add_buddy_items() def __destroy_cb(self, menu): if self._active_activity_changed_hid is not None: home_model = shell.get_model() home_model.disconnect(self._active_activity_changed_hid) self._buddy.disconnect_by_func(self.__buddy_notify_nick_cb) def _add_buddy_items(self): menu_item = None if friends.get_model().has_buddy(self._buddy): menu_item = PaletteMenuItem(_('Remove friend'), 'list-remove') menu_item.connect('activate', self._remove_friend_cb) else: menu_item = PaletteMenuItem(_('Make friend'), 'list-add') menu_item.connect('activate', self._make_friend_cb) self.menu_box.pack_start(menu_item, True, True, 0) self._invite_menu = PaletteMenuItem('') self._invite_menu.connect('activate', self._invite_friend_cb) self.menu_box.pack_start(self._invite_menu, True, True, 0) home_model = shell.get_model() self._active_activity_changed_hid = home_model.connect( 'active-activity-changed', self._cur_activity_changed_cb) activity = home_model.get_active_activity() self._update_invite_menu(activity) def _add_my_items(self): settings = Gio.Settings('org.sugarlabs') show_shutdown = settings.get_boolean('show-shutdown') show_restart = settings.get_boolean('show-restart') show_logout = settings.get_boolean('show-logout') if "SUGAR_SHOW_SHUTDOWN" in os.environ: show_shutdown = os.environ["SUGAR_SHOW_SHUTDOWN"] == "yes" if "SUGAR_SHOW_RESTART" in os.environ: show_restart = os.environ["SUGAR_SHOW_RESTART"] == "yes" if "SUGAR_SHOW_LOGOUT" in os.environ: show_logout = os.environ["SUGAR_SHOW_LOGOUT"] == "yes" if show_shutdown: item = PaletteMenuItem(_('Shutdown'), 'system-shutdown') item.connect('activate', self.__shutdown_activate_cb) self.menu_box.pack_start(item, True, True, 0) if show_restart: item = PaletteMenuItem(_('Restart'), 'system-restart') item.connect('activate', self.__reboot_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() if show_logout: item = PaletteMenuItem(_('Logout'), 'system-logout') item.connect('activate', self.__logout_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() item = PaletteMenuItem(_('My Settings'), 'preferences-system') item.connect('activate', self.__controlpanel_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() def _quit(self, action): import jarabe.desktop.homewindow home_window = jarabe.desktop.homewindow.get_instance() home_window.busy_during_delayed_action(action) def __logout_activate_cb(self, menu_item): self._quit(get_session_manager().logout) def __reboot_activate_cb(self, menu_item): self._quit(get_session_manager().reboot) def __shutdown_activate_cb(self, menu_item): self._quit(get_session_manager().shutdown) def __controlpanel_activate_cb(self, menu_item): # hide the frame when control panel is shown import jarabe.frame frame = jarabe.frame.get_view() frame.hide() # show the control panel panel = ControlPanel() panel.show() def _update_invite_menu(self, activity): buddy_activity = self._buddy.props.current_activity if buddy_activity is not None: buddy_activity_id = buddy_activity.activity_id else: buddy_activity_id = None if activity is None or activity.is_journal() or \ activity.get_activity_id() == buddy_activity_id: self._invite_menu.hide() else: title = activity.get_title() self._invite_menu.set_label(_('Invite to %s') % title) icon = Icon(file=activity.get_icon_path(), pixel_size=style.SMALL_ICON_SIZE) icon.props.xo_color = activity.get_icon_color() self._invite_menu.set_image(icon) icon.show() self._invite_menu.show() def _cur_activity_changed_cb(self, home_model, activity_model): self._update_invite_menu(activity_model) def __buddy_notify_nick_cb(self, buddy, pspec): self.set_primary_text(buddy.props.nick) def _make_friend_cb(self, menuitem): friends.get_model().make_friend(self._buddy) def _remove_friend_cb(self, menuitem): friends.get_model().remove(self._buddy) def _invite_friend_cb(self, menuitem): activity = shell.get_model().get_active_activity() service = activity.get_service() if service: try: service.InviteContact(self._buddy.props.account, self._buddy.props.contact_id) except dbus.DBusException, e: expected_exceptions = [ 'org.freedesktop.DBus.Error.UnknownMethod', 'org.freedesktop.DBus.Python.NotImplementedError'] if e.get_dbus_name() in expected_exceptions: logging.warning('Trying deprecated Activity.Invite') service.Invite(self._buddy.props.key) else: raise else:
class BuddyMenu(Palette): def __init__(self, buddy): self._buddy = buddy buddy_icon = Icon(icon_name='computer-xo', xo_color=buddy.get_color(), pixel_size=style.STANDARD_ICON_SIZE) nick = buddy.get_nick() Palette.__init__(self, None, primary_text=GLib.markup_escape_text(nick), icon=buddy_icon) self.menu_box = Gtk.VBox() self.set_content(self.menu_box) self.menu_box.show_all() self._invite_menu = None self._active_activity_changed_hid = None # Fixme: we need to make the widget accessible through the Palette API self._widget.connect('destroy', self.__destroy_cb) self._buddy.connect('notify::nick', self.__buddy_notify_nick_cb) if buddy.is_owner(): self._add_my_items() else: self._add_buddy_items() def __destroy_cb(self, menu): if self._active_activity_changed_hid is not None: home_model = shell.get_model() home_model.disconnect(self._active_activity_changed_hid) self._buddy.disconnect_by_func(self.__buddy_notify_nick_cb) def _add_buddy_items(self): menu_item = None if friends.get_model().has_buddy(self._buddy): menu_item = PaletteMenuItem(_('Remove friend'), 'list-remove') menu_item.connect('activate', self._remove_friend_cb) else: menu_item = PaletteMenuItem(_('Make friend'), 'list-add') menu_item.connect('activate', self._make_friend_cb) self.menu_box.pack_start(menu_item, True, True, 0) self._invite_menu = PaletteMenuItem('') self._invite_menu.connect('activate', self._invite_friend_cb) self.menu_box.pack_start(self._invite_menu, True, True, 0) home_model = shell.get_model() self._active_activity_changed_hid = home_model.connect( 'active-activity-changed', self._cur_activity_changed_cb) activity = home_model.get_active_activity() self._update_invite_menu(activity) def _add_my_items(self): settings = Gio.Settings('org.sugarlabs') show_shutdown = settings.get_boolean('show-shutdown') show_restart = settings.get_boolean('show-restart') show_logout = settings.get_boolean('show-logout') if "SUGAR_SHOW_SHUTDOWN" in os.environ: show_shutdown = os.environ["SUGAR_SHOW_SHUTDOWN"] == "yes" if "SUGAR_SHOW_RESTART" in os.environ: show_restart = os.environ["SUGAR_SHOW_RESTART"] == "yes" if "SUGAR_SHOW_LOGOUT" in os.environ: show_logout = os.environ["SUGAR_SHOW_LOGOUT"] == "yes" if show_shutdown: item = PaletteMenuItem(_('Shutdown'), 'system-shutdown') item.connect('activate', self.__shutdown_activate_cb) self.menu_box.pack_start(item, True, True, 0) if show_restart: item = PaletteMenuItem(_('Restart'), 'system-restart') item.connect('activate', self.__reboot_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() if show_logout: item = PaletteMenuItem(_('Logout'), 'system-logout') item.connect('activate', self.__logout_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() item = PaletteMenuItem(_('My Settings'), 'preferences-system') item.connect('activate', self.__controlpanel_activate_cb) self.menu_box.pack_start(item, True, True, 0) item.show() def _quit(self, action): import jarabe.desktop.homewindow home_window = jarabe.desktop.homewindow.get_instance() home_window.busy_during_delayed_action(action) def __logout_activate_cb(self, menu_item): self._quit(get_session_manager().logout) def __reboot_activate_cb(self, menu_item): self._quit(get_session_manager().reboot) def __shutdown_activate_cb(self, menu_item): self._quit(get_session_manager().shutdown) def __controlpanel_activate_cb(self, menu_item): # hide the frame when control panel is shown import jarabe.frame frame = jarabe.frame.get_view() frame.hide() # show the control panel panel = ControlPanel() panel.show() def _update_invite_menu(self, activity): buddy_activity = self._buddy.props.current_activity if buddy_activity is not None: buddy_activity_id = buddy_activity.activity_id else: buddy_activity_id = None if activity is None or activity.is_journal() or \ activity.get_activity_id() == buddy_activity_id: self._invite_menu.hide() else: title = activity.get_title() self._invite_menu.set_label(_('Invite to %s') % title) icon = Icon(file=activity.get_icon_path(), pixel_size=style.SMALL_ICON_SIZE) icon.props.xo_color = activity.get_icon_color() self._invite_menu.set_image(icon) icon.show() self._invite_menu.show() def _cur_activity_changed_cb(self, home_model, activity_model): self._update_invite_menu(activity_model) def __buddy_notify_nick_cb(self, buddy, pspec): self.set_primary_text(GLib.markup_escape_text(buddy.props.nick)) def _make_friend_cb(self, menuitem): friends.get_model().make_friend(self._buddy) def _remove_friend_cb(self, menuitem): friends.get_model().remove(self._buddy) def _invite_friend_cb(self, menuitem): activity = shell.get_model().get_active_activity() service = activity.get_service() if service: try: service.InviteContact(self._buddy.props.account, self._buddy.props.contact_id) except dbus.DBusException, e: expected_exceptions = [ 'org.freedesktop.DBus.Error.UnknownMethod', 'org.freedesktop.DBus.Python.NotImplementedError'] if e.get_dbus_name() in expected_exceptions: logging.warning('Trying deprecated Activity.Invite') service.Invite(self._buddy.props.key) else: raise else:
class OlpcMeshView(EventPulsingIcon): def __init__(self, mesh_mgr, channel): EventPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME, pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._channel = channel self._mesh_mgr = mesh_mgr self._disconnect_item = None self._connect_item = None self._filtered = False self._device_state = None self._active = False device = mesh_mgr.mesh_device interface_props = dbus.Interface(device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) interface_props.Get(network.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.__device_state_changed_cb, signal_name='StateChanged', path=device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device.object_path, dbus_interface=network.NM_OLPC_MESH_IFACE) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self.props.base_color = profile.get_color() self.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) def _create_palette(self): _palette = palette.Palette(_('Mesh Network %d') % (self._channel, )) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) _palette.set_content(self.menu_box) self.menu_box.show_all() return _palette def __get_device_state_reply_cb(self, state): self._device_state = state self._update() @staticmethod def __get_device_state_error_cb(err): logging.error('Error getting the device state: %s', err) def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update() self._update_color() def __get_active_channel_reply_cb(self, channel): self._active = (channel == self._channel) self._update() @staticmethod def __get_active_channel_error_cb(err): logging.error('Error getting the active channel: %s', err) def __wireless_properties_changed_cb(self, properties): if 'ActiveChannel' in properties: channel = properties['ActiveChannel'] self._active = (channel == self._channel) self._update() def _update(self): if self._active: state = self._device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state in [ network.NM_DEVICE_STATE_PREPARE, network.NM_DEVICE_STATE_CONFIG, network.NM_DEVICE_STATE_NEED_AUTH, network.NM_DEVICE_STATE_IP_CONFIG ]: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False def _update_color(self): self.props.base_color = profile.get_color() if self._filtered: self.alpha = _FILTERED_ALPHA else: self.alpha = 1.0 def __connect_activate_cb(self, icon): self._connect() def _connect(self): self._mesh_mgr.user_activate_channel(self._channel) def set_filter(self, query): self._filtered = (query != '') self._update_color() def disconnect(self): device_object_path = self._mesh_mgr.mesh_device.object_path self._bus.remove_signal_receiver( self.__device_state_changed_cb, signal_name='StateChanged', path=device_object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device_object_path, dbus_interface=network.NM_OLPC_MESH_IFACE) def get_positioning_data(self): return str(type(self)) + str(self._channel)
class WirelessNetworkView(EventPulsingIcon): def __init__(self, initial_ap): EventPulsingIcon.__init__(self, pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._access_points = {initial_ap.model.object_path: initial_ap} self._active_ap = None self._device = initial_ap.device self._palette_icon = None self._disconnect_item = None self._connect_item = None self._filtered = False self._ssid = initial_ap.ssid self._display_name = network.ssid_to_display_name(self._ssid) self._mode = initial_ap.mode self._strength = initial_ap.strength self._flags = initial_ap.flags self._wpa_flags = initial_ap.wpa_flags self._rsn_flags = initial_ap.rsn_flags self._device_caps = 0 self._device_state = None self._color = None self._removed_hid = None if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): self._color = profile.get_color() else: sha_hash = hashlib.sha1() data = self._ssid.decode() + hex(self._flags) sha_hash.update(data.encode('utf-8')) digest = hash(sha_hash.digest()) index = digest % len(xocolor.colors) self._color = xocolor.XoColor( '%s,%s' % (xocolor.colors[index][0], xocolor.colors[index][1])) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self.props.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) self._palette_icon.props.xo_color = self._color self._update_badge() interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_WIRELESS_IFACE, 'WirelessCapabilities', reply_handler=self.__get_device_caps_reply_cb, error_handler=self.__get_device_caps_error_cb) interface_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def _create_palette(self): icon_name = get_icon_state(_AP_ICON_NAME, self._strength) self._palette_icon = Icon(icon_name=icon_name, pixel_size=style.STANDARD_ICON_SIZE, badge_name=self.props.badge_name) p = palette.Palette(primary_text=self._display_name, icon=self._palette_icon) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect('activate', self.__disconnect_activate_cb) self.menu_box.add(self._disconnect_item) self._forget_item = PaletteMenuItem(_('Forget')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='list-remove') self._forget_item.set_image(icon) self._forget_item.connect('activate', self.__forget_activate_cb) self.menu_box.add(self._forget_item) p.set_content(self.menu_box) self.menu_box.show_all() self.connect_to_palette_pop_events(p) return p def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update_state() self._update_icon() self._update_badge() self._update_color() def __update_active_ap(self, ap_path): if ap_path in self._access_points: # save reference to active AP, so that we always display the # strength of that one self._active_ap = self._access_points[ap_path] self.update_strength() elif self._active_ap is not None: # revert to showing state of strongest AP again self._active_ap = None self.update_strength() def __wireless_properties_changed_cb(self, properties): if 'ActiveAccessPoint' in properties: self.__update_active_ap(properties['ActiveAccessPoint']) def __get_active_ap_reply_cb(self, ap_path): self.__update_active_ap(ap_path) interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) @staticmethod def __get_active_ap_error_cb(err): logging.error('Error getting the active access point: %s', err) def __get_device_caps_reply_cb(self, caps): self._device_caps = caps @staticmethod def __get_device_caps_error_cb(err): logging.error('Error getting the wireless device properties: %s', err) def __get_device_state_reply_cb(self, state): self._device_state = state self._update_state() self._update_color() self._update_icon() self._update_badge() @staticmethod def __get_device_state_error_cb(err): logging.error('Error getting the device state: %s', err) def _update_icon(self): if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): channel = max( [1] + [ap.channel for ap in list(self._access_points.values())]) if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = 'network-adhoc-%s-connected' % channel else: icon_name = 'network-adhoc-%s' % channel self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name else: if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = '%s-connected' % _AP_ICON_NAME else: icon_name = _AP_ICON_NAME icon_name = get_icon_state(icon_name, self._strength) if icon_name: self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name def _update_badge(self): badge = None favorite = False if self._mode != network.NM_802_11_MODE_ADHOC: locked = (self._flags == network.NM_802_11_AP_FLAGS_PRIVACY) connection = network.find_connection_by_ssid(self._ssid) if connection is not None: favorite = True self._connect_removed(connection) if locked: badge = 'emblem-favorite-locked' else: badge = 'emblem-favorite' elif locked: badge = 'emblem-locked' self.props.badge_name = self._palette_icon.props.badge_name = badge self._forget_item.set_visible(favorite) def _connect_removed(self, connection): if self._removed_hid is not None: return self._removed_hid = connection.connect('removed', self._connection_removed_cb) def _disconnect_removed(self, connection): connection.disconnect(self._removed_hid) self._removed_hid = None def _connection_removed_cb(self, connection): self._update_badge() self._disconnect_removed(connection) def _update_state(self): if self._active_ap is not None: state = self._device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state == network.NM_DEVICE_STATE_PREPARE or \ state == network.NM_DEVICE_STATE_CONFIG or \ state == network.NM_DEVICE_STATE_NEED_AUTH or \ state == network.NM_DEVICE_STATE_IP_CONFIG: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: network.set_connected() if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False def _update_color(self): self.props.base_color = self._color if self._filtered: self.props.pulsing = False self.props.alpha = _FILTERED_ALPHA else: self.props.alpha = 1.0 def __disconnect_activate_cb(self, item): ap_paths = list(self._access_points.keys()) network.disconnect_access_points(ap_paths) def __forget_activate_cb(self, item): network.forget_wireless_network(self._ssid) @staticmethod def _add_ciphers_from_flags(flags, pairwise): ciphers = [] if pairwise: if flags & network.NM_802_11_AP_SEC_PAIR_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_PAIR_CCMP: ciphers.append('ccmp') else: if flags & network.NM_802_11_AP_SEC_GROUP_WEP40: ciphers.append('wep40') if flags & network.NM_802_11_AP_SEC_GROUP_WEP104: ciphers.append('wep104') if flags & network.NM_802_11_AP_SEC_GROUP_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_GROUP_CCMP: ciphers.append('ccmp') return ciphers def _get_security(self): if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # No security return None if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # Static WEP, Dynamic WEP, or LEAP wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'none' return wireless_security if (self._mode != network.NM_802_11_MODE_INFRA): # Stuff after this point requires infrastructure logging.error('The infrastructure mode is not supoorted' ' by your wireless device.') return None if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_RSN): # WPA2 PSK first pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) group = self._add_ciphers_from_flags(self._rsn_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'rsn' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_WPA): # WPA PSK pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) group = self._add_ciphers_from_flags(self._wpa_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'wpa' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security def __connect_activate_cb(self, icon): self._connect() def _connect(self): # Activate existing connection, if there is one connection = network.find_connection_by_ssid(self._ssid) if connection: logging.debug('Activating existing connection for SSID %r', self._ssid) connection.activate(self._device) return # Otherwise, create new connection and activate it logging.debug('Creating new connection for SSID %r', self._ssid) settings = Settings() settings.connection.id = self._display_name settings.connection.uuid = str(uuid.uuid4()) settings.connection.type = '802-11-wireless' settings.wireless.ssid = self._ssid if self._mode == network.NM_802_11_MODE_INFRA: settings.wireless.mode = 'infrastructure' settings.connection.autoconnect = True elif self._mode == network.NM_802_11_MODE_ADHOC: settings.wireless.mode = 'adhoc' settings.wireless.band = 'bg' settings.ip4_config = IP4Config() settings.ip4_config.method = 'link-local' wireless_security = self._get_security() settings.wireless_security = wireless_security if wireless_security is not None: settings.wireless.security = '802-11-wireless-security' network.add_and_activate_connection(self._device, settings, self.get_first_ap().model) def set_filter(self, query): normalized_name = normalize_string(self._display_name) self._filtered = normalized_name.find(query) == -1 self._update_icon() self._update_color() def create_keydialog(self, response): keydialog.create(self._ssid, self._flags, self._wpa_flags, self._rsn_flags, self._device_caps, response) def update_strength(self): if self._active_ap is not None: # display strength of AP that we are connected to new_strength = self._active_ap.strength else: # display the strength of the strongest AP that makes up this # network, also considering that there may be no APs new_strength = max( [0] + [ap.strength for ap in list(self._access_points.values())]) if new_strength != self._strength: self._strength = new_strength self._update_icon() def add_ap(self, ap): self._access_points[ap.model.object_path] = ap self.update_strength() def remove_ap(self, ap): path = ap.model.object_path if path not in self._access_points: return del self._access_points[path] if self._active_ap == ap: self._active_ap = None self.update_strength() def num_aps(self): return len(self._access_points) def find_ap(self, ap_path): if ap_path not in self._access_points: return None return self._access_points[ap_path] def get_first_ap(self): return list(self._access_points.values())[0] def is_olpc_mesh(self): return self._mode == network.NM_802_11_MODE_ADHOC \ and self._ssid == b'olpc-mesh' def remove_all_aps(self): for ap in list(self._access_points.values()): ap.disconnect() self._access_points = {} self._active_ap = None self.update_strength() def disconnect(self): self._bus.remove_signal_receiver( self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def get_positioning_data(self): return str(self.get_first_ap().network_hash())
class SugarAdhocView(EventPulsingIcon): """To mimic the mesh behavior on devices where mesh hardware is not available we support the creation of an Ad-hoc network on three channels 1, 6, 11. This is the class for an icon representing a channel in the neighborhood view. """ _ICON_NAME = 'network-adhoc-' _NAME = 'Ad-hoc Network ' def __init__(self, channel): EventPulsingIcon.__init__(self, icon_name=self._ICON_NAME + str(channel), pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._channel = channel self._disconnect_item = None self._connect_item = None self._palette_icon = None self._filtered = False get_adhoc_manager_instance().connect('members-changed', self.__members_changed_cb) get_adhoc_manager_instance().connect('state-changed', self.__state_changed_cb) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self._state_color = XoColor('%s,%s' % (profile.get_color().get_stroke_color(), style.COLOR_TRANSPARENT.get_svg())) self.props.base_color = self._state_color self.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) self._palette_icon.props.xo_color = self._state_color def _create_palette(self): self._palette_icon = Icon(icon_name=self._ICON_NAME + str(self._channel), pixel_size=style.STANDARD_ICON_SIZE) palette_ = palette.Palette(_('Ad-hoc Network %d') % (self._channel, ), icon=self._palette_icon) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect('activate', self.__disconnect_activate_cb) self.menu_box.add(self._disconnect_item) palette_.set_content(self.menu_box) self.menu_box.show_all() self._disconnect_item.hide() self.connect_to_palette_pop_events(palette_) return palette_ def __connect_activate_cb(self, icon): get_adhoc_manager_instance().activate_channel(self._channel) @staticmethod def __disconnect_activate_cb(icon): get_adhoc_manager_instance().deactivate_active_channel() def __state_changed_cb(self, adhoc_manager, channel, device_state): if self._channel == channel: state = device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state == network.NM_DEVICE_STATE_ACTIVATED: icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel)) else: icon_name = self._ICON_NAME + str(self._channel) if icon_name is not None: self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name if (state >= network.NM_DEVICE_STATE_PREPARE) and \ (state <= network.NM_DEVICE_STATE_IP_CONFIG): if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False self._update_color() def _update_color(self): self.props.base_color = self._state_color if self._filtered: self.props.pulsing = False self.alpha = _FILTERED_ALPHA else: self.alpha = 1.0 def __members_changed_cb(self, adhoc_manager, channel, has_members): if channel == self._channel: if has_members is True: self._state_color = profile.get_color() else: color = '%s,%s' % (profile.get_color().get_stroke_color(), style.COLOR_TRANSPARENT.get_svg()) self._state_color = XoColor(color) if not self._filtered: self.props.base_color = self._state_color self._palette_icon.props.xo_color = self._state_color self.alpha = 1.0 else: self.alpha = _FILTERED_ALPHA def set_filter(self, query): name = self._NAME + str(self._channel) self._filtered = name.lower().find(query) == -1 self._update_color() def get_positioning_data(self): return str(type(self)) + str(self._channel)
class WirelessPalette(Palette): __gtype_name__ = 'SugarWirelessPalette' __gsignals__ = { 'deactivate-connection': (GObject.SignalFlags.RUN_FIRST, None, ([])), } def __init__(self, primary_text): Palette.__init__(self, label=primary_text) self._disconnect_item = None self._channel_label = Gtk.Label() self._channel_label.props.xalign = 0.0 self._channel_label.show() self._ip_address_label = Gtk.Label() self._ip_address_label.props.xalign = 0.0 self._ip_address_label.show() self._info = Gtk.VBox() self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(icon_size=Gtk.IconSize.MENU, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect('activate', self.__disconnect_activate_cb) self._info.add(self._disconnect_item) separator = PaletteMenuItemSeparator() self._info.pack_start(separator, True, True, 0) def _padded(child, xalign=0, yalign=0.5): padder = Gtk.Alignment.new(xalign=xalign, yalign=yalign, xscale=1, yscale=0.33) padder.set_padding(style.DEFAULT_SPACING, style.DEFAULT_SPACING, style.DEFAULT_SPACING, style.DEFAULT_SPACING) padder.add(child) return padder self._info.pack_start(_padded(self._channel_label), True, True, 0) self._info.pack_start(_padded(self._ip_address_label), True, True, 0) self._info.show_all() def set_connecting(self): label = glib.markup_escape_text(_('Connecting...')) self.props.secondary_text = label def _set_connected(self, iaddress): self.set_content(self._info) self.props.secondary_text = glib.markup_escape_text(_('Connected')) 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): label = glib.markup_escape_text(_('No wireless connection')) self.props.primary_text = label self.props.secondary_text = '' self._disconnect_item.hide() self.set_content(None) def __disconnect_activate_cb(self, menuitem): self.emit('deactivate-connection') def _set_frequency(self, frequency): channel = network.frequency_to_channel(frequency) 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): if ip_address is not None: ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % \ socket.inet_ntoa(struct.pack('I', ip_address)) else: ip_address_text = "" self._ip_address_label.set_text(ip_address_text)