Example #1
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)
Example #2
0
    def createRequest(self, _op, request, _outgoing_data):
        """Create a new request.

        Args:
             request: const QNetworkRequest & req
             _op: Operation op
             _outgoing_data: QIODevice * outgoingData

        Return:
            A QNetworkReply.
        """
        try:
            mimetype, data = qutescheme.data_for_url(request.url())
        except qutescheme.NoHandlerFound:
            errorstr = "No handler found for {}!".format(
                request.url().toDisplayString())
            return networkreply.ErrorNetworkReply(
                request, errorstr, QNetworkReply.ContentNotFoundError,
                self.parent())
        except qutescheme.QuteSchemeOSError as e:
            return networkreply.ErrorNetworkReply(
                request, str(e), QNetworkReply.ContentNotFoundError,
                self.parent())
        except qutescheme.QuteSchemeError as e:
            return networkreply.ErrorNetworkReply(request, e.errorstring,
                                                  e.error, self.parent())
        except qutescheme.Redirect as e:
            qtutils.ensure_valid(e.url)
            return networkreply.RedirectNetworkReply(e.url, self.parent())

        return networkreply.FixedDataNetworkReply(request, data, mimetype,
                                                  self.parent())
Example #3
0
    def resolve_url(self, baseurl):
        """Resolve the URL in the element's src/href attribute.

        Args:
            baseurl: The URL to base relative URLs on as QUrl.

        Return:
            A QUrl with the absolute URL, or None.
        """
        if baseurl.isRelative():
            raise ValueError("Need an absolute base URL!")

        for attr in ['href', 'src']:
            if attr in self:
                text = self[attr].strip()
                break
        else:
            return None

        url = QUrl(text)
        if not url.isValid():
            return None
        if url.isRelative():
            url = baseurl.resolved(url)
        qtutils.ensure_valid(url)
        return url
Example #4
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)
        tab_icon_size = opt.icon.actualSize(icon_size, icon_mode, icon_state)
        tab_icon_size = QSize(min(tab_icon_size.width(), icon_size.width()),
                              min(tab_icon_size.height(), icon_size.height()))
        icon_rect = QRect(text_rect.left(),
                          text_rect.center().y() - tab_icon_size.height() / 2,
                          tab_icon_size.width(), tab_icon_size.height())
        icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
        qtutils.ensure_valid(icon_rect)
        return icon_rect
def handler(request):
    """Scheme handler for qute:// URLs.

    Args:
        request: QNetworkRequest to answer to.

    Return:
        A QNetworkReply.
    """
    try:
        mimetype, data = qutescheme.data_for_url(request.url())
    except qutescheme.NoHandlerFound:
        errorstr = "No handler found for {}!".format(
            request.url().toDisplayString())
        return networkreply.ErrorNetworkReply(
            request, errorstr, QNetworkReply.ContentNotFoundError)
    except qutescheme.QuteSchemeOSError as e:
        return networkreply.ErrorNetworkReply(
            request, str(e), QNetworkReply.ContentNotFoundError)
    except qutescheme.QuteSchemeError as e:
        return networkreply.ErrorNetworkReply(request, e.errorstring, e.error)
    except qutescheme.Redirect as e:
        qtutils.ensure_valid(e.url)
        return networkreply.RedirectNetworkReply(e.url)

    return networkreply.FixedDataNetworkReply(request, data, mimetype)
Example #6
0
    def resolve(self, query, from_file=False):
        """Resolve a proxy via PAC.

        Args:
            query: QNetworkProxyQuery.
            from_file: Whether the proxy info is coming from a file.

        Return:
            A list of QNetworkProxy objects in order of preference.
        """
        qtutils.ensure_valid(query.url())

        if from_file:
            string_flags = QUrl.PrettyDecoded
        else:
            string_flags = QUrl.RemoveUserInfo
            if query.url().scheme() == 'https':
                string_flags |= QUrl.RemovePath | QUrl.RemoveQuery

        result = self._resolver.call([query.url().toString(string_flags),
                                      query.peerHostName()])
        result_str = result.toString()
        if not result.isString():
            err = "Got strange value from FindProxyForURL: '{}'"
            raise EvalProxyError(err.format(result_str))
        return self._parse_proxy_string(result_str)
    def requestStarted(self, job):
        """Handle a request for a qute: scheme.

        This method must be reimplemented by all custom URL scheme handlers.
        The request is asynchronous and does not need to be handled right away.

        Args:
            job: QWebEngineUrlRequestJob
        """
        url = job.requestUrl()

        if url.scheme() in ['chrome-error', 'chrome-extension']:
            # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378
            job.fail(QWebEngineUrlRequestJob.UrlInvalid)
            return

        if not self._check_initiator(job):
            return

        if job.requestMethod() != b'GET':
            job.fail(QWebEngineUrlRequestJob.RequestDenied)
            return

        assert url.scheme() == 'qute'

        log.misc.debug("Got request for {}".format(url.toDisplayString()))
        try:
            mimetype, data = qutescheme.data_for_url(url)
        except qutescheme.Error as e:
            errors = {
                qutescheme.NotFoundError:
                    QWebEngineUrlRequestJob.UrlNotFound,
                qutescheme.UrlInvalidError:
                    QWebEngineUrlRequestJob.UrlInvalid,
                qutescheme.RequestDeniedError:
                    QWebEngineUrlRequestJob.RequestDenied,
                qutescheme.SchemeOSError:
                    QWebEngineUrlRequestJob.UrlNotFound,
                qutescheme.Error:
                    QWebEngineUrlRequestJob.RequestFailed,
            }
            exctype = type(e)
            log.misc.error("{} while handling qute://* URL".format(
                exctype.__name__))
            job.fail(errors[exctype])
        except qutescheme.Redirect as e:
            qtutils.ensure_valid(e.url)
            job.redirect(e.url)
        else:
            log.misc.debug("Returning {} data".format(mimetype))

            # We can't just use the QBuffer constructor taking a QByteArray,
            # because that somehow segfaults...
            # https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
            buf = QBuffer(parent=self)
            buf.open(QIODevice.WriteOnly)
            buf.write(data)
            buf.seek(0)
            buf.close()
            job.reply(mimetype.encode('ascii'), buf)
    def sizeHint(self, option, index):
        """Override sizeHint of QStyledItemDelegate.

        Return the cell size based on the QTextDocument size, but might not
        work correctly yet.

        Args:
            option: const QStyleOptionViewItem & option
            index: const QModelIndex & index

        Return:
            A QSize with the recommended size.
        """
        value = index.data(Qt.SizeHintRole)
        if value is not None:
            return value
        self._opt = QStyleOptionViewItem(option)
        self.initStyleOption(self._opt, index)
        self._style = self._opt.widget.style()
        self._get_textdoc(index)
        docsize = self._doc.size().toSize()
        size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
                                            docsize, self._opt.widget)
        qtutils.ensure_valid(size)
        return size + QSize(10, 3)
Example #9
0
    def follow_prevnext(self, frame, baseurl, prev=False, tab=False, background=False, window=False):
        """Click a "previous"/"next" element on the page.

        Args:
            frame: The frame where the element is in.
            baseurl: The base URL of the current tab.
            prev: True to open a "previous" link, False to open a "next" link.
            tab: True to open in a new tab, False for the current tab.
            background: True to open in a background tab.
            window: True to open in a new window, False for the current one.
        """
        from qutebrowser.mainwindow import mainwindow

        elem = self._find_prevnext(frame, prev)
        if elem is None:
            raise cmdexc.CommandError("No {} links found!".format("prev" if prev else "forward"))
        url = self._resolve_url(elem, baseurl)
        if url is None:
            raise cmdexc.CommandError("No {} links found!".format("prev" if prev else "forward"))
        qtutils.ensure_valid(url)
        if window:
            new_window = mainwindow.MainWindow()
            new_window.show()
            tabbed_browser = objreg.get("tabbed-browser", scope="window", window=new_window.win_id)
            tabbed_browser.tabopen(url, background=False)
        elif tab:
            tabbed_browser = objreg.get("tabbed-browser", scope="window", window=self._win_id)
            tabbed_browser.tabopen(url, background=background)
        else:
            webview = objreg.get("webview", scope="tab", window=self._win_id, tab=self._tab_id)
            webview.openurl(url)
Example #10
0
    def _remove_tab(self, tab):
        """Remove a tab from the tab list and delete it properly.

        Args:
            tab: The QWebView to be closed.

        Raise:
            ValueError if the tab is not in the QTabWidget.
        """
        idx = self.indexOf(tab)
        if idx == -1:
            raise ValueError("tab {} is not contained in TabbedWidget!".format(
                tab))
        if tab is self._now_focused:
            self._now_focused = None
        if tab is objreg.get('last-focused-tab', None):
            objreg.delete('last-focused-tab')
        if not tab.cur_url.isEmpty():
            qtutils.ensure_valid(tab.cur_url)
            history_data = qtutils.serialize(tab.history())
            entry = UndoEntry(tab.cur_url, history_data)
            self._undo_stack.append(entry)
        tab.shutdown()
        self._tabs.remove(tab)
        self.removeTab(idx)
        tab.deleteLater()
Example #11
0
    def current_url(self):
        """Get the URL of the current tab.

        Intended to be used from command handlers.

        Return:
            The current URL as QUrl.

        Raise:
            CommandError if the current URL is invalid.
        """
        widget = self.currentWidget()
        if widget is None:
            url = QUrl()
        else:
            url = widget.cur_url
        try:
            qtutils.ensure_valid(url)
        except qtutils.QtValueError as e:
            msg = "Current URL is invalid"
            if e.reason:
                msg += " ({})".format(e.reason)
            msg += "!"
            raise cmdexc.CommandError(msg)
        return url
Example #12
0
    def _prevnext_cb(elems):
        elem = _find_prevnext(prev, elems)
        word = 'prev' if prev else 'forward'

        if elem is None:
            message.error(win_id, "No {} links found!".format(word))
            return
        url = elem.resolve_url(baseurl)
        if url is None:
            message.error(win_id, "No {} links found!".format(word))
            return
        qtutils.ensure_valid(url)

        if window:
            from qutebrowser.mainwindow import mainwindow
            new_window = mainwindow.MainWindow()
            new_window.show()
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=new_window.win_id)
            tabbed_browser.tabopen(url, background=False)
        elif tab:
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=win_id)
            tabbed_browser.tabopen(url, background=background)
        else:
            browsertab.openurl(url)
Example #13
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 {!r}".format(txt))
    engine, term = _parse_search_term(txt)
    assert term
    if engine is None:
        engine = 'DEFAULT'
    template = config.val.url.searchengines[engine]
    quoted_term = urllib.parse.quote(term, safe='')
    url = qurl_from_user_input(template.format(quoted_term))

    if config.val.url.open_base_url and term in config.val.url.searchengines:
        url = qurl_from_user_input(config.val.url.searchengines[term])
        url.setPath(None)
        url.setFragment(None)
        url.setQuery(None)
    qtutils.ensure_valid(url)
    return url
Example #14
0
def fuzzy_url(urlstr, cwd=None):
    """Get a QUrl based on an user input which is URL or search term.

    Args:
        urlstr: URL to load as a string.
        cwd: The current working directory, or None.

    Return:
        A target QUrl to a searchpage or the original URL.
    """
    if cwd:
        path = os.path.join(cwd, os.path.expanduser(urlstr))
    else:
        try:
            path = os.path.abspath(os.path.expanduser(urlstr))
        except OSError:
            path = None
    stripped = urlstr.strip()
    if path is not None and os.path.exists(path):
        log.url.debug("URL is a local file")
        url = QUrl.fromLocalFile(path)
    elif is_url(stripped):
        # probably an address
        log.url.debug("URL is a fuzzy address")
        url = qurl_from_user_input(urlstr)
    else:  # probably a search term
        log.url.debug("URL is a fuzzy search term")
        try:
            url = _get_search_url(urlstr)
        except ValueError:  # invalid search engine
            url = qurl_from_user_input(stripped)
    log.url.debug("Converting fuzzy term {} to URL -> {}".format(
                  urlstr, url.toDisplayString()))
    qtutils.ensure_valid(url)
    return url
Example #15
0
def fuzzy_url(urlstr):
    """Get a QUrl based on an user input which is URL or search term.

    Args:
        urlstr: URL to load as a string.

    Return:
        A target QUrl to a searchpage or the original URL.
    """
    path = os.path.abspath(os.path.expanduser(urlstr))
    stripped = urlstr.strip()
    if os.path.exists(path):
        log.url.debug("URL is a local file")
        url = QUrl.fromLocalFile(path)
    elif (not _has_explicit_scheme(QUrl(urlstr)) and
            os.path.exists(os.path.abspath(path))):
        # We do this here rather than in the first block because we first want
        # to make sure it's not an URL like http://, because os.path.abspath
        # would mangle that.
        log.url.debug("URL is a relative local file")
        url = QUrl.fromLocalFile(os.path.abspath(path))
    elif is_url(stripped):
        # probably an address
        log.url.debug("URL is a fuzzy address")
        url = qurl_from_user_input(urlstr)
    else:  # probably a search term
        log.url.debug("URL is a fuzzy search term")
        try:
            url = _get_search_url(urlstr)
        except ValueError:  # invalid search engine
            url = qurl_from_user_input(stripped)
    log.url.debug("Converting fuzzy term {} to URL -> {}".format(
                  urlstr, url.toDisplayString()))
    qtutils.ensure_valid(url)
    return url
Example #16
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
Example #17
0
    def lessThan(self, lindex, rindex):
        """Custom sorting implementation.

        Prefers all items which start with self._pattern. Other than that, uses
        normal Python string sorting.

        Args:
            lindex: The QModelIndex of the left item (*left* < right)
            rindex: The QModelIndex of the right item (left < *right*)

        Return:
            True if left < right, else False
        """
        qtutils.ensure_valid(lindex)
        qtutils.ensure_valid(rindex)

        left = self.srcmodel.data(lindex)
        right = self.srcmodel.data(rindex)

        leftstart = left.startswith(self._pattern)
        rightstart = right.startswith(self._pattern)

        if leftstart and not rightstart:
            return True
        elif rightstart and not leftstart:
            return False
        elif self._sort:
            return left < right
        else:
            return False
Example #18
0
    def _prevnext_cb(elems):
        if elems is None:
            message.error("There was an error while getting hint elements")
            return

        elem = _find_prevnext(prev, elems)
        word = 'prev' if prev else 'forward'

        if elem is None:
            message.error("No {} links found!".format(word))
            return
        url = elem.resolve_url(baseurl)
        if url is None:
            message.error("No {} links found!".format(word))
            return
        qtutils.ensure_valid(url)

        cur_tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=win_id)

        if window:
            new_window = mainwindow.MainWindow(
                private=cur_tabbed_browser.private)
            new_window.show()
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=new_window.win_id)
            tabbed_browser.tabopen(url, background=False)
        elif tab:
            cur_tabbed_browser.tabopen(url, background=background)
        else:
            browsertab.openurl(url)
Example #19
0
    def tabopen(self, url=None, background=None, explicit=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 explicitely.
                      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.
                          - Explicitely opened tabs are at the very right.

        Return:
            The opened WebView instance.
        """
        if url is not None:
            qtutils.ensure_valid(url)
        log.webview.debug("Creating new tab with URL {}".format(url))
        tab = webview.WebView(self)
        self._connect_tab_signals(tab)
        self._tabs.append(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))
        self.insertTab(idx, tab, "")
        if url is not None:
            tab.openurl(url)
        if background is None:
            background = config.get('tabs', 'background-tabs')
        if not background:
            self.setCurrentWidget(tab)
        tab.show()
        return tab
Example #20
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:
            self.tab_index_changed.emit(self.currentIndex(), self.count())
        else:
            self.setCurrentWidget(tab)
        tab.show()
        self.new_tab.emit(tab, idx)
        return tab
Example #21
0
 def first_item(self):
     """Return the index of the first child (non-category) in the model."""
     for row, cat in enumerate(self._categories):
         if cat.rowCount() > 0:
             parent = self.index(row, 0)
             index = self.index(0, 0, parent)
             qtutils.ensure_valid(index)
             return index
     return QModelIndex()
Example #22
0
 def first_item(self):
     """Return the first item in the model."""
     for i in range(self.rowCount()):
         cat = self.index(i, 0)
         qtutils.ensure_valid(cat)
         if cat.model().hasChildren(cat):
             index = self.index(0, 0, cat)
             qtutils.ensure_valid(index)
             return index
     return QModelIndex()
Example #23
0
 def connect_log_slot(obj):
     """Helper function to connect all signals to a logging slot."""
     metaobj = obj.metaObject()
     for i in range(metaobj.methodCount()):
         meta_method = metaobj.method(i)
         qtutils.ensure_valid(meta_method)
         if meta_method.methodType() == QMetaMethod.Signal:
             name = bytes(meta_method.name()).decode('ascii')
             signal = getattr(obj, name)
             signal.connect(functools.partial(log_slot, obj, signal))
Example #24
0
 def last_item(self):
     """Return the index of the last child (non-category) in the model."""
     for row, cat in reversed(list(enumerate(self._categories))):
         childcount = cat.rowCount()
         if childcount > 0:
             parent = self.index(row, 0)
             index = self.index(childcount - 1, 0, parent)
             qtutils.ensure_valid(index)
             return index
     return QModelIndex()
Example #25
0
    def _preset_cmd_text(self, url):
        """Preset a commandline text based on a hint URL.

        Args:
            url: The URL to open as a QUrl.
        """
        qtutils.ensure_valid(url)
        urlstr = url.toDisplayString(QUrl.FullyEncoded)
        args = self._context.get_args(urlstr)
        message.set_cmd_text(' '.join(args))
Example #26
0
 def sizeHint(self):
     """Return sizeHint based on the view contents."""
     idx = self.model().last_index()
     height = self.visualRect(idx).bottom()
     if height != -1:
         size = QSize(0, height + 2)
     else:
         size = QSize(0, 0)
     qtutils.ensure_valid(size)
     return size
Example #27
0
 def on_data_changed(self, download):
     """Emit data_changed signal when download data changed."""
     try:
         idx = self.downloads.index(download)
     except ValueError:
         # download has been deleted in the meantime
         return
     model_idx = self.index(idx, 0)
     qtutils.ensure_valid(model_idx)
     self.dataChanged.emit(model_idx, model_idx)
Example #28
0
def prompt_save(url):
    """Prompt for a new quickmark name to be added and add it.

    Args:
        url: The quickmark url as a QUrl.
    """
    qtutils.ensure_valid(url)
    urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
    message.ask_async("Add quickmark:", usertypes.PromptMode.text,
                      functools.partial(quickmark_add, urlstr))
Example #29
0
    def delete_url(self, url):
        """Remove all history entries with the given url.

        Args:
            url: URL string to delete.
        """
        qurl = QUrl(url)
        qtutils.ensure_valid(qurl)
        self.delete('url', self._format_url(qurl))
        self.completion.delete('url', self._format_completion_url(qurl))
Example #30
0
    def tabSizeHint(self, index: int):
        """Override tabSizeHint to customize qb's tab 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.val.tabs.width.bar)
            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 macOS.
            # We return it directly rather than setting `size' because we don't
            # want to ensure it's valid in this special case.
            return QSize()
        else:
            pinned = self._tab_pinned(index)
            pinned_count, pinned_width = self._pinned_statistics()
            no_pinned_count = self.count() - pinned_count
            no_pinned_width = self.width() - pinned_width

            if pinned:
                # Give pinned tabs the minimum size they need to display their
                # titles, let Qt handle scaling it down if we get too small.
                width = self.minimumTabSizeHint(index, ellipsis=False).width()
            else:
                width = no_pinned_width / no_pinned_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

            # If we don't have enough space, we return the minimum size so we
            # get scroll buttons as soon as needed.
            width = max(width, minimum_size.width())

            size = QSize(width, height)
        qtutils.ensure_valid(size)
        return size
Example #31
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 {!r}".format(txt))
    engine, term = _parse_search_term(txt)
    assert term
    if engine is None:
        engine = 'DEFAULT'
    template = config.val.url.searchengines[engine]
    url = qurl_from_user_input(template.format(urllib.parse.quote(term)))

    if config.val.url.open_base_url and term in config.val.url.searchengines:
        url = qurl_from_user_input(config.val.url.searchengines[term])
        url.setPath(None)
        url.setFragment(None)
        url.setQuery(None)
    qtutils.ensure_valid(url)
    return url
Example #32
0
def incdec(url, count, inc_or_dec):
    """Helper method for :navigate when `where' is increment/decrement.

    Args:
        url: The current url.
        count: How much to increment or decrement by.
        inc_or_dec: Either 'increment' or 'decrement'.
        tab: Whether to open the link in a new tab.
        background: Open the link in a new background tab.
        window: Open the link in a new window.
    """
    urlutils.ensure_valid(url)
    segments: Optional[Set[str]] = (set(config.val.url.incdec_segments))

    if segments is None:
        segments = {'path', 'query'}

    # Make a copy of the QUrl so we don't modify the original
    url = QUrl(url)
    # We're searching the last number so we walk the url segments backwards
    for segment, getter, setter in reversed(_URL_SEGMENTS):
        if segment not in segments:
            continue

        # Get the last number in a string not preceded by regex '%' or '%.'
        match = re.fullmatch(r'(.*\D|^)(?<!%)(?<!%.)(0*)(\d+)(.*)',
                             getter(url))
        if not match:
            continue

        setter(url, _get_incdec_value(match, inc_or_dec, count))
        qtutils.ensure_valid(url)

        return url

    raise Error("No number found in URL!")
Example #33
0
    def _save_tab(self, tab, active):
        """Get a dict with data for a single tab.

        Args:
            tab: The WebView to save.
            active: Whether the tab is currently active.
        """
        data = {'history': []}
        if active:
            data['active'] = True
        history = tab.page().history()
        for idx, item in enumerate(history.items()):
            qtutils.ensure_valid(item)
            item_data = {
                'url': bytes(item.url().toEncoded()).decode('ascii'),
                'title': item.title(),
            }
            if item.originalUrl() != item.url():
                encoded = item.originalUrl().toEncoded()
                item_data['original-url'] = bytes(encoded).decode('ascii')
            user_data = item.userData()
            if history.currentItemIndex() == idx:
                item_data['active'] = True
                if user_data is None:
                    pos = tab.page().mainFrame().scrollPosition()
                    data['zoom'] = tab.zoomFactor()
                    data['scroll-pos'] = {'x': pos.x(), 'y': pos.y()}
            data['history'].append(item_data)

            if user_data is not None:
                if 'zoom' in user_data:
                    data['zoom'] = user_data['zoom']
                if 'scroll-pos' in user_data:
                    pos = user_data['scroll-pos']
                    data['scroll-pos'] = {'x': pos.x(), 'y': pos.y()}
        return data
Example #34
0
def fuzzy_url(urlstr, cwd=None, relative=False, do_search=True):
    """Get a QUrl based on a user input which is URL or search term.

    Args:
        urlstr: URL to load as a string.
        cwd: The current working directory, or None.
        relative: Whether to resolve relative files.
        do_search: Whether to perform a search on non-URLs.

    Return:
        A target QUrl to a search page or the original URL.
    """
    urlstr = urlstr.strip()
    path = get_path_if_valid(urlstr, cwd=cwd, relative=relative,
                             check_exists=True)

    if path is not None:
        url = QUrl.fromLocalFile(path)
    elif (not do_search) or is_url(urlstr):
        # probably an address
        log.url.debug("URL is a fuzzy address")
        url = qurl_from_user_input(urlstr)
    else:  # probably a search term
        log.url.debug("URL is a fuzzy search term")
        try:
            url = _get_search_url(urlstr)
        except ValueError:  # invalid search engine
            url = qurl_from_user_input(urlstr)
    log.url.debug("Converting fuzzy term {!r} to URL -> {}".format(
                  urlstr, url.toDisplayString()))
    if do_search and config.get('general', 'auto-search') and urlstr:
        qtutils.ensure_valid(url)
    else:
        if not url.isValid():
            raise InvalidUrlError(url)
    return url
Example #35
0
def _get_search_url(txt: str) -> QUrl:
    """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 {!r}".format(txt))
    engine, term = _parse_search_term(txt)
    if not engine:
        engine = 'DEFAULT'
    if term:
        template = config.val.url.searchengines[engine]
        quoted_term = urllib.parse.quote(term, safe='')
        url = qurl_from_user_input(template.format(quoted_term))
    else:
        url = qurl_from_user_input(config.val.url.searchengines[engine])
        url.setPath(None)  # type: ignore
        url.setFragment(None)  # type: ignore
        url.setQuery(None)  # type: ignore
    qtutils.ensure_valid(url)
    return url
Example #36
0
    def present(self, qt_notification: "QWebEngineNotification") -> None:
        """Show a notification using the configured adapter.

        Lazily initializes a suitable adapter if none exists yet.

        This should *not* be directly passed to setNotificationPresenter on
        PyQtWebEngine < 5.15 because of a bug in the PyQtWebEngine bindings.
        """
        if self._adapter is None:
            self._init_adapter()
            assert self._adapter is not None

        replaces_id = self._find_replaces_id(qt_notification)
        qtutils.ensure_valid(qt_notification.origin())

        notification_id = self._adapter.present(
            qt_notification, replaces_id=replaces_id)
        log.misc.debug(f"New notification ID from adapter: {notification_id}")

        if self._adapter is None:
            # If a fatal error occurred, we replace the adapter via its "error" signal.
            log.misc.debug("Adapter vanished, bailing out")  # type: ignore[unreachable]
            return

        if notification_id <= 0:
            raise Error(f"Got invalid notification id {notification_id}")

        if replaces_id is None:
            if notification_id in self._active_notifications:
                raise Error(f"Got duplicate id {notification_id}")

        qt_notification.show()
        self._active_notifications[notification_id] = qt_notification

        qt_notification.closed.connect(  # type: ignore[attr-defined]
            functools.partial(self._adapter.on_web_closed, notification_id))
Example #37
0
    def _resolve_url(self, elem, baseurl=None):
        """Resolve a URL and check if we want to keep it.

        Args:
            elem: The QWebElement to get the URL of.
            baseurl: The baseurl of the current tab (overrides baseurl from
                     self._context).

        Return:
            A QUrl with the absolute URL, or None.
        """
        try:
            text = elem['href']
        except KeyError:
            return None
        url = QUrl(text)
        if not url.isValid():
            return None
        if url.isRelative():
            if baseurl is None:
                baseurl = self._context.baseurl
            url = baseurl.resolved(url)
        qtutils.ensure_valid(url)
        return url
Example #38
0
    def _resolve_url(self, elem, baseurl):
        """Resolve a URL and check if we want to keep it.

        Args:
            elem: The QWebElement to get the URL of.
            baseurl: The baseurl of the current tab.

        Return:
            A QUrl with the absolute URL, or None.
        """
        for attr in ('href', 'src'):
            if attr in elem:
                text = elem[attr].strip()
                break
        else:
            return None

        url = QUrl(text)
        if not url.isValid():
            return None
        if url.isRelative():
            url = baseurl.resolved(url)
        qtutils.ensure_valid(url)
        return url
Example #39
0
    def _prevnext_cb(elems):
        if elems is None:
            message.error("Unknown error while getting hint elements")
            return
        elif isinstance(elems, webelem.Error):
            message.error(str(elems))
            return

        elem = _find_prevnext(prev, elems)
        word = 'prev' if prev else 'forward'

        if elem is None:
            message.error("No {} links found!".format(word))
            return
        url = elem.resolve_url(baseurl)
        if url is None:
            message.error("No {} links found!".format(word))
            return
        qtutils.ensure_valid(url)

        cur_tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=win_id)

        if window:
            new_window = mainwindow.MainWindow(
                private=cur_tabbed_browser.is_private)
            new_window.show()
            tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=new_window.win_id)
            tabbed_browser.tabopen(url, background=False)
        elif tab:
            cur_tabbed_browser.tabopen(url, background=background)
        else:
            browsertab.openurl(url)
Example #40
0
    def _save_tab(self, tab, active):
        """Get a dict with data for a single tab.

        Args:
            tab: The WebView to save.
            active: Whether the tab is currently active.
        """
        # FIXME understand why this happens
        if tab is None:
            return {}
        data = {'history': []}
        if active:
            data['active'] = True
        for idx, item in enumerate(tab.history):
            qtutils.ensure_valid(item)
            item_data = self._save_tab_item(tab, idx, item)
            if item.url().scheme() == 'qute' and item.url().host() == 'back':
                # don't add qute://back to the session file
                if item_data.get('active', False) and data['history']:
                    # mark entry before qute://back as active
                    data['history'][-1]['active'] = True
            else:
                data['history'].append(item_data)
        return data
Example #41
0
    def lessThan(self, lindex, rindex):
        """Custom sorting implementation.

        Prefers all items which start with self.pattern. Other than that, uses
        normal Python string sorting.

        Args:
            lindex: The QModelIndex of the left item (*left* < right)
            rindex: The QModelIndex of the right item (left < *right*)

        Return:
            True if left < right, else False
        """
        qtutils.ensure_valid(lindex)
        qtutils.ensure_valid(rindex)

        left_sort = self.srcmodel.data(lindex, role=completion.Role.sort)
        right_sort = self.srcmodel.data(rindex, role=completion.Role.sort)

        if left_sort is not None and right_sort is not None:
            return left_sort < right_sort

        left = self.srcmodel.data(lindex)
        right = self.srcmodel.data(rindex)

        leftstart = left.startswith(self.pattern)
        rightstart = right.startswith(self.pattern)

        if leftstart and rightstart:
            return left < right
        elif leftstart:
            return True
        elif rightstart:
            return False
        else:
            return left < right
Example #42
0
    def follow_prevnext(self, frame, baseurl, prev=False, tab=False,
                        background=False, window=False):
        """Click a "previous"/"next" element on the page.

        Args:
            frame: The frame where the element is in.
            baseurl: The base URL of the current tab.
            prev: True to open a "previous" link, False to open a "next" link.
            tab: True to open in a new tab, False for the current tab.
            background: True to open in a background tab.
            window: True to open in a new window, False for the current one.
        """
        from qutebrowser.mainwindow import mainwindow
        elem = self._find_prevnext(frame, prev)
        if elem is None:
            raise cmdexc.CommandError("No {} links found!".format(
                "prev" if prev else "forward"))
        url = self._resolve_url(elem, baseurl)
        if url is None:
            raise cmdexc.CommandError("No {} links found!".format(
                "prev" if prev else "forward"))
        qtutils.ensure_valid(url)
        if window:
            new_window = mainwindow.MainWindow()
            new_window.show()
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=new_window.win_id)
            tabbed_browser.tabopen(url, background=False)
        elif tab:
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=self._win_id)
            tabbed_browser.tabopen(url, background=background)
        else:
            webview = objreg.get('webview', scope='tab', window=self._win_id,
                                 tab=self._tab_id)
            webview.openurl(url)
Example #43
0
def interpolate_color(
        start: QColor,
        end: QColor,
        percent: int,
        colorspace: typing.Optional[QColor.Spec] = QColor.Rgb
) -> QColor:
    """Get an interpolated color value.

    Args:
        start: The start color.
        end: The end color.
        percent: Which value to get (0 - 100)
        colorspace: The desired interpolation color system,
                    QColor::{Rgb,Hsv,Hsl} (from QColor::Spec enum)
                    If None, start is used except when percent is 100.

    Return:
        The interpolated QColor, with the same spec as the given start color.
    """
    qtutils.ensure_valid(start)
    qtutils.ensure_valid(end)

    if colorspace is None:
        if percent == 100:
            return QColor(*end.getRgb())
        else:
            return QColor(*start.getRgb())

    out = QColor()
    if colorspace == QColor.Rgb:
        a_c1, a_c2, a_c3, _alpha = start.getRgb()
        b_c1, b_c2, b_c3, _alpha = end.getRgb()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setRgb(*components)
    elif colorspace == QColor.Hsv:
        a_c1, a_c2, a_c3, _alpha = start.getHsv()
        b_c1, b_c2, b_c3, _alpha = end.getHsv()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setHsv(*components)
    elif colorspace == QColor.Hsl:
        a_c1, a_c2, a_c3, _alpha = start.getHsl()
        b_c1, b_c2, b_c3, _alpha = end.getHsl()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setHsl(*components)
    else:
        raise ValueError("Invalid colorspace!")
    out = out.convertTo(start.spec())
    qtutils.ensure_valid(out)
    return out
Example #44
0
    def delete_cur_item(self, completion):
        """Delete the selected item.

        Args:
            completion: The Completion object to use.
        """
        index = completion.currentIndex()
        qtutils.ensure_valid(index)
        url = index.data()
        category = index.parent()
        qtutils.ensure_valid(category)

        if category.data() == 'Bookmarks':
            bookmark_manager = objreg.get('bookmark-manager')
            bookmark_manager.delete(url)
        elif category.data() == 'Quickmarks':
            quickmark_manager = objreg.get('quickmark-manager')
            sibling = index.sibling(index.row(), self.TEXT_COLUMN)
            qtutils.ensure_valid(sibling)
            name = sibling.data()
            quickmark_manager.quickmark_del(name)
Example #45
0
def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
    """Get an interpolated color value.

    Args:
        start: The start color.
        end: The end color.
        percent: Which value to get (0 - 100)
        colorspace: The desired interpolation colorsystem,
                    QColor::{Rgb,Hsv,Hsl} (from QColor::Spec enum)

    Return:
        The interpolated QColor, with the same spec as the given start color.
    """
    qtutils.ensure_valid(start)
    qtutils.ensure_valid(end)
    out = QColor()
    if colorspace == QColor.Rgb:
        a_c1, a_c2, a_c3, _alpha = start.getRgb()
        b_c1, b_c2, b_c3, _alpha = end.getRgb()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setRgb(*components)
    elif colorspace == QColor.Hsv:
        a_c1, a_c2, a_c3, _alpha = start.getHsv()
        b_c1, b_c2, b_c3, _alpha = end.getHsv()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setHsv(*components)
    elif colorspace == QColor.Hsl:
        a_c1, a_c2, a_c3, _alpha = start.getHsl()
        b_c1, b_c2, b_c3, _alpha = end.getHsl()
        components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
                                           percent)
        out.setHsl(*components)
    else:
        raise ValueError("Invalid colorspace!")
    out = out.convertTo(start.spec())
    qtutils.ensure_valid(out)
    return out
Example #46
0
 def _on_before_load_started(self, url: QUrl) -> None:
     """Adjust the title if we are going to visit a URL soon."""
     qtutils.ensure_valid(url)
     url_string = url.toDisplayString()
     log.webview.debug("Going to start loading: {}".format(url_string))
     self.title_changed.emit(url_string)
Example #47
0
    def tabopen(
        self,
        url: QUrl = None,
        background: bool = None,
        related: bool = True,
        idx: int = None,
    ) -> browsertab.AbstractTab:
        """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 `tabs.background` setting decides.
            related: Whether the tab was opened from another existing tab.
                     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 (related=True).
                         - Explicitly opened tabs are at the very right
                           (related=False)
            idx: The index where the new tab should be opened.

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

        prev_focus = QApplication.focusWidget()

        if config.val.tabs.tabs_are_windows and self.widget.count() > 0:
            window = mainwindow.MainWindow(private=self.is_private)
            window.show()
            tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=window.win_id)
            return tabbed_browser.tabopen(url=url,
                                          background=background,
                                          related=related)

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

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

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

        if background is None:
            background = config.val.tabs.background
        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.
            tab.resize(self.widget.currentWidget().size())
            self.widget.tab_index_changed.emit(self.widget.currentIndex(),
                                               self.widget.count())
            # Refocus webview in case we lost it by spawning a bg tab
            self.widget.currentWidget().setFocus()
        else:
            self.widget.setCurrentWidget(tab)

        mode = modeman.instance(self._win_id).mode
        if mode in [
                usertypes.KeyMode.command, usertypes.KeyMode.prompt,
                usertypes.KeyMode.yesno
        ]:
            # If we were in a command prompt, restore old focus
            # The above commands need to be run to switch tabs
            if prev_focus is not None:
                prev_focus.setFocus()

        tab.show()
        self.new_tab.emit(tab, idx)
        return tab
Example #48
0
 def _load_url_prepare(self, url: QUrl) -> None:
     qtutils.ensure_valid(url)
     self.before_load_started.emit(url)
Example #49
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
Example #50
0
def data_url(mimetype: str, data: bytes) -> QUrl:
    """Get a data: QUrl for the given data."""
    b64 = base64.b64encode(data).decode('ascii')
    url = QUrl('data:{};base64,{}'.format(mimetype, b64))
    qtutils.ensure_valid(url)
    return url
Example #51
0
 def _load_url_prepare(self, url: QUrl, *,
                       emit_before_load_started: bool = True) -> None:
     qtutils.ensure_valid(url)
     if emit_before_load_started:
         self.before_load_started.emit(url)
Example #52
0
 def on_data_changed(self, download):
     """Emit data_changed signal when download data changed."""
     idx = self.downloads.index(download)
     model_idx = self.index(idx, 0)
     qtutils.ensure_valid(model_idx)
     self.dataChanged.emit(model_idx, model_idx)
Example #53
0
 def _on_predicted_navigation(self, url):
     """Adjust the title if we are going to visit an URL soon."""
     qtutils.ensure_valid(url)
     url_string = url.toDisplayString()
     log.webview.debug("Predicted navigation: {}".format(url_string))
     self.title_changed.emit(url_string)
Example #54
0
 def _openurl_prepare(self, url, *, predict=True):
     qtutils.ensure_valid(url)
     if predict:
         self.predicted_navigation.emit(url)
Example #55
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
Example #56
0
 def resizeEvent(self, e):
     """Extend QLabel::resizeEvent to update the elided text afterwards."""
     super().resizeEvent(e)
     size = e.size()
     qtutils.ensure_valid(size)
     self._update_elided_text(size.width())
Example #57
0
    def tabopen(self,
                url=None,
                background=None,
                related=True,
                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 `tabs.background_tabs`` setting decides.
            related: Whether the tab was opened from another existing tab.
                     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 (related=True).
                         - Explicitly opened tabs are at the very right
                           (related=False)
            idx: The index where the new tab should be opened.
            ignore_tabs_are_windows: If given, never open a new window, even
                                     with tabs.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 {}, "
                          "related {}, idx {}".format(url, background, related,
                                                      idx))

        if (config.val.tabs.tabs_are_windows and self.count() > 0
                and not ignore_tabs_are_windows):
            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=url,
                                          background=background,
                                          related=related)

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

        # this was necessary to remove otherwise it was making a hell of a mess in tree structure
        # if idx is None:
        #     idx = self._get_new_tab_idx(related)
        idx = self._get_new_tab_idx(related)

        self.insertTab(idx, tab, "")

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

        if background is None:
            background = config.val.tabs.background
        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.
            tab.resize(self.currentWidget().size())
            self.tab_index_changed.emit(self.currentIndex(), self.count())
        else:
            self.setCurrentWidget(tab)

        tab.show()
        self.new_tab.emit(tab, idx)
        return tab
Example #58
0
 def __init__(self, atime, url, title, redirect=False):
     self.atime = float(atime)
     self.url = url
     self.title = title
     self.redirect = redirect
     qtutils.ensure_valid(url)
Example #59
0
 def _openurl_prepare(self, url: QUrl, *, predict: bool = True) -> None:
     qtutils.ensure_valid(url)
     if predict:
         self.predicted_navigation.emit(url)
Example #60
0
 def _openurl_prepare(self, url):
     qtutils.ensure_valid(url)
     self.title_changed.emit(url.toDisplayString())