diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py index 24c669180..5a919bca5 100644 --- a/qutebrowser/completion/completer.py +++ b/qutebrowser/completion/completer.py @@ -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. diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py index 80e87dbe4..3e33f6614 100644 --- a/qutebrowser/completion/completionwidget.py +++ b/qutebrowser/completion/completionwidget.py @@ -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.""" diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 79a5546d3..1f549f847 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -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) diff --git a/tests/unit/completion/test_completer.py b/tests/unit/completion/test_completer.py index 9335bbf70..381871657 100644 --- a/tests/unit/completion/test_completer.py +++ b/tests/unit/completion/test_completer.py @@ -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) diff --git a/tests/unit/completion/test_completionwidget.py b/tests/unit/completion/test_completionwidget.py index 02d3977eb..e52b85fa0 100644 --- a/tests/unit/completion/test_completionwidget.py +++ b/tests/unit/completion/test_completionwidget.py @@ -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):