Decouple Completer and CompletionView.
Rather than having a CompletionView instantiate and register a Completer, instantiate both in MainWindow. The CompletionView is the parent of the Completer, and communicates by emitting selection_changed, meaning it no longer needs to contain a reference to the Completer.
This commit is contained in:
parent
d836fcb118
commit
b9cf9d180b
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
"""Completer attached to a CompletionView."""
|
"""Completer attached to a CompletionView."""
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QTimer
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QTimer, QItemSelection
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.commands import cmdutils, runners
|
from qutebrowser.commands import cmdutils, runners
|
||||||
@ -249,7 +249,8 @@ class Completer(QObject):
|
|||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def selection_changed(self, selected, _deselected):
|
@pyqtSlot(QItemSelection, QItemSelection)
|
||||||
|
def on_selection_changed(self, selected, _deselected):
|
||||||
"""Change the completed part if a new item was selected.
|
"""Change the completed part if a new item was selected.
|
||||||
|
|
||||||
Called from the views selectionChanged method.
|
Called from the views selectionChanged method.
|
||||||
|
@ -24,7 +24,8 @@ subclasses to provide completions.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
|
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel
|
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QItemSelectionModel,
|
||||||
|
QItemSelection)
|
||||||
|
|
||||||
from qutebrowser.config import config, style
|
from qutebrowser.config import config, style
|
||||||
from qutebrowser.completion import completiondelegate, completer
|
from qutebrowser.completion import completiondelegate, completer
|
||||||
@ -50,6 +51,7 @@ class CompletionView(QTreeView):
|
|||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
resize_completion: Emitted when the completion should be resized.
|
resize_completion: Emitted when the completion should be resized.
|
||||||
|
selection_changed: Emitted when the completion item selection changes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Drawing the item foreground will be done by CompletionItemDelegate, so we
|
# Drawing the item foreground will be done by CompletionItemDelegate, so we
|
||||||
@ -102,16 +104,11 @@ class CompletionView(QTreeView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
resize_completion = pyqtSignal()
|
resize_completion = pyqtSignal()
|
||||||
|
selection_changed = pyqtSignal(QItemSelection, QItemSelection)
|
||||||
|
|
||||||
def __init__(self, win_id, parent=None):
|
def __init__(self, win_id, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._win_id = win_id
|
self._win_id = win_id
|
||||||
objreg.register('completion', self, scope='window', window=win_id)
|
|
||||||
cmd = objreg.get('status-command', scope='window', window=win_id)
|
|
||||||
completer_obj = completer.Completer(cmd, win_id, self)
|
|
||||||
completer_obj.next_prev_item.connect(self.on_next_prev_item)
|
|
||||||
objreg.register('completer', completer_obj, scope='window',
|
|
||||||
window=win_id)
|
|
||||||
self.enabled = config.get('completion', 'show')
|
self.enabled = config.get('completion', 'show')
|
||||||
objreg.get('config').changed.connect(self.set_enabled)
|
objreg.get('config').changed.connect(self.set_enabled)
|
||||||
# FIXME handle new aliases.
|
# FIXME handle new aliases.
|
||||||
@ -262,9 +259,7 @@ class CompletionView(QTreeView):
|
|||||||
def selectionChanged(self, selected, deselected):
|
def selectionChanged(self, selected, deselected):
|
||||||
"""Extend selectionChanged to call completers selection_changed."""
|
"""Extend selectionChanged to call completers selection_changed."""
|
||||||
super().selectionChanged(selected, deselected)
|
super().selectionChanged(selected, deselected)
|
||||||
completer_obj = objreg.get('completer', scope='window',
|
self.selection_changed.emit(selected, deselected)
|
||||||
window=self._win_id)
|
|
||||||
completer_obj.selection_changed(selected, deselected)
|
|
||||||
|
|
||||||
def resizeEvent(self, e):
|
def resizeEvent(self, e):
|
||||||
"""Extend resizeEvent to adjust column size."""
|
"""Extend resizeEvent to adjust column size."""
|
||||||
|
@ -32,7 +32,7 @@ from qutebrowser.config import config
|
|||||||
from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils
|
from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils
|
||||||
from qutebrowser.mainwindow import tabbedbrowser
|
from qutebrowser.mainwindow import tabbedbrowser
|
||||||
from qutebrowser.mainwindow.statusbar import bar
|
from qutebrowser.mainwindow.statusbar import bar
|
||||||
from qutebrowser.completion import completionwidget
|
from qutebrowser.completion import completionwidget, completer
|
||||||
from qutebrowser.keyinput import modeman
|
from qutebrowser.keyinput import modeman
|
||||||
from qutebrowser.browser import commands, downloadview, hints
|
from qutebrowser.browser import commands, downloadview, hints
|
||||||
from qutebrowser.browser.webkit import downloads
|
from qutebrowser.browser.webkit import downloads
|
||||||
@ -158,6 +158,15 @@ class MainWindow(QWidget):
|
|||||||
self._downloadview.show()
|
self._downloadview.show()
|
||||||
|
|
||||||
self._completion = completionwidget.CompletionView(self.win_id, self)
|
self._completion = completionwidget.CompletionView(self.win_id, self)
|
||||||
|
cmd = objreg.get('status-command', scope='window', window=self.win_id)
|
||||||
|
completer_obj = completer.Completer(cmd, self.win_id, self._completion)
|
||||||
|
completer_obj.next_prev_item.connect(self._completion.on_next_prev_item)
|
||||||
|
self._completion.selection_changed.connect(
|
||||||
|
completer_obj.on_selection_changed)
|
||||||
|
objreg.register('completer', completer_obj, scope='window',
|
||||||
|
window=self.win_id)
|
||||||
|
objreg.register('completion', self._completion, scope='window',
|
||||||
|
window=self.win_id)
|
||||||
|
|
||||||
self._commandrunner = runners.CommandRunner(self.win_id,
|
self._commandrunner = runners.CommandRunner(self.win_id,
|
||||||
partial_match=True)
|
partial_match=True)
|
||||||
|
@ -193,10 +193,10 @@ def test_completion_item_next(completer_obj, status_command_stub,
|
|||||||
(':foo |', '', True, 1, ":foo '' |"),
|
(':foo |', '', True, 1, ":foo '' |"),
|
||||||
(':foo |', None, True, 1, ":foo |"),
|
(':foo |', None, True, 1, ":foo |"),
|
||||||
])
|
])
|
||||||
def test_selection_changed(before, newtxt, count, quick_complete, after,
|
def test_on_selection_changed(before, newtxt, count, quick_complete, after,
|
||||||
completer_obj, status_command_stub,
|
completer_obj, status_command_stub,
|
||||||
completion_widget_stub, config_stub):
|
completion_widget_stub, config_stub):
|
||||||
"""Test that change_completed_part modifies the cmd text properly.
|
"""Test that on_selection_changed modifies the cmd text properly.
|
||||||
|
|
||||||
The | represents the current cursor position in the cmd prompt.
|
The | represents the current cursor position in the cmd prompt.
|
||||||
If quick-complete is True and there is only 1 completion (count == 1),
|
If quick-complete is True and there is only 1 completion (count == 1),
|
||||||
@ -213,6 +213,6 @@ def test_selection_changed(before, newtxt, count, quick_complete, after,
|
|||||||
_set_cmd_prompt(status_command_stub, before)
|
_set_cmd_prompt(status_command_stub, before)
|
||||||
# schedule_completion_update is needed to pick up the cursor position
|
# schedule_completion_update is needed to pick up the cursor position
|
||||||
completer_obj.schedule_completion_update()
|
completer_obj.schedule_completion_update()
|
||||||
completer_obj.selection_changed(selection, None)
|
completer_obj.on_selection_changed(selection, None)
|
||||||
model.data.assert_called_with(indexes[0])
|
model.data.assert_called_with(indexes[0])
|
||||||
_validate_cmd_prompt(status_command_stub, after)
|
_validate_cmd_prompt(status_command_stub, after)
|
||||||
|
@ -29,7 +29,7 @@ from qutebrowser.completion.models import base, sortfilter
|
|||||||
from qutebrowser.utils import objreg
|
from qutebrowser.utils import objreg
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.fixture
|
||||||
def completionview(qtbot, status_command_stub, config_stub, win_registry,
|
def completionview(qtbot, status_command_stub, config_stub, win_registry,
|
||||||
mocker):
|
mocker):
|
||||||
"""Create the CompletionView used for testing."""
|
"""Create the CompletionView used for testing."""
|
||||||
@ -65,10 +65,7 @@ def completionview(qtbot, status_command_stub, config_stub, win_registry,
|
|||||||
mocker.patch('qutebrowser.completion.completer.Completer', autospec=True)
|
mocker.patch('qutebrowser.completion.completer.Completer', autospec=True)
|
||||||
view = completionwidget.CompletionView(win_id=0)
|
view = completionwidget.CompletionView(win_id=0)
|
||||||
qtbot.addWidget(view)
|
qtbot.addWidget(view)
|
||||||
yield view
|
return view
|
||||||
# the constructor registers both 'completion' (itself) and 'completer'
|
|
||||||
objreg.delete('completion', scope='window', window=0)
|
|
||||||
objreg.delete('completer', scope='window', window=0)
|
|
||||||
|
|
||||||
|
|
||||||
def test_set_model(completionview):
|
def test_set_model(completionview):
|
||||||
|
Loading…
Reference in New Issue
Block a user