We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Errors when `completion show` setting is false
Pressing up, down, or tab when there are completions available but the `completion show` setting is `false` crashes qutebrowser. The relevant error:

```
  ...
  File "/home/marshall/Github/qutebrowser/qutebrowser/completion/completionwidget.py", line 164, in _next_idx
    idx = self.selectionModel().currentIndex()
AttributeError: 'NoneType' object has no attribute 'currentIndex'
```

This appears after the recent completion fixes from @rcorre.

Generally, the completion `show` and `auto-open` options don't seem to make sense. Before the change, `show` would do what I expected `auto-open` to do (turning it off hides the completion window until the user asks for it with up, down, or tab). `auto-open` doesn't do anything (before or after the change), as far as I can tell.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `qutebrowser/completion/completionwidget.py`
Content:
```
1 # vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
2 
3 # Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
4 #
5 # This file is part of qutebrowser.
6 #
7 # qutebrowser is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # qutebrowser is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.
19 
20 """Completion view for statusbar command section.
21 
22 Defines a CompletionView which uses CompletionFiterModel and CompletionModel
23 subclasses to provide completions.
24 """
25 
26 from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
27 from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QItemSelectionModel,
28                           QItemSelection)
29 
30 from qutebrowser.config import config, style
31 from qutebrowser.completion import completiondelegate
32 from qutebrowser.completion.models import base
33 from qutebrowser.utils import qtutils, objreg, utils, usertypes
34 from qutebrowser.commands import cmdexc, cmdutils
35 
36 
37 class CompletionView(QTreeView):
38 
39     """The view showing available completions.
40 
41     Based on QTreeView but heavily customized so root elements show as category
42     headers, and children show as flat list.
43 
44     Attributes:
45         enabled: Whether showing the CompletionView is enabled.
46         _win_id: The ID of the window this CompletionView is associated with.
47         _height: The height to use for the CompletionView.
48         _height_perc: Either None or a percentage if height should be relative.
49         _delegate: The item delegate used.
50         _column_widths: A list of column widths, in percent.
51 
52     Signals:
53         resize_completion: Emitted when the completion should be resized.
54         selection_changed: Emitted when the completion item selection changes.
55     """
56 
57     # Drawing the item foreground will be done by CompletionItemDelegate, so we
58     # don't define that in this stylesheet.
59     STYLESHEET = """
60         QTreeView {
61             font: {{ font['completion'] }};
62             background-color: {{ color['completion.bg'] }};
63             alternate-background-color: {{ color['completion.alternate-bg'] }};
64             outline: 0;
65             border: 0px;
66         }
67 
68         QTreeView::item:disabled {
69             background-color: {{ color['completion.category.bg'] }};
70             border-top: 1px solid
71                 {{ color['completion.category.border.top'] }};
72             border-bottom: 1px solid
73                 {{ color['completion.category.border.bottom'] }};
74         }
75 
76         QTreeView::item:selected, QTreeView::item:selected:hover {
77             border-top: 1px solid
78                 {{ color['completion.item.selected.border.top'] }};
79             border-bottom: 1px solid
80                 {{ color['completion.item.selected.border.bottom'] }};
81             background-color: {{ color['completion.item.selected.bg'] }};
82         }
83 
84         QTreeView:item::hover {
85             border: 0px;
86         }
87 
88         QTreeView QScrollBar {
89             width: {{ config.get('completion', 'scrollbar-width') }}px;
90             background: {{ color['completion.scrollbar.bg'] }};
91         }
92 
93         QTreeView QScrollBar::handle {
94             background: {{ color['completion.scrollbar.fg'] }};
95             border: {{ config.get('completion', 'scrollbar-padding') }}px solid
96                     {{ color['completion.scrollbar.bg'] }};
97             min-height: 10px;
98         }
99 
100         QTreeView QScrollBar::sub-line, QScrollBar::add-line {
101             border: none;
102             background: none;
103         }
104     """
105 
106     resize_completion = pyqtSignal()
107     selection_changed = pyqtSignal(QItemSelection)
108 
109     def __init__(self, win_id, parent=None):
110         super().__init__(parent)
111         self._win_id = win_id
112         self.enabled = config.get('completion', 'show')
113         objreg.get('config').changed.connect(self.set_enabled)
114         # FIXME handle new aliases.
115         # objreg.get('config').changed.connect(self.init_command_completion)
116 
117         self._column_widths = base.BaseCompletionModel.COLUMN_WIDTHS
118 
119         self._delegate = completiondelegate.CompletionItemDelegate(self)
120         self.setItemDelegate(self._delegate)
121         style.set_register_stylesheet(self)
122         self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
123         self.setHeaderHidden(True)
124         self.setAlternatingRowColors(True)
125         self.setIndentation(0)
126         self.setItemsExpandable(False)
127         self.setExpandsOnDoubleClick(False)
128         self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
129         # WORKAROUND
130         # This is a workaround for weird race conditions with invalid
131         # item indexes leading to segfaults in Qt.
132         #
133         # Some background: http://bugs.quassel-irc.org/issues/663
134         # The proposed fix there was later reverted because it didn't help.
135         self.setUniformRowHeights(True)
136         self.hide()
137         # FIXME set elidemode
138         # https://github.com/The-Compiler/qutebrowser/issues/118
139 
140     def __repr__(self):
141         return utils.get_repr(self)
142 
143     def _resize_columns(self):
144         """Resize the completion columns based on column_widths."""
145         width = self.size().width()
146         pixel_widths = [(width * perc // 100) for perc in self._column_widths]
147         if self.verticalScrollBar().isVisible():
148             pixel_widths[-1] -= self.style().pixelMetric(
149                 QStyle.PM_ScrollBarExtent) + 5
150         for i, w in enumerate(pixel_widths):
151             self.setColumnWidth(i, w)
152 
153     def _next_idx(self, upwards):
154         """Get the previous/next QModelIndex displayed in the view.
155 
156         Used by tab_handler.
157 
158         Args:
159             upwards: Get previous item, not next.
160 
161         Return:
162             A QModelIndex.
163         """
164         idx = self.selectionModel().currentIndex()
165         if not idx.isValid():
166             # No item selected yet
167             if upwards:
168                 return self.model().last_item()
169             else:
170                 return self.model().first_item()
171         while True:
172             idx = self.indexAbove(idx) if upwards else self.indexBelow(idx)
173             # wrap around if we arrived at beginning/end
174             if not idx.isValid() and upwards:
175                 return self.model().last_item()
176             elif not idx.isValid() and not upwards:
177                 idx = self.model().first_item()
178                 self.scrollTo(idx.parent())
179                 return idx
180             elif idx.parent().isValid():
181                 # Item is a real item, not a category header -> success
182                 return idx
183 
184     def _next_prev_item(self, prev):
185         """Handle a tab press for the CompletionView.
186 
187         Select the previous/next item and write the new text to the
188         statusbar.
189 
190         Helper for completion_item_next and completion_item_prev.
191 
192         Args:
193             prev: True for prev item, False for next one.
194         """
195         idx = self._next_idx(prev)
196         qtutils.ensure_valid(idx)
197         self.selectionModel().setCurrentIndex(
198             idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
199 
200     def set_model(self, model):
201         """Switch completion to a new model.
202 
203         Called from on_update_completion().
204 
205         Args:
206             model: The model to use.
207         """
208         old_model = self.model()
209         sel_model = self.selectionModel()
210 
211         self.setModel(model)
212 
213         if sel_model is not None:
214             sel_model.deleteLater()
215         if old_model is not None:
216             old_model.deleteLater()
217 
218         for i in range(model.rowCount()):
219             self.expand(model.index(i, 0))
220 
221         self._column_widths = model.srcmodel.COLUMN_WIDTHS
222         self._resize_columns()
223         self.maybe_resize_completion()
224 
225     def set_pattern(self, pattern):
226         """Set the completion pattern for the current model.
227 
228         Called from on_update_completion().
229 
230         Args:
231             pattern: The filter pattern to set (what the user entered).
232         """
233         self.model().set_pattern(pattern)
234         self.maybe_resize_completion()
235 
236     @pyqtSlot()
237     def maybe_resize_completion(self):
238         """Emit the resize_completion signal if the config says so."""
239         if config.get('completion', 'shrink'):
240             self.resize_completion.emit()
241 
242     @config.change_filter('completion', 'show')
243     def set_enabled(self):
244         """Update self.enabled when the config changed."""
245         self.enabled = config.get('completion', 'show')
246 
247     @pyqtSlot()
248     def on_clear_completion_selection(self):
249         """Clear the selection model when an item is activated."""
250         selmod = self.selectionModel()
251         if selmod is not None:
252             selmod.clearSelection()
253             selmod.clearCurrentIndex()
254 
255     def selectionChanged(self, selected, deselected):
256         """Extend selectionChanged to call completers selection_changed."""
257         super().selectionChanged(selected, deselected)
258         self.selection_changed.emit(selected)
259 
260     def resizeEvent(self, e):
261         """Extend resizeEvent to adjust column size."""
262         super().resizeEvent(e)
263         self._resize_columns()
264 
265     def showEvent(self, e):
266         """Adjust the completion size and scroll when it's freshly shown."""
267         self.resize_completion.emit()
268         scrollbar = self.verticalScrollBar()
269         if scrollbar is not None:
270             scrollbar.setValue(scrollbar.minimum())
271         super().showEvent(e)
272 
273     @cmdutils.register(instance='completion', hide=True,
274                        modes=[usertypes.KeyMode.command], scope='window')
275     def completion_item_prev(self):
276         """Select the previous completion item."""
277         self._next_prev_item(True)
278 
279     @cmdutils.register(instance='completion', hide=True,
280                        modes=[usertypes.KeyMode.command], scope='window')
281     def completion_item_next(self):
282         """Select the next completion item."""
283         self._next_prev_item(False)
284 
285     @cmdutils.register(instance='completion', hide=True,
286                        modes=[usertypes.KeyMode.command], scope='window')
287     def completion_item_del(self):
288         """Delete the current completion item."""
289         if not self.currentIndex().isValid():
290             raise cmdexc.CommandError("No item selected!")
291         try:
292             self.model().srcmodel.delete_cur_item(self)
293         except NotImplementedError:
294             raise cmdexc.CommandError("Cannot delete this item.")
295
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py
--- a/qutebrowser/completion/completionwidget.py
+++ b/qutebrowser/completion/completionwidget.py
@@ -192,10 +192,13 @@
         Args:
             prev: True for prev item, False for next one.
         """
-        idx = self._next_idx(prev)
-        qtutils.ensure_valid(idx)
-        self.selectionModel().setCurrentIndex(
-            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
+        # selmodel can be None if 'show' and 'auto-open' are set to False
+        # https://github.com/The-Compiler/qutebrowser/issues/1731
+        selmodel = self.selectionModel()
+        if (selmodel is not None):
+            idx = self._next_idx(prev)
+            selmodel.setCurrentIndex(idx,
+                QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
 
     def set_model(self, model):
         """Switch completion to a new model.

{"golden_diff": "diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py\n--- a/qutebrowser/completion/completionwidget.py\n+++ b/qutebrowser/completion/completionwidget.py\n@@ -192,10 +192,13 @@\n         Args:\n             prev: True for prev item, False for next one.\n         \"\"\"\n-        idx = self._next_idx(prev)\n-        qtutils.ensure_valid(idx)\n-        self.selectionModel().setCurrentIndex(\n-            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)\n+        # selmodel can be None if 'show' and 'auto-open' are set to False\n+        # https://github.com/The-Compiler/qutebrowser/issues/1731\n+        selmodel = self.selectionModel()\n+        if (selmodel is not None):\n+            idx = self._next_idx(prev)\n+            selmodel.setCurrentIndex(idx,\n+                QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)\n \n     def set_model(self, model):\n         \"\"\"Switch completion to a new model.\n", "issue": "Errors when `completion show` setting is false\nPressing up, down, or tab when there are completions available but the `completion show` setting is `false` crashes qutebrowser. The relevant error:\n\n```\n  ...\n  File \"/home/marshall/Github/qutebrowser/qutebrowser/completion/completionwidget.py\", line 164, in _next_idx\n    idx = self.selectionModel().currentIndex()\nAttributeError: 'NoneType' object has no attribute 'currentIndex'\n```\n\nThis appears after the recent completion fixes from @rcorre.\n\nGenerally, the completion `show` and `auto-open` options don't seem to make sense. Before the change, `show` would do what I expected `auto-open` to do (turning it off hides the completion window until the user asks for it with up, down, or tab). `auto-open` doesn't do anything (before or after the change), as far as I can tell.\n\n", "before_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>\n#\n# This file is part of qutebrowser.\n#\n# qutebrowser is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# qutebrowser is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Completion view for statusbar command section.\n\nDefines a CompletionView which uses CompletionFiterModel and CompletionModel\nsubclasses to provide completions.\n\"\"\"\n\nfrom PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy\nfrom PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QItemSelectionModel,\n                          QItemSelection)\n\nfrom qutebrowser.config import config, style\nfrom qutebrowser.completion import completiondelegate\nfrom qutebrowser.completion.models import base\nfrom qutebrowser.utils import qtutils, objreg, utils, usertypes\nfrom qutebrowser.commands import cmdexc, cmdutils\n\n\nclass CompletionView(QTreeView):\n\n    \"\"\"The view showing available completions.\n\n    Based on QTreeView but heavily customized so root elements show as category\n    headers, and children show as flat list.\n\n    Attributes:\n        enabled: Whether showing the CompletionView is enabled.\n        _win_id: The ID of the window this CompletionView is associated with.\n        _height: The height to use for the CompletionView.\n        _height_perc: Either None or a percentage if height should be relative.\n        _delegate: The item delegate used.\n        _column_widths: A list of column widths, in percent.\n\n    Signals:\n        resize_completion: Emitted when the completion should be resized.\n        selection_changed: Emitted when the completion item selection changes.\n    \"\"\"\n\n    # Drawing the item foreground will be done by CompletionItemDelegate, so we\n    # don't define that in this stylesheet.\n    STYLESHEET = \"\"\"\n        QTreeView {\n            font: {{ font['completion'] }};\n            background-color: {{ color['completion.bg'] }};\n            alternate-background-color: {{ color['completion.alternate-bg'] }};\n            outline: 0;\n            border: 0px;\n        }\n\n        QTreeView::item:disabled {\n            background-color: {{ color['completion.category.bg'] }};\n            border-top: 1px solid\n                {{ color['completion.category.border.top'] }};\n            border-bottom: 1px solid\n                {{ color['completion.category.border.bottom'] }};\n        }\n\n        QTreeView::item:selected, QTreeView::item:selected:hover {\n            border-top: 1px solid\n                {{ color['completion.item.selected.border.top'] }};\n            border-bottom: 1px solid\n                {{ color['completion.item.selected.border.bottom'] }};\n            background-color: {{ color['completion.item.selected.bg'] }};\n        }\n\n        QTreeView:item::hover {\n            border: 0px;\n        }\n\n        QTreeView QScrollBar {\n            width: {{ config.get('completion', 'scrollbar-width') }}px;\n            background: {{ color['completion.scrollbar.bg'] }};\n        }\n\n        QTreeView QScrollBar::handle {\n            background: {{ color['completion.scrollbar.fg'] }};\n            border: {{ config.get('completion', 'scrollbar-padding') }}px solid\n                    {{ color['completion.scrollbar.bg'] }};\n            min-height: 10px;\n        }\n\n        QTreeView QScrollBar::sub-line, QScrollBar::add-line {\n            border: none;\n            background: none;\n        }\n    \"\"\"\n\n    resize_completion = pyqtSignal()\n    selection_changed = pyqtSignal(QItemSelection)\n\n    def __init__(self, win_id, parent=None):\n        super().__init__(parent)\n        self._win_id = win_id\n        self.enabled = config.get('completion', 'show')\n        objreg.get('config').changed.connect(self.set_enabled)\n        # FIXME handle new aliases.\n        # objreg.get('config').changed.connect(self.init_command_completion)\n\n        self._column_widths = base.BaseCompletionModel.COLUMN_WIDTHS\n\n        self._delegate = completiondelegate.CompletionItemDelegate(self)\n        self.setItemDelegate(self._delegate)\n        style.set_register_stylesheet(self)\n        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)\n        self.setHeaderHidden(True)\n        self.setAlternatingRowColors(True)\n        self.setIndentation(0)\n        self.setItemsExpandable(False)\n        self.setExpandsOnDoubleClick(False)\n        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)\n        # WORKAROUND\n        # This is a workaround for weird race conditions with invalid\n        # item indexes leading to segfaults in Qt.\n        #\n        # Some background: http://bugs.quassel-irc.org/issues/663\n        # The proposed fix there was later reverted because it didn't help.\n        self.setUniformRowHeights(True)\n        self.hide()\n        # FIXME set elidemode\n        # https://github.com/The-Compiler/qutebrowser/issues/118\n\n    def __repr__(self):\n        return utils.get_repr(self)\n\n    def _resize_columns(self):\n        \"\"\"Resize the completion columns based on column_widths.\"\"\"\n        width = self.size().width()\n        pixel_widths = [(width * perc // 100) for perc in self._column_widths]\n        if self.verticalScrollBar().isVisible():\n            pixel_widths[-1] -= self.style().pixelMetric(\n                QStyle.PM_ScrollBarExtent) + 5\n        for i, w in enumerate(pixel_widths):\n            self.setColumnWidth(i, w)\n\n    def _next_idx(self, upwards):\n        \"\"\"Get the previous/next QModelIndex displayed in the view.\n\n        Used by tab_handler.\n\n        Args:\n            upwards: Get previous item, not next.\n\n        Return:\n            A QModelIndex.\n        \"\"\"\n        idx = self.selectionModel().currentIndex()\n        if not idx.isValid():\n            # No item selected yet\n            if upwards:\n                return self.model().last_item()\n            else:\n                return self.model().first_item()\n        while True:\n            idx = self.indexAbove(idx) if upwards else self.indexBelow(idx)\n            # wrap around if we arrived at beginning/end\n            if not idx.isValid() and upwards:\n                return self.model().last_item()\n            elif not idx.isValid() and not upwards:\n                idx = self.model().first_item()\n                self.scrollTo(idx.parent())\n                return idx\n            elif idx.parent().isValid():\n                # Item is a real item, not a category header -> success\n                return idx\n\n    def _next_prev_item(self, prev):\n        \"\"\"Handle a tab press for the CompletionView.\n\n        Select the previous/next item and write the new text to the\n        statusbar.\n\n        Helper for completion_item_next and completion_item_prev.\n\n        Args:\n            prev: True for prev item, False for next one.\n        \"\"\"\n        idx = self._next_idx(prev)\n        qtutils.ensure_valid(idx)\n        self.selectionModel().setCurrentIndex(\n            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)\n\n    def set_model(self, model):\n        \"\"\"Switch completion to a new model.\n\n        Called from on_update_completion().\n\n        Args:\n            model: The model to use.\n        \"\"\"\n        old_model = self.model()\n        sel_model = self.selectionModel()\n\n        self.setModel(model)\n\n        if sel_model is not None:\n            sel_model.deleteLater()\n        if old_model is not None:\n            old_model.deleteLater()\n\n        for i in range(model.rowCount()):\n            self.expand(model.index(i, 0))\n\n        self._column_widths = model.srcmodel.COLUMN_WIDTHS\n        self._resize_columns()\n        self.maybe_resize_completion()\n\n    def set_pattern(self, pattern):\n        \"\"\"Set the completion pattern for the current model.\n\n        Called from on_update_completion().\n\n        Args:\n            pattern: The filter pattern to set (what the user entered).\n        \"\"\"\n        self.model().set_pattern(pattern)\n        self.maybe_resize_completion()\n\n    @pyqtSlot()\n    def maybe_resize_completion(self):\n        \"\"\"Emit the resize_completion signal if the config says so.\"\"\"\n        if config.get('completion', 'shrink'):\n            self.resize_completion.emit()\n\n    @config.change_filter('completion', 'show')\n    def set_enabled(self):\n        \"\"\"Update self.enabled when the config changed.\"\"\"\n        self.enabled = config.get('completion', 'show')\n\n    @pyqtSlot()\n    def on_clear_completion_selection(self):\n        \"\"\"Clear the selection model when an item is activated.\"\"\"\n        selmod = self.selectionModel()\n        if selmod is not None:\n            selmod.clearSelection()\n            selmod.clearCurrentIndex()\n\n    def selectionChanged(self, selected, deselected):\n        \"\"\"Extend selectionChanged to call completers selection_changed.\"\"\"\n        super().selectionChanged(selected, deselected)\n        self.selection_changed.emit(selected)\n\n    def resizeEvent(self, e):\n        \"\"\"Extend resizeEvent to adjust column size.\"\"\"\n        super().resizeEvent(e)\n        self._resize_columns()\n\n    def showEvent(self, e):\n        \"\"\"Adjust the completion size and scroll when it's freshly shown.\"\"\"\n        self.resize_completion.emit()\n        scrollbar = self.verticalScrollBar()\n        if scrollbar is not None:\n            scrollbar.setValue(scrollbar.minimum())\n        super().showEvent(e)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_prev(self):\n        \"\"\"Select the previous completion item.\"\"\"\n        self._next_prev_item(True)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_next(self):\n        \"\"\"Select the next completion item.\"\"\"\n        self._next_prev_item(False)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_del(self):\n        \"\"\"Delete the current completion item.\"\"\"\n        if not self.currentIndex().isValid():\n            raise cmdexc.CommandError(\"No item selected!\")\n        try:\n            self.model().srcmodel.delete_cur_item(self)\n        except NotImplementedError:\n            raise cmdexc.CommandError(\"Cannot delete this item.\")\n", "path": "qutebrowser/completion/completionwidget.py"}], "after_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>\n#\n# This file is part of qutebrowser.\n#\n# qutebrowser is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# qutebrowser is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Completion view for statusbar command section.\n\nDefines a CompletionView which uses CompletionFiterModel and CompletionModel\nsubclasses to provide completions.\n\"\"\"\n\nfrom PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy\nfrom PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QItemSelectionModel,\n                          QItemSelection)\n\nfrom qutebrowser.config import config, style\nfrom qutebrowser.completion import completiondelegate\nfrom qutebrowser.completion.models import base\nfrom qutebrowser.utils import qtutils, objreg, utils, usertypes\nfrom qutebrowser.commands import cmdexc, cmdutils\n\n\nclass CompletionView(QTreeView):\n\n    \"\"\"The view showing available completions.\n\n    Based on QTreeView but heavily customized so root elements show as category\n    headers, and children show as flat list.\n\n    Attributes:\n        enabled: Whether showing the CompletionView is enabled.\n        _win_id: The ID of the window this CompletionView is associated with.\n        _height: The height to use for the CompletionView.\n        _height_perc: Either None or a percentage if height should be relative.\n        _delegate: The item delegate used.\n        _column_widths: A list of column widths, in percent.\n\n    Signals:\n        resize_completion: Emitted when the completion should be resized.\n        selection_changed: Emitted when the completion item selection changes.\n    \"\"\"\n\n    # Drawing the item foreground will be done by CompletionItemDelegate, so we\n    # don't define that in this stylesheet.\n    STYLESHEET = \"\"\"\n        QTreeView {\n            font: {{ font['completion'] }};\n            background-color: {{ color['completion.bg'] }};\n            alternate-background-color: {{ color['completion.alternate-bg'] }};\n            outline: 0;\n            border: 0px;\n        }\n\n        QTreeView::item:disabled {\n            background-color: {{ color['completion.category.bg'] }};\n            border-top: 1px solid\n                {{ color['completion.category.border.top'] }};\n            border-bottom: 1px solid\n                {{ color['completion.category.border.bottom'] }};\n        }\n\n        QTreeView::item:selected, QTreeView::item:selected:hover {\n            border-top: 1px solid\n                {{ color['completion.item.selected.border.top'] }};\n            border-bottom: 1px solid\n                {{ color['completion.item.selected.border.bottom'] }};\n            background-color: {{ color['completion.item.selected.bg'] }};\n        }\n\n        QTreeView:item::hover {\n            border: 0px;\n        }\n\n        QTreeView QScrollBar {\n            width: {{ config.get('completion', 'scrollbar-width') }}px;\n            background: {{ color['completion.scrollbar.bg'] }};\n        }\n\n        QTreeView QScrollBar::handle {\n            background: {{ color['completion.scrollbar.fg'] }};\n            border: {{ config.get('completion', 'scrollbar-padding') }}px solid\n                    {{ color['completion.scrollbar.bg'] }};\n            min-height: 10px;\n        }\n\n        QTreeView QScrollBar::sub-line, QScrollBar::add-line {\n            border: none;\n            background: none;\n        }\n    \"\"\"\n\n    resize_completion = pyqtSignal()\n    selection_changed = pyqtSignal(QItemSelection)\n\n    def __init__(self, win_id, parent=None):\n        super().__init__(parent)\n        self._win_id = win_id\n        self.enabled = config.get('completion', 'show')\n        objreg.get('config').changed.connect(self.set_enabled)\n        # FIXME handle new aliases.\n        # objreg.get('config').changed.connect(self.init_command_completion)\n\n        self._column_widths = base.BaseCompletionModel.COLUMN_WIDTHS\n\n        self._delegate = completiondelegate.CompletionItemDelegate(self)\n        self.setItemDelegate(self._delegate)\n        style.set_register_stylesheet(self)\n        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)\n        self.setHeaderHidden(True)\n        self.setAlternatingRowColors(True)\n        self.setIndentation(0)\n        self.setItemsExpandable(False)\n        self.setExpandsOnDoubleClick(False)\n        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)\n        # WORKAROUND\n        # This is a workaround for weird race conditions with invalid\n        # item indexes leading to segfaults in Qt.\n        #\n        # Some background: http://bugs.quassel-irc.org/issues/663\n        # The proposed fix there was later reverted because it didn't help.\n        self.setUniformRowHeights(True)\n        self.hide()\n        # FIXME set elidemode\n        # https://github.com/The-Compiler/qutebrowser/issues/118\n\n    def __repr__(self):\n        return utils.get_repr(self)\n\n    def _resize_columns(self):\n        \"\"\"Resize the completion columns based on column_widths.\"\"\"\n        width = self.size().width()\n        pixel_widths = [(width * perc // 100) for perc in self._column_widths]\n        if self.verticalScrollBar().isVisible():\n            pixel_widths[-1] -= self.style().pixelMetric(\n                QStyle.PM_ScrollBarExtent) + 5\n        for i, w in enumerate(pixel_widths):\n            self.setColumnWidth(i, w)\n\n    def _next_idx(self, upwards):\n        \"\"\"Get the previous/next QModelIndex displayed in the view.\n\n        Used by tab_handler.\n\n        Args:\n            upwards: Get previous item, not next.\n\n        Return:\n            A QModelIndex.\n        \"\"\"\n        idx = self.selectionModel().currentIndex()\n        if not idx.isValid():\n            # No item selected yet\n            if upwards:\n                return self.model().last_item()\n            else:\n                return self.model().first_item()\n        while True:\n            idx = self.indexAbove(idx) if upwards else self.indexBelow(idx)\n            # wrap around if we arrived at beginning/end\n            if not idx.isValid() and upwards:\n                return self.model().last_item()\n            elif not idx.isValid() and not upwards:\n                idx = self.model().first_item()\n                self.scrollTo(idx.parent())\n                return idx\n            elif idx.parent().isValid():\n                # Item is a real item, not a category header -> success\n                return idx\n\n    def _next_prev_item(self, prev):\n        \"\"\"Handle a tab press for the CompletionView.\n\n        Select the previous/next item and write the new text to the\n        statusbar.\n\n        Helper for completion_item_next and completion_item_prev.\n\n        Args:\n            prev: True for prev item, False for next one.\n        \"\"\"\n        # selmodel can be None if 'show' and 'auto-open' are set to False\n        # https://github.com/The-Compiler/qutebrowser/issues/1731\n        selmodel = self.selectionModel()\n        if (selmodel is not None):\n            idx = self._next_idx(prev)\n            selmodel.setCurrentIndex(idx,\n                QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)\n\n    def set_model(self, model):\n        \"\"\"Switch completion to a new model.\n\n        Called from on_update_completion().\n\n        Args:\n            model: The model to use.\n        \"\"\"\n        old_model = self.model()\n        sel_model = self.selectionModel()\n\n        self.setModel(model)\n\n        if sel_model is not None:\n            sel_model.deleteLater()\n        if old_model is not None:\n            old_model.deleteLater()\n\n        for i in range(model.rowCount()):\n            self.expand(model.index(i, 0))\n\n        self._column_widths = model.srcmodel.COLUMN_WIDTHS\n        self._resize_columns()\n        self.maybe_resize_completion()\n\n    def set_pattern(self, pattern):\n        \"\"\"Set the completion pattern for the current model.\n\n        Called from on_update_completion().\n\n        Args:\n            pattern: The filter pattern to set (what the user entered).\n        \"\"\"\n        self.model().set_pattern(pattern)\n        self.maybe_resize_completion()\n\n    @pyqtSlot()\n    def maybe_resize_completion(self):\n        \"\"\"Emit the resize_completion signal if the config says so.\"\"\"\n        if config.get('completion', 'shrink'):\n            self.resize_completion.emit()\n\n    @config.change_filter('completion', 'show')\n    def set_enabled(self):\n        \"\"\"Update self.enabled when the config changed.\"\"\"\n        self.enabled = config.get('completion', 'show')\n\n    @pyqtSlot()\n    def on_clear_completion_selection(self):\n        \"\"\"Clear the selection model when an item is activated.\"\"\"\n        selmod = self.selectionModel()\n        if selmod is not None:\n            selmod.clearSelection()\n            selmod.clearCurrentIndex()\n\n    def selectionChanged(self, selected, deselected):\n        \"\"\"Extend selectionChanged to call completers selection_changed.\"\"\"\n        super().selectionChanged(selected, deselected)\n        self.selection_changed.emit(selected)\n\n    def resizeEvent(self, e):\n        \"\"\"Extend resizeEvent to adjust column size.\"\"\"\n        super().resizeEvent(e)\n        self._resize_columns()\n\n    def showEvent(self, e):\n        \"\"\"Adjust the completion size and scroll when it's freshly shown.\"\"\"\n        self.resize_completion.emit()\n        scrollbar = self.verticalScrollBar()\n        if scrollbar is not None:\n            scrollbar.setValue(scrollbar.minimum())\n        super().showEvent(e)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_prev(self):\n        \"\"\"Select the previous completion item.\"\"\"\n        self._next_prev_item(True)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_next(self):\n        \"\"\"Select the next completion item.\"\"\"\n        self._next_prev_item(False)\n\n    @cmdutils.register(instance='completion', hide=True,\n                       modes=[usertypes.KeyMode.command], scope='window')\n    def completion_item_del(self):\n        \"\"\"Delete the current completion item.\"\"\"\n        if not self.currentIndex().isValid():\n            raise cmdexc.CommandError(\"No item selected!\")\n        try:\n            self.model().srcmodel.delete_cur_item(self)\n        except NotImplementedError:\n            raise cmdexc.CommandError(\"Cannot delete this item.\")\n", "path": "qutebrowser/completion/completionwidget.py"}]}