Example #1
0
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())
Example #2
0
class PrimaryToolbar(ToolbarBase):
    __gtype_name__ = 'PrimaryToolbar'

    __gsignals__ = {
        'add-link': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'set-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'reset-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-library': (GObject.SignalFlags.RUN_FIRST, None, ([])),
    }

    def __init__(self, tabbed_view, act):
        ToolbarBase.__init__(self)

        self._url_toolbar = UrlToolbar()

        self._activity = act

        self._tabbed_view = self._canvas = tabbed_view

        self._loading = False

        toolbar = self.toolbar
        activity_button = ActivityToolbarButton(self._activity)
        toolbar.insert(activity_button, 0)

        separator = Gtk.SeparatorToolItem()

        save_as_pdf = ToolButton('save-as-pdf')
        save_as_pdf.set_tooltip(_('Save page as pdf'))
        save_as_pdf.connect('clicked', self.save_as_pdf)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(save_as_pdf, -1)
        separator.show()
        save_as_pdf.show()

        self._go_home = ToolButton('go-home')
        self._go_home.set_tooltip(_('Home page'))
        self._go_home.connect('clicked', self._go_home_cb)
        # add a menu to save the home page
        menu_box = PaletteMenuBox()
        self._go_home.props.palette.set_content(menu_box)
        menu_item = PaletteMenuItem()
        menu_item.set_label(_('Select as initial page'))
        menu_item.connect('activate', self._set_home_cb)
        menu_box.append_item(menu_item)

        self._reset_home_menu = PaletteMenuItem()
        self._reset_home_menu.set_label(_('Reset initial page'))
        self._reset_home_menu.connect('activate', self._reset_home_cb)
        menu_box.append_item(self._reset_home_menu)

        if os.path.isfile(LIBRARY_PATH):
            library_menu = PaletteMenuItem()
            library_menu.set_label(_('Library'))
            library_menu.connect('activate', self._go_library_cb)
            menu_box.append_item(library_menu)

        menu_box.show_all()

        # verify if the home page is configured
        client = GConf.Client.get_default()
        self._reset_home_menu.set_visible(
            client.get_string(HOME_PAGE_GCONF_KEY) is not None)

        toolbar.insert(self._go_home, -1)
        self._go_home.show()

        self.entry = WebEntry()
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')
        self.entry.connect('icon-press', self._stop_and_reload_cb)
        self.entry.connect('activate', self._entry_activate_cb)
        self.entry.connect('focus-in-event', self.__focus_in_event_cb)
        self.entry.connect('focus-out-event', self.__focus_out_event_cb)
        self.entry.connect('key-press-event', self.__key_press_event_cb)
        self.entry.connect('changed', self.__changed_cb)

        self._entry_item = Gtk.ToolItem()
        self._entry_item.set_expand(True)
        self._entry_item.add(self.entry)
        self.entry.show()

        toolbar.insert(self._entry_item, -1)

        self._entry_item.show()

        self._back = ToolButton('go-previous-paired')
        self._back.set_tooltip(_('Back'))
        self._back.props.sensitive = False
        self._back.connect('clicked', self._go_back_cb)
        toolbar.insert(self._back, -1)
        self._back.show()

        palette = self._back.get_palette()
        self._back_box_menu = Gtk.VBox()
        self._back_box_menu.show()
        palette.set_content(self._back_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._forward = ToolButton('go-next-paired')
        self._forward.set_tooltip(_('Forward'))
        self._forward.props.sensitive = False
        self._forward.connect('clicked', self._go_forward_cb)
        toolbar.insert(self._forward, -1)
        self._forward.show()

        palette = self._forward.get_palette()
        self._forward_box_menu = Gtk.VBox()
        self._forward_box_menu.show()
        palette.set_content(self._forward_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        # Downloads ProgressIcon
        self._download_icon = ProgressToolButton('emblem-downloads',
                                                 style.STANDARD_ICON_SIZE,
                                                 'vertical')
        self._download_icon.set_tooltip(_('Downloads'))
        self._download_icon.props.sensitive = False
        down_id = GObject.timeout_add(500, self.__download_running_cb)
        toolbar.insert(self._download_icon, -1)
        self._download_icon.show()

        self._link_add = ToolButton('emblem-favorite')
        self._link_add.set_tooltip(_('Bookmark'))
        self._link_add.connect('clicked', self._link_add_clicked_cb)
        toolbar.insert(self._link_add, -1)
        self._link_add.show()

        self._toolbar_separator = Gtk.SeparatorToolItem()
        self._toolbar_separator.props.draw = False
        self._toolbar_separator.set_expand(True)

        # Adds an options-toolbar button to the main-toolbar
        self._options_toolbar = OptionsToolbar(self._activity)
        self._options_toolbar_button = ToolbarButton(
            page=self._options_toolbar, icon_name='options')
        toolbar.insert(self._options_toolbar_button, -1)

        stop_button = StopButton(self._activity)
        toolbar.insert(stop_button, -1)

        self._progress_listener = None
        self._browser = None

        self._loading_changed_hid = None
        self._progress_changed_hid = None
        self._session_history_changed_hid = None
        self._uri_changed_hid = None
        self._security_status_changed_hid = None

        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

        tabbed_view.connect_after('switch-page', self.__switch_page_cb)
        tabbed_view.connect_after('page-added', self.__page_added_cb)

        Gdk.Screen.get_default().connect('size-changed',
                                         self.__screen_size_changed_cb)

        self._configure_toolbar()

    def __download_running_cb(self):
        '''
        Updates the downloadIcon tooltip message and progress value.
        '''
        progress = downloadmanager.overall_downloads_progress()
        self._download_icon.update(progress)
        if progress > 0.0:
            self._download_icon.set_tooltip(
                _("Downloading.. {}%".format(int(progress * 100))))
        else:
            self._download_icon.set_tooltip(_("No active downloads"))
        return True

    def __key_press_event_cb(self, entry, event):
        self._tabbed_view.current_browser.loading_uri = entry.props.text

    def __switch_page_cb(self, tabbed_view, page, page_num):
        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

    def __page_added_cb(self, notebook, child, pagenum):
        self.entry._search_popdown()

    def _configure_toolbar(self, screen=None):
        # Adapt the toolbars for portrait or landscape mode.

        if screen is None:
            screen = Gdk.Screen.get_default()

        if screen.get_width() < screen.get_height():
            if self._entry_item in self._url_toolbar.toolbar.get_children():
                return

            self.toolbar.remove(self._entry_item)
            self._url_toolbar.toolbar.insert(self._entry_item, -1)

            separator_pos = len(self.toolbar.get_children()) - 1
            self.toolbar.insert(self._toolbar_separator, separator_pos)
            self._toolbar_separator.show()

            self.pack_end(self._url_toolbar, True, True, 0)
            self._url_toolbar.show()

        else:
            if self._entry_item in self.toolbar.get_children():
                return

            self.toolbar.remove(self._toolbar_separator)

            position = len(self.toolbar.get_children()) - 4
            self._url_toolbar.toolbar.remove(self._entry_item)
            self.toolbar.insert(self._entry_item, position)

            self._toolbar_separator.hide()
            self.remove(self._url_toolbar)

    def __screen_size_changed_cb(self, screen):
        self._configure_toolbar(screen)

    def _connect_to_browser(self, browser):
        if self._browser is not None:
            self._browser.disconnect(self._uri_changed_hid)
            self._browser.disconnect(self._progress_changed_hid)
            self._browser.disconnect(self._loading_changed_hid)
            self._browser.disconnect(self._security_status_changed_hid)

        self._browser = browser
        if not isinstance(self._browser, DummyBrowser):
            address = self._browser.props.uri or self._browser.loading_uri
        else:
            address = self._browser.props.uri
        self._set_address(address)
        self._set_progress(self._browser.props.progress)
        self._set_status(self._browser.props.load_status)
        self._set_security_status(self._browser.security_status)

        is_webkit_browser = isinstance(self._browser, Browser)
        self.entry.props.editable = is_webkit_browser

        self._uri_changed_hid = self._browser.connect('notify::uri',
                                                      self.__uri_changed_cb)
        self._progress_changed_hid = self._browser.connect(
            'notify::progress', self.__progress_changed_cb)
        self._loading_changed_hid = self._browser.connect(
            'notify::load-status', self.__loading_changed_cb)
        self._security_status_changed_hid = self._browser.connect(
            'security-status-changed', self.__security_status_changed_cb)

        self._update_navigation_buttons()

    def __loading_changed_cb(self, widget, param):
        self._set_status(widget.get_load_status())

    def __security_status_changed_cb(self, widget):
        self._set_security_status(widget.security_status)

    def __progress_changed_cb(self, widget, param):
        self._set_progress(widget.get_progress())

    def _set_status(self, status):
        self._set_loading(status < WebKit.LoadStatus.FINISHED)

    def _set_security_status(self, security_status):
        # Display security status as a lock icon in the left side of
        # the URL entry.
        if security_status is None:
            self.entry.set_icon_from_pixbuf(iconentry.ICON_ENTRY_PRIMARY, None)
        elif security_status == Browser.SECURITY_STATUS_SECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                          'channel-secure-symbolic')
        elif security_status == Browser.SECURITY_STATUS_INSECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                          'channel-insecure-symbolic')

    def _set_progress(self, progress):
        if progress == 1.0:
            self.entry.set_progress_fraction(0.0)
        else:
            self.entry.set_progress_fraction(progress)

    def _set_address(self, uri):
        if uri is None:
            self.entry.props.address = ''
        else:
            self.entry.props.address = uri

    def __changed_cb(self, iconentry):
        # The WebEntry can be changed when we click on a link, then we
        # have to show the clear icon only if is the user who has
        # changed the entry
        if self.entry.has_focus():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_in_event_cb(self, entry, event):
        if not self._tabbed_view.is_current_page_pdf():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_out_event_cb(self, entry, event):
        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._show_reload_icon()

    def _show_no_icon(self):
        self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY)

    def _show_stop_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')

    def _show_reload_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-refresh')

    def _show_clear_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-cancel')

    def _update_navigation_buttons(self):
        can_go_back = self._browser.can_go_back()
        self._back.props.sensitive = can_go_back

        can_go_forward = self._browser.can_go_forward()
        self._forward.props.sensitive = can_go_forward

        is_webkit_browser = isinstance(self._browser, Browser)
        self._link_add.props.sensitive = is_webkit_browser
        self._go_home.props.sensitive = is_webkit_browser
        if is_webkit_browser:
            self._reload_session_history()

    def _entry_activate_cb(self, entry):
        url = entry.props.text
        effective_url = self._tabbed_view.normalize_or_autosearch_url(url)
        self._browser.load_uri(effective_url)
        self._browser.loading_uri = effective_url
        self.entry.props.address = effective_url
        self._browser.grab_focus()

    def _go_home_cb(self, button):
        self.emit('go-home')

    def _go_library_cb(self, button):
        self.emit('go-library')

    def _set_home_cb(self, button):
        self._reset_home_menu.set_visible(True)
        self.emit('set-home')

    def _reset_home_cb(self, button):
        self._reset_home_menu.set_visible(False)
        self.emit('reset-home')

    def _go_back_cb(self, button):
        self._browser.go_back()

    def _go_forward_cb(self, button):
        self._browser.go_forward()

    def __uri_changed_cb(self, widget, param):
        self._set_address(widget.get_uri())
        self._update_navigation_buttons()
        filepicker.cleanup_temp_files()

    def _stop_and_reload_cb(self, entry, icon_pos, button):
        if entry.has_focus() and \
                not self._tabbed_view.is_current_page_pdf():
            entry.set_text('')
        else:
            if self._loading:
                self._browser.stop_loading()
            else:
                self._browser.reload()

    def _set_loading(self, loading):
        self._loading = loading

        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self.set_sensitive(True)
                self._show_reload_icon()
            else:
                self.set_sensitive(False)
                self._show_no_icon()

    def _reload_session_history(self):
        back_forward_list = self._browser.get_back_forward_list()
        item_index = 0  # The index of the history item

        # Clear menus in palettes:
        for box_menu in (self._back_box_menu, self._forward_box_menu):
            for menu_item in box_menu.get_children():
                box_menu.remove(menu_item)

        def create_menu_item(history_item, item_index):
            """Create a MenuItem for the back or forward palettes."""
            title = history_item.get_title()
            if not isinstance(title, unicode):
                title = unicode(title, 'utf-8')
            # This is a fix until the Sugar MenuItem is fixed:
            menu_item = PaletteMenuItem(text_label=title)
            menu_item.connect('activate', self._history_item_activated_cb,
                              item_index)
            return menu_item

        back_list = back_forward_list.get_back_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        back_list.reverse()
        for item in back_list:
            menu_item = create_menu_item(item, item_index)
            self._back_box_menu.pack_end(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

        # Increment the item index to count the current page:
        item_index += 1

        forward_list = back_forward_list.get_forward_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        forward_list.reverse()
        for item in forward_list:
            menu_item = create_menu_item(item, item_index)
            self._forward_box_menu.pack_start(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

    def _history_item_activated_cb(self, menu_item, index):
        self._back.get_palette().popdown(immediate=True)
        self._forward.get_palette().popdown(immediate=True)
        self._browser.set_history_index(index)

    def _link_add_clicked_cb(self, button):
        self.emit('add-link')

    def save_as_pdf(self, widget):
        tmp_dir = os.path.join(self._activity.get_activity_root(), 'tmp')
        fd, file_path = tempfile.mkstemp(dir=tmp_dir)
        os.close(fd)

        page = self._canvas.get_current_page()
        webview = self._canvas.get_children()[page].get_children()[0]

        operation = Gtk.PrintOperation.new()
        operation.set_export_filename(file_path)

        webview.get_main_frame().print_full(operation,
                                            Gtk.PrintOperationAction.EXPORT)

        client = GConf.Client.get_default()
        jobject = datastore.create()
        color = client.get_string('/desktop/sugar/user/color')
        try:
            jobject.metadata['title'] = _('Browse activity as PDF')
            jobject.metadata['icon-color'] = color
            jobject.metadata['mime_type'] = 'application/pdf'
            jobject.file_path = file_path
            datastore.write(jobject)
        finally:
            self.__pdf_alert(jobject.object_id)
            jobject.destroy()
            del jobject

    def __pdf_alert(self, object_id):
        alert = Alert()
        alert.props.title = _('Page saved')
        alert.props.msg = _('The page has been saved as PDF to journal')

        alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'),
                         Icon(icon_name='zoom-activity'))
        alert.add_button(Gtk.ResponseType.OK, _('Ok'),
                         Icon(icon_name='dialog-ok'))

        # Remove other alerts
        for alert in self._activity._alerts:
            self._activity.remove_alert(alert)

        self._activity.add_alert(alert)
        alert.connect('response', self.__pdf_response_alert, object_id)
        alert.show_all()

    def __pdf_response_alert(self, alert, response_id, object_id):

        if response_id is Gtk.ResponseType.APPLY:
            activity.show_object_in_journal(object_id)

        self._activity.remove_alert(alert)
Example #3
0
class PrimaryToolbar(ToolbarBase):
    __gtype_name__ = "PrimaryToolbar"

    __gsignals__ = {
        "add-link": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "go-home": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "set-home": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "reset-home": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "go-library": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "go-to-JSshell": (GObject.SignalFlags.RUN_FIRST, None, ([])),
        "get-shell-input": (GObject.SignalFlags.RUN_FIRST, None, ([])),
    }

    def __init__(self, tabbed_view, act):
        ToolbarBase.__init__(self)

        self._url_toolbar = UrlToolbar()

        self._activity = act

        self._tabbed_view = self._canvas = tabbed_view

        self._loading = False

        toolbar = self.toolbar
        activity_button = ActivityToolbarButton(self._activity)
        toolbar.insert(activity_button, 0)

        separator = Gtk.SeparatorToolItem()

        save_as_pdf = ToolButton("save-as-pdf")
        save_as_pdf.set_tooltip(_("Save page as pdf"))
        save_as_pdf.connect("clicked", self.save_as_pdf)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(save_as_pdf, -1)
        separator.show()
        save_as_pdf.show()

        self._go_home = ToolButton("go-home")
        self._go_home.set_tooltip(_("Home page"))
        self._go_home.connect("clicked", self._go_home_cb)
        # add a menu to save the home page
        menu_box = PaletteMenuBox()
        self._go_home.props.palette.set_content(menu_box)
        menu_item = PaletteMenuItem()
        menu_item.set_label(_("Select as initial page"))
        menu_item.connect("activate", self._set_home_cb)
        menu_box.append_item(menu_item)

        self._reset_home_menu = PaletteMenuItem()
        self._reset_home_menu.set_label(_("Reset initial page"))
        self._reset_home_menu.connect("activate", self._reset_home_cb)
        menu_box.append_item(self._reset_home_menu)

        if os.path.isfile(LIBRARY_PATH):
            library_menu = PaletteMenuItem()
            library_menu.set_label(_("Library"))
            library_menu.connect("activate", self._go_library_cb)
            menu_box.append_item(library_menu)

        menu_box.show_all()

        # verify if the home page is configured
        client = GConf.Client.get_default()
        self._reset_home_menu.set_visible(client.get_string(HOME_PAGE_GCONF_KEY) is not None)

        toolbar.insert(self._go_home, -1)
        self._go_home.show()

        self.entry = WebEntry()
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, "entry-stop")
        self.entry.connect("icon-press", self._stop_and_reload_cb)
        self.entry.connect("activate", self._entry_activate_cb)
        self.entry.connect("focus-in-event", self.__focus_in_event_cb)
        self.entry.connect("focus-out-event", self.__focus_out_event_cb)
        self.entry.connect("key-press-event", self.__key_press_event_cb)
        self.entry.connect("changed", self.__changed_cb)

        self._entry_item = Gtk.ToolItem()
        self._entry_item.set_expand(True)
        self._entry_item.add(self.entry)
        self.entry.show()

        toolbar.insert(self._entry_item, -1)

        self._entry_item.show()

        self._back = ToolButton("go-previous-paired")
        self._back.set_tooltip(_("Back"))
        self._back.props.sensitive = False
        self._back.connect("clicked", self._go_back_cb)
        toolbar.insert(self._back, -1)
        self._back.show()

        palette = self._back.get_palette()
        self._back_box_menu = Gtk.VBox()
        self._back_box_menu.show()
        palette.set_content(self._back_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._forward = ToolButton("go-next-paired")
        self._forward.set_tooltip(_("Forward"))
        self._forward.props.sensitive = False
        self._forward.connect("clicked", self._go_forward_cb)
        toolbar.insert(self._forward, -1)
        self._forward.show()

        palette = self._forward.get_palette()
        self._forward_box_menu = Gtk.VBox()
        self._forward_box_menu.show()
        palette.set_content(self._forward_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._link_add = ToolButton("emblem-favorite")
        self._link_add.set_tooltip(_("Bookmark"))
        self._link_add.connect("clicked", self._link_add_clicked_cb)
        toolbar.insert(self._link_add, -1)
        self._link_add.show()

        self._toolbar_separator = Gtk.SeparatorToolItem()
        self._toolbar_separator.props.draw = False
        self._toolbar_separator.set_expand(True)

        self._go_to_JSshell = ToolButton("go-to-JSshell")
        self._go_to_JSshell.set_tooltip(_("Go to Interactive Javascript Shell"))
        self._go_to_JSshell.connect("clicked", self._go_to_JSshell_cb)
        # adding a button for the Interactive Javascript shell
        toolbar.insert(self._go_to_JSshell, -1)
        self._go_to_JSshell.show()

        self._get_shell_input = ToolButton("get-shell-input")
        self._get_shell_input.set_tooltip(_("Get Interactive Javascript Shell Input"))
        self._get_shell_input.connect("clicked", self._get_shell_input_cb)
        # adding a button for the Interactive Javascript shell
        toolbar.insert(self._get_shell_input, -1)
        self._get_shell_input.show()

        stop_button = StopButton(self._activity)
        toolbar.insert(stop_button, -1)

        self._progress_listener = None
        self._browser = None

        self._loading_changed_hid = None
        self._progress_changed_hid = None
        self._session_history_changed_hid = None
        self._uri_changed_hid = None
        self._security_status_changed_hid = None

        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

        tabbed_view.connect_after("switch-page", self.__switch_page_cb)
        tabbed_view.connect_after("page-added", self.__page_added_cb)

        Gdk.Screen.get_default().connect("size-changed", self.__screen_size_changed_cb)

        self._configure_toolbar()

    def __key_press_event_cb(self, entry, event):
        self._tabbed_view.current_browser.loading_uri = entry.props.text

    def __switch_page_cb(self, tabbed_view, page, page_num):
        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

    def __page_added_cb(self, notebook, child, pagenum):
        self.entry._search_popdown()

    def _configure_toolbar(self, screen=None):
        # Adapt the toolbars for portrait or landscape mode.

        if screen is None:
            screen = Gdk.Screen.get_default()

        if screen.get_width() < screen.get_height():
            if self._entry_item in self._url_toolbar.toolbar.get_children():
                return

            self.toolbar.remove(self._entry_item)
            self._url_toolbar.toolbar.insert(self._entry_item, -1)

            separator_pos = len(self.toolbar.get_children()) - 1
            self.toolbar.insert(self._toolbar_separator, separator_pos)
            self._toolbar_separator.show()

            self.pack_end(self._url_toolbar, True, True, 0)
            self._url_toolbar.show()

        else:
            if self._entry_item in self.toolbar.get_children():
                return

            self.toolbar.remove(self._toolbar_separator)

            position = len(self.toolbar.get_children()) - 4
            self._url_toolbar.toolbar.remove(self._entry_item)
            self.toolbar.insert(self._entry_item, position)

            self._toolbar_separator.hide()
            self.remove(self._url_toolbar)

    def __screen_size_changed_cb(self, screen):
        self._configure_toolbar(screen)

    def _connect_to_browser(self, browser):
        if self._browser is not None:
            self._browser.disconnect(self._uri_changed_hid)
            self._browser.disconnect(self._progress_changed_hid)
            self._browser.disconnect(self._loading_changed_hid)
            self._browser.disconnect(self._security_status_changed_hid)

        self._browser = browser
        if not isinstance(self._browser, DummyBrowser):
            address = self._browser.props.uri or self._browser.loading_uri
        else:
            address = self._browser.props.uri
        self._set_address(address)
        self._set_progress(self._browser.props.progress)
        self._set_status(self._browser.props.load_status)
        self._set_security_status(self._browser.security_status)

        is_webkit_browser = isinstance(self._browser, Browser)
        self.entry.props.editable = is_webkit_browser

        self._uri_changed_hid = self._browser.connect("notify::uri", self.__uri_changed_cb)
        self._progress_changed_hid = self._browser.connect("notify::progress", self.__progress_changed_cb)
        self._loading_changed_hid = self._browser.connect("notify::load-status", self.__loading_changed_cb)
        self._security_status_changed_hid = self._browser.connect(
            "security-status-changed", self.__security_status_changed_cb
        )

        self._update_navigation_buttons()

    def __loading_changed_cb(self, widget, param):
        self._set_status(widget.get_load_status())

    def __security_status_changed_cb(self, widget):
        self._set_security_status(widget.security_status)

    def __progress_changed_cb(self, widget, param):
        self._set_progress(widget.get_progress())

    def _set_status(self, status):
        self._set_loading(status < WebKit.LoadStatus.FINISHED)

    def _set_security_status(self, security_status):
        # Display security status as a lock icon in the left side of
        # the URL entry.
        if security_status is None:
            self.entry.set_icon_from_pixbuf(iconentry.ICON_ENTRY_PRIMARY, None)
        elif security_status == Browser.SECURITY_STATUS_SECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, "channel-secure-symbolic")
        elif security_status == Browser.SECURITY_STATUS_INSECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, "channel-insecure-symbolic")

    def _set_progress(self, progress):
        if progress == 1.0:
            self.entry.set_progress_fraction(0.0)
        else:
            self.entry.set_progress_fraction(progress)

    def _set_address(self, uri):
        if uri is None:
            self.entry.props.address = ""
        else:
            self.entry.props.address = uri

    def __changed_cb(self, iconentry):
        # The WebEntry can be changed when we click on a link, then we
        # have to show the clear icon only if is the user who has
        # changed the entry
        if self.entry.has_focus():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_in_event_cb(self, entry, event):
        if not self._tabbed_view.is_current_page_pdf():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_out_event_cb(self, entry, event):
        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._show_reload_icon()

    def _show_no_icon(self):
        self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY)

    def _show_stop_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, "entry-stop")

    def _show_reload_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, "entry-refresh")

    def _show_clear_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, "entry-cancel")

    def _update_navigation_buttons(self):
        can_go_back = self._browser.can_go_back()
        self._back.props.sensitive = can_go_back

        can_go_forward = self._browser.can_go_forward()
        self._forward.props.sensitive = can_go_forward

        is_webkit_browser = isinstance(self._browser, Browser)
        self._link_add.props.sensitive = is_webkit_browser
        self._go_home.props.sensitive = is_webkit_browser
        if is_webkit_browser:
            self._reload_session_history()

    def _entry_activate_cb(self, entry):
        url = entry.props.text
        effective_url = self._tabbed_view.normalize_or_autosearch_url(url)
        self._browser.load_uri(effective_url)
        self._browser.loading_uri = effective_url
        self.entry.props.address = effective_url
        self._browser.grab_focus()

    def _go_home_cb(self, button):
        self.emit("go-home")

    def _go_library_cb(self, button):
        self.emit("go-library")

    def _set_home_cb(self, button):
        self._reset_home_menu.set_visible(True)
        self.emit("set-home")

    def _reset_home_cb(self, button):
        self._reset_home_menu.set_visible(False)
        self.emit("reset-home")

    def _go_to_JSshell_cb(self, button):
        self.emit("go-to-JSshell")

    def _get_shell_input_cb(self, button):
        self.emit("get-shell-input")

    def _go_back_cb(self, button):
        self._browser.go_back()

    def _go_forward_cb(self, button):
        self._browser.go_forward()

    def __uri_changed_cb(self, widget, param):
        self._set_address(widget.get_uri())
        self._update_navigation_buttons()
        filepicker.cleanup_temp_files()

    def _stop_and_reload_cb(self, entry, icon_pos, button):
        if entry.has_focus() and not self._tabbed_view.is_current_page_pdf():
            entry.set_text("")
        else:
            if self._loading:
                self._browser.stop_loading()
            else:
                self._browser.reload()

    def _set_loading(self, loading):
        self._loading = loading

        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self.set_sensitive(True)
                self._show_reload_icon()
            else:
                self.set_sensitive(False)
                self._show_no_icon()

    def _reload_session_history(self):
        back_forward_list = self._browser.get_back_forward_list()
        item_index = 0  # The index of the history item

        # Clear menus in palettes:
        for box_menu in (self._back_box_menu, self._forward_box_menu):
            for menu_item in box_menu.get_children():
                box_menu.remove(menu_item)

        def create_menu_item(history_item, item_index):
            """Create a MenuItem for the back or forward palettes."""
            title = history_item.get_title()
            if not isinstance(title, unicode):
                title = unicode(title, "utf-8")
            # This is a fix until the Sugar MenuItem is fixed:
            menu_item = PaletteMenuItem(text_label=title)
            menu_item.connect("activate", self._history_item_activated_cb, item_index)
            return menu_item

        back_list = back_forward_list.get_back_list_with_limit(_MAX_HISTORY_ENTRIES)
        back_list.reverse()
        for item in back_list:
            menu_item = create_menu_item(item, item_index)
            self._back_box_menu.pack_end(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

        # Increment the item index to count the current page:
        item_index += 1

        forward_list = back_forward_list.get_forward_list_with_limit(_MAX_HISTORY_ENTRIES)
        forward_list.reverse()
        for item in forward_list:
            menu_item = create_menu_item(item, item_index)
            self._forward_box_menu.pack_start(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

    def _history_item_activated_cb(self, menu_item, index):
        self._back.get_palette().popdown(immediate=True)
        self._forward.get_palette().popdown(immediate=True)
        self._browser.set_history_index(index)

    def _link_add_clicked_cb(self, button):
        self.emit("add-link")

    def save_as_pdf(self, widget):
        tmp_dir = os.path.join(self._activity.get_activity_root(), "tmp")
        fd, file_path = tempfile.mkstemp(dir=tmp_dir)
        os.close(fd)

        page = self._canvas.get_current_page()
        webview = self._canvas.get_children()[page].get_children()[0]

        operation = Gtk.PrintOperation.new()
        operation.set_export_filename(file_path)

        webview.get_main_frame().print_full(operation, Gtk.PrintOperationAction.EXPORT)

        client = GConf.Client.get_default()
        jobject = datastore.create()
        color = client.get_string("/desktop/sugar/user/color")
        try:
            jobject.metadata["title"] = _("Browse activity as PDF")
            jobject.metadata["icon-color"] = color
            jobject.metadata["mime_type"] = "application/pdf"
            jobject.file_path = file_path
            datastore.write(jobject)
        finally:
            self.__pdf_alert(jobject.object_id)
            jobject.destroy()
            del jobject

    def __pdf_alert(self, object_id):
        alert = Alert()
        alert.props.title = _("Page saved")
        alert.props.msg = _("The page has been saved as PDF to journal")

        alert.add_button(Gtk.ResponseType.APPLY, _("Show in Journal"), Icon(icon_name="zoom-activity"))
        alert.add_button(Gtk.ResponseType.OK, _("Ok"), Icon(icon_name="dialog-ok"))

        # Remove other alerts
        for alert in self._activity._alerts:
            self._activity.remove_alert(alert)

        self._activity.add_alert(alert)
        alert.connect("response", self.__pdf_response_alert, object_id)
        alert.show_all()

    def __pdf_response_alert(self, alert, response_id, object_id):

        if response_id is Gtk.ResponseType.APPLY:
            activity.show_object_in_journal(object_id)

        self._activity.remove_alert(alert)
Example #4
0
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)

    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 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)

    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)
        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 PrimaryToolbar(ToolbarBase):
    __gtype_name__ = 'PrimaryToolbar'

    __gsignals__ = {
        'add-link': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'remove-link': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'set-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'reset-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-library': (GObject.SignalFlags.RUN_FIRST, None, ([])),
    }

    def __init__(self, tabbed_view, act):
        ToolbarBase.__init__(self)

        self._url_toolbar = UrlToolbar()

        self._activity = act
        self.model = act.model
        self.model.link_removed_signal.connect(self.__link_removed_cb)

        self._tabbed_view = self._canvas = tabbed_view

        self._loading = False
        self._download_running_hid = None

        toolbar = self.toolbar
        activity_button = ActivityToolbarButton(self._activity)
        toolbar.insert(activity_button, 0)

        separator = Gtk.SeparatorToolItem()
        '''
        Disabled since the python gi bindings don't expose the critical
        WebKit2.PrintOperation.print function

        save_as_pdf = ToolButton('save-as-pdf')
        save_as_pdf.set_tooltip(_('Save page as pdf'))
        save_as_pdf.connect('clicked', self.save_as_pdf)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(save_as_pdf, -1)
        separator.show()
        save_as_pdf.show()
        '''
        inspect_view = ToolButton('emblem-view-source')
        inspect_view.set_tooltip(_('Show Web Inspector'))
        inspect_view.connect('clicked', self.inspect_view)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(inspect_view, -1)
        separator.show()
        inspect_view.show()

        self._go_home = ToolButton('go-home')
        self._go_home.set_tooltip(_('Home page'))
        self._go_home.connect('clicked', self._go_home_cb)
        # add a menu to save the home page
        menu_box = PaletteMenuBox()
        self._go_home.props.palette.set_content(menu_box)
        menu_item = PaletteMenuItem()
        menu_item.set_label(_('Select as initial page'))
        menu_item.connect('activate', self._set_home_cb)
        menu_box.append_item(menu_item)

        self._reset_home_menu = PaletteMenuItem()
        self._reset_home_menu.set_label(_('Reset initial page'))
        self._reset_home_menu.connect('activate', self._reset_home_cb)
        menu_box.append_item(self._reset_home_menu)

        if os.path.isfile(LIBRARY_PATH):
            library_menu = PaletteMenuItem()
            library_menu.set_label(_('Library'))
            library_menu.connect('activate', self._go_library_cb)
            menu_box.append_item(library_menu)

        menu_box.show_all()

        # verify if the home page is configured
        client = GConf.Client.get_default()
        self._reset_home_menu.set_visible(
            client.get_string(HOME_PAGE_GCONF_KEY) is not None)

        toolbar.insert(self._go_home, -1)
        self._go_home.show()

        self.entry = WebEntry()
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')
        self.entry.connect('icon-press', self._stop_and_reload_cb)
        self.entry.connect('activate', self._entry_activate_cb)
        self.entry.connect('focus-in-event', self.__focus_in_event_cb)
        self.entry.connect('focus-out-event', self.__focus_out_event_cb)
        self.entry.connect('key-press-event', self.__key_press_event_cb)
        self.entry.connect('changed', self.__changed_cb)

        # In an event box so that it can render the background
        entry_box = Gtk.EventBox()
        entry_box.add(self.entry)
        entry_box.show()

        self._entry_item = Gtk.ToolItem()
        self._entry_item.set_expand(True)
        self._entry_item.add(entry_box)
        self.entry.show()

        toolbar.insert(self._entry_item, -1)

        self._entry_item.show()

        self._back = ToolButton('go-previous-paired', accelerator='<ctrl>Left')
        self._back.set_tooltip(_('Back'))
        self._back.props.sensitive = False
        self._back.connect('clicked', self._go_back_cb)
        toolbar.insert(self._back, -1)
        self._back.show()

        palette = self._back.get_palette()
        self._back_box_menu = Gtk.VBox()
        self._back_box_menu.show()
        palette.set_content(self._back_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._forward = ToolButton('go-next-paired', accelerator='<ctrl>Right')
        self._forward.set_tooltip(_('Forward'))
        self._forward.props.sensitive = False
        self._forward.connect('clicked', self._go_forward_cb)
        toolbar.insert(self._forward, -1)
        self._forward.show()

        palette = self._forward.get_palette()
        self._forward_box_menu = Gtk.VBox()
        self._forward_box_menu.show()
        palette.set_content(self._forward_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._download_icon = ProgressToolButton(
            icon_name='emblem-downloads', tooltip=_('No Downloads Running'))
        toolbar.insert(self._download_icon, -1)
        self._download_icon.show()
        downloadmanager.connect_donwload_started(self.__download_started_cb)

        self._link_add = ToggleToolButton('emblem-favorite')
        self._link_add.set_accelerator('<ctrl>d')
        self._link_add.set_tooltip(_('Bookmark'))
        self._link_add_toggled_hid = \
            self._link_add.connect('toggled', self.__link_add_toggled_cb)
        toolbar.insert(self._link_add, -1)
        self._link_add.show()

        self._toolbar_separator = Gtk.SeparatorToolItem()
        self._toolbar_separator.props.draw = False
        self._toolbar_separator.set_expand(True)

        self._stop_button = StopButton(self._activity)
        toolbar.insert(self._stop_button, -1)

        self._progress_listener = None
        self._browser = None

        self._loading_changed_hid = None
        self._progress_changed_hid = None
        self._session_history_changed_hid = None
        self._uri_changed_hid = None
        self._load_changed_hid = None
        self._security_status_changed_hid = None

        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

        tabbed_view.connect_after('switch-page', self.__switch_page_cb)
        tabbed_view.connect_after('page-added', self.__page_added_cb)

        Gdk.Screen.get_default().connect('size-changed',
                                         self.__screen_size_changed_cb)

        self._configure_toolbar()

    def __download_started_cb(self):
        if self._download_running_hid is None:
            self._download_running_hid = GLib.timeout_add(
                80, self.__download_running_cb)

    def __download_running_cb(self):
        print('__DLR')
        progress = downloadmanager.overall_downloads_progress()
        self._download_icon.update(progress)
        if downloadmanager.num_downloads() > 0:
            self._download_icon.props.tooltip = \
                _('{}% Downloaded').format(int(progress*100))
            self._download_icon.props.xo_color = XoColor(None)
            return True
        else:
            GLib.source_remove(self._download_running_hid)
            self._download_running_hid = None
            self._download_icon.props.tooltip = _('No Downloads Running')
            self._download_icon.props.xo_color = XoColor('insensitive')
            return False

    def __key_press_event_cb(self, entry, event):
        self._tabbed_view.current_browser.loading_uri = entry.props.text

    def __switch_page_cb(self, tabbed_view, page, page_num):
        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

    def __page_added_cb(self, notebook, child, pagenum):
        self.entry._search_popdown()

    def _configure_toolbar(self, screen=None):
        # Adapt the toolbars for portrait or landscape mode.

        if screen is None:
            screen = Gdk.Screen.get_default()

        if screen.get_width() < screen.get_height():
            if self._entry_item in self._url_toolbar.toolbar.get_children():
                return

            self.toolbar.remove(self._entry_item)
            self._url_toolbar.toolbar.insert(self._entry_item, -1)

            separator_pos = len(self.toolbar.get_children()) - 1
            self.toolbar.insert(self._toolbar_separator, separator_pos)
            self._toolbar_separator.show()

            self.pack_end(self._url_toolbar, True, True, 0)
            self._url_toolbar.show()

        else:
            if self._entry_item in self.toolbar.get_children():
                return

            self.toolbar.remove(self._toolbar_separator)

            position = len(self.toolbar.get_children()) - 4
            self._url_toolbar.toolbar.remove(self._entry_item)
            self.toolbar.insert(self._entry_item, position)

            self._toolbar_separator.hide()
            self.remove(self._url_toolbar)

    def __screen_size_changed_cb(self, screen):
        self._configure_toolbar(screen)

    def _connect_to_browser(self, browser):
        if self._browser is not None:
            self._browser.disconnect(self._uri_changed_hid)
            self._browser.disconnect(self._load_changed_hid)
            self._browser.disconnect(self._progress_changed_hid)
            self._browser.disconnect(self._security_status_changed_hid)

        self._browser = browser
        if not isinstance(self._browser, DummyBrowser):
            address = self._browser.props.uri or self._browser.loading_uri
        else:
            address = self._browser.props.uri
        self._set_address(address)
        self._set_progress(self._browser.props.estimated_load_progress)
        self._set_loading(self._browser.props.estimated_load_progress < 1.0)
        self._set_security_status(self._browser.security_status)

        is_webkit_browser = isinstance(self._browser, Browser)
        self.entry.props.editable = is_webkit_browser

        self._uri_changed_hid = self._browser.connect('notify::uri',
                                                      self.__uri_changed_cb)
        self._load_changed_hid = self._browser.connect('load-changed',
                                                       self.__load_changed_cb)
        self._progress_changed_hid = self._browser.connect(
            'notify::estimated-load-progress', self.__progress_changed_cb)
        self._security_status_changed_hid = self._browser.connect(
            'security-status-changed', self.__security_status_changed_cb)

        self._update_navigation_buttons()

    def __security_status_changed_cb(self, widget):
        self._set_security_status(widget.security_status)

    def __progress_changed_cb(self, widget, param):
        self._set_progress(widget.props.estimated_load_progress)
        self._set_loading(widget.props.estimated_load_progress < 1.0)

    def _set_security_status(self, security_status):
        # Display security status as a lock icon in the left side of
        # the URL entry.
        if security_status is None:
            self.entry.set_icon_from_pixbuf(iconentry.ICON_ENTRY_PRIMARY, None)
        elif security_status == Browser.SECURITY_STATUS_SECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                          'channel-secure-symbolic')
        elif security_status == Browser.SECURITY_STATUS_INSECURE:
            self.entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                          'channel-insecure-symbolic')

    def _set_progress(self, progress):
        if progress == 1.0:
            self.entry.set_progress_fraction(0.0)
        else:
            self.entry.set_progress_fraction(progress)

    def _set_address(self, uri):
        if uri is None:
            self.entry.props.address = ''
        else:
            self.entry.props.address = uri

    def __changed_cb(self, iconentry):
        # The WebEntry can be changed when we click on a link, then we
        # have to show the clear icon only if is the user who has
        # changed the entry
        if self.entry.has_focus():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_in_event_cb(self, entry, event):
        if not self._tabbed_view.is_current_page_pdf():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_out_event_cb(self, entry, event):
        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._show_reload_icon()

    def _show_no_icon(self):
        self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY)

    def _show_stop_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')

    def _show_reload_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-refresh')

    def _show_clear_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-cancel')

    def _update_navigation_buttons(self):
        can_go_back = self._browser.can_go_back()
        self._back.props.sensitive = can_go_back

        can_go_forward = self._browser.can_go_forward()
        self._forward.props.sensitive = can_go_forward

        is_webkit_browser = isinstance(self._browser, Browser)
        self._go_home.props.sensitive = is_webkit_browser
        if is_webkit_browser:
            self._reload_session_history()

        with self._link_add.handler_block(self._link_add_toggled_hid):
            uri = self._browser.get_uri()
            print(self.model.has_link(uri), uri)
            self._link_add.props.active = self.model.has_link(uri)

    def __link_removed_cb(self, model):
        self._update_navigation_buttons()

    def _entry_activate_cb(self, entry):
        url = entry.props.text
        effective_url = self._tabbed_view.normalize_or_autosearch_url(url)
        self._browser.load_uri(effective_url)
        self._browser.loading_uri = effective_url
        self.entry.props.address = effective_url
        self._browser.grab_focus()

    def _go_home_cb(self, button):
        self.emit('go-home')

    def _go_library_cb(self, button):
        self.emit('go-library')

    def _set_home_cb(self, button):
        self._reset_home_menu.set_visible(True)
        self.emit('set-home')

    def _reset_home_cb(self, button):
        self._reset_home_menu.set_visible(False)
        self.emit('reset-home')

    def _go_back_cb(self, button):
        self._browser.go_back()

    def _go_forward_cb(self, button):
        self._browser.go_forward()

    def __uri_changed_cb(self, widget, param):
        self._set_address(widget.get_uri())
        self._update_navigation_buttons()
        filepicker.cleanup_temp_files()

    def __load_changed_cb(self, widget, event):
        self._update_navigation_buttons()

    def _stop_and_reload_cb(self, entry, icon_pos, button):
        if entry.has_focus() and \
                not self._tabbed_view.is_current_page_pdf():
            entry.set_text('')
        else:
            if self._loading:
                self._browser.stop_loading()
            else:
                self._browser.reload()

    def _set_loading(self, loading):
        self._loading = loading

        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._set_sensitive(True)
                self._show_reload_icon()
            else:
                self._set_sensitive(False)
                self._show_no_icon()

    def _set_sensitive(self, value):
        for widget in self.toolbar:
            if widget not in (self._stop_button, self._link_add):
                widget.set_sensitive(value)

    def _reload_session_history(self):
        back_forward_list = self._browser.get_back_forward_list()
        item_index = 0  # The index of the history item

        # Clear menus in palettes:
        for box_menu in (self._back_box_menu, self._forward_box_menu):
            for menu_item in box_menu.get_children():
                box_menu.remove(menu_item)

        def create_menu_item(history_item):
            """Create a MenuItem for the back or forward palettes."""
            title = history_item.get_title() or _('No Title')
            if not isinstance(title, unicode):
                title = unicode(title, 'utf-8')
            # This is a fix until the Sugar MenuItem is fixed:
            menu_item = PaletteMenuItem(text_label=title)
            menu_item.connect('activate', self._history_item_activated_cb,
                              history_item)
            return menu_item

        back_list = back_forward_list.get_back_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        back_list.reverse()
        for item in back_list:
            menu_item = create_menu_item(item)
            self._back_box_menu.pack_end(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

        # Increment the item index to count the current page:
        item_index += 1

        forward_list = back_forward_list.get_forward_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        forward_list.reverse()
        for item in forward_list:
            menu_item = create_menu_item(item)
            self._forward_box_menu.pack_start(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

    def _history_item_activated_cb(self, menu_item, history_item):
        self._back.get_palette().popdown(immediate=True)
        self._forward.get_palette().popdown(immediate=True)
        # self._browser.set_history_index(index)
        self._browser.go_to_back_forward_list_item(history_item)

    def __link_add_toggled_cb(self, button):
        if button.props.active:
            self.emit('add-link')
        else:
            self.emit('remove-link')

    def inspect_view(self, button):
        page = self._canvas.get_current_page()
        webview = self._canvas.get_children()[page].props.browser

        # If get_inspector returns None, it is not a real WebView
        inspector = webview.get_inspector()
        if inspector is not None:
            # Inspector window will be blank if disabled
            web_settings = webview.get_settings()
            web_settings.props.enable_developer_extras = True

            inspector.show()
            inspector.attach()

    '''
class PrimaryToolbar(ToolbarBase):
    __gtype_name__ = 'PrimaryToolbar'

    __gsignals__ = {
       'go-home': (GObject.SignalFlags.RUN_FIRST,
                     None,
                     ([])),
        'set-home': (GObject.SignalFlags.RUN_FIRST,
                     None,
                     ([])),
        'reset-home': (GObject.SignalFlags.RUN_FIRST,
                     None,
                     ([])),
        'go-library': (GObject.SignalFlags.RUN_FIRST,
                     None,
                     ([])),
    }

    def __init__(self, tabbed_view, act):
        ToolbarBase.__init__(self)

        self._url_toolbar = UrlToolbar()

        self._activity = act

        self._tabbed_view = tabbed_view

        self._loading = False

        toolbar = self.toolbar
        activity_button = ActivityToolbarButton(self._activity)
        toolbar.insert(activity_button, 0)

        self._go_home = ToolButton('go-home')
        self._go_home.set_tooltip(_('Home page'))
        self._go_home.connect('clicked', self._go_home_cb)
        # add a menu to save the home page
        menu_box = PaletteMenuBox()
        self._go_home.props.palette.set_content(menu_box)
        menu_item = PaletteMenuItem()
        menu_item.set_label(_('Select as initial page'))
        menu_item.connect('activate', self._set_home_cb)
        menu_box.append_item(menu_item)

        self._reset_home_menu = PaletteMenuItem()
        self._reset_home_menu.set_label(_('Reset initial page'))
        self._reset_home_menu.connect('activate', self._reset_home_cb)
        menu_box.append_item(self._reset_home_menu)

        if os.path.isfile(LIBRARY_PATH):
            library_menu = PaletteMenuItem()
            library_menu.set_label(_('Library'))
            library_menu.connect('activate', self._go_library_cb)
            menu_box.append_item(library_menu)

        menu_box.show_all()

        # verify if the home page is configured
        client = GConf.Client.get_default()
        self._reset_home_menu.set_visible(
            client.get_string(HOME_PAGE_GCONF_KEY) is not None)

        toolbar.insert(self._go_home, -1)
        self._go_home.show()

        self.entry = WebEntry()
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')
        self.entry.connect('icon-press', self._stop_and_reload_cb)
        self.entry.connect('activate', self._entry_activate_cb)
        self.entry.connect('focus-in-event', self.__focus_in_event_cb)
        self.entry.connect('focus-out-event', self.__focus_out_event_cb)
        self.entry.connect('key-press-event', self.__key_press_event_cb)
        self.entry.connect('changed', self.__changed_cb)

        self._entry_item = Gtk.ToolItem()
        self._entry_item.set_expand(True)
        self._entry_item.add(self.entry)
        self.entry.show()

        toolbar.insert(self._entry_item, -1)

        self._entry_item.show()

        self._back = ToolButton('go-previous-paired')
        self._back.set_tooltip(_('Back'))
        self._back.props.sensitive = False
        self._back.connect('clicked', self._go_back_cb)
        toolbar.insert(self._back, -1)
        self._back.show()

        palette = self._back.get_palette()
        self._back_box_menu = Gtk.VBox()
        self._back_box_menu.show()
        palette.set_content(self._back_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._forward = ToolButton('go-next-paired')
        self._forward.set_tooltip(_('Forward'))
        self._forward.props.sensitive = False
        self._forward.connect('clicked', self._go_forward_cb)
        toolbar.insert(self._forward, -1)
        self._forward.show()

        palette = self._forward.get_palette()
        self._forward_box_menu = Gtk.VBox()
        self._forward_box_menu.show()
        palette.set_content(self._forward_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._toolbar_separator = Gtk.SeparatorToolItem()
        self._toolbar_separator.props.draw = False
        self._toolbar_separator.set_expand(True)

        stop_button = StopButton(self._activity)
        toolbar.insert(stop_button, -1)

        self._progress_listener = None
        self._browser = None

        self._loading_changed_hid = None
        self._progress_changed_hid = None
        self._session_history_changed_hid = None
        self._uri_changed_hid = None
        self._security_status_changed_hid = None

        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

        tabbed_view.connect_after('switch-page', self.__switch_page_cb)
        tabbed_view.connect_after('page-added', self.__page_added_cb)

        Gdk.Screen.get_default().connect('size-changed',
                                         self.__screen_size_changed_cb)

        self._configure_toolbar()

    def __key_press_event_cb(self, entry, event):
        self._tabbed_view.current_browser.loading_uri = entry.props.text

    def __switch_page_cb(self, tabbed_view, page, page_num):
        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

    def __page_added_cb(self, notebook, child, pagenum):
        self.entry._search_popdown()

    def _configure_toolbar(self, screen=None):
        # Adapt the toolbars for portrait or landscape mode.

        if screen is None:
            screen = Gdk.Screen.get_default()

        if screen.get_width() < screen.get_height():
            if self._entry_item in self._url_toolbar.toolbar.get_children():
                return

            self.toolbar.remove(self._entry_item)
            self._url_toolbar.toolbar.insert(self._entry_item, -1)

            separator_pos = len(self.toolbar.get_children()) - 1
            self.toolbar.insert(self._toolbar_separator, separator_pos)
            self._toolbar_separator.show()

            self.pack_end(self._url_toolbar, True, True, 0)
            self._url_toolbar.show()

        else:
            if self._entry_item in self.toolbar.get_children():
                return

            self.toolbar.remove(self._toolbar_separator)

            position = len(self.toolbar.get_children()) - 4
            self._url_toolbar.toolbar.remove(self._entry_item)
            self.toolbar.insert(self._entry_item, position)

            self._toolbar_separator.hide()
            self.remove(self._url_toolbar)

    def __screen_size_changed_cb(self, screen):
        self._configure_toolbar(screen)

    def _connect_to_browser(self, browser):
        if self._browser is not None:
            self._browser.disconnect(self._uri_changed_hid)
            self._browser.disconnect(self._progress_changed_hid)
            self._browser.disconnect(self._loading_changed_hid)
            self._browser.disconnect(self._security_status_changed_hid)

        self._browser = browser
        if not isinstance(self._browser, DummyBrowser):
            address = self._browser.props.uri or self._browser.loading_uri
        else:
            address = self._browser.props.uri
        self._set_address(address)
        self._set_progress(self._browser.props.progress)
        self._set_status(self._browser.props.load_status)
        self._set_security_status(self._browser.security_status)

        is_webkit_browser = isinstance(self._browser, Browser)
        self.entry.props.editable = is_webkit_browser

        self._uri_changed_hid = self._browser.connect(
                'notify::uri', self.__uri_changed_cb)
        self._progress_changed_hid = self._browser.connect(
                'notify::progress', self.__progress_changed_cb)
        self._loading_changed_hid = self._browser.connect(
                'notify::load-status', self.__loading_changed_cb)
        self._security_status_changed_hid = self._browser.connect(
                'security-status-changed', self.__security_status_changed_cb)

        self._update_navigation_buttons()

    def __loading_changed_cb(self, widget, param):
        self._set_status(widget.get_load_status())

    def __security_status_changed_cb(self, widget):
        self._set_security_status(widget.security_status)

    def __progress_changed_cb(self, widget, param):
        self._set_progress(widget.get_progress())

    def _set_status(self, status):
        self._set_loading(status < WebKit.LoadStatus.FINISHED)

    def _set_security_status(self, security_status):
        # Display security status as a lock icon in the left side of
        # the URL entry.
        if security_status is None:
            self.entry.set_icon_from_pixbuf(
                iconentry.ICON_ENTRY_PRIMARY, None)
        elif security_status == Browser.SECURITY_STATUS_SECURE:
            self.entry.set_icon_from_name(
                iconentry.ICON_ENTRY_PRIMARY, 'channel-secure-symbolic')
        elif security_status == Browser.SECURITY_STATUS_INSECURE:
            self.entry.set_icon_from_name(
                iconentry.ICON_ENTRY_PRIMARY, 'channel-insecure-symbolic')

    def _set_progress(self, progress):
        if progress == 1.0:
            self.entry.set_progress_fraction(0.0)
        else:
            self.entry.set_progress_fraction(progress)

    def _set_address(self, uri):
        if uri is None:
            self.entry.props.address = ''
        else:
            self.entry.props.address = uri

    def __changed_cb(self, iconentry):
        # The WebEntry can be changed when we click on a link, then we
        # have to show the clear icon only if is the user who has
        # changed the entry
        if self.entry.has_focus():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_in_event_cb(self, entry, event):
        if not self._tabbed_view.is_current_page_pdf():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_out_event_cb(self, entry, event):
        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._show_reload_icon()

    def _show_no_icon(self):
        self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY)

    def _show_stop_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')

    def _show_reload_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-refresh')

    def _show_clear_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-cancel')

    def _update_navigation_buttons(self):
        can_go_back = self._browser.can_go_back()
        self._back.props.sensitive = can_go_back

        can_go_forward = self._browser.can_go_forward()
        self._forward.props.sensitive = can_go_forward

        is_webkit_browser = isinstance(self._browser, Browser)
        self._go_home.props.sensitive = is_webkit_browser
        if is_webkit_browser:
            self._reload_session_history()

    def _entry_activate_cb(self, entry):
        url = entry.props.text
        effective_url = self._tabbed_view.normalize_or_autosearch_url(url)
        self._browser.load_uri(effective_url)
        self._browser.loading_uri = effective_url
        self.entry.props.address = effective_url
        self._browser.grab_focus()

    def _go_home_cb(self, button):
        self.emit('go-home')

    def _go_library_cb(self, button):
        self.emit('go-library')

    def _set_home_cb(self, button):
        self._reset_home_menu.set_visible(True)
        self.emit('set-home')

    def _reset_home_cb(self, button):
        self._reset_home_menu.set_visible(False)
        self.emit('reset-home')

    def _go_back_cb(self, button):
        self._browser.go_back()

    def _go_forward_cb(self, button):
        self._browser.go_forward()

    def __uri_changed_cb(self, widget, param):
        self._set_address(widget.get_uri())
        self._update_navigation_buttons()
        filepicker.cleanup_temp_files()

    def _stop_and_reload_cb(self, entry, icon_pos, button):
        if entry.has_focus() and \
                not self._tabbed_view.is_current_page_pdf():
            entry.set_text('')
        else:
            if self._loading:
                self._browser.stop_loading()
            else:
                self._browser.reload()

    def _set_loading(self, loading):
        self._loading = loading

        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self.set_sensitive(True)
                self._show_reload_icon()
            else:
                self.set_sensitive(False)
                self._show_no_icon()

    def _reload_session_history(self):
        back_forward_list = self._browser.get_back_forward_list()
        item_index = 0  # The index of the history item

        # Clear menus in palettes:
        for box_menu in (self._back_box_menu, self._forward_box_menu):
            for menu_item in box_menu.get_children():
                box_menu.remove(menu_item)

        def create_menu_item(history_item, item_index):
            """Create a MenuItem for the back or forward palettes."""
            title = history_item.get_title()
            if not isinstance(title, unicode):
                title = unicode(title, 'utf-8')
            # This is a fix until the Sugar MenuItem is fixed:
            menu_item = PaletteMenuItem(text_label=title)
            menu_item.connect('activate', self._history_item_activated_cb,
                              item_index)
            return menu_item

        back_list = back_forward_list.get_back_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        back_list.reverse()
        for item in back_list:
            menu_item = create_menu_item(item, item_index)
            self._back_box_menu.pack_end(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

        # Increment the item index to count the current page:
        item_index += 1

        forward_list = back_forward_list.get_forward_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        forward_list.reverse()
        for item in forward_list:
            menu_item = create_menu_item(item, item_index)
            self._forward_box_menu.pack_start(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

    def _history_item_activated_cb(self, menu_item, index):
        self._back.get_palette().popdown(immediate=True)
        self._forward.get_palette().popdown(immediate=True)
        self._browser.set_history_index(index)
Example #7
0
class PrimaryToolbar(ToolbarBase):
    __gtype_name__ = 'PrimaryToolbar'

    __gsignals__ = {
        'add-link': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'remove-link': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'set-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'reset-home': (GObject.SignalFlags.RUN_FIRST, None, ([])),
        'go-library': (GObject.SignalFlags.RUN_FIRST, None, ([])),
    }

    def __init__(self, tabbed_view, act):
        ToolbarBase.__init__(self)

        self._url_toolbar = UrlToolbar()

        self._activity = act
        self.model = act.model
        self.model.link_removed_signal.connect(self.__link_removed_cb)

        self._tabbed_view = self._canvas = tabbed_view

        self._loading = False
        self._download_running_hid = None

        toolbar = self.toolbar
        activity_button = ActivityToolbarButton(self._activity)
        toolbar.insert(activity_button, 0)

        separator = Gtk.SeparatorToolItem()

        '''
        Disabled since the python gi bindings don't expose the critical
        WebKit2.PrintOperation.print function

        save_as_pdf = ToolButton('save-as-pdf')
        save_as_pdf.set_tooltip(_('Save page as pdf'))
        save_as_pdf.connect('clicked', self.save_as_pdf)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(save_as_pdf, -1)
        separator.show()
        save_as_pdf.show()
        '''
        inspect_view = ToolButton('emblem-view-source')
        inspect_view.set_tooltip(_('Show Web Inspector'))
        inspect_view.connect('clicked', self.inspect_view)

        activity_button.props.page.insert(separator, -1)
        activity_button.props.page.insert(inspect_view, -1)
        separator.show()
        inspect_view.show()

        self._go_home = ToolButton('go-home')
        self._go_home.set_tooltip(_('Home page'))
        self._go_home.connect('clicked', self._go_home_cb)
        # add a menu to save the home page
        menu_box = PaletteMenuBox()
        self._go_home.props.palette.set_content(menu_box)
        menu_item = PaletteMenuItem()
        menu_item.set_label(_('Select as initial page'))
        menu_item.connect('activate', self._set_home_cb)
        menu_box.append_item(menu_item)

        self._reset_home_menu = PaletteMenuItem()
        self._reset_home_menu.set_label(_('Reset initial page'))
        self._reset_home_menu.connect('activate', self._reset_home_cb)
        menu_box.append_item(self._reset_home_menu)

        if os.path.isfile(LIBRARY_PATH):
            library_menu = PaletteMenuItem()
            library_menu.set_label(_('Library'))
            library_menu.connect('activate', self._go_library_cb)
            menu_box.append_item(library_menu)

        menu_box.show_all()

        # verify if the home page is configured
        client = GConf.Client.get_default()
        self._reset_home_menu.set_visible(
            client.get_string(HOME_PAGE_GCONF_KEY) is not None)

        toolbar.insert(self._go_home, -1)
        self._go_home.show()

        self.entry = WebEntry()
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')
        self.entry.connect('icon-press', self._stop_and_reload_cb)
        self.entry.connect('activate', self._entry_activate_cb)
        self.entry.connect('focus-in-event', self.__focus_in_event_cb)
        self.entry.connect('focus-out-event', self.__focus_out_event_cb)
        self.entry.connect('key-press-event', self.__key_press_event_cb)
        self.entry.connect('changed', self.__changed_cb)

        # In an event box so that it can render the background
        entry_box = Gtk.EventBox()
        entry_box.add(self.entry)
        entry_box.show()

        self._entry_item = Gtk.ToolItem()
        self._entry_item.set_expand(True)
        self._entry_item.add(entry_box)
        self.entry.show()

        toolbar.insert(self._entry_item, -1)

        self._entry_item.show()

        self._back = ToolButton('go-previous-paired',
                                accelerator='<ctrl>Left')
        self._back.set_tooltip(_('Back'))
        self._back.props.sensitive = False
        self._back.connect('clicked', self._go_back_cb)
        toolbar.insert(self._back, -1)
        self._back.show()

        palette = self._back.get_palette()
        self._back_box_menu = Gtk.VBox()
        self._back_box_menu.show()
        palette.set_content(self._back_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._forward = ToolButton('go-next-paired',
                                   accelerator='<ctrl>Right')
        self._forward.set_tooltip(_('Forward'))
        self._forward.props.sensitive = False
        self._forward.connect('clicked', self._go_forward_cb)
        toolbar.insert(self._forward, -1)
        self._forward.show()

        palette = self._forward.get_palette()
        self._forward_box_menu = Gtk.VBox()
        self._forward_box_menu.show()
        palette.set_content(self._forward_box_menu)
        # FIXME, this is a hack, should be done in the theme:
        palette._content.set_border_width(1)

        self._download_icon = ProgressToolButton(
            icon_name='emblem-downloads',
            tooltip=_('No Downloads Running'))
        toolbar.insert(self._download_icon, -1)
        self._download_icon.show()
        downloadmanager.connect_download_started(self.__download_started_cb)

        self._link_add = ToggleToolButton('emblem-favorite')
        self._link_add.set_accelerator('<ctrl>d')
        self._link_add.set_tooltip(_('Bookmark'))
        self._link_add_toggled_hid = \
            self._link_add.connect('toggled', self.__link_add_toggled_cb)
        toolbar.insert(self._link_add, -1)
        self._link_add.show()

        self._toolbar_separator = Gtk.SeparatorToolItem()
        self._toolbar_separator.props.draw = False
        self._toolbar_separator.set_expand(True)

        self._stop_button = StopButton(self._activity)
        toolbar.insert(self._stop_button, -1)

        self._progress_listener = None
        self._browser = None

        self._loading_changed_hid = None
        self._progress_changed_hid = None
        self._session_history_changed_hid = None
        self._uri_changed_hid = None
        self._load_changed_hid = None
        self._security_status_changed_hid = None

        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

        tabbed_view.connect_after('switch-page', self.__switch_page_cb)
        tabbed_view.connect_after('page-added', self.__page_added_cb)

        Gdk.Screen.get_default().connect('size-changed',
                                         self.__screen_size_changed_cb)

        self._configure_toolbar()

    def __download_started_cb(self):
        if self._download_running_hid is None:
            self._download_running_hid = GLib.timeout_add(
                80, self.__download_running_cb)

    def __download_running_cb(self):
        progress = downloadmanager.overall_downloads_progress()
        self._download_icon.update(progress)
        if downloadmanager.num_downloads() > 0:
            self._download_icon.props.tooltip = \
                _('{}% Downloaded').format(int(progress*100))
            return True
        else:
            self._download_running_hid = None
            self._download_icon.props.tooltip = _('No Downloads Running')
            return False

    def __key_press_event_cb(self, entry, event):
        self._tabbed_view.current_browser.loading_uri = entry.props.text

    def __switch_page_cb(self, tabbed_view, page, page_num):
        if tabbed_view.get_n_pages():
            self._connect_to_browser(tabbed_view.props.current_browser)

    def __page_added_cb(self, notebook, child, pagenum):
        self.entry._search_popdown()

    def _configure_toolbar(self, screen=None):
        # Adapt the toolbars for portrait or landscape mode.

        if screen is None:
            screen = Gdk.Screen.get_default()

        if screen.get_width() < screen.get_height():
            if self._entry_item in self._url_toolbar.toolbar.get_children():
                return

            self.toolbar.remove(self._entry_item)
            self._url_toolbar.toolbar.insert(self._entry_item, -1)

            separator_pos = len(self.toolbar.get_children()) - 1
            self.toolbar.insert(self._toolbar_separator, separator_pos)
            self._toolbar_separator.show()

            self.pack_end(self._url_toolbar, True, True, 0)
            self._url_toolbar.show()

        else:
            if self._entry_item in self.toolbar.get_children():
                return

            self.toolbar.remove(self._toolbar_separator)

            position = len(self.toolbar.get_children()) - 4
            self._url_toolbar.toolbar.remove(self._entry_item)
            self.toolbar.insert(self._entry_item, position)

            self._toolbar_separator.hide()
            self.remove(self._url_toolbar)

    def __screen_size_changed_cb(self, screen):
        self._configure_toolbar(screen)

    def _connect_to_browser(self, browser):
        if self._browser is not None:
            self._browser.disconnect(self._uri_changed_hid)
            self._browser.disconnect(self._load_changed_hid)
            self._browser.disconnect(self._progress_changed_hid)
            self._browser.disconnect(self._security_status_changed_hid)

        self._browser = browser
        if not isinstance(self._browser, DummyBrowser):
            address = self._browser.props.uri or self._browser.loading_uri
        else:
            address = self._browser.props.uri
        self._set_address(address)
        self._set_progress(self._browser.props.estimated_load_progress)
        self._set_loading(self._browser.props.estimated_load_progress < 1.0)
        self._set_security_status(self._browser.security_status)

        is_webkit_browser = isinstance(self._browser, Browser)
        self.entry.props.editable = is_webkit_browser

        self._uri_changed_hid = self._browser.connect(
            'notify::uri', self.__uri_changed_cb)
        self._load_changed_hid = self._browser.connect(
            'load-changed', self.__load_changed_cb)
        self._progress_changed_hid = self._browser.connect(
            'notify::estimated-load-progress', self.__progress_changed_cb)
        self._security_status_changed_hid = self._browser.connect(
            'security-status-changed', self.__security_status_changed_cb)

        self._update_navigation_buttons()

    def __security_status_changed_cb(self, widget):
        self._set_security_status(widget.security_status)

    def __progress_changed_cb(self, widget, param):
        self._set_progress(widget.props.estimated_load_progress)
        self._set_loading(widget.props.estimated_load_progress < 1.0)

    def _set_security_status(self, security_status):
        # Display security status as a lock icon in the left side of
        # the URL entry.
        if security_status is None:
            self.entry.set_icon_from_pixbuf(
                iconentry.ICON_ENTRY_PRIMARY, None)
        elif security_status == Browser.SECURITY_STATUS_SECURE:
            self.entry.set_icon_from_name(
                iconentry.ICON_ENTRY_PRIMARY, 'channel-secure-symbolic')
        elif security_status == Browser.SECURITY_STATUS_INSECURE:
            self.entry.set_icon_from_name(
                iconentry.ICON_ENTRY_PRIMARY, 'channel-insecure-symbolic')

    def _set_progress(self, progress):
        if progress == 1.0:
            self.entry.set_progress_fraction(0.0)
        else:
            self.entry.set_progress_fraction(progress)

    def _set_address(self, uri):
        if uri is None:
            self.entry.props.address = ''
        else:
            self.entry.props.address = uri

    def __changed_cb(self, iconentry):
        # The WebEntry can be changed when we click on a link, then we
        # have to show the clear icon only if is the user who has
        # changed the entry
        if self.entry.has_focus():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_in_event_cb(self, entry, event):
        if not self._tabbed_view.is_current_page_pdf():
            if not self.entry.props.text:
                self._show_no_icon()
            else:
                self._show_clear_icon()

    def __focus_out_event_cb(self, entry, event):
        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._show_reload_icon()

    def _show_no_icon(self):
        self.entry.remove_icon(iconentry.ICON_ENTRY_SECONDARY)

    def _show_stop_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-stop')

    def _show_reload_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-refresh')

    def _show_clear_icon(self):
        self.entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY,
                                      'entry-cancel')

    def _update_navigation_buttons(self):
        can_go_back = self._browser.can_go_back()
        self._back.props.sensitive = can_go_back

        can_go_forward = self._browser.can_go_forward()
        self._forward.props.sensitive = can_go_forward

        is_webkit_browser = isinstance(self._browser, Browser)
        self._go_home.props.sensitive = is_webkit_browser
        if is_webkit_browser:
            self._reload_session_history()

        with self._link_add.handler_block(self._link_add_toggled_hid):
            uri = self._browser.get_uri()
            self._link_add.props.active = self.model.has_link(uri)

    def __link_removed_cb(self, model):
        self._update_navigation_buttons()

    def _entry_activate_cb(self, entry):
        url = entry.props.text
        effective_url = self._tabbed_view.normalize_or_autosearch_url(url)
        self._browser.load_uri(effective_url)
        self._browser.loading_uri = effective_url
        self.entry.props.address = effective_url
        self._browser.grab_focus()

    def _go_home_cb(self, button):
        self.emit('go-home')

    def _go_library_cb(self, button):
        self.emit('go-library')

    def _set_home_cb(self, button):
        self._reset_home_menu.set_visible(True)
        self.emit('set-home')

    def _reset_home_cb(self, button):
        self._reset_home_menu.set_visible(False)
        self.emit('reset-home')

    def _go_back_cb(self, button):
        self._browser.go_back()

    def _go_forward_cb(self, button):
        self._browser.go_forward()

    def __uri_changed_cb(self, widget, param):
        self._set_address(widget.get_uri())
        self._update_navigation_buttons()
        filepicker.cleanup_temp_files()

    def __load_changed_cb(self, widget, event):
        self._update_navigation_buttons()

    def _stop_and_reload_cb(self, entry, icon_pos, button):
        if entry.has_focus() and \
                not self._tabbed_view.is_current_page_pdf():
            entry.set_text('')
        else:
            if self._loading:
                self._browser.stop_loading()
            else:
                self._browser.reload()

    def _set_loading(self, loading):
        self._loading = loading

        if self._loading:
            self._show_stop_icon()
        else:
            if not self._tabbed_view.is_current_page_pdf():
                self._set_sensitive(True)
                self._show_reload_icon()
            else:
                self._set_sensitive(False)
                self._show_no_icon()

    def _set_sensitive(self, value):
        for widget in self.toolbar:
            if widget not in (self._stop_button,
                              self._link_add):
                widget.set_sensitive(value)

    def _reload_session_history(self):
        back_forward_list = self._browser.get_back_forward_list()
        item_index = 0  # The index of the history item

        # Clear menus in palettes:
        for box_menu in (self._back_box_menu, self._forward_box_menu):
            for menu_item in box_menu.get_children():
                box_menu.remove(menu_item)

        def create_menu_item(history_item):
            """Create a MenuItem for the back or forward palettes."""
            title = history_item.get_title() or _('No Title')
            if not isinstance(title, unicode):
                title = unicode(title, 'utf-8')
            # This is a fix until the Sugar MenuItem is fixed:
            menu_item = PaletteMenuItem(text_label=title)
            menu_item.connect('activate', self._history_item_activated_cb,
                              history_item)
            return menu_item

        back_list = back_forward_list.get_back_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        back_list.reverse()
        for item in back_list:
            menu_item = create_menu_item(item)
            self._back_box_menu.pack_end(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

        # Increment the item index to count the current page:
        item_index += 1

        forward_list = back_forward_list.get_forward_list_with_limit(
            _MAX_HISTORY_ENTRIES)
        forward_list.reverse()
        for item in forward_list:
            menu_item = create_menu_item(item)
            self._forward_box_menu.pack_start(menu_item, False, False, 0)
            menu_item.show()
            item_index += 1

    def _history_item_activated_cb(self, menu_item, history_item):
        self._back.get_palette().popdown(immediate=True)
        self._forward.get_palette().popdown(immediate=True)
        # self._browser.set_history_index(index)
        self._browser.go_to_back_forward_list_item(history_item)

    def __link_add_toggled_cb(self, button):
        if button.props.active:
            self.emit('add-link')
        else:
            self.emit('remove-link')

    def inspect_view(self, button):
        page = self._canvas.get_current_page()
        webview = self._canvas.get_children()[page].props.browser

        # If get_inspector returns None, it is not a real WebView
        inspector = webview.get_inspector()
        if inspector is not None:
            # Inspector window will be blank if disabled
            web_settings = webview.get_settings()
            web_settings.props.enable_developer_extras = True

            inspector.show()
            inspector.attach()

    '''