Repository: spyder-ide/spyder

Issue:
Issue reporter misbehaves if you delete characters of the header with the Delete key
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

Open the Issue reporter window, and start typing in the Steps to reproduce edit box, just a word or two is fine. Then go up to the first line ("### What steps will reproduce the problem") and delete the third hash mark. This effectively breaks editing. For example, but the cursor on the line you typed, hit HOME, then type another character. The cursor jumps to the end of the line and inserts the character there. 

Alternatively, open the window and immediately delete the third hash mark. You will now be in a mode where you cannot enter any text at all, including adding the hash mark back.

Alternatively, open the Issues reporter window, select all text in the Steps to reproduce edit box, and press delete. All text disappears, and you are no longer able to enter any text at all. 





## Versions

* Spyder version: 4.0.0b4 
* Python version: 3.7.3
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 7

### Dependencies

```
pygments >=2.0    :  2.4.2 (OK)
qdarkstyle >=2.6.4:  2.7 (OK)
sphinx >=0.6.6    :  2.1.2 (OK)
pyls >=0.27.0     :  0.28.2 (OK)
nbconvert >=4.0   :  5.5.0 (OK)
pandas >=0.13.1   :  0.25.1 (OK)
numpy >=1.7       :  1.16.4 (OK)
sympy >=0.7.3     :  1.4 (OK)
cython >=0.21     :  0.29.13 (OK)
qtconsole >=4.5.2 :  4.5.4 (OK)
IPython >=4.0     :  7.8.0 (OK)
matplotlib >=2.0.0:  3.1.1 (OK)
pylint >=0.25     :  2.3.1 (OK)
```



Discussion:
You missed the critical part in your report, but thanks for doing it. This was caused by a refactoring in our code editor widget to better handle the Del key there, but we forgot to update the issue reporter after that.

Resolving patch:
diff --git a/spyder/widgets/reporterror.py b/spyder/widgets/reporterror.py
--- a/spyder/widgets/reporterror.py
+++ b/spyder/widgets/reporterror.py
@@ -82,11 +82,6 @@ def keyPressEvent(self, event):
 
         if cursor_position < self.header_end_pos:
             self.restrict_cursor_position(self.header_end_pos, 'eof')
-        elif key == Qt.Key_Delete:
-            if self.has_selected_text():
-                self.remove_text()
-            else:
-                self.stdkey_clear()
         elif key == Qt.Key_Backspace:
             if self.has_selected_text():
                 self.remove_text()
@@ -99,6 +94,17 @@ def keyPressEvent(self, event):
         else:
             CodeEditor.keyPressEvent(self, event)
 
+    def delete(self):
+        """Reimplemented to avoid removing the header."""
+        cursor_position = self.get_position('cursor')
+
+        if cursor_position < self.header_end_pos:
+            self.restrict_cursor_position(self.header_end_pos, 'eof')
+        elif self.has_selected_text():
+            self.remove_text()
+        else:
+            self.stdkey_clear()
+
     def contextMenuEvent(self, event):
         """Reimplemented Qt Method to not show the context menu."""
         pass


Test patch:
diff --git a/spyder/widgets/tests/test_reporterror.py b/spyder/widgets/tests/test_reporterror.py
--- a/spyder/widgets/tests/test_reporterror.py
+++ b/spyder/widgets/tests/test_reporterror.py
@@ -25,6 +25,7 @@ def error_dialog(qtbot):
     """Set up error report dialog."""
     widget = SpyderErrorDialog(None)
     qtbot.addWidget(widget)
+    widget.show()
     return widget
 
 
@@ -55,7 +56,13 @@ def test_dialog(error_dialog, qtbot):
     # Assert delete leaves the header
     qtbot.keyClicks(dlg.input_description, desc_text)
     dlg.input_description.selectAll()
-    qtbot.keyPress(dlg.input_description, Qt.Key_Delete)
+    dlg.input_description.delete()
+    assert dlg.input_description.toPlainText() == dlg.input_description.header
+
+    # Assert delete doesn't remove characters on the header
+    ini_pos = dlg.input_description.get_position('sof')
+    dlg.input_description.set_cursor_position(ini_pos)
+    dlg.input_description.delete()
     assert dlg.input_description.toPlainText() == dlg.input_description.header
 
     # Assert backspace works as expected
@@ -67,6 +74,12 @@ def test_dialog(error_dialog, qtbot):
     qtbot.keyPress(dlg.input_description, Qt.Key_Backspace)
     assert dlg.input_description.toPlainText() == dlg.input_description.header
 
+    ini_pos = dlg.input_description.get_position('sof')
+    dlg.input_description.set_cursor_position(ini_pos)
+    dlg.input_description.set_cursor_position('eol')
+    qtbot.keyPress(dlg.input_description, Qt.Key_Backspace)
+    assert dlg.input_description.toPlainText() == dlg.input_description.header
+
     # Assert chars label works as expected
     assert dlg.desc_chars_label.text() == '{} more characters to go...'.format(DESC_MIN_CHARS)
     qtbot.keyClicks(dlg.input_description, desc_text)