diff --git a/qutebrowser/completion/models/sqlmodel.py b/qutebrowser/completion/models/sqlmodel.py index 8a0abda2b..39182628c 100644 --- a/qutebrowser/completion/models/sqlmodel.py +++ b/qutebrowser/completion/models/sqlmodel.py @@ -29,7 +29,7 @@ from qutebrowser.misc import sql class SqlCompletionCategory(QSqlQueryModel): - def __init__(self, name, sort_by, sort_order, limit, select, + def __init__(self, name, sort_by, sort_order, limit, select, where, columns_to_filter, parent=None): super().__init__(parent=parent) self.tablename = name @@ -37,9 +37,12 @@ class SqlCompletionCategory(QSqlQueryModel): query = sql.run_query('select * from {} limit 1'.format(name)) self._fields = [query.record().fieldName(i) for i in columns_to_filter] - querystr = 'select {} from {} where '.format(select, name) - querystr += ' or '.join('{} like ?'.format(f) for f in self._fields) - querystr += " escape '\\'" + querystr = 'select {} from {} where ('.format(select, name) + querystr += ' or '.join("{} like ? escape '\\'".format(f) + for f in self._fields) + querystr += ')' + if where: + querystr += ' and ' + where if sort_by: sortstr = 'asc' if sort_order == Qt.AscendingOrder else 'desc' @@ -87,13 +90,14 @@ class SqlCompletionModel(QAbstractItemModel): self.srcmodel = self # TODO: dummy for compat with old API self.pattern = '' - def new_category(self, name, select='*', sort_by=None, + def new_category(self, name, select='*', where=None, sort_by=None, sort_order=None, limit=None): """Create a new completion category and add it to this model. Args: name: Name of category, and the table in the database. select: A custom result column expression for the select statement. + where: An optional clause to filter out some rows. sort_by: The name of the field to sort by, or None for no sorting. sort_order: Sorting order, if sort_by is non-None. limit: Maximum row count to return on a query. @@ -102,7 +106,7 @@ class SqlCompletionModel(QAbstractItemModel): """ cat = SqlCompletionCategory(name, parent=self, sort_by=sort_by, sort_order=sort_order, limit=limit, - select=select, + select=select, where=where, columns_to_filter=self.columns_to_filter) self._categories.append(cat) diff --git a/qutebrowser/completion/models/urlmodel.py b/qutebrowser/completion/models/urlmodel.py index 164a5da15..2f573aab7 100644 --- a/qutebrowser/completion/models/urlmodel.py +++ b/qutebrowser/completion/models/urlmodel.py @@ -38,7 +38,8 @@ def url(): select_time = "strftime('{}', atime, 'unixepoch')".format(timefmt) model.new_category('History', limit=limit, - select='url, title, {}'.format(select_time)) + select='url, title, {}'.format(select_time), + where='not redirect') model.new_category('Quickmarks', select='url, name') model.new_category('Bookmarks') return model diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py index 21b65e092..d0732f660 100644 --- a/tests/unit/completion/test_models.py +++ b/tests/unit/completion/test_models.py @@ -154,6 +154,8 @@ def web_history(stubs, init_sql): """Pre-populate the web-history database.""" table = sql.SqlTable("History", ['url', 'title', 'atime', 'redirect'], primary_key='url') + table.insert(['http://some-redirect.example.com', 'redirect', + datetime(2016, 9, 5).timestamp(), True]) table.insert(['http://qutebrowser.org', 'qutebrowser', datetime(2015, 9, 5).timestamp(), False]) table.insert(['https://python.org', 'Welcome to Python.org', @@ -266,6 +268,7 @@ def test_url_completion(qtmodeltester, config_stub, web_history, quickmarks, - quickmarks, bookmarks, and urls are included - no more than 'web-history-max-items' items are included (TODO) - the most recent entries are included + - redirect entries are not included """ # TODO: time formatting and item limiting config_stub.data['completion'] = {'timestamp-format': '%Y-%m-%d', diff --git a/tests/unit/completion/test_sqlmodel.py b/tests/unit/completion/test_sqlmodel.py index a0dbbe7b3..b94e8e048 100644 --- a/tests/unit/completion/test_sqlmodel.py +++ b/tests/unit/completion/test_sqlmodel.py @@ -156,6 +156,10 @@ def test_sorting(sort_by, sort_order, data, expected): [('A', [('a_b', '', ''), ('__a', '', ''), ('abc', '', '')])], [('A', [('a_b', '', ''), ('__a', '', '')])]), + ('%', [0, 1], + [('A', [('\\foo', '\\bar', '')])], + [('A', [])]), + ("can't", [0], [('A', [("can't touch this", '', ''), ('a', '', '')])], [('A', [("can't touch this", '', '')])]), @@ -218,3 +222,12 @@ def test_select(): model = sqlmodel.SqlCompletionModel() model.new_category('test_select', select='b, c, a') _check_model(model, [('test_select', [('bar', 'baz', 'foo')])]) + + +def test_where(): + table = sql.SqlTable('test_where', ['a', 'b', 'c'], primary_key='a') + table.insert(['foo', 'bar', False]) + table.insert(['baz', 'biz', True]) + model = sqlmodel.SqlCompletionModel() + model.new_category('test_where', where='not c') + _check_model(model, [('test_where', [('foo', 'bar', False)])])