Repository: spyder-ide/spyder

Issue:
Spyder quits when removing a plot and save plots dialog is wrong.
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [ ] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [ ] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [ ] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [ ] Tried basic troubleshooting (if a bug/error)
    * [ ] Restarted Spyder
    * [ ] Reset preferences with ``spyder --reset``
    * [ ] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [ ] Tried the other applicable steps from the Troubleshooting Guide
* [ ] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description

1) The dialog when saving multiple plots in the plots pane is wrong, it should be the dialog that says "Save"
![Screen Shot 2020-04-23 at 4 15 59 AM](https://user-images.githubusercontent.com/18587879/80082894-95f92b00-851a-11ea-9aac-ba810b043f6c.png)

2) Spyder quits unexpectedly when removing a plot from the context menu.

![issue](https://user-images.githubusercontent.com/18587879/80083062-cd67d780-851a-11ea-82d4-56787fb40b8e.gif)



### What steps reproduce the problem?

1. 
2. 
3. 

### What is the expected output? What do you see instead?



### Paste Traceback/Error Below (if applicable)
<!--- Copy from error dialog or View > Panes > Internal Console --->

```python-traceback

PASTE TRACEBACK HERE

```

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: Spyder 4.2.0.dev0 (Commit: 89791cb28) 
* Python version: 3.7.4
* Qt version: 5.9.6
* PyQt version: 5.9.2
* Operating System name/version:  macOS Catalina 10.15.3

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
PASTE DEPENDENCIES HERE
```



Discussion:
Thanks a lot @juanis2112 for finding this on time before 4.1.3! I can reproduce it on Linux too and it's critical for us to solve it before we can do the release.

@dalthviz, please take a look at this one.
1. I think it is Ok to use `getExistingDirectory` for the feature to save all figures to disk. Since we are saving multiple figures, I don't see how the "getSaveFileName" would work...  The idea is to select a directory where all figures are saved in batch in that directory. The names of the figures are determined programattically.

2. Thank you very much for finding this nasty bug! In Windows everything is working fine though.
@ccordoba12 is working for me on Windows:

![plots](https://user-images.githubusercontent.com/16781833/80428145-d0621f80-88ae-11ea-8380-5c3fee5cebd9.gif)

I can try to fix it. It does happen to me as well.
> @ccordoba12 is working for me on Windows

Yeah, it doesn't fail on Windows, just Linux and macOS.

> I can try to fix it. It does happen to me as well.

Thanks @goanpeca! Please also address @juanis2112 first comment as well.

Resolving patch:
diff --git a/spyder/plugins/plots/widgets/figurebrowser.py b/spyder/plugins/plots/widgets/figurebrowser.py
--- a/spyder/plugins/plots/widgets/figurebrowser.py
+++ b/spyder/plugins/plots/widgets/figurebrowser.py
@@ -860,11 +860,14 @@ def remove_current_thumbnail(self):
     def remove_all_thumbnails(self):
         """Remove all thumbnails."""
         for thumbnail in self._thumbnails:
-            self.layout().removeWidget(thumbnail)
             thumbnail.sig_canvas_clicked.disconnect()
             thumbnail.sig_remove_figure.disconnect()
             thumbnail.sig_save_figure.disconnect()
+            self.layout().removeWidget(thumbnail)
             thumbnail.setParent(None)
+            thumbnail.hide()
+            thumbnail.close()
+
         self._thumbnails = []
         self.current_thumbnail = None
         self.figure_viewer.figcanvas.clear_canvas()
@@ -873,20 +876,35 @@ def remove_thumbnail(self, thumbnail):
         """Remove thumbnail."""
         if thumbnail in self._thumbnails:
             index = self._thumbnails.index(thumbnail)
+
+        # Disconnect signals
+        try:
+            thumbnail.sig_canvas_clicked.disconnect()
+            thumbnail.sig_remove_figure.disconnect()
+            thumbnail.sig_save_figure.disconnect()
+        except TypeError:
+            pass
+
+        if thumbnail in self._thumbnails:
             self._thumbnails.remove(thumbnail)
-        self.layout().removeWidget(thumbnail)
-        thumbnail.setParent(None)
-        thumbnail.sig_canvas_clicked.disconnect()
-        thumbnail.sig_remove_figure.disconnect()
-        thumbnail.sig_save_figure.disconnect()
 
         # Select a new thumbnail if any :
         if thumbnail == self.current_thumbnail:
             if len(self._thumbnails) > 0:
-                self.set_current_index(min(index, len(self._thumbnails)-1))
+                self.set_current_index(
+                    min(index, len(self._thumbnails) - 1)
+                )
             else:
-                self.current_thumbnail = None
                 self.figure_viewer.figcanvas.clear_canvas()
+                self.current_thumbnail = None
+
+        # Hide and close thumbnails
+        self.layout().removeWidget(thumbnail)
+        thumbnail.hide()
+        thumbnail.close()
+
+        # See: spyder-ide/spyder#12459
+        QTimer.singleShot(150, lambda: thumbnail.setParent(None))
 
     def set_current_index(self, index):
         """Set the currently selected thumbnail by its index."""


Test patch:
diff --git a/spyder/plugins/plots/widgets/tests/test_plots_widgets.py b/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
--- a/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
+++ b/spyder/plugins/plots/widgets/tests/test_plots_widgets.py
@@ -216,7 +216,7 @@ def test_close_all_figures(figbrowser, tmpdir, fmt):
 
 
 @pytest.mark.parametrize("fmt", ['image/png', 'image/svg+xml'])
-def test_close_one_thumbnail(figbrowser, tmpdir, fmt):
+def test_close_one_thumbnail(qtbot, figbrowser, tmpdir, fmt):
     """
     Test the thumbnail is removed from the GUI.
     """
@@ -228,6 +228,9 @@ def test_close_one_thumbnail(figbrowser, tmpdir, fmt):
     figures = figbrowser.thumbnails_sb.findChildren(FigureThumbnail)
     figbrowser.thumbnails_sb.remove_thumbnail(figures[0])
 
+    # Removed thumbnails are unparented with a timer to prevent segfaults
+    qtbot.wait(200)
+
     assert len(figbrowser.thumbnails_sb.findChildren(FigureThumbnail)) == 1