class WirelessNetworkView(EventPulsingIcon): def __init__(self, initial_ap): EventPulsingIcon.__init__(self, pixel_size=style.STANDARD_ICON_SIZE, cache=True) self._bus = dbus.SystemBus() self._access_points = {initial_ap.model.object_path: initial_ap} self._active_ap = None self._device = initial_ap.device self._palette_icon = None self._disconnect_item = None self._connect_item = None self._filtered = False self._ssid = initial_ap.ssid self._display_name = network.ssid_to_display_name(self._ssid) self._mode = initial_ap.mode self._strength = initial_ap.strength self._flags = initial_ap.flags self._wpa_flags = initial_ap.wpa_flags self._rsn_flags = initial_ap.rsn_flags self._device_caps = 0 self._device_state = None self._color = None self._removed_hid = None if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): self._color = profile.get_color() else: sha_hash = hashlib.sha1() data = self._ssid + hex(self._flags) sha_hash.update(data) digest = hash(sha_hash.digest()) index = digest % len(xocolor.colors) self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[index][0], xocolor.colors[index][1])) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) self.props.pulse_color = pulse_color self.props.palette_invoker.props.toggle_palette = True self._palette = self._create_palette() self.set_palette(self._palette) self._palette_icon.props.xo_color = self._color self._update_badge() interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_WIRELESS_IFACE, 'WirelessCapabilities', reply_handler=self.__get_device_caps_reply_cb, error_handler=self.__get_device_caps_error_cb) interface_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def _create_palette(self): icon_name = get_icon_state(_AP_ICON_NAME, self._strength) self._palette_icon = Icon(icon_name=icon_name, pixel_size=style.STANDARD_ICON_SIZE, badge_name=self.props.badge_name) p = palette.Palette(primary_text=self._display_name, icon=self._palette_icon) self.menu_box = Gtk.VBox() self._connect_item = PaletteMenuItem(_('Connect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='dialog-ok') self._connect_item.set_image(icon) self._connect_item.connect('activate', self.__connect_activate_cb) self.menu_box.add(self._connect_item) self._disconnect_item = PaletteMenuItem(_('Disconnect')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='media-eject') self._disconnect_item.set_image(icon) self._disconnect_item.connect( 'activate', self.__disconnect_activate_cb) self.menu_box.add(self._disconnect_item) self._forget_item = PaletteMenuItem(_('Forget')) icon = Icon(pixel_size=style.SMALL_ICON_SIZE, icon_name='list-remove') self._forget_item.set_image(icon) self._forget_item.connect('activate', self.__forget_activate_cb) self.menu_box.add(self._forget_item) p.set_content(self.menu_box) self.menu_box.show_all() self.connect_to_palette_pop_events(p) return p def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update_state() self._update_icon() self._update_badge() self._update_color() def __update_active_ap(self, ap_path): if ap_path in self._access_points: # save reference to active AP, so that we always display the # strength of that one self._active_ap = self._access_points[ap_path] self.update_strength() elif self._active_ap is not None: # revert to showing state of strongest AP again self._active_ap = None self.update_strength() def __wireless_properties_changed_cb(self, properties): if 'ActiveAccessPoint' in properties: self.__update_active_ap(properties['ActiveAccessPoint']) def __get_active_ap_reply_cb(self, ap_path): self.__update_active_ap(ap_path) interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) def __get_active_ap_error_cb(self, err): logging.error('Error getting the active access point: %s', err) def __get_device_caps_reply_cb(self, caps): self._device_caps = caps def __get_device_caps_error_cb(self, err): logging.error('Error getting the wireless device properties: %s', err) def __get_device_state_reply_cb(self, state): self._device_state = state self._update_state() self._update_color() self._update_icon() self._update_badge() def __get_device_state_error_cb(self, err): logging.error('Error getting the device state: %s', err) def _update_icon(self): if self._mode == network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._ssid): channel = max([1] + [ap.channel for ap in self._access_points.values()]) if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = 'network-adhoc-%s-connected' % channel else: icon_name = 'network-adhoc-%s' % channel self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name else: if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = '%s-connected' % _AP_ICON_NAME else: icon_name = _AP_ICON_NAME icon_name = get_icon_state(icon_name, self._strength) if icon_name: self.props.icon_name = icon_name icon = self._palette.props.icon icon.props.icon_name = icon_name def _update_badge(self): badge = None favorite = False if self._mode != network.NM_802_11_MODE_ADHOC: locked = (self._flags == network.NM_802_11_AP_FLAGS_PRIVACY) connection = network.find_connection_by_ssid(self._ssid) if connection is not None: favorite = True self._connect_removed(connection) if locked: badge = 'emblem-favorite-locked' else: badge = 'emblem-favorite' elif locked: badge = 'emblem-locked' self.props.badge_name = self._palette_icon.props.badge_name = badge self._forget_item.set_visible(favorite) def _connect_removed(self, connection): if self._removed_hid is not None: return self._removed_hid = connection.connect('removed', self._connection_removed_cb) def _disconnect_removed(self, connection): connection.disconnect(self._removed_hid) self._removed_hid = None def _connection_removed_cb(self, connection): self._update_badge() self._disconnect_removed(connection) def _update_state(self): if self._active_ap is not None: state = self._device_state else: state = network.NM_DEVICE_STATE_UNKNOWN if state == network.NM_DEVICE_STATE_PREPARE or \ state == network.NM_DEVICE_STATE_CONFIG or \ state == network.NM_DEVICE_STATE_NEED_AUTH or \ state == network.NM_DEVICE_STATE_IP_CONFIG: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True elif state == network.NM_DEVICE_STATE_ACTIVATED: network.set_connected() if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connected') self.props.pulsing = False else: if self._disconnect_item: self._disconnect_item.hide() self._connect_item.show() self._palette.props.secondary_text = None self.props.pulsing = False def _update_color(self): self.props.base_color = self._color if self._filtered: self.props.pulsing = False self.props.alpha = _FILTERED_ALPHA else: self.props.alpha = 1.0 def __disconnect_activate_cb(self, item): ap_paths = self._access_points.keys() network.disconnect_access_points(ap_paths) def __forget_activate_cb(self, item): network.forget_wireless_network(self._ssid) def _add_ciphers_from_flags(self, flags, pairwise): ciphers = [] if pairwise: if flags & network.NM_802_11_AP_SEC_PAIR_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_PAIR_CCMP: ciphers.append('ccmp') else: if flags & network.NM_802_11_AP_SEC_GROUP_WEP40: ciphers.append('wep40') if flags & network.NM_802_11_AP_SEC_GROUP_WEP104: ciphers.append('wep104') if flags & network.NM_802_11_AP_SEC_GROUP_TKIP: ciphers.append('tkip') if flags & network.NM_802_11_AP_SEC_GROUP_CCMP: ciphers.append('ccmp') return ciphers def _get_security(self): if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # No security return None if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): # Static WEP, Dynamic WEP, or LEAP wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'none' return wireless_security if (self._mode != network.NM_802_11_MODE_INFRA): # Stuff after this point requires infrastructure logging.error('The infrastructure mode is not supoorted' ' by your wireless device.') return None if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_RSN): # WPA2 PSK first pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) group = self._add_ciphers_from_flags(self._rsn_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'rsn' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ (self._device_caps & network.NM_WIFI_DEVICE_CAP_WPA): # WPA PSK pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) group = self._add_ciphers_from_flags(self._wpa_flags, False) wireless_security = WirelessSecurity() wireless_security.key_mgmt = 'wpa-psk' wireless_security.proto = 'wpa' wireless_security.pairwise = pairwise wireless_security.group = group return wireless_security def __connect_activate_cb(self, icon): self._connect() def _connect(self): # Activate existing connection, if there is one connection = network.find_connection_by_ssid(self._ssid) if connection: logging.debug('Activating existing connection for SSID %r', self._ssid) connection.activate(self._device) return # Otherwise, create new connection and activate it logging.debug('Creating new connection for SSID %r', self._ssid) settings = Settings() settings.connection.id = self._display_name settings.connection.uuid = str(uuid.uuid4()) settings.connection.type = '802-11-wireless' settings.wireless.ssid = self._ssid if self._mode == network.NM_802_11_MODE_INFRA: settings.wireless.mode = 'infrastructure' settings.connection.autoconnect = True elif self._mode == network.NM_802_11_MODE_ADHOC: settings.wireless.mode = 'adhoc' settings.wireless.band = 'bg' settings.ip4_config = IP4Config() settings.ip4_config.method = 'link-local' wireless_security = self._get_security() settings.wireless_security = wireless_security if wireless_security is not None: settings.wireless.security = '802-11-wireless-security' network.add_and_activate_connection(self._device, settings, self.get_first_ap().model) def set_filter(self, query): normalized_name = normalize_string(self._display_name.decode('utf-8')) self._filtered = normalized_name.find(query) == -1 self._update_icon() self._update_color() def create_keydialog(self, response): keydialog.create(self._ssid, self._flags, self._wpa_flags, self._rsn_flags, self._device_caps, response) def update_strength(self): if self._active_ap is not None: # display strength of AP that we are connected to new_strength = self._active_ap.strength else: # display the strength of the strongest AP that makes up this # network, also considering that there may be no APs new_strength = max([0] + [ap.strength for ap in self._access_points.values()]) if new_strength != self._strength: self._strength = new_strength self._update_icon() def add_ap(self, ap): self._access_points[ap.model.object_path] = ap self.update_strength() def remove_ap(self, ap): path = ap.model.object_path if path not in self._access_points: return del self._access_points[path] if self._active_ap == ap: self._active_ap = None self.update_strength() def num_aps(self): return len(self._access_points) def find_ap(self, ap_path): if ap_path not in self._access_points: return None return self._access_points[ap_path] def get_first_ap(self): return self._access_points.values()[0] def is_olpc_mesh(self): return self._mode == network.NM_802_11_MODE_ADHOC \ and self._ssid == 'olpc-mesh' def remove_all_aps(self): for ap in self._access_points.values(): ap.disconnect() self._access_points = {} self._active_ap = None self.update_strength() def disconnect(self): self._bus.remove_signal_receiver( self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver( self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, dbus_interface=network.NM_WIRELESS_IFACE) def get_positioning_data(self): return str(self.get_first_ap().network_hash())
class 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)
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)
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)
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() '''