Repository: spyder-ide/spyder

Issue:
Bug with saved window layouts
## Description

**What steps will reproduce the problem?**

1. Saved a window layout as just the text editor named Editor.  No ipython, variable explorer, file explorer, or help.
2. Opened default spyder window layout.
3. Selected Editor window layout.

**What is the expected output? What do you see instead?**
Expected Editor window layout.  Spyder crashed instead.

**Please provide any additional information below**

  File "/home/damian/opt/anaconda3/lib/python3.6/site-packages/spyder/app/mainwindow.py", line 1783, in <lambda>
    return lambda: self.quick_layout_switch(i)
  File "/home/damian/opt/anaconda3/lib/python3.6/site-packages/spyder/app/mainwindow.py", line 1903, in quick_layout_switch
    self.setup_default_layouts(index, settings)
  File "/home/damian/opt/anaconda3/lib/python3.6/site-packages/spyder/app/mainwindow.py", line 1616, in setup_default_layouts
    layout = layouts[index]
KeyError: 4


## Version and main components

* Spyder Version: 3.2.6 
* Python Version: 3.6.3
* Qt Versions: 5.6.2, PyQt5 5.6 on Linux

## Dependencies
```
pyflakes >=0.6.0 :  1.6.0 (OK)
pycodestyle >=2.3:  2.3.1 (OK)
pygments >=2.0   :  2.2.0 (OK)
pandas >=0.13.1  :  0.20.3 (OK)
numpy >=1.7      :  1.13.3 (OK)
sphinx >=0.6.6   :  1.6.3 (OK)
rope >=0.9.4     :  0.10.5 (OK)
jedi >=0.9.0     :  0.10.2 (OK)
psutil >=0.3     :  5.4.0 (OK)
nbconvert >=4.0  :  5.3.1 (OK)
sympy >=0.7.3    :  1.1.1 (OK)
cython >=0.21    :  0.26.1 (OK)
qtconsole >=4.2.0:  4.3.1 (OK)
IPython >=4.0    :  6.1.0 (OK)
pylint >=0.25    :  1.7.4 (OK)

```



Discussion:
Thanks for reporting, we'll fix this in a future release.
Also, seems to have been reported before as #5858 but this appears to be a clear way to reproduce it.
I'm glad there were some old issues with this; otherwise, I would have thought it was related to #6153.  Since I've been in layouts recently, I'll take a look, but so far I haven't been able to recreate it.  I know what needs to happen for the error to occur, but I just can't figure out the sequence of events for making that happen.

Resolving patch:
diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py
--- a/spyder/app/mainwindow.py
+++ b/spyder/app/mainwindow.py
@@ -257,6 +257,7 @@ class MainWindow(QMainWindow):
          ('winpython', "https://winpython.github.io/",
           _("WinPython"))
                 )
+    DEFAULT_LAYOUTS = 4
 
     # Signals
     restore_scrollbar_position = Signal()
@@ -1498,7 +1499,7 @@ def setup_default_layouts(self, index, settings):
         self.setUpdatesEnabled(False)
 
         # IMPORTANT: order has to be the same as defined in the config file
-        MATLAB, RSTUDIO, VERTICAL, HORIZONTAL = range(4)
+        MATLAB, RSTUDIO, VERTICAL, HORIZONTAL = range(self.DEFAULT_LAYOUTS)
 
         # define widgets locally
         editor = self.editor
@@ -1901,10 +1902,21 @@ def quick_layout_switch(self, index):
             (hexstate, window_size, prefs_dialog_size, pos, is_maximized,
              is_fullscreen) = settings
 
-            # The defaults layouts will alwyas be regenerated unless there was
+            # The defaults layouts will always be regenerated unless there was
             # an overwrite, either by rewriting with same name, or by deleting
             # and then creating a new one
             if hexstate is None:
+                # The value for hexstate shouldn't be None for a custom saved
+                # layout (ie, where the index is greater than the number of
+                # defaults).  See issue 6202.
+                if index != 'default' and index >= self.DEFAULT_LAYOUTS:
+                    QMessageBox.critical(
+                            self, _("Warning"),
+                            _("Error opening the custom layout.  Please close"
+                              " Spyder and try again.  If the issue persists,"
+                              " then you must use 'Reset to Spyder default' "
+                              "from the layout menu."))
+                    return
                 self.setup_default_layouts(index, settings)
         except cp.NoOptionError:
             QMessageBox.critical(self, _("Warning"),


Test patch: