From 933296f47ffd6dc7cafcf29ff55f29c5a494dfdc Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 14 Feb 2014 17:41:12 +0100 Subject: [PATCH] Move models to qutebrowser.models --- qutebrowser/commands/utils.py | 19 --- qutebrowser/models/__init__.py | 18 +++ qutebrowser/models/commandcompletion.py | 39 ++++++ qutebrowser/{utils => models}/completion.py | 110 +---------------- qutebrowser/models/completionfilter.py | 129 ++++++++++++++++++++ qutebrowser/widgets/completion.py | 4 +- 6 files changed, 190 insertions(+), 129 deletions(-) create mode 100644 qutebrowser/models/__init__.py create mode 100644 qutebrowser/models/commandcompletion.py rename qutebrowser/{utils => models}/completion.py (73%) create mode 100644 qutebrowser/models/completionfilter.py diff --git a/qutebrowser/commands/utils.py b/qutebrowser/commands/utils.py index 44b0438a7..4678a7748 100644 --- a/qutebrowser/commands/utils.py +++ b/qutebrowser/commands/utils.py @@ -27,7 +27,6 @@ import qutebrowser.commands.commands import qutebrowser.utils.config as config from qutebrowser.commands.exceptions import (ArgumentCountError, NoSuchCommandError) -from qutebrowser.utils.completion import CompletionModel # A mapping from command-strings to command objects. cmd_dict = {} @@ -170,21 +169,3 @@ class CommandParser(QObject): else: raise self._run(count=count) - - -class CommandCompletionModel(CompletionModel): - - """A CompletionModel filled with all commands and descriptions.""" - - # pylint: disable=abstract-method - - def __init__(self, parent=None): - super().__init__(parent) - assert cmd_dict - cmdlist = [] - for obj in set(cmd_dict.values()): - if not obj.hide: - doc = obj.__doc__.splitlines()[0].strip().rstrip('.') - cmdlist.append([obj.mainname, doc]) - self._data['Commands'] = sorted(cmdlist) - self.init_data() diff --git a/qutebrowser/models/__init__.py b/qutebrowser/models/__init__.py new file mode 100644 index 000000000..41e3ddde0 --- /dev/null +++ b/qutebrowser/models/__init__.py @@ -0,0 +1,18 @@ +# Copyright 2014 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Various data models.""" diff --git a/qutebrowser/models/commandcompletion.py b/qutebrowser/models/commandcompletion.py new file mode 100644 index 000000000..8d4c94a97 --- /dev/null +++ b/qutebrowser/models/commandcompletion.py @@ -0,0 +1,39 @@ +"""A CompletionModel filled with all commands and descriptions.""" + +# Copyright 2014 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +from qutebrowser.commands.utils import cmd_dict +from qutebrowser.models.completion import CompletionModel + + +class CommandCompletionModel(CompletionModel): + + """A CompletionModel filled with all commands and descriptions.""" + + # pylint: disable=abstract-method + + def __init__(self, parent=None): + super().__init__(parent) + assert cmd_dict + cmdlist = [] + for obj in set(cmd_dict.values()): + if not obj.hide: + doc = obj.__doc__.splitlines()[0].strip().rstrip('.') + cmdlist.append([obj.mainname, doc]) + self._data['Commands'] = sorted(cmdlist) + self.init_data() diff --git a/qutebrowser/utils/completion.py b/qutebrowser/models/completion.py similarity index 73% rename from qutebrowser/utils/completion.py rename to qutebrowser/models/completion.py index 64092f984..04dbf230f 100644 --- a/qutebrowser/utils/completion.py +++ b/qutebrowser/models/completion.py @@ -1,9 +1,8 @@ -"""The base data models for completion in the commandline. +"""The base completion model for completion in the command line. Contains: CompletionModel -- A simple tree model based on Python data. CompletionItem -- One item in the CompletionModel. - CompletionFilterModel -- A QSortFilterProxyModel subclass for completions. """ @@ -26,8 +25,7 @@ Contains: from collections import OrderedDict -from PyQt5.QtCore import (QAbstractItemModel, Qt, QModelIndex, QVariant, - QSortFilterProxyModel) +from PyQt5.QtCore import QAbstractItemModel, Qt, QModelIndex, QVariant class CompletionModel(QAbstractItemModel): @@ -303,107 +301,3 @@ class CompletionItem(): if self.parent: return self.parent.children.index(self) return 0 - - -class CompletionFilterModel(QSortFilterProxyModel): - - """Subclass of QSortFilterProxyModel with custom sorting/filtering.""" - - _pattern = None - srcmodel = None - - def __init__(self, parent=None): - super().__init__(parent) - self._pattern = '' - - @property - def pattern(self): - """Getter for pattern.""" - return self._pattern - - def setsrc(self, model): - """Set a new source model and clear the pattern. - - model -- The new source model. - - """ - self.setSourceModel(model) - self.srcmodel = model - self.pattern = '' - - @pattern.setter - def pattern(self, val): - """Setter for pattern. - - Invalidates the filter and re-sorts the model. - - If the current completion model overrides sort(), it is used. - If not, the default implementation in QCompletionFilterModel is called. - - """ - self._pattern = val - self.invalidateFilter() - sortcol = 0 - srcmodel = self.sourceModel() - if srcmodel is not None: - try: - srcmodel.sort(sortcol) - except NotImplementedError: - self.sort(sortcol) - self.invalidate() - - def filterAcceptsRow(self, row, parent): - """Custom filter implementation. - - Override QSortFilterProxyModel::filterAcceptsRow. - - row -- The row of the item. - parent -- The parent item QModelIndex. - - Return True if self.pattern is contained in item, or if it's a root - item (category). Else returns False. - - """ - if parent == QModelIndex(): - return True - idx = self.srcmodel.index(row, 0, parent) - data = self.srcmodel.data(idx).value() - # TODO more sophisticated filtering - if not self.pattern: - return True - return self.pattern in data - - def lessThan(self, lindex, rindex): - """Custom sorting implementation. - - lindex -- The QModelIndex of the left item (*left* < right) - rindex -- The QModelIndex of the right item (left < *right*) - - Prefers all items which start with self.pattern. Other than that, uses - normal Python string sorting. - - """ - left = self.srcmodel.data(lindex).value() - right = self.srcmodel.data(rindex).value() - - 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 - - def first_item(self): - """Return the first item in the model.""" - cat = self.index(0, 0) - return self.index(0, 0, cat) - - def last_item(self): - """Return the last item in the model.""" - cat = self.index(self.rowCount() - 1, 0) - return self.index(self.rowCount(cat) - 1, 0, cat) diff --git a/qutebrowser/models/completionfilter.py b/qutebrowser/models/completionfilter.py new file mode 100644 index 000000000..0f94408cb --- /dev/null +++ b/qutebrowser/models/completionfilter.py @@ -0,0 +1,129 @@ +"""A filtering/sorting base model for completions. + +Contains: + CompletionFilterModel -- A QSortFilterProxyModel subclass for completions. + +""" + +# Copyright 2014 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +from PyQt5.QtCore import QModelIndex, QSortFilterProxyModel + + +class CompletionFilterModel(QSortFilterProxyModel): + + """Subclass of QSortFilterProxyModel with custom sorting/filtering.""" + + _pattern = None + srcmodel = None + + def __init__(self, parent=None): + super().__init__(parent) + self._pattern = '' + + @property + def pattern(self): + """Getter for pattern.""" + return self._pattern + + def setsrc(self, model): + """Set a new source model and clear the pattern. + + model -- The new source model. + + """ + self.setSourceModel(model) + self.srcmodel = model + self.pattern = '' + + @pattern.setter + def pattern(self, val): + """Setter for pattern. + + Invalidates the filter and re-sorts the model. + + If the current completion model overrides sort(), it is used. + If not, the default implementation in QCompletionFilterModel is called. + + """ + self._pattern = val + self.invalidateFilter() + sortcol = 0 + srcmodel = self.sourceModel() + if srcmodel is not None: + try: + srcmodel.sort(sortcol) + except NotImplementedError: + self.sort(sortcol) + self.invalidate() + + def filterAcceptsRow(self, row, parent): + """Custom filter implementation. + + Override QSortFilterProxyModel::filterAcceptsRow. + + row -- The row of the item. + parent -- The parent item QModelIndex. + + Return True if self.pattern is contained in item, or if it's a root + item (category). Else returns False. + + """ + if parent == QModelIndex(): + return True + idx = self.srcmodel.index(row, 0, parent) + data = self.srcmodel.data(idx).value() + # TODO more sophisticated filtering + if not self.pattern: + return True + return self.pattern in data + + def lessThan(self, lindex, rindex): + """Custom sorting implementation. + + lindex -- The QModelIndex of the left item (*left* < right) + rindex -- The QModelIndex of the right item (left < *right*) + + Prefers all items which start with self.pattern. Other than that, uses + normal Python string sorting. + + """ + left = self.srcmodel.data(lindex).value() + right = self.srcmodel.data(rindex).value() + + 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 + + def first_item(self): + """Return the first item in the model.""" + cat = self.index(0, 0) + return self.index(0, 0, cat) + + def last_item(self): + """Return the last item in the model.""" + cat = self.index(self.rowCount() - 1, 0) + return self.index(self.rowCount(cat) - 1, 0, cat) diff --git a/qutebrowser/widgets/completion.py b/qutebrowser/widgets/completion.py index d93c533ed..07f487ccc 100644 --- a/qutebrowser/widgets/completion.py +++ b/qutebrowser/widgets/completion.py @@ -32,8 +32,8 @@ from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption, QTextCursor) import qutebrowser.utils.config as config -from qutebrowser.utils.completion import CompletionFilterModel -from qutebrowser.commands.utils import CommandCompletionModel +from qutebrowser.models.completionfilter import CompletionFilterModel +from qutebrowser.models.commandcompletion import CommandCompletionModel class CompletionView(QTreeView):