Use object registry for hintmanager.
This commit is contained in:
parent
e8ce45c440
commit
78949a8c1b
@ -404,13 +404,6 @@ class Application(QApplication):
|
||||
status.keystring.setText)
|
||||
tabs.got_cmd.connect(self._commandrunner.run_safely)
|
||||
|
||||
# hints
|
||||
kp[utypes.KeyMode.hint].fire_hint.connect(tabs.fire_hint)
|
||||
kp[utypes.KeyMode.hint].filter_hints.connect(tabs.filter_hints)
|
||||
kp[utypes.KeyMode.hint].keystring_updated.connect(tabs.handle_hint_key)
|
||||
tabs.hint_strings_updated.connect(
|
||||
kp[utypes.KeyMode.hint].on_hint_strings_updated)
|
||||
|
||||
# messages
|
||||
message_bridge.s_error.connect(status.disp_error)
|
||||
message_bridge.s_info.connect(status.disp_temp_text)
|
||||
|
@ -302,55 +302,6 @@ class CommandDispatcher:
|
||||
for _ in range(count):
|
||||
self._current_widget().go_forward()
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher')
|
||||
def hint(self, group=webelem.Group.all, target=hints.Target.normal,
|
||||
*args: {'nargs': '*'}):
|
||||
"""Start hinting.
|
||||
|
||||
Args:
|
||||
group: The hinting mode to use.
|
||||
|
||||
- `all`: All clickable elements.
|
||||
- `links`: Only links.
|
||||
- `images`: Only images.
|
||||
|
||||
target: What to do with the selected element.
|
||||
|
||||
- `normal`: Open the link in the current tab.
|
||||
- `tab`: Open the link in a new tab.
|
||||
- `tab-bg`: Open the link in a new background tab.
|
||||
- `yank`: Yank the link to the clipboard.
|
||||
- `yank-primary`: Yank the link to the primary selection.
|
||||
- `fill`: Fill the commandline with the command given as
|
||||
argument.
|
||||
- `rapid`: Open the link in a new tab and stay in hinting mode.
|
||||
- `download`: Download the link.
|
||||
- `userscript`: Call an userscript with `$QUTE_URL` set to the
|
||||
link.
|
||||
- `spawn`: Spawn a command.
|
||||
|
||||
*args: Arguments for spawn/userscript/fill.
|
||||
|
||||
- With `spawn`: The executable and arguments to spawn.
|
||||
`{hint-url}` will get replaced by the selected
|
||||
URL.
|
||||
- With `userscript`: The userscript to execute.
|
||||
- With `fill`: The command to fill the statusbar with.
|
||||
`{hint-url}` will get replaced by the selected
|
||||
URL.
|
||||
"""
|
||||
widget = self._current_widget()
|
||||
frame = widget.page().mainFrame()
|
||||
if frame is None:
|
||||
raise cmdexc.CommandError("No frame focused!")
|
||||
widget.hintmanager.start(frame, self._current_url(), group, target,
|
||||
*args)
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', hide=True)
|
||||
def follow_hint(self):
|
||||
"""Follow the currently selected hint."""
|
||||
self._current_widget().hintmanager.follow_hint()
|
||||
|
||||
def _navigate_incdec(self, url, tab, incdec):
|
||||
"""Helper method for :navigate when `where' is increment/decrement.
|
||||
|
||||
@ -424,12 +375,11 @@ class CommandDispatcher:
|
||||
url = self._current_url()
|
||||
if frame is None:
|
||||
raise cmdexc.CommandError("No frame focused!")
|
||||
hintmanager = objreg.get('hintmanager', scope='tab')
|
||||
if where == 'prev':
|
||||
widget.hintmanager.follow_prevnext(frame, url, prev=True,
|
||||
newtab=tab)
|
||||
hintmanager.follow_prevnext(frame, url, prev=True, newtab=tab)
|
||||
elif where == 'next':
|
||||
widget.hintmanager.follow_prevnext(frame, url, prev=False,
|
||||
newtab=tab)
|
||||
hintmanager.follow_prevnext(frame, url, prev=False, newtab=tab)
|
||||
elif where == 'up':
|
||||
self._navigate_up(url, tab)
|
||||
elif where in ('decrement', 'increment'):
|
||||
|
@ -30,9 +30,8 @@ from PyQt5.QtWidgets import QApplication
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.keyinput import modeman
|
||||
from qutebrowser.browser import webelem
|
||||
from qutebrowser.commands import userscripts, cmdexc
|
||||
from qutebrowser.utils import (usertypes, log, qtutils, message, objreg,
|
||||
cmdutils)
|
||||
from qutebrowser.commands import userscripts, cmdexc, cmdutils
|
||||
from qutebrowser.utils import usertypes, log, qtutils, message, objreg
|
||||
|
||||
|
||||
ElemTuple = collections.namedtuple('ElemTuple', 'elem, label')
|
||||
@ -96,13 +95,8 @@ class HintManager(QObject):
|
||||
_context: The HintContext for the current invocation.
|
||||
|
||||
Signals:
|
||||
hint_strings_updated: Emitted when the possible hint strings changed.
|
||||
arg: A list of hint strings.
|
||||
mouse_event: Mouse event to be posted in the web view.
|
||||
arg: A QMouseEvent
|
||||
openurl: Open a new URL
|
||||
arg 0: URL to open as QUrl.
|
||||
arg 1: True if it should be opened in a new tab, else False.
|
||||
set_open_target: Set a new target to open the links in.
|
||||
"""
|
||||
|
||||
@ -133,9 +127,7 @@ class HintManager(QObject):
|
||||
Target.spawn: "Spawn command via hint...",
|
||||
}
|
||||
|
||||
hint_strings_updated = pyqtSignal(list)
|
||||
mouse_event = pyqtSignal('QMouseEvent')
|
||||
openurl = pyqtSignal('QUrl', bool)
|
||||
set_open_target = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@ -492,7 +484,8 @@ class HintManager(QObject):
|
||||
for e, string in zip(elems, strings):
|
||||
label = self._draw_label(e, string)
|
||||
self._context.elems[string] = ElemTuple(e, label)
|
||||
self.hint_strings_updated.emit(strings)
|
||||
keyparser = objreg.get('keyparsers')[usertypes.KeyMode.hint]
|
||||
keyparser.update_bindings(strings)
|
||||
|
||||
def follow_prevnext(self, frame, baseurl, prev=False, newtab=False):
|
||||
"""Click a "previous"/"next" element on the page.
|
||||
@ -511,31 +504,60 @@ class HintManager(QObject):
|
||||
if url is None:
|
||||
raise cmdexc.CommandError("No {} links found!".format(
|
||||
"prev" if prev else "forward"))
|
||||
self.openurl.emit(url, newtab)
|
||||
qtutils.ensure_valid(url)
|
||||
if newtab:
|
||||
objreg.get('tabbed-browser').tabopen(url, background=False)
|
||||
else:
|
||||
objreg.get('webview', scope='tab').openurl(url)
|
||||
|
||||
def start(self, mainframe, baseurl, group=webelem.Group.all,
|
||||
target=Target.normal, *args):
|
||||
@cmdutils.register(instance='hintmanager', scope='tab', name='hint')
|
||||
def start(self, group=webelem.Group.all, target=Target.normal,
|
||||
*args: {'nargs': '*'}):
|
||||
"""Start hinting.
|
||||
|
||||
Args:
|
||||
mainframe: The main QWebFrame.
|
||||
baseurl: URL of the current page.
|
||||
group: Which group of elements to hint.
|
||||
target: What to do with the link. See attribute docstring.
|
||||
*args: Arguments for userscript/download
|
||||
group: The hinting mode to use.
|
||||
|
||||
Emit:
|
||||
hint_strings_updated: Emitted to update keypraser.
|
||||
- `all`: All clickable elements.
|
||||
- `links`: Only links.
|
||||
- `images`: Only images.
|
||||
|
||||
target: What to do with the selected element.
|
||||
|
||||
- `normal`: Open the link in the current tab.
|
||||
- `tab`: Open the link in a new tab.
|
||||
- `tab-bg`: Open the link in a new background tab.
|
||||
- `yank`: Yank the link to the clipboard.
|
||||
- `yank-primary`: Yank the link to the primary selection.
|
||||
- `fill`: Fill the commandline with the command given as
|
||||
argument.
|
||||
- `rapid`: Open the link in a new tab and stay in hinting mode.
|
||||
- `download`: Download the link.
|
||||
- `userscript`: Call an userscript with `$QUTE_URL` set to the
|
||||
link.
|
||||
- `spawn`: Spawn a command.
|
||||
|
||||
*args: Arguments for spawn/userscript/fill.
|
||||
|
||||
- With `spawn`: The executable and arguments to spawn.
|
||||
`{hint-url}` will get replaced by the selected
|
||||
URL.
|
||||
- With `userscript`: The userscript to execute.
|
||||
- With `fill`: The command to fill the statusbar with.
|
||||
`{hint-url}` will get replaced by the selected
|
||||
URL.
|
||||
"""
|
||||
self._check_args(target, *args)
|
||||
tabbed_browser = objreg.get('tabbed-browser')
|
||||
widget = tabbed_browser.currentWidget()
|
||||
if widget is None:
|
||||
raise cmdexc.CommandError("No WebView available yet!")
|
||||
mainframe = widget.page().mainFrame()
|
||||
if mainframe is None:
|
||||
# This should never happen since we check frame before calling
|
||||
# start. But since we had a bug where frame is None in
|
||||
# on_mode_left, we are extra careful here.
|
||||
raise ValueError("start() was called with frame=None")
|
||||
raise cmdexc.CommandError("No frame focused!")
|
||||
self._check_args(target, *args)
|
||||
self._context = HintContext()
|
||||
self._context.target = target
|
||||
self._context.baseurl = baseurl
|
||||
self._context.baseurl = tabbed_browser.current_url()
|
||||
self._context.frames = webelem.get_child_frames(mainframe)
|
||||
self._context.args = args
|
||||
self._init_elements(mainframe, group)
|
||||
@ -634,6 +656,7 @@ class HintManager(QObject):
|
||||
if self._context.target != Target.rapid:
|
||||
modeman.maybe_leave(usertypes.KeyMode.hint, 'followed')
|
||||
|
||||
@cmdutils.register(instance='hintmanager', scope='tab', hide=True)
|
||||
def follow_hint(self):
|
||||
"""Follow the currently selected hint."""
|
||||
if not self._context.to_follow:
|
||||
|
@ -23,12 +23,12 @@ Module attributes:
|
||||
STARTCHARS: Possible chars for starting a commandline input.
|
||||
"""
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
|
||||
|
||||
from qutebrowser.utils import message
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.keyinput import keyparser
|
||||
from qutebrowser.utils import usertypes, log
|
||||
from qutebrowser.utils import usertypes, log, objreg
|
||||
|
||||
|
||||
STARTCHARS = ":/?"
|
||||
@ -80,25 +80,17 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
|
||||
"""KeyChainParser for hints.
|
||||
|
||||
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.
|
||||
_last_press: The nature of the last keypress, a LastPress member.
|
||||
"""
|
||||
|
||||
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._last_press = LastPress.none
|
||||
self.read_config('hint')
|
||||
self.keystring_updated.connect(self.on_keystring_updated)
|
||||
|
||||
def _handle_special_key(self, e):
|
||||
"""Override _handle_special_key to handle string filtering.
|
||||
@ -112,11 +104,11 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
True if event has been handled, False otherwise.
|
||||
|
||||
Emit:
|
||||
filter_hints: Emitted when filter string has changed.
|
||||
keystring_updated: Emitted when keystring has been changed.
|
||||
"""
|
||||
log.keyboard.debug("Got special key 0x{:x} text {}".format(
|
||||
e.key(), e.text()))
|
||||
hintmanager = objreg.get('hintmanager', scope='tab')
|
||||
if e.key() == Qt.Key_Backspace:
|
||||
log.keyboard.debug("Got backspace, mode {}, filtertext '{}', "
|
||||
"keystring '{}'".format(self._last_press,
|
||||
@ -124,7 +116,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
self._keystring))
|
||||
if self._last_press == LastPress.filtertext and self._filtertext:
|
||||
self._filtertext = self._filtertext[:-1]
|
||||
self.filter_hints.emit(self._filtertext)
|
||||
hintmanager.filter_hints(self._filtertext)
|
||||
return True
|
||||
elif self._last_press == LastPress.keystring and self._keystring:
|
||||
self._keystring = self._keystring[:-1]
|
||||
@ -138,7 +130,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
return super()._handle_special_key(e)
|
||||
else:
|
||||
self._filtertext += e.text()
|
||||
self.filter_hints.emit(self._filtertext)
|
||||
hintmanager.filter_hints(self._filtertext)
|
||||
self._last_press = LastPress.filtertext
|
||||
return True
|
||||
|
||||
@ -167,24 +159,25 @@ class HintKeyParser(keyparser.CommandKeyParser):
|
||||
return self._handle_special_key(e)
|
||||
|
||||
def execute(self, cmdstr, keytype, count=None):
|
||||
"""Handle a completed keychain.
|
||||
|
||||
Emit:
|
||||
fire_hint: Emitted if keytype is chain
|
||||
"""
|
||||
"""Handle a completed keychain."""
|
||||
if not isinstance(keytype, self.Type):
|
||||
raise TypeError("Type {} is no Type member!".format(keytype))
|
||||
if keytype == self.Type.chain:
|
||||
self.fire_hint.emit(cmdstr)
|
||||
objreg.get('hintmanager', scope='tab').fire(cmdstr)
|
||||
else:
|
||||
# execute as command
|
||||
super().execute(cmdstr, keytype, count)
|
||||
|
||||
def on_hint_strings_updated(self, strings):
|
||||
"""Handler for HintManager's hint_strings_updated.
|
||||
def update_bindings(self, strings):
|
||||
"""Update bindings when the hint strings changed.
|
||||
|
||||
Args:
|
||||
strings: A list of hint strings.
|
||||
"""
|
||||
self.bindings = {s: s for s in strings}
|
||||
self._filtertext = ''
|
||||
|
||||
@pyqtSlot(str)
|
||||
def on_keystring_updated(self, keystr):
|
||||
"""Update hintmanager when the keystring was updated."""
|
||||
objreg.get('hintmanager', scope='tab').handle_partial_key(keystr)
|
||||
|
@ -67,8 +67,6 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
arg 1: x-position in %.
|
||||
arg 2: y-position in %.
|
||||
cur_load_status_changed: Loading status of current tab changed.
|
||||
hint_strings_updated: Hint strings were updated.
|
||||
arg: A list of hint strings.
|
||||
quit: The last tab was closed, quit application.
|
||||
resized: Emitted when the browser window has resized, so the completion
|
||||
widget can adjust its size to it.
|
||||
@ -89,7 +87,6 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
cur_scroll_perc_changed = pyqtSignal(int, int)
|
||||
cur_load_status_changed = pyqtSignal(str)
|
||||
start_download = pyqtSignal('QNetworkReply*')
|
||||
hint_strings_updated = pyqtSignal(list)
|
||||
quit = pyqtSignal()
|
||||
resized = pyqtSignal('QRect')
|
||||
got_cmd = pyqtSignal(str)
|
||||
@ -151,9 +148,6 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
self._filter.create(self.cur_load_status_changed, tab))
|
||||
tab.url_text_changed.connect(
|
||||
functools.partial(self.on_url_text_changed, tab))
|
||||
# hintmanager
|
||||
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
|
||||
tab.hintmanager.openurl.connect(self.openurl)
|
||||
self.cur_load_started.connect(self.on_cur_load_started)
|
||||
# downloads
|
||||
page.start_download.connect(self.start_download)
|
||||
@ -370,21 +364,6 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
# We first want QWebPage to refresh.
|
||||
QTimer.singleShot(0, check_scroll_pos)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def handle_hint_key(self, keystr):
|
||||
"""Handle a new hint keypress."""
|
||||
self.currentWidget().hintmanager.handle_partial_key(keystr)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def fire_hint(self, keystr):
|
||||
"""Fire a completed hint."""
|
||||
self.currentWidget().hintmanager.fire(keystr)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def filter_hints(self, filterstr):
|
||||
"""Filter displayed hints."""
|
||||
self.currentWidget().hintmanager.filter_hints(filterstr)
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def on_config_changed(self, section, option):
|
||||
"""Update tab config when config was changed."""
|
||||
|
@ -94,9 +94,10 @@ class WebView(QWebView):
|
||||
objreg.register('webview', self, registry=self.registry)
|
||||
page = webpage.BrowserPage(self)
|
||||
self.setPage(page)
|
||||
self.hintmanager = hints.HintManager(self)
|
||||
self.hintmanager.mouse_event.connect(self.on_mouse_event)
|
||||
self.hintmanager.set_open_target.connect(self.set_force_open_target)
|
||||
hintmanager = hints.HintManager(self)
|
||||
hintmanager.mouse_event.connect(self.on_mouse_event)
|
||||
hintmanager.set_open_target.connect(self.set_force_open_target)
|
||||
objreg.register('hintmanager', hintmanager, registry=self.registry)
|
||||
page.linkHovered.connect(self.linkHovered)
|
||||
page.mainFrame().loadStarted.connect(self.on_load_started)
|
||||
page.change_title.connect(self.titleChanged)
|
||||
|
Loading…
Reference in New Issue
Block a user