Beispiel #1
0
def format_args(args: Sequence = None, kwargs: Mapping = None) -> str:
    """Format a list of arguments/kwargs to a function-call like string."""
    if args is not None:
        arglist = [utils.compact_text(repr(arg), 200) for arg in args]
    else:
        arglist = []
    if kwargs is not None:
        for k, v in kwargs.items():
            arglist.append('{}={}'.format(k, utils.compact_text(repr(v), 200)))
    return ', '.join(arglist)
Beispiel #2
0
def format_args(args=None, kwargs=None):
    """Format a list of arguments/kwargs to a function-call like string."""
    if args is not None:
        arglist = [utils.compact_text(repr(arg), 200) for arg in args]
    else:
        arglist = []
    if kwargs is not None:
        for k, v in kwargs.items():
            arglist.append('{}={}'.format(k, utils.compact_text(repr(v), 200)))
    return ', '.join(arglist)
Beispiel #3
0
 def __repr__(self) -> str:
     try:
         html = utils.compact_text(self.outer_xml(),
                                   500)  # type: typing.Optional[str]
     except Error:
         html = None
     return utils.get_repr(self, html=html)
Beispiel #4
0
    def _rect_on_view_js(self, adjust_zoom):
        """Javascript implementation for rect_on_view."""
        rects = self._elem.evaluateJavaScript("this.getClientRects()")
        if rects is None:  # pragma: no cover
            # Depending on unknown circumstances, this might not work with JS
            # disabled in QWebSettings:
            # https://github.com/The-Compiler/qutebrowser/issues/1641
            return None

        text = utils.compact_text(self._elem.toOuterXml(), 500)
        log.hints.vdebug("Client rectangles of element '{}': {}".format(
            text, rects))

        for i in range(int(rects.get("length", 0))):
            rect = rects[str(i)]
            width = rect.get("width", 0)
            height = rect.get("height", 0)
            if width > 1 and height > 1:
                # fix coordinates according to zoom level
                zoom = self._elem.webFrame().zoomFactor()
                if not config.get('ui', 'zoom-text-only') and adjust_zoom:
                    rect["left"] *= zoom
                    rect["top"] *= zoom
                    width *= zoom
                    height *= zoom
                rect = QRect(rect["left"], rect["top"], width, height)
                frame = self._elem.webFrame()
                while frame is not None:
                    # Translate to parent frames' position (scroll position
                    # is taken care of inside getClientRects)
                    rect.translate(frame.geometry().topLeft())
                    frame = frame.parentFrame()
                return rect

        return None
Beispiel #5
0
    def trace(frame, event, arg):
        """Trace function passed to sys.settrace.

        Return:
            Itself, so tracing continues.
        """
        if sys is not None:
            loc = '{}:{}'.format(frame.f_code.co_filename, frame.f_lineno)
            if arg is not None:
                arg = utils.compact_text(str(arg), 200)
            else:
                arg = ''
            print("{:11} {:80} {}".format(event, loc, arg), file=sys.stderr)
            return trace
        else:
            # When tracing while shutting down, it seems sys can be None
            # sometimes... if that's the case, we stop tracing.
            return None
Beispiel #6
0
    def trace(frame, event, arg):
        """Trace function passed to sys.settrace.

        Return:
            Itself, so tracing continues.
        """
        if sys is not None:
            loc = '{}:{}'.format(frame.f_code.co_filename, frame.f_lineno)
            if arg is not None:
                arg = utils.compact_text(str(arg), 200)
            else:
                arg = ''
            print("{:11} {:80} {}".format(event, loc, arg), file=sys.stderr)
            return trace
        else:
            # When tracing while shutting down, it seems sys can be None
            # sometimes... if that's the case, we stop tracing.
            return None
Beispiel #7
0
    def _rect_on_view_js(self) -> typing.Optional[QRect]:
        """Javascript implementation for rect_on_view."""
        # FIXME:qtwebengine maybe we can reuse this?
        rects = self._elem.evaluateJavaScript("this.getClientRects()")
        if rects is None:  # pragma: no cover
            # On e.g. Void Linux with musl libc, the stack size is too small
            # for jsc, and running JS will fail. If that happens, fall back to
            # the Python implementation.
            # https://github.com/qutebrowser/qutebrowser/issues/1641
            return None

        text = utils.compact_text(self._elem.toOuterXml(), 500)
        log.webelem.vdebug(  # type: ignore[attr-defined]
            "Client rectangles of element '{}': {}".format(text, rects))

        for i in range(int(rects.get("length", 0))):
            rect = rects[str(i)]
            width = rect.get("width", 0)
            height = rect.get("height", 0)
            if width > 1 and height > 1:
                # fix coordinates according to zoom level
                zoom = self._elem.webFrame().zoomFactor()
                if not config.val.zoom.text_only:
                    rect["left"] *= zoom
                    rect["top"] *= zoom
                    width *= zoom
                    height *= zoom
                rect = QRect(int(rect["left"]), int(rect["top"]), int(width),
                             int(height))

                frame = typing.cast(typing.Optional[QWebFrame],
                                    self._elem.webFrame())
                while frame is not None:
                    # Translate to parent frames' position (scroll position
                    # is taken care of inside getClientRects)
                    rect.translate(frame.geometry().topLeft())
                    frame = frame.parentFrame()

                return rect

        return None
    def _rect_on_view_js(self):
        """Javascript implementation for rect_on_view."""
        # FIXME:qtwebengine maybe we can reuse this?
        rects = self._elem.evaluateJavaScript("this.getClientRects()")
        if rects is None:  # pragma: no cover
            # On e.g. Void Linux with musl libc, the stack size is too small
            # for jsc, and running JS will fail. If that happens, fall back to
            # the Python implementation.
            # https://github.com/qutebrowser/qutebrowser/issues/1641
            return None

        text = utils.compact_text(self._elem.toOuterXml(), 500)
        log.webelem.vdebug("Client rectangles of element '{}': {}".format(
            text, rects))

        for i in range(int(rects.get("length", 0))):
            rect = rects[str(i)]
            width = rect.get("width", 0)
            height = rect.get("height", 0)
            if width > 1 and height > 1:
                # fix coordinates according to zoom level
                zoom = self._elem.webFrame().zoomFactor()
                if not config.get('ui', 'zoom-text-only'):
                    rect["left"] *= zoom
                    rect["top"] *= zoom
                    width *= zoom
                    height *= zoom
                rect = QRect(rect["left"], rect["top"], width, height)
                frame = self._elem.webFrame()
                while frame is not None:
                    # Translate to parent frames' position (scroll position
                    # is taken care of inside getClientRects)
                    rect.translate(frame.geometry().topLeft())
                    frame = frame.parentFrame()
                return rect

        return None
Beispiel #9
0
    def _rect_on_view_js(self):
        """Javascript implementation for rect_on_view."""
        # FIXME:qtwebengine maybe we can reuse this?
        rects = self._elem.evaluateJavaScript("this.getClientRects()")
        if rects is None:  # pragma: no cover
            # Depending on unknown circumstances, this might not work with JS
            # disabled in QWebSettings:
            # https://github.com/The-Compiler/qutebrowser/issues/1641
            return None

        text = utils.compact_text(self._elem.toOuterXml(), 500)
        log.hints.vdebug("Client rectangles of element '{}': {}".format(
            text, rects))

        for i in range(int(rects.get("length", 0))):
            rect = rects[str(i)]
            width = rect.get("width", 0)
            height = rect.get("height", 0)
            if width > 1 and height > 1:
                # fix coordinates according to zoom level
                zoom = self._elem.webFrame().zoomFactor()
                if not config.get('ui', 'zoom-text-only'):
                    rect["left"] *= zoom
                    rect["top"] *= zoom
                    width *= zoom
                    height *= zoom
                rect = QRect(rect["left"], rect["top"], width, height)
                frame = self._elem.webFrame()
                while frame is not None:
                    # Translate to parent frames' position (scroll position
                    # is taken care of inside getClientRects)
                    rect.translate(frame.geometry().topLeft())
                    frame = frame.parentFrame()
                return rect

        return None
Beispiel #10
0
 def debug_text(self):
     """Get a text based on an element suitable for debug output."""
     self._check_vanished()
     return utils.compact_text(self._elem.toOuterXml(), 500)
Beispiel #11
0
 def __repr__(self):
     try:
         html = utils.compact_text(self.outer_xml(), 500)
     except Error:
         html = None
     return utils.get_repr(self, html=html)
Beispiel #12
0
 def debug_text(self):
     """Get a text based on an element suitable for debug output."""
     return utils.compact_text(self.outer_xml(), 500)
Beispiel #13
0
    def rect_on_view(self, *, elem_geometry=None, adjust_zoom=True,
                     no_js=False):
        """Get the geometry of the element relative to the webview.

        Uses the getClientRects() JavaScript method to obtain the collection of
        rectangles containing the element and returns the first rectangle which
        is large enough (larger than 1px times 1px). If all rectangles returned
        by getClientRects() are too small, falls back to elem.rect_on_view().

        Skipping of small rectangles is due to <a> elements containing other
        elements with "display:block" style, see
        https://github.com/The-Compiler/qutebrowser/issues/1298

        Args:
            elem_geometry: The geometry of the element, or None.
                           Calling QWebElement::geometry is rather expensive so
                           we want to avoid doing it twice.
            adjust_zoom: Whether to adjust the element position based on the
                         current zoom level.
            no_js: Fall back to the Python implementation
        """
        self._check_vanished()

        # First try getting the element rect via JS, as that's usually more
        # accurate
        if elem_geometry is None and not no_js:
            rects = self._elem.evaluateJavaScript("this.getClientRects()")
            text = utils.compact_text(self._elem.toOuterXml(), 500)
            log.hints.vdebug("Client rectangles of element '{}': {}".format(
                text, rects))
            for i in range(int(rects.get("length", 0))):
                rect = rects[str(i)]
                width = rect.get("width", 0)
                height = rect.get("height", 0)
                if width > 1 and height > 1:
                    # fix coordinates according to zoom level
                    zoom = self._elem.webFrame().zoomFactor()
                    if not config.get('ui', 'zoom-text-only') and adjust_zoom:
                        rect["left"] *= zoom
                        rect["top"] *= zoom
                        width *= zoom
                        height *= zoom
                    rect = QRect(rect["left"], rect["top"], width, height)
                    frame = self._elem.webFrame()
                    while frame is not None:
                        # Translate to parent frames' position (scroll position
                        # is taken care of inside getClientRects)
                        rect.translate(frame.geometry().topLeft())
                        frame = frame.parentFrame()
                    return rect

        # No suitable rects found via JS, try via the QWebElement API
        if elem_geometry is None:
            geometry = self._elem.geometry()
        else:
            geometry = elem_geometry
        frame = self._elem.webFrame()
        rect = QRect(geometry)
        while frame is not None:
            rect.translate(frame.geometry().topLeft())
            rect.translate(frame.scrollPosition() * -1)
            frame = frame.parentFrame()
        # We deliberately always adjust the zoom here, even with
        # adjust_zoom=False
        if elem_geometry is None:
            zoom = self._elem.webFrame().zoomFactor()
            if not config.get('ui', 'zoom-text-only'):
                rect.moveTo(rect.left() / zoom, rect.top() / zoom)
                rect.setWidth(rect.width() / zoom)
                rect.setHeight(rect.height() / zoom)
        return rect
Beispiel #14
0
 def __repr__(self):
     try:
         html = utils.compact_text(self.outer_xml(), 500)
     except Error:
         html = None
     return utils.get_repr(self, html=html)
Beispiel #15
0
def rect_on_view(elem, *, elem_geometry=None, adjust_zoom=True, no_js=False):
    """Get the geometry of the element relative to the webview.

    We need this as a standalone function (as opposed to a WebElementWrapper
    method) because we want to run is_visible before wrapping when hinting for
    performance reasons.

    Uses the getClientRects() JavaScript method to obtain the collection of
    rectangles containing the element and returns the first rectangle which is
    large enough (larger than 1px times 1px). If all rectangles returned by
    getClientRects() are too small, falls back to elem.rect_on_view().

    Skipping of small rectangles is due to <a> elements containing other
    elements with "display:block" style, see
    https://github.com/The-Compiler/qutebrowser/issues/1298

    Args:
        elem: The QWebElement to get the rect for.
        elem_geometry: The geometry of the element, or None.
                       Calling QWebElement::geometry is rather expensive so we
                       want to avoid doing it twice.
        adjust_zoom: Whether to adjust the element position based on the
                     current zoom level.
        no_js: Fall back to the Python implementation
    """
    if elem.isNull():
        raise IsNullError("Got called on a null element!")

    # First try getting the element rect via JS, as that's usually more
    # accurate
    if elem_geometry is None and not no_js:
        rects = elem.evaluateJavaScript("this.getClientRects()")
        text = utils.compact_text(elem.toOuterXml(), 500)
        log.hints.vdebug("Client rectangles of element '{}': {}".format(
            text, rects))
        for i in range(int(rects.get("length", 0))):
            rect = rects[str(i)]
            width = rect.get("width", 0)
            height = rect.get("height", 0)
            if width > 1 and height > 1:
                # fix coordinates according to zoom level
                zoom = elem.webFrame().zoomFactor()
                if not config.get('ui', 'zoom-text-only') and adjust_zoom:
                    rect["left"] *= zoom
                    rect["top"] *= zoom
                    width *= zoom
                    height *= zoom
                rect = QRect(rect["left"], rect["top"], width, height)
                frame = elem.webFrame()
                while frame is not None:
                    # Translate to parent frames' position
                    # (scroll position is taken care of inside getClientRects)
                    rect.translate(frame.geometry().topLeft())
                    frame = frame.parentFrame()
                return rect

    # No suitable rects found via JS, try via the QWebElement API
    if elem_geometry is None:
        geometry = elem.geometry()
    else:
        geometry = elem_geometry
    frame = elem.webFrame()
    rect = QRect(geometry)
    while frame is not None:
        rect.translate(frame.geometry().topLeft())
        rect.translate(frame.scrollPosition() * -1)
        frame = frame.parentFrame()
    # We deliberately always adjust the zoom here, even with adjust_zoom=False
    if elem_geometry is None:
        zoom = elem.webFrame().zoomFactor()
        if not config.get('ui', 'zoom-text-only'):
            rect.moveTo(rect.left() / zoom, rect.top() / zoom)
            rect.setWidth(rect.width() / zoom)
            rect.setHeight(rect.height() / zoom)
    return rect
Beispiel #16
0
 def debug_text(self):
     """Get a text based on an element suitable for debug output."""
     return utils.compact_text(self.outer_xml(), 500)
Beispiel #17
0
 def debug_text(self):
     """Get a text based on an element suitable for debug output."""
     self._check_vanished()
     return utils.compact_text(self._elem.toOuterXml(), 500)