Exemplo n.º 1
0
    def queryProxy(self, query):
        """Get the QNetworkProxies for a query.

        Args:
            query: The QNetworkProxyQuery to get a proxy for.

        Return:
            A list of QNetworkProxy objects in order of preference.
        """
        proxy = config.get('network', 'proxy')
        if proxy is configtypes.SYSTEM_PROXY:
            proxies = QNetworkProxyFactory.systemProxyForQuery(query)
        elif isinstance(proxy, pac.PACFetcher):
            proxies = proxy.resolve(query)
        else:
            proxies = [proxy]
        for p in proxies:
            if p.type() != QNetworkProxy.NoProxy:
                capabilities = p.capabilities()
                if config.get('network', 'proxy-dns-requests'):
                    capabilities |= QNetworkProxy.HostNameLookupCapability
                else:
                    capabilities &= ~QNetworkProxy.HostNameLookupCapability
                p.setCapabilities(capabilities)
        return proxies
Exemplo n.º 2
0
    def close_tab(self, tab):
        """Close a tab.

        Args:
            tab: The QWebView to be closed.
        """
        last_close = config.get('tabs', 'last-close')
        count = self.count()

        if last_close == 'ignore' and count == 1:
            return

        self._remove_tab(tab)

        if count == 1:  # We just closed the last tab above.
            if last_close == 'close':
                self.close_window.emit()
            elif last_close == 'blank':
                self.openurl(QUrl('about:blank'), newtab=True)
            elif last_close == 'startpage':
                url = QUrl(config.get('general', 'startpage')[0])
                self.openurl(url, newtab=True)
            elif last_close == 'default-page':
                url = config.get('general', 'default-page')
                self.openurl(url, newtab=True)
Exemplo n.º 3
0
    def _hint_strings(self, elems):
        """Calculate the hint strings for elems.

        Inspired by Vimium.

        Args:
            elems: The elements to get hint strings for.

        Return:
            A list of hint strings, in the same order as the elements.
        """
        hint_mode = config.get('hints', 'mode')
        if hint_mode == 'word':
            try:
                return self._word_hinter.hint(elems)
            except WordHintingError as e:
                message.error(self._win_id, str(e), immediately=True)
                # falls back on letter hints
        if hint_mode == 'number':
            chars = '0123456789'
        else:
            chars = config.get('hints', 'chars')
        min_chars = config.get('hints', 'min-chars')
        if config.get('hints', 'scatter') and hint_mode != 'number':
            return self._hint_scattered(min_chars, chars, elems)
        else:
            return self._hint_linear(min_chars, chars, elems)
Exemplo n.º 4
0
    def _get_new_tab_idx(self, explicit):
        """Get the index of a tab to insert.

        Args:
            explicit: Whether the tab was opened explicitely.

        Return:
            The index of the new tab.
        """
        if explicit:
            pos = config.get('tabs', 'new-tab-position-explicit')
        else:
            pos = config.get('tabs', 'new-tab-position')
        if pos == 'left':
            idx = self._tab_insert_idx_left
            # On first sight, we'd think we have to decrement
            # self._tab_insert_idx_left here, as we want the next tab to be
            # *before* the one we just opened. However, since we opened a tab
            # *to the left* of the currently focused tab, indices will shift by
            # 1 automatically.
        elif pos == 'right':
            idx = self._tab_insert_idx_right
            self._tab_insert_idx_right += 1
        elif pos == 'first':
            idx = 0
        elif pos == 'last':
            idx = -1
        else:
            raise ValueError("Invalid new-tab-position '{}'.".format(pos))
        log.webview.debug("new-tab-position {} -> opening new tab at {}, "
                          "next left: {} / right: {}".format(
                              pos, idx, self._tab_insert_idx_left,
                              self._tab_insert_idx_right))
        return idx
Exemplo n.º 5
0
    def minimumTabSizeHint(self, index):
        """Set the minimum tab size to indicator/icon/... text.

        Args:
            index: The index of the tab to get a size hint for.

        Return:
            A QSize.
        """
        icon = self.tabIcon(index)
        padding = config.get('tabs', 'padding')
        padding_h = padding.left + padding.right
        padding_v = padding.top + padding.bottom
        if icon.isNull():
            icon_size = QSize(0, 0)
        else:
            extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None,
                                              self)
            icon_size = icon.actualSize(QSize(extent, extent))
            padding_h += self.style().pixelMetric(
                PixelMetrics.icon_padding, None, self)
        indicator_width = config.get('tabs', 'indicator-width')
        height = self.fontMetrics().height() + padding_v
        width = (self.fontMetrics().width('\u2026') + icon_size.width() +
                 padding_h + indicator_width)
        return QSize(width, height)
Exemplo n.º 6
0
    def minimumTabSizeHint(self, index):
        """Set the minimum tab size to indicator/icon/... text.

        Args:
            index: The index of the tab to get a size hint for.

        Return:
            A QSize.
        """
        icon = self.tabIcon(index)
        padding_count = 2
        if icon.isNull():
            icon_size = QSize(0, 0)
        else:
            extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None,
                                              self)
            icon_size = icon.actualSize(QSize(extent, extent))
            padding_count += 1
        indicator_width = config.get('tabs', 'indicator-width')
        if indicator_width != 0:
            indicator_width += config.get('tabs', 'indicator-space')
        padding_width = self.style().pixelMetric(PM_TabBarPadding, None, self)
        height = self.fontMetrics().height()
        width = (self.fontMetrics().width('\u2026') +
                 icon_size.width() + padding_count * padding_width +
                 indicator_width)
        return QSize(width, height)
Exemplo n.º 7
0
    def edit(self, text):
        """Edit a given text.

        Args:
            text: The initial text to edit.
        """
        if self._text is not None:
            raise ValueError("Already editing a file!")
        self._text = text
        try:
            self._oshandle, self._filename = tempfile.mkstemp(
                text=True, prefix='qutebrowser-editor-')
            if text:
                encoding = config.get('general', 'editor-encoding')
                with open(self._filename, 'w', encoding=encoding) as f:
                    f.write(text)  # pragma: no branch
        except OSError as e:
            message.error(self._win_id, "Failed to create initial file: "
                                        "{}".format(e))
            return
        self._proc = guiprocess.GUIProcess(self._win_id, what='editor',
                                           parent=self)
        self._proc.finished.connect(self.on_proc_closed)
        self._proc.error.connect(self.on_proc_error)
        editor = config.get('general', 'editor')
        executable = editor[0]
        args = [self._filename if arg == '{}' else arg for arg in editor[1:]]
        log.procs.debug("Calling \"{}\" with args {}".format(executable, args))
        self._proc.start(executable, args)
Exemplo n.º 8
0
    def close_tab(self, tab, *, add_undo=True):
        """Close a tab.

        Args:
            tab: The QWebView to be closed.
            add_undo: Whether the tab close can be undone.
        """
        last_close = config.get('tabs', 'last-close')
        count = self.count()

        if last_close == 'ignore' and count == 1:
            return

        # If we are removing a pinned tab, decrease count
        if tab.data.pinned:
            self.tabBar().pinned_count -= 1

        self._remove_tab(tab, add_undo=add_undo)

        if count == 1:  # We just closed the last tab above.
            if last_close == 'close':
                self.close_window.emit()
            elif last_close == 'blank':
                self.openurl(QUrl('about:blank'), newtab=True)
            elif last_close == 'startpage':
                url = QUrl(config.get('general', 'startpage')[0])
                self.openurl(url, newtab=True)
            elif last_close == 'default-page':
                url = config.get('general', 'default-page')
                self.openurl(url, newtab=True)
Exemplo n.º 9
0
    def search(self, text, reverse=False):
        """Search for a text on the current page.

        Args:
            text: The text to search for.
            reverse: Reverse search direction.
        """
        if self._text is not None and self._text != text:
            # We first clear the marked text, then the highlights
            self.do_search.emit('', 0)
            self.do_search.emit('', QWebPage.HighlightAllOccurrences)
        self._text = text
        self._flags = 0
        ignore_case = config.get('general', 'ignore-case')
        if ignore_case == 'smart':
            if not text.islower():
                self._flags |= QWebPage.FindCaseSensitively
        elif not ignore_case:
            self._flags |= QWebPage.FindCaseSensitively
        if config.get('general', 'wrap-search'):
            self._flags |= QWebPage.FindWrapsAroundDocument
        if reverse:
            self._flags |= QWebPage.FindBackward
        # We actually search *twice* - once to highlight everything, then again
        # to get a mark so we can navigate.
        self.do_search.emit(self._text, self._flags)
        self.do_search.emit(self._text, self._flags |
                            QWebPage.HighlightAllOccurrences)
Exemplo n.º 10
0
    def close_tab(self, tab):
        """Close a tab.

        Args:
            tab: The QWebView to be closed.
        """
        last_close = config.get("tabs", "last-close")
        count = self.count()

        if last_close == "ignore" and count == 1:
            return

        self._remove_tab(tab)

        if count == 1:  # We just closed the last tab above.
            if last_close == "close":
                self.close_window.emit()
            elif last_close == "blank":
                self.openurl(QUrl("about:blank"), newtab=True)
            elif last_close == "startpage":
                url = QUrl(config.get("general", "startpage")[0])
                self.openurl(url, newtab=True)
            elif last_close == "default-page":
                url = config.get("general", "default-page")
                self.openurl(url, newtab=True)
Exemplo n.º 11
0
    def undo(self):
        """Undo removing of a tab."""
        # Remove unused tab which may be created after the last tab is closed
        last_close = config.get("tabs", "last-close")
        use_current_tab = False
        if last_close in ["blank", "startpage", "default-page"]:
            only_one_tab_open = self.count() == 1
            no_history = self.widget(0).history().count() == 1
            urls = {
                "blank": QUrl("about:blank"),
                "startpage": QUrl(config.get("general", "startpage")[0]),
                "default-page": config.get("general", "default-page"),
            }
            first_tab_url = self.widget(0).page().mainFrame().requestedUrl()
            last_close_urlstr = urls[last_close].toString().rstrip("/")
            first_tab_urlstr = first_tab_url.toString().rstrip("/")
            last_close_url_used = first_tab_urlstr == last_close_urlstr
            use_current_tab = only_one_tab_open and no_history and last_close_url_used

        url, history_data = self._undo_stack.pop()

        if use_current_tab:
            self.openurl(url, newtab=False)
            newtab = self.widget(0)
        else:
            newtab = self.tabopen(url, background=False)

        qtutils.deserialize(history_data, newtab.history())
Exemplo n.º 12
0
    def search(self, text="", reverse=False):
        """Search for a text on the current page. With no text, clear results.

        Args:
            text: The text to search for.
            reverse: Reverse search direction.
        """
        view = self._current_widget()
        if view.search_text is not None and view.search_text != text:
            # We first clear the marked text, then the highlights
            view.search('', 0)
            view.search('', QWebPage.HighlightAllOccurrences)

        flags = 0
        ignore_case = config.get('general', 'ignore-case')
        if ignore_case == 'smart':
            if not text.islower():
                flags |= QWebPage.FindCaseSensitively
        elif not ignore_case:
            flags |= QWebPage.FindCaseSensitively
        if config.get('general', 'wrap-search'):
            flags |= QWebPage.FindWrapsAroundDocument
        if reverse:
            flags |= QWebPage.FindBackward
        # We actually search *twice* - once to highlight everything, then again
        # to get a mark so we can navigate.
        view.search(text, flags)
        view.search(text, flags | QWebPage.HighlightAllOccurrences)
        view.search_text = text
        view.search_flags = flags
Exemplo n.º 13
0
    def _hint_strings(self, elems):
        """Calculate the hint strings for elems.

        Inspired by Vimium.

        Args:
            elems: The elements to get hint strings for.

        Return:
            A list of hint strings, in the same order as the elements.
        """
        if not elems:
            return []
        hint_mode = self._context.hint_mode
        if hint_mode == "word":
            try:
                return self._word_hinter.hint(elems)
            except HintingError as e:
                message.error(str(e))
                # falls back on letter hints
        if hint_mode == "number":
            chars = "0123456789"
        else:
            chars = config.get("hints", "chars")
        min_chars = config.get("hints", "min-chars")
        if config.get("hints", "scatter") and hint_mode != "number":
            return self._hint_scattered(min_chars, chars, elems)
        else:
            return self._hint_linear(min_chars, chars, elems)
Exemplo n.º 14
0
    def show_help(self, topic=None):
        r"""Show help about a command or setting.

        Args:
            topic: The topic to show help for.

                   - :__command__ for commands.
                   - __section__\->__option__ for settings.
        """
        if topic is None:
            path = 'index.html'
        elif topic.startswith(':'):
            command = topic[1:]
            if command not in cmdutils.cmd_dict:
                raise cmdexc.CommandError("Invalid command {}!".format(
                    command))
            path = 'commands.html#{}'.format(command)
        elif '->' in topic:
            parts = topic.split('->')
            if len(parts) != 2:
                raise cmdexc.CommandError("Invalid help topic {}!".format(
                    topic))
            try:
                config.get(*parts)
            except config.NoSectionError:
                raise cmdexc.CommandError("Invalid section {}!".format(
                    parts[0]))
            except config.NoOptionError:
                raise cmdexc.CommandError("Invalid option {}!".format(
                    parts[1]))
            path = 'settings.html#{}'.format(topic.replace('->', '-'))
        else:
            raise cmdexc.CommandError("Invalid help topic {}!".format(topic))
        self.openurl('qute://help/{}'.format(path))
Exemplo n.º 15
0
    def completion_item_focus(self, which):
        """Shift the focus of the completion menu to another item.

        Args:
            which: 'next', 'prev', 'next-category', or 'prev-category'.
        """
        if not self._active:
            return
        selmodel = self.selectionModel()

        if which == 'next':
            idx = self._next_idx(upwards=False)
        elif which == 'prev':
            idx = self._next_idx(upwards=True)
        elif which == 'next-category':
            idx = self._next_category_idx(upwards=False)
        elif which == 'prev-category':
            idx = self._next_category_idx(upwards=True)
        else:  # pragma: no cover
            raise ValueError("Invalid 'which' value {!r}".format(which))

        if not idx.isValid():
            return

        selmodel.setCurrentIndex(
            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)

        count = self.model().count()
        if count == 0:
            self.hide()
        elif count == 1 and config.get('completion', 'quick-complete'):
            self.hide()
        elif config.get('completion', 'show') == 'auto':
            self.show()
Exemplo n.º 16
0
 def resize_completion(self):
     """Adjust completion according to config."""
     if not self._completion.isVisible():
         # It doesn't make sense to resize the completion as long as it's
         # not shown anyways.
         return
     # Get the configured height/percentage.
     confheight = str(config.get("completion", "height"))
     if confheight.endswith("%"):
         perc = int(confheight.rstrip("%"))
         height = self.height() * perc / 100
     else:
         height = int(confheight)
     # Shrink to content size if needed and shrinking is enabled
     if config.get("completion", "shrink"):
         contents_height = (
             self._completion.viewportSizeHint().height()
             + self._completion.horizontalScrollBar().sizeHint().height()
         )
         if contents_height <= height:
             height = contents_height
     else:
         contents_height = -1
     # hpoint now would be the bottom-left edge of the widget if it was on
     # the top of the main window.
     topleft_y = self.height() - self.status.height() - height
     topleft_y = qtutils.check_overflow(topleft_y, "int", fatal=False)
     topleft = QPoint(0, topleft_y)
     bottomright = self.status.geometry().topRight()
     rect = QRect(topleft, bottomright)
     log.misc.debug("completion rect: {}".format(rect))
     if rect.isValid():
         self._completion.setGeometry(rect)
Exemplo n.º 17
0
def _get_search_url(txt):
    """Get a search engine URL for a text.

    Args:
        txt: Text to search for.

    Return:
        The search URL as a QUrl.
    """
    log.url.debug("Finding search engine for '{}'".format(txt))
    r = re.compile(r'(^\w+)\s+(.+)($|\s+)')
    m = r.search(txt)
    if m:
        engine = m.group(1)
        try:
            template = config.get('searchengines', engine)
        except configexc.NoOptionError:
            template = config.get('searchengines', 'DEFAULT')
            term = txt
        else:
            term = m.group(2).rstrip()
            log.url.debug("engine {}, term '{}'".format(engine, term))
    else:
        template = config.get('searchengines', 'DEFAULT')
        term = txt
        log.url.debug("engine: default, term '{}'".format(txt))
    if not term:
        raise FuzzyUrlError("No search term given")
    url = qurl_from_user_input(template.format(urllib.parse.quote(term)))
    qtutils.ensure_valid(url)
    return url
Exemplo n.º 18
0
 def paintEvent(self, _e):
     """Override paintEvent to draw the tabs like we want to."""
     p = QStylePainter(self)
     tab = QStyleOptionTab()
     selected = self.currentIndex()
     for idx in range(self.count()):
         self.initStyleOption(tab, idx)
         if idx == selected:
             color = config.get('colors', 'tab.bg.selected')
         elif idx % 2:
             color = config.get('colors', 'tab.bg.odd')
         else:
             color = config.get('colors', 'tab.bg.even')
         tab.palette.setColor(QPalette.Window, color)
         tab.palette.setColor(QPalette.WindowText,
                              config.get('colors', 'tab.fg'))
         indicator_color = self.tabData(idx)
         if indicator_color is None:
             indicator_color = QColor()
         tab.palette.setColor(QPalette.Base, indicator_color)
         if tab.rect.right() < 0 or tab.rect.left() > self.width():
             # Don't bother drawing a tab if the entire tab is outside of
             # the visible tab bar.
             continue
         p.drawControl(QStyle.CE_TabBarTab, tab)
Exemplo n.º 19
0
    def _handle_auto_follow(self, keystr="", filterstr="", visible=None):
        """Handle the auto-follow option."""
        if visible is None:
            visible = {string: label
                       for string, label in self._context.labels.items()
                       if label.isVisible()}

        if len(visible) != 1:
            return

        auto_follow = config.get('hints', 'auto-follow')

        if auto_follow == "always":
            follow = True
        elif auto_follow == "unique-match":
            follow = keystr or filterstr
        elif auto_follow == "full-match":
            elemstr = str(list(visible.values())[0].elem)
            filter_match = self._filter_matches_exactly(filterstr, elemstr)
            follow = (keystr in visible) or filter_match
        else:
            follow = False
            # save the keystr of the only one visible hint to be picked up
            # later by self.follow_hint
            self._context.to_follow = list(visible.keys())[0]

        if follow:
            # apply auto-follow-timeout
            timeout = config.get('hints', 'auto-follow-timeout')
            keyparsers = objreg.get('keyparsers', scope='window',
                                    window=self._win_id)
            normal_parser = keyparsers[usertypes.KeyMode.normal]
            normal_parser.set_inhibited_timeout(timeout)
            # unpacking gets us the first (and only) key in the dict.
            self._fire(*visible)
Exemplo n.º 20
0
    def paintEvent(self, _e):
        """Override paintEvent to draw the tabs like we want to."""
        # pylint: disable=bad-config-call
        # WORKAROUND for https://bitbucket.org/logilab/astroid/issue/104
        p = QStylePainter(self)
        selected = self.currentIndex()
        for idx in range(self.count()):
            tab = QStyleOptionTab()
            self.initStyleOption(tab, idx)

            bg_parts = ['tabs', 'bg']
            fg_parts = ['tabs', 'fg']
            if idx == selected:
                bg_parts.append('selected')
                fg_parts.append('selected')

            if idx % 2:
                bg_parts.append('odd')
                fg_parts.append('odd')
            else:
                bg_parts.append('even')
                fg_parts.append('even')

            bg_color = config.get('colors', '.'.join(bg_parts))
            fg_color = config.get('colors', '.'.join(fg_parts))
            tab.palette.setColor(QPalette.Window, bg_color)
            tab.palette.setColor(QPalette.WindowText, fg_color)

            indicator_color = self.tab_indicator_color(idx)
            tab.palette.setColor(QPalette.Base, indicator_color)
            if tab.rect.right() < 0 or tab.rect.left() > self.width():
                # Don't bother drawing a tab if the entire tab is outside of
                # the visible tab bar.
                continue
            p.drawControl(QStyle.CE_TabBarTab, tab)
Exemplo n.º 21
0
    def _add_widgets(self):
        """Add or readd all widgets to the VBox."""
        self._vbox.removeWidget(self.tabbed_browser)
        self._vbox.removeWidget(self._downloadview)
        self._vbox.removeWidget(self.status)
        downloads_position = config.get('ui', 'downloads-position')
        status_position = config.get('ui', 'status-position')
        widgets = [self.tabbed_browser]

        if downloads_position == 'top':
            widgets.insert(0, self._downloadview)
        elif downloads_position == 'bottom':
            widgets.append(self._downloadview)
        else:
            raise ValueError("Invalid position {}!".format(downloads_position))

        if status_position == 'top':
            widgets.insert(0, self.status)
        elif status_position == 'bottom':
            widgets.append(self.status)
        else:
            raise ValueError("Invalid position {}!".format(status_position))

        for widget in widgets:
            self._vbox.addWidget(widget)
Exemplo n.º 22
0
    def _get_icon_rect(self, opt, text_rect):
        """Get a QRect for the icon to draw.

        Args:
            opt: QStyleOptionTab
            text_rect: The QRect for the text.

        Return:
            A QRect.
        """
        icon_size = opt.iconSize
        if not icon_size.isValid():
            icon_extent = self.pixelMetric(QStyle.PM_SmallIconSize)
            icon_size = QSize(icon_extent, icon_extent)
        icon_mode = (QIcon.Normal if opt.state & QStyle.State_Enabled
                     else QIcon.Disabled)
        icon_state = (QIcon.On if opt.state & QStyle.State_Selected
                      else QIcon.Off)
        # reserve space for favicon when tab bar is vertical (issue #1968)
        position = config.get('tabs', 'position')
        if (opt.icon.isNull() and
                position in [QTabWidget.East, QTabWidget.West] and
                config.get('tabs', 'show-favicons')):
            tab_icon_size = icon_size
        else:
            actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state)
            tab_icon_size = QSize(
                min(actual_size.width(), icon_size.width()),
                min(actual_size.height(), icon_size.height()))
        icon_rect = QRect(text_rect.left(), text_rect.top() + 1,
                          tab_icon_size.width(), tab_icon_size.height())
        icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
        return icon_rect
Exemplo n.º 23
0
def _parse_search_term(s):
    """Get a search engine name and search term from a string.

    Args:
        s: The string to get a search engine for.

    Return:
        A (engine, term) tuple, where engine is None for the default engine.
    """
    s = s.strip()
    split = s.split(maxsplit=1)

    if len(split) == 2:
        engine = split[0]
        try:
            config.get('searchengines', engine)
        except configexc.NoOptionError:
            engine = None
            term = s
        else:
            term = split[1]
    elif not split:
        raise ValueError("Empty search term!")
    else:
        engine = None
        term = s

    log.url.debug("engine {}, term {!r}".format(engine, term))
    return (engine, term)
Exemplo n.º 24
0
    def edit(self, text):
        """Edit a given text.

        Args:
            text: The initial text to edit.
        """
        if self._text is not None:
            raise ValueError("Already editing a file!")
        self._text = text
        encoding = config.get('general', 'editor-encoding')
        try:
            # Close while the external process is running, as otherwise systems
            # with exclusive write access (e.g. Windows) may fail to update
            # the file from the external editor, see
            # https://github.com/The-Compiler/qutebrowser/issues/1767
            with tempfile.NamedTemporaryFile(
                    mode='w', prefix='qutebrowser-editor-', encoding=encoding,
                    delete=False) as fobj:
                if text:
                    fobj.write(text)
                self._file = fobj
        except OSError as e:
            message.error("Failed to create initial file: {}".format(e))
            return
        self._proc = guiprocess.GUIProcess(what='editor', parent=self)
        self._proc.finished.connect(self.on_proc_closed)
        self._proc.error.connect(self.on_proc_error)
        editor = config.get('general', 'editor')
        executable = editor[0]
        args = [arg.replace('{}', self._file.name) for arg in editor[1:]]
        log.procs.debug("Calling \"{}\" with args {}".format(executable, args))
        self._proc.start(executable, args)
Exemplo n.º 25
0
    def _draw_textdoc(self, rect):
        """Draw the QTextDocument of an item.

        Args:
            rect: The QRect to clip the drawing to.
        """
        # We can't use drawContents because then the color would be ignored.
        # See: https://qt-project.org/forums/viewthread/21492
        clip = QRectF(0, 0, rect.width(), rect.height())
        self._painter.save()
        if self._opt.state & QStyle.State_Selected:
            option = 'completion.item.selected.fg'
        elif not self._opt.state & QStyle.State_Enabled:
            option = 'completion.category.fg'
        else:
            option = 'completion.fg'
        try:
            self._painter.setPen(config.get('colors', option))
        except configexc.NoOptionError:
            self._painter.setPen(config.get('colors', 'completion.fg'))
        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
        if clip.isValid():
            self._painter.setClipRect(clip)
            ctx.clip = clip
        self._doc.documentLayout().draw(self._painter, ctx)
        self._painter.restore()
Exemplo n.º 26
0
 def resize_completion(self):
     """Adjust completion according to config."""
     if not self._completion.isVisible():
         # It doesn't make sense to resize the completion as long as it's
         # not shown anyways.
         return
     # Get the configured height/percentage.
     confheight = str(config.get('completion', 'height'))
     if confheight.endswith('%'):
         perc = int(confheight.rstrip('%'))
         height = self.height() * perc / 100
     else:
         height = int(confheight)
     # Shrink to content size if needed and shrinking is enabled
     if config.get('completion', 'shrink'):
         contents_height = (
             self._completion.viewportSizeHint().height() +
             self._completion.horizontalScrollBar().sizeHint().height())
         if contents_height <= height:
             height = contents_height
     else:
         contents_height = -1
     rect = self._get_overlay_position(height)
     log.misc.debug('completion rect: {}'.format(rect))
     if rect.isValid():
         self._completion.setGeometry(rect)
Exemplo n.º 27
0
    def undo(self):
        """Undo removing of a tab."""
        # Remove unused tab which may be created after the last tab is closed
        last_close = config.get('tabs', 'last-close')
        use_current_tab = False
        if last_close in ['blank', 'startpage', 'default-page']:
            only_one_tab_open = self.count() == 1
            no_history = len(self.widget(0).history) == 1
            urls = {
                'blank': QUrl('about:blank'),
                'startpage': QUrl(config.get('general', 'startpage')[0]),
                'default-page': config.get('general', 'default-page'),
            }
            first_tab_url = self.widget(0).url()
            last_close_urlstr = urls[last_close].toString().rstrip('/')
            first_tab_urlstr = first_tab_url.toString().rstrip('/')
            last_close_url_used = first_tab_urlstr == last_close_urlstr
            use_current_tab = (only_one_tab_open and no_history and
                               last_close_url_used)

        url, history_data, idx = self._undo_stack.pop()

        if use_current_tab:
            self.openurl(url, newtab=False)
            newtab = self.widget(0)
        else:
            newtab = self.tabopen(url, background=False, idx=idx)

        newtab.history.deserialize(history_data)
Exemplo n.º 28
0
def init():
    """Initialize the global QWebSettings."""
    cache_path = standarddir.cache()
    data_path = standarddir.data()
    if config.get('general', 'private-browsing') or cache_path is None:
        QWebSettings.setIconDatabasePath('')
    else:
        QWebSettings.setIconDatabasePath(cache_path)
    if cache_path is not None:
        QWebSettings.setOfflineWebApplicationCachePath(
            os.path.join(cache_path, 'application-cache'))
    if data_path is not None:
        QWebSettings.globalSettings().setLocalStoragePath(
            os.path.join(data_path, 'local-storage'))
        QWebSettings.setOfflineStoragePath(
            os.path.join(data_path, 'offline-storage'))

    for sectname, section in MAPPINGS.items():
        for optname, mapping in section.items():
            default = mapping.save_default()
            log.config.vdebug("Saved default for {} -> {}: {!r}".format(
                sectname, optname, default))
            value = config.get(sectname, optname)
            log.config.vdebug("Setting {} -> {} to {!r}".format(
                sectname, optname, value))
            mapping.set(value)
    objreg.get('config').changed.connect(update_settings)
Exemplo n.º 29
0
 def resize_completion(self):
     """Adjust completion according to config."""
     # Get the configured height/percentage.
     confheight = str(config.get('completion', 'height'))
     if confheight.endswith('%'):
         perc = int(confheight.rstrip('%'))
         height = self.height() * perc / 100
     else:
         height = int(confheight)
     # Shrink to content size if needed and shrinking is enabled
     if config.get('completion', 'shrink'):
         contents_height = (
             self._completion.viewportSizeHint().height() +
             self._completion.horizontalScrollBar().sizeHint().height())
         if contents_height <= height:
             height = contents_height
     else:
         contents_height = -1
     # hpoint now would be the bottom-left edge of the widget if it was on
     # the top of the main window.
     topleft_y = self.height() - self.status.height() - height
     topleft_y = qtutils.check_overflow(topleft_y, 'int', fatal=False)
     topleft = QPoint(0, topleft_y)
     bottomright = self.status.geometry().topRight()
     rect = QRect(topleft, bottomright)
     if rect.isValid():
         self._completion.setGeometry(rect)
Exemplo n.º 30
0
    def _tab_layout(self, opt):
        """Compute the text/icon rect from the opt rect.

        This is based on Qt's QCommonStylePrivate::tabLayout
        (qtbase/src/widgets/styles/qcommonstyle.cpp) as we can't use the
        private implementation.

        Args:
            opt: QStyleOptionTab

        Return:
            A (text_rect, icon_rect) tuple (both QRects).
        """
        padding = self.pixelMetric(PM_TabBarPadding, opt)
        icon_rect = QRect()
        text_rect = QRect(opt.rect)
        qtutils.ensure_valid(text_rect)
        indicator_width = config.get('tabs', 'indicator-width')
        text_rect.adjust(padding, 0, 0, 0)
        if indicator_width != 0:
            text_rect.adjust(indicator_width +
                             config.get('tabs', 'indicator-space'), 0, 0, 0)
        if not opt.icon.isNull():
            icon_rect = self._get_icon_rect(opt, text_rect)
            text_rect.adjust(icon_rect.width() + padding, 0, 0, 0)
        text_rect = self._style.visualRect(opt.direction, opt.rect, text_rect)
        return (text_rect, icon_rect)
Exemplo n.º 31
0
    def on_unsupported_content(self, reply):
        """Handle an unsupportedContent signal.

        Most likely this will mean we need to download the reply, but we
        correct for some common errors the server do.

        At some point we might want to implement the MIME Sniffing standard
        here: http://mimesniff.spec.whatwg.org/
        """
        inline, suggested_filename = http.parse_content_disposition(reply)
        download_manager = objreg.get('qtnetwork-download-manager',
                                      scope='window', window=self._win_id)
        if not inline:
            # Content-Disposition: attachment -> force download
            download_manager.fetch(reply,
                                   suggested_filename=suggested_filename)
            return
        mimetype, _rest = http.parse_content_type(reply)
        if mimetype == 'image/jpg':
            # Some servers (e.g. the LinkedIn CDN) send a non-standard
            # image/jpg (instead of image/jpeg, defined in RFC 1341 section
            # 7.5). If this is the case, we force displaying with a corrected
            # mimetype.
            if reply.isFinished():
                self.display_content(reply, 'image/jpeg')
            else:
                reply.finished.connect(functools.partial(
                    self.display_content, reply, 'image/jpeg'))
        elif (mimetype in ['application/pdf', 'application/x-pdf'] and
              config.get('content', 'enable-pdfjs')):
            # Use pdf.js to display the page
            self._show_pdfjs(reply)
        else:
            # Unknown mimetype, so download anyways.
            download_manager.fetch(reply,
                                   suggested_filename=suggested_filename)
Exemplo n.º 32
0
 def set_colors(self):
     """Set the tabbar colors."""
     p = self.palette()
     p.setColor(QPalette.Window, config.get('colors', 'tabs.bg.bar'))
     self.setPalette(p)
Exemplo n.º 33
0
 def get(self, settings=None):
     return config.get('content', 'cookies-accept')
Exemplo n.º 34
0
 def set_hbox_padding(self):
     padding = config.get('ui', 'statusbar-padding')
     self._hbox.setContentsMargins(padding.left, 0, padding.right, 0)
Exemplo n.º 35
0
 def set_enabled(self):
     """Update self.enabled when the config changed."""
     self.enabled = config.get('completion', 'show')
Exemplo n.º 36
0
 def _set_bg_color(self):
     col = config.get('colors', 'webpage.bg')
     if col is None:
         col = self._theme_color
     self.setBackgroundColor(col)
Exemplo n.º 37
0
def _init_modules(args, crash_handler):
    """Initialize all 'modules' which need to be initialized.

    Args:
        args: The argparse namespace.
        crash_handler: The CrashHandler instance.
    """
    # pylint: disable=too-many-statements
    log.init.debug("Initializing save manager...")
    save_manager = savemanager.SaveManager(qApp)
    objreg.register('save-manager', save_manager)
    save_manager.add_saveable('version', _save_version)
    log.init.debug("Initializing network...")
    networkmanager.init()
    log.init.debug("Initializing readline-bridge...")
    readline_bridge = readline.ReadlineBridge()
    objreg.register('readline-bridge', readline_bridge)
    log.init.debug("Initializing directories...")
    standarddir.init(args)
    log.init.debug("Initializing config...")
    config.init(qApp)
    save_manager.init_autosave()
    log.init.debug("Initializing web history...")
    history.init(qApp)
    log.init.debug("Initializing crashlog...")
    if not args.no_err_windows:
        crash_handler.handle_segfault()
    log.init.debug("Initializing sessions...")
    sessions.init(qApp)
    log.init.debug("Initializing js-bridge...")
    js_bridge = qutescheme.JSBridge(qApp)
    objreg.register('js-bridge', js_bridge)
    log.init.debug("Initializing websettings...")
    websettings.init()
    log.init.debug("Initializing adblock...")
    host_blocker = adblock.HostBlocker()
    host_blocker.read_hosts()
    objreg.register('host-blocker', host_blocker)
    log.init.debug("Initializing quickmarks...")
    quickmark_manager = urlmarks.QuickmarkManager(qApp)
    objreg.register('quickmark-manager', quickmark_manager)
    log.init.debug("Initializing bookmarks...")
    bookmark_manager = urlmarks.BookmarkManager(qApp)
    objreg.register('bookmark-manager', bookmark_manager)
    log.init.debug("Initializing proxy...")
    proxy.init()
    log.init.debug("Initializing cookies...")
    cookie_jar = cookies.CookieJar(qApp)
    objreg.register('cookie-jar', cookie_jar)
    log.init.debug("Initializing cache...")
    diskcache = cache.DiskCache(standarddir.cache(), parent=qApp)
    objreg.register('cache', diskcache)
    log.init.debug("Initializing completions...")
    completionmodels.init()
    log.init.debug("Misc initialization...")
    if config.get('ui', 'hide-wayland-decoration'):
        os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1'
    else:
        os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None)
    _maybe_hide_mouse_cursor()
    objreg.get('config').changed.connect(_maybe_hide_mouse_cursor)
Exemplo n.º 38
0
    def tabSizeHint(self, index):
        """Override tabSizeHint so all tabs are the same size.

        https://wiki.python.org/moin/PyQt/Customising%20tab%20bars

        Args:
            index: The index of the tab.

        Return:
            A QSize.
        """
        minimum_size = self.minimumTabSizeHint(index)
        height = minimum_size.height()
        if self.vertical:
            confwidth = str(config.get('tabs', 'width'))
            if confwidth.endswith('%'):
                main_window = objreg.get('main-window', scope='window',
                                         window=self._win_id)
                perc = int(confwidth.rstrip('%'))
                width = main_window.width() * perc / 100
            else:
                width = int(confwidth)
            size = QSize(max(minimum_size.width(), width), height)
        elif self.count() == 0:
            # This happens on startup on OS X.
            # We return it directly rather than setting `size' because we don't
            # want to ensure it's valid in this special case.
            return QSize()
        elif self.count() * minimum_size.width() > self.width():
            # If we don't have enough space, we return the minimum size so we
            # get scroll buttons as soon as needed.
            size = minimum_size
        else:
            tab_width_pinned_conf = config.get('tabs', 'pinned-width')

            try:
                pinned = self.tab_data(index, 'pinned')
            except KeyError:
                pinned = False

            no_pinned_count = self.count() - self.pinned_count
            pinned_width = tab_width_pinned_conf * self.pinned_count
            no_pinned_width = self.width() - pinned_width

            if pinned:
                width = tab_width_pinned_conf
            else:

                # If we *do* have enough space, tabs should occupy the whole
                # window width. If there are pinned tabs their size will be
                # subtracted from the total window width.
                # During shutdown the self.count goes down,
                # but the self.pinned_count not - this generates some odd
                # behavior. To avoid this we compare self.count against
                # self.pinned_count.
                if self.pinned_count > 0 and no_pinned_count > 0:
                    width = no_pinned_width / no_pinned_count
                else:
                    width = self.width() / self.count()

            # If no_pinned_width is not divisible by no_pinned_count, add a
            # pixel to some tabs so that there is no ugly leftover space.
            if (no_pinned_count > 0 and
                    index < no_pinned_width % no_pinned_count):
                width += 1

            size = QSize(width, height)
        qtutils.ensure_valid(size)
        return size
Exemplo n.º 39
0
 def _set_clear_timer_interval(self):
     """Configure self._clear_timer according to the config."""
     self._clear_timer.setInterval(config.get('ui', 'message-timeout'))
Exemplo n.º 40
0
 def on_show_switching_delay_changed(self):
     """Set timer interval when tabs->show-switching-delay got changed."""
     self._auto_hide_timer.setInterval(
         config.get('tabs', 'show-switching-delay'))
Exemplo n.º 41
0
 def set_icon_size(self):
     """Set the tab bar favicon size."""
     size = self.fontMetrics().height() - 2
     size *= config.get('tabs', 'favicon-scale')
     self.setIconSize(QSize(size, size))
Exemplo n.º 42
0
 def _shutdown(self, status):  # noqa
     """Second stage of shutdown."""
     # pylint: disable=too-many-branches, too-many-statements
     # FIXME refactor this
     # https://github.com/The-Compiler/qutebrowser/issues/113
     log.destroy.debug("Stage 2 of shutting down...")
     # Remove eventfilter
     try:
         log.destroy.debug("Removing eventfilter...")
         self.removeEventFilter(self._event_filter)
     except AttributeError:
         pass
     # Close all windows
     QApplication.closeAllWindows()
     # Shut down IPC
     try:
         objreg.get('ipc-server').shutdown()
     except KeyError:
         pass
     # Save everything
     try:
         config_obj = objreg.get('config')
     except KeyError:
         log.destroy.debug("Config not initialized yet, so not saving "
                           "anything.")
     else:
         to_save = []
         if config.get('general', 'auto-save-config'):
             to_save.append(("config", config_obj.save))
             try:
                 key_config = objreg.get('key-config')
             except KeyError:
                 pass
             else:
                 to_save.append(("keyconfig", key_config.save))
         to_save += [("window geometry", self._save_geometry)]
         try:
             command_history = objreg.get('command-history')
         except KeyError:
             pass
         else:
             to_save.append(("command history", command_history.save))
         try:
             quickmark_manager = objreg.get('quickmark-manager')
         except KeyError:
             pass
         else:
             to_save.append(("command history", quickmark_manager.save))
         try:
             state_config = objreg.get('state-config')
         except KeyError:
             pass
         else:
             to_save.append(("window geometry", state_config.save))
         try:
             cookie_jar = objreg.get('cookie-jar')
         except KeyError:
             pass
         else:
             to_save.append(("cookies", cookie_jar.save))
         for what, handler in to_save:
             log.destroy.debug("Saving {} (handler: {})".format(
                 what, utils.qualname(handler)))
             try:
                 handler()
             except AttributeError as e:
                 log.destroy.warning("Could not save {}.".format(what))
                 log.destroy.debug(e)
     # Re-enable faulthandler to stdout, then remove crash log
     log.destroy.debug("Deactiving crash log...")
     self._destroy_crashlogfile()
     # If we don't kill our custom handler here we might get segfaults
     log.destroy.debug("Deactiving message handler...")
     qInstallMessageHandler(None)
     # Now we can hopefully quit without segfaults
     log.destroy.debug("Deferring QApplication::exit...")
     # We use a singleshot timer to exit here to minimize the likelyhood of
     # segfaults.
     QTimer.singleShot(0, functools.partial(self.exit, status))
Exemplo n.º 43
0
 def _maybe_update_geometry(self):
     """Emit the update_geometry signal if the config says so."""
     if config.get('completion', 'shrink'):
         self.update_geometry.emit()
Exemplo n.º 44
0
 def home(self):
     """Open main startpage in current tab."""
     self.openurl(config.get('general', 'startpage')[0])
Exemplo n.º 45
0
 def set_forward_unbound_keys(self):
     """Update local setting when config changed."""
     self._forward_unbound_keys = config.get('input',
                                             'forward-unbound-keys')
Exemplo n.º 46
0
    def fetch(self,
              reply,
              *,
              fileobj=None,
              filename=None,
              auto_remove=False,
              suggested_filename=None,
              prompt_download_directory=None):
        """Download a QNetworkReply to disk.

        Args:
            reply: The QNetworkReply to download.
            fileobj: The file object to write the answer to.
            filename: A path to write the data to.
            auto_remove: Whether to remove the download even if
                         ui -> remove-finished-downloads is set to -1.

        Return:
            The created DownloadItem.
        """
        if fileobj is not None and filename is not None:
            raise TypeError("Only one of fileobj/filename may be given!")
        if not suggested_filename:
            if filename is not None:
                suggested_filename = os.path.basename(filename)
            elif fileobj is not None and getattr(fileobj, 'name', None):
                suggested_filename = fileobj.name
            else:
                _, suggested_filename = http.parse_content_disposition(reply)
        log.downloads.debug("fetch: {} -> {}".format(reply.url(),
                                                     suggested_filename))
        download = DownloadItem(reply, self._win_id, self)
        download.cancelled.connect(
            functools.partial(self.remove_item, download))

        delay = config.get('ui', 'remove-finished-downloads')
        if delay > -1:
            download.finished.connect(
                functools.partial(self.remove_item_delayed, download, delay))
        elif auto_remove:
            download.finished.connect(
                functools.partial(self.remove_item, download))

        download.data_changed.connect(
            functools.partial(self.on_data_changed, download))
        download.error.connect(self.on_error)
        download.redirected.connect(
            functools.partial(self.on_redirect, download))
        download.basename = suggested_filename
        idx = len(self.downloads) + 1
        download.index = idx
        self.beginInsertRows(QModelIndex(), idx, idx)
        self.downloads.append(download)
        self.endInsertRows()

        if not self._update_timer.isActive():
            self._update_timer.start()

        if fileobj is not None:
            download.set_fileobj(fileobj)
            download.autoclose = False
            return download

        if filename is not None:
            download.set_filename(filename)
            return download

        # Neither filename nor fileobj were given, prepare a question
        filename, q = ask_for_filename(
            suggested_filename,
            self._win_id,
            parent=self,
            prompt_download_directory=prompt_download_directory,
        )

        # User doesn't want to be asked, so just use the download_dir
        if filename is not None:
            download.set_filename(filename)
            return download

        # Ask the user for a filename
        self._postprocess_question(q)
        q.answered.connect(download.set_filename)
        q.cancelled.connect(download.cancel)
        download.cancelled.connect(q.abort)
        download.error.connect(q.abort)
        q.ask()

        return download
Exemplo n.º 47
0
 def set_pop_timer_interval(self):
     """Update message timeout when config changed."""
     self._text_pop_timer.setInterval(config.get('ui', 'message-timeout'))
Exemplo n.º 48
0
 def _handle_context_menu(self, _e):
     """Suppress context menus if rocker gestures are turned on."""
     return config.get('input', 'rocker-gestures')
Exemplo n.º 49
0
    def fire(self, keystr, force=False):
        """Fire a completed hint.

        Args:
            keystr: The keychain string to follow.
            force: When True, follow even when auto-follow is false.
        """
        if not (force or config.get('hints', 'auto-follow')):
            self.handle_partial_key(keystr)
            self._context.to_follow = keystr
            return
        # Handlers which take a QWebElement
        elem_handlers = {
            Target.normal:
            self._click,
            Target.tab:
            self._click,
            Target.tab_bg:
            self._click,
            Target.window:
            self._click,
            Target.rapid:
            self._click,
            Target.rapid_win:
            self._click,
            Target.hover:
            self._click,
            # _download needs a QWebElement to get the frame.
            Target.download:
            self._download,
        }
        # Handlers which take a QUrl
        url_handlers = {
            Target.yank: self._yank,
            Target.yank_primary: self._yank,
            Target.run: self._run_cmd,
            Target.fill: self._preset_cmd_text,
            Target.userscript: self._call_userscript,
            Target.spawn: self._spawn,
        }
        elem = self._context.elems[keystr].elem
        if self._context.target in elem_handlers:
            handler = functools.partial(elem_handlers[self._context.target],
                                        elem, self._context)
        elif self._context.target in url_handlers:
            url = self._resolve_url(elem, self._context.baseurl)
            if url is None:
                message.error(self._win_id,
                              "No suitable link found for this element.",
                              immediately=True)
                return
            handler = functools.partial(url_handlers[self._context.target],
                                        url, self._context)
        else:
            raise ValueError("No suitable handler found!")
        if self._context.target not in (Target.rapid, Target.rapid_win):
            modeman.maybe_leave(self._win_id, usertypes.KeyMode.hint,
                                'followed')
        else:
            # Show all hints again
            self.filter_hints(None)
            # Undo keystring highlighting
            for (string, elems) in self._context.elems.items():
                elems.label.setInnerXml(string)
        handler()
Exemplo n.º 50
0
    def start(self,
              rapid=False,
              group=webelem.Group.all,
              target=Target.normal,
              *args: {'nargs': '*'},
              win_id):
        """Start hinting.

        Args:
            rapid: Whether to do rapid hinting. This is only possible with
                   targets `tab` (with background-tabs=true), `tab-bg`,
                   `window`, `run`, `hover`, `userscript` and `spawn`.
            group: The hinting mode to use.

                - `all`: All clickable elements.
                - `links`: Only links.
                - `images`: Only images.

            target: What to do with the selected element.

                - `normal`: Open the link in the current tab.
                - `tab`: Open the link in a new tab (honoring the
                         background-tabs setting).
                - `tab-fg`: Open the link in a new foreground tab.
                - `tab-bg`: Open the link in a new background tab.
                - `window`: Open the link in a new window.
                - `hover` : Hover over the link.
                - `yank`: Yank the link to the clipboard.
                - `yank-primary`: Yank the link to the primary selection.
                - `run`: Run the argument as command.
                - `fill`: Fill the commandline with the command given as
                          argument.
                - `download`: Download the link.
                - `userscript`: Call a userscript with `$QUTE_URL` set to the
                                link.
                - `spawn`: Spawn a command.

            *args: Arguments for spawn/userscript/run/fill.

                - With `spawn`: The executable and arguments to spawn.
                                `{hint-url}` will get replaced by the selected
                                URL.
                - With `userscript`: The userscript to execute. Either store
                                     the userscript in
                                     `~/.local/share/qutebrowser/userscripts`
                                     (or `$XDG_DATA_DIR`), or use an absolute
                                     path.
                - With `fill`: The command to fill the statusbar with.
                                `{hint-url}` will get replaced by the selected
                                URL.
                - With `run`: Same as `fill`.
        """
        tabbed_browser = objreg.get('tabbed-browser',
                                    scope='window',
                                    window=self._win_id)
        widget = tabbed_browser.currentWidget()
        if widget is None:
            raise cmdexc.CommandError("No WebView available yet!")
        mainframe = widget.page().mainFrame()
        if mainframe is None:
            raise cmdexc.CommandError("No frame focused!")
        mode_manager = objreg.get('mode-manager',
                                  scope='window',
                                  window=self._win_id)
        if mode_manager.mode == usertypes.KeyMode.hint:
            modeman.leave(win_id, usertypes.KeyMode.hint, 're-hinting')

        if rapid:
            if target in [
                    Target.tab_bg, Target.window, Target.run, Target.hover,
                    Target.userscript, Target.spawn, Target.download
            ]:
                pass
            elif (target == Target.tab
                  and config.get('tabs', 'background-tabs')):
                pass
            else:
                name = target.name.replace('_', '-')
                raise cmdexc.CommandError("Rapid hinting makes no sense with "
                                          "target {}!".format(name))

        self._check_args(target, *args)
        self._context = HintContext()
        self._context.target = target
        self._context.rapid = rapid
        try:
            self._context.baseurl = tabbed_browser.current_url()
        except qtutils.QtValueError:
            raise cmdexc.CommandError("No URL set for this page yet!")
        self._context.frames = webelem.get_child_frames(mainframe)
        for frame in self._context.frames:
            # WORKAROUND for
            # https://github.com/The-Compiler/qutebrowser/issues/152
            frame.destroyed.connect(
                functools.partial(self._context.destroyed_frames.append,
                                  id(frame)))
        self._context.args = args
        self._context.mainframe = mainframe
        self._context.group = group
        self._init_elements()
        message_bridge = objreg.get('message-bridge',
                                    scope='window',
                                    window=self._win_id)
        message_bridge.set_text(self._get_text())
        self._connect_frame_signals()
        modeman.enter(self._win_id, usertypes.KeyMode.hint,
                      'HintManager.start')
Exemplo n.º 51
0
 def init_neighborlist(self):
     """Initialize the _zoom neighborlist."""
     levels = config.get('ui', 'zoom-levels')
     self._zoom = usertypes.NeighborList(
         levels, mode=usertypes.NeighborList.Modes.block)
     self._zoom.fuzzyval = config.get('ui', 'default-zoom')
Exemplo n.º 52
0
 def get(self, settings=None):
     utils.unused(settings)
     return config.get('content', 'cookies-store')
Exemplo n.º 53
0
    def tabopen(self,
                url=None,
                background=None,
                explicit=False,
                idx=None,
                *,
                ignore_tabs_are_windows=False):
        """Open a new tab with a given URL.

        Inner logic for open-tab and open-tab-bg.
        Also connect all the signals we need to _filter_signals.

        Args:
            url: The URL to open as QUrl or None for an empty tab.
            background: Whether to open the tab in the background.
                        if None, the background-tabs setting decides.
            explicit: Whether the tab was opened explicitly.
                      If this is set, the new position might be different. With
                      the default settings we handle it like Chromium does:
                          - Tabs from clicked links etc. are to the right of
                            the current.
                          - Explicitly opened tabs are at the very right.
            idx: The index where the new tab should be opened.
            ignore_tabs_are_windows: If given, never open a new window, even
                                     with tabs-are-windows set.

        Return:
            The opened WebView instance.
        """
        if url is not None:
            qtutils.ensure_valid(url)
        log.webview.debug("Creating new tab with URL {}, background {}, "
                          "explicit {}, idx {}".format(url, background,
                                                       explicit, idx))

        if (config.get('tabs', 'tabs-are-windows') and self.count() > 0
                and not ignore_tabs_are_windows):
            from qutebrowser.mainwindow import mainwindow
            window = mainwindow.MainWindow(private=self.private)
            window.show()
            tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=window.win_id)
            return tabbed_browser.tabopen(url, background, explicit)

        tab = browsertab.create(win_id=self._win_id,
                                private=self.private,
                                parent=self)
        self._connect_tab_signals(tab)

        if idx is None:
            idx = self._get_new_tab_idx(explicit)
        self.insertTab(idx, tab, "")

        if url is not None:
            tab.openurl(url)

        if background is None:
            background = config.get('tabs', 'background-tabs')
        if background:
            # Make sure the background tab has the correct initial size.
            # With a foreground tab, it's going to be resized correctly by the
            # layout anyways.
            if self.tabBar().vertical:
                tab_size = QSize(self.width() - self.tabBar().width(),
                                 self.height())
            else:
                tab_size = QSize(self.width(),
                                 self.height() - self.tabBar().height())
            tab.resize(tab_size)
            self.tab_index_changed.emit(self.currentIndex(), self.count())
        else:
            self.setCurrentWidget(tab)

        tab.show()
        self.new_tab.emit(tab, idx)
        return tab
Exemplo n.º 54
0
    def start(self,
              rapid=False,
              group=webelem.Group.all,
              target=Target.normal,
              *args,
              win_id,
              mode=None,
              add_history=False):
        """Start hinting.

        Args:
            rapid: Whether to do rapid hinting. This is only possible with
                   targets `tab` (with background-tabs=true), `tab-bg`,
                   `window`, `run`, `hover`, `userscript` and `spawn`.
            add_history: Whether to add the spawned or yanked link to the
                         browsing history.
            group: The element types to hint.

                - `all`: All clickable elements.
                - `links`: Only links.
                - `images`: Only images.
                - `inputs`: Only input fields.

            target: What to do with the selected element.

                - `normal`: Open the link.
                - `current`: Open the link in the current tab.
                - `tab`: Open the link in a new tab (honoring the
                         background-tabs setting).
                - `tab-fg`: Open the link in a new foreground tab.
                - `tab-bg`: Open the link in a new background tab.
                - `window`: Open the link in a new window.
                - `hover` : Hover over the link.
                - `yank`: Yank the link to the clipboard.
                - `yank-primary`: Yank the link to the primary selection.
                - `run`: Run the argument as command.
                - `fill`: Fill the commandline with the command given as
                          argument.
                - `download`: Download the link.
                - `userscript`: Call a userscript with `$QUTE_URL` set to the
                                link.
                - `spawn`: Spawn a command.

            mode: The hinting mode to use.

                - `number`: Use numeric hints.
                - `letter`: Use the chars in the hints->chars settings.
                - `word`: Use hint words based on the html elements and the
                          extra words.

            *args: Arguments for spawn/userscript/run/fill.

                - With `spawn`: The executable and arguments to spawn.
                                `{hint-url}` will get replaced by the selected
                                URL.
                - With `userscript`: The userscript to execute. Either store
                                     the userscript in
                                     `~/.local/share/qutebrowser/userscripts`
                                     (or `$XDG_DATA_DIR`), or use an absolute
                                     path.
                - With `fill`: The command to fill the statusbar with.
                                `{hint-url}` will get replaced by the selected
                                URL.
                - With `run`: Same as `fill`.
        """
        tabbed_browser = objreg.get('tabbed-browser',
                                    scope='window',
                                    window=self._win_id)
        tab = tabbed_browser.currentWidget()
        if tab is None:
            raise cmdexc.CommandError("No WebView available yet!")

        mode_manager = objreg.get('mode-manager',
                                  scope='window',
                                  window=self._win_id)
        if mode_manager.mode == usertypes.KeyMode.hint:
            modeman.leave(win_id, usertypes.KeyMode.hint, 're-hinting')

        if rapid:
            if target in [
                    Target.tab_bg, Target.window, Target.run, Target.hover,
                    Target.userscript, Target.spawn, Target.download,
                    Target.normal, Target.current
            ]:
                pass
            elif (target == Target.tab
                  and config.get('tabs', 'background-tabs')):
                pass
            else:
                name = target.name.replace('_', '-')
                raise cmdexc.CommandError("Rapid hinting makes no sense with "
                                          "target {}!".format(name))

        if mode is None:
            mode = config.get('hints', 'mode')

        self._check_args(target, *args)
        self._context = HintContext()
        self._context.tab = tab
        self._context.target = target
        self._context.rapid = rapid
        self._context.hint_mode = mode
        self._context.add_history = add_history
        try:
            self._context.baseurl = tabbed_browser.current_url()
        except qtutils.QtValueError:
            raise cmdexc.CommandError("No URL set for this page yet!")
        self._context.args = args
        self._context.group = group
        selector = webelem.SELECTORS[self._context.group]
        self._context.tab.elements.find_css(selector,
                                            self._start_cb,
                                            only_visible=True)
Exemplo n.º 55
0
 def maybe_resize_completion(self):
     """Emit the resize_completion signal if the config says so."""
     if config.get('completion', 'shrink'):
         self.resize_completion.emit()
Exemplo n.º 56
0
 def minimumSizeHint(self):
     """Set the minimum height to the text height plus some padding."""
     padding = config.get('ui', 'statusbar-padding')
     width = super().minimumSizeHint().width()
     height = self.fontMetrics().height() + padding.top + padding.bottom
     return QSize(width, height)
Exemplo n.º 57
0
 def set_font(self):
     """Set the tabbar font."""
     self.setFont(config.get('fonts', 'tabbar'))
Exemplo n.º 58
0
def _init_modules(args, crash_handler):
    """Initialize all 'modules' which need to be initialized.

    Args:
        args: The argparse namespace.
        crash_handler: The CrashHandler instance.
    """
    # pylint: disable=too-many-statements
    log.init.debug("Initializing prompts...")
    prompt.init()

    log.init.debug("Initializing save manager...")
    save_manager = savemanager.SaveManager(qApp)
    objreg.register('save-manager', save_manager)
    save_manager.add_saveable('version', _save_version)

    log.init.debug("Initializing network...")
    networkmanager.init()

    if qtutils.version_check('5.8'):
        # Otherwise we can only initialize it for QtWebKit because of crashes
        log.init.debug("Initializing proxy...")
        proxy.init()

    log.init.debug("Initializing readline-bridge...")
    readline_bridge = readline.ReadlineBridge()
    objreg.register('readline-bridge', readline_bridge)

    log.init.debug("Initializing config...")
    config.init(qApp)
    save_manager.init_autosave()

    log.init.debug("Initializing web history...")
    history.init(qApp)

    log.init.debug("Initializing crashlog...")
    if not args.no_err_windows:
        crash_handler.handle_segfault()

    log.init.debug("Initializing sessions...")
    sessions.init(qApp)

    log.init.debug("Initializing websettings...")
    websettings.init(args)

    log.init.debug("Initializing adblock...")
    host_blocker = adblock.HostBlocker()
    host_blocker.read_hosts()
    objreg.register('host-blocker', host_blocker)

    log.init.debug("Initializing quickmarks...")
    quickmark_manager = urlmarks.QuickmarkManager(qApp)
    objreg.register('quickmark-manager', quickmark_manager)

    log.init.debug("Initializing bookmarks...")
    bookmark_manager = urlmarks.BookmarkManager(qApp)
    objreg.register('bookmark-manager', bookmark_manager)

    log.init.debug("Initializing cookies...")
    cookie_jar = cookies.CookieJar(qApp)
    ram_cookie_jar = cookies.RAMCookieJar(qApp)
    objreg.register('cookie-jar', cookie_jar)
    objreg.register('ram-cookie-jar', ram_cookie_jar)

    log.init.debug("Initializing cache...")
    diskcache = cache.DiskCache(standarddir.cache(), parent=qApp)
    objreg.register('cache', diskcache)

    log.init.debug("Initializing completions...")
    completionmodels.init()

    log.init.debug("Misc initialization...")
    if config.get('ui', 'hide-wayland-decoration'):
        os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1'
    else:
        os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None)
    macros.init()
    # Init backend-specific stuff
    browsertab.init()
Exemplo n.º 59
0
 def on_change(self):
     """Show tab bar when current tab got changed."""
     show = config.get('tabs', 'show')
     if show == 'switching':
         self.show()
         self._auto_hide_timer.start()
Exemplo n.º 60
0
 def set_font(self):
     """Set the tab bar font."""
     self.setFont(config.get('fonts', 'tabbar'))
     size = self.fontMetrics().height() - 2
     self.setIconSize(QSize(size, size))