Merge pull request #3237 from rcorre/completionsort

Fix completion sorting
This commit is contained in:
Florian Bruhin 2017-11-03 14:36:42 +01:00 committed by GitHub
commit 0f28804032
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 23 deletions

View File

@ -29,7 +29,7 @@ def option(*, info):
model = completionmodel.CompletionModel(column_widths=(20, 70, 10)) model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
options = ((opt.name, opt.description, info.config.get_str(opt.name)) options = ((opt.name, opt.description, info.config.get_str(opt.name))
for opt in configdata.DATA.values()) for opt in configdata.DATA.values())
model.add_category(listcategory.ListCategory("Options", sorted(options))) model.add_category(listcategory.ListCategory("Options", options))
return model return model
@ -39,7 +39,7 @@ def customized_option(*, info):
options = ((opt.name, opt.description, info.config.get_str(opt.name)) options = ((opt.name, opt.description, info.config.get_str(opt.name))
for opt, _value in info.config) for opt, _value in info.config)
model.add_category(listcategory.ListCategory("Customized options", model.add_category(listcategory.ListCategory("Customized options",
sorted(options))) options))
return model return model
@ -66,8 +66,7 @@ def value(optname, *_values, info):
vals = opt.typ.complete() vals = opt.typ.complete()
if vals is not None: if vals is not None:
model.add_category(listcategory.ListCategory("Completions", model.add_category(listcategory.ListCategory("Completions", vals))
sorted(vals)))
return model return model

View File

@ -31,7 +31,7 @@ class ListCategory(QSortFilterProxyModel):
"""Expose a list of items as a category for the CompletionModel.""" """Expose a list of items as a category for the CompletionModel."""
def __init__(self, name, items, delete_func=None, parent=None): def __init__(self, name, items, sort=True, delete_func=None, parent=None):
super().__init__(parent) super().__init__(parent)
self.name = name self.name = name
self.srcmodel = QStandardItemModel(parent=self) self.srcmodel = QStandardItemModel(parent=self)
@ -43,6 +43,7 @@ class ListCategory(QSortFilterProxyModel):
self.srcmodel.appendRow([QStandardItem(x) for x in item]) self.srcmodel.appendRow([QStandardItem(x) for x in item])
self.setSourceModel(self.srcmodel) self.setSourceModel(self.srcmodel)
self.delete_func = delete_func self.delete_func = delete_func
self._sort = sort
def set_pattern(self, val): def set_pattern(self, val):
"""Setter for pattern. """Setter for pattern.
@ -60,19 +61,33 @@ class ListCategory(QSortFilterProxyModel):
sortcol = 0 sortcol = 0
self.sort(sortcol) self.sort(sortcol)
def lessThan(self, _lindex, rindex): def lessThan(self, lindex, rindex):
"""Custom sorting implementation. """Custom sorting implementation.
Prefers all items which start with self._pattern. Other than that, keep Prefers all items which start with self._pattern. Other than that, uses
items in their original order. normal Python string sorting.
Args: Args:
_lindex: The QModelIndex of the left item (*left* < right) lindex: The QModelIndex of the left item (*left* < right)
rindex: The QModelIndex of the right item (left < *right*) rindex: The QModelIndex of the right item (left < *right*)
Return: Return:
True if left < right, else False True if left < right, else False
""" """
qtutils.ensure_valid(lindex)
qtutils.ensure_valid(rindex) qtutils.ensure_valid(rindex)
left = self.srcmodel.data(lindex)
right = self.srcmodel.data(rindex) right = self.srcmodel.data(rindex)
return not right.startswith(self._pattern)
leftstart = left.startswith(self._pattern)
rightstart = right.startswith(self._pattern)
if leftstart and not rightstart:
return True
elif rightstart and not leftstart:
return False
elif self._sort:
return left < right
else:
return False

View File

@ -43,7 +43,7 @@ def helptopic(*, info):
for opt in configdata.DATA.values()) for opt in configdata.DATA.values())
model.add_category(listcategory.ListCategory("Commands", cmdlist)) model.add_category(listcategory.ListCategory("Commands", cmdlist))
model.add_category(listcategory.ListCategory("Settings", sorted(settings))) model.add_category(listcategory.ListCategory("Settings", settings))
return model return model
@ -59,7 +59,8 @@ def quickmark(*, info=None): # pylint: disable=unused-argument
model = completionmodel.CompletionModel(column_widths=(30, 70, 0)) model = completionmodel.CompletionModel(column_widths=(30, 70, 0))
marks = objreg.get('quickmark-manager').marks.items() marks = objreg.get('quickmark-manager').marks.items()
model.add_category(listcategory.ListCategory('Quickmarks', marks, model.add_category(listcategory.ListCategory('Quickmarks', marks,
delete_func=delete)) delete_func=delete,
sort=False))
return model return model
@ -75,7 +76,8 @@ def bookmark(*, info=None): # pylint: disable=unused-argument
model = completionmodel.CompletionModel(column_widths=(30, 70, 0)) model = completionmodel.CompletionModel(column_widths=(30, 70, 0))
marks = objreg.get('bookmark-manager').marks.items() marks = objreg.get('bookmark-manager').marks.items()
model.add_category(listcategory.ListCategory('Bookmarks', marks, model.add_category(listcategory.ListCategory('Bookmarks', marks,
delete_func=delete)) delete_func=delete,
sort=False))
return model return model

View File

@ -61,9 +61,9 @@ def url(*, info):
bookmarks = objreg.get('bookmark-manager').marks.items() bookmarks = objreg.get('bookmark-manager').marks.items()
model.add_category(listcategory.ListCategory( model.add_category(listcategory.ListCategory(
'Quickmarks', quickmarks, delete_func=_delete_quickmark)) 'Quickmarks', quickmarks, delete_func=_delete_quickmark, sort=False))
model.add_category(listcategory.ListCategory( model.add_category(listcategory.ListCategory(
'Bookmarks', bookmarks, delete_func=_delete_bookmark)) 'Bookmarks', bookmarks, delete_func=_delete_bookmark, sort=False))
if info.config.get('completion.web_history_max_items') != 0: if info.config.get('completion.web_history_max_items') != 0:
hist_cat = histcategory.HistoryCategory(delete_func=_delete_history) hist_cat = histcategory.HistoryCategory(delete_func=_delete_history)

View File

@ -147,7 +147,7 @@ def test_remove_rows(hist, model_validator):
cat.set_pattern('') cat.set_pattern('')
hist.delete('url', 'foo') hist.delete('url', 'foo')
cat.removeRows(0, 1) cat.removeRows(0, 1)
model_validator.validate([('bar', 'Bar', '1970-01-01')]) model_validator.validate([('bar', 'Bar')])
def test_remove_rows_fetch(hist): def test_remove_rows_fetch(hist):

View File

@ -24,27 +24,36 @@ import pytest
from qutebrowser.completion.models import listcategory from qutebrowser.completion.models import listcategory
@pytest.mark.parametrize('pattern, before, after', [ @pytest.mark.parametrize('pattern, before, after, after_nosort', [
('foo', ('foo',
[('foo', ''), ('bar', '')], [('foo', ''), ('bar', '')],
[('foo', '')],
[('foo', '')]), [('foo', '')]),
('foo', ('foo',
[('foob', ''), ('fooc', ''), ('fooa', '')], [('foob', ''), ('fooc', ''), ('fooa', '')],
[('fooa', ''), ('foob', ''), ('fooc', '')],
[('foob', ''), ('fooc', ''), ('fooa', '')]), [('foob', ''), ('fooc', ''), ('fooa', '')]),
# prefer foobar as it starts with the pattern # prefer foobar as it starts with the pattern
('foo', ('foo',
[('barfoo', ''), ('foobar', '')], [('barfoo', ''), ('foobaz', ''), ('foobar', '')],
[('foobar', ''), ('barfoo', '')]), [('foobar', ''), ('foobaz', ''), ('barfoo', '')],
[('foobaz', ''), ('foobar', ''), ('barfoo', '')]),
('foo', ('foo',
[('foo', 'bar'), ('bar', 'foo'), ('bar', 'bar')], [('foo', 'bar'), ('bar', 'foo'), ('bar', 'bar')],
[('foo', 'bar'), ('bar', 'foo')],
[('foo', 'bar'), ('bar', 'foo')]), [('foo', 'bar'), ('bar', 'foo')]),
]) ])
def test_set_pattern(pattern, before, after, model_validator): def test_set_pattern(pattern, before, after, after_nosort, model_validator):
"""Validate the filtering and sorting results of set_pattern.""" """Validate the filtering and sorting results of set_pattern."""
cat = listcategory.ListCategory('Foo', before) cat = listcategory.ListCategory('Foo', before)
model_validator.set_model(cat) model_validator.set_model(cat)
cat.set_pattern(pattern) cat.set_pattern(pattern)
model_validator.validate(after) model_validator.validate(after)
cat = listcategory.ListCategory('Foo', before, sort=False)
model_validator.set_model(cat)
cat.set_pattern(pattern)
model_validator.validate(after_nosort)

View File

@ -466,9 +466,9 @@ def test_session_completion(qtmodeltester, session_manager_stub):
qtmodeltester.check(model) qtmodeltester.check(model)
_check_completions(model, { _check_completions(model, {
"Sessions": [('default', None, None), "Sessions": [('1', None, None),
('1', None, None), ('2', None, None),
('2', None, None)] ('default', None, None)]
}) })