We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Console/Editor lose focus when auto-connected to help
## Description of your problem
1. Open spyder
2. Enable automatic connection to help in settings
3. Type in editor or console until the help connects, either by function(, or function? in the console

Expected behaviour is for the help for that function to show and I can continue typing my code.
What happens is that when the help activates, where I'm typing loses focus and I need to click back into the editor or console window to continue typing. The only way to write code in the editor without constantly being interrupted is to disable the help connection, which is annoying because thats one of my favourite parts of spyder.
## Versions and main components
- Spyder Version: 3.0.0b4
- Python Version:3.5.2
- Operating system: Mac OSX 10.11.5
## Dependencies

jedi >=0.8.1     :  0.9.0 (OK)
matplotlib >=1.0 :  1.5.1 (OK)
nbconvert >=4.0  :  4.2.0 (OK)
numpy >=1.7      :  1.11.1 (OK)
pandas >=0.13.1  :  0.18.1 (OK)
pep8 >=0.6       :  1.7.0 (OK)
psutil >=0.3     :  4.3.0 (OK)
pyflakes >=0.6.0 :  1.2.3 (OK)
pygments >=2.0   :  2.1.3 (OK)
qtconsole >=4.2.0:  4.2.1 (OK)
rope >=0.9.4     :  0.9.4-1 (OK)
sphinx >=0.6.6   :  1.4.1 (OK)
sympy >=0.7.3    :  1.0 (OK)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `spyder/widgets/browser.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright © Spyder Project Contributors
4 # Licensed under the terms of the MIT License
5 # (see spyder/__init__.py for details)
6 
7 """Simple web browser widget"""
8 
9 # Standard library imports
10 import sys
11 
12 # Third party imports
13 from qtpy.QtCore import QUrl, Signal, Slot
14 from qtpy.QtWidgets import (QFrame, QHBoxLayout, QLabel, QProgressBar, QMenu,
15                             QVBoxLayout, QWidget)
16 from qtpy.QtWebEngineWidgets import (QWebEnginePage, QWebEngineSettings,
17                                      QWebEngineView, WEBENGINE)
18 
19 # Local imports
20 from spyder.config.base import _, DEV
21 from spyder.py3compat import is_text_string, to_text_string
22 from spyder.utils.qthelpers import (action2button, add_actions,
23                                     create_action, create_toolbutton)
24 from spyder.utils import icon_manager as ima
25 from spyder.widgets.comboboxes import UrlComboBox
26 from spyder.widgets.findreplace import FindReplace
27 
28 
29 class WebPage(QWebEnginePage):
30     """
31     Web page subclass to manage hyperlinks for WebEngine
32 
33     Note: This can't be used for WebKit because the
34     acceptNavigationRequest method has a different
35     functionality for it.
36     """
37     linkClicked = Signal(QUrl)
38 
39     def acceptNavigationRequest(self, url, navigation_type, isMainFrame):
40         """
41         Overloaded method to handle links ourselves
42         """
43         if navigation_type == QWebEnginePage.NavigationTypeLinkClicked:
44             self.linkClicked.emit(url)
45             return False
46         return True
47 
48 
49 class WebView(QWebEngineView):
50     """Web view"""
51     def __init__(self, parent):
52         QWebEngineView.__init__(self, parent)
53         self.zoom_factor = 1.
54         self.zoom_out_action = create_action(self, _("Zoom out"),
55                                              icon=ima.icon('zoom_out'),
56                                              triggered=self.zoom_out)
57         self.zoom_in_action = create_action(self, _("Zoom in"),
58                                             icon=ima.icon('zoom_in'),
59                                             triggered=self.zoom_in)
60         if WEBENGINE:
61             web_page = WebPage(self)
62             self.setPage(web_page)
63 
64     def find_text(self, text, changed=True,
65                   forward=True, case=False, words=False,
66                   regexp=False):
67         """Find text"""
68         if not WEBENGINE:
69             findflag = QWebEnginePage.FindWrapsAroundDocument
70         else:
71             findflag = 0
72 
73         if not forward:
74             findflag = findflag | QWebEnginePage.FindBackward
75         if case:
76             findflag = findflag | QWebEnginePage.FindCaseSensitively
77 
78         return self.findText(text, QWebEnginePage.FindFlags(findflag))
79 
80     def get_selected_text(self):
81         """Return text selected by current text cursor"""
82         return self.selectedText()
83         
84     def set_font(self, font, fixed_font=None):
85         settings = self.page().settings()
86         for fontfamily in (settings.StandardFont, settings.SerifFont,
87                            settings.SansSerifFont, settings.CursiveFont,
88                            settings.FantasyFont):
89             settings.setFontFamily(fontfamily, font.family())
90         if fixed_font is not None:
91             settings.setFontFamily(settings.FixedFont, fixed_font.family())
92         size = font.pointSize()
93         settings.setFontSize(settings.DefaultFontSize, size)
94         settings.setFontSize(settings.DefaultFixedFontSize, size)
95         
96     def apply_zoom_factor(self):
97         """Apply zoom factor"""
98         if hasattr(self, 'setZoomFactor'):
99             # Assuming Qt >=v4.5
100             self.setZoomFactor(self.zoom_factor)
101         else:
102             # Qt v4.4
103             self.setTextSizeMultiplier(self.zoom_factor)
104         
105     def set_zoom_factor(self, zoom_factor):
106         """Set zoom factor"""
107         self.zoom_factor = zoom_factor
108         self.apply_zoom_factor()
109     
110     def get_zoom_factor(self):
111         """Return zoom factor"""
112         return self.zoom_factor
113 
114     @Slot()
115     def zoom_out(self):
116         """Zoom out"""
117         self.zoom_factor = max(.1, self.zoom_factor-.1)
118         self.apply_zoom_factor()
119 
120     @Slot()
121     def zoom_in(self):
122         """Zoom in"""
123         self.zoom_factor += .1
124         self.apply_zoom_factor()
125     
126     #------ QWebEngineView API -------------------------------------------------------
127     def createWindow(self, webwindowtype):
128         import webbrowser
129         webbrowser.open(to_text_string(self.url().toString()))
130         
131     def contextMenuEvent(self, event):
132         menu = QMenu(self)
133         actions = [self.pageAction(QWebEnginePage.Back),
134                    self.pageAction(QWebEnginePage.Forward), None,
135                    self.pageAction(QWebEnginePage.SelectAll),
136                    self.pageAction(QWebEnginePage.Copy), None,
137                    self.zoom_in_action, self.zoom_out_action]
138         if DEV and not WEBENGINE:
139             settings = self.page().settings()
140             settings.setAttribute(QWebEngineSettings.DeveloperExtrasEnabled, True)
141             actions += [None, self.pageAction(QWebEnginePage.InspectElement)]
142         add_actions(menu, actions)
143         menu.popup(event.globalPos())
144         event.accept()
145                 
146 
147 class WebBrowser(QWidget):
148     """
149     Web browser widget
150     """
151     def __init__(self, parent=None):
152         QWidget.__init__(self, parent)
153         
154         self.home_url = None
155         
156         self.webview = WebView(self)
157         self.webview.loadFinished.connect(self.load_finished)
158         self.webview.titleChanged.connect(self.setWindowTitle)
159         self.webview.urlChanged.connect(self.url_changed)
160                 
161         home_button = create_toolbutton(self, icon=ima.icon('home'),
162                                         tip=_("Home"),
163                                         triggered=self.go_home)
164         
165         zoom_out_button = action2button(self.webview.zoom_out_action)
166         zoom_in_button = action2button(self.webview.zoom_in_action)
167         
168         pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),
169                                                  parent=self.webview)
170         refresh_button = pageact2btn(QWebEnginePage.Reload)
171         stop_button = pageact2btn(QWebEnginePage.Stop)
172         previous_button = pageact2btn(QWebEnginePage.Back)
173         next_button = pageact2btn(QWebEnginePage.Forward)
174         
175         stop_button.setEnabled(False)
176         self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))
177         self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False))
178         
179         progressbar = QProgressBar(self)
180         progressbar.setTextVisible(False)
181         progressbar.hide()
182         self.webview.loadStarted.connect(progressbar.show)
183         self.webview.loadProgress.connect(progressbar.setValue)
184         self.webview.loadFinished.connect(lambda _state: progressbar.hide())
185 
186         label = QLabel(self.get_label())
187 
188         self.url_combo = UrlComboBox(self)
189         self.url_combo.valid.connect(self.url_combo_activated)
190         if not WEBENGINE:
191             self.webview.iconChanged.connect(self.icon_changed)
192 
193         self.find_widget = FindReplace(self)
194         self.find_widget.set_editor(self.webview)
195         self.find_widget.hide()
196 
197         find_button = create_toolbutton(self, icon=ima.icon('find'),
198                                         tip=_("Find text"),
199                                         toggled=self.toggle_find_widget)
200         self.find_widget.visibility_changed.connect(find_button.setChecked)
201 
202         hlayout = QHBoxLayout()
203         for widget in (previous_button, next_button, home_button, find_button,
204                        label, self.url_combo, zoom_out_button, zoom_in_button,
205                        refresh_button, progressbar, stop_button):
206             hlayout.addWidget(widget)
207         
208         layout = QVBoxLayout()
209         layout.addLayout(hlayout)
210         layout.addWidget(self.webview)
211         layout.addWidget(self.find_widget)
212         self.setLayout(layout)
213                 
214     def get_label(self):
215         """Return address label text"""
216         return _("Address:")
217             
218     def set_home_url(self, text):
219         """Set home URL"""
220         self.home_url = QUrl(text)
221         
222     def set_url(self, url):
223         """Set current URL"""
224         self.url_changed(url)
225         self.go_to(url)
226         
227     def go_to(self, url_or_text):
228         """Go to page *address*"""
229         if is_text_string(url_or_text):
230             url = QUrl(url_or_text)
231         else:
232             url = url_or_text
233         self.webview.load(url)
234 
235     @Slot()
236     def go_home(self):
237         """Go to home page"""
238         if self.home_url is not None:
239             self.set_url(self.home_url)
240         
241     def text_to_url(self, text):
242         """Convert text address into QUrl object"""
243         return QUrl(text)
244         
245     def url_combo_activated(self, valid):
246         """Load URL from combo box first item"""
247         text = to_text_string(self.url_combo.currentText())
248         self.go_to(self.text_to_url(text))
249         
250     def load_finished(self, ok):
251         if not ok:
252             self.webview.setHtml(_("Unable to load page"))
253             
254     def url_to_text(self, url):
255         """Convert QUrl object to displayed text in combo box"""
256         return url.toString()
257             
258     def url_changed(self, url):
259         """Displayed URL has changed -> updating URL combo box"""
260         self.url_combo.add_text(self.url_to_text(url))
261             
262     def icon_changed(self):
263         self.url_combo.setItemIcon(self.url_combo.currentIndex(),
264                                    self.webview.icon())
265         self.setWindowIcon(self.webview.icon())
266 
267     @Slot(bool)
268     def toggle_find_widget(self, state):
269         if state:
270             self.find_widget.show()
271         else:
272             self.find_widget.hide()
273 
274 
275 class FrameWebView(QFrame):
276     """
277     Framed QWebEngineView for UI consistency in Spyder.
278     """
279     linkClicked = Signal(QUrl)
280 
281     def __init__(self, parent):
282         QFrame.__init__(self, parent)
283 
284         self._webview = WebView(self)
285 
286         layout = QHBoxLayout()
287         layout.addWidget(self._webview)
288         layout.setContentsMargins(0, 0, 0, 0)
289         self.setLayout(layout)
290 
291         self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
292 
293         if WEBENGINE:
294             self._webview.page().linkClicked.connect(self.linkClicked)
295         else:
296             self._webview.linkClicked.connect(self.linkClicked)
297 
298     def __getattr__(self, name):
299         return getattr(self._webview, name)
300 
301     @property
302     def web_widget(self):
303         return self._webview
304 
305 
306 def test():
307     """Run web browser"""
308     from spyder.utils.qthelpers import qapplication
309     app = qapplication(test_time=8)
310     widget = WebBrowser()
311     widget.show()
312     widget.set_home_url('http://www.google.com/')
313     widget.go_home()
314     sys.exit(app.exec_())
315 
316 
317 if __name__ == '__main__':
318     test()
319
```
--- 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/spyder/widgets/browser.py b/spyder/widgets/browser.py
--- a/spyder/widgets/browser.py
+++ b/spyder/widgets/browser.py
@@ -142,7 +142,22 @@
         add_actions(menu, actions)
         menu.popup(event.globalPos())
         event.accept()
-                
+
+    def setHtml(self, html, baseUrl=QUrl()):
+        """
+        Reimplement Qt method to prevent WebEngine to steal focus
+        when setting html on the page
+
+        Solution taken from
+        https://bugreports.qt.io/browse/QTBUG-52999
+        """
+        if WEBENGINE:
+            self.setEnabled(False)
+            super(WebView, self).setHtml(html, baseUrl)
+            self.setEnabled(True)
+        else:
+            super(WebView, self).setHtml(html, baseUrl)
+
 
 class WebBrowser(QWidget):
     """

{"golden_diff": "diff --git a/spyder/widgets/browser.py b/spyder/widgets/browser.py\n--- a/spyder/widgets/browser.py\n+++ b/spyder/widgets/browser.py\n@@ -142,7 +142,22 @@\n         add_actions(menu, actions)\r\n         menu.popup(event.globalPos())\r\n         event.accept()\r\n-                \r\n+\r\n+    def setHtml(self, html, baseUrl=QUrl()):\r\n+        \"\"\"\r\n+        Reimplement Qt method to prevent WebEngine to steal focus\r\n+        when setting html on the page\r\n+\r\n+        Solution taken from\r\n+        https://bugreports.qt.io/browse/QTBUG-52999\r\n+        \"\"\"\r\n+        if WEBENGINE:\r\n+            self.setEnabled(False)\r\n+            super(WebView, self).setHtml(html, baseUrl)\r\n+            self.setEnabled(True)\r\n+        else:\r\n+            super(WebView, self).setHtml(html, baseUrl)\r\n+\r\n \r\n class WebBrowser(QWidget):\r\n     \"\"\"\n", "issue": "Console/Editor lose focus when auto-connected to help\n## Description of your problem\n1. Open spyder\n2. Enable automatic connection to help in settings\n3. Type in editor or console until the help connects, either by function(, or function? in the console\n\nExpected behaviour is for the help for that function to show and I can continue typing my code.\nWhat happens is that when the help activates, where I'm typing loses focus and I need to click back into the editor or console window to continue typing. The only way to write code in the editor without constantly being interrupted is to disable the help connection, which is annoying because thats one of my favourite parts of spyder.\n## Versions and main components\n- Spyder Version: 3.0.0b4\n- Python Version:3.5.2\n- Operating system: Mac OSX 10.11.5\n## Dependencies\n\njedi >=0.8.1     :  0.9.0 (OK)\nmatplotlib >=1.0 :  1.5.1 (OK)\nnbconvert >=4.0  :  4.2.0 (OK)\nnumpy >=1.7      :  1.11.1 (OK)\npandas >=0.13.1  :  0.18.1 (OK)\npep8 >=0.6       :  1.7.0 (OK)\npsutil >=0.3     :  4.3.0 (OK)\npyflakes >=0.6.0 :  1.2.3 (OK)\npygments >=2.0   :  2.1.3 (OK)\nqtconsole >=4.2.0:  4.2.1 (OK)\nrope >=0.9.4     :  0.9.4-1 (OK)\nsphinx >=0.6.6   :  1.4.1 (OK)\nsympy >=0.7.3    :  1.0 (OK)\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\r\n#\r\n# Copyright \u00a9 Spyder Project Contributors\r\n# Licensed under the terms of the MIT License\r\n# (see spyder/__init__.py for details)\r\n\r\n\"\"\"Simple web browser widget\"\"\"\r\n\r\n# Standard library imports\r\nimport sys\r\n\r\n# Third party imports\r\nfrom qtpy.QtCore import QUrl, Signal, Slot\r\nfrom qtpy.QtWidgets import (QFrame, QHBoxLayout, QLabel, QProgressBar, QMenu,\r\n                            QVBoxLayout, QWidget)\r\nfrom qtpy.QtWebEngineWidgets import (QWebEnginePage, QWebEngineSettings,\r\n                                     QWebEngineView, WEBENGINE)\r\n\r\n# Local imports\r\nfrom spyder.config.base import _, DEV\r\nfrom spyder.py3compat import is_text_string, to_text_string\r\nfrom spyder.utils.qthelpers import (action2button, add_actions,\r\n                                    create_action, create_toolbutton)\r\nfrom spyder.utils import icon_manager as ima\r\nfrom spyder.widgets.comboboxes import UrlComboBox\r\nfrom spyder.widgets.findreplace import FindReplace\r\n\r\n\r\nclass WebPage(QWebEnginePage):\r\n    \"\"\"\r\n    Web page subclass to manage hyperlinks for WebEngine\r\n\r\n    Note: This can't be used for WebKit because the\r\n    acceptNavigationRequest method has a different\r\n    functionality for it.\r\n    \"\"\"\r\n    linkClicked = Signal(QUrl)\r\n\r\n    def acceptNavigationRequest(self, url, navigation_type, isMainFrame):\r\n        \"\"\"\r\n        Overloaded method to handle links ourselves\r\n        \"\"\"\r\n        if navigation_type == QWebEnginePage.NavigationTypeLinkClicked:\r\n            self.linkClicked.emit(url)\r\n            return False\r\n        return True\r\n\r\n\r\nclass WebView(QWebEngineView):\r\n    \"\"\"Web view\"\"\"\r\n    def __init__(self, parent):\r\n        QWebEngineView.__init__(self, parent)\r\n        self.zoom_factor = 1.\r\n        self.zoom_out_action = create_action(self, _(\"Zoom out\"),\r\n                                             icon=ima.icon('zoom_out'),\r\n                                             triggered=self.zoom_out)\r\n        self.zoom_in_action = create_action(self, _(\"Zoom in\"),\r\n                                            icon=ima.icon('zoom_in'),\r\n                                            triggered=self.zoom_in)\r\n        if WEBENGINE:\r\n            web_page = WebPage(self)\r\n            self.setPage(web_page)\r\n\r\n    def find_text(self, text, changed=True,\r\n                  forward=True, case=False, words=False,\r\n                  regexp=False):\r\n        \"\"\"Find text\"\"\"\r\n        if not WEBENGINE:\r\n            findflag = QWebEnginePage.FindWrapsAroundDocument\r\n        else:\r\n            findflag = 0\r\n\r\n        if not forward:\r\n            findflag = findflag | QWebEnginePage.FindBackward\r\n        if case:\r\n            findflag = findflag | QWebEnginePage.FindCaseSensitively\r\n\r\n        return self.findText(text, QWebEnginePage.FindFlags(findflag))\r\n\r\n    def get_selected_text(self):\r\n        \"\"\"Return text selected by current text cursor\"\"\"\r\n        return self.selectedText()\r\n        \r\n    def set_font(self, font, fixed_font=None):\r\n        settings = self.page().settings()\r\n        for fontfamily in (settings.StandardFont, settings.SerifFont,\r\n                           settings.SansSerifFont, settings.CursiveFont,\r\n                           settings.FantasyFont):\r\n            settings.setFontFamily(fontfamily, font.family())\r\n        if fixed_font is not None:\r\n            settings.setFontFamily(settings.FixedFont, fixed_font.family())\r\n        size = font.pointSize()\r\n        settings.setFontSize(settings.DefaultFontSize, size)\r\n        settings.setFontSize(settings.DefaultFixedFontSize, size)\r\n        \r\n    def apply_zoom_factor(self):\r\n        \"\"\"Apply zoom factor\"\"\"\r\n        if hasattr(self, 'setZoomFactor'):\r\n            # Assuming Qt >=v4.5\r\n            self.setZoomFactor(self.zoom_factor)\r\n        else:\r\n            # Qt v4.4\r\n            self.setTextSizeMultiplier(self.zoom_factor)\r\n        \r\n    def set_zoom_factor(self, zoom_factor):\r\n        \"\"\"Set zoom factor\"\"\"\r\n        self.zoom_factor = zoom_factor\r\n        self.apply_zoom_factor()\r\n    \r\n    def get_zoom_factor(self):\r\n        \"\"\"Return zoom factor\"\"\"\r\n        return self.zoom_factor\r\n\r\n    @Slot()\r\n    def zoom_out(self):\r\n        \"\"\"Zoom out\"\"\"\r\n        self.zoom_factor = max(.1, self.zoom_factor-.1)\r\n        self.apply_zoom_factor()\r\n\r\n    @Slot()\r\n    def zoom_in(self):\r\n        \"\"\"Zoom in\"\"\"\r\n        self.zoom_factor += .1\r\n        self.apply_zoom_factor()\r\n    \r\n    #------ QWebEngineView API -------------------------------------------------------\r\n    def createWindow(self, webwindowtype):\r\n        import webbrowser\r\n        webbrowser.open(to_text_string(self.url().toString()))\r\n        \r\n    def contextMenuEvent(self, event):\r\n        menu = QMenu(self)\r\n        actions = [self.pageAction(QWebEnginePage.Back),\r\n                   self.pageAction(QWebEnginePage.Forward), None,\r\n                   self.pageAction(QWebEnginePage.SelectAll),\r\n                   self.pageAction(QWebEnginePage.Copy), None,\r\n                   self.zoom_in_action, self.zoom_out_action]\r\n        if DEV and not WEBENGINE:\r\n            settings = self.page().settings()\r\n            settings.setAttribute(QWebEngineSettings.DeveloperExtrasEnabled, True)\r\n            actions += [None, self.pageAction(QWebEnginePage.InspectElement)]\r\n        add_actions(menu, actions)\r\n        menu.popup(event.globalPos())\r\n        event.accept()\r\n                \r\n\r\nclass WebBrowser(QWidget):\r\n    \"\"\"\r\n    Web browser widget\r\n    \"\"\"\r\n    def __init__(self, parent=None):\r\n        QWidget.__init__(self, parent)\r\n        \r\n        self.home_url = None\r\n        \r\n        self.webview = WebView(self)\r\n        self.webview.loadFinished.connect(self.load_finished)\r\n        self.webview.titleChanged.connect(self.setWindowTitle)\r\n        self.webview.urlChanged.connect(self.url_changed)\r\n                \r\n        home_button = create_toolbutton(self, icon=ima.icon('home'),\r\n                                        tip=_(\"Home\"),\r\n                                        triggered=self.go_home)\r\n        \r\n        zoom_out_button = action2button(self.webview.zoom_out_action)\r\n        zoom_in_button = action2button(self.webview.zoom_in_action)\r\n        \r\n        pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),\r\n                                                 parent=self.webview)\r\n        refresh_button = pageact2btn(QWebEnginePage.Reload)\r\n        stop_button = pageact2btn(QWebEnginePage.Stop)\r\n        previous_button = pageact2btn(QWebEnginePage.Back)\r\n        next_button = pageact2btn(QWebEnginePage.Forward)\r\n        \r\n        stop_button.setEnabled(False)\r\n        self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))\r\n        self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False))\r\n        \r\n        progressbar = QProgressBar(self)\r\n        progressbar.setTextVisible(False)\r\n        progressbar.hide()\r\n        self.webview.loadStarted.connect(progressbar.show)\r\n        self.webview.loadProgress.connect(progressbar.setValue)\r\n        self.webview.loadFinished.connect(lambda _state: progressbar.hide())\r\n\r\n        label = QLabel(self.get_label())\r\n\r\n        self.url_combo = UrlComboBox(self)\r\n        self.url_combo.valid.connect(self.url_combo_activated)\r\n        if not WEBENGINE:\r\n            self.webview.iconChanged.connect(self.icon_changed)\r\n\r\n        self.find_widget = FindReplace(self)\r\n        self.find_widget.set_editor(self.webview)\r\n        self.find_widget.hide()\r\n\r\n        find_button = create_toolbutton(self, icon=ima.icon('find'),\r\n                                        tip=_(\"Find text\"),\r\n                                        toggled=self.toggle_find_widget)\r\n        self.find_widget.visibility_changed.connect(find_button.setChecked)\r\n\r\n        hlayout = QHBoxLayout()\r\n        for widget in (previous_button, next_button, home_button, find_button,\r\n                       label, self.url_combo, zoom_out_button, zoom_in_button,\r\n                       refresh_button, progressbar, stop_button):\r\n            hlayout.addWidget(widget)\r\n        \r\n        layout = QVBoxLayout()\r\n        layout.addLayout(hlayout)\r\n        layout.addWidget(self.webview)\r\n        layout.addWidget(self.find_widget)\r\n        self.setLayout(layout)\r\n                \r\n    def get_label(self):\r\n        \"\"\"Return address label text\"\"\"\r\n        return _(\"Address:\")\r\n            \r\n    def set_home_url(self, text):\r\n        \"\"\"Set home URL\"\"\"\r\n        self.home_url = QUrl(text)\r\n        \r\n    def set_url(self, url):\r\n        \"\"\"Set current URL\"\"\"\r\n        self.url_changed(url)\r\n        self.go_to(url)\r\n        \r\n    def go_to(self, url_or_text):\r\n        \"\"\"Go to page *address*\"\"\"\r\n        if is_text_string(url_or_text):\r\n            url = QUrl(url_or_text)\r\n        else:\r\n            url = url_or_text\r\n        self.webview.load(url)\r\n\r\n    @Slot()\r\n    def go_home(self):\r\n        \"\"\"Go to home page\"\"\"\r\n        if self.home_url is not None:\r\n            self.set_url(self.home_url)\r\n        \r\n    def text_to_url(self, text):\r\n        \"\"\"Convert text address into QUrl object\"\"\"\r\n        return QUrl(text)\r\n        \r\n    def url_combo_activated(self, valid):\r\n        \"\"\"Load URL from combo box first item\"\"\"\r\n        text = to_text_string(self.url_combo.currentText())\r\n        self.go_to(self.text_to_url(text))\r\n        \r\n    def load_finished(self, ok):\r\n        if not ok:\r\n            self.webview.setHtml(_(\"Unable to load page\"))\r\n            \r\n    def url_to_text(self, url):\r\n        \"\"\"Convert QUrl object to displayed text in combo box\"\"\"\r\n        return url.toString()\r\n            \r\n    def url_changed(self, url):\r\n        \"\"\"Displayed URL has changed -> updating URL combo box\"\"\"\r\n        self.url_combo.add_text(self.url_to_text(url))\r\n            \r\n    def icon_changed(self):\r\n        self.url_combo.setItemIcon(self.url_combo.currentIndex(),\r\n                                   self.webview.icon())\r\n        self.setWindowIcon(self.webview.icon())\r\n\r\n    @Slot(bool)\r\n    def toggle_find_widget(self, state):\r\n        if state:\r\n            self.find_widget.show()\r\n        else:\r\n            self.find_widget.hide()\r\n\r\n\r\nclass FrameWebView(QFrame):\r\n    \"\"\"\r\n    Framed QWebEngineView for UI consistency in Spyder.\r\n    \"\"\"\r\n    linkClicked = Signal(QUrl)\r\n\r\n    def __init__(self, parent):\r\n        QFrame.__init__(self, parent)\r\n\r\n        self._webview = WebView(self)\r\n\r\n        layout = QHBoxLayout()\r\n        layout.addWidget(self._webview)\r\n        layout.setContentsMargins(0, 0, 0, 0)\r\n        self.setLayout(layout)\r\n\r\n        self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)\r\n\r\n        if WEBENGINE:\r\n            self._webview.page().linkClicked.connect(self.linkClicked)\r\n        else:\r\n            self._webview.linkClicked.connect(self.linkClicked)\r\n\r\n    def __getattr__(self, name):\r\n        return getattr(self._webview, name)\r\n\r\n    @property\r\n    def web_widget(self):\r\n        return self._webview\r\n\r\n\r\ndef test():\r\n    \"\"\"Run web browser\"\"\"\r\n    from spyder.utils.qthelpers import qapplication\r\n    app = qapplication(test_time=8)\r\n    widget = WebBrowser()\r\n    widget.show()\r\n    widget.set_home_url('http://www.google.com/')\r\n    widget.go_home()\r\n    sys.exit(app.exec_())\r\n\r\n\r\nif __name__ == '__main__':\r\n    test()\r\n", "path": "spyder/widgets/browser.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\r\n#\r\n# Copyright \u00a9 Spyder Project Contributors\r\n# Licensed under the terms of the MIT License\r\n# (see spyder/__init__.py for details)\r\n\r\n\"\"\"Simple web browser widget\"\"\"\r\n\r\n# Standard library imports\r\nimport sys\r\n\r\n# Third party imports\r\nfrom qtpy.QtCore import QUrl, Signal, Slot\r\nfrom qtpy.QtWidgets import (QFrame, QHBoxLayout, QLabel, QProgressBar, QMenu,\r\n                            QVBoxLayout, QWidget)\r\nfrom qtpy.QtWebEngineWidgets import (QWebEnginePage, QWebEngineSettings,\r\n                                     QWebEngineView, WEBENGINE)\r\n\r\n# Local imports\r\nfrom spyder.config.base import _, DEV\r\nfrom spyder.py3compat import is_text_string, to_text_string\r\nfrom spyder.utils.qthelpers import (action2button, add_actions,\r\n                                    create_action, create_toolbutton)\r\nfrom spyder.utils import icon_manager as ima\r\nfrom spyder.widgets.comboboxes import UrlComboBox\r\nfrom spyder.widgets.findreplace import FindReplace\r\n\r\n\r\nclass WebPage(QWebEnginePage):\r\n    \"\"\"\r\n    Web page subclass to manage hyperlinks for WebEngine\r\n\r\n    Note: This can't be used for WebKit because the\r\n    acceptNavigationRequest method has a different\r\n    functionality for it.\r\n    \"\"\"\r\n    linkClicked = Signal(QUrl)\r\n\r\n    def acceptNavigationRequest(self, url, navigation_type, isMainFrame):\r\n        \"\"\"\r\n        Overloaded method to handle links ourselves\r\n        \"\"\"\r\n        if navigation_type == QWebEnginePage.NavigationTypeLinkClicked:\r\n            self.linkClicked.emit(url)\r\n            return False\r\n        return True\r\n\r\n\r\nclass WebView(QWebEngineView):\r\n    \"\"\"Web view\"\"\"\r\n    def __init__(self, parent):\r\n        QWebEngineView.__init__(self, parent)\r\n        self.zoom_factor = 1.\r\n        self.zoom_out_action = create_action(self, _(\"Zoom out\"),\r\n                                             icon=ima.icon('zoom_out'),\r\n                                             triggered=self.zoom_out)\r\n        self.zoom_in_action = create_action(self, _(\"Zoom in\"),\r\n                                            icon=ima.icon('zoom_in'),\r\n                                            triggered=self.zoom_in)\r\n        if WEBENGINE:\r\n            web_page = WebPage(self)\r\n            self.setPage(web_page)\r\n\r\n    def find_text(self, text, changed=True,\r\n                  forward=True, case=False, words=False,\r\n                  regexp=False):\r\n        \"\"\"Find text\"\"\"\r\n        if not WEBENGINE:\r\n            findflag = QWebEnginePage.FindWrapsAroundDocument\r\n        else:\r\n            findflag = 0\r\n\r\n        if not forward:\r\n            findflag = findflag | QWebEnginePage.FindBackward\r\n        if case:\r\n            findflag = findflag | QWebEnginePage.FindCaseSensitively\r\n\r\n        return self.findText(text, QWebEnginePage.FindFlags(findflag))\r\n\r\n    def get_selected_text(self):\r\n        \"\"\"Return text selected by current text cursor\"\"\"\r\n        return self.selectedText()\r\n        \r\n    def set_font(self, font, fixed_font=None):\r\n        settings = self.page().settings()\r\n        for fontfamily in (settings.StandardFont, settings.SerifFont,\r\n                           settings.SansSerifFont, settings.CursiveFont,\r\n                           settings.FantasyFont):\r\n            settings.setFontFamily(fontfamily, font.family())\r\n        if fixed_font is not None:\r\n            settings.setFontFamily(settings.FixedFont, fixed_font.family())\r\n        size = font.pointSize()\r\n        settings.setFontSize(settings.DefaultFontSize, size)\r\n        settings.setFontSize(settings.DefaultFixedFontSize, size)\r\n        \r\n    def apply_zoom_factor(self):\r\n        \"\"\"Apply zoom factor\"\"\"\r\n        if hasattr(self, 'setZoomFactor'):\r\n            # Assuming Qt >=v4.5\r\n            self.setZoomFactor(self.zoom_factor)\r\n        else:\r\n            # Qt v4.4\r\n            self.setTextSizeMultiplier(self.zoom_factor)\r\n        \r\n    def set_zoom_factor(self, zoom_factor):\r\n        \"\"\"Set zoom factor\"\"\"\r\n        self.zoom_factor = zoom_factor\r\n        self.apply_zoom_factor()\r\n    \r\n    def get_zoom_factor(self):\r\n        \"\"\"Return zoom factor\"\"\"\r\n        return self.zoom_factor\r\n\r\n    @Slot()\r\n    def zoom_out(self):\r\n        \"\"\"Zoom out\"\"\"\r\n        self.zoom_factor = max(.1, self.zoom_factor-.1)\r\n        self.apply_zoom_factor()\r\n\r\n    @Slot()\r\n    def zoom_in(self):\r\n        \"\"\"Zoom in\"\"\"\r\n        self.zoom_factor += .1\r\n        self.apply_zoom_factor()\r\n    \r\n    #------ QWebEngineView API -------------------------------------------------------\r\n    def createWindow(self, webwindowtype):\r\n        import webbrowser\r\n        webbrowser.open(to_text_string(self.url().toString()))\r\n        \r\n    def contextMenuEvent(self, event):\r\n        menu = QMenu(self)\r\n        actions = [self.pageAction(QWebEnginePage.Back),\r\n                   self.pageAction(QWebEnginePage.Forward), None,\r\n                   self.pageAction(QWebEnginePage.SelectAll),\r\n                   self.pageAction(QWebEnginePage.Copy), None,\r\n                   self.zoom_in_action, self.zoom_out_action]\r\n        if DEV and not WEBENGINE:\r\n            settings = self.page().settings()\r\n            settings.setAttribute(QWebEngineSettings.DeveloperExtrasEnabled, True)\r\n            actions += [None, self.pageAction(QWebEnginePage.InspectElement)]\r\n        add_actions(menu, actions)\r\n        menu.popup(event.globalPos())\r\n        event.accept()\r\n\r\n    def setHtml(self, html, baseUrl=QUrl()):\r\n        \"\"\"\r\n        Reimplement Qt method to prevent WebEngine to steal focus\r\n        when setting html on the page\r\n\r\n        Solution taken from\r\n        https://bugreports.qt.io/browse/QTBUG-52999\r\n        \"\"\"\r\n        if WEBENGINE:\r\n            self.setEnabled(False)\r\n            super(WebView, self).setHtml(html, baseUrl)\r\n            self.setEnabled(True)\r\n        else:\r\n            super(WebView, self).setHtml(html, baseUrl)\r\n\r\n\r\nclass WebBrowser(QWidget):\r\n    \"\"\"\r\n    Web browser widget\r\n    \"\"\"\r\n    def __init__(self, parent=None):\r\n        QWidget.__init__(self, parent)\r\n        \r\n        self.home_url = None\r\n        \r\n        self.webview = WebView(self)\r\n        self.webview.loadFinished.connect(self.load_finished)\r\n        self.webview.titleChanged.connect(self.setWindowTitle)\r\n        self.webview.urlChanged.connect(self.url_changed)\r\n                \r\n        home_button = create_toolbutton(self, icon=ima.icon('home'),\r\n                                        tip=_(\"Home\"),\r\n                                        triggered=self.go_home)\r\n        \r\n        zoom_out_button = action2button(self.webview.zoom_out_action)\r\n        zoom_in_button = action2button(self.webview.zoom_in_action)\r\n        \r\n        pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),\r\n                                                 parent=self.webview)\r\n        refresh_button = pageact2btn(QWebEnginePage.Reload)\r\n        stop_button = pageact2btn(QWebEnginePage.Stop)\r\n        previous_button = pageact2btn(QWebEnginePage.Back)\r\n        next_button = pageact2btn(QWebEnginePage.Forward)\r\n        \r\n        stop_button.setEnabled(False)\r\n        self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))\r\n        self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False))\r\n        \r\n        progressbar = QProgressBar(self)\r\n        progressbar.setTextVisible(False)\r\n        progressbar.hide()\r\n        self.webview.loadStarted.connect(progressbar.show)\r\n        self.webview.loadProgress.connect(progressbar.setValue)\r\n        self.webview.loadFinished.connect(lambda _state: progressbar.hide())\r\n\r\n        label = QLabel(self.get_label())\r\n\r\n        self.url_combo = UrlComboBox(self)\r\n        self.url_combo.valid.connect(self.url_combo_activated)\r\n        if not WEBENGINE:\r\n            self.webview.iconChanged.connect(self.icon_changed)\r\n\r\n        self.find_widget = FindReplace(self)\r\n        self.find_widget.set_editor(self.webview)\r\n        self.find_widget.hide()\r\n\r\n        find_button = create_toolbutton(self, icon=ima.icon('find'),\r\n                                        tip=_(\"Find text\"),\r\n                                        toggled=self.toggle_find_widget)\r\n        self.find_widget.visibility_changed.connect(find_button.setChecked)\r\n\r\n        hlayout = QHBoxLayout()\r\n        for widget in (previous_button, next_button, home_button, find_button,\r\n                       label, self.url_combo, zoom_out_button, zoom_in_button,\r\n                       refresh_button, progressbar, stop_button):\r\n            hlayout.addWidget(widget)\r\n        \r\n        layout = QVBoxLayout()\r\n        layout.addLayout(hlayout)\r\n        layout.addWidget(self.webview)\r\n        layout.addWidget(self.find_widget)\r\n        self.setLayout(layout)\r\n                \r\n    def get_label(self):\r\n        \"\"\"Return address label text\"\"\"\r\n        return _(\"Address:\")\r\n            \r\n    def set_home_url(self, text):\r\n        \"\"\"Set home URL\"\"\"\r\n        self.home_url = QUrl(text)\r\n        \r\n    def set_url(self, url):\r\n        \"\"\"Set current URL\"\"\"\r\n        self.url_changed(url)\r\n        self.go_to(url)\r\n        \r\n    def go_to(self, url_or_text):\r\n        \"\"\"Go to page *address*\"\"\"\r\n        if is_text_string(url_or_text):\r\n            url = QUrl(url_or_text)\r\n        else:\r\n            url = url_or_text\r\n        self.webview.load(url)\r\n\r\n    @Slot()\r\n    def go_home(self):\r\n        \"\"\"Go to home page\"\"\"\r\n        if self.home_url is not None:\r\n            self.set_url(self.home_url)\r\n        \r\n    def text_to_url(self, text):\r\n        \"\"\"Convert text address into QUrl object\"\"\"\r\n        return QUrl(text)\r\n        \r\n    def url_combo_activated(self, valid):\r\n        \"\"\"Load URL from combo box first item\"\"\"\r\n        text = to_text_string(self.url_combo.currentText())\r\n        self.go_to(self.text_to_url(text))\r\n        \r\n    def load_finished(self, ok):\r\n        if not ok:\r\n            self.webview.setHtml(_(\"Unable to load page\"))\r\n            \r\n    def url_to_text(self, url):\r\n        \"\"\"Convert QUrl object to displayed text in combo box\"\"\"\r\n        return url.toString()\r\n            \r\n    def url_changed(self, url):\r\n        \"\"\"Displayed URL has changed -> updating URL combo box\"\"\"\r\n        self.url_combo.add_text(self.url_to_text(url))\r\n            \r\n    def icon_changed(self):\r\n        self.url_combo.setItemIcon(self.url_combo.currentIndex(),\r\n                                   self.webview.icon())\r\n        self.setWindowIcon(self.webview.icon())\r\n\r\n    @Slot(bool)\r\n    def toggle_find_widget(self, state):\r\n        if state:\r\n            self.find_widget.show()\r\n        else:\r\n            self.find_widget.hide()\r\n\r\n\r\nclass FrameWebView(QFrame):\r\n    \"\"\"\r\n    Framed QWebEngineView for UI consistency in Spyder.\r\n    \"\"\"\r\n    linkClicked = Signal(QUrl)\r\n\r\n    def __init__(self, parent):\r\n        QFrame.__init__(self, parent)\r\n\r\n        self._webview = WebView(self)\r\n\r\n        layout = QHBoxLayout()\r\n        layout.addWidget(self._webview)\r\n        layout.setContentsMargins(0, 0, 0, 0)\r\n        self.setLayout(layout)\r\n\r\n        self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)\r\n\r\n        if WEBENGINE:\r\n            self._webview.page().linkClicked.connect(self.linkClicked)\r\n        else:\r\n            self._webview.linkClicked.connect(self.linkClicked)\r\n\r\n    def __getattr__(self, name):\r\n        return getattr(self._webview, name)\r\n\r\n    @property\r\n    def web_widget(self):\r\n        return self._webview\r\n\r\n\r\ndef test():\r\n    \"\"\"Run web browser\"\"\"\r\n    from spyder.utils.qthelpers import qapplication\r\n    app = qapplication(test_time=8)\r\n    widget = WebBrowser()\r\n    widget.show()\r\n    widget.set_home_url('http://www.google.com/')\r\n    widget.go_home()\r\n    sys.exit(app.exec_())\r\n\r\n\r\nif __name__ == '__main__':\r\n    test()\r\n", "path": "spyder/widgets/browser.py"}]}