Index: src/sas/sasgui/guiframe/gui_manager.py
===================================================================
--- src/sas/sasgui/guiframe/gui_manager.py	(revision 8ac05a59a0078f40fc8af4febae16624b9d5c818)
+++ src/sas/sasgui/guiframe/gui_manager.py	(revision 5251ec6db8aae214addfa0a5a1da16820994958b)
@@ -13,6 +13,4 @@
 
 
-import wx
-import wx.aui
 import os
 import sys
@@ -25,4 +23,8 @@
 import urllib
 import json
+import copy
+
+import wx
+import wx.aui
 
 from matplotlib import _pylab_helpers
@@ -286,5 +288,5 @@
         return client size tuple
         """
-        width, height = self.GetClientSizeTuple()
+        width, height = self.GetClientSize()
         height -= 45
         # Adjust toolbar height
@@ -361,9 +363,8 @@
         try:
             self.read_batch_tofile(file_name=path)
-        except:
+        except Exception as exc:
             msg = "Error occurred when reading the file; %s\n" % path
-            msg += "%s\n" % sys.exc_value
-            wx.PostEvent(self, StatusEvent(status=msg,
-                                           info="error"))
+            msg += "%s\n" % exc
+            wx.PostEvent(self, StatusEvent(status=msg, info="error"))
 
     def read_batch_tofile(self, file_name):
@@ -705,8 +706,8 @@
         try:
             self.load_from_cmd(self._input_file)
-        except:
+        except Exception as exc:
             msg = "%s Cannot load file %s\n" % (str(APPLICATION_NAME),
                                                 str(self._input_file))
-            msg += str(sys.exc_value) + '\n'
+            msg += str(exc) + '\n'
             logger.error(msg)
         if self._data_panel is not None and len(self.plugins) > 0:
@@ -797,7 +798,7 @@
                 self._data_plugin = data_loader.Plugin()
                 plugins.append(self._data_plugin)
-            except:
+            except Exception as exc:
                 msg = "ViewerFrame._get_local_plugins:"
-                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
+                msg += "cannot import dataloader plugin.\n %s" % exc
                 logger.error(msg)
         if style2 == GUIFRAME.PLOTTING_ON:
@@ -807,7 +808,7 @@
                 self._plotting_plugin = plotting.Plugin()
                 plugins.append(self._plotting_plugin)
-            except:
+            except Exception as exc:
                 msg = "ViewerFrame._get_local_plugins:"
-                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
+                msg += "cannot import plotting plugin.\n %s" % exc
                 logger.error(msg)
 
@@ -856,18 +857,18 @@
                                 msg = "Found plug-in: %s" % module.PLUGIN_ID
                                 logger.info(msg)
-                            except:
+                            except Exception as exc:
                                 msg = "Error accessing PluginPanel"
-                                msg += " in %s\n  %s" % (name, sys.exc_value)
+                                msg += " in %s\n  %s" % (name, exc)
                                 config.printEVT(msg)
-                    except:
-                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
+                    except Exception as exc:
+                        msg = "ViewerFrame._find_plugins: %s" % exc
                         logger.error(msg)
                     finally:
                         if file is not None:
                             file.close()
-        except:
+        except Exception as exc:
             # Should raise and catch at a higher level and
             # display error on status bar
-            logger.error(sys.exc_value)
+            logger.error(exc)
 
         return plugins
@@ -1599,5 +1600,5 @@
         """
         # This CallAfter fixes many crashes on MAC.
-        wx.CallAfter(self.sb.set_status, evt)
+        wx.CallAfter(self.sb.set_status, evt.Clone())
 
     def on_view(self, evt):
@@ -1643,5 +1644,5 @@
         ID = str(uid)
         config.printEVT("delete_panel: %s" % ID)
-        if ID in self.panels.keys():
+        if ID in self.panels:
             self.panel_on_focus = None
             panel = self.panels[ID]
@@ -1655,7 +1656,7 @@
 
             # delete uid number not str(uid)
-            if ID in self.plot_panels.keys():
+            if ID in self.plot_panels:
                 del self.plot_panels[ID]
-            if ID in self.panels.keys():
+            if ID in self.panels:
                 del self.panels[ID]
         else:
@@ -1691,7 +1692,7 @@
                     try:
                         reader.read(path)
-                    except:
+                    except Exception as exc:
                         msg = "DataLoader Error: Encounted Non-ASCII character"
-                        msg += "\n(%s)" % sys.exc_value
+                        msg += "\n(%s)" % exc
                         wx.PostEvent(self, StatusEvent(status=msg,
                                                        info="error",
@@ -1774,8 +1775,8 @@
 
             self.add_data(data_list=output)
-        except:
+        except Exception as exc:
             error_message = "Error while loading"
             error_message += " Data from cmd:\n %s\n" % str(path)
-            error_message += str(sys.exc_value) + "\n"
+            error_message += str(exc) + "\n"
             logger.error(error_message)
 
@@ -1795,8 +1796,8 @@
             else:
                 return
-        except:
+        except Exception as exc:
             error_message = "Error while loading"
             error_message += " Data folder from cmd:\n %s\n" % str(path)
-            error_message += str(sys.exc_value) + "\n"
+            error_message += str(exc) + "\n"
             logger.error(error_message)
 
@@ -1865,6 +1866,6 @@
             self._data_panel.selection_cbox.SetValue('Select all Data')
             self._data_panel._on_selection_type(None)
-            for _, theory_dict in self._data_panel.list_cb_theory.iteritems():
-                for key, value in theory_dict.iteritems():
+            for _, theory_dict in self._data_panel.list_cb_theory.items():
+                for key, value in theory_dict.items():
                     item, _, _ = value
                     item.Check(True)
@@ -1974,5 +1975,5 @@
             # case of a panel with multi-pages
             if hasattr(panel, "opened_pages"):
-                for _, page in panel.opened_pages.iteritems():
+                for _, page in panel.opened_pages.items():
                     data = page.get_data()
                     # state must be cloned
@@ -2096,5 +2097,5 @@
                 msg += " Please try again later."
                 self.SetStatusText(msg)
-            elif cmp(version, config.__version__) > 0:
+            elif version > config.__version__:
                 msg = "Version %s is available! " % str(version)
                 if not standalone:
@@ -2112,7 +2113,7 @@
                     msg += " of %s" % str(config.__appname__)
                     self.SetStatusText(msg)
-        except:
+        except Exception as exc:
             msg = "guiframe: could not get latest application"
-            msg += " version number\n  %s" % sys.exc_value
+            msg += " version number\n  %s" % exc
             logger.error(msg)
             if not standalone:
@@ -2154,5 +2155,5 @@
         # S King, Sep 2018
 
-        from documentation_window import DocumentationWindow
+        from .documentation_window import DocumentationWindow
         _TreeLocation = "user/release.html"
         DocumentationWindow(self, -1, _TreeLocation, "",
@@ -2170,10 +2171,10 @@
         # original 2.x tutorial.
         # Code below, implemented from 4.2.0, redirects
-        # action to the Tutorials page of the help 
+        # action to the Tutorials page of the help
         # documentation to give access to all available
         # tutorials
         # S King, Sep 2018
 
-        from documentation_window import DocumentationWindow
+        from .documentation_window import DocumentationWindow
         _TreeLocation = "user/tutorial.html"
         DocumentationWindow(self, -1, _TreeLocation, "",
@@ -2190,5 +2191,5 @@
         # Running SasView "in-place" using run.py means the docs will be in a
         # different place than they would otherwise.
-        from documentation_window import DocumentationWindow
+        from .documentation_window import DocumentationWindow
         _TreeLocation = "user/user.html"
         DocumentationWindow(self, -1, _TreeLocation, "",
@@ -2238,5 +2239,5 @@
                 if (style == GUIFRAME.MANAGER_ON) \
                         and self.panels[item] == self._data_panel:
-                    if 'data_panel' in self.panels.keys():
+                    if 'data_panel' in self.panels:
                         frame = self.panels['data_panel'].get_frame()
                         if frame is None:
@@ -2290,5 +2291,5 @@
         # set data in the data panel
         if self._data_panel is not None:
-            data_state = self._data_manager.get_data_state(data_list.keys())
+            data_state = self._data_manager.get_data_state(list(data_list.keys()))
             self._data_panel.load_data_list(data_state)
         # if the data panel is shown wait for the user to press a button
@@ -2302,5 +2303,5 @@
         else:
             # automatically send that to the current perspective
-            self.set_data(data_id=data_list.keys())
+            self.set_data(data_id=list(data_list.keys()))
 
     def set_data(self, data_id, theory_id=None):
@@ -2310,5 +2311,5 @@
         list_data, _ = self._data_manager.get_by_id(data_id)
         if self._current_perspective is not None:
-            self._current_perspective.set_data(list_data.values())
+            self._current_perspective.set_data(list(list_data.values()))
 
         else:
@@ -2322,7 +2323,7 @@
         if self._current_perspective is not None:
             try:
-                self._current_perspective.set_theory(list_theory.values())
-            except:
-                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
+                self._current_perspective.set_theory(list(list_theory.values()))
+            except Exception as exc:
+                msg = "Guiframe set_theory: \n" + str(exc)
                 logger.info(msg)
                 wx.PostEvent(self, StatusEvent(status=msg, info="error"))
@@ -2338,5 +2339,5 @@
         data_list, _ = self._data_manager.get_by_id(data_id)
         _, temp_list_theory = self._data_manager.get_by_id(theory_id)
-        total_plot_list = data_list.values()
+        total_plot_list = list(data_list.values())
         for item in temp_list_theory.values():
             theory_data, theory_state = item
@@ -2387,5 +2388,5 @@
         data_list, _ = self._data_manager.get_by_id(data_id)
         _, temp_list_theory = self._data_manager.get_by_id(theory_id)
-        total_plot_list = data_list.values()
+        total_plot_list = list(data_list.values())
         for item in temp_list_theory.values():
             theory_data, theory_state = item
@@ -2410,6 +2411,6 @@
                                             group_id=("res" + str(id)),
                                             action='remove'))
-        except:
-            logger.error(sys.exc_value)
+        except Exception as exc:
+            logger.error(exc)
 
     def save_data1d(self, data, fname):
@@ -2516,5 +2517,5 @@
             wx.PostEvent(self, StatusEvent(status=msg,
                                            info="error"))
-            raise ValueError, msg
+            raise ValueError(msg)
         # text = str(data)
         text = data.__str__()
@@ -2551,5 +2552,5 @@
                                                   dy_val,
                                                   dx_val)
-        from pdfview import TextFrame
+        from .pdfview import TextFrame
         frame = TextFrame(None, -1, "Data Info: %s" % data.name, text)
         # put icon
@@ -2635,5 +2636,5 @@
                 break
 
-        from pdfview import TextFrame
+        from .pdfview import TextFrame
         frame = TextFrame(None, -1, "Data Info: %s" % data.name, text)
         # put icon
@@ -2702,5 +2703,5 @@
         check = "Theory1D"
         is_theory = len(self.panel_on_focus.plots) <= 1 and \
-            self.panel_on_focus.plots.values()[0].__class__.__name__ == check
+            list(self.panel_on_focus.plots.values())[0].__class__.__name__ == check
 
         is_data2d = hasattr(new_plot, 'data')
@@ -3218,9 +3219,9 @@
             else:
                 self.frame.Show()
-        except:
+        except Exception as exc:
             if self.s_screen is not None:
                 self.s_screen.Close()
             msg = "Cannot display splash screen\n"
-            msg += str(sys.exc_value)
+            msg += str(exc)
             logger.error(msg)
             self.frame.Show()
@@ -3277,7 +3278,7 @@
                         if os.path.isfile(file_path):
                             os.remove(file_path)
-                except:
+                except Exception as exc:
                     logger.error("gui_manager.clean_plugin_models:\n  %s"
-                                  % sys.exc_value)
+                                 % exc)
 
     def set_manager(self, manager):
@@ -3372,4 +3373,9 @@
                               path=SPLASH_SCREEN_PATH):
         """Displays the splash screen.  It will exactly cover the main frame."""
+        try:
+            from wx.adv import SplashScreen, SPLASH_TIMEOUT, SPLASH_CENTRE_ON_SCREEN
+        except ImportError:
+            # CRUFT: wx 4 moved SplashScreen from wx to wx.adv
+            from wx import SplashScreen, SPLASH_TIMEOUT, SPLASH_CENTRE_ON_SCREEN
 
         # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
@@ -3388,13 +3394,13 @@
         # Note that on Linux, the timeout appears to occur immediately in which
         # case the splash screen disappears upon entering the event loop.
-        s_screen = wx.SplashScreen(bitmap=bm,
-                                   splashStyle=(wx.SPLASH_TIMEOUT |
-                                                wx.SPLASH_CENTRE_ON_SCREEN),
-                                   style=(wx.SIMPLE_BORDER |
-                                          wx.FRAME_NO_TASKBAR |
-                                          wx.FRAME_FLOAT_ON_PARENT),
-                                   milliseconds=SS_MAX_DISPLAY_TIME,
-                                   parent=parent,
-                                   id=wx.ID_ANY)
+        s_screen = SplashScreen(bitmap=bm,
+                                splashStyle=(SPLASH_TIMEOUT |
+                                             SPLASH_CENTRE_ON_SCREEN),
+                                style=(wx.SIMPLE_BORDER |
+                                       wx.FRAME_NO_TASKBAR |
+                                       wx.FRAME_FLOAT_ON_PARENT),
+                                milliseconds=SS_MAX_DISPLAY_TIME,
+                                parent=parent,
+                                id=wx.ID_ANY)
         from sas.sasgui.guiframe.gui_statusbar import SPageStatusbar
         statusBar = SPageStatusbar(s_screen)
