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:
Ryan Roden-Corrent 2016-07-27 07:39:25 -04:00
parent d836fcb118
commit b9cf9d180b
5 changed files with 23 additions and 21 deletions

View File

@ -19,7 +19,7 @@
"""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.commands import cmdutils, runners
@ -249,7 +249,8 @@ class Completer(QObject):
else:
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.
Called from the views selectionChanged method.

View File

@ -24,7 +24,8 @@ subclasses to provide completions.
"""
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.completion import completiondelegate, completer
@ -50,6 +51,7 @@ class CompletionView(QTreeView):
Signals:
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
@ -102,16 +104,11 @@ class CompletionView(QTreeView):
"""
resize_completion = pyqtSignal()
selection_changed = pyqtSignal(QItemSelection, QItemSelection)
def __init__(self, win_id, parent=None):
super().__init__(parent)
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')
objreg.get('config').changed.connect(self.set_enabled)
# FIXME handle new aliases.
@ -262,9 +259,7 @@ class CompletionView(QTreeView):
def selectionChanged(self, selected, deselected):
"""Extend selectionChanged to call completers selection_changed."""
super().selectionChanged(selected, deselected)
completer_obj = objreg.get('completer', scope='window',
window=self._win_id)
completer_obj.selection_changed(selected, deselected)
self.selection_changed.emit(selected, deselected)
def resizeEvent(self, e):
"""Extend resizeEvent to adjust column size."""

View File

@ -32,7 +32,7 @@ from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils
from qutebrowser.mainwindow import tabbedbrowser
from qutebrowser.mainwindow.statusbar import bar
from qutebrowser.completion import completionwidget
from qutebrowser.completion import completionwidget, completer
from qutebrowser.keyinput import modeman
from qutebrowser.browser import commands, downloadview, hints
from qutebrowser.browser.webkit import downloads
@ -158,6 +158,15 @@ class MainWindow(QWidget):
self._downloadview.show()
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,
partial_match=True)

View File

@ -193,10 +193,10 @@ def test_completion_item_next(completer_obj, status_command_stub,
(':foo |', '', 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,
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.
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)
# schedule_completion_update is needed to pick up the cursor position
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])
_validate_cmd_prompt(status_command_stub, after)

View File

@ -29,7 +29,7 @@ from qutebrowser.completion.models import base, sortfilter
from qutebrowser.utils import objreg
@pytest.yield_fixture
@pytest.fixture
def completionview(qtbot, status_command_stub, config_stub, win_registry,
mocker):
"""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)
view = completionwidget.CompletionView(win_id=0)
qtbot.addWidget(view)
yield view
# the constructor registers both 'completion' (itself) and 'completer'
objreg.delete('completion', scope='window', window=0)
objreg.delete('completer', scope='window', window=0)
return view
def test_set_model(completionview):