Don't perform alphabetical sort in listcategory.

Instead, expect the data to be given in the desired order. Completion
functions should sort their data _if_ they want it sorted in the
completion. This has a few implications:

- {book,quick}marks appear in the same order they do in the text file.
  This means users can rearrange their mark files for custom sorting.
  Fixes #2354
- Sessions are sorted as they appear in the session manager
- Tabs are sorted numerically, not alphabetically (Fixes #2883)

Note that prefix-based filter sorting is still performed, so items
starting with the filter pattern come first.
This commit is contained in:
Ryan Roden-Corrent 2017-08-05 17:03:40 -04:00
parent 49b858e359
commit 6e025c1bb0
5 changed files with 29 additions and 42 deletions

View File

@ -29,7 +29,7 @@ def section():
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
sections = ((name, configdata.SECTION_DESC[name].splitlines()[0].strip())
for name in configdata.DATA)
model.add_category(listcategory.ListCategory("Sections", sections))
model.add_category(listcategory.ListCategory("Sections", sorted(sections)))
return model
@ -57,7 +57,7 @@ def option(sectname):
config = objreg.get('config')
val = config.get(sectname, name, raw=True)
options.append((name, desc, val))
model.add_category(listcategory.ListCategory(sectname, options))
model.add_category(listcategory.ListCategory(sectname, sorted(options)))
return model
@ -92,5 +92,6 @@ def value(sectname, optname):
[(current, "Current value"), (default, "Default value")])
model.add_category(cur_cat)
if vals is not None:
model.add_category(listcategory.ListCategory("Completions", vals))
model.add_category(listcategory.ListCategory("Completions",
sorted(vals)))
return model

View File

@ -60,33 +60,19 @@ class ListCategory(QSortFilterProxyModel):
sortcol = 0
self.sort(sortcol)
def lessThan(self, lindex, rindex):
def lessThan(self, _lindex, rindex):
"""Custom sorting implementation.
Prefers all items which start with self._pattern. Other than that, uses
normal Python string sorting.
Prefers all items which start with self._pattern. Other than that, keep
items in their original order.
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*)
Return:
True if left < right, else False
"""
qtutils.ensure_valid(lindex)
qtutils.ensure_valid(rindex)
left = self.srcmodel.data(lindex)
right = self.srcmodel.data(rindex)
leftstart = left.startswith(self._pattern)
rightstart = right.startswith(self._pattern)
if leftstart and rightstart:
return left < right
elif leftstart:
return True
elif rightstart:
return False
else:
return left < right
return not right.startswith(self._pattern)

View File

@ -54,7 +54,7 @@ def helptopic():
settings.append((name, desc))
model.add_category(listcategory.ListCategory("Commands", cmdlist))
model.add_category(listcategory.ListCategory("Settings", settings))
model.add_category(listcategory.ListCategory("Settings", sorted(settings)))
return model
@ -180,4 +180,4 @@ def _get_cmd_completions(include_hidden, include_aliases, prefix=''):
bindings = ', '.join(cmd_to_keys.get(name, []))
cmdlist.append((name, "Alias for '{}'".format(cmd), bindings))
return cmdlist
return sorted(cmdlist)

View File

@ -31,7 +31,7 @@ from qutebrowser.completion.models import listcategory
('foo',
[('foob', ''), ('fooc', ''), ('fooa', '')],
[('fooa', ''), ('foob', ''), ('fooc', '')]),
[('foob', ''), ('fooc', ''), ('fooa', '')]),
# prefer foobar as it starts with the pattern
('foo',

View File

@ -119,8 +119,8 @@ def quickmarks(quickmark_manager_stub):
"""Pre-populate the quickmark-manager stub with some quickmarks."""
quickmark_manager_stub.marks = collections.OrderedDict([
('aw', 'https://wiki.archlinux.org'),
('ddg', 'https://duckduckgo.com'),
('wiki', 'https://wikipedia.org'),
('ddg', 'https://duckduckgo.com'),
])
return quickmark_manager_stub
@ -246,16 +246,16 @@ def test_quickmark_completion(qtmodeltester, quickmarks):
_check_completions(model, {
"Quickmarks": [
('aw', 'https://wiki.archlinux.org', None),
('ddg', 'https://duckduckgo.com', None),
('wiki', 'https://wikipedia.org', None),
('ddg', 'https://duckduckgo.com', None),
]
})
@pytest.mark.parametrize('row, removed', [
(0, 'aw'),
(1, 'ddg'),
(2, 'wiki'),
(1, 'wiki'),
(2, 'ddg'),
])
def test_quickmark_completion_delete(qtmodeltester, quickmarks, row, removed):
"""Test deleting a quickmark from the quickmark completion model."""
@ -282,17 +282,17 @@ def test_bookmark_completion(qtmodeltester, bookmarks):
_check_completions(model, {
"Bookmarks": [
('http://qutebrowser.org', 'qutebrowser | qutebrowser', None),
('https://github.com', 'GitHub', None),
('https://python.org', 'Welcome to Python.org', None),
('http://qutebrowser.org', 'qutebrowser | qutebrowser', None),
]
})
@pytest.mark.parametrize('row, removed', [
(0, 'http://qutebrowser.org'),
(1, 'https://github.com'),
(2, 'https://python.org'),
(0, 'https://github.com'),
(1, 'https://python.org'),
(2, 'http://qutebrowser.org'),
])
def test_bookmark_completion_delete(qtmodeltester, bookmarks, row, removed):
"""Test deleting a quickmark from the quickmark completion model."""
@ -326,14 +326,14 @@ def test_url_completion(qtmodeltester, web_history_populated,
_check_completions(model, {
"Quickmarks": [
('https://duckduckgo.com', 'ddg', None),
('https://wiki.archlinux.org', 'aw', None),
('https://wikipedia.org', 'wiki', None),
('https://duckduckgo.com', 'ddg', None),
],
"Bookmarks": [
('http://qutebrowser.org', 'qutebrowser | qutebrowser', None),
('https://github.com', 'GitHub', None),
('https://python.org', 'Welcome to Python.org', None),
('http://qutebrowser.org', 'qutebrowser | qutebrowser', None),
],
"History": [
('https://github.com', 'https://github.com', '2016-05-01'),
@ -385,12 +385,12 @@ def test_url_completion_delete_bookmark(qtmodeltester, bookmarks,
# sanity checks
assert model.data(parent) == "Bookmarks"
assert model.data(idx) == 'https://github.com'
assert model.data(idx) == 'https://python.org'
assert 'https://github.com' in bookmarks.marks
len_before = len(bookmarks.marks)
model.delete_cur_item(idx)
assert 'https://github.com' not in bookmarks.marks
assert 'https://python.org' not in bookmarks.marks
assert len_before == len(bookmarks.marks) + 1
@ -408,12 +408,12 @@ def test_url_completion_delete_quickmark(qtmodeltester,
# sanity checks
assert model.data(parent) == "Quickmarks"
assert model.data(idx) == 'https://duckduckgo.com'
assert model.data(idx) == 'https://wiki.archlinux.org'
assert 'ddg' in quickmarks.marks
len_before = len(quickmarks.marks)
model.delete_cur_item(idx)
assert 'ddg' not in quickmarks.marks
assert 'aw' not in quickmarks.marks
assert len_before == len(quickmarks.marks) + 1
@ -456,9 +456,9 @@ def test_session_completion(qtmodeltester, session_manager_stub):
qtmodeltester.check(model)
_check_completions(model, {
"Sessions": [('1', None, None),
('2', None, None),
('default', None, None)]
"Sessions": [('default', None, None),
('1', None, None),
('2', None, None)]
})