Implement numeric hints

This commit is contained in:
Florian Bruhin 2014-05-02 17:53:16 +02:00
parent e5c7d467ae
commit efc613811f
7 changed files with 97 additions and 3 deletions

2
TODO
View File

@ -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
========

View File

@ -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)

View File

@ -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."""

View File

@ -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.

View File

@ -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.

View File

@ -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."),

View File

@ -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 = ''