Repository: psychopy/psychopy

Issue:
Error when applying preferences
I get the following error when applying preferences using the GUI. 

```
Traceback (most recent call last):
  File "C:\Users\matth\PycharmProjects\psychopy\psychopy\app\preferencesDlg.py", line 885, in OnOKClicked
    self.applyPrefs()
  File "C:\Users\matth\PycharmProjects\psychopy\psychopy\app\preferencesDlg.py", line 845, in applyPrefs
    self.updateBuilderUI()
  File "C:\Users\matth\PycharmProjects\psychopy\psychopy\app\preferencesDlg.py", line 861, in updateBuilderUI
    builder = self.app.builder
AttributeError: 'PsychoPyApp' object has no attribute 'builder'

```

I guess because there is no Builder frame open and were trying to apply preferences to it.


Discussion:
Actually, having looked at the code it also assumes there's a single Builder frame (there is only one Coder frame permitted currently but multiple Builder frames).

I believe, rather than updateCoder and updateBuilder we should be using an updateFrames method and letting that handle both types:

```python

    def updateFramesUI(self):
        """Update the Coder UI (eg. fonts, themes, etc.) from prefs."""
        for frame in self.app.getAllFrames():
            if frame.frameType == 'builder':
                frame.layoutPanes()
            elif frame.frameType == 'coder':
                # apply settings over document pages
                for ii in range(frame.notebook.GetPageCount()):
                    doc = frame.notebook.GetPage(ii)
                    doc.theme = prefs.app['theme']
                for ii in range(frame.shelf.GetPageCount()):
                    doc = frame.shelf.GetPage(ii)
                    doc.theme = prefs.app['theme']
```


Resolving patch:
diff --git a/psychopy/app/preferencesDlg.py b/psychopy/app/preferencesDlg.py
--- a/psychopy/app/preferencesDlg.py
+++ b/psychopy/app/preferencesDlg.py
@@ -841,26 +841,21 @@ def applyPrefs(self):
 
         # after validation, update the UI
         self.app.theme = self.app.theme
-        self.updateCoderUI()
-        self.updateBuilderUI()
+        self.updateFramesUI()
 
-    def updateCoderUI(self):
+    def updateFramesUI(self):
         """Update the Coder UI (eg. fonts, themes, etc.) from prefs."""
-        # start applying prefs to take effect
-        coder = self.app.coder
-        if coder is not None:
-            # apply settings over document pages
-            for ii in range(coder.notebook.GetPageCount()):
-                doc = coder.notebook.GetPage(ii)
-                doc.theme = prefs.app['theme']
-            for ii in range(coder.shelf.GetPageCount()):
-                doc = coder.shelf.GetPage(ii)
-                doc.theme = prefs.app['theme']
-
-    def updateBuilderUI(self):
-        builder = self.app.builder
-        if builder is not None:
-            builder.layoutPanes()
+        for frame in self.app.getAllFrames():
+            if frame.frameType == 'builder':
+                frame.layoutPanes()
+            elif frame.frameType == 'coder':
+                # apply settings over document pages
+                for ii in range(frame.notebook.GetPageCount()):
+                    doc = frame.notebook.GetPage(ii)
+                    doc.theme = prefs.app['theme']
+                for ii in range(frame.shelf.GetPageCount()):
+                    doc = frame.shelf.GetPage(ii)
+                    doc.theme = prefs.app['theme']
 
     def OnApplyClicked(self, event):
         """Apply button clicked, this makes changes to the UI without leaving


Test patch: