Add a :devtools-focus command

This commit is contained in:
Florian Bruhin 2020-07-12 13:45:12 +02:00
parent 359a9c7dfb
commit b6d2dbb1dc
9 changed files with 61 additions and 6 deletions

View File

@ -36,6 +36,8 @@ Added
which behaves like `{index}`, but space-pads the index based on the total
numbers of tabs. This can be used to get aligned tab texts with vertical
tabs.
- New command `:devtools-focus` (bound to `wIf`) to toggle keyboard focus
between the devtools and web page.
Fixed
~~~~~

View File

@ -52,6 +52,7 @@ possible to run or bind multiple commands by separating them with `;;`.
|<<config-unset,config-unset>>|Unset an option.
|<<config-write-py,config-write-py>>|Write the current configuration to a config.py file.
|<<devtools,devtools>>|Toggle the developer tools (web inspector).
|<<devtools-focus,devtools-focus>>|Toggle focus between the devtools/tab.
|<<download,download>>|Download a given URL, or current page if no URL given.
|<<download-cancel,download-cancel>>|Cancel the last/[count]th download.
|<<download-clear,download-clear>>|Remove all finished downloads from the list.
@ -423,6 +424,10 @@ Toggle the developer tools (web inspector).
* +'position'+: Where to open the devtools (right/left/top/bottom/window).
[[devtools-focus]]
=== devtools-focus
Toggle focus between the devtools/tab.
[[download]]
=== download
Syntax: +:download [*--mhtml*] [*--dest* 'dest'] ['url']+

View File

@ -683,6 +683,7 @@ Default:
* +pass:[u]+: +pass:[undo]+
* +pass:[v]+: +pass:[enter-mode caret]+
* +pass:[wB]+: +pass:[set-cmd-text -s :bookmark-load -w]+
* +pass:[wIf]+: +pass:[devtools-focus]+
* +pass:[wIh]+: +pass:[devtools left]+
* +pass:[wIj]+: +pass:[devtools bottom]+
* +pass:[wIk]+: +pass:[devtools top]+

View File

@ -953,7 +953,8 @@ class AbstractTab(QWidget):
def _set_widget(self, widget: QWidget) -> None:
# pylint: disable=protected-access
self._widget = widget
self.data.splitter = miscwidgets.InspectorSplitter(widget)
self.data.splitter = miscwidgets.InspectorSplitter(
win_id=self.win_id, main_webview=widget)
self._layout.wrap(self, self.data.splitter)
self.history._history = widget.history()
self.history.private_api._history = widget.history()

View File

@ -335,6 +335,16 @@ def devtools(tab: apitypes.Tab,
raise cmdutils.CommandError(e)
@cmdutils.register()
@cmdutils.argument('tab', value=cmdutils.Value.cur_tab)
def devtools_focus(tab: apitypes.Tab) -> None:
"""Toggle focus between the devtools/tab."""
try:
tab.data.splitter.cycle_focus()
except apitypes.InspectorError as e:
raise cmdutils.CommandError(e)
@cmdutils.register(deprecated='Use :devtools instead')
@cmdutils.argument('tab', value=cmdutils.Value.cur_tab)
def inspector(tab: apitypes.Tab) -> None:

View File

@ -3154,6 +3154,7 @@ bindings.default:
wIk: devtools top
wIl: devtools right
wIw: devtools window
wIf: devtools-focus
gd: download
ad: download-cancel
cd: download-clear

View File

@ -28,10 +28,10 @@ from PyQt5.QtWidgets import (QLineEdit, QWidget, QHBoxLayout, QLabel,
from PyQt5.QtGui import QValidator, QPainter, QResizeEvent
from qutebrowser.config import config, configfiles
from qutebrowser.utils import utils, log
from qutebrowser.utils import utils, log, usertypes
from qutebrowser.misc import cmdhistory
from qutebrowser.browser import inspector
from qutebrowser.keyinput import keyutils
from qutebrowser.keyinput import keyutils, modeman
class MinimalLineEditMixin:
@ -383,8 +383,9 @@ class InspectorSplitter(QSplitter):
_PROTECTED_MAIN_SIZE = 150
_SMALL_SIZE_THRESHOLD = 300
def __init__(self, main_webview: QWidget, parent: QWidget = None) -> None:
def __init__(self, win_id: int, main_webview: QWidget, parent: QWidget = None) -> None:
super().__init__(parent)
self._win_id = win_id
self.addWidget(main_webview)
self.setFocusProxy(main_webview)
self.splitterMoved.connect(self._on_splitter_moved)
@ -393,6 +394,25 @@ class InspectorSplitter(QSplitter):
self._position = None # type: typing.Optional[inspector.Position]
self._preferred_size = None # type: typing.Optional[int]
def cycle_focus(self):
"""Cycle keyboard focus between the main/inspector widget."""
breakpoint()
if self.count() == 1:
raise inspector.Error("No inspector inside main window")
main_widget = self.widget(self._main_idx)
inspector_widget = self.widget(self._inspector_idx)
if not inspector_widget.isVisible():
raise inspector.Error("No inspector inside main window")
if main_widget.hasFocus():
inspector_widget.setFocus()
modeman.enter(self._win_id, usertypes.KeyMode.insert,
reason='Inspector focused', only_if_normal=True)
elif inspector_widget.hasFocus():
main_widget.setFocus()
def set_inspector(self, inspector_widget: inspector.AbstractWebInspector,
position: inspector.Position) -> None:
"""Set the position of the inspector."""

View File

@ -56,7 +56,8 @@ def inspector_widget(red_widget):
@pytest.fixture
def splitter(qtbot, webview_widget):
splitter = miscwidgets.InspectorSplitter(webview_widget)
splitter = miscwidgets.InspectorSplitter(
win_id=0, main_webview=webview_widget)
qtbot.add_widget(splitter)
return splitter

View File

@ -158,7 +158,8 @@ class TestInspectorSplitter:
@pytest.fixture
def splitter(self, qtbot, fake_webview):
inspector_splitter = miscwidgets.InspectorSplitter(fake_webview)
inspector_splitter = miscwidgets.InspectorSplitter(
win_id=0, main_webview=fake_webview)
qtbot.add_widget(inspector_splitter)
return inspector_splitter
@ -171,6 +172,11 @@ class TestInspectorSplitter:
splitter.show()
splitter.resize(800, 600)
def test_cycle_focus_no_inspector(self, splitter):
with pytest.raises(inspector.Error,
match='No inspector inside main window'):
splitter.cycle_focus()
@pytest.mark.parametrize(
'position, orientation, inspector_idx, webview_idx', [
(inspector.Position.left, Qt.Horizontal, 0, 1),
@ -192,6 +198,14 @@ class TestInspectorSplitter:
assert splitter.orientation() == orientation
def test_cycle_focus_hidden_inspector(self, splitter, fake_inspector):
splitter.set_inspector(fake_inspector, inspector.Position.right)
splitter.show()
fake_inspector.hide()
with pytest.raises(inspector.Error,
match='No inspector inside main window'):
splitter.cycle_focus()
@pytest.mark.parametrize(
'config, width, height, position, expected_size', [
# No config but enough big window