Use QWebElement API to set hint elem style.

See #225.
This commit is contained in:
Florian Bruhin 2014-10-29 22:49:46 +01:00
parent 2937fb9232
commit 8e0e33e89a

View File

@ -20,7 +20,6 @@
"""A HintManager to draw hints over links.""" """A HintManager to draw hints over links."""
import math import math
import functools
import subprocess import subprocess
import collections import collections
@ -28,6 +27,7 @@ import sip
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl
from PyQt5.QtGui import QMouseEvent, QClipboard from PyQt5.QtGui import QMouseEvent, QClipboard
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKit import QWebElement
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.keyinput import modeman from qutebrowser.keyinput import modeman
@ -94,7 +94,6 @@ class HintManager(QObject):
"""Manage drawing hints over links or other elements. """Manage drawing hints over links or other elements.
Class attributes: Class attributes:
HINT_CSS: The CSS template to use for hints.
HINT_TEXTS: Text displayed for different hinting modes. HINT_TEXTS: Text displayed for different hinting modes.
Attributes: Attributes:
@ -108,21 +107,6 @@ class HintManager(QObject):
set_open_target: Set a new target to open the links in. set_open_target: Set a new target to open the links in.
""" """
HINT_CSS = """
display: {display};
color: {config[colors][hints.fg]};
background: {config[colors][hints.bg]};
text-transform: {texttransform};
font: {config[fonts][hints]};
border: {config[hints][border]};
opacity: {config[hints][opacity]};
z-index: 100000;
pointer-events: none;
position: absolute;
left: {left}px;
top: {top}px;
"""
HINT_TEXTS = { HINT_TEXTS = {
Target.normal: "Follow hint...", Target.normal: "Follow hint...",
Target.tab: "Follow hint in new tab...", Target.tab: "Follow hint in new tab...",
@ -262,27 +246,48 @@ class HintManager(QObject):
hintstr.insert(0, chars[0]) hintstr.insert(0, chars[0])
return ''.join(hintstr) return ''.join(hintstr)
def _get_hint_css(self, elem, label=None): def _is_hidden(self, elem):
"""Get the hint CSS for the element given. """Check if the element is hidden via display=none."""
display = elem.styleProperty('display', QWebElement.InlineStyle)
return display == 'none'
def _set_style_properties(self, elem, label):
"""Set the hint CSS on the element given.
Args: Args:
elem: The QWebElement to get the CSS for. elem: The QWebElement to set the style attributes for.
label: The label QWebElement if display: none should be preserved. label: The label QWebElement.
Return:
The CSS to set as a string.
""" """
if label is None or label['hidden'] != 'true': attrs = [
display = 'inline' ('display', 'inline'),
else: ('z-index', '100000'),
display = 'none' ('pointer-events', 'none'),
('position', 'absolute'),
('color', config.get('colors', 'hints.fg')),
('background', config.get('colors', 'hints.bg')),
('font', config.get('fonts', 'hints')),
('border', config.get('hints', 'border')),
('opacity', str(config.get('hints', 'opacity'))),
]
# Make text uppercase if set in config # Make text uppercase if set in config
if (config.get('hints', 'uppercase') and if (config.get('hints', 'uppercase') and
config.get('hints', 'mode') == 'letter'): config.get('hints', 'mode') == 'letter'):
texttransform = 'uppercase' attrs.append(('texttransform', 'uppercase'))
else: else:
texttransform = 'none' attrs.append(('texttransform', 'none'))
for k, v in attrs:
label.setStyleProperty(k, v)
self._set_style_position(elem, label)
def _set_style_position(self, elem, label):
"""Set the CSS position of the label element.
Args:
elem: The QWebElement to set the style attributes for.
label: The label QWebElement.
"""
rect = elem.geometry() rect = elem.geometry()
left = rect.x() left = rect.x()
top = rect.y() top = rect.y()
@ -290,11 +295,10 @@ class HintManager(QObject):
if not config.get('ui', 'zoom-text-only'): if not config.get('ui', 'zoom-text-only'):
left /= zoom left /= zoom
top /= zoom top /= zoom
log.hints.vdebug("Drawing label '{}' at {}/{} for element '{!r}', " log.hints.vdebug("Drawing label '{!r}' at {}/{} for element '{!r}', "
"zoom level {}".format(label, left, top, elem, zoom)) "zoom level {}".format(label, left, top, elem, zoom))
return self.HINT_CSS.format( label.setStyleProperty('left', '{}px'.format(left))
left=left, top=top, config=objreg.get('config'), display=display, label.setStyleProperty('top', '{}px'.format(top))
texttransform=texttransform)
def _draw_label(self, elem, string): def _draw_label(self, elem, string):
"""Draw a hint label over an element. """Draw a hint label over an element.
@ -304,9 +308,8 @@ class HintManager(QObject):
string: The hint string to print. string: The hint string to print.
Return: Return:
The newly created label elment The newly created label element
""" """
css = self._get_hint_css(elem)
doc = elem.webFrame().documentElement() doc = elem.webFrame().documentElement()
# It seems impossible to create an empty QWebElement for which isNull() # It seems impossible to create an empty QWebElement for which isNull()
# is false so we can work with it. # is false so we can work with it.
@ -314,12 +317,11 @@ class HintManager(QObject):
# then use lastChild() to get a reference to it. # then use lastChild() to get a reference to it.
# See: http://stackoverflow.com/q/7364852/2085149 # See: http://stackoverflow.com/q/7364852/2085149
doc.appendInside('<span></span>') doc.appendInside('<span></span>')
elem = webelem.WebElementWrapper(doc.lastChild()) label = webelem.WebElementWrapper(doc.lastChild())
elem['class'] = 'qutehint' label['class'] = 'qutehint'
elem['hidden'] = 'false' self._set_style_properties(elem, label)
elem['style'] = css label.setPlainText(string)
elem.setPlainText(string) return label
return elem
def _click(self, elem): def _click(self, elem):
"""Click an element. """Click an element.
@ -631,16 +633,12 @@ class HintManager(QObject):
rest = string[len(keystr):] rest = string[len(keystr):]
elems.label.setInnerXml('<font color="{}">{}</font>{}'.format( elems.label.setInnerXml('<font color="{}">{}</font>{}'.format(
config.get('colors', 'hints.fg.match'), matched, rest)) config.get('colors', 'hints.fg.match'), matched, rest))
if elems.label['hidden'] == 'true': if self._is_hidden(elems.label):
# hidden element which matches again -> unhide it # hidden element which matches again -> unhide it
elems.label['hidden'] = 'false' elems.label.setStyleProperty('display', 'inline')
css = self._get_hint_css(elems.elem, elems.label)
elems.label['style'] = css
else: else:
# element doesn't match anymore -> hide it # element doesn't match anymore -> hide it
elems.label['hidden'] = 'true' elems.label.setStyleProperty('display', 'none')
css = self._get_hint_css(elems.elem, elems.label)
elems.label['style'] = css
def filter_hints(self, filterstr): def filter_hints(self, filterstr):
"""Filter displayed hints according to a text. """Filter displayed hints according to a text.
@ -651,19 +649,15 @@ class HintManager(QObject):
for elems in self._context.elems.values(): for elems in self._context.elems.values():
if (filterstr is None or if (filterstr is None or
str(elems.elem).lower().startswith(filterstr)): str(elems.elem).lower().startswith(filterstr)):
if elems.label['hidden'] == 'true': if self._is_hidden(elems.label):
# hidden element which matches again -> unhide it # hidden element which matches again -> unhide it
elems.label['hidden'] = 'false' elems.label.setStyleProperty('display', 'none')
css = self._get_hint_css(elems.elem, elems.label)
elems.label['style'] = css
else: else:
# element doesn't match anymore -> hide it # element doesn't match anymore -> hide it
elems.label['hidden'] = 'true' elems.label.setStyleProperty('display', 'none')
css = self._get_hint_css(elems.elem, elems.label)
elems.label['style'] = css
visible = {} visible = {}
for k, e in self._context.elems.items(): for k, e in self._context.elems.items():
if e.label['hidden'] != 'true': if not self._is_hidden(e.label):
visible[k] = e visible[k] = e
if not visible: if not visible:
# Whoops, filtered all hints # Whoops, filtered all hints
@ -741,8 +735,7 @@ class HintManager(QObject):
# This sometimes happens for some reason... # This sometimes happens for some reason...
elems.label.removeFromDocument() elems.label.removeFromDocument()
continue continue
css = self._get_hint_css(elems.elem, elems.label) self._set_style_position(elems.elem, elems.label)
elems.label['style'] = css
@pyqtSlot(usertypes.KeyMode) @pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode): def on_mode_left(self, mode):