Merge branch 'mlochbaum-auto-open-fixes'
This commit is contained in:
commit
8bbadc79a0
@ -101,6 +101,8 @@ Changed
|
|||||||
- `tabs -> title-format` now treats an empty string as valid.
|
- `tabs -> title-format` now treats an empty string as valid.
|
||||||
- Bindings for `:`, `/` and `?` are now configured explicitly and not hardcoded
|
- Bindings for `:`, `/` and `?` are now configured explicitly and not hardcoded
|
||||||
anymore.
|
anymore.
|
||||||
|
- The `completion -> show` setting can now be set to `always`, `auto` or
|
||||||
|
`never`.
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
@ -120,6 +122,8 @@ Removed
|
|||||||
- The `ui -> hide-mouse-cursor` setting since it was completely broken and
|
- The `ui -> hide-mouse-cursor` setting since it was completely broken and
|
||||||
nobody seemed to care.
|
nobody seemed to care.
|
||||||
- The `hints -> opacity` setting - see the "Changed" section for details.
|
- The `hints -> opacity` setting - see the "Changed" section for details.
|
||||||
|
- The `completion -> auto-open` setting got merged into `completion -> show` and
|
||||||
|
thus removed.
|
||||||
|
|
||||||
Fixed
|
Fixed
|
||||||
~~~~~
|
~~~~~
|
||||||
|
@ -146,9 +146,9 @@ Contributors, sorted by the number of commits in descending order:
|
|||||||
* Antoni Boucher
|
* Antoni Boucher
|
||||||
* Lamar Pavel
|
* Lamar Pavel
|
||||||
* Jan Verbeek
|
* Jan Verbeek
|
||||||
|
* Marshall Lochbaum
|
||||||
* Bruno Oliveira
|
* Bruno Oliveira
|
||||||
* Alexander Cogneau
|
* Alexander Cogneau
|
||||||
* Marshall Lochbaum
|
|
||||||
* Felix Van der Jeugt
|
* Felix Van der Jeugt
|
||||||
* Martin Tournoij
|
* Martin Tournoij
|
||||||
* Raphael Pierzina
|
* Raphael Pierzina
|
||||||
|
@ -74,10 +74,9 @@
|
|||||||
[options="header",width="75%",cols="25%,75%"]
|
[options="header",width="75%",cols="25%,75%"]
|
||||||
|==============
|
|==============
|
||||||
|Setting|Description
|
|Setting|Description
|
||||||
|<<completion-auto-open,auto-open>>|Automatically open completion when typing.
|
|<<completion-show,show>>|When to show the autocompletion window.
|
||||||
|<<completion-download-path-suggestion,download-path-suggestion>>|What to display in the download filename input.
|
|<<completion-download-path-suggestion,download-path-suggestion>>|What to display in the download filename input.
|
||||||
|<<completion-timestamp-format,timestamp-format>>|How to format timestamps (e.g. for history)
|
|<<completion-timestamp-format,timestamp-format>>|How to format timestamps (e.g. for history)
|
||||||
|<<completion-show,show>>|Whether to show the autocompletion window.
|
|
||||||
|<<completion-height,height>>|The height of the completion, in px or as percentage of the window.
|
|<<completion-height,height>>|The height of the completion, in px or as percentage of the window.
|
||||||
|<<completion-cmd-history-max-items,cmd-history-max-items>>|How many commands to save in the command history.
|
|<<completion-cmd-history-max-items,cmd-history-max-items>>|How many commands to save in the command history.
|
||||||
|<<completion-web-history-max-items,web-history-max-items>>|How many URLs to show in the web history.
|
|<<completion-web-history-max-items,web-history-max-items>>|How many URLs to show in the web history.
|
||||||
@ -803,16 +802,17 @@ This setting is only available with the QtWebKit backend.
|
|||||||
== completion
|
== completion
|
||||||
Options related to completion and command history.
|
Options related to completion and command history.
|
||||||
|
|
||||||
[[completion-auto-open]]
|
[[completion-show]]
|
||||||
=== auto-open
|
=== show
|
||||||
Automatically open completion when typing.
|
When to show the autocompletion window.
|
||||||
|
|
||||||
Valid values:
|
Valid values:
|
||||||
|
|
||||||
* +true+
|
* +always+: Whenever a completion is available.
|
||||||
* +false+
|
* +auto+: Whenever a completion is requested.
|
||||||
|
* +never+: Never.
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[always]+
|
||||||
|
|
||||||
[[completion-download-path-suggestion]]
|
[[completion-download-path-suggestion]]
|
||||||
=== download-path-suggestion
|
=== download-path-suggestion
|
||||||
@ -832,17 +832,6 @@ How to format timestamps (e.g. for history)
|
|||||||
|
|
||||||
Default: +pass:[%Y-%m-%d]+
|
Default: +pass:[%Y-%m-%d]+
|
||||||
|
|
||||||
[[completion-show]]
|
|
||||||
=== show
|
|
||||||
Whether to show the autocompletion window.
|
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
|
||||||
|
|
||||||
[[completion-height]]
|
[[completion-height]]
|
||||||
=== height
|
=== height
|
||||||
The height of the completion, in px or as percentage of the window.
|
The height of the completion, in px or as percentage of the window.
|
||||||
|
@ -23,7 +23,7 @@ from PyQt5.QtCore import 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
|
||||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
from qutebrowser.utils import usertypes, log, utils
|
||||||
from qutebrowser.completion.models import instances, sortfilter
|
from qutebrowser.completion.models import instances, sortfilter
|
||||||
|
|
||||||
|
|
||||||
@ -40,15 +40,12 @@ class Completer(QObject):
|
|||||||
_last_cursor_pos: The old cursor position so we avoid double completion
|
_last_cursor_pos: The old cursor position so we avoid double completion
|
||||||
updates.
|
updates.
|
||||||
_last_text: The old command text so we avoid double completion updates.
|
_last_text: The old command text so we avoid double completion updates.
|
||||||
_signals_connected: Whether the signals are connected to update the
|
|
||||||
completion when the command widget requests that.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cmd, win_id, parent=None):
|
def __init__(self, cmd, win_id, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._win_id = win_id
|
self._win_id = win_id
|
||||||
self._cmd = cmd
|
self._cmd = cmd
|
||||||
self._signals_connected = False
|
|
||||||
self._ignore_change = False
|
self._ignore_change = False
|
||||||
self._empty_item_idx = None
|
self._empty_item_idx = None
|
||||||
self._timer = QTimer()
|
self._timer = QTimer()
|
||||||
@ -58,64 +55,12 @@ class Completer(QObject):
|
|||||||
self._cursor_part = None
|
self._cursor_part = None
|
||||||
self._last_cursor_pos = None
|
self._last_cursor_pos = None
|
||||||
self._last_text = None
|
self._last_text = None
|
||||||
|
self._cmd.update_completion.connect(self.schedule_completion_update)
|
||||||
objreg.get('config').changed.connect(self._on_auto_open_changed)
|
self._cmd.textChanged.connect(self._on_text_edited)
|
||||||
self._handle_signal_connections()
|
|
||||||
self._cmd.clear_completion_selection.connect(
|
|
||||||
self._handle_signal_connections)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return utils.get_repr(self)
|
return utils.get_repr(self)
|
||||||
|
|
||||||
@config.change_filter('completion', 'auto-open')
|
|
||||||
def _on_auto_open_changed(self):
|
|
||||||
self._handle_signal_connections()
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _handle_signal_connections(self):
|
|
||||||
self._connect_signals(config.get('completion', 'auto-open'))
|
|
||||||
|
|
||||||
def _connect_signals(self, connect=True):
|
|
||||||
"""Connect or disconnect the completion signals.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connect: Whether to connect (True) or disconnect (False) the
|
|
||||||
signals.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
True if the signals were connected (connect=True and aren't
|
|
||||||
connected yet) - otherwise False.
|
|
||||||
"""
|
|
||||||
connections = [
|
|
||||||
(self._cmd.update_completion, self.schedule_completion_update),
|
|
||||||
(self._cmd.textChanged, self._on_text_edited),
|
|
||||||
]
|
|
||||||
|
|
||||||
if connect and not self._signals_connected:
|
|
||||||
for sender, receiver in connections:
|
|
||||||
sender.connect(receiver)
|
|
||||||
self._signals_connected = True
|
|
||||||
return True
|
|
||||||
elif not connect:
|
|
||||||
for sender, receiver in connections:
|
|
||||||
try:
|
|
||||||
sender.disconnect(receiver)
|
|
||||||
except TypeError:
|
|
||||||
# Don't fail if not connected
|
|
||||||
pass
|
|
||||||
self._signals_connected = False
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _open_completion_if_needed(self):
|
|
||||||
"""If auto-open is false, temporarily connect signals.
|
|
||||||
|
|
||||||
Also opens the completion.
|
|
||||||
"""
|
|
||||||
if not config.get('completion', 'auto-open'):
|
|
||||||
connected = self._connect_signals(True)
|
|
||||||
if connected:
|
|
||||||
self._update_completion()
|
|
||||||
|
|
||||||
def _model(self):
|
def _model(self):
|
||||||
"""Convenience method to get the current completion model."""
|
"""Convenience method to get the current completion model."""
|
||||||
completion = self.parent()
|
completion = self.parent()
|
||||||
@ -244,7 +189,6 @@ class Completer(QObject):
|
|||||||
selected: New selection.
|
selected: New selection.
|
||||||
_deselected: Previous selection.
|
_deselected: Previous selection.
|
||||||
"""
|
"""
|
||||||
self._open_completion_if_needed()
|
|
||||||
indexes = selected.indexes()
|
indexes = selected.indexes()
|
||||||
if not indexes:
|
if not indexes:
|
||||||
return
|
return
|
||||||
@ -308,37 +252,24 @@ class Completer(QObject):
|
|||||||
# anything (yet)
|
# anything (yet)
|
||||||
# FIXME complete searches
|
# FIXME complete searches
|
||||||
# https://github.com/The-Compiler/qutebrowser/issues/32
|
# https://github.com/The-Compiler/qutebrowser/issues/32
|
||||||
completion.hide()
|
completion.set_model(None)
|
||||||
return
|
return
|
||||||
|
|
||||||
model = self._get_new_completion(parts, self._cursor_part)
|
model = self._get_new_completion(parts, self._cursor_part)
|
||||||
|
|
||||||
if model != self._model():
|
|
||||||
if model is None:
|
|
||||||
completion.hide()
|
|
||||||
else:
|
|
||||||
completion.set_model(model)
|
|
||||||
|
|
||||||
if model is None:
|
|
||||||
log.completion.debug("No completion model for {}.".format(parts))
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pattern = parts[self._cursor_part].strip()
|
pattern = parts[self._cursor_part].strip()
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pattern = ''
|
pattern = ''
|
||||||
completion.set_pattern(pattern)
|
|
||||||
|
|
||||||
log.completion.debug(
|
if model is None:
|
||||||
"New completion for {}: {}, with pattern '{}'".format(
|
log.completion.debug("No completion model for {}.".format(parts))
|
||||||
parts, model.srcmodel.__class__.__name__, pattern))
|
else:
|
||||||
|
log.completion.debug(
|
||||||
|
"New completion for {}: {}, with pattern '{}'".format(
|
||||||
|
parts, model.srcmodel.__class__.__name__, pattern))
|
||||||
|
|
||||||
if self._model().count() == 0:
|
completion.set_model(model, pattern)
|
||||||
completion.hide()
|
|
||||||
return
|
|
||||||
|
|
||||||
if completion.enabled:
|
|
||||||
completion.show()
|
|
||||||
|
|
||||||
def _split(self, keep=False):
|
def _split(self, keep=False):
|
||||||
"""Get the text split up in parts.
|
"""Get the text split up in parts.
|
||||||
|
@ -30,7 +30,7 @@ from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QItemSelectionModel,
|
|||||||
from qutebrowser.config import config, style
|
from qutebrowser.config import config, style
|
||||||
from qutebrowser.completion import completiondelegate
|
from qutebrowser.completion import completiondelegate
|
||||||
from qutebrowser.completion.models import base
|
from qutebrowser.completion.models import base
|
||||||
from qutebrowser.utils import objreg, utils, usertypes
|
from qutebrowser.utils import utils, usertypes
|
||||||
from qutebrowser.commands import cmdexc, cmdutils
|
from qutebrowser.commands import cmdexc, cmdutils
|
||||||
|
|
||||||
|
|
||||||
@ -42,12 +42,12 @@ class CompletionView(QTreeView):
|
|||||||
headers, and children show as flat list.
|
headers, and children show as flat list.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
enabled: Whether showing the CompletionView is enabled.
|
|
||||||
_win_id: The ID of the window this CompletionView is associated with.
|
_win_id: The ID of the window this CompletionView is associated with.
|
||||||
_height: The height to use for the CompletionView.
|
_height: The height to use for the CompletionView.
|
||||||
_height_perc: Either None or a percentage if height should be relative.
|
_height_perc: Either None or a percentage if height should be relative.
|
||||||
_delegate: The item delegate used.
|
_delegate: The item delegate used.
|
||||||
_column_widths: A list of column widths, in percent.
|
_column_widths: A list of column widths, in percent.
|
||||||
|
_active: Whether a selection is active.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
resize_completion: Emitted when the completion should be resized.
|
resize_completion: Emitted when the completion should be resized.
|
||||||
@ -109,12 +109,11 @@ class CompletionView(QTreeView):
|
|||||||
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
|
||||||
self.enabled = config.get('completion', 'show')
|
|
||||||
objreg.get('config').changed.connect(self.set_enabled)
|
|
||||||
# FIXME handle new aliases.
|
# FIXME handle new aliases.
|
||||||
# objreg.get('config').changed.connect(self.init_command_completion)
|
# objreg.get('config').changed.connect(self.init_command_completion)
|
||||||
|
|
||||||
self._column_widths = base.BaseCompletionModel.COLUMN_WIDTHS
|
self._column_widths = base.BaseCompletionModel.COLUMN_WIDTHS
|
||||||
|
self._active = False
|
||||||
|
|
||||||
self._delegate = completiondelegate.CompletionItemDelegate(self)
|
self._delegate = completiondelegate.CompletionItemDelegate(self)
|
||||||
self.setItemDelegate(self._delegate)
|
self.setItemDelegate(self._delegate)
|
||||||
@ -220,11 +219,9 @@ class CompletionView(QTreeView):
|
|||||||
Args:
|
Args:
|
||||||
which: 'next', 'prev', 'next-category', or 'prev-category'.
|
which: 'next', 'prev', 'next-category', or 'prev-category'.
|
||||||
"""
|
"""
|
||||||
# selmodel can be None if 'show' and 'auto-open' are set to False
|
if not self._active:
|
||||||
# https://github.com/The-Compiler/qutebrowser/issues/1731
|
|
||||||
selmodel = self.selectionModel()
|
|
||||||
if selmodel is None:
|
|
||||||
return
|
return
|
||||||
|
selmodel = self.selectionModel()
|
||||||
|
|
||||||
if which == 'next':
|
if which == 'next':
|
||||||
idx = self._next_idx(upwards=False)
|
idx = self._next_idx(upwards=False)
|
||||||
@ -243,56 +240,66 @@ class CompletionView(QTreeView):
|
|||||||
selmodel.setCurrentIndex(
|
selmodel.setCurrentIndex(
|
||||||
idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
|
idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
|
||||||
|
|
||||||
def set_model(self, model):
|
count = self.model().count()
|
||||||
|
if count == 0:
|
||||||
|
self.hide()
|
||||||
|
elif count == 1 and config.get('completion', 'quick-complete'):
|
||||||
|
self.hide()
|
||||||
|
elif config.get('completion', 'show') == 'auto':
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def set_model(self, model, pattern=None):
|
||||||
"""Switch completion to a new model.
|
"""Switch completion to a new model.
|
||||||
|
|
||||||
Called from on_update_completion().
|
Called from on_update_completion().
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
model: The model to use.
|
model: The model to use.
|
||||||
|
pattern: The filter pattern to set (what the user entered).
|
||||||
"""
|
"""
|
||||||
|
if model is None:
|
||||||
|
self._active = False
|
||||||
|
self.hide()
|
||||||
|
return
|
||||||
|
|
||||||
old_model = self.model()
|
old_model = self.model()
|
||||||
sel_model = self.selectionModel()
|
if model is not old_model:
|
||||||
|
sel_model = self.selectionModel()
|
||||||
|
|
||||||
self.setModel(model)
|
self.setModel(model)
|
||||||
|
self._active = True
|
||||||
|
|
||||||
if sel_model is not None:
|
if sel_model is not None:
|
||||||
sel_model.deleteLater()
|
sel_model.deleteLater()
|
||||||
if old_model is not None:
|
if old_model is not None:
|
||||||
old_model.deleteLater()
|
old_model.deleteLater()
|
||||||
|
|
||||||
|
if (config.get('completion', 'show') == 'always' and
|
||||||
|
model.count() > 0):
|
||||||
|
self.show()
|
||||||
|
else:
|
||||||
|
self.hide()
|
||||||
|
|
||||||
for i in range(model.rowCount()):
|
for i in range(model.rowCount()):
|
||||||
self.expand(model.index(i, 0))
|
self.expand(model.index(i, 0))
|
||||||
|
|
||||||
|
if pattern is not None:
|
||||||
|
model.set_pattern(pattern)
|
||||||
|
|
||||||
self._column_widths = model.srcmodel.COLUMN_WIDTHS
|
self._column_widths = model.srcmodel.COLUMN_WIDTHS
|
||||||
self._resize_columns()
|
self._resize_columns()
|
||||||
self.maybe_resize_completion()
|
self.maybe_resize_completion()
|
||||||
|
|
||||||
def set_pattern(self, pattern):
|
|
||||||
"""Set the completion pattern for the current model.
|
|
||||||
|
|
||||||
Called from on_update_completion().
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pattern: The filter pattern to set (what the user entered).
|
|
||||||
"""
|
|
||||||
self.model().set_pattern(pattern)
|
|
||||||
self.maybe_resize_completion()
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def maybe_resize_completion(self):
|
def maybe_resize_completion(self):
|
||||||
"""Emit the resize_completion signal if the config says so."""
|
"""Emit the resize_completion signal if the config says so."""
|
||||||
if config.get('completion', 'shrink'):
|
if config.get('completion', 'shrink'):
|
||||||
self.resize_completion.emit()
|
self.resize_completion.emit()
|
||||||
|
|
||||||
@config.change_filter('completion', 'show')
|
|
||||||
def set_enabled(self):
|
|
||||||
"""Update self.enabled when the config changed."""
|
|
||||||
self.enabled = config.get('completion', 'show')
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_clear_completion_selection(self):
|
def on_clear_completion_selection(self):
|
||||||
"""Clear the selection model when an item is activated."""
|
"""Clear the selection model when an item is activated."""
|
||||||
|
self.hide()
|
||||||
selmod = self.selectionModel()
|
selmod = self.selectionModel()
|
||||||
if selmod is not None:
|
if selmod is not None:
|
||||||
selmod.clearSelection()
|
selmod.clearSelection()
|
||||||
@ -300,6 +307,8 @@ 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."""
|
||||||
|
if not self._active:
|
||||||
|
return
|
||||||
super().selectionChanged(selected, deselected)
|
super().selectionChanged(selected, deselected)
|
||||||
self.selection_changed.emit(selected)
|
self.selection_changed.emit(selected)
|
||||||
|
|
||||||
|
@ -400,6 +400,7 @@ class ConfigManager(QObject):
|
|||||||
('ui', 'hide-mouse-cursor'),
|
('ui', 'hide-mouse-cursor'),
|
||||||
('general', 'wrap-search'),
|
('general', 'wrap-search'),
|
||||||
('hints', 'opacity'),
|
('hints', 'opacity'),
|
||||||
|
('completion', 'auto-open'),
|
||||||
]
|
]
|
||||||
CHANGED_OPTIONS = {
|
CHANGED_OPTIONS = {
|
||||||
('content', 'cookies-accept'):
|
('content', 'cookies-accept'):
|
||||||
@ -418,6 +419,8 @@ class ConfigManager(QObject):
|
|||||||
('colors', 'hints.fg'): _transform_hint_color,
|
('colors', 'hints.fg'): _transform_hint_color,
|
||||||
('colors', 'hints.fg.match'): _transform_hint_color,
|
('colors', 'hints.fg.match'): _transform_hint_color,
|
||||||
('fonts', 'hints'): _transform_hint_font,
|
('fonts', 'hints'): _transform_hint_font,
|
||||||
|
('completion', 'show'):
|
||||||
|
_get_value_transformer({'false': 'never', 'true': 'always'}),
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = pyqtSignal(str, str)
|
changed = pyqtSignal(str, str)
|
||||||
|
@ -438,9 +438,14 @@ def data(readonly=False):
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('completion', sect.KeyValue(
|
('completion', sect.KeyValue(
|
||||||
('auto-open',
|
('show',
|
||||||
SettingValue(typ.Bool(), 'true'),
|
SettingValue(typ.String(
|
||||||
"Automatically open completion when typing."),
|
valid_values=typ.ValidValues(
|
||||||
|
('always', "Whenever a completion is available."),
|
||||||
|
('auto', "Whenever a completion is requested."),
|
||||||
|
('never', "Never.")
|
||||||
|
)), 'always'),
|
||||||
|
"When to show the autocompletion window."),
|
||||||
|
|
||||||
('download-path-suggestion',
|
('download-path-suggestion',
|
||||||
SettingValue(
|
SettingValue(
|
||||||
@ -455,10 +460,6 @@ def data(readonly=False):
|
|||||||
SettingValue(typ.TimestampTemplate(none_ok=True), '%Y-%m-%d'),
|
SettingValue(typ.TimestampTemplate(none_ok=True), '%Y-%m-%d'),
|
||||||
"How to format timestamps (e.g. for history)"),
|
"How to format timestamps (e.g. for history)"),
|
||||||
|
|
||||||
('show',
|
|
||||||
SettingValue(typ.Bool(), 'true'),
|
|
||||||
"Whether to show the autocompletion window."),
|
|
||||||
|
|
||||||
('height',
|
('height',
|
||||||
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1),
|
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1),
|
||||||
'50%'),
|
'50%'),
|
||||||
|
@ -66,7 +66,7 @@ def completer_obj(qtbot, status_command_stub, config_stub, monkeypatch, stubs,
|
|||||||
"""Create the completer used for testing."""
|
"""Create the completer used for testing."""
|
||||||
monkeypatch.setattr('qutebrowser.completion.completer.QTimer',
|
monkeypatch.setattr('qutebrowser.completion.completer.QTimer',
|
||||||
stubs.InstaTimer)
|
stubs.InstaTimer)
|
||||||
config_stub.data = {'completion': {'auto-open': False}}
|
config_stub.data = {'completion': {'show': 'auto'}}
|
||||||
return completer.Completer(status_command_stub, 0, completion_widget_stub)
|
return completer.Completer(status_command_stub, 0, completion_widget_stub)
|
||||||
|
|
||||||
|
|
||||||
@ -199,12 +199,12 @@ def test_update_completion(txt, expected, status_command_stub, completer_obj,
|
|||||||
# this test uses | as a placeholder for the current cursor position
|
# this test uses | as a placeholder for the current cursor position
|
||||||
_set_cmd_prompt(status_command_stub, txt)
|
_set_cmd_prompt(status_command_stub, txt)
|
||||||
completer_obj.schedule_completion_update()
|
completer_obj.schedule_completion_update()
|
||||||
|
assert completion_widget_stub.set_model.call_count == 1
|
||||||
|
arg = completion_widget_stub.set_model.call_args[0][0]
|
||||||
|
# the outer model is just for sorting; srcmodel is the completion model
|
||||||
if expected is None:
|
if expected is None:
|
||||||
assert not completion_widget_stub.set_model.called
|
assert arg == expected
|
||||||
else:
|
else:
|
||||||
assert completion_widget_stub.set_model.call_count == 1
|
|
||||||
arg = completion_widget_stub.set_model.call_args[0][0]
|
|
||||||
# the outer model is just for sorting; srcmodel is the completion model
|
|
||||||
assert arg.srcmodel.kind == expected
|
assert arg.srcmodel.kind == expected
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ def completionview(qtbot, status_command_stub, config_stub, win_registry,
|
|||||||
"""Create the CompletionView used for testing."""
|
"""Create the CompletionView used for testing."""
|
||||||
config_stub.data = {
|
config_stub.data = {
|
||||||
'completion': {
|
'completion': {
|
||||||
'show': True,
|
'show': 'always',
|
||||||
'auto-open': True,
|
|
||||||
'scrollbar-width': 12,
|
'scrollbar-width': 12,
|
||||||
'scrollbar-padding': 2,
|
'scrollbar-padding': 2,
|
||||||
'shrink': False,
|
'shrink': False,
|
||||||
|
'quick-complete': False,
|
||||||
},
|
},
|
||||||
'colors': {
|
'colors': {
|
||||||
'completion.fg': QColor(),
|
'completion.fg': QColor(),
|
||||||
@ -83,8 +83,7 @@ def test_set_model(completionview):
|
|||||||
def test_set_pattern(completionview):
|
def test_set_pattern(completionview):
|
||||||
model = sortfilter.CompletionFilterModel(base.BaseCompletionModel())
|
model = sortfilter.CompletionFilterModel(base.BaseCompletionModel())
|
||||||
model.set_pattern = unittest.mock.Mock()
|
model.set_pattern = unittest.mock.Mock()
|
||||||
completionview.set_model(model)
|
completionview.set_model(model, 'foo')
|
||||||
completionview.set_pattern('foo')
|
|
||||||
model.set_pattern.assert_called_with('foo')
|
model.set_pattern.assert_called_with('foo')
|
||||||
|
|
||||||
|
|
||||||
@ -170,11 +169,36 @@ def test_completion_item_focus(which, tree, count, expected, completionview):
|
|||||||
assert filtermodel.data(idx) == expected
|
assert filtermodel.data(idx) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_completion_item_focus_no_model(completionview):
|
@pytest.mark.parametrize('show', ['always', 'auto', 'never'])
|
||||||
"""Test that next/prev won't crash with no model set.
|
@pytest.mark.parametrize('rows', [[], ['Aa'], ['Aa', 'Bb']])
|
||||||
|
@pytest.mark.parametrize('quick_complete', [True, False])
|
||||||
|
def test_completion_show(show, rows, quick_complete, completionview,
|
||||||
|
config_stub):
|
||||||
|
"""Test that the completion widget is shown at appropriate times.
|
||||||
|
|
||||||
This can happen if completion.show and completion.auto-open are False.
|
Args:
|
||||||
Regression test for issue #1722.
|
show: The completion show config setting.
|
||||||
|
rows: Each entry represents a completion category with only one item.
|
||||||
|
quick_complete: The completion quick-complete config setting.
|
||||||
"""
|
"""
|
||||||
completionview.completion_item_focus('prev')
|
config_stub.data['completion']['show'] = show
|
||||||
|
config_stub.data['completion']['quick-complete'] = quick_complete
|
||||||
|
|
||||||
|
model = base.BaseCompletionModel()
|
||||||
|
for name in rows:
|
||||||
|
cat = QStandardItem()
|
||||||
|
model.appendRow(cat)
|
||||||
|
cat.appendRow(QStandardItem(name))
|
||||||
|
filtermodel = sortfilter.CompletionFilterModel(model,
|
||||||
|
parent=completionview)
|
||||||
|
|
||||||
|
assert not completionview.isVisible()
|
||||||
|
completionview.set_model(filtermodel)
|
||||||
|
assert completionview.isVisible() == (show == 'always' and len(rows) > 0)
|
||||||
completionview.completion_item_focus('next')
|
completionview.completion_item_focus('next')
|
||||||
|
expected = (show != 'never' and len(rows) > 0 and
|
||||||
|
not (quick_complete and len(rows) == 1))
|
||||||
|
assert completionview.isVisible() == expected
|
||||||
|
completionview.set_model(None)
|
||||||
|
completionview.completion_item_focus('next')
|
||||||
|
assert not completionview.isVisible()
|
||||||
|
Loading…
Reference in New Issue
Block a user