webelem: Make it possible to use is_visible with unwrapped elements.
This commit is contained in:
parent
bc884ed51e
commit
2686278b48
@ -164,58 +164,11 @@ class WebElementWrapper(collections.abc.MutableMapping):
|
|||||||
Return:
|
Return:
|
||||||
True if the element is visible, False otherwise.
|
True if the element is visible, False otherwise.
|
||||||
"""
|
"""
|
||||||
self._check_vanished()
|
return is_visible(self._elem, mainframe)
|
||||||
# CSS attributes which hide an element
|
|
||||||
hidden_attributes = {
|
|
||||||
'visibility': 'hidden',
|
|
||||||
'display': 'none',
|
|
||||||
}
|
|
||||||
for k, v in hidden_attributes.items():
|
|
||||||
if self._elem.styleProperty(k, QWebElement.ComputedStyle) == v:
|
|
||||||
return False
|
|
||||||
geometry = self._elem.geometry()
|
|
||||||
if not geometry.isValid() and geometry.x() == 0:
|
|
||||||
# Most likely an invisible link
|
|
||||||
return False
|
|
||||||
# First check if the element is visible on screen
|
|
||||||
elem_rect = self.rect_on_view()
|
|
||||||
if elem_rect.isValid():
|
|
||||||
visible_on_screen = mainframe.geometry().intersects(elem_rect)
|
|
||||||
else:
|
|
||||||
# We got an invalid rectangle (width/height 0/0 probably), but this
|
|
||||||
# can still be a valid link.
|
|
||||||
visible_on_screen = mainframe.geometry().contains(
|
|
||||||
elem_rect.topLeft())
|
|
||||||
# Then check if it's visible in its frame if it's not in the main
|
|
||||||
# frame.
|
|
||||||
elem_frame = self._elem.webFrame()
|
|
||||||
elem_rect = self._elem.geometry()
|
|
||||||
framegeom = QRect(elem_frame.geometry())
|
|
||||||
if not framegeom.isValid():
|
|
||||||
visible_in_frame = False
|
|
||||||
elif elem_frame.parentFrame() is not None:
|
|
||||||
framegeom.moveTo(0, 0)
|
|
||||||
framegeom.translate(elem_frame.scrollPosition())
|
|
||||||
if elem_rect.isValid():
|
|
||||||
visible_in_frame = framegeom.intersects(elem_rect)
|
|
||||||
else:
|
|
||||||
# We got an invalid rectangle (width/height 0/0 probably), but
|
|
||||||
# this can still be a valid link.
|
|
||||||
visible_in_frame = framegeom.contains(elem_rect.topLeft())
|
|
||||||
else:
|
|
||||||
visible_in_frame = visible_on_screen
|
|
||||||
return all([visible_on_screen, visible_in_frame])
|
|
||||||
|
|
||||||
def rect_on_view(self):
|
def rect_on_view(self):
|
||||||
"""Get the geometry of the element relative to the webview."""
|
"""Get the geometry of the element relative to the webview."""
|
||||||
self._check_vanished()
|
return rect_on_view(self._elem)
|
||||||
frame = self._elem.webFrame()
|
|
||||||
rect = QRect(self._elem.geometry())
|
|
||||||
while frame is not None:
|
|
||||||
rect.translate(frame.geometry().topLeft())
|
|
||||||
rect.translate(frame.scrollPosition() * -1)
|
|
||||||
frame = frame.parentFrame()
|
|
||||||
return rect
|
|
||||||
|
|
||||||
def is_writable(self):
|
def is_writable(self):
|
||||||
"""Check whether an element is writable."""
|
"""Check whether an element is writable."""
|
||||||
@ -381,3 +334,79 @@ def focus_elem(frame):
|
|||||||
"""
|
"""
|
||||||
elem = frame.findFirstElement(SELECTORS[Group.focus])
|
elem = frame.findFirstElement(SELECTORS[Group.focus])
|
||||||
return WebElementWrapper(elem)
|
return WebElementWrapper(elem)
|
||||||
|
|
||||||
|
|
||||||
|
def rect_on_view(elem):
|
||||||
|
"""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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
elem: The QWebElement to get the rect for.
|
||||||
|
"""
|
||||||
|
if elem.isNull():
|
||||||
|
raise IsNullError("Got called on a null element!")
|
||||||
|
frame = elem.webFrame()
|
||||||
|
rect = QRect(elem.geometry())
|
||||||
|
while frame is not None:
|
||||||
|
rect.translate(frame.geometry().topLeft())
|
||||||
|
rect.translate(frame.scrollPosition() * -1)
|
||||||
|
frame = frame.parentFrame()
|
||||||
|
return rect
|
||||||
|
|
||||||
|
|
||||||
|
def is_visible(elem, mainframe):
|
||||||
|
"""Check if the given element is visible in the frame.
|
||||||
|
|
||||||
|
We need this as a standalone function (as opposed to a WebElementWrapper
|
||||||
|
method) because we want to check this before wrapping when hinting for
|
||||||
|
performance reasons.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
elem: The QWebElement to check.
|
||||||
|
mainframe: The QWebFrame in which the element should be visible.
|
||||||
|
"""
|
||||||
|
if elem.isNull():
|
||||||
|
raise IsNullError("Got called on a null element!")
|
||||||
|
# CSS attributes which hide an element
|
||||||
|
hidden_attributes = {
|
||||||
|
'visibility': 'hidden',
|
||||||
|
'display': 'none',
|
||||||
|
}
|
||||||
|
for k, v in hidden_attributes.items():
|
||||||
|
if elem.styleProperty(k, QWebElement.ComputedStyle) == v:
|
||||||
|
return False
|
||||||
|
geometry = elem.geometry()
|
||||||
|
if not geometry.isValid() and geometry.x() == 0:
|
||||||
|
# Most likely an invisible link
|
||||||
|
return False
|
||||||
|
# First check if the element is visible on screen
|
||||||
|
elem_rect = rect_on_view(elem)
|
||||||
|
if elem_rect.isValid():
|
||||||
|
visible_on_screen = mainframe.geometry().intersects(elem_rect)
|
||||||
|
else:
|
||||||
|
# We got an invalid rectangle (width/height 0/0 probably), but this
|
||||||
|
# can still be a valid link.
|
||||||
|
visible_on_screen = mainframe.geometry().contains(
|
||||||
|
elem_rect.topLeft())
|
||||||
|
# Then check if it's visible in its frame if it's not in the main
|
||||||
|
# frame.
|
||||||
|
elem_frame = elem.webFrame()
|
||||||
|
elem_rect = elem.geometry()
|
||||||
|
framegeom = QRect(elem_frame.geometry())
|
||||||
|
if not framegeom.isValid():
|
||||||
|
visible_in_frame = False
|
||||||
|
elif elem_frame.parentFrame() is not None:
|
||||||
|
framegeom.moveTo(0, 0)
|
||||||
|
framegeom.translate(elem_frame.scrollPosition())
|
||||||
|
if elem_rect.isValid():
|
||||||
|
visible_in_frame = framegeom.intersects(elem_rect)
|
||||||
|
else:
|
||||||
|
# We got an invalid rectangle (width/height 0/0 probably), but
|
||||||
|
# this can still be a valid link.
|
||||||
|
visible_in_frame = framegeom.contains(elem_rect.topLeft())
|
||||||
|
else:
|
||||||
|
visible_in_frame = visible_on_screen
|
||||||
|
return all([visible_on_screen, visible_in_frame])
|
||||||
|
Loading…
Reference in New Issue
Block a user