We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Different colors per completion column
I think it would present a lot of visual clarity to be able to style the completion list's “sections” separately.

For example in pentadactyl, I can very easily visually distinguish between URLs and URL titles based on color alone:

![pentadactyl](https://0x0.st/BbS.png)

I'm lacking this visual feedback in qutebrowser. I think as a rough first approximation it would be fine to give explicit colors to the Nth sections (regardless of what they are), but I think in principle for this to work as well as possible the section order would have to be somewhat consistent between commands (so the URL is always in the same place, the title is always in the same place, etc.)


--- 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/completiondelegate.py`
Content:
```
1 # vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
2 
3 # Copyright 2014-2017 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 item delegate for CompletionView.
21 
22 We use this to be able to highlight parts of the text.
23 """
24 
25 import re
26 import html
27 
28 from PyQt5.QtWidgets import QStyle, QStyleOptionViewItem, QStyledItemDelegate
29 from PyQt5.QtCore import QRectF, QSize, Qt
30 from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
31                          QAbstractTextDocumentLayout)
32 
33 from qutebrowser.config import config
34 from qutebrowser.utils import qtutils, jinja
35 
36 
37 _cached_stylesheet = None
38 
39 
40 class CompletionItemDelegate(QStyledItemDelegate):
41 
42     """Delegate used by CompletionView to draw individual items.
43 
44     Mainly a cleaned up port of Qt's way to draw a TreeView item, except it
45     uses a QTextDocument to draw the text and add marking.
46 
47     Original implementation:
48         qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153
49 
50     Attributes:
51         _opt: The QStyleOptionViewItem which is used.
52         _style: The style to be used.
53         _painter: The QPainter to be used.
54         _doc: The QTextDocument to be used.
55     """
56 
57     # FIXME this is horribly slow when resizing.
58     # We should probably cache something in _get_textdoc or so, but as soon as
59     # we implement eliding that cache probably isn't worth much anymore...
60     # https://github.com/qutebrowser/qutebrowser/issues/121
61 
62     def __init__(self, parent=None):
63         self._painter = None
64         self._opt = None
65         self._doc = None
66         self._style = None
67         super().__init__(parent)
68 
69     def _draw_background(self):
70         """Draw the background of an ItemViewItem."""
71         self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,
72                                   self._painter, self._opt.widget)
73 
74     def _draw_icon(self):
75         """Draw the icon of an ItemViewItem."""
76         icon_rect = self._style.subElementRect(
77             self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget)
78         if not icon_rect.isValid():
79             # The rect seems to be wrong in all kind of ways if no icon should
80             # be displayed.
81             return
82 
83         mode = QIcon.Normal
84         if not self._opt.state & QStyle.State_Enabled:
85             mode = QIcon.Disabled
86         elif self._opt.state & QStyle.State_Selected:
87             mode = QIcon.Selected
88         state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off
89         self._opt.icon.paint(self._painter, icon_rect,
90                              self._opt.decorationAlignment, mode, state)
91 
92     def _draw_text(self, index):
93         """Draw the text of an ItemViewItem.
94 
95         This is the main part where we differ from the original implementation
96         in Qt: We use a QTextDocument to draw text.
97 
98         Args:
99             index: The QModelIndex of the item to draw.
100         """
101         if not self._opt.text:
102             return
103 
104         text_rect_ = self._style.subElementRect(
105             self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
106         qtutils.ensure_valid(text_rect_)
107         margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
108                                          self._opt, self._opt.widget) + 1
109         # remove width padding
110         text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
111         qtutils.ensure_valid(text_rect)
112         # move text upwards a bit
113         if index.parent().isValid():
114             text_rect.adjust(0, -1, 0, -1)
115         else:
116             text_rect.adjust(0, -2, 0, -2)
117         self._painter.save()
118         state = self._opt.state
119         if state & QStyle.State_Enabled and state & QStyle.State_Active:
120             cg = QPalette.Normal
121         elif state & QStyle.State_Enabled:
122             cg = QPalette.Inactive
123         else:
124             cg = QPalette.Disabled
125 
126         if state & QStyle.State_Selected:
127             self._painter.setPen(self._opt.palette.color(
128                 cg, QPalette.HighlightedText))
129             # This is a dirty fix for the text jumping by one pixel for
130             # whatever reason.
131             text_rect.adjust(0, -1, 0, 0)
132         else:
133             self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))
134 
135         if state & QStyle.State_Editing:
136             self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))
137             self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))
138 
139         self._painter.translate(text_rect.left(), text_rect.top())
140         self._get_textdoc(index)
141         self._draw_textdoc(text_rect)
142         self._painter.restore()
143 
144     def _draw_textdoc(self, rect):
145         """Draw the QTextDocument of an item.
146 
147         Args:
148             rect: The QRect to clip the drawing to.
149         """
150         # We can't use drawContents because then the color would be ignored.
151         clip = QRectF(0, 0, rect.width(), rect.height())
152         self._painter.save()
153 
154         if self._opt.state & QStyle.State_Selected:
155             color = config.val.colors.completion.item.selected.fg
156         elif not self._opt.state & QStyle.State_Enabled:
157             color = config.val.colors.completion.category.fg
158         else:
159             color = config.val.colors.completion.fg
160         self._painter.setPen(color)
161 
162         ctx = QAbstractTextDocumentLayout.PaintContext()
163         ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
164         if clip.isValid():
165             self._painter.setClipRect(clip)
166             ctx.clip = clip
167         self._doc.documentLayout().draw(self._painter, ctx)
168         self._painter.restore()
169 
170     def _get_textdoc(self, index):
171         """Create the QTextDocument of an item.
172 
173         Args:
174             index: The QModelIndex of the item to draw.
175         """
176         # FIXME we probably should do eliding here. See
177         # qcommonstyle.cpp:viewItemDrawText
178         # https://github.com/qutebrowser/qutebrowser/issues/118
179         text_option = QTextOption()
180         if self._opt.features & QStyleOptionViewItem.WrapText:
181             text_option.setWrapMode(QTextOption.WordWrap)
182         else:
183             text_option.setWrapMode(QTextOption.ManualWrap)
184         text_option.setTextDirection(self._opt.direction)
185         text_option.setAlignment(QStyle.visualAlignment(
186             self._opt.direction, self._opt.displayAlignment))
187 
188         if self._doc is not None:
189             self._doc.deleteLater()
190         self._doc = QTextDocument(self)
191         self._doc.setDefaultFont(self._opt.font)
192         self._doc.setDefaultTextOption(text_option)
193         self._doc.setDocumentMargin(2)
194 
195         assert _cached_stylesheet is not None
196         self._doc.setDefaultStyleSheet(_cached_stylesheet)
197 
198         if index.parent().isValid():
199             view = self.parent()
200             pattern = view.pattern
201             columns_to_filter = index.model().columns_to_filter(index)
202             if index.column() in columns_to_filter and pattern:
203                 repl = r'<span class="highlight">\g<0></span>'
204                 text = re.sub(re.escape(pattern).replace(r'\ ', r'|'),
205                               repl, html.escape(self._opt.text),
206                               flags=re.IGNORECASE)
207                 self._doc.setHtml(text)
208             else:
209                 self._doc.setPlainText(self._opt.text)
210         else:
211             self._doc.setHtml(
212                 '<span style="font: {};">{}</span>'.format(
213                     html.escape(config.val.fonts.completion.category),
214                     html.escape(self._opt.text)))
215 
216     def _draw_focus_rect(self):
217         """Draw the focus rectangle of an ItemViewItem."""
218         state = self._opt.state
219         if not state & QStyle.State_HasFocus:
220             return
221         o = self._opt
222         o.rect = self._style.subElementRect(
223             self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
224         o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
225         qtutils.ensure_valid(o.rect)
226         if state & QStyle.State_Enabled:
227             cg = QPalette.Normal
228         else:
229             cg = QPalette.Disabled
230         if state & QStyle.State_Selected:
231             role = QPalette.Highlight
232         else:
233             role = QPalette.Window
234         o.backgroundColor = self._opt.palette.color(cg, role)
235         self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,
236                                   self._opt.widget)
237 
238     def sizeHint(self, option, index):
239         """Override sizeHint of QStyledItemDelegate.
240 
241         Return the cell size based on the QTextDocument size, but might not
242         work correctly yet.
243 
244         Args:
245             option: const QStyleOptionViewItem & option
246             index: const QModelIndex & index
247 
248         Return:
249             A QSize with the recommended size.
250         """
251         value = index.data(Qt.SizeHintRole)
252         if value is not None:
253             return value
254         self._opt = QStyleOptionViewItem(option)
255         self.initStyleOption(self._opt, index)
256         self._style = self._opt.widget.style()
257         self._get_textdoc(index)
258         docsize = self._doc.size().toSize()
259         size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
260                                             docsize, self._opt.widget)
261         qtutils.ensure_valid(size)
262         return size + QSize(10, 3)
263 
264     def paint(self, painter, option, index):
265         """Override the QStyledItemDelegate paint function.
266 
267         Args:
268             painter: QPainter * painter
269             option: const QStyleOptionViewItem & option
270             index: const QModelIndex & index
271         """
272         self._painter = painter
273         self._painter.save()
274         self._opt = QStyleOptionViewItem(option)
275         self.initStyleOption(self._opt, index)
276         self._style = self._opt.widget.style()
277 
278         self._draw_background()
279         self._draw_icon()
280         self._draw_text(index)
281         self._draw_focus_rect()
282 
283         self._painter.restore()
284 
285 
286 @config.change_filter('colors.completion.match.fg', function=True)
287 def _update_stylesheet():
288     """Update the cached stylesheet."""
289     stylesheet = """
290         .highlight {
291             color: {{ conf.colors.completion.match.fg }};
292         }
293     """
294     with jinja.environment.no_autoescape():
295         template = jinja.environment.from_string(stylesheet)
296 
297     global _cached_stylesheet
298     _cached_stylesheet = template.render(conf=config.val)
299 
300 
301 def init():
302     """Initialize the cached stylesheet."""
303     _update_stylesheet()
304     config.instance.changed.connect(_update_stylesheet)
305
```
--- 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/completiondelegate.py b/qutebrowser/completion/completiondelegate.py
--- a/qutebrowser/completion/completiondelegate.py
+++ b/qutebrowser/completion/completiondelegate.py
@@ -138,10 +138,10 @@
 
         self._painter.translate(text_rect.left(), text_rect.top())
         self._get_textdoc(index)
-        self._draw_textdoc(text_rect)
+        self._draw_textdoc(text_rect, index.column())
         self._painter.restore()
 
-    def _draw_textdoc(self, rect):
+    def _draw_textdoc(self, rect, col):
         """Draw the QTextDocument of an item.
 
         Args:
@@ -156,7 +156,9 @@
         elif not self._opt.state & QStyle.State_Enabled:
             color = config.val.colors.completion.category.fg
         else:
-            color = config.val.colors.completion.fg
+            colors = config.val.colors.completion.fg
+            # if multiple colors are set, use different colors per column
+            color = colors[col % len(colors)]
         self._painter.setPen(color)
 
         ctx = QAbstractTextDocumentLayout.PaintContext()

{"golden_diff": "diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py\n--- a/qutebrowser/completion/completiondelegate.py\n+++ b/qutebrowser/completion/completiondelegate.py\n@@ -138,10 +138,10 @@\n \n         self._painter.translate(text_rect.left(), text_rect.top())\n         self._get_textdoc(index)\n-        self._draw_textdoc(text_rect)\n+        self._draw_textdoc(text_rect, index.column())\n         self._painter.restore()\n \n-    def _draw_textdoc(self, rect):\n+    def _draw_textdoc(self, rect, col):\n         \"\"\"Draw the QTextDocument of an item.\n \n         Args:\n@@ -156,7 +156,9 @@\n         elif not self._opt.state & QStyle.State_Enabled:\n             color = config.val.colors.completion.category.fg\n         else:\n-            color = config.val.colors.completion.fg\n+            colors = config.val.colors.completion.fg\n+            # if multiple colors are set, use different colors per column\n+            color = colors[col % len(colors)]\n         self._painter.setPen(color)\n \n         ctx = QAbstractTextDocumentLayout.PaintContext()\n", "issue": "Different colors per completion column\nI think it would present a lot of visual clarity to be able to style the completion list's \u201csections\u201d separately.\n\nFor example in pentadactyl, I can very easily visually distinguish between URLs and URL titles based on color alone:\n\n![pentadactyl](https://0x0.st/BbS.png)\n\nI'm lacking this visual feedback in qutebrowser. I think as a rough first approximation it would be fine to give explicit colors to the Nth sections (regardless of what they are), but I think in principle for this to work as well as possible the section order would have to be somewhat consistent between commands (so the URL is always in the same place, the title is always in the same place, etc.)\n\n", "before_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2017 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 item delegate for CompletionView.\n\nWe use this to be able to highlight parts of the text.\n\"\"\"\n\nimport re\nimport html\n\nfrom PyQt5.QtWidgets import QStyle, QStyleOptionViewItem, QStyledItemDelegate\nfrom PyQt5.QtCore import QRectF, QSize, Qt\nfrom PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,\n                         QAbstractTextDocumentLayout)\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import qtutils, jinja\n\n\n_cached_stylesheet = None\n\n\nclass CompletionItemDelegate(QStyledItemDelegate):\n\n    \"\"\"Delegate used by CompletionView to draw individual items.\n\n    Mainly a cleaned up port of Qt's way to draw a TreeView item, except it\n    uses a QTextDocument to draw the text and add marking.\n\n    Original implementation:\n        qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153\n\n    Attributes:\n        _opt: The QStyleOptionViewItem which is used.\n        _style: The style to be used.\n        _painter: The QPainter to be used.\n        _doc: The QTextDocument to be used.\n    \"\"\"\n\n    # FIXME this is horribly slow when resizing.\n    # We should probably cache something in _get_textdoc or so, but as soon as\n    # we implement eliding that cache probably isn't worth much anymore...\n    # https://github.com/qutebrowser/qutebrowser/issues/121\n\n    def __init__(self, parent=None):\n        self._painter = None\n        self._opt = None\n        self._doc = None\n        self._style = None\n        super().__init__(parent)\n\n    def _draw_background(self):\n        \"\"\"Draw the background of an ItemViewItem.\"\"\"\n        self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,\n                                  self._painter, self._opt.widget)\n\n    def _draw_icon(self):\n        \"\"\"Draw the icon of an ItemViewItem.\"\"\"\n        icon_rect = self._style.subElementRect(\n            self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget)\n        if not icon_rect.isValid():\n            # The rect seems to be wrong in all kind of ways if no icon should\n            # be displayed.\n            return\n\n        mode = QIcon.Normal\n        if not self._opt.state & QStyle.State_Enabled:\n            mode = QIcon.Disabled\n        elif self._opt.state & QStyle.State_Selected:\n            mode = QIcon.Selected\n        state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off\n        self._opt.icon.paint(self._painter, icon_rect,\n                             self._opt.decorationAlignment, mode, state)\n\n    def _draw_text(self, index):\n        \"\"\"Draw the text of an ItemViewItem.\n\n        This is the main part where we differ from the original implementation\n        in Qt: We use a QTextDocument to draw text.\n\n        Args:\n            index: The QModelIndex of the item to draw.\n        \"\"\"\n        if not self._opt.text:\n            return\n\n        text_rect_ = self._style.subElementRect(\n            self._style.SE_ItemViewItemText, self._opt, self._opt.widget)\n        qtutils.ensure_valid(text_rect_)\n        margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,\n                                         self._opt, self._opt.widget) + 1\n        # remove width padding\n        text_rect = text_rect_.adjusted(margin, 0, -margin, 0)\n        qtutils.ensure_valid(text_rect)\n        # move text upwards a bit\n        if index.parent().isValid():\n            text_rect.adjust(0, -1, 0, -1)\n        else:\n            text_rect.adjust(0, -2, 0, -2)\n        self._painter.save()\n        state = self._opt.state\n        if state & QStyle.State_Enabled and state & QStyle.State_Active:\n            cg = QPalette.Normal\n        elif state & QStyle.State_Enabled:\n            cg = QPalette.Inactive\n        else:\n            cg = QPalette.Disabled\n\n        if state & QStyle.State_Selected:\n            self._painter.setPen(self._opt.palette.color(\n                cg, QPalette.HighlightedText))\n            # This is a dirty fix for the text jumping by one pixel for\n            # whatever reason.\n            text_rect.adjust(0, -1, 0, 0)\n        else:\n            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))\n\n        if state & QStyle.State_Editing:\n            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))\n            self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))\n\n        self._painter.translate(text_rect.left(), text_rect.top())\n        self._get_textdoc(index)\n        self._draw_textdoc(text_rect)\n        self._painter.restore()\n\n    def _draw_textdoc(self, rect):\n        \"\"\"Draw the QTextDocument of an item.\n\n        Args:\n            rect: The QRect to clip the drawing to.\n        \"\"\"\n        # We can't use drawContents because then the color would be ignored.\n        clip = QRectF(0, 0, rect.width(), rect.height())\n        self._painter.save()\n\n        if self._opt.state & QStyle.State_Selected:\n            color = config.val.colors.completion.item.selected.fg\n        elif not self._opt.state & QStyle.State_Enabled:\n            color = config.val.colors.completion.category.fg\n        else:\n            color = config.val.colors.completion.fg\n        self._painter.setPen(color)\n\n        ctx = QAbstractTextDocumentLayout.PaintContext()\n        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())\n        if clip.isValid():\n            self._painter.setClipRect(clip)\n            ctx.clip = clip\n        self._doc.documentLayout().draw(self._painter, ctx)\n        self._painter.restore()\n\n    def _get_textdoc(self, index):\n        \"\"\"Create the QTextDocument of an item.\n\n        Args:\n            index: The QModelIndex of the item to draw.\n        \"\"\"\n        # FIXME we probably should do eliding here. See\n        # qcommonstyle.cpp:viewItemDrawText\n        # https://github.com/qutebrowser/qutebrowser/issues/118\n        text_option = QTextOption()\n        if self._opt.features & QStyleOptionViewItem.WrapText:\n            text_option.setWrapMode(QTextOption.WordWrap)\n        else:\n            text_option.setWrapMode(QTextOption.ManualWrap)\n        text_option.setTextDirection(self._opt.direction)\n        text_option.setAlignment(QStyle.visualAlignment(\n            self._opt.direction, self._opt.displayAlignment))\n\n        if self._doc is not None:\n            self._doc.deleteLater()\n        self._doc = QTextDocument(self)\n        self._doc.setDefaultFont(self._opt.font)\n        self._doc.setDefaultTextOption(text_option)\n        self._doc.setDocumentMargin(2)\n\n        assert _cached_stylesheet is not None\n        self._doc.setDefaultStyleSheet(_cached_stylesheet)\n\n        if index.parent().isValid():\n            view = self.parent()\n            pattern = view.pattern\n            columns_to_filter = index.model().columns_to_filter(index)\n            if index.column() in columns_to_filter and pattern:\n                repl = r'<span class=\"highlight\">\\g<0></span>'\n                text = re.sub(re.escape(pattern).replace(r'\\ ', r'|'),\n                              repl, html.escape(self._opt.text),\n                              flags=re.IGNORECASE)\n                self._doc.setHtml(text)\n            else:\n                self._doc.setPlainText(self._opt.text)\n        else:\n            self._doc.setHtml(\n                '<span style=\"font: {};\">{}</span>'.format(\n                    html.escape(config.val.fonts.completion.category),\n                    html.escape(self._opt.text)))\n\n    def _draw_focus_rect(self):\n        \"\"\"Draw the focus rectangle of an ItemViewItem.\"\"\"\n        state = self._opt.state\n        if not state & QStyle.State_HasFocus:\n            return\n        o = self._opt\n        o.rect = self._style.subElementRect(\n            self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)\n        o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item\n        qtutils.ensure_valid(o.rect)\n        if state & QStyle.State_Enabled:\n            cg = QPalette.Normal\n        else:\n            cg = QPalette.Disabled\n        if state & QStyle.State_Selected:\n            role = QPalette.Highlight\n        else:\n            role = QPalette.Window\n        o.backgroundColor = self._opt.palette.color(cg, role)\n        self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,\n                                  self._opt.widget)\n\n    def sizeHint(self, option, index):\n        \"\"\"Override sizeHint of QStyledItemDelegate.\n\n        Return the cell size based on the QTextDocument size, but might not\n        work correctly yet.\n\n        Args:\n            option: const QStyleOptionViewItem & option\n            index: const QModelIndex & index\n\n        Return:\n            A QSize with the recommended size.\n        \"\"\"\n        value = index.data(Qt.SizeHintRole)\n        if value is not None:\n            return value\n        self._opt = QStyleOptionViewItem(option)\n        self.initStyleOption(self._opt, index)\n        self._style = self._opt.widget.style()\n        self._get_textdoc(index)\n        docsize = self._doc.size().toSize()\n        size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,\n                                            docsize, self._opt.widget)\n        qtutils.ensure_valid(size)\n        return size + QSize(10, 3)\n\n    def paint(self, painter, option, index):\n        \"\"\"Override the QStyledItemDelegate paint function.\n\n        Args:\n            painter: QPainter * painter\n            option: const QStyleOptionViewItem & option\n            index: const QModelIndex & index\n        \"\"\"\n        self._painter = painter\n        self._painter.save()\n        self._opt = QStyleOptionViewItem(option)\n        self.initStyleOption(self._opt, index)\n        self._style = self._opt.widget.style()\n\n        self._draw_background()\n        self._draw_icon()\n        self._draw_text(index)\n        self._draw_focus_rect()\n\n        self._painter.restore()\n\n\n@config.change_filter('colors.completion.match.fg', function=True)\ndef _update_stylesheet():\n    \"\"\"Update the cached stylesheet.\"\"\"\n    stylesheet = \"\"\"\n        .highlight {\n            color: {{ conf.colors.completion.match.fg }};\n        }\n    \"\"\"\n    with jinja.environment.no_autoescape():\n        template = jinja.environment.from_string(stylesheet)\n\n    global _cached_stylesheet\n    _cached_stylesheet = template.render(conf=config.val)\n\n\ndef init():\n    \"\"\"Initialize the cached stylesheet.\"\"\"\n    _update_stylesheet()\n    config.instance.changed.connect(_update_stylesheet)\n", "path": "qutebrowser/completion/completiondelegate.py"}], "after_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2017 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 item delegate for CompletionView.\n\nWe use this to be able to highlight parts of the text.\n\"\"\"\n\nimport re\nimport html\n\nfrom PyQt5.QtWidgets import QStyle, QStyleOptionViewItem, QStyledItemDelegate\nfrom PyQt5.QtCore import QRectF, QSize, Qt\nfrom PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,\n                         QAbstractTextDocumentLayout)\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import qtutils, jinja\n\n\n_cached_stylesheet = None\n\n\nclass CompletionItemDelegate(QStyledItemDelegate):\n\n    \"\"\"Delegate used by CompletionView to draw individual items.\n\n    Mainly a cleaned up port of Qt's way to draw a TreeView item, except it\n    uses a QTextDocument to draw the text and add marking.\n\n    Original implementation:\n        qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153\n\n    Attributes:\n        _opt: The QStyleOptionViewItem which is used.\n        _style: The style to be used.\n        _painter: The QPainter to be used.\n        _doc: The QTextDocument to be used.\n    \"\"\"\n\n    # FIXME this is horribly slow when resizing.\n    # We should probably cache something in _get_textdoc or so, but as soon as\n    # we implement eliding that cache probably isn't worth much anymore...\n    # https://github.com/qutebrowser/qutebrowser/issues/121\n\n    def __init__(self, parent=None):\n        self._painter = None\n        self._opt = None\n        self._doc = None\n        self._style = None\n        super().__init__(parent)\n\n    def _draw_background(self):\n        \"\"\"Draw the background of an ItemViewItem.\"\"\"\n        self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,\n                                  self._painter, self._opt.widget)\n\n    def _draw_icon(self):\n        \"\"\"Draw the icon of an ItemViewItem.\"\"\"\n        icon_rect = self._style.subElementRect(\n            self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget)\n        if not icon_rect.isValid():\n            # The rect seems to be wrong in all kind of ways if no icon should\n            # be displayed.\n            return\n\n        mode = QIcon.Normal\n        if not self._opt.state & QStyle.State_Enabled:\n            mode = QIcon.Disabled\n        elif self._opt.state & QStyle.State_Selected:\n            mode = QIcon.Selected\n        state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off\n        self._opt.icon.paint(self._painter, icon_rect,\n                             self._opt.decorationAlignment, mode, state)\n\n    def _draw_text(self, index):\n        \"\"\"Draw the text of an ItemViewItem.\n\n        This is the main part where we differ from the original implementation\n        in Qt: We use a QTextDocument to draw text.\n\n        Args:\n            index: The QModelIndex of the item to draw.\n        \"\"\"\n        if not self._opt.text:\n            return\n\n        text_rect_ = self._style.subElementRect(\n            self._style.SE_ItemViewItemText, self._opt, self._opt.widget)\n        qtutils.ensure_valid(text_rect_)\n        margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,\n                                         self._opt, self._opt.widget) + 1\n        # remove width padding\n        text_rect = text_rect_.adjusted(margin, 0, -margin, 0)\n        qtutils.ensure_valid(text_rect)\n        # move text upwards a bit\n        if index.parent().isValid():\n            text_rect.adjust(0, -1, 0, -1)\n        else:\n            text_rect.adjust(0, -2, 0, -2)\n        self._painter.save()\n        state = self._opt.state\n        if state & QStyle.State_Enabled and state & QStyle.State_Active:\n            cg = QPalette.Normal\n        elif state & QStyle.State_Enabled:\n            cg = QPalette.Inactive\n        else:\n            cg = QPalette.Disabled\n\n        if state & QStyle.State_Selected:\n            self._painter.setPen(self._opt.palette.color(\n                cg, QPalette.HighlightedText))\n            # This is a dirty fix for the text jumping by one pixel for\n            # whatever reason.\n            text_rect.adjust(0, -1, 0, 0)\n        else:\n            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))\n\n        if state & QStyle.State_Editing:\n            self._painter.setPen(self._opt.palette.color(cg, QPalette.Text))\n            self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))\n\n        self._painter.translate(text_rect.left(), text_rect.top())\n        self._get_textdoc(index)\n        self._draw_textdoc(text_rect, index.column())\n        self._painter.restore()\n\n    def _draw_textdoc(self, rect, col):\n        \"\"\"Draw the QTextDocument of an item.\n\n        Args:\n            rect: The QRect to clip the drawing to.\n        \"\"\"\n        # We can't use drawContents because then the color would be ignored.\n        clip = QRectF(0, 0, rect.width(), rect.height())\n        self._painter.save()\n\n        if self._opt.state & QStyle.State_Selected:\n            color = config.val.colors.completion.item.selected.fg\n        elif not self._opt.state & QStyle.State_Enabled:\n            color = config.val.colors.completion.category.fg\n        else:\n            colors = config.val.colors.completion.fg\n            # if multiple colors are set, use different colors per column\n            color = colors[col % len(colors)]\n        self._painter.setPen(color)\n\n        ctx = QAbstractTextDocumentLayout.PaintContext()\n        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())\n        if clip.isValid():\n            self._painter.setClipRect(clip)\n            ctx.clip = clip\n        self._doc.documentLayout().draw(self._painter, ctx)\n        self._painter.restore()\n\n    def _get_textdoc(self, index):\n        \"\"\"Create the QTextDocument of an item.\n\n        Args:\n            index: The QModelIndex of the item to draw.\n        \"\"\"\n        # FIXME we probably should do eliding here. See\n        # qcommonstyle.cpp:viewItemDrawText\n        # https://github.com/qutebrowser/qutebrowser/issues/118\n        text_option = QTextOption()\n        if self._opt.features & QStyleOptionViewItem.WrapText:\n            text_option.setWrapMode(QTextOption.WordWrap)\n        else:\n            text_option.setWrapMode(QTextOption.ManualWrap)\n        text_option.setTextDirection(self._opt.direction)\n        text_option.setAlignment(QStyle.visualAlignment(\n            self._opt.direction, self._opt.displayAlignment))\n\n        if self._doc is not None:\n            self._doc.deleteLater()\n        self._doc = QTextDocument(self)\n        self._doc.setDefaultFont(self._opt.font)\n        self._doc.setDefaultTextOption(text_option)\n        self._doc.setDocumentMargin(2)\n\n        assert _cached_stylesheet is not None\n        self._doc.setDefaultStyleSheet(_cached_stylesheet)\n\n        if index.parent().isValid():\n            view = self.parent()\n            pattern = view.pattern\n            columns_to_filter = index.model().columns_to_filter(index)\n            if index.column() in columns_to_filter and pattern:\n                repl = r'<span class=\"highlight\">\\g<0></span>'\n                text = re.sub(re.escape(pattern).replace(r'\\ ', r'|'),\n                              repl, html.escape(self._opt.text),\n                              flags=re.IGNORECASE)\n                self._doc.setHtml(text)\n            else:\n                self._doc.setPlainText(self._opt.text)\n        else:\n            self._doc.setHtml(\n                '<span style=\"font: {};\">{}</span>'.format(\n                    html.escape(config.val.fonts.completion.category),\n                    html.escape(self._opt.text)))\n\n    def _draw_focus_rect(self):\n        \"\"\"Draw the focus rectangle of an ItemViewItem.\"\"\"\n        state = self._opt.state\n        if not state & QStyle.State_HasFocus:\n            return\n        o = self._opt\n        o.rect = self._style.subElementRect(\n            self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)\n        o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item\n        qtutils.ensure_valid(o.rect)\n        if state & QStyle.State_Enabled:\n            cg = QPalette.Normal\n        else:\n            cg = QPalette.Disabled\n        if state & QStyle.State_Selected:\n            role = QPalette.Highlight\n        else:\n            role = QPalette.Window\n        o.backgroundColor = self._opt.palette.color(cg, role)\n        self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,\n                                  self._opt.widget)\n\n    def sizeHint(self, option, index):\n        \"\"\"Override sizeHint of QStyledItemDelegate.\n\n        Return the cell size based on the QTextDocument size, but might not\n        work correctly yet.\n\n        Args:\n            option: const QStyleOptionViewItem & option\n            index: const QModelIndex & index\n\n        Return:\n            A QSize with the recommended size.\n        \"\"\"\n        value = index.data(Qt.SizeHintRole)\n        if value is not None:\n            return value\n        self._opt = QStyleOptionViewItem(option)\n        self.initStyleOption(self._opt, index)\n        self._style = self._opt.widget.style()\n        self._get_textdoc(index)\n        docsize = self._doc.size().toSize()\n        size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,\n                                            docsize, self._opt.widget)\n        qtutils.ensure_valid(size)\n        return size + QSize(10, 3)\n\n    def paint(self, painter, option, index):\n        \"\"\"Override the QStyledItemDelegate paint function.\n\n        Args:\n            painter: QPainter * painter\n            option: const QStyleOptionViewItem & option\n            index: const QModelIndex & index\n        \"\"\"\n        self._painter = painter\n        self._painter.save()\n        self._opt = QStyleOptionViewItem(option)\n        self.initStyleOption(self._opt, index)\n        self._style = self._opt.widget.style()\n\n        self._draw_background()\n        self._draw_icon()\n        self._draw_text(index)\n        self._draw_focus_rect()\n\n        self._painter.restore()\n\n\n@config.change_filter('colors.completion.match.fg', function=True)\ndef _update_stylesheet():\n    \"\"\"Update the cached stylesheet.\"\"\"\n    stylesheet = \"\"\"\n        .highlight {\n            color: {{ conf.colors.completion.match.fg }};\n        }\n    \"\"\"\n    with jinja.environment.no_autoescape():\n        template = jinja.environment.from_string(stylesheet)\n\n    global _cached_stylesheet\n    _cached_stylesheet = template.render(conf=config.val)\n\n\ndef init():\n    \"\"\"Initialize the cached stylesheet.\"\"\"\n    _update_stylesheet()\n    config.instance.changed.connect(_update_stylesheet)\n", "path": "qutebrowser/completion/completiondelegate.py"}]}