From 9c0c1745343f345664efa2e02b12c9da3818039d Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Thu, 29 Jun 2017 12:44:02 -0400 Subject: [PATCH] Use builtin SortFilter regex functionality. With the new completion API, we no longer need a custom filterAcceptsRow function. This was necessary to handle the tree structure of the model, but now we use a separate QSortFilterProxyModel for each category, so the data it filters is flat. We can simplify the code by using the builtin setFilterRegExp. This changes the behavior a little, as now all list categories filter on all columns. This should be beneficial if anything. For example, help topics are now filtered on description in addition to name. This also seems to slightly speed up filtering, according to the url model benchmark. Before: ----------------------------------------------- benchmark: 1 tests ---------------------------------------------- Name (time in s) Min Max Mean StdDev Median IQR Outliers(*) Rounds Iterations ----------------------------------------------------------------------------------------------------------------- test_url_completion_benchmark 1.2806 1.3817 1.3195 0.0390 1.3068 0.0487 1;0 5 1 ----------------------------------------------------------------------------------------------------------------- After: ----------------------------------------------- benchmark: 1 tests ---------------------------------------------- Name (time in s) Min Max Mean StdDev Median IQR Outliers(*) Rounds Iterations ----------------------------------------------------------------------------------------------------------------- test_url_completion_benchmark 1.1183 1.1508 1.1281 0.0132 1.1241 0.0142 1;0 5 1 ----------------------------------------------------------------------------------------------------------------- --- qutebrowser/completion/models/listcategory.py | 40 ++++--------------- qutebrowser/completion/models/miscmodels.py | 4 -- qutebrowser/completion/models/urlmodel.py | 6 +-- 3 files changed, 9 insertions(+), 41 deletions(-) diff --git a/qutebrowser/completion/models/listcategory.py b/qutebrowser/completion/models/listcategory.py index c02783e66..ee9a5e53e 100644 --- a/qutebrowser/completion/models/listcategory.py +++ b/qutebrowser/completion/models/listcategory.py @@ -21,7 +21,7 @@ import re -from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex +from PyQt5.QtCore import Qt, QSortFilterProxyModel, QModelIndex, QRegExp from PyQt5.QtGui import QStandardItem, QStandardItemModel from qutebrowser.utils import qtutils @@ -32,14 +32,14 @@ class ListCategory(QSortFilterProxyModel): """Expose a list of items as a category for the CompletionModel.""" - def __init__(self, name, items, columns_to_filter=None, - delete_func=None, parent=None): + def __init__(self, name, items, delete_func=None, parent=None): super().__init__(parent) self.name = name self.srcmodel = QStandardItemModel(parent=self) self.pattern = '' - self.pattern_re = None - self.columns_to_filter = columns_to_filter or [0] + # ListCategory filters all columns + self.columns_to_filter = [0, 1, 2] + self.setFilterKeyColumn(-1) for item in items: self.srcmodel.appendRow([QStandardItem(x) for x in item]) self.setSourceModel(self.srcmodel) @@ -55,38 +55,12 @@ class ListCategory(QSortFilterProxyModel): val = re.sub(r' +', r' ', val) # See #1919 val = re.escape(val) val = val.replace(r'\ ', '.*') - self.pattern_re = re.compile(val, re.IGNORECASE) + rx = QRegExp(val, Qt.CaseInsensitive) + self.setFilterRegExp(rx) self.invalidate() sortcol = 0 self.sort(sortcol) - def filterAcceptsRow(self, row, parent): - """Custom filter implementation. - - Override QSortFilterProxyModel::filterAcceptsRow. - - Args: - row: The row of the item. - parent: The parent item QModelIndex. - - Return: - True if self.pattern is contained in item. - """ - if not self.pattern: - return True - - for col in self.columns_to_filter: - idx = self.srcmodel.index(row, col, parent) - if not idx.isValid(): # pragma: no cover - # this is a sanity check not hit by any test case - continue - data = self.srcmodel.data(idx) - if not data: - continue - elif self.pattern_re.search(data): - return True - return False - def lessThan(self, lindex, rindex): """Custom sorting implementation. diff --git a/qutebrowser/completion/models/miscmodels.py b/qutebrowser/completion/models/miscmodels.py index 8338452c9..0af6060e7 100644 --- a/qutebrowser/completion/models/miscmodels.py +++ b/qutebrowser/completion/models/miscmodels.py @@ -92,9 +92,6 @@ def buffer(): Used for switching the buffer command. """ - idx_column = 0 - url_column = 1 - text_column = 2 def delete_buffer(data): """Close the selected tab.""" @@ -117,7 +114,6 @@ def buffer(): tab.url().toDisplayString(), tabbed_browser.page_title(idx))) cat = listcategory.ListCategory("{}".format(win_id), tabs, - columns_to_filter=[idx_column, url_column, text_column], delete_func=delete_buffer) model.add_category(cat) diff --git a/qutebrowser/completion/models/urlmodel.py b/qutebrowser/completion/models/urlmodel.py index 0c63f2582..4f5fdeae9 100644 --- a/qutebrowser/completion/models/urlmodel.py +++ b/qutebrowser/completion/models/urlmodel.py @@ -62,11 +62,9 @@ def url(): bookmarks = objreg.get('bookmark-manager').marks.items() model.add_category(listcategory.ListCategory( - 'Quickmarks', quickmarks, columns_to_filter=[0, 1], - delete_func=_delete_quickmark)) + 'Quickmarks', quickmarks, delete_func=_delete_quickmark)) model.add_category(listcategory.ListCategory( - 'Bookmarks', bookmarks, columns_to_filter=[0, 1], - delete_func=_delete_bookmark)) + 'Bookmarks', bookmarks, delete_func=_delete_bookmark)) # replace 's to avoid breaking the query timefmt = config.get('completion', 'timestamp-format').replace("'", "`")