Implement numeric hints
This commit is contained in:
parent
e5c7d467ae
commit
efc613811f
2
TODO
2
TODO
@ -50,8 +50,8 @@ hints
|
||||
|
||||
bindings for prev/next hint
|
||||
more intelligent clicking (end of textfields)
|
||||
filtering when typing part of name
|
||||
filter close hints when it's the same link
|
||||
ignore keypresses shortly after link following
|
||||
|
||||
Qt Bugs
|
||||
========
|
||||
|
@ -284,6 +284,7 @@ class QuteBrowser(QApplication):
|
||||
|
||||
# hints
|
||||
kp['hint'].fire_hint.connect(tabs.cur.fire_hint)
|
||||
kp['hint'].filter_hints.connect(tabs.cur.filter_hints)
|
||||
kp['hint'].keystring_updated.connect(tabs.cur.handle_hint_key)
|
||||
tabs.hint_strings_updated.connect(kp['hint'].on_hint_strings_updated)
|
||||
|
||||
|
@ -245,6 +245,11 @@ class CurCommandDispatcher(QObject):
|
||||
"""Fire a completed hint."""
|
||||
self._tabs.currentWidget().hintmanager.fire(keystr)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def filter_hints(self, filterstr):
|
||||
"""Filter displayed hints."""
|
||||
self._tabs.currentWidget().hintmanager.filter_hints(filterstr)
|
||||
|
||||
@cmdutils.register(instance='mainwindow.tabs.cur')
|
||||
def prevpage(self):
|
||||
"""Open a "previous" link."""
|
||||
|
@ -107,7 +107,10 @@ class HintManager(QObject):
|
||||
Return:
|
||||
A list of hint strings, in the same order as the elements.
|
||||
"""
|
||||
chars = config.get("hints", "chars")
|
||||
if config.get('hints', 'mode') == 'number':
|
||||
chars = '0123456789'
|
||||
else:
|
||||
chars = config.get('hints', 'chars')
|
||||
# Determine how many digits the link hints will require in the worst
|
||||
# case. Usually we do not need all of these digits for every link
|
||||
# single hint, so we can show shorter hints for a few of the links.
|
||||
@ -389,6 +392,22 @@ class HintManager(QObject):
|
||||
for key in delete:
|
||||
del self._elems[key]
|
||||
|
||||
def filter_hints(self, filterstr):
|
||||
"""Filter displayed hints according to a text."""
|
||||
delete = []
|
||||
for (string, elems) in self._elems.items():
|
||||
if not elems.elem.toPlainText().lower().startswith(filterstr):
|
||||
elems.label.removeFromDocument()
|
||||
delete.append(string)
|
||||
for key in delete:
|
||||
del self._elems[key]
|
||||
if not self._elems:
|
||||
# Whoops, filtered all hints
|
||||
modeman.leave('hint')
|
||||
elif len(self._elems) == 1 and config.get('hints', 'auto-follow'):
|
||||
# unpacking gets us the first (and only) key in the dict.
|
||||
self.fire(*self._elems)
|
||||
|
||||
def fire(self, keystr, force=False):
|
||||
"""Fire a completed hint.
|
||||
|
||||
|
@ -200,6 +200,16 @@ class ShellCommand(String):
|
||||
return shlex.split(value)
|
||||
|
||||
|
||||
class HintMode(BaseType):
|
||||
|
||||
"""Base class for the hints -> mode setting."""
|
||||
|
||||
typestr = 'hint-mode'
|
||||
|
||||
valid_values = ValidValues(('number', "Use numeric hints."),
|
||||
('letter', "Use the chars in hints -> chars."))
|
||||
|
||||
|
||||
class Bool(BaseType):
|
||||
|
||||
"""Base class for a boolean setting.
|
||||
|
@ -410,6 +410,10 @@ DATA = OrderedDict([
|
||||
SettingValue(types.Float(minval=0.0, maxval=1.0), '0.7'),
|
||||
"Opacity for hints."),
|
||||
|
||||
('mode',
|
||||
SettingValue(types.HintMode(), 'letter'),
|
||||
"Mode to use for hints, 'number' or 'letter'."),
|
||||
|
||||
('chars',
|
||||
SettingValue(types.String(minlen=2), 'asdfghjkl'),
|
||||
"Chars used for hint strings."),
|
||||
|
@ -21,9 +21,12 @@ Module attributes:
|
||||
STARTCHARS: Possible chars for starting a commandline input.
|
||||
"""
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
|
||||
import qutebrowser.utils.message as message
|
||||
import qutebrowser.config.config as config
|
||||
from qutebrowser.keyinput.keyparser import CommandKeyParser
|
||||
|
||||
|
||||
@ -61,14 +64,65 @@ class HintKeyParser(CommandKeyParser):
|
||||
Signals:
|
||||
fire_hint: When a hint keybinding was completed.
|
||||
Arg: the keystring/hint string pressed.
|
||||
filter_hints: When the filter text changed.
|
||||
Arg: the text to filter hints with.
|
||||
|
||||
Attributes:
|
||||
_filtertext: The text to filter with.
|
||||
"""
|
||||
|
||||
fire_hint = pyqtSignal(str)
|
||||
filter_hints = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent, supports_count=False, supports_chains=True)
|
||||
self._filtertext = ''
|
||||
self.read_config('keybind.hint')
|
||||
|
||||
def _handle_special_key(self, e):
|
||||
"""Override _handle_special_key to handle string filtering.
|
||||
|
||||
Return True if the keypress has been handled, and False if not.
|
||||
|
||||
Args:
|
||||
e: the KeyPressEvent from Qt.
|
||||
|
||||
Return:
|
||||
True if event has been handled, False otherwise.
|
||||
|
||||
Emit:
|
||||
filter_hints: Emitted when filter string has changed.
|
||||
"""
|
||||
logging.debug("Got special key {} text {}".format(e.key(), e.text()))
|
||||
if config.get('hints', 'mode') != 'number':
|
||||
return super()._handle_special_key(e)
|
||||
elif e.key() == Qt.Key_Backspace:
|
||||
if self._filtertext:
|
||||
self._filtertext = self._filtertext[:-1]
|
||||
self.filter_hints.emit(self._filtertext)
|
||||
return True
|
||||
elif not e.text():
|
||||
return super()._handle_special_key(e)
|
||||
else:
|
||||
self._filtertext += e.text()
|
||||
self.filter_hints.emit(self._filtertext)
|
||||
return True
|
||||
|
||||
def handle(self, e):
|
||||
"""Handle a new keypress and call the respective handlers.
|
||||
|
||||
Args:
|
||||
e: the KeyPressEvent from Qt
|
||||
|
||||
Emit:
|
||||
keystring_updated: If a new keystring should be set.
|
||||
"""
|
||||
handled = self._handle_single_key(e)
|
||||
if handled:
|
||||
self.keystring_updated.emit(self._keystring)
|
||||
return handled
|
||||
return self._handle_special_key(e)
|
||||
|
||||
def execute(self, cmdstr, keytype, count=None):
|
||||
"""Handle a completed keychain.
|
||||
|
||||
@ -88,3 +142,4 @@ class HintKeyParser(CommandKeyParser):
|
||||
strings: A list of hint strings.
|
||||
"""
|
||||
self.bindings = {s: s for s in strings}
|
||||
self._filtertext = ''
|
||||
|
Loading…
Reference in New Issue
Block a user