We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Title field of error dialog is too small in macOS
This can be clearly seen in the following image:

![imagen](https://user-images.githubusercontent.com/365293/49333052-faae9100-f585-11e8-96a7-3033fbd160c8.png)

----

@juanis2112, this field is defined here:

https://github.com/spyder-ide/spyder/blob/master/spyder/widgets/reporterror.py#L158

I don't know exactly how to do this, but QLineEdit has several methods to define its size (e.g. `setMinimumWidth` or `setMaximumWidth`). You can find the full list here:

http://doc.qt.io/qt-5/qlineedit-members.html

I'm sure one of them will allow us to set the QLineEdit width to expand to the size of the report error dialog.

--- 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/reporterror.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # -----------------------------------------------------------------------------
3 # Copyright © Spyder Project Contributors
4 #
5 # Licensed under the terms of the MIT License
6 # (see spyder/__init__.py for details)
7 # -----------------------------------------------------------------------------
8 
9 """Report Error Dialog"""
10 
11 # Standard library imports
12 import sys
13 
14 # Third party imports
15 from qtpy.QtCore import Qt, Signal
16 from qtpy.QtWidgets import (QApplication, QCheckBox, QDialog, QFormLayout,
17                             QHBoxLayout, QLabel, QLineEdit, QMessageBox,
18                             QPlainTextEdit, QPushButton, QVBoxLayout)
19 
20 # Local imports
21 from spyder import __project_url__, __trouble_url__
22 from spyder.config.base import _
23 from spyder.config.gui import get_font
24 from spyder.config.gui import CONF
25 from spyder.utils import icon_manager as ima
26 from spyder.utils.qthelpers import restore_keyevent
27 from spyder.widgets.github.backend import GithubBackend
28 from spyder.plugins.editor.widgets.codeeditor import CodeEditor
29 from spyder.widgets.mixins import BaseEditMixin, TracebackLinksMixin
30 from spyder.plugins.editor.widgets.base import ConsoleBaseWidget
31 
32 
33 # Minimum number of characters to introduce in the title and
34 # description fields before being able to send the report to
35 # Github.
36 TITLE_MIN_CHARS = 15
37 DESC_MIN_CHARS = 50
38 
39 
40 class DescriptionWidget(CodeEditor):
41     """Widget to enter error description."""
42 
43     def __init__(self, parent=None):
44         CodeEditor.__init__(self, parent)
45 
46         # Editor options
47         self.setup_editor(
48             language='md',
49             color_scheme=CONF.get('appearance',
50                                   'selected'),
51             linenumbers=False,
52             scrollflagarea=False,
53             wrap=True,
54             edge_line=False,
55             highlight_current_line=False,
56             highlight_current_cell=False,
57             occurrence_highlighting=False,
58             auto_unindent=False)
59 
60         # Set font
61         self.set_font(get_font())
62 
63         # Header
64         self.header = (
65             "### What steps will reproduce the problem?\n\n"
66             "<!--- You can use Markdown here --->\n\n")
67         self.set_text(self.header)
68         self.move_cursor(len(self.header))
69         self.header_end_pos = self.get_position('eof')
70 
71     def remove_text(self):
72         """Remove text."""
73         self.truncate_selection(self.header_end_pos)
74         self.remove_selected_text()
75 
76     def cut(self):
77         """Cut text"""
78         self.truncate_selection(self.header_end_pos)
79         if self.has_selected_text():
80             CodeEditor.cut(self)
81 
82     def keyPressEvent(self, event):
83         """Reimplemented Qt Method to avoid removing the header."""
84         event, text, key, ctrl, shift = restore_keyevent(event)
85         cursor_position = self.get_position('cursor')
86 
87         if cursor_position < self.header_end_pos:
88             self.restrict_cursor_position(self.header_end_pos, 'eof')
89         elif key == Qt.Key_Delete:
90             if self.has_selected_text():
91                 self.remove_text()
92             else:
93                 self.stdkey_clear()
94         elif key == Qt.Key_Backspace:
95             if self.has_selected_text():
96                 self.remove_text()
97             elif self.header_end_pos == cursor_position:
98                 return
99             else:
100                 self.stdkey_backspace()
101         elif key == Qt.Key_X and ctrl:
102             self.cut()
103         else:
104             CodeEditor.keyPressEvent(self, event)
105 
106     def contextMenuEvent(self, event):
107         """Reimplemented Qt Method to not show the context menu."""
108         pass
109 
110 
111 class ShowErrorWidget(TracebackLinksMixin, ConsoleBaseWidget, BaseEditMixin):
112     """Widget to show errors as they appear in the Internal console."""
113     QT_CLASS = QPlainTextEdit
114     go_to_error = Signal(str)
115 
116     def __init__(self, parent=None):
117         ConsoleBaseWidget.__init__(self, parent)
118         BaseEditMixin.__init__(self)
119         TracebackLinksMixin.__init__(self)
120         self.setReadOnly(True)
121 
122 
123 class SpyderErrorDialog(QDialog):
124     """Custom error dialog for error reporting."""
125 
126     def __init__(self, parent=None, is_report=False):
127         QDialog.__init__(self, parent)
128         self.is_report = is_report
129 
130         self.setWindowTitle(_("Issue reporter"))
131         self.setModal(True)
132 
133         # To save the traceback sent to the internal console
134         self.error_traceback = ""
135 
136         # Dialog main label
137         if self.is_report:
138             title = _("Please fill the following information")
139         else:
140             title = _("Spyder has encountered an internal problem!")
141         main_label = QLabel(
142             _("<h3>{title}</h3>"
143               "Before reporting this problem, <i>please</i> consult our "
144               "comprehensive "
145               "<b><a href=\"{trouble_url}\">Troubleshooting Guide</a></b> "
146               "which should help solve most issues, and search for "
147               "<b><a href=\"{project_url}\">known bugs</a></b> "
148               "matching your error message or problem description for a "
149               "quicker solution."
150               ).format(title=title, trouble_url=__trouble_url__,
151                           project_url=__project_url__))
152         main_label.setOpenExternalLinks(True)
153         main_label.setWordWrap(True)
154         main_label.setAlignment(Qt.AlignJustify)
155         main_label.setStyleSheet('font-size: 12px;')
156 
157         # Issue title
158         self.title = QLineEdit()
159         self.title.textChanged.connect(self._contents_changed)
160         self.title_chars_label = QLabel(_("{} more characters "
161                                           "to go...").format(TITLE_MIN_CHARS))
162         form_layout = QFormLayout()
163         red_asterisk = '<font color="Red">*</font>'
164         title_label = QLabel(_("<b>Title</b>: {}").format(red_asterisk))
165         form_layout.setWidget(0, QFormLayout.LabelRole, title_label)
166         form_layout.setWidget(0, QFormLayout.FieldRole, self.title)
167 
168         # Description
169         steps_header = QLabel(
170             _("<b>Steps to reproduce:</b> {}").format(red_asterisk))
171         steps_text = QLabel(_("Please enter a detailed step-by-step "
172                               "description (in English) of what led up to "
173                               "the problem below. Issue reports without a "
174                               "clear way to reproduce them will be closed."))
175         steps_text.setWordWrap(True)
176         steps_text.setAlignment(Qt.AlignJustify)
177         steps_text.setStyleSheet('font-size: 12px;')
178 
179         # Field to input the description of the problem
180         self.input_description = DescriptionWidget(self)
181 
182         # Only allow to submit to Github if we have a long enough description
183         self.input_description.textChanged.connect(self._contents_changed)
184 
185         # Widget to show errors
186         self.details = ShowErrorWidget(self)
187         self.details.set_pythonshell_font(get_font())
188         self.details.hide()
189 
190         # Label to show missing chars
191         self.initial_chars = len(self.input_description.toPlainText())
192         self.desc_chars_label = QLabel(_("{} more characters "
193                                          "to go...").format(DESC_MIN_CHARS))
194 
195         # Checkbox to dismiss future errors
196         self.dismiss_box = QCheckBox(_("Hide all future errors during this "
197                                        "session"))
198         if self.is_report:
199             self.dismiss_box.hide()
200 
201         # Dialog buttons
202         gh_icon = ima.icon('github')
203         self.submit_btn = QPushButton(gh_icon, _('Submit to Github'))
204         self.submit_btn.setEnabled(False)
205         self.submit_btn.clicked.connect(self._submit_to_github)
206 
207         self.details_btn = QPushButton(_('Show details'))
208         self.details_btn.clicked.connect(self._show_details)
209         if self.is_report:
210             self.details_btn.hide()
211 
212         self.close_btn = QPushButton(_('Close'))
213         if self.is_report:
214             self.close_btn.clicked.connect(self.reject)
215 
216         # Buttons layout
217         buttons_layout = QHBoxLayout()
218         buttons_layout.addWidget(self.submit_btn)
219         buttons_layout.addWidget(self.details_btn)
220         buttons_layout.addWidget(self.close_btn)
221 
222         # Main layout
223         layout = QVBoxLayout()
224         layout.addWidget(main_label)
225         layout.addSpacing(20)
226         layout.addLayout(form_layout)
227         layout.addWidget(self.title_chars_label)
228         layout.addSpacing(12)
229         layout.addWidget(steps_header)
230         layout.addSpacing(-1)
231         layout.addWidget(steps_text)
232         layout.addSpacing(1)
233         layout.addWidget(self.input_description)
234         layout.addWidget(self.details)
235         layout.addWidget(self.desc_chars_label)
236         layout.addSpacing(15)
237         layout.addWidget(self.dismiss_box)
238         layout.addSpacing(15)
239         layout.addLayout(buttons_layout)
240         layout.setContentsMargins(25, 20, 25, 10)
241         self.setLayout(layout)
242 
243         self.resize(570, 600)
244         self.title.setFocus()
245 
246         # Set Tab key focus order
247         self.setTabOrder(self.title, self.input_description)
248 
249     def _submit_to_github(self):
250         """Action to take when pressing the submit button."""
251         # Get reference to the main window
252         if self.parent() is not None:
253             if getattr(self.parent(), 'main', False):
254                 # This covers the case when the dialog is attached
255                 # to the internal console
256                 main = self.parent().main
257             else:
258                 # Else the dialog is attached to the main window
259                 # directly
260                 main = self.parent()
261         else:
262             main = None
263 
264         # Getting description and traceback
265         title = self.title.text()
266         description = self.input_description.toPlainText()
267         traceback = self.error_traceback[:-1]  # Remove last EOL
268 
269         # Render issue
270         if main is not None:
271             issue_text = main.render_issue(description=description,
272                                            traceback=traceback)
273         else:
274             issue_text = description
275 
276         try:
277             if main is None:
278                 org = 'ccordoba12'
279             else:
280                 org = 'spyder-ide'
281             github_backend = GithubBackend(org, 'spyder', parent_widget=main)
282             github_report = github_backend.send_report(title, issue_text)
283             if github_report:
284                 self.close()
285         except Exception:
286             ret = QMessageBox.question(
287                       self, _('Error'),
288                       _("An error occurred while trying to send the issue to "
289                         "Github automatically. Would you like to open it "
290                         "manually?<br><br>"
291                         "If so, please make sure to paste your clipboard "
292                         "into the issue report box that will appear in a new "
293                         "browser tab before clicking <i>Submit</i> on that "
294                         "page."))
295             if ret in [QMessageBox.Yes, QMessageBox.Ok]:
296                 QApplication.clipboard().setText(issue_text)
297                 issue_body = (
298                     " \n<!---   *** BEFORE SUBMITTING: PASTE CLIPBOARD HERE "
299                     "TO COMPLETE YOUR REPORT ***   ---!>\n")
300                 if main is not None:
301                     main.report_issue(body=issue_body, title=title,
302                                       open_webpage=True)
303                 else:
304                     pass
305 
306     def append_traceback(self, text):
307         """Append text to the traceback, to be displayed in details."""
308         self.error_traceback += text
309 
310     def _show_details(self):
311         """Show traceback on its own dialog"""
312         if self.details.isVisible():
313             self.details.hide()
314             self.details_btn.setText(_('Show details'))
315         else:
316             self.resize(570, 700)
317             self.details.document().setPlainText('')
318             self.details.append_text_to_shell(self.error_traceback,
319                                               error=True,
320                                               prompt=False)
321             self.details.show()
322             self.details_btn.setText(_('Hide details'))
323 
324     def _contents_changed(self):
325         """Activate submit_btn."""
326         desc_chars = (len(self.input_description.toPlainText()) -
327                       self.initial_chars)
328         if desc_chars < DESC_MIN_CHARS:
329             self.desc_chars_label.setText(
330                 u"{} {}".format(DESC_MIN_CHARS - desc_chars,
331                                 _("more characters to go...")))
332         else:
333             self.desc_chars_label.setText(_("Description complete; thanks!"))
334 
335         title_chars = len(self.title.text())
336         if title_chars < TITLE_MIN_CHARS:
337             self.title_chars_label.setText(
338                 u"{} {}".format(TITLE_MIN_CHARS - title_chars,
339                                 _("more characters to go...")))
340         else:
341             self.title_chars_label.setText(_("Title complete; thanks!"))
342 
343         submission_enabled = (desc_chars >= DESC_MIN_CHARS and
344                               title_chars >= TITLE_MIN_CHARS)
345         self.submit_btn.setEnabled(submission_enabled)
346 
347 
348 def test():
349     from spyder.utils.qthelpers import qapplication
350     app = qapplication()
351     dlg = SpyderErrorDialog()
352     dlg.show()
353     sys.exit(dlg.exec_())
354 
355 
356 if __name__ == "__main__":
357     test()
358
```
--- 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/reporterror.py b/spyder/widgets/reporterror.py
--- a/spyder/widgets/reporterror.py
+++ b/spyder/widgets/reporterror.py
@@ -160,6 +160,7 @@
         self.title_chars_label = QLabel(_("{} more characters "
                                           "to go...").format(TITLE_MIN_CHARS))
         form_layout = QFormLayout()
+        form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
         red_asterisk = '<font color="Red">*</font>'
         title_label = QLabel(_("<b>Title</b>: {}").format(red_asterisk))
         form_layout.setWidget(0, QFormLayout.LabelRole, title_label)

{"golden_diff": "diff --git a/spyder/widgets/reporterror.py b/spyder/widgets/reporterror.py\n--- a/spyder/widgets/reporterror.py\n+++ b/spyder/widgets/reporterror.py\n@@ -160,6 +160,7 @@\n         self.title_chars_label = QLabel(_(\"{} more characters \"\n                                           \"to go...\").format(TITLE_MIN_CHARS))\n         form_layout = QFormLayout()\n+        form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)\n         red_asterisk = '<font color=\"Red\">*</font>'\n         title_label = QLabel(_(\"<b>Title</b>: {}\").format(red_asterisk))\n         form_layout.setWidget(0, QFormLayout.LabelRole, title_label)\n", "issue": "Title field of error dialog is too small in macOS\nThis can be clearly seen in the following image:\r\n\r\n![imagen](https://user-images.githubusercontent.com/365293/49333052-faae9100-f585-11e8-96a7-3033fbd160c8.png)\r\n\r\n----\r\n\r\n@juanis2112, this field is defined here:\r\n\r\nhttps://github.com/spyder-ide/spyder/blob/master/spyder/widgets/reporterror.py#L158\r\n\r\nI don't know exactly how to do this, but QLineEdit has several methods to define its size (e.g. `setMinimumWidth` or `setMaximumWidth`). You can find the full list here:\r\n\r\nhttp://doc.qt.io/qt-5/qlineedit-members.html\r\n\r\nI'm sure one of them will allow us to set the QLineEdit width to expand to the size of the report error dialog.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# -----------------------------------------------------------------------------\n# Copyright \u00a9 Spyder Project Contributors\n#\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n# -----------------------------------------------------------------------------\n\n\"\"\"Report Error Dialog\"\"\"\n\n# Standard library imports\nimport sys\n\n# Third party imports\nfrom qtpy.QtCore import Qt, Signal\nfrom qtpy.QtWidgets import (QApplication, QCheckBox, QDialog, QFormLayout,\n                            QHBoxLayout, QLabel, QLineEdit, QMessageBox,\n                            QPlainTextEdit, QPushButton, QVBoxLayout)\n\n# Local imports\nfrom spyder import __project_url__, __trouble_url__\nfrom spyder.config.base import _\nfrom spyder.config.gui import get_font\nfrom spyder.config.gui import CONF\nfrom spyder.utils import icon_manager as ima\nfrom spyder.utils.qthelpers import restore_keyevent\nfrom spyder.widgets.github.backend import GithubBackend\nfrom spyder.plugins.editor.widgets.codeeditor import CodeEditor\nfrom spyder.widgets.mixins import BaseEditMixin, TracebackLinksMixin\nfrom spyder.plugins.editor.widgets.base import ConsoleBaseWidget\n\n\n# Minimum number of characters to introduce in the title and\n# description fields before being able to send the report to\n# Github.\nTITLE_MIN_CHARS = 15\nDESC_MIN_CHARS = 50\n\n\nclass DescriptionWidget(CodeEditor):\n    \"\"\"Widget to enter error description.\"\"\"\n\n    def __init__(self, parent=None):\n        CodeEditor.__init__(self, parent)\n\n        # Editor options\n        self.setup_editor(\n            language='md',\n            color_scheme=CONF.get('appearance',\n                                  'selected'),\n            linenumbers=False,\n            scrollflagarea=False,\n            wrap=True,\n            edge_line=False,\n            highlight_current_line=False,\n            highlight_current_cell=False,\n            occurrence_highlighting=False,\n            auto_unindent=False)\n\n        # Set font\n        self.set_font(get_font())\n\n        # Header\n        self.header = (\n            \"### What steps will reproduce the problem?\\n\\n\"\n            \"<!--- You can use Markdown here --->\\n\\n\")\n        self.set_text(self.header)\n        self.move_cursor(len(self.header))\n        self.header_end_pos = self.get_position('eof')\n\n    def remove_text(self):\n        \"\"\"Remove text.\"\"\"\n        self.truncate_selection(self.header_end_pos)\n        self.remove_selected_text()\n\n    def cut(self):\n        \"\"\"Cut text\"\"\"\n        self.truncate_selection(self.header_end_pos)\n        if self.has_selected_text():\n            CodeEditor.cut(self)\n\n    def keyPressEvent(self, event):\n        \"\"\"Reimplemented Qt Method to avoid removing the header.\"\"\"\n        event, text, key, ctrl, shift = restore_keyevent(event)\n        cursor_position = self.get_position('cursor')\n\n        if cursor_position < self.header_end_pos:\n            self.restrict_cursor_position(self.header_end_pos, 'eof')\n        elif key == Qt.Key_Delete:\n            if self.has_selected_text():\n                self.remove_text()\n            else:\n                self.stdkey_clear()\n        elif key == Qt.Key_Backspace:\n            if self.has_selected_text():\n                self.remove_text()\n            elif self.header_end_pos == cursor_position:\n                return\n            else:\n                self.stdkey_backspace()\n        elif key == Qt.Key_X and ctrl:\n            self.cut()\n        else:\n            CodeEditor.keyPressEvent(self, event)\n\n    def contextMenuEvent(self, event):\n        \"\"\"Reimplemented Qt Method to not show the context menu.\"\"\"\n        pass\n\n\nclass ShowErrorWidget(TracebackLinksMixin, ConsoleBaseWidget, BaseEditMixin):\n    \"\"\"Widget to show errors as they appear in the Internal console.\"\"\"\n    QT_CLASS = QPlainTextEdit\n    go_to_error = Signal(str)\n\n    def __init__(self, parent=None):\n        ConsoleBaseWidget.__init__(self, parent)\n        BaseEditMixin.__init__(self)\n        TracebackLinksMixin.__init__(self)\n        self.setReadOnly(True)\n\n\nclass SpyderErrorDialog(QDialog):\n    \"\"\"Custom error dialog for error reporting.\"\"\"\n\n    def __init__(self, parent=None, is_report=False):\n        QDialog.__init__(self, parent)\n        self.is_report = is_report\n\n        self.setWindowTitle(_(\"Issue reporter\"))\n        self.setModal(True)\n\n        # To save the traceback sent to the internal console\n        self.error_traceback = \"\"\n\n        # Dialog main label\n        if self.is_report:\n            title = _(\"Please fill the following information\")\n        else:\n            title = _(\"Spyder has encountered an internal problem!\")\n        main_label = QLabel(\n            _(\"<h3>{title}</h3>\"\n              \"Before reporting this problem, <i>please</i> consult our \"\n              \"comprehensive \"\n              \"<b><a href=\\\"{trouble_url}\\\">Troubleshooting Guide</a></b> \"\n              \"which should help solve most issues, and search for \"\n              \"<b><a href=\\\"{project_url}\\\">known bugs</a></b> \"\n              \"matching your error message or problem description for a \"\n              \"quicker solution.\"\n              ).format(title=title, trouble_url=__trouble_url__,\n                          project_url=__project_url__))\n        main_label.setOpenExternalLinks(True)\n        main_label.setWordWrap(True)\n        main_label.setAlignment(Qt.AlignJustify)\n        main_label.setStyleSheet('font-size: 12px;')\n\n        # Issue title\n        self.title = QLineEdit()\n        self.title.textChanged.connect(self._contents_changed)\n        self.title_chars_label = QLabel(_(\"{} more characters \"\n                                          \"to go...\").format(TITLE_MIN_CHARS))\n        form_layout = QFormLayout()\n        red_asterisk = '<font color=\"Red\">*</font>'\n        title_label = QLabel(_(\"<b>Title</b>: {}\").format(red_asterisk))\n        form_layout.setWidget(0, QFormLayout.LabelRole, title_label)\n        form_layout.setWidget(0, QFormLayout.FieldRole, self.title)\n\n        # Description\n        steps_header = QLabel(\n            _(\"<b>Steps to reproduce:</b> {}\").format(red_asterisk))\n        steps_text = QLabel(_(\"Please enter a detailed step-by-step \"\n                              \"description (in English) of what led up to \"\n                              \"the problem below. Issue reports without a \"\n                              \"clear way to reproduce them will be closed.\"))\n        steps_text.setWordWrap(True)\n        steps_text.setAlignment(Qt.AlignJustify)\n        steps_text.setStyleSheet('font-size: 12px;')\n\n        # Field to input the description of the problem\n        self.input_description = DescriptionWidget(self)\n\n        # Only allow to submit to Github if we have a long enough description\n        self.input_description.textChanged.connect(self._contents_changed)\n\n        # Widget to show errors\n        self.details = ShowErrorWidget(self)\n        self.details.set_pythonshell_font(get_font())\n        self.details.hide()\n\n        # Label to show missing chars\n        self.initial_chars = len(self.input_description.toPlainText())\n        self.desc_chars_label = QLabel(_(\"{} more characters \"\n                                         \"to go...\").format(DESC_MIN_CHARS))\n\n        # Checkbox to dismiss future errors\n        self.dismiss_box = QCheckBox(_(\"Hide all future errors during this \"\n                                       \"session\"))\n        if self.is_report:\n            self.dismiss_box.hide()\n\n        # Dialog buttons\n        gh_icon = ima.icon('github')\n        self.submit_btn = QPushButton(gh_icon, _('Submit to Github'))\n        self.submit_btn.setEnabled(False)\n        self.submit_btn.clicked.connect(self._submit_to_github)\n\n        self.details_btn = QPushButton(_('Show details'))\n        self.details_btn.clicked.connect(self._show_details)\n        if self.is_report:\n            self.details_btn.hide()\n\n        self.close_btn = QPushButton(_('Close'))\n        if self.is_report:\n            self.close_btn.clicked.connect(self.reject)\n\n        # Buttons layout\n        buttons_layout = QHBoxLayout()\n        buttons_layout.addWidget(self.submit_btn)\n        buttons_layout.addWidget(self.details_btn)\n        buttons_layout.addWidget(self.close_btn)\n\n        # Main layout\n        layout = QVBoxLayout()\n        layout.addWidget(main_label)\n        layout.addSpacing(20)\n        layout.addLayout(form_layout)\n        layout.addWidget(self.title_chars_label)\n        layout.addSpacing(12)\n        layout.addWidget(steps_header)\n        layout.addSpacing(-1)\n        layout.addWidget(steps_text)\n        layout.addSpacing(1)\n        layout.addWidget(self.input_description)\n        layout.addWidget(self.details)\n        layout.addWidget(self.desc_chars_label)\n        layout.addSpacing(15)\n        layout.addWidget(self.dismiss_box)\n        layout.addSpacing(15)\n        layout.addLayout(buttons_layout)\n        layout.setContentsMargins(25, 20, 25, 10)\n        self.setLayout(layout)\n\n        self.resize(570, 600)\n        self.title.setFocus()\n\n        # Set Tab key focus order\n        self.setTabOrder(self.title, self.input_description)\n\n    def _submit_to_github(self):\n        \"\"\"Action to take when pressing the submit button.\"\"\"\n        # Get reference to the main window\n        if self.parent() is not None:\n            if getattr(self.parent(), 'main', False):\n                # This covers the case when the dialog is attached\n                # to the internal console\n                main = self.parent().main\n            else:\n                # Else the dialog is attached to the main window\n                # directly\n                main = self.parent()\n        else:\n            main = None\n\n        # Getting description and traceback\n        title = self.title.text()\n        description = self.input_description.toPlainText()\n        traceback = self.error_traceback[:-1]  # Remove last EOL\n\n        # Render issue\n        if main is not None:\n            issue_text = main.render_issue(description=description,\n                                           traceback=traceback)\n        else:\n            issue_text = description\n\n        try:\n            if main is None:\n                org = 'ccordoba12'\n            else:\n                org = 'spyder-ide'\n            github_backend = GithubBackend(org, 'spyder', parent_widget=main)\n            github_report = github_backend.send_report(title, issue_text)\n            if github_report:\n                self.close()\n        except Exception:\n            ret = QMessageBox.question(\n                      self, _('Error'),\n                      _(\"An error occurred while trying to send the issue to \"\n                        \"Github automatically. Would you like to open it \"\n                        \"manually?<br><br>\"\n                        \"If so, please make sure to paste your clipboard \"\n                        \"into the issue report box that will appear in a new \"\n                        \"browser tab before clicking <i>Submit</i> on that \"\n                        \"page.\"))\n            if ret in [QMessageBox.Yes, QMessageBox.Ok]:\n                QApplication.clipboard().setText(issue_text)\n                issue_body = (\n                    \" \\n<!---   *** BEFORE SUBMITTING: PASTE CLIPBOARD HERE \"\n                    \"TO COMPLETE YOUR REPORT ***   ---!>\\n\")\n                if main is not None:\n                    main.report_issue(body=issue_body, title=title,\n                                      open_webpage=True)\n                else:\n                    pass\n\n    def append_traceback(self, text):\n        \"\"\"Append text to the traceback, to be displayed in details.\"\"\"\n        self.error_traceback += text\n\n    def _show_details(self):\n        \"\"\"Show traceback on its own dialog\"\"\"\n        if self.details.isVisible():\n            self.details.hide()\n            self.details_btn.setText(_('Show details'))\n        else:\n            self.resize(570, 700)\n            self.details.document().setPlainText('')\n            self.details.append_text_to_shell(self.error_traceback,\n                                              error=True,\n                                              prompt=False)\n            self.details.show()\n            self.details_btn.setText(_('Hide details'))\n\n    def _contents_changed(self):\n        \"\"\"Activate submit_btn.\"\"\"\n        desc_chars = (len(self.input_description.toPlainText()) -\n                      self.initial_chars)\n        if desc_chars < DESC_MIN_CHARS:\n            self.desc_chars_label.setText(\n                u\"{} {}\".format(DESC_MIN_CHARS - desc_chars,\n                                _(\"more characters to go...\")))\n        else:\n            self.desc_chars_label.setText(_(\"Description complete; thanks!\"))\n\n        title_chars = len(self.title.text())\n        if title_chars < TITLE_MIN_CHARS:\n            self.title_chars_label.setText(\n                u\"{} {}\".format(TITLE_MIN_CHARS - title_chars,\n                                _(\"more characters to go...\")))\n        else:\n            self.title_chars_label.setText(_(\"Title complete; thanks!\"))\n\n        submission_enabled = (desc_chars >= DESC_MIN_CHARS and\n                              title_chars >= TITLE_MIN_CHARS)\n        self.submit_btn.setEnabled(submission_enabled)\n\n\ndef test():\n    from spyder.utils.qthelpers import qapplication\n    app = qapplication()\n    dlg = SpyderErrorDialog()\n    dlg.show()\n    sys.exit(dlg.exec_())\n\n\nif __name__ == \"__main__\":\n    test()\n", "path": "spyder/widgets/reporterror.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# -----------------------------------------------------------------------------\n# Copyright \u00a9 Spyder Project Contributors\n#\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n# -----------------------------------------------------------------------------\n\n\"\"\"Report Error Dialog\"\"\"\n\n# Standard library imports\nimport sys\n\n# Third party imports\nfrom qtpy.QtCore import Qt, Signal\nfrom qtpy.QtWidgets import (QApplication, QCheckBox, QDialog, QFormLayout,\n                            QHBoxLayout, QLabel, QLineEdit, QMessageBox,\n                            QPlainTextEdit, QPushButton, QVBoxLayout)\n\n# Local imports\nfrom spyder import __project_url__, __trouble_url__\nfrom spyder.config.base import _\nfrom spyder.config.gui import get_font\nfrom spyder.config.gui import CONF\nfrom spyder.utils import icon_manager as ima\nfrom spyder.utils.qthelpers import restore_keyevent\nfrom spyder.widgets.github.backend import GithubBackend\nfrom spyder.plugins.editor.widgets.codeeditor import CodeEditor\nfrom spyder.widgets.mixins import BaseEditMixin, TracebackLinksMixin\nfrom spyder.plugins.editor.widgets.base import ConsoleBaseWidget\n\n\n# Minimum number of characters to introduce in the title and\n# description fields before being able to send the report to\n# Github.\nTITLE_MIN_CHARS = 15\nDESC_MIN_CHARS = 50\n\n\nclass DescriptionWidget(CodeEditor):\n    \"\"\"Widget to enter error description.\"\"\"\n\n    def __init__(self, parent=None):\n        CodeEditor.__init__(self, parent)\n\n        # Editor options\n        self.setup_editor(\n            language='md',\n            color_scheme=CONF.get('appearance',\n                                  'selected'),\n            linenumbers=False,\n            scrollflagarea=False,\n            wrap=True,\n            edge_line=False,\n            highlight_current_line=False,\n            highlight_current_cell=False,\n            occurrence_highlighting=False,\n            auto_unindent=False)\n\n        # Set font\n        self.set_font(get_font())\n\n        # Header\n        self.header = (\n            \"### What steps will reproduce the problem?\\n\\n\"\n            \"<!--- You can use Markdown here --->\\n\\n\")\n        self.set_text(self.header)\n        self.move_cursor(len(self.header))\n        self.header_end_pos = self.get_position('eof')\n\n    def remove_text(self):\n        \"\"\"Remove text.\"\"\"\n        self.truncate_selection(self.header_end_pos)\n        self.remove_selected_text()\n\n    def cut(self):\n        \"\"\"Cut text\"\"\"\n        self.truncate_selection(self.header_end_pos)\n        if self.has_selected_text():\n            CodeEditor.cut(self)\n\n    def keyPressEvent(self, event):\n        \"\"\"Reimplemented Qt Method to avoid removing the header.\"\"\"\n        event, text, key, ctrl, shift = restore_keyevent(event)\n        cursor_position = self.get_position('cursor')\n\n        if cursor_position < self.header_end_pos:\n            self.restrict_cursor_position(self.header_end_pos, 'eof')\n        elif key == Qt.Key_Delete:\n            if self.has_selected_text():\n                self.remove_text()\n            else:\n                self.stdkey_clear()\n        elif key == Qt.Key_Backspace:\n            if self.has_selected_text():\n                self.remove_text()\n            elif self.header_end_pos == cursor_position:\n                return\n            else:\n                self.stdkey_backspace()\n        elif key == Qt.Key_X and ctrl:\n            self.cut()\n        else:\n            CodeEditor.keyPressEvent(self, event)\n\n    def contextMenuEvent(self, event):\n        \"\"\"Reimplemented Qt Method to not show the context menu.\"\"\"\n        pass\n\n\nclass ShowErrorWidget(TracebackLinksMixin, ConsoleBaseWidget, BaseEditMixin):\n    \"\"\"Widget to show errors as they appear in the Internal console.\"\"\"\n    QT_CLASS = QPlainTextEdit\n    go_to_error = Signal(str)\n\n    def __init__(self, parent=None):\n        ConsoleBaseWidget.__init__(self, parent)\n        BaseEditMixin.__init__(self)\n        TracebackLinksMixin.__init__(self)\n        self.setReadOnly(True)\n\n\nclass SpyderErrorDialog(QDialog):\n    \"\"\"Custom error dialog for error reporting.\"\"\"\n\n    def __init__(self, parent=None, is_report=False):\n        QDialog.__init__(self, parent)\n        self.is_report = is_report\n\n        self.setWindowTitle(_(\"Issue reporter\"))\n        self.setModal(True)\n\n        # To save the traceback sent to the internal console\n        self.error_traceback = \"\"\n\n        # Dialog main label\n        if self.is_report:\n            title = _(\"Please fill the following information\")\n        else:\n            title = _(\"Spyder has encountered an internal problem!\")\n        main_label = QLabel(\n            _(\"<h3>{title}</h3>\"\n              \"Before reporting this problem, <i>please</i> consult our \"\n              \"comprehensive \"\n              \"<b><a href=\\\"{trouble_url}\\\">Troubleshooting Guide</a></b> \"\n              \"which should help solve most issues, and search for \"\n              \"<b><a href=\\\"{project_url}\\\">known bugs</a></b> \"\n              \"matching your error message or problem description for a \"\n              \"quicker solution.\"\n              ).format(title=title, trouble_url=__trouble_url__,\n                          project_url=__project_url__))\n        main_label.setOpenExternalLinks(True)\n        main_label.setWordWrap(True)\n        main_label.setAlignment(Qt.AlignJustify)\n        main_label.setStyleSheet('font-size: 12px;')\n\n        # Issue title\n        self.title = QLineEdit()\n        self.title.textChanged.connect(self._contents_changed)\n        self.title_chars_label = QLabel(_(\"{} more characters \"\n                                          \"to go...\").format(TITLE_MIN_CHARS))\n        form_layout = QFormLayout()\n        form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)\n        red_asterisk = '<font color=\"Red\">*</font>'\n        title_label = QLabel(_(\"<b>Title</b>: {}\").format(red_asterisk))\n        form_layout.setWidget(0, QFormLayout.LabelRole, title_label)\n        form_layout.setWidget(0, QFormLayout.FieldRole, self.title)\n\n        # Description\n        steps_header = QLabel(\n            _(\"<b>Steps to reproduce:</b> {}\").format(red_asterisk))\n        steps_text = QLabel(_(\"Please enter a detailed step-by-step \"\n                              \"description (in English) of what led up to \"\n                              \"the problem below. Issue reports without a \"\n                              \"clear way to reproduce them will be closed.\"))\n        steps_text.setWordWrap(True)\n        steps_text.setAlignment(Qt.AlignJustify)\n        steps_text.setStyleSheet('font-size: 12px;')\n\n        # Field to input the description of the problem\n        self.input_description = DescriptionWidget(self)\n\n        # Only allow to submit to Github if we have a long enough description\n        self.input_description.textChanged.connect(self._contents_changed)\n\n        # Widget to show errors\n        self.details = ShowErrorWidget(self)\n        self.details.set_pythonshell_font(get_font())\n        self.details.hide()\n\n        # Label to show missing chars\n        self.initial_chars = len(self.input_description.toPlainText())\n        self.desc_chars_label = QLabel(_(\"{} more characters \"\n                                         \"to go...\").format(DESC_MIN_CHARS))\n\n        # Checkbox to dismiss future errors\n        self.dismiss_box = QCheckBox(_(\"Hide all future errors during this \"\n                                       \"session\"))\n        if self.is_report:\n            self.dismiss_box.hide()\n\n        # Dialog buttons\n        gh_icon = ima.icon('github')\n        self.submit_btn = QPushButton(gh_icon, _('Submit to Github'))\n        self.submit_btn.setEnabled(False)\n        self.submit_btn.clicked.connect(self._submit_to_github)\n\n        self.details_btn = QPushButton(_('Show details'))\n        self.details_btn.clicked.connect(self._show_details)\n        if self.is_report:\n            self.details_btn.hide()\n\n        self.close_btn = QPushButton(_('Close'))\n        if self.is_report:\n            self.close_btn.clicked.connect(self.reject)\n\n        # Buttons layout\n        buttons_layout = QHBoxLayout()\n        buttons_layout.addWidget(self.submit_btn)\n        buttons_layout.addWidget(self.details_btn)\n        buttons_layout.addWidget(self.close_btn)\n\n        # Main layout\n        layout = QVBoxLayout()\n        layout.addWidget(main_label)\n        layout.addSpacing(20)\n        layout.addLayout(form_layout)\n        layout.addWidget(self.title_chars_label)\n        layout.addSpacing(12)\n        layout.addWidget(steps_header)\n        layout.addSpacing(-1)\n        layout.addWidget(steps_text)\n        layout.addSpacing(1)\n        layout.addWidget(self.input_description)\n        layout.addWidget(self.details)\n        layout.addWidget(self.desc_chars_label)\n        layout.addSpacing(15)\n        layout.addWidget(self.dismiss_box)\n        layout.addSpacing(15)\n        layout.addLayout(buttons_layout)\n        layout.setContentsMargins(25, 20, 25, 10)\n        self.setLayout(layout)\n\n        self.resize(570, 600)\n        self.title.setFocus()\n\n        # Set Tab key focus order\n        self.setTabOrder(self.title, self.input_description)\n\n    def _submit_to_github(self):\n        \"\"\"Action to take when pressing the submit button.\"\"\"\n        # Get reference to the main window\n        if self.parent() is not None:\n            if getattr(self.parent(), 'main', False):\n                # This covers the case when the dialog is attached\n                # to the internal console\n                main = self.parent().main\n            else:\n                # Else the dialog is attached to the main window\n                # directly\n                main = self.parent()\n        else:\n            main = None\n\n        # Getting description and traceback\n        title = self.title.text()\n        description = self.input_description.toPlainText()\n        traceback = self.error_traceback[:-1]  # Remove last EOL\n\n        # Render issue\n        if main is not None:\n            issue_text = main.render_issue(description=description,\n                                           traceback=traceback)\n        else:\n            issue_text = description\n\n        try:\n            if main is None:\n                org = 'ccordoba12'\n            else:\n                org = 'spyder-ide'\n            github_backend = GithubBackend(org, 'spyder', parent_widget=main)\n            github_report = github_backend.send_report(title, issue_text)\n            if github_report:\n                self.close()\n        except Exception:\n            ret = QMessageBox.question(\n                      self, _('Error'),\n                      _(\"An error occurred while trying to send the issue to \"\n                        \"Github automatically. Would you like to open it \"\n                        \"manually?<br><br>\"\n                        \"If so, please make sure to paste your clipboard \"\n                        \"into the issue report box that will appear in a new \"\n                        \"browser tab before clicking <i>Submit</i> on that \"\n                        \"page.\"))\n            if ret in [QMessageBox.Yes, QMessageBox.Ok]:\n                QApplication.clipboard().setText(issue_text)\n                issue_body = (\n                    \" \\n<!---   *** BEFORE SUBMITTING: PASTE CLIPBOARD HERE \"\n                    \"TO COMPLETE YOUR REPORT ***   ---!>\\n\")\n                if main is not None:\n                    main.report_issue(body=issue_body, title=title,\n                                      open_webpage=True)\n                else:\n                    pass\n\n    def append_traceback(self, text):\n        \"\"\"Append text to the traceback, to be displayed in details.\"\"\"\n        self.error_traceback += text\n\n    def _show_details(self):\n        \"\"\"Show traceback on its own dialog\"\"\"\n        if self.details.isVisible():\n            self.details.hide()\n            self.details_btn.setText(_('Show details'))\n        else:\n            self.resize(570, 700)\n            self.details.document().setPlainText('')\n            self.details.append_text_to_shell(self.error_traceback,\n                                              error=True,\n                                              prompt=False)\n            self.details.show()\n            self.details_btn.setText(_('Hide details'))\n\n    def _contents_changed(self):\n        \"\"\"Activate submit_btn.\"\"\"\n        desc_chars = (len(self.input_description.toPlainText()) -\n                      self.initial_chars)\n        if desc_chars < DESC_MIN_CHARS:\n            self.desc_chars_label.setText(\n                u\"{} {}\".format(DESC_MIN_CHARS - desc_chars,\n                                _(\"more characters to go...\")))\n        else:\n            self.desc_chars_label.setText(_(\"Description complete; thanks!\"))\n\n        title_chars = len(self.title.text())\n        if title_chars < TITLE_MIN_CHARS:\n            self.title_chars_label.setText(\n                u\"{} {}\".format(TITLE_MIN_CHARS - title_chars,\n                                _(\"more characters to go...\")))\n        else:\n            self.title_chars_label.setText(_(\"Title complete; thanks!\"))\n\n        submission_enabled = (desc_chars >= DESC_MIN_CHARS and\n                              title_chars >= TITLE_MIN_CHARS)\n        self.submit_btn.setEnabled(submission_enabled)\n\n\ndef test():\n    from spyder.utils.qthelpers import qapplication\n    app = qapplication()\n    dlg = SpyderErrorDialog()\n    dlg.show()\n    sys.exit(dlg.exec_())\n\n\nif __name__ == \"__main__\":\n    test()\n", "path": "spyder/widgets/reporterror.py"}]}