We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Shift-home doesn't mark anything in commandline
Shift-end works fine, but shift-home doesn't - probably due to qutebrowser changing the cursor position to after the `:`.

--- 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/misc/miscwidgets.py`
Content:
```
1 # vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
2 
3 # Copyright 2014-2018 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 """Misc. widgets used at different places."""
21 
22 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QSize, QTimer
23 from PyQt5.QtWidgets import (QLineEdit, QWidget, QHBoxLayout, QLabel,
24                              QStyleOption, QStyle, QLayout, QApplication)
25 from PyQt5.QtGui import QValidator, QPainter
26 
27 from qutebrowser.config import config
28 from qutebrowser.utils import utils
29 from qutebrowser.misc import cmdhistory
30 
31 
32 class MinimalLineEditMixin:
33 
34     """A mixin to give a QLineEdit a minimal look and nicer repr()."""
35 
36     def __init__(self):
37         self.setStyleSheet("""
38             QLineEdit {
39                 border: 0px;
40                 padding-left: 1px;
41                 background-color: transparent;
42             }
43         """)
44         self.setAttribute(Qt.WA_MacShowFocusRect, False)
45 
46     def keyPressEvent(self, e):
47         """Override keyPressEvent to paste primary selection on Shift + Ins."""
48         if e.key() == Qt.Key_Insert and e.modifiers() == Qt.ShiftModifier:
49             try:
50                 text = utils.get_clipboard(selection=True, fallback=True)
51             except utils.ClipboardError:
52                 e.ignore()
53             else:
54                 e.accept()
55                 self.insert(text)
56             return
57         super().keyPressEvent(e)
58 
59     def __repr__(self):
60         return utils.get_repr(self)
61 
62 
63 class CommandLineEdit(QLineEdit):
64 
65     """A QLineEdit with a history and prompt chars.
66 
67     Attributes:
68         history: The command history object.
69         _validator: The current command validator.
70         _promptlen: The length of the current prompt.
71     """
72 
73     def __init__(self, *, parent=None):
74         super().__init__(parent)
75         self.history = cmdhistory.History(parent=self)
76         self._validator = _CommandValidator(self)
77         self.setValidator(self._validator)
78         self.textEdited.connect(self.on_text_edited)
79         self.cursorPositionChanged.connect(self.__on_cursor_position_changed)
80         self._promptlen = 0
81 
82     def __repr__(self):
83         return utils.get_repr(self, text=self.text())
84 
85     @pyqtSlot(str)
86     def on_text_edited(self, _text):
87         """Slot for textEdited. Stop history browsing."""
88         self.history.stop()
89 
90     @pyqtSlot(int, int)
91     def __on_cursor_position_changed(self, _old, new):
92         """Prevent the cursor moving to the prompt.
93 
94         We use __ here to avoid accidentally overriding it in subclasses.
95         """
96         if new < self._promptlen:
97             self.setCursorPosition(self._promptlen)
98 
99     def set_prompt(self, text):
100         """Set the current prompt to text.
101 
102         This updates the validator, and makes sure the user can't move the
103         cursor behind the prompt.
104         """
105         self._validator.prompt = text
106         self._promptlen = len(text)
107 
108     def home(self, mark):
109         """Override home so it works properly with our cursor restriction."""
110         oldpos = self.cursorPosition()
111         self.setCursorPosition(self._promptlen)
112         if mark:
113             self.setSelection(self._promptlen, oldpos - self._promptlen)
114 
115 
116 class _CommandValidator(QValidator):
117 
118     """Validator to prevent the : from getting deleted.
119 
120     Attributes:
121         prompt: The current prompt.
122     """
123 
124     def __init__(self, parent=None):
125         super().__init__(parent)
126         self.prompt = None
127 
128     def validate(self, string, pos):
129         """Override QValidator::validate.
130 
131         Args:
132             string: The string to validate.
133             pos: The current cursor position.
134 
135         Return:
136             A tuple (status, string, pos) as a QValidator should.
137         """
138         if self.prompt is None or string.startswith(self.prompt):
139             return (QValidator.Acceptable, string, pos)
140         else:
141             return (QValidator.Invalid, string, pos)
142 
143 
144 class DetailFold(QWidget):
145 
146     """A "fold" widget with an arrow to show/hide details.
147 
148     Attributes:
149         _folded: Whether the widget is currently folded or not.
150         _hbox: The HBoxLayout the arrow/label are in.
151         _arrow: The FoldArrow widget.
152 
153     Signals:
154         toggled: Emitted when the widget was folded/unfolded.
155                  arg 0: bool, if the contents are currently visible.
156     """
157 
158     toggled = pyqtSignal(bool)
159 
160     def __init__(self, text, parent=None):
161         super().__init__(parent)
162         self._folded = True
163         self._hbox = QHBoxLayout(self)
164         self._hbox.setContentsMargins(0, 0, 0, 0)
165         self._arrow = _FoldArrow()
166         self._hbox.addWidget(self._arrow)
167         label = QLabel(text)
168         self._hbox.addWidget(label)
169         self._hbox.addStretch()
170 
171     def toggle(self):
172         """Toggle the fold of the widget."""
173         self._folded = not self._folded
174         self._arrow.fold(self._folded)
175         self.toggled.emit(not self._folded)
176 
177     def mousePressEvent(self, e):
178         """Toggle the fold if the widget was pressed.
179 
180         Args:
181             e: The QMouseEvent.
182         """
183         if e.button() == Qt.LeftButton:
184             e.accept()
185             self.toggle()
186         else:
187             super().mousePressEvent(e)
188 
189 
190 class _FoldArrow(QWidget):
191 
192     """The arrow shown for the DetailFold widget.
193 
194     Attributes:
195         _folded: Whether the widget is currently folded or not.
196     """
197 
198     def __init__(self, parent=None):
199         super().__init__(parent)
200         self._folded = True
201 
202     def fold(self, folded):
203         """Fold/unfold the widget.
204 
205         Args:
206             folded: The new desired state.
207         """
208         self._folded = folded
209         self.update()
210 
211     def paintEvent(self, _event):
212         """Paint the arrow.
213 
214         Args:
215             _paint: The QPaintEvent (unused).
216         """
217         opt = QStyleOption()
218         opt.initFrom(self)
219         painter = QPainter(self)
220         if self._folded:
221             elem = QStyle.PE_IndicatorArrowRight
222         else:
223             elem = QStyle.PE_IndicatorArrowDown
224         self.style().drawPrimitive(elem, opt, painter, self)
225 
226     def minimumSizeHint(self):
227         """Return a sensible size."""
228         return QSize(8, 8)
229 
230 
231 class WrapperLayout(QLayout):
232 
233     """A Qt layout which simply wraps a single widget.
234 
235     This is used so the widget is hidden behind a defined API and can't
236     easily be accidentally accessed.
237     """
238 
239     def __init__(self, parent=None):
240         super().__init__(parent)
241         self._widget = None
242 
243     def addItem(self, _widget):
244         raise utils.Unreachable
245 
246     def sizeHint(self):
247         return self._widget.sizeHint()
248 
249     def itemAt(self, _index):
250         return None
251 
252     def takeAt(self, _index):
253         raise utils.Unreachable
254 
255     def setGeometry(self, rect):
256         self._widget.setGeometry(rect)
257 
258     def wrap(self, container, widget):
259         """Wrap the given widget in the given container."""
260         self._widget = widget
261         container.setFocusProxy(widget)
262         widget.setParent(container)
263 
264     def unwrap(self):
265         self._widget.setParent(None)
266         self._widget.deleteLater()
267 
268 
269 class PseudoLayout(QLayout):
270 
271     """A layout which isn't actually a real layout.
272 
273     This is used to replace QWebEngineView's internal layout, as a WORKAROUND
274     for https://bugreports.qt.io/browse/QTBUG-68224 and other related issues.
275 
276     This is partly inspired by https://codereview.qt-project.org/#/c/230894/
277     which does something similar as part of Qt.
278     """
279 
280     def addItem(self, item):
281         assert self.parent() is not None
282         item.widget().setParent(self.parent())
283 
284     def removeItem(self, item):
285         item.widget().setParent(None)
286 
287     def count(self):
288         return 0
289 
290     def itemAt(self, _pos):
291         return None
292 
293     def widget(self):
294         return self.parent().render_widget()
295 
296     def setGeometry(self, rect):
297         """Resize the render widget when the view is resized."""
298         widget = self.widget()
299         if widget is not None:
300             widget.setGeometry(rect)
301 
302     def sizeHint(self):
303         """Make sure the view has the sizeHint of the render widget."""
304         widget = self.widget()
305         if widget is not None:
306             return widget.sizeHint()
307         return QSize()
308 
309 
310 class FullscreenNotification(QLabel):
311 
312     """A label telling the user this page is now fullscreen."""
313 
314     def __init__(self, parent=None):
315         super().__init__(parent)
316         self.setStyleSheet("""
317             background-color: rgba(50, 50, 50, 80%);
318             color: white;
319             border-radius: 20px;
320             padding: 30px;
321         """)
322 
323         all_bindings = config.key_instance.get_reverse_bindings_for('normal')
324         bindings = all_bindings.get('fullscreen --leave')
325         if bindings:
326             key = bindings[0]
327             self.setText("Press {} to exit fullscreen.".format(key))
328         else:
329             self.setText("Page is now fullscreen.")
330 
331         self.resize(self.sizeHint())
332         if config.val.content.windowed_fullscreen:
333             geom = self.parentWidget().geometry()
334         else:
335             geom = QApplication.desktop().screenGeometry(self)
336         self.move((geom.width() - self.sizeHint().width()) / 2, 30)
337 
338     def set_timeout(self, timeout):
339         """Hide the widget after the given timeout."""
340         QTimer.singleShot(timeout, self._on_timeout)
341 
342     @pyqtSlot()
343     def _on_timeout(self):
344         """Hide and delete the widget."""
345         self.hide()
346         self.deleteLater()
347
```
--- 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/misc/miscwidgets.py b/qutebrowser/misc/miscwidgets.py
--- a/qutebrowser/misc/miscwidgets.py
+++ b/qutebrowser/misc/miscwidgets.py
@@ -94,7 +94,7 @@
         We use __ here to avoid accidentally overriding it in subclasses.
         """
         if new < self._promptlen:
-            self.setCursorPosition(self._promptlen)
+            self.cursorForward(self.hasSelectedText(), self._promptlen - new)
 
     def set_prompt(self, text):
         """Set the current prompt to text.
@@ -105,13 +105,6 @@
         self._validator.prompt = text
         self._promptlen = len(text)
 
-    def home(self, mark):
-        """Override home so it works properly with our cursor restriction."""
-        oldpos = self.cursorPosition()
-        self.setCursorPosition(self._promptlen)
-        if mark:
-            self.setSelection(self._promptlen, oldpos - self._promptlen)
-
 
 class _CommandValidator(QValidator):

{"golden_diff": "diff --git a/qutebrowser/misc/miscwidgets.py b/qutebrowser/misc/miscwidgets.py\n--- a/qutebrowser/misc/miscwidgets.py\n+++ b/qutebrowser/misc/miscwidgets.py\n@@ -94,7 +94,7 @@\n         We use __ here to avoid accidentally overriding it in subclasses.\n         \"\"\"\n         if new < self._promptlen:\n-            self.setCursorPosition(self._promptlen)\n+            self.cursorForward(self.hasSelectedText(), self._promptlen - new)\n \n     def set_prompt(self, text):\n         \"\"\"Set the current prompt to text.\n@@ -105,13 +105,6 @@\n         self._validator.prompt = text\n         self._promptlen = len(text)\n \n-    def home(self, mark):\n-        \"\"\"Override home so it works properly with our cursor restriction.\"\"\"\n-        oldpos = self.cursorPosition()\n-        self.setCursorPosition(self._promptlen)\n-        if mark:\n-            self.setSelection(self._promptlen, oldpos - self._promptlen)\n-\n \n class _CommandValidator(QValidator):\n", "issue": "Shift-home doesn't mark anything in commandline\nShift-end works fine, but shift-home doesn't - probably due to qutebrowser changing the cursor position to after the `:`.\n", "before_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2018 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\"\"\"Misc. widgets used at different places.\"\"\"\n\nfrom PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QSize, QTimer\nfrom PyQt5.QtWidgets import (QLineEdit, QWidget, QHBoxLayout, QLabel,\n                             QStyleOption, QStyle, QLayout, QApplication)\nfrom PyQt5.QtGui import QValidator, QPainter\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import utils\nfrom qutebrowser.misc import cmdhistory\n\n\nclass MinimalLineEditMixin:\n\n    \"\"\"A mixin to give a QLineEdit a minimal look and nicer repr().\"\"\"\n\n    def __init__(self):\n        self.setStyleSheet(\"\"\"\n            QLineEdit {\n                border: 0px;\n                padding-left: 1px;\n                background-color: transparent;\n            }\n        \"\"\")\n        self.setAttribute(Qt.WA_MacShowFocusRect, False)\n\n    def keyPressEvent(self, e):\n        \"\"\"Override keyPressEvent to paste primary selection on Shift + Ins.\"\"\"\n        if e.key() == Qt.Key_Insert and e.modifiers() == Qt.ShiftModifier:\n            try:\n                text = utils.get_clipboard(selection=True, fallback=True)\n            except utils.ClipboardError:\n                e.ignore()\n            else:\n                e.accept()\n                self.insert(text)\n            return\n        super().keyPressEvent(e)\n\n    def __repr__(self):\n        return utils.get_repr(self)\n\n\nclass CommandLineEdit(QLineEdit):\n\n    \"\"\"A QLineEdit with a history and prompt chars.\n\n    Attributes:\n        history: The command history object.\n        _validator: The current command validator.\n        _promptlen: The length of the current prompt.\n    \"\"\"\n\n    def __init__(self, *, parent=None):\n        super().__init__(parent)\n        self.history = cmdhistory.History(parent=self)\n        self._validator = _CommandValidator(self)\n        self.setValidator(self._validator)\n        self.textEdited.connect(self.on_text_edited)\n        self.cursorPositionChanged.connect(self.__on_cursor_position_changed)\n        self._promptlen = 0\n\n    def __repr__(self):\n        return utils.get_repr(self, text=self.text())\n\n    @pyqtSlot(str)\n    def on_text_edited(self, _text):\n        \"\"\"Slot for textEdited. Stop history browsing.\"\"\"\n        self.history.stop()\n\n    @pyqtSlot(int, int)\n    def __on_cursor_position_changed(self, _old, new):\n        \"\"\"Prevent the cursor moving to the prompt.\n\n        We use __ here to avoid accidentally overriding it in subclasses.\n        \"\"\"\n        if new < self._promptlen:\n            self.setCursorPosition(self._promptlen)\n\n    def set_prompt(self, text):\n        \"\"\"Set the current prompt to text.\n\n        This updates the validator, and makes sure the user can't move the\n        cursor behind the prompt.\n        \"\"\"\n        self._validator.prompt = text\n        self._promptlen = len(text)\n\n    def home(self, mark):\n        \"\"\"Override home so it works properly with our cursor restriction.\"\"\"\n        oldpos = self.cursorPosition()\n        self.setCursorPosition(self._promptlen)\n        if mark:\n            self.setSelection(self._promptlen, oldpos - self._promptlen)\n\n\nclass _CommandValidator(QValidator):\n\n    \"\"\"Validator to prevent the : from getting deleted.\n\n    Attributes:\n        prompt: The current prompt.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self.prompt = None\n\n    def validate(self, string, pos):\n        \"\"\"Override QValidator::validate.\n\n        Args:\n            string: The string to validate.\n            pos: The current cursor position.\n\n        Return:\n            A tuple (status, string, pos) as a QValidator should.\n        \"\"\"\n        if self.prompt is None or string.startswith(self.prompt):\n            return (QValidator.Acceptable, string, pos)\n        else:\n            return (QValidator.Invalid, string, pos)\n\n\nclass DetailFold(QWidget):\n\n    \"\"\"A \"fold\" widget with an arrow to show/hide details.\n\n    Attributes:\n        _folded: Whether the widget is currently folded or not.\n        _hbox: The HBoxLayout the arrow/label are in.\n        _arrow: The FoldArrow widget.\n\n    Signals:\n        toggled: Emitted when the widget was folded/unfolded.\n                 arg 0: bool, if the contents are currently visible.\n    \"\"\"\n\n    toggled = pyqtSignal(bool)\n\n    def __init__(self, text, parent=None):\n        super().__init__(parent)\n        self._folded = True\n        self._hbox = QHBoxLayout(self)\n        self._hbox.setContentsMargins(0, 0, 0, 0)\n        self._arrow = _FoldArrow()\n        self._hbox.addWidget(self._arrow)\n        label = QLabel(text)\n        self._hbox.addWidget(label)\n        self._hbox.addStretch()\n\n    def toggle(self):\n        \"\"\"Toggle the fold of the widget.\"\"\"\n        self._folded = not self._folded\n        self._arrow.fold(self._folded)\n        self.toggled.emit(not self._folded)\n\n    def mousePressEvent(self, e):\n        \"\"\"Toggle the fold if the widget was pressed.\n\n        Args:\n            e: The QMouseEvent.\n        \"\"\"\n        if e.button() == Qt.LeftButton:\n            e.accept()\n            self.toggle()\n        else:\n            super().mousePressEvent(e)\n\n\nclass _FoldArrow(QWidget):\n\n    \"\"\"The arrow shown for the DetailFold widget.\n\n    Attributes:\n        _folded: Whether the widget is currently folded or not.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self._folded = True\n\n    def fold(self, folded):\n        \"\"\"Fold/unfold the widget.\n\n        Args:\n            folded: The new desired state.\n        \"\"\"\n        self._folded = folded\n        self.update()\n\n    def paintEvent(self, _event):\n        \"\"\"Paint the arrow.\n\n        Args:\n            _paint: The QPaintEvent (unused).\n        \"\"\"\n        opt = QStyleOption()\n        opt.initFrom(self)\n        painter = QPainter(self)\n        if self._folded:\n            elem = QStyle.PE_IndicatorArrowRight\n        else:\n            elem = QStyle.PE_IndicatorArrowDown\n        self.style().drawPrimitive(elem, opt, painter, self)\n\n    def minimumSizeHint(self):\n        \"\"\"Return a sensible size.\"\"\"\n        return QSize(8, 8)\n\n\nclass WrapperLayout(QLayout):\n\n    \"\"\"A Qt layout which simply wraps a single widget.\n\n    This is used so the widget is hidden behind a defined API and can't\n    easily be accidentally accessed.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self._widget = None\n\n    def addItem(self, _widget):\n        raise utils.Unreachable\n\n    def sizeHint(self):\n        return self._widget.sizeHint()\n\n    def itemAt(self, _index):\n        return None\n\n    def takeAt(self, _index):\n        raise utils.Unreachable\n\n    def setGeometry(self, rect):\n        self._widget.setGeometry(rect)\n\n    def wrap(self, container, widget):\n        \"\"\"Wrap the given widget in the given container.\"\"\"\n        self._widget = widget\n        container.setFocusProxy(widget)\n        widget.setParent(container)\n\n    def unwrap(self):\n        self._widget.setParent(None)\n        self._widget.deleteLater()\n\n\nclass PseudoLayout(QLayout):\n\n    \"\"\"A layout which isn't actually a real layout.\n\n    This is used to replace QWebEngineView's internal layout, as a WORKAROUND\n    for https://bugreports.qt.io/browse/QTBUG-68224 and other related issues.\n\n    This is partly inspired by https://codereview.qt-project.org/#/c/230894/\n    which does something similar as part of Qt.\n    \"\"\"\n\n    def addItem(self, item):\n        assert self.parent() is not None\n        item.widget().setParent(self.parent())\n\n    def removeItem(self, item):\n        item.widget().setParent(None)\n\n    def count(self):\n        return 0\n\n    def itemAt(self, _pos):\n        return None\n\n    def widget(self):\n        return self.parent().render_widget()\n\n    def setGeometry(self, rect):\n        \"\"\"Resize the render widget when the view is resized.\"\"\"\n        widget = self.widget()\n        if widget is not None:\n            widget.setGeometry(rect)\n\n    def sizeHint(self):\n        \"\"\"Make sure the view has the sizeHint of the render widget.\"\"\"\n        widget = self.widget()\n        if widget is not None:\n            return widget.sizeHint()\n        return QSize()\n\n\nclass FullscreenNotification(QLabel):\n\n    \"\"\"A label telling the user this page is now fullscreen.\"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self.setStyleSheet(\"\"\"\n            background-color: rgba(50, 50, 50, 80%);\n            color: white;\n            border-radius: 20px;\n            padding: 30px;\n        \"\"\")\n\n        all_bindings = config.key_instance.get_reverse_bindings_for('normal')\n        bindings = all_bindings.get('fullscreen --leave')\n        if bindings:\n            key = bindings[0]\n            self.setText(\"Press {} to exit fullscreen.\".format(key))\n        else:\n            self.setText(\"Page is now fullscreen.\")\n\n        self.resize(self.sizeHint())\n        if config.val.content.windowed_fullscreen:\n            geom = self.parentWidget().geometry()\n        else:\n            geom = QApplication.desktop().screenGeometry(self)\n        self.move((geom.width() - self.sizeHint().width()) / 2, 30)\n\n    def set_timeout(self, timeout):\n        \"\"\"Hide the widget after the given timeout.\"\"\"\n        QTimer.singleShot(timeout, self._on_timeout)\n\n    @pyqtSlot()\n    def _on_timeout(self):\n        \"\"\"Hide and delete the widget.\"\"\"\n        self.hide()\n        self.deleteLater()\n", "path": "qutebrowser/misc/miscwidgets.py"}], "after_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2014-2018 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\"\"\"Misc. widgets used at different places.\"\"\"\n\nfrom PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QSize, QTimer\nfrom PyQt5.QtWidgets import (QLineEdit, QWidget, QHBoxLayout, QLabel,\n                             QStyleOption, QStyle, QLayout, QApplication)\nfrom PyQt5.QtGui import QValidator, QPainter\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import utils\nfrom qutebrowser.misc import cmdhistory\n\n\nclass MinimalLineEditMixin:\n\n    \"\"\"A mixin to give a QLineEdit a minimal look and nicer repr().\"\"\"\n\n    def __init__(self):\n        self.setStyleSheet(\"\"\"\n            QLineEdit {\n                border: 0px;\n                padding-left: 1px;\n                background-color: transparent;\n            }\n        \"\"\")\n        self.setAttribute(Qt.WA_MacShowFocusRect, False)\n\n    def keyPressEvent(self, e):\n        \"\"\"Override keyPressEvent to paste primary selection on Shift + Ins.\"\"\"\n        if e.key() == Qt.Key_Insert and e.modifiers() == Qt.ShiftModifier:\n            try:\n                text = utils.get_clipboard(selection=True, fallback=True)\n            except utils.ClipboardError:\n                e.ignore()\n            else:\n                e.accept()\n                self.insert(text)\n            return\n        super().keyPressEvent(e)\n\n    def __repr__(self):\n        return utils.get_repr(self)\n\n\nclass CommandLineEdit(QLineEdit):\n\n    \"\"\"A QLineEdit with a history and prompt chars.\n\n    Attributes:\n        history: The command history object.\n        _validator: The current command validator.\n        _promptlen: The length of the current prompt.\n    \"\"\"\n\n    def __init__(self, *, parent=None):\n        super().__init__(parent)\n        self.history = cmdhistory.History(parent=self)\n        self._validator = _CommandValidator(self)\n        self.setValidator(self._validator)\n        self.textEdited.connect(self.on_text_edited)\n        self.cursorPositionChanged.connect(self.__on_cursor_position_changed)\n        self._promptlen = 0\n\n    def __repr__(self):\n        return utils.get_repr(self, text=self.text())\n\n    @pyqtSlot(str)\n    def on_text_edited(self, _text):\n        \"\"\"Slot for textEdited. Stop history browsing.\"\"\"\n        self.history.stop()\n\n    @pyqtSlot(int, int)\n    def __on_cursor_position_changed(self, _old, new):\n        \"\"\"Prevent the cursor moving to the prompt.\n\n        We use __ here to avoid accidentally overriding it in subclasses.\n        \"\"\"\n        if new < self._promptlen:\n            self.cursorForward(self.hasSelectedText(), self._promptlen - new)\n\n    def set_prompt(self, text):\n        \"\"\"Set the current prompt to text.\n\n        This updates the validator, and makes sure the user can't move the\n        cursor behind the prompt.\n        \"\"\"\n        self._validator.prompt = text\n        self._promptlen = len(text)\n\n\nclass _CommandValidator(QValidator):\n\n    \"\"\"Validator to prevent the : from getting deleted.\n\n    Attributes:\n        prompt: The current prompt.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self.prompt = None\n\n    def validate(self, string, pos):\n        \"\"\"Override QValidator::validate.\n\n        Args:\n            string: The string to validate.\n            pos: The current cursor position.\n\n        Return:\n            A tuple (status, string, pos) as a QValidator should.\n        \"\"\"\n        if self.prompt is None or string.startswith(self.prompt):\n            return (QValidator.Acceptable, string, pos)\n        else:\n            return (QValidator.Invalid, string, pos)\n\n\nclass DetailFold(QWidget):\n\n    \"\"\"A \"fold\" widget with an arrow to show/hide details.\n\n    Attributes:\n        _folded: Whether the widget is currently folded or not.\n        _hbox: The HBoxLayout the arrow/label are in.\n        _arrow: The FoldArrow widget.\n\n    Signals:\n        toggled: Emitted when the widget was folded/unfolded.\n                 arg 0: bool, if the contents are currently visible.\n    \"\"\"\n\n    toggled = pyqtSignal(bool)\n\n    def __init__(self, text, parent=None):\n        super().__init__(parent)\n        self._folded = True\n        self._hbox = QHBoxLayout(self)\n        self._hbox.setContentsMargins(0, 0, 0, 0)\n        self._arrow = _FoldArrow()\n        self._hbox.addWidget(self._arrow)\n        label = QLabel(text)\n        self._hbox.addWidget(label)\n        self._hbox.addStretch()\n\n    def toggle(self):\n        \"\"\"Toggle the fold of the widget.\"\"\"\n        self._folded = not self._folded\n        self._arrow.fold(self._folded)\n        self.toggled.emit(not self._folded)\n\n    def mousePressEvent(self, e):\n        \"\"\"Toggle the fold if the widget was pressed.\n\n        Args:\n            e: The QMouseEvent.\n        \"\"\"\n        if e.button() == Qt.LeftButton:\n            e.accept()\n            self.toggle()\n        else:\n            super().mousePressEvent(e)\n\n\nclass _FoldArrow(QWidget):\n\n    \"\"\"The arrow shown for the DetailFold widget.\n\n    Attributes:\n        _folded: Whether the widget is currently folded or not.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self._folded = True\n\n    def fold(self, folded):\n        \"\"\"Fold/unfold the widget.\n\n        Args:\n            folded: The new desired state.\n        \"\"\"\n        self._folded = folded\n        self.update()\n\n    def paintEvent(self, _event):\n        \"\"\"Paint the arrow.\n\n        Args:\n            _paint: The QPaintEvent (unused).\n        \"\"\"\n        opt = QStyleOption()\n        opt.initFrom(self)\n        painter = QPainter(self)\n        if self._folded:\n            elem = QStyle.PE_IndicatorArrowRight\n        else:\n            elem = QStyle.PE_IndicatorArrowDown\n        self.style().drawPrimitive(elem, opt, painter, self)\n\n    def minimumSizeHint(self):\n        \"\"\"Return a sensible size.\"\"\"\n        return QSize(8, 8)\n\n\nclass WrapperLayout(QLayout):\n\n    \"\"\"A Qt layout which simply wraps a single widget.\n\n    This is used so the widget is hidden behind a defined API and can't\n    easily be accidentally accessed.\n    \"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self._widget = None\n\n    def addItem(self, _widget):\n        raise utils.Unreachable\n\n    def sizeHint(self):\n        return self._widget.sizeHint()\n\n    def itemAt(self, _index):\n        return None\n\n    def takeAt(self, _index):\n        raise utils.Unreachable\n\n    def setGeometry(self, rect):\n        self._widget.setGeometry(rect)\n\n    def wrap(self, container, widget):\n        \"\"\"Wrap the given widget in the given container.\"\"\"\n        self._widget = widget\n        container.setFocusProxy(widget)\n        widget.setParent(container)\n\n    def unwrap(self):\n        self._widget.setParent(None)\n        self._widget.deleteLater()\n\n\nclass PseudoLayout(QLayout):\n\n    \"\"\"A layout which isn't actually a real layout.\n\n    This is used to replace QWebEngineView's internal layout, as a WORKAROUND\n    for https://bugreports.qt.io/browse/QTBUG-68224 and other related issues.\n\n    This is partly inspired by https://codereview.qt-project.org/#/c/230894/\n    which does something similar as part of Qt.\n    \"\"\"\n\n    def addItem(self, item):\n        assert self.parent() is not None\n        item.widget().setParent(self.parent())\n\n    def removeItem(self, item):\n        item.widget().setParent(None)\n\n    def count(self):\n        return 0\n\n    def itemAt(self, _pos):\n        return None\n\n    def widget(self):\n        return self.parent().render_widget()\n\n    def setGeometry(self, rect):\n        \"\"\"Resize the render widget when the view is resized.\"\"\"\n        widget = self.widget()\n        if widget is not None:\n            widget.setGeometry(rect)\n\n    def sizeHint(self):\n        \"\"\"Make sure the view has the sizeHint of the render widget.\"\"\"\n        widget = self.widget()\n        if widget is not None:\n            return widget.sizeHint()\n        return QSize()\n\n\nclass FullscreenNotification(QLabel):\n\n    \"\"\"A label telling the user this page is now fullscreen.\"\"\"\n\n    def __init__(self, parent=None):\n        super().__init__(parent)\n        self.setStyleSheet(\"\"\"\n            background-color: rgba(50, 50, 50, 80%);\n            color: white;\n            border-radius: 20px;\n            padding: 30px;\n        \"\"\")\n\n        all_bindings = config.key_instance.get_reverse_bindings_for('normal')\n        bindings = all_bindings.get('fullscreen --leave')\n        if bindings:\n            key = bindings[0]\n            self.setText(\"Press {} to exit fullscreen.\".format(key))\n        else:\n            self.setText(\"Page is now fullscreen.\")\n\n        self.resize(self.sizeHint())\n        if config.val.content.windowed_fullscreen:\n            geom = self.parentWidget().geometry()\n        else:\n            geom = QApplication.desktop().screenGeometry(self)\n        self.move((geom.width() - self.sizeHint().width()) / 2, 30)\n\n    def set_timeout(self, timeout):\n        \"\"\"Hide the widget after the given timeout.\"\"\"\n        QTimer.singleShot(timeout, self._on_timeout)\n\n    @pyqtSlot()\n    def _on_timeout(self):\n        \"\"\"Hide and delete the widget.\"\"\"\n        self.hide()\n        self.deleteLater()\n", "path": "qutebrowser/misc/miscwidgets.py"}]}