Repository: spyder-ide/spyder

Issue:
Spyder fails to quit if Preferences dialog is open
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

1. Open Spyder
2. Open Preferences
3. Quit Spyder

Spyder proceeds to shutdown plugins, but aborts before completing the shutdown process.

![quit](https://user-images.githubusercontent.com/9618975/165804545-2fbc4643-470d-4c55-ba75-84c4f86eb660.gif)

## Versions

* Spyder version: 5.4.0.dev0 bb3a32093
* Python version: 3.10.4
* Qt version: 5.12.9
* PyQt5 version: 5.12.3
* Operating System: Darwin 20.6.0

### Dependencies

```
# Mandatory:
applaunchservices >=0.1.7            :  0.2.1 (OK)
atomicwrites >=1.2.0                 :  1.4.0 (OK)
chardet >=2.0.0                      :  4.0.0 (OK)
cloudpickle >=0.5.0                  :  2.0.0 (OK)
cookiecutter >=1.6.0                 :  1.7.3 (OK)
diff_match_patch >=20181111          :  20200713 (OK)
intervaltree >=3.0.2                 :  3.0.2 (OK)
IPython >=7.31.1;<8.0.0              :  7.32.0 (OK)
jedi >=0.17.2;<0.19.0                :  0.18.1 (OK)
jellyfish >=0.7                      :  0.9.0 (OK)
jsonschema >=3.2.0                   :  4.4.0 (OK)
keyring >=17.0.0                     :  23.4.0 (OK)
nbconvert >=4.0                      :  6.5.0 (OK)
numpydoc >=0.6.0                     :  1.2.1 (OK)
parso >=0.7.0;<0.9.0                 :  0.8.3 (OK)
pexpect >=4.4.0                      :  4.8.0 (OK)
pickleshare >=0.4                    :  0.7.5 (OK)
psutil >=5.3                         :  5.9.0 (OK)
pygments >=2.0                       :  2.12.0 (OK)
pylint >=2.5.0                       :  2.13.5 (OK)
pyls_spyder >=0.4.0                  :  0.4.0 (OK)
pylsp >=1.4.1;<1.5.0                 :  1.4.1 (OK)
pylsp_black >=1.2.0                  :  1.2.1 (OK)
qdarkstyle >=3.0.2;<3.1.0            :  3.0.3 (OK)
qstylizer >=0.1.10                   :  0.2.1 (OK)
qtawesome >=1.0.2                    :  1.1.1 (OK)
qtconsole >=5.3.0;<5.4.0             :  5.4.0.dev0 (OK)
qtpy >=2.0.1                         :  2.0.1 (OK)
rtree >=0.9.7                        :  1.0.0 (OK)
setuptools >=49.6.0                  :  62.1.0 (OK)
sphinx >=0.6.6                       :  4.5.0 (OK)
spyder_kernels >=2.3.0;<2.4.0        :  2.4.0.dev0 (OK)
textdistance >=4.2.0                 :  4.2.2 (OK)
three_merge >=0.1.1                  :  0.1.1 (OK)
watchdog >=0.10.3                    :  2.1.7 (OK)
zmq >=17                             :  22.3.0 (OK)

# Optional:
cython >=0.21                        :  0.29.28 (OK)
matplotlib >=3.0.0                   :  3.5.1 (OK)
numpy >=1.7                          :  1.22.3 (OK)
pandas >=1.1.1                       :  1.4.2 (OK)
scipy >=0.17.0                       :  1.8.0 (OK)
sympy >=0.7.3                        :  1.10.1 (OK)

# Spyder plugins:
spyder_terminal.terminalplugin 1.2.2 :  1.2.2 (OK)
```



Discussion:
Just in case, I was able to reproduce this with Spyder 5.3.0 on the Windows installer too
Yep, I noticed it too on Linux.
I'm guessing that Preferences just fails to close its open dialog window during the plugin shutdown process. Do you think this is unique to the Preferences plugin, or would this happen for any plugin that has an open dialog?
The Run plugin's dialog is modal, so I can't quit Spyder while it is open.

Resolving patch:
diff --git a/spyder/plugins/preferences/plugin.py b/spyder/plugins/preferences/plugin.py
--- a/spyder/plugins/preferences/plugin.py
+++ b/spyder/plugins/preferences/plugin.py
@@ -346,6 +346,8 @@ def reset(self):
             application = self.get_plugin(Plugins.Application)
             application.sig_restart_requested.emit()
 
-    def can_close(self) -> bool:
+    def on_close(self, cancelable=False):
         container = self.get_container()
-        return not container.is_dialog_open()
+        if container.is_preferences_open():
+            container.close_preferences()
+        return True
diff --git a/spyder/plugins/preferences/widgets/container.py b/spyder/plugins/preferences/widgets/container.py
--- a/spyder/plugins/preferences/widgets/container.py
+++ b/spyder/plugins/preferences/widgets/container.py
@@ -91,9 +91,14 @@ def __preference_page_changed(self, index):
         """Preference page index has changed."""
         self.dialog_index = index
 
-    def is_dialog_open(self):
+    def is_preferences_open(self):
+        """Check if preferences is open."""
         return self.dialog is not None and self.dialog.isVisible()
 
+    def close_preferences(self):
+        """Close preferences"""
+        self.dialog.close()
+
     def show_preferences(self):
         """Show preferences."""
         self.sig_show_preferences_requested.emit()


Test patch: