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
|
bindings for prev/next hint
|
||||||
more intelligent clicking (end of textfields)
|
more intelligent clicking (end of textfields)
|
||||||
filtering when typing part of name
|
|
||||||
filter close hints when it's the same link
|
filter close hints when it's the same link
|
||||||
|
ignore keypresses shortly after link following
|
||||||
|
|
||||||
Qt Bugs
|
Qt Bugs
|
||||||
========
|
========
|
||||||
|
@ -284,6 +284,7 @@ class QuteBrowser(QApplication):
|
|||||||
|
|
||||||
# hints
|
# hints
|
||||||
kp['hint'].fire_hint.connect(tabs.cur.fire_hint)
|
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)
|
kp['hint'].keystring_updated.connect(tabs.cur.handle_hint_key)
|
||||||
tabs.hint_strings_updated.connect(kp['hint'].on_hint_strings_updated)
|
tabs.hint_strings_updated.connect(kp['hint'].on_hint_strings_updated)
|
||||||
|
|
||||||
|
@ -245,6 +245,11 @@ class CurCommandDispatcher(QObject):
|
|||||||
"""Fire a completed hint."""
|
"""Fire a completed hint."""
|
||||||
self._tabs.currentWidget().hintmanager.fire(keystr)
|
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')
|
@cmdutils.register(instance='mainwindow.tabs.cur')
|
||||||
def prevpage(self):
|
def prevpage(self):
|
||||||
"""Open a "previous" link."""
|
"""Open a "previous" link."""
|
||||||
|
@ -107,7 +107,10 @@ class HintManager(QObject):
|
|||||||
Return:
|
Return:
|
||||||
A list of hint strings, in the same order as the elements.
|
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
|
# 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
|
# 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.
|
# 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:
|
for key in delete:
|
||||||
del self._elems[key]
|
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):
|
def fire(self, keystr, force=False):
|
||||||
"""Fire a completed hint.
|
"""Fire a completed hint.
|
||||||
|
|
||||||
|
@ -200,6 +200,16 @@ class ShellCommand(String):
|
|||||||
return shlex.split(value)
|
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):
|
class Bool(BaseType):
|
||||||
|
|
||||||
"""Base class for a boolean setting.
|
"""Base class for a boolean setting.
|
||||||
|
@ -410,6 +410,10 @@ DATA = OrderedDict([
|
|||||||
SettingValue(types.Float(minval=0.0, maxval=1.0), '0.7'),
|
SettingValue(types.Float(minval=0.0, maxval=1.0), '0.7'),
|
||||||
"Opacity for hints."),
|
"Opacity for hints."),
|
||||||
|
|
||||||
|
('mode',
|
||||||
|
SettingValue(types.HintMode(), 'letter'),
|
||||||
|
"Mode to use for hints, 'number' or 'letter'."),
|
||||||
|
|
||||||
('chars',
|
('chars',
|
||||||
SettingValue(types.String(minlen=2), 'asdfghjkl'),
|
SettingValue(types.String(minlen=2), 'asdfghjkl'),
|
||||||
"Chars used for hint strings."),
|
"Chars used for hint strings."),
|
||||||
|
@ -21,9 +21,12 @@ Module attributes:
|
|||||||
STARTCHARS: Possible chars for starting a commandline input.
|
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.utils.message as message
|
||||||
|
import qutebrowser.config.config as config
|
||||||
from qutebrowser.keyinput.keyparser import CommandKeyParser
|
from qutebrowser.keyinput.keyparser import CommandKeyParser
|
||||||
|
|
||||||
|
|
||||||
@ -61,14 +64,65 @@ class HintKeyParser(CommandKeyParser):
|
|||||||
Signals:
|
Signals:
|
||||||
fire_hint: When a hint keybinding was completed.
|
fire_hint: When a hint keybinding was completed.
|
||||||
Arg: the keystring/hint string pressed.
|
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)
|
fire_hint = pyqtSignal(str)
|
||||||
|
filter_hints = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent, supports_count=False, supports_chains=True)
|
super().__init__(parent, supports_count=False, supports_chains=True)
|
||||||
|
self._filtertext = ''
|
||||||
self.read_config('keybind.hint')
|
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):
|
def execute(self, cmdstr, keytype, count=None):
|
||||||
"""Handle a completed keychain.
|
"""Handle a completed keychain.
|
||||||
|
|
||||||
@ -88,3 +142,4 @@ class HintKeyParser(CommandKeyParser):
|
|||||||
strings: A list of hint strings.
|
strings: A list of hint strings.
|
||||||
"""
|
"""
|
||||||
self.bindings = {s: s for s in strings}
|
self.bindings = {s: s for s in strings}
|
||||||
|
self._filtertext = ''
|
||||||
|
Loading…
Reference in New Issue
Block a user