Mark partial hint matches
This commit is contained in:
parent
d7b87e09c9
commit
c2aa9517ea
@ -18,6 +18,7 @@
|
|||||||
"""A HintManager to draw hints over links."""
|
"""A HintManager to draw hints over links."""
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QObject
|
from PyQt5.QtCore import pyqtSignal, QObject
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ import qutebrowser.config.config as config
|
|||||||
from qutebrowser.utils.keyparser import KeyParser
|
from qutebrowser.utils.keyparser import KeyParser
|
||||||
|
|
||||||
|
|
||||||
|
ElemTuple = namedtuple('ElemTuple', 'elem, label')
|
||||||
|
|
||||||
|
|
||||||
class HintKeyParser(KeyParser):
|
class HintKeyParser(KeyParser):
|
||||||
|
|
||||||
"""KeyParser for hints.
|
"""KeyParser for hints.
|
||||||
@ -63,8 +67,7 @@ class HintManager(QObject):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_frame: The QWebFrame to use.
|
_frame: The QWebFrame to use.
|
||||||
_elems: The elements we're hinting currently.
|
_elems: A mapping from keystrings to (elem, label) namedtuples.
|
||||||
_labels: The label elements.
|
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
hint_strings_updated: Emitted when the possible hint strings changed.
|
hint_strings_updated: Emitted when the possible hint strings changed.
|
||||||
@ -106,8 +109,7 @@ class HintManager(QObject):
|
|||||||
"""
|
"""
|
||||||
super().__init__(frame)
|
super().__init__(frame)
|
||||||
self._frame = frame
|
self._frame = frame
|
||||||
self._elems = []
|
self._elems = {}
|
||||||
self._labels = []
|
|
||||||
|
|
||||||
def _hint_strings(self, elems):
|
def _hint_strings(self, elems):
|
||||||
"""Calculate the hint strings for elems.
|
"""Calculate the hint strings for elems.
|
||||||
@ -204,6 +206,9 @@ class HintManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
elem: The QWebElement to use.
|
elem: The QWebElement to use.
|
||||||
string: The hint string to print.
|
string: The hint string to print.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
The newly created label elment
|
||||||
"""
|
"""
|
||||||
rect = elem.geometry()
|
rect = elem.geometry()
|
||||||
css = HintManager.HINT_CSS.format(left=rect.x(), top=rect.y(),
|
css = HintManager.HINT_CSS.format(left=rect.x(), top=rect.y(),
|
||||||
@ -211,7 +216,7 @@ class HintManager(QObject):
|
|||||||
doc = self._frame.documentElement()
|
doc = self._frame.documentElement()
|
||||||
doc.appendInside('<span class="qutehint" style="{}">{}</span>'.format(
|
doc.appendInside('<span class="qutehint" style="{}">{}</span>'.format(
|
||||||
css, string))
|
css, string))
|
||||||
self._labels.append(doc.lastChild())
|
return doc.lastChild()
|
||||||
|
|
||||||
def start(self, mode="all"):
|
def start(self, mode="all"):
|
||||||
"""Start hinting.
|
"""Start hinting.
|
||||||
@ -221,6 +226,7 @@ class HintManager(QObject):
|
|||||||
"""
|
"""
|
||||||
selector = HintManager.SELECTORS[mode]
|
selector = HintManager.SELECTORS[mode]
|
||||||
elems = self._frame.findAllElements(selector)
|
elems = self._frame.findAllElements(selector)
|
||||||
|
visible_elems = []
|
||||||
for e in elems:
|
for e in elems:
|
||||||
rect = e.geometry()
|
rect = e.geometry()
|
||||||
if (not rect.isValid()) and rect.x() == 0:
|
if (not rect.isValid()) and rect.x() == 0:
|
||||||
@ -231,24 +237,35 @@ class HintManager(QObject):
|
|||||||
if not framegeom.contains(rect):
|
if not framegeom.contains(rect):
|
||||||
# out of screen
|
# out of screen
|
||||||
continue
|
continue
|
||||||
self._elems.append(e)
|
visible_elems.append(e)
|
||||||
strings = self._hint_strings(self._elems)
|
strings = self._hint_strings(visible_elems)
|
||||||
for e, string in zip(self._elems, strings):
|
for e, string in zip(visible_elems, strings):
|
||||||
self._draw_label(e, string)
|
label = self._draw_label(e, string)
|
||||||
|
self._elems[string] = ElemTuple(e, label)
|
||||||
self.hint_strings_updated.emit(strings)
|
self.hint_strings_updated.emit(strings)
|
||||||
self.set_mode.emit("hint")
|
self.set_mode.emit("hint")
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop hinting."""
|
"""Stop hinting."""
|
||||||
for e in self._labels:
|
for elem in self._elems:
|
||||||
e.removeFromDocument()
|
elem.label.removeFromDocument()
|
||||||
self._elems = None
|
self._elems = {}
|
||||||
self._labels = []
|
|
||||||
self.set_mode.emit("normal")
|
self.set_mode.emit("normal")
|
||||||
|
|
||||||
def handle_partial_key(self, keystr):
|
def handle_partial_key(self, keystr):
|
||||||
"""Handle a new partial keypress."""
|
"""Handle a new partial keypress."""
|
||||||
raise NotImplementedError
|
delete = []
|
||||||
|
for (string, elems) in self._elems.items():
|
||||||
|
if string.startswith(keystr):
|
||||||
|
matched = string[:len(keystr)]
|
||||||
|
rest = string[len(keystr):]
|
||||||
|
elems.label.setInnerXml('<font color="{}">{}</font>{}'.format(
|
||||||
|
config.get("colors", "hints.fg.match"), matched, rest))
|
||||||
|
else:
|
||||||
|
elems.label.removeFromDocument()
|
||||||
|
delete.append(string)
|
||||||
|
for key in delete:
|
||||||
|
del self._elems[key]
|
||||||
|
|
||||||
def fire(self, keystr):
|
def fire(self, keystr):
|
||||||
"""Fire a completed hint."""
|
"""Fire a completed hint."""
|
||||||
|
@ -478,6 +478,10 @@ DATA = OrderedDict([
|
|||||||
SettingValue(types.CssColor, "black"),
|
SettingValue(types.CssColor, "black"),
|
||||||
"Font color for hints."),
|
"Font color for hints."),
|
||||||
|
|
||||||
|
('hints.fg.match',
|
||||||
|
SettingValue(types.CssColor, "green"),
|
||||||
|
"Font color for the matched part of hints."),
|
||||||
|
|
||||||
('hints.bg',
|
('hints.bg',
|
||||||
SettingValue(types.CssColor, "-webkit-gradient(linear, left top, "
|
SettingValue(types.CssColor, "-webkit-gradient(linear, left top, "
|
||||||
"left bottom, color-stop(0%,#FFF785), "
|
"left bottom, color-stop(0%,#FFF785), "
|
||||||
|
Loading…
Reference in New Issue
Block a user