Index: src/sas/qtgui/Calculators/DataOperationUtilityPanel.py
===================================================================
--- src/sas/qtgui/Calculators/DataOperationUtilityPanel.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Calculators/DataOperationUtilityPanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,6 +4,7 @@
 import copy
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.PlotterData import Data1D
@@ -19,5 +20,5 @@
 
 
-class DataOperationUtilityPanel(QtGui.QDialog, Ui_DataOperationUtility):
+class DataOperationUtilityPanel(QtWidgets.QDialog, Ui_DataOperationUtility):
     def __init__(self, parent=None):
         super(DataOperationUtilityPanel, self).__init__()
@@ -57,7 +58,7 @@
         self.txtNumber.setValidator(QtGui.QDoubleValidator())
 
-        self.layoutOutput = QtGui.QHBoxLayout()
-        self.layoutData1 = QtGui.QHBoxLayout()
-        self.layoutData2 = QtGui.QHBoxLayout()
+        self.layoutOutput = QtWidgets.QHBoxLayout()
+        self.layoutData1 = QtWidgets.QHBoxLayout()
+        self.layoutData2 = QtWidgets.QHBoxLayout()
 
         # Create default layout for initial graphs (when they are still empty)
@@ -383,6 +384,6 @@
     def newPlot(self, graph, layout):
         """ Create template for graphs with default '?' layout"""
-        assert isinstance(graph, QtGui.QGraphicsView)
-        assert isinstance(layout, QtGui.QHBoxLayout)
+        assert isinstance(graph, QtWidgets.QGraphicsView)
+        assert isinstance(layout, QtWidgets.QHBoxLayout)
 
         # clear layout
@@ -399,6 +400,6 @@
         """ plot data in graph after clearing its layout """
 
-        assert isinstance(graph, QtGui.QGraphicsView)
-        assert isinstance(layout, QtGui.QHBoxLayout)
+        assert isinstance(graph, QtWidgets.QGraphicsView)
+        assert isinstance(layout, QtWidgets.QHBoxLayout)
 
         # clear layout
@@ -455,8 +456,8 @@
     def prepareSubgraphWithData(self, data):
         """ Create graphics view containing scene with string """
-        scene = QtGui.QGraphicsScene()
+        scene = QtWidgets.QGraphicsScene()
         scene.addText(str(data))
 
-        subgraph = QtGui.QGraphicsView()
+        subgraph = QtWidgets.QGraphicsView()
         subgraph.setScene(scene)
 
Index: src/sas/qtgui/Calculators/DensityPanel.py
===================================================================
--- src/sas/qtgui/Calculators/DensityPanel.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Calculators/DensityPanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,5 +2,7 @@
 import logging
 import functools
-from PyQt4 import QtGui, QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from periodictable import formula as Formula
@@ -39,5 +41,5 @@
 
 
-class DensityPanel(QtGui.QDialog):
+class DensityPanel(QtWidgets.QDialog):
 
     def __init__(self, parent=None):
@@ -68,6 +70,6 @@
         self.ui.editMassDensity.textEdited.connect(functools.partial(self.setMode, MODES.DENSITY_TO_VOLUME))
 
-        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
-        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
+        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
+        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
 
     def setupModel(self):
@@ -83,5 +85,5 @@
 
     def setupMapper(self):
-        self.mapper = QtGui.QDataWidgetMapper(self)
+        self.mapper = QtWidgets.QDataWidgetMapper(self)
         self.mapper.setModel(self.model)
         self.mapper.setOrientation(QtCore.Qt.Vertical)
@@ -92,5 +94,6 @@
         self.mapper.addMapping(self.ui.editMassDensity     , MODEL.MASS_DENSITY)
 
-        self.mapper.toFirst()
+        # FIXME DOESNT WORK WITH QT5
+        #self.mapper.toFirst()
 
     def dataChanged(self, top, bottom):
Index: src/sas/qtgui/Calculators/GenericScatteringCalculator.py
===================================================================
--- src/sas/qtgui/Calculators/GenericScatteringCalculator.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Calculators/GenericScatteringCalculator.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -5,6 +5,8 @@
 import time
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+
 from twisted.internet import threads
 
@@ -27,5 +29,5 @@
 
 
-class GenericScatteringCalculator(QtGui.QDialog, Ui_GenericScatteringCalculator):
+class GenericScatteringCalculator(QtWidgets.QDialog, Ui_GenericScatteringCalculator):
 
     trigger_plot_3d = QtCore.pyqtSignal()
@@ -129,5 +131,5 @@
         """
         try:
-            self.datafile = QtGui.QFileDialog.getOpenFileName(
+            self.datafile = QtWidgets.QFileDialog.getOpenFileName(
                 self, "Choose a file", "", "All Gen files (*.OMF *.omf) ;;"
                                           "SLD files (*.SLD *.sld);;PDB files (*.pdb *.PDB);; "
@@ -607,7 +609,7 @@
             'directory': default_name,
             'filter': 'SLD file (*.sld)',
-            'options': QtGui.QFileDialog.DontUseNativeDialog}
+            'options': QtWidgets.QFileDialog.DontUseNativeDialog}
         # Query user for filename.
-        filename = str(QtGui.QFileDialog.getSaveFileName(**kwargs))
+        filename = str(QtWidgets.QFileDialog.getSaveFileName(**kwargs))
         if filename:
             try:
@@ -830,8 +832,8 @@
 
 
-class Plotter3D(QtGui.QDialog, Plotter3DWidget):
+class Plotter3D(QtWidgets.QDialog, Plotter3DWidget):
     def __init__(self, parent=None, graph_title=''):
         self.graph_title = graph_title
-        QtGui.QDialog.__init__(self)
+        QtWidgets.QDialog.__init__(self)
         Plotter3DWidget.__init__(self, manager=parent)
         self.setWindowTitle(self.graph_title)
Index: src/sas/qtgui/Calculators/KiessigPanel.py
===================================================================
--- src/sas/qtgui/Calculators/KiessigPanel.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Calculators/KiessigPanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,4 +1,5 @@
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.UI import main_resources_rc
@@ -10,5 +11,5 @@
 
 
-class KiessigPanel(QtGui.QDialog, Ui_KiessigPanel):
+class KiessigPanel(QtWidgets.QDialog, Ui_KiessigPanel):
     def __init__(self, parent=None):
         super(KiessigPanel, self).__init__()
Index: src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py
===================================================================
--- src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,6 +4,7 @@
 instrumental parameters.
 """
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from twisted.internet import threads
@@ -33,5 +34,5 @@
 
 
-class ResolutionCalculatorPanel(QtGui.QDialog, Ui_ResolutionCalculatorPanel):
+class ResolutionCalculatorPanel(QtWidgets.QDialog, Ui_ResolutionCalculatorPanel):
     """
     compute resolution in 2D
@@ -315,8 +316,8 @@
         """ On Spectrum Combobox event"""
         if self.cbCustomSpectrum.currentText() == 'Add New':
-            datafile = QtGui.QFileDialog.getOpenFileName(
+            datafile = QtWidgets.QFileDialog.getOpenFileName(
                 self, "Choose a spectral distribution file", "",
                 "All files (*.*)",
-                QtGui.QFileDialog.DontUseNativeDialog)
+                QtWidgets.QFileDialog.DontUseNativeDialog)
 
             if datafile is None or str(datafile) == '':
@@ -721,5 +722,5 @@
         self.plotter.scale = 'linear'
         self.plotter.cmap = None
-        layout = QtGui.QHBoxLayout()
+        layout = QtWidgets.QHBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
         self.graphicsView.setLayout(layout)
Index: src/sas/qtgui/Calculators/SldPanel.py
===================================================================
--- src/sas/qtgui/Calculators/SldPanel.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Calculators/SldPanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,5 +1,7 @@
 # global
 import logging
-from PyQt4 import QtGui, QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from periodictable import formula as Formula
@@ -97,5 +99,5 @@
 
 
-class SldPanel(QtGui.QDialog):
+class SldPanel(QtWidgets.QDialog):
 
     def __init__(self, parent=None):
@@ -133,6 +135,6 @@
 
         # signals
-        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
-        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
+        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset)
+        self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp)
 
     def setupModel(self):
@@ -145,16 +147,16 @@
             self.model.setItem(key, QtGui.QStandardItem())
 
-        QtCore.QObject.connect(
-            self.model,
-            QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
-            self.dataChanged)
+        self.model.dataChanged.connect(self.dataChanged)
+        #QtCore.QObject.connect(
+        #    self.model,
+        #    QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
+        #    self.dataChanged)
 
         self.modelReset()
 
     def setupMapper(self):
-        self.mapper = QtGui.QDataWidgetMapper(self)
+        self.mapper = QtWidgets.QDataWidgetMapper(self)
         self.mapper.setModel(self.model)
         self.mapper.setOrientation(QtCore.Qt.Vertical)
-
         self.mapper.addMapping(self.ui.editMolecularFormula, MODEL.MOLECULAR_FORMULA)
         self.mapper.addMapping(self.ui.editMassDensity     , MODEL.MASS_DENSITY)
@@ -164,5 +166,6 @@
             self.mapper.addMapping(edit, key)
 
-        self.mapper.toFirst()
+        # FIXME DOESNT WORK WITH QT5
+        #self.mapper.toFirst()
 
     def dataChanged(self, top, bottom):
Index: src/sas/qtgui/Calculators/SlitSizeCalculator.py
===================================================================
--- src/sas/qtgui/Calculators/SlitSizeCalculator.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Calculators/SlitSizeCalculator.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -5,6 +5,7 @@
 import sys
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.UI import main_resources_rc
@@ -16,5 +17,5 @@
 
 
-class SlitSizeCalculator(QtGui.QDialog, Ui_SlitSizeCalculator):
+class SlitSizeCalculator(QtWidgets.QDialog, Ui_SlitSizeCalculator):
     """
     Provides the slit length calculator GUI.
@@ -75,7 +76,8 @@
         # Location is automatically saved - no need to keep track of the last dir
         # But only with Qt built-in dialog (non-platform native)
-        path = QtGui.QFileDialog.getOpenFileName(self, "Choose a file", "",
+        path = QtWidgets.QFileDialog.getOpenFileName(self, "Choose a file", "",
                                                  "SAXSess 1D data (*.txt *.TXT *.dat *.DAT)",
-                                                 QtGui.QFileDialog.DontUseNativeDialog)
+                                                 None,
+                                                 QtWidgets.QFileDialog.DontUseNativeDialog)
 
         if path is None:
Index: src/sas/qtgui/GUITests.py
===================================================================
--- src/sas/qtgui/GUITests.py	(revision d5c5d3dac558e84d4de22e41b9d47bbbcd007de1)
+++ src/sas/qtgui/GUITests.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,8 +1,9 @@
 import unittest
 import sys
-from PyQt4 import QtGui
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # Prepare the general QApplication instance
-app = QtGui.QApplication(sys.argv)
+app = QtWidgets.QApplication(sys.argv)
 
 # Main Window
Index: src/sas/qtgui/MainWindow/AboutBox.py
===================================================================
--- src/sas/qtgui/MainWindow/AboutBox.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/MainWindow/AboutBox.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,4 +1,4 @@
 import functools
-from PyQt4 import QtGui
+from PyQt5 import QtWidgets
 
 import sas.sasview
@@ -10,5 +10,5 @@
 from .UI.AboutUI import Ui_AboutUI
 
-class AboutBox(QtGui.QDialog, Ui_AboutUI):
+class AboutBox(QtWidgets.QDialog, Ui_AboutUI):
     def __init__(self, parent=None):
         super(AboutBox, self).__init__(parent)
Index: src/sas/qtgui/MainWindow/DataExplorer.py
===================================================================
--- src/sas/qtgui/MainWindow/DataExplorer.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/MainWindow/DataExplorer.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -5,8 +5,8 @@
 import logging
 
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
-from PyQt4.Qt import QMutex
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+from PyQt5 import QtWebKitWidgets
 
 from twisted.internet import threads
@@ -48,8 +48,8 @@
         self.loader = Loader()
         self.manager = manager if manager is not None else DataManager()
-        self.txt_widget = QtGui.QTextEdit(None)
+        self.txt_widget = QtWidgets.QTextEdit(None)
 
         # Be careful with twisted threads.
-        self.mutex = QMutex()
+        self.mutex = QtCore.QMutex()
 
         # Active plots
@@ -69,5 +69,5 @@
 
         # Display HTML content
-        self._helpView = QtWebKit.QWebView()
+        self._helpView = QtWebKitWidgets.QWebView()
 
         # Fill in the perspectives combo
@@ -98,5 +98,5 @@
 
         # Proxy model for showing a subset of Data1D/Data2D content
-        self.data_proxy = QtGui.QSortFilterProxyModel(self)
+        self.data_proxy = QtCore.QSortFilterProxyModel(self)
         self.data_proxy.setSourceModel(self.model)
 
@@ -108,5 +108,5 @@
 
         # Proxy model for showing a subset of Theory content
-        self.theory_proxy = QtGui.QSortFilterProxyModel(self)
+        self.theory_proxy = QtCore.QSortFilterProxyModel(self)
         self.theory_proxy.setSourceModel(self.theory_model)
 
@@ -182,4 +182,5 @@
         Opens the Qt "Open File..." dialog
         """
+        print("A")
         path_str = self.chooseFiles()
         if not path_str:
@@ -192,6 +193,6 @@
         Opens the Qt "Open Folder..." dialog
         """
-        folder = QtGui.QFileDialog.getExistingDirectory(self, "Choose a directory", "",
-              QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
+        folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Choose a directory", "", None,
+              QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
         if folder is None:
             return
@@ -216,11 +217,17 @@
             'caption'   : 'Open Project',
             'filter'    : 'Project (*.json);;All files (*.*)',
-            'options'   : QtGui.QFileDialog.DontUseNativeDialog
+            'options'   : QtWidgets.QFileDialog.DontUseNativeDialog
         }
-        filename = str(QtGui.QFileDialog.getOpenFileName(**kwargs))
+        filename = str(QtWidgets.QFileDialog.getOpenFileName(**kwargs))
         if filename:
             load_thread = threads.deferToThread(self.readProject, filename)
             load_thread.addCallback(self.readProjectComplete)
             load_thread.addErrback(self.readProjectFailed)
+
+    def loadFailed(self, reason):
+        """
+        """
+        print("file load FAILED: ", reason)
+        pass
 
     def readProjectFailed(self, reason):
@@ -248,8 +255,9 @@
 
         self.manager.assign(manager)
+        self.model.beginResetModel()
         for id, item in self.manager.get_all_data().items():
             self.updateModel(item.data, item.path)
 
-        self.model.reset()
+        self.model.endResetModel()
 
     def saveProject(self):
@@ -261,7 +269,7 @@
             'caption'   : 'Save Project',
             'filter'    : 'Project (*.json)',
-            'options'   : QtGui.QFileDialog.DontUseNativeDialog
+            'options'   : QtWidgets.QFileDialog.DontUseNativeDialog
         }
-        filename = str(QtGui.QFileDialog.getSaveFileName(**kwargs))
+        filename = str(QtWidgets.QFileDialog.getSaveFileName(**kwargs))
         if filename:
             self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename))
@@ -617,6 +625,6 @@
         # Location is automatically saved - no need to keep track of the last dir
         # But only with Qt built-in dialog (non-platform native)
-        paths = QtGui.QFileDialog.getOpenFileNames(self, "Choose a file", "",
-                wlist, QtGui.QFileDialog.DontUseNativeDialog)
+        paths = QtWidgets.QFileDialog.getOpenFileNames(self, "Choose a file", "",
+                wlist, None, QtWidgets.QFileDialog.DontUseNativeDialog)
         if paths is None:
             return
@@ -835,5 +843,5 @@
         """
         # Create a custom menu based on actions defined in the UI file
-        self.context_menu = QtGui.QMenu(self)
+        self.context_menu = QtWidgets.QMenu(self)
         self.context_menu.addAction(self.actionDataInfo)
         self.context_menu.addAction(self.actionSaveAs)
@@ -1071,5 +1079,6 @@
         # If so, delete them
         # TODO: fix this to resemble GuiUtils.updateModelItemWithPlot
-        # 
+        #
+        self.model.beginResetModel()
         current_tab_name = model_item.text()[:2]
         for current_index in range(self.theory_model.rowCount()):
@@ -1079,5 +1088,5 @@
 
         # Reset the view
-        self.model.reset()
+        self.model.endResetModel()
 
         # Reset the view
Index: src/sas/qtgui/MainWindow/DroppableDataLoadWidget.py
===================================================================
--- src/sas/qtgui/MainWindow/DroppableDataLoadWidget.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/MainWindow/DroppableDataLoadWidget.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,4 +1,6 @@
 # global
-from PyQt4 import QtGui, QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # UI
@@ -6,5 +8,5 @@
 from sas.qtgui.MainWindow.UI.DataExplorerUI import Ui_DataLoadWidget
 
-class DroppableDataLoadWidget(QtGui.QTabWidget, Ui_DataLoadWidget):
+class DroppableDataLoadWidget(QtWidgets.QTabWidget, Ui_DataLoadWidget):
     """
     Overwrite drag and drop methods in the base class
Index: src/sas/qtgui/MainWindow/GuiManager.py
===================================================================
--- src/sas/qtgui/MainWindow/GuiManager.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/MainWindow/GuiManager.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -6,7 +6,8 @@
 import webbrowser
 
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
+from PyQt5.QtWidgets import *
+from PyQt5.QtGui import *
+from PyQt5.QtCore import Qt
+from PyQt5.QtWebKitWidgets import QWebView
 
 from twisted.internet import reactor
@@ -38,7 +39,7 @@
 from sas.qtgui.MainWindow.DataExplorer import DataExplorerWindow
 
-class Acknowledgements(QtGui.QDialog, Ui_Acknowledgements):
+class Acknowledgements(QDialog, Ui_Acknowledgements):
     def __init__(self, parent=None):
-        QtGui.QDialog.__init__(self, parent)
+        QDialog.__init__(self, parent)
         self.setupUi(self)
 
@@ -77,5 +78,4 @@
         # Invoke the initial perspective
         self.perspectiveChanged("Fitting")
-
         self.addWidgets()
 
@@ -94,8 +94,8 @@
         # Show the Welcome panel
         self.welcomePanel = WelcomePanel()
-        self._workspace.workspace.addWindow(self.welcomePanel)
+        self._workspace.workspace.addSubWindow(self.welcomePanel)
 
         # Current help file
-        self._helpView = QtWebKit.QWebView()
+        self._helpView = QWebView()
         # Needs URL like path, so no path.join() here
         self._helpLocation = GuiUtils.HELP_DIRECTORY_LOCATION + "/index.html"
@@ -116,19 +116,21 @@
         ObjectLibrary.addObject('DataExplorer', self.filesWidget)
 
-        self.dockedFilesWidget = QtGui.QDockWidget("Data Explorer", self._workspace)
+        self.dockedFilesWidget = QDockWidget("Data Explorer", self._workspace)
+        self.dockedFilesWidget.setFloating(True)
         self.dockedFilesWidget.setWidget(self.filesWidget)
 
         # Disable maximize/minimize and close buttons
-        self.dockedFilesWidget.setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures)
-        self._workspace.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
-                                      self.dockedFilesWidget)
+        self.dockedFilesWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
+        self.dockedFilesWidget.setFeatures(Qt.LeftDockWidgetArea)
+
+        self._workspace.workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget)
 
         # Add the console window as another docked widget
-        self.logDockWidget = QtGui.QDockWidget("Log Explorer", self._workspace)
+        self.logDockWidget = QDockWidget("Log Explorer", self._workspace)
         self.logDockWidget.setObjectName("LogDockWidget")
-        self.listWidget = QtGui.QTextBrowser()
+
+        self.listWidget = QTextBrowser()
         self.logDockWidget.setWidget(self.listWidget)
-        self._workspace.addDockWidget(QtCore.Qt.BottomDockWidgetArea,
-                                      self.logDockWidget)
+        self._workspace.workspace.addDockWidget(Qt.BottomDockWidgetAre, self.logDockWidget) 
 
         # Add other, minor widgets
@@ -152,8 +154,8 @@
         Progress bar invisible until explicitly shown
         """
-        self.progress = QtGui.QProgressBar()
+        self.progress = QProgressBar()
         self._workspace.statusbar.setSizeGripEnabled(False)
 
-        self.statusLabel = QtGui.QLabel()
+        self.statusLabel = QLabel()
         self.statusLabel.setText("Welcome to SasView")
         self._workspace.statusbar.addPermanentWidget(self.statusLabel, 1)
@@ -187,5 +189,6 @@
         self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](parent=self)
 
-        self._workspace.workspace.addWindow(self._current_perspective)
+        self._workspace.workspace.addSubWindow(self._current_perspective)
+
         # Resize to the workspace height
         workspace_height = self._workspace.workspace.sizeHint().height()
@@ -257,13 +260,13 @@
         # Display confirmation messagebox
         quit_msg = "Are you sure you want to exit the application?"
-        reply = QtGui.QMessageBox.question(
+        reply = QMessageBox.question(
             self._parent,
             'Information',
             quit_msg,
-            QtGui.QMessageBox.Yes,
-            QtGui.QMessageBox.No)
+            QMessageBox.Yes,
+            QMessageBox.No)
 
         # Exit if yes
-        if reply == QtGui.QMessageBox.Yes:
+        if reply == QMessageBox.Yes:
             reactor.callFromThread(reactor.stop)
             return True
@@ -578,9 +581,8 @@
 
         # Add the console window as another docked widget
-        self.ipDockWidget = QtGui.QDockWidget("IPython", self._workspace)
+        self.ipDockWidget = QDockWidget("IPython", self._workspace)
         self.ipDockWidget.setObjectName("IPythonDockWidget")
         self.ipDockWidget.setWidget(terminal)
-        self._workspace.addDockWidget(QtCore.Qt.RightDockWidgetArea,
-                                      self.ipDockWidget)
+        self._workspace.workspace.addSubWindow(self.ipDockWidget, Qt.RightDockWidgetArea)
 
     def actionImage_Viewer(self):
@@ -695,5 +697,5 @@
         TODO: use QNetworkAccessManager to assure _helpLocation is valid
         """
-        self._helpView.load(QtCore.QUrl(self._helpLocation))
+        self._helpView.load(QUrl(self._helpLocation))
         self._helpView.show()
 
@@ -740,5 +742,5 @@
         :param new_datalist_item:
         """
-        if not isinstance(new_item, QtGui.QStandardItem) or \
+        if not isinstance(new_item, QStandardItem) or \
                 not isinstance(new_datalist_item, dict):
             msg = "Wrong data type returned from calculations."
Index: src/sas/qtgui/MainWindow/MainWindow.py
===================================================================
--- src/sas/qtgui/MainWindow/MainWindow.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/MainWindow/MainWindow.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,5 +1,7 @@
 # UNLESS EXEPTIONALLY REQUIRED TRY TO AVOID IMPORTING ANY MODULES HERE
 # ESPECIALLY ANYTHING IN SAS, SASMODELS NAMESPACE
-from PyQt4 import QtGui
+#from PyQt4 import QtGui
+from PyQt5.QtWidgets import *
+from PyQt5.QtGui import *
 
 # Local UI
@@ -10,5 +12,5 @@
 import sas.qtgui.Utilities.SasviewLogger
 
-class MainSasViewWindow(QtGui.QMainWindow, Ui_MainWindow):
+class MainSasViewWindow(QMainWindow, Ui_MainWindow):
     # Main window of the application
     def __init__(self, parent=None):
@@ -17,10 +19,13 @@
 
         # define workspace for dialogs.
-        self.workspace = QtGui.QWorkspace(self)
+        self.workspace = QMdiArea(self)
         self.setCentralWidget(self.workspace)
 
         # Create the gui manager
         from .GuiManager import GuiManager
-        self.guiManager = GuiManager(self)
+        try:
+            self.guiManager = GuiManager(self)
+        except Exception as ex:
+            print("EXCEPTION: ", ex)
 
     def closeEvent(self, event):
@@ -37,10 +42,10 @@
     """
     # TODO: standardize path to images
-    pixmap = QtGui.QPixmap("src/sas/qtgui/images/SVwelcome_mini.png")
-    splashScreen = QtGui.QSplashScreen(pixmap)
+    pixmap = QPixmap("src/sas/qtgui/images/SVwelcome_mini.png")
+    splashScreen = QSplashScreen(pixmap)
     return splashScreen
 
 def run():
-    app = QtGui.QApplication([])
+    app = QApplication([])
 
     # Main must have reference to the splash screen, so making it explicit
@@ -55,7 +60,7 @@
     # DO NOT move the following import to the top!
     # (unless you know what you're doing)
-    import qt4reactor
+    import qt5reactor
     # Using the Qt4 reactor wrapper from https://github.com/ghtdak/qtreactor
-    qt4reactor.install()
+    qt5reactor.install()
 
     # DO NOT move the following import to the top!
Index: src/sas/qtgui/MainWindow/WelcomePanel.py
===================================================================
--- src/sas/qtgui/MainWindow/WelcomePanel.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/MainWindow/WelcomePanel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,7 +2,6 @@
 import sys
 import os
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
+
+from PyQt5 import QtWidgets
 
 import sas.sasview
@@ -13,5 +12,5 @@
 from sas.qtgui.MainWindow.UI.WelcomePanelUI import Ui_WelcomePanelUI
 
-class WelcomePanel(QtGui.QDialog, Ui_WelcomePanelUI):
+class WelcomePanel(QtWidgets.QDialog, Ui_WelcomePanelUI):
     def __init__(self, parent=None):
         super(WelcomePanel, self).__init__(parent)
Index: src/sas/qtgui/Perspectives/Fitting/FittingOptions.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingOptions.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Perspectives/Fitting/FittingOptions.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,7 +4,8 @@
 import types
 
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+from PyQt5 import QtWebKitWidgets
 
 from sas.qtgui.UI import images_rc
@@ -21,5 +22,5 @@
 
 
-class FittingOptions(QtGui.QDialog, Ui_FittingOptions):
+class FittingOptions(QtWidgets.QDialog, Ui_FittingOptions):
     """
     Hard-coded version of the fit options dialog available from BUMPS.
@@ -52,7 +53,7 @@
 
         # Handle the Apply button click
-        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).clicked.connect(self.onApply)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.onApply)
         # handle the Help button click
-        self.buttonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self.onHelp)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.onHelp)
 
         # Handle the combo box changes
@@ -71,8 +72,8 @@
 
         # OK has to be initialized to True, after initial validator setup
-        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
 
         # Display HTML content
-        self.helpView = QtWebKit.QWebView()
+        self.helpView = QtWebKitWidgets.QWebView()
 
     def assignValidators(self):
@@ -104,8 +105,8 @@
         if state == QtGui.QValidator.Acceptable:
             color = '' # default
-            self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
+            self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
         else:
             color = '#fff79a' # yellow
-            self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
+            self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False)
 
         sender.setStyleSheet('QLineEdit { background-color: %s }' % color)
@@ -134,5 +135,5 @@
 
         # OK has to be reinitialized to True
-        self.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True)
 
     def onApply(self):
@@ -148,5 +149,5 @@
             """
             widget = self.widgetFromOption(option)
-            new_value = widget.currentText() if isinstance(widget, QtGui.QComboBox) \
+            new_value = widget.currentText() if isinstance(widget, QtWidgets.QComboBox) \
                 else float(widget.text())
             self.config.values[self.current_fitter_id][option] = new_value
Index: src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,6 +1,7 @@
 import numpy
 
-from PyQt4 import QtCore
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from bumps import options
@@ -13,9 +14,10 @@
 #from sas.qtgui.Perspectives.Fitting import ModelUtilities
 
-class FittingWindow(QtGui.QTabWidget):
+class FittingWindow(QtWidgets.QTabWidget):
     """
     """
     name = "Fitting" # For displaying in the combo box in DataExplorer
     def __init__(self, parent=None, data=None):
+
         super(FittingWindow, self).__init__()
 
Index: src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,6 +1,7 @@
 from copy import deepcopy
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 import numpy
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -9,7 +9,8 @@
 import numpy as np
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
-from PyQt4 import QtWebKit
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+from PyQt5 import QtWebKitWidgets
 
 from sasmodels import generate
@@ -73,5 +74,5 @@
         return QtGui.QStandardItemModel.headerData(self, section, orientation, role)
 
-class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI):
+class FittingWidget(QtWidgets.QWidget, Ui_FittingWidgetUI):
     """
     Main widget for selecting form and structure factor models
@@ -120,5 +121,5 @@
 
         # Display HTML content
-        self.helpView = QtWebKit.QWebView()
+        self.helpView = QtWebKitWidgets.QWebView()
 
         # New font to display angstrom symbol
@@ -228,5 +229,5 @@
         """
         # Options widget
-        layout = QtGui.QGridLayout()
+        layout = QtWidgets.QGridLayout()
         self.options_widget = OptionsWidget(self, self.logic)
         layout.addWidget(self.options_widget)
@@ -234,5 +235,5 @@
 
         # Smearing widget
-        layout = QtGui.QGridLayout()
+        layout = QtWidgets.QGridLayout()
         self.smearing_widget = SmearingWidget(self)
         layout.addWidget(self.smearing_widget)
@@ -249,6 +250,6 @@
 
         # Magnetic angles explained in one picture
-        self.magneticAnglesWidget = QtGui.QWidget()
-        labl = QtGui.QLabel(self.magneticAnglesWidget)
+        self.magneticAnglesWidget = QtWidgets.QWidget()
+        labl = QtWidgets.QLabel(self.magneticAnglesWidget)
         pixmap = QtGui.QPixmap(GuiUtils.IMAGES_DIRECTORY_LOCATION + '/M_angles_pic.bmp')
         labl.setPixmap(pixmap)
@@ -269,4 +270,5 @@
         self.lstParams.setModel(self._model_model)
         self.readCategoryInfo()
+
         self.model_parameters = None
 
@@ -302,5 +304,4 @@
         self.lstParams.customContextMenuRequested.connect(self.showModelDescription)
         self.lstParams.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False)
-
         # Poly model displayed in poly list
         self.lstPoly.setModel(self._poly_model)
@@ -460,6 +461,6 @@
             msg += "You must select a model to get information on this"
 
-        menu = QtGui.QMenu()
-        label = QtGui.QLabel(msg)
+        menu = QtWidgets.QMenu()
+        label = QtWidgets.QLabel(msg)
         action = QtGui.QWidgetAction(self)
         action.setDefaultWidget(label)
@@ -909,5 +910,5 @@
         self.lstParams.resizeColumnToContents(4)
         self.lstParams.resizeColumnToContents(5)
-        self.lstParams.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding)
+        self.lstParams.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
 
         self.has_error_column = True
@@ -1224,5 +1225,5 @@
         # Adjust the table cells width
         self.lstParams.resizeColumnToContents(0)
-        self.lstParams.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding)
+        self.lstParams.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
 
         # Now we claim the model has been loaded
@@ -1527,16 +1528,17 @@
         table.verticalHeader().setVisible(False)
         table.setAlternatingRowColors(True)
-        table.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding)
-        table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+        table.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
+        table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
         table.resizeColumnsToContents()
 
         # Header
         header = table.horizontalHeader()
-        header.setResizeMode(QtGui.QHeaderView.ResizeToContents)
-
-        header.ResizeMode(QtGui.QHeaderView.Interactive)
+        header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
+        header.ResizeMode(QtWidgets.QHeaderView.Interactive)
+
+        # Qt5: the following 2 lines crash - figure out why!
         # Resize column 0 and 7 to content
-        header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents)
-        header.setResizeMode(7, QtGui.QHeaderView.ResizeToContents)
+        #header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
+        #header.setSectionResizeMode(7, QtWidgets.QHeaderView.ResizeToContents)
 
     def setPolyModel(self):
@@ -1591,5 +1593,5 @@
 
         # All possible polydisp. functions as strings in combobox
-        func = QtGui.QComboBox()
+        func = QtWidgets.QComboBox()
         func.addItems([str(name_disp) for name_disp in POLYDISPERSITY_MODELS.keys()])
         # Set the default index
@@ -1674,7 +1676,7 @@
         Show the load file dialog and loads requested data into state
         """
-        datafile = QtGui.QFileDialog.getOpenFileName(
-            self, "Choose a weight file", "", "All files (*.*)",
-            QtGui.QFileDialog.DontUseNativeDialog)
+        datafile = QtWidgets.QFileDialog.getOpenFileName(
+            self, "Choose a weight file", "", "All files (*.*)", None,
+            QtWidgets.QFileDialog.DontUseNativeDialog)
 
         if datafile is None or str(datafile)=='':
@@ -1775,5 +1777,5 @@
         item1 = QtGui.QStandardItem(param_name)
 
-        func = QtGui.QComboBox()
+        func = QtWidgets.QComboBox()
         # Available range of shells displayed in the combobox
         func.addItems([str(i) for i in range(param_length+1)])
Index: src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -3,6 +3,7 @@
 """
 import numpy as np
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.PlotterData import Data2D
@@ -21,5 +22,5 @@
     'LOG_SPACED']
 
-class DataWidgetMapper(QtGui.QDataWidgetMapper):
+class DataWidgetMapper(QtWidgets.QDataWidgetMapper):
     """
     Custom version of the standard QDataWidgetMapper allowing for proper
@@ -32,13 +33,13 @@
             super(DataWidgetMapper, self).addMapping(widget, section, propertyName)
 
-        if isinstance(widget, QtGui.QComboBox):
+        if isinstance(widget, QtWidgets.QComboBox):
             delegate = self.itemDelegate()
             widget.currentIndexChanged.connect(lambda: delegate.commitData.emit(widget))
 
-        elif isinstance(widget, QtGui.QCheckBox):
+        elif isinstance(widget, QtWidgets.QCheckBox):
             delegate = self.itemDelegate()
             widget.stateChanged.connect(lambda: delegate.commitData.emit(widget))
 
-class OptionsWidget(QtGui.QWidget, Ui_tabOptions):
+class OptionsWidget(QtWidgets.QWidget, Ui_tabOptions):
     plot_signal = QtCore.pyqtSignal()
     def __init__(self, parent=None, logic=None):
@@ -52,5 +53,5 @@
 
         # Weight radio box group
-        self.weightingGroup = QtGui.QButtonGroup()
+        self.weightingGroup = QtWidgets.QButtonGroup()
         self.weighting = 0
 
@@ -114,5 +115,6 @@
         self.mapper.addMapping(self.txtNpts,     MODEL.index('NPTS'))
         self.mapper.addMapping(self.chkLogData,  MODEL.index('LOG_SPACED'))
-        self.mapper.toFirst()
+        # FIXME DOESNT WORK WITH QT5
+        #self.mapper.toFirst()
 
     def toggleLogData(self, isChecked):
Index: src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,6 +2,7 @@
 Widget/logic for smearing data.
 """
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.PlotterData import Data1D
@@ -11,5 +12,5 @@
 from sas.qtgui.Perspectives.Fitting.UI.SmearingWidgetUI import Ui_SmearingWidgetUI
 
-class DataWidgetMapper(QtGui.QDataWidgetMapper):
+class DataWidgetMapper(QtWidgets.QDataWidgetMapper):
     """
     Custom version of the standard QDataWidgetMapper allowing for proper
@@ -22,5 +23,5 @@
             super(DataWidgetMapper, self).addMapping(widget, section, propertyName)
 
-        if isinstance(widget, QtGui.QComboBox):
+        if isinstance(widget, QtWidgets.QComboBox):
             delegate = self.itemDelegate()
             widget.currentIndexChanged.connect(lambda: delegate.commitData.emit(widget))
@@ -35,5 +36,5 @@
     'ACCURACY']
 
-class SmearingWidget(QtGui.QWidget, Ui_SmearingWidgetUI):
+class SmearingWidget(QtWidgets.QWidget, Ui_SmearingWidgetUI):
     def __init__(self, parent=None):
         super(SmearingWidget, self).__init__()
@@ -83,5 +84,7 @@
         self.mapper.addMapping(self.cbSmearing,   MODEL.index('SMEARING'))
         self.mapper.addMapping(self.cbAccuracy,   MODEL.index('ACCURACY'))
-        self.mapper.toFirst()
+
+        # FIXME DOESNT WORK WITH QT5
+        #self.mapper.toFirst()
 
     def updateSmearing(self, data=None):
Index: src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py	(revision 7ffa5ee9a77203192f99f6d0097da50e4a8e1207)
+++ src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,8 +1,9 @@
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 import sas.qtgui.Utilities.GuiUtils as GuiUtils
 
-class ModelViewDelegate(QtGui.QStyledItemDelegate):
+class ModelViewDelegate(QtWidgets.QStyledItemDelegate):
     """
     Custom delegate for appearance and behavior control of the model view
@@ -12,5 +13,5 @@
         Overwrite generic constructor to allow for some globals
         """
-        super(QtGui.QStyledItemDelegate, self).__init__()
+        super(QtWidgets.QStyledItemDelegate, self).__init__()
 
         # Main parameter table view columns
@@ -43,5 +44,6 @@
         if index.column() in self.fancyColumns():
             # Units - present in nice HTML
-            options = QtGui.QStyleOptionViewItemV4(option)
+            #options = QtWidgets.QStyleOptionViewItemV4(option)
+            options = QtWidgets.QStyleOptionViewItem(option)
             self.initStyleOption(options,index)
 
@@ -57,8 +59,8 @@
             # delete the original content
             options.text = ""
-            style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter, options.widget);
+            style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter, options.widget);
 
             context = QtGui.QAbstractTextDocumentLayout.PaintContext()
-            textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options)
+            textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options)
 
             painter.save()
@@ -70,5 +72,5 @@
         else:
             # Just the default paint
-            QtGui.QStyledItemDelegate.paint(self, painter, option, index)
+            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
 
     def createEditor(self, widget, option, index):
@@ -79,5 +81,5 @@
             return 0
         if index.column() == self.param_value: #only in the value column
-            editor = QtGui.QLineEdit(widget)
+            editor = QtWidgets.QLineEdit(widget)
             validator = QtGui.QDoubleValidator()
             editor.setValidator(validator)
@@ -100,8 +102,8 @@
                 # balloon popup? tooltip? cell background colour flash?
                 return
-        QtGui.QStyledItemDelegate.setModelData(self, editor, model, index)
-
-
-class PolyViewDelegate(QtGui.QStyledItemDelegate):
+        QtWidgets.QStyledItemDelegate.setModelData(self, editor, model, index)
+
+
+class PolyViewDelegate(QtWidgets.QStyledItemDelegate):
     """
     Custom delegate for appearance and behavior control of the polydispersity view
@@ -116,5 +118,5 @@
         Overwrite generic constructor to allow for some globals
         """
-        super(QtGui.QStyledItemDelegate, self).__init__()
+        super(QtWidgets.QStyledItemDelegate, self).__init__()
 
         self.poly_parameter = 0
@@ -160,10 +162,10 @@
             return None
         elif index.column() in self.editableParameters():
-            self.editor = QtGui.QLineEdit(widget)
+            self.editor = QtWidgets.QLineEdit(widget)
             validator = QtGui.QDoubleValidator()
             self.editor.setValidator(validator)
             return self.editor
         else:
-            QtGui.QStyledItemDelegate.createEditor(self, widget, option, index)
+            QtWidgets.QStyledItemDelegate.createEditor(self, widget, option, index)
 
     def paint(self, painter, option, index):
@@ -173,5 +175,5 @@
         if index.column() in (self.poly_min, self.poly_max):
             # Units - present in nice HTML
-            options = QtGui.QStyleOptionViewItemV4(option)
+            options = QtWidgets.QStyleOptionViewItem(option)
             self.initStyleOption(options,index)
 
@@ -187,8 +189,8 @@
             # delete the original content
             options.text = ""
-            style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter, options.widget);
+            style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter, options.widget);
 
             context = QtGui.QAbstractTextDocumentLayout.PaintContext()
-            textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options)
+            textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options)
 
             painter.save()
@@ -200,7 +202,7 @@
         else:
             # Just the default paint
-            QtGui.QStyledItemDelegate.paint(self, painter, option, index)
-
-class MagnetismViewDelegate(QtGui.QStyledItemDelegate):
+            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
+
+class MagnetismViewDelegate(QtWidgets.QStyledItemDelegate):
     """
     Custom delegate for appearance and behavior control of the magnetism view
@@ -210,5 +212,5 @@
         Overwrite generic constructor to allow for some globals
         """
-        super(QtGui.QStyledItemDelegate, self).__init__()
+        super(QtWidgets.QStyledItemDelegate, self).__init__()
 
         self.mag_parameter = 0
@@ -238,10 +240,10 @@
             return 0
         if index.column() in self.editableParameters():
-            editor = QtGui.QLineEdit(widget)
+            editor = QtWidgets.QLineEdit(widget)
             validator = QtGui.QDoubleValidator()
             editor.setValidator(validator)
             return editor
         else:
-            QtGui.QStyledItemDelegate.createEditor(self, widget, option, index)
+            QtWidgets.QStyledItemDelegate.createEditor(self, widget, option, index)
 
     def paint(self, painter, option, index):
@@ -251,5 +253,5 @@
         if index.column() in (self.mag_min, self.mag_max, self.mag_unit):
             # Units - present in nice HTML
-            options = QtGui.QStyleOptionViewItemV4(option)
+            options = QtWidgets.QStyleOptionViewItem(option)
             self.initStyleOption(options,index)
 
@@ -265,8 +267,8 @@
             # delete the original content
             options.text = ""
-            style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter, options.widget);
+            style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter, options.widget);
 
             context = QtGui.QAbstractTextDocumentLayout.PaintContext()
-            textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options)
+            textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options)
 
             painter.save()
@@ -278,3 +280,3 @@
         else:
             # Just the default paint
-            QtGui.QStyledItemDelegate.paint(self, painter, option, index)
+            QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
Index: src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py
===================================================================
--- src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,6 +1,7 @@
 import sys
 import os
-from PyQt4 import QtCore
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # local
@@ -8,5 +9,5 @@
 from .InvariantUtils import WIDGETS
 
-class DetailsDialog(QtGui.QDialog, Ui_Dialog):
+class DetailsDialog(QtWidgets.QDialog, Ui_Dialog):
     """
     """
Index: src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,7 +2,8 @@
 import sys
 import os
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-from PyQt4 import QtWebKit
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+from PyQt5 import QtWebKitWidgets
 
 from twisted.internet import threads
@@ -35,5 +36,5 @@
         self._model.appendRow(item)
 
-class InvariantWindow(QtGui.QDialog, Ui_tabbedInvariantUI):
+class InvariantWindow(QtWidgets.QDialog, Ui_tabbedInvariantUI):
     # The controller which is responsible for managing signal slots connections
     # for the gui and providing an interface to the data model.
@@ -61,5 +62,5 @@
         self._model_item = QtGui.QStandardItem()
 
-        self._helpView = QtWebKit.QWebView()
+        self._helpView = QtWebKitWidgets.QWebView()
         self.detailsDialog = DetailsDialog(self)
 
@@ -502,5 +503,5 @@
     def setupMapper(self):
         # Set up the mapper.
-        self.mapper = QtGui.QDataWidgetMapper(self)
+        self.mapper = QtWidgets.QDataWidgetMapper(self)
         self.mapper.setOrientation(QtCore.Qt.Vertical)
         self.mapper.setModel(self.model)
@@ -543,5 +544,6 @@
         self.mapper.addMapping(self.lineEdit_18, WIDGETS.W_INVARIANT_ERR)
 
-        self.mapper.toFirst()
+        # FIXME DOESNT WORK WITH QT5
+        #self.mapper.toFirst()
 
     def setData(self, data_item, is_batch=False):
@@ -644,13 +646,2 @@
         """
         return False
-
-if __name__ == "__main__":
-    app = QtGui.QApplication([])
-    import qt4reactor
-    qt4reactor.install()
-    # DO NOT move the following import to the top!
-    # (unless you know what you're doing)
-    from twisted.internet import reactor
-    dlg = InvariantWindow(reactor)
-    dlg.show()
-    reactor.run()
Index: src/sas/qtgui/Plotting/AddText.py
===================================================================
--- src/sas/qtgui/Plotting/AddText.py	(revision 83eb5208b8acb86b064162274de583670f72da47)
+++ src/sas/qtgui/Plotting/AddText.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,3 +1,5 @@
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 import sas.sasview
@@ -5,5 +7,5 @@
 from sas.qtgui.Plotting.UI.AddTextUI import Ui_AddText
 
-class AddText(QtGui.QDialog, Ui_AddText):
+class AddText(QtWidgets.QDialog, Ui_AddText):
     """ Simple GUI for a single line text query """
     def __init__(self, parent=None):
Index: src/sas/qtgui/Plotting/BoxSum.py
===================================================================
--- src/sas/qtgui/Plotting/BoxSum.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/Plotting/BoxSum.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,6 +2,7 @@
 Allows users to modify the box slicer parameters.
 """
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # Local UI
@@ -9,5 +10,5 @@
 from sas.qtgui.Plotting.UI.BoxSumUI import Ui_BoxSumUI
 
-class BoxSum(QtGui.QDialog, Ui_BoxSumUI):
+class BoxSum(QtWidgets.QDialog, Ui_BoxSumUI):
     apply_signal = QtCore.pyqtSignal(tuple, str)
     def __init__(self, parent=None, model=None):
Index: src/sas/qtgui/Plotting/ColorMap.py
===================================================================
--- src/sas/qtgui/Plotting/ColorMap.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Plotting/ColorMap.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,6 +2,7 @@
 Allows users to change the range of the current graph
 """
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 import sas.qtgui.path_prepare
 
@@ -10,5 +11,5 @@
 import numpy
 
-from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
 from sas.qtgui.Plotting.PlotterData import Data2D
 from sas.qtgui.Utilities.GuiUtils import formatNumber
@@ -21,5 +22,5 @@
 from sas.qtgui.Plotting.UI.ColorMapUI import Ui_ColorMapUI
 
-class ColorMap(QtGui.QDialog, Ui_ColorMapUI):
+class ColorMap(QtWidgets.QDialog, Ui_ColorMapUI):
     apply_signal = QtCore.pyqtSignal(tuple, str)
     def __init__(self, parent=None, cmap=None, vmin=0.0, vmax=100.0, data=None):
@@ -71,8 +72,8 @@
 
         # Handle the Reset button click
-        self.buttonBox.button(QtGui.QDialogButtonBox.Reset).clicked.connect(self.onReset)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.onReset)
 
         # Handle the Apply button click
-        self.buttonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self.onApply)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self.onApply)
 
         # Handle the amplitude setup
@@ -161,5 +162,5 @@
         self.slider.setOrientation(QtCore.Qt.Horizontal)
 
-        self.slider_label = QtGui.QLabel()
+        self.slider_label = QtWidgets.QLabel()
         self.slider_label.setText("Drag the sliders to adjust color range.")
 
@@ -192,5 +193,5 @@
         self.canvas = FigureCanvas(self.fig)
 
-        layout = QtGui.QVBoxLayout()
+        layout = QtWidgets.QVBoxLayout()
         layout.addWidget(self.slider_label)
         layout.addWidget(self.slider)
Index: src/sas/qtgui/Plotting/LinearFit.py
===================================================================
--- src/sas/qtgui/Plotting/LinearFit.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Plotting/LinearFit.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,6 +4,7 @@
 import re
 import numpy
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Utilities.GuiUtils import formatNumber
@@ -17,5 +18,5 @@
 from sas.qtgui.Plotting.UI.LinearFitUI import Ui_LinearFitUI
 
-class LinearFit(QtGui.QDialog, Ui_LinearFitUI):
+class LinearFit(QtWidgets.QDialog, Ui_LinearFitUI):
     def __init__(self, parent=None,
                  data=None,
Index: src/sas/qtgui/Plotting/MaskEditor.py
===================================================================
--- src/sas/qtgui/Plotting/MaskEditor.py	(revision dc5ef150e8b37e01a3b7e253eb5b66d3b82de99c)
+++ src/sas/qtgui/Plotting/MaskEditor.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,3 +1,5 @@
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.PlotterData import Data2D
@@ -8,5 +10,5 @@
 from sas.qtgui.Plotting.Plotter2D import Plotter2DWidget
 
-class MaskEditor(QtGui.QDialog, Ui_MaskEditorUI):
+class MaskEditor(QtWidgets.QDialog, Ui_MaskEditorUI):
     def __init__(self, parent=None, data=None):
         super(MaskEditor, self).__init__()
@@ -23,5 +25,5 @@
         self.plotter.data = self.data
 
-        layout = QtGui.QHBoxLayout()
+        layout = QtWidgets.QHBoxLayout()
         layout.setContentsMargins(0, 0, 0, 0)
         self.frame.setLayout(layout)
Index: src/sas/qtgui/Plotting/PlotProperties.py
===================================================================
--- src/sas/qtgui/Plotting/PlotProperties.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Plotting/PlotProperties.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,3 +1,5 @@
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.PlotUtilities import COLORS, SHAPES
@@ -6,5 +8,5 @@
 from sas.qtgui.Plotting.UI.PlotPropertiesUI import Ui_PlotPropertiesUI
 
-class PlotProperties(QtGui.QDialog, Ui_PlotPropertiesUI):
+class PlotProperties(QtWidgets.QDialog, Ui_PlotPropertiesUI):
     """ Dialog for modification of single plot properties """
     def __init__(self,
Index: src/sas/qtgui/Plotting/Plotter.py
===================================================================
--- src/sas/qtgui/Plotting/Plotter.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Plotter.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,4 +1,6 @@
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+
 import functools
 import copy
@@ -19,4 +21,5 @@
     1D Plot widget for use with a QDialog
     """
+    updatePlot = QtCore.pyqtSignal(tuple)
     def __init__(self, parent=None, manager=None, quickplot=False):
         super(PlotterWidget, self).__init__(parent, manager=manager, quickplot=quickplot)
@@ -41,8 +44,7 @@
         # Add a slot for receiving update signal from LinearFit
         # NEW style signals
-        #self.updatePlot = QtCore.pyqtSignal(tuple)
-        # self.updatePlot.connect(self.onFitDisplay)
+        self.updatePlot.connect(self.onFitDisplay)
         # OLD style signals
-        QtCore.QObject.connect(self, QtCore.SIGNAL('updatePlot'), self.onFitDisplay)
+        # QtCore.QObject.connect(self, QtCore.SIGNAL('updatePlot'), self.onFitDisplay)
 
     @property
@@ -269,5 +271,5 @@
         Show a dialog allowing axes rescaling
         """
-        if self.properties.exec_() == QtGui.QDialog.Accepted:
+        if self.properties.exec_() == QtWidgets.QDialog.Accepted:
             self.xLogLabel, self.yLogLabel = self.properties.getValues()
             self.xyTransform(self.xLogLabel, self.yLogLabel)
@@ -277,5 +279,5 @@
         Show a dialog allowing adding custom text to the chart
         """
-        if self.addText.exec_() == QtGui.QDialog.Accepted:
+        if self.addText.exec_() == QtWidgets.QDialog.Accepted:
             # Retrieve the new text, its font and color
             extra_text = self.addText.text()
@@ -329,5 +331,5 @@
         """
         # min and max of data
-        if self.setRange.exec_() == QtGui.QDialog.Accepted:
+        if self.setRange.exec_() == QtWidgets.QDialog.Accepted:
             x_range = self.setRange.xrange()
             y_range = self.setRange.yrange()
@@ -363,5 +365,5 @@
                     xlabel=self.xLogLabel,
                     ylabel=self.yLogLabel)
-        if fit_dialog.exec_() == QtGui.QDialog.Accepted:
+        if fit_dialog.exec_() == QtWidgets.QDialog.Accepted:
             return
 
@@ -440,5 +442,5 @@
                                 marker_size=marker_size,
                                 legend=legend)
-        if plotPropertiesWidget.exec_() == QtGui.QDialog.Accepted:
+        if plotPropertiesWidget.exec_() == QtWidgets.QDialog.Accepted:
             # Update Data1d
             selected_plot.markersize = plotPropertiesWidget.markersize()
@@ -697,8 +699,8 @@
 
 
-class Plotter(QtGui.QDialog, PlotterWidget):
+class Plotter(QtWidgets.QDialog, PlotterWidget):
     def __init__(self, parent=None, quickplot=False):
 
-        QtGui.QDialog.__init__(self)
+        QtWidgets.QDialog.__init__(self)
         PlotterWidget.__init__(self, parent=self, manager=parent, quickplot=quickplot)
         icon = QtGui.QIcon()
Index: src/sas/qtgui/Plotting/Plotter2D.py
===================================================================
--- src/sas/qtgui/Plotting/Plotter2D.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Plotter2D.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,8 +4,15 @@
 import functools
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 DEFAULT_CMAP = pylab.cm.jet
+
+#import sys
+#print("SYS.PATH = ", sys.path)
+import matplotlib as mpl
+mpl.use("Qt5Agg")
+
 from mpl_toolkits.mplot3d import Axes3D
 
@@ -365,5 +372,5 @@
         color_map_dialog.apply_signal.connect(self.onApplyMap)
 
-        if color_map_dialog.exec_() == QtGui.QDialog.Accepted:
+        if color_map_dialog.exec_() == QtWidgets.QDialog.Accepted:
             self.onApplyMap(color_map_dialog.norm(), color_map_dialog.cmap())
 
@@ -503,10 +510,10 @@
 
 
-class Plotter2D(QtGui.QDialog, Plotter2DWidget):
+class Plotter2D(QtWidgets.QDialog, Plotter2DWidget):
     """
     Plotter widget implementation
     """
     def __init__(self, parent=None, quickplot=False, dimension=2):
-        QtGui.QDialog.__init__(self)
+        QtWidgets.QDialog.__init__(self)
         Plotter2DWidget.__init__(self, manager=parent, quickplot=quickplot, dimension=dimension)
         icon = QtGui.QIcon()
Index: src/sas/qtgui/Plotting/PlotterBase.py
===================================================================
--- src/sas/qtgui/Plotting/PlotterBase.py	(revision 7d8bebfa86b0a6c7db7ce72a8f4f36897ad9f0f6)
+++ src/sas/qtgui/Plotting/PlotterBase.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,6 +2,7 @@
 import numpy
 
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # TODO: Replace the qt4agg calls below with qt5 equivalent.
@@ -9,6 +10,7 @@
 # https://www.boxcontrol.net/embedding-matplotlib-plot-on-pyqt5-gui.html
 #
-from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
-from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
+# matplotlib.use("Qt5Agg")
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
 
 import matplotlib.pyplot as plt
@@ -25,5 +27,5 @@
 import sas.qtgui.Plotting.PlotUtilities as PlotUtilities
 
-class PlotterBase(QtGui.QWidget):
+class PlotterBase(QtWidgets.QWidget):
     def __init__(self, parent=None, manager=None, quickplot=False):
         super(PlotterBase, self).__init__(parent)
@@ -43,9 +45,10 @@
 
         # Simple window for data display
-        self.txt_widget = QtGui.QTextEdit(None)
+        self.txt_widget = QtWidgets.QTextEdit(None)
 
         # Set the layout and place the canvas widget in it.
-        layout = QtGui.QVBoxLayout()
-        layout.setMargin(0)
+        layout = QtWidgets.QVBoxLayout()
+        # FIXME setMargin -> setContentsMargins in qt5 with 4 args
+        #layout.setContentsMargins(0)
         layout.addWidget(self.canvas)
 
@@ -105,5 +108,5 @@
         self.canvas.mpl_connect('scroll_event', self.onMplWheel)
 
-        self.contextMenu = QtGui.QMenu(self)
+        self.contextMenu = QtWidgets.QMenu(self)
 
         if not quickplot:
@@ -296,5 +299,5 @@
         dialog.setModal(True)
         dialog.setWindowTitle("Print")
-        if dialog.exec_() != QtGui.QDialog.Accepted:
+        if dialog.exec_() != QtWidgets.QDialog.Accepted:
             return
 
@@ -303,5 +306,5 @@
         pmap = QtGui.QPixmap.grabWidget(self)
         # Create a label with pixmap drawn
-        printLabel = QtGui.QLabel()
+        printLabel = QtWidgets.QLabel()
         printLabel.setPixmap(pmap)
 
@@ -333,5 +336,5 @@
         titleWidget = WindowTitle(self, new_title=current_title)
         result = titleWidget.exec_()
-        if result != QtGui.QDialog.Accepted:
+        if result != QtWidgets.QDialog.Accepted:
             return
 
Index: src/sas/qtgui/Plotting/ScaleProperties.py
===================================================================
--- src/sas/qtgui/Plotting/ScaleProperties.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/Plotting/ScaleProperties.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,3 +1,5 @@
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 import sas.sasview
@@ -20,5 +22,5 @@
     view_values[5]: [0, 4], # Kratky
 }
-class ScaleProperties(QtGui.QDialog, Ui_scalePropertiesUI):
+class ScaleProperties(QtWidgets.QDialog, Ui_scalePropertiesUI):
     def __init__(self, parent=None, init_scale_x='x', init_scale_y='y'):
         super(ScaleProperties, self).__init__(parent)
Index: src/sas/qtgui/Plotting/SetGraphRange.py
===================================================================
--- src/sas/qtgui/Plotting/SetGraphRange.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/Plotting/SetGraphRange.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -2,5 +2,7 @@
 Allows users to change the range of the current graph
 """
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 # Local UI
@@ -8,5 +10,5 @@
 from sas.qtgui.Plotting.UI.SetGraphRangeUI import Ui_setGraphRangeUI
 
-class SetGraphRange(QtGui.QDialog, Ui_setGraphRangeUI):
+class SetGraphRange(QtWidgets.QDialog, Ui_setGraphRangeUI):
     def __init__(self, parent=None, x_range=(0.0, 0.0), y_range=(0.0, 0.0)):
         super(SetGraphRange, self).__init__()
Index: src/sas/qtgui/Plotting/SlicerModel.py
===================================================================
--- src/sas/qtgui/Plotting/SlicerModel.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/SlicerModel.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,4 +1,3 @@
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtGui
 
 import sas.qtgui.Utilities.GuiUtils as GuiUtils
Index: src/sas/qtgui/Plotting/SlicerParameters.py
===================================================================
--- src/sas/qtgui/Plotting/SlicerParameters.py	(revision cd2cc7458970e179039a783e9409f48c4c1fca0d)
+++ src/sas/qtgui/Plotting/SlicerParameters.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,7 +4,8 @@
 import numpy
 import functools
-from PyQt4 import QtGui
-from PyQt4 import QtCore
-from PyQt4 import QtWebKit
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+from PyQt5 import QtWebKitWidgets
 
 # Local UI
@@ -12,5 +13,5 @@
 from sas.qtgui.Plotting.UI.SlicerParametersUI import Ui_SlicerParametersUI
 
-class SlicerParameters(QtGui.QDialog, Ui_SlicerParametersUI):
+class SlicerParameters(QtWidgets.QDialog, Ui_SlicerParametersUI):
     """
     Interaction between the QTableView and the underlying model,
@@ -44,17 +45,17 @@
 
         # Display Help on clicking the button
-        self.buttonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self.onHelp)
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.onHelp)
 
         # Close doesn't trigger closeEvent automatically, so force it
-        self.buttonBox.button(QtGui.QDialogButtonBox.Close).clicked.connect(functools.partial(self.closeEvent, None))
+        self.buttonBox.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(functools.partial(self.closeEvent, None))
 
         # Disable row number display
         self.lstParams.verticalHeader().setVisible(False)
         self.lstParams.setAlternatingRowColors(True)
-        self.lstParams.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding)
+        self.lstParams.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
 
         # Header properties for nicer display
         header = self.lstParams.horizontalHeader()
-        header.setResizeMode(QtGui.QHeaderView.Stretch)
+        header.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
         header.setStretchLastSection(True)
 
@@ -86,10 +87,10 @@
         location = "docs/sphinx-docs/build/html" + \
             "/user/sasgui/guiframe/graph_help.html#d-data-averaging"
-        self.helpView = QtWebKit.QWebView()
+        self.helpView = QtWebKitWidgets.QWebView()
         self.helpView.load(QtCore.QUrl(location))
         self.helpView.show()
 
 
-class ProxyModel(QtGui.QIdentityProxyModel):
+class ProxyModel(QtCore.QIdentityProxyModel):
     """
     Trivial proxy model with custom column edit flag
@@ -117,5 +118,5 @@
         return flags
 
-class PositiveDoubleEditor(QtGui.QLineEdit):
+class PositiveDoubleEditor(QtWidgets.QLineEdit):
     # a signal to tell the delegate when we have finished editing
     editingFinished = QtCore.Signal()
@@ -136,5 +137,5 @@
 
 
-class EditDelegate(QtGui.QStyledItemDelegate):
+class EditDelegate(QtWidgets.QStyledItemDelegate):
     refocus_signal = QtCore.pyqtSignal(int, int)
     def __init__(self, parent=None, validate_method=None):
@@ -155,5 +156,5 @@
                 return self.editor
         else:
-                return QtGui.QStyledItemDelegate.createEditor(self, parent, option, index)
+                return QtWidgets.QStyledItemDelegate.createEditor(self, parent, option, index)
 
     def setModelData(self, editor, model, index):
Index: src/sas/qtgui/Plotting/Slicers/AnnulusSlicer.py
===================================================================
--- src/sas/qtgui/Plotting/Slicers/AnnulusSlicer.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Slicers/AnnulusSlicer.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,5 +1,3 @@
 import numpy
-from PyQt4 import QtGui
-from PyQt4 import QtCore
 
 import sas.qtgui.Utilities.GuiUtils as GuiUtils
Index: src/sas/qtgui/Plotting/Slicers/BoxSlicer.py
===================================================================
--- src/sas/qtgui/Plotting/Slicers/BoxSlicer.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Slicers/BoxSlicer.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,5 +1,3 @@
 import numpy
-from PyQt4 import QtGui
-from PyQt4 import QtCore
 
 from .BaseInteractor import BaseInteractor
Index: src/sas/qtgui/Plotting/Slicers/BoxSum.py
===================================================================
--- src/sas/qtgui/Plotting/Slicers/BoxSum.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Slicers/BoxSum.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,6 +4,6 @@
 """
 import numpy
-from PyQt4 import QtGui
-from PyQt4 import QtCore
+from PyQt5 import QtGui
+
 from sas.qtgui.Utilities.GuiUtils import formatNumber
 
Index: src/sas/qtgui/Plotting/Slicers/SectorSlicer.py
===================================================================
--- src/sas/qtgui/Plotting/Slicers/SectorSlicer.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Plotting/Slicers/SectorSlicer.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -3,6 +3,4 @@
 """
 import numpy
-from PyQt4 import QtGui
-from PyQt4 import QtCore
 
 from .BaseInteractor import BaseInteractor
Index: src/sas/qtgui/Plotting/UnitTesting/SlicerParametersTest.py
===================================================================
--- src/sas/qtgui/Plotting/UnitTesting/SlicerParametersTest.py	(revision 99ea1b0a8c79c7cca1feb2e3bcae293656ef8ca8)
+++ src/sas/qtgui/Plotting/UnitTesting/SlicerParametersTest.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -37,5 +37,5 @@
         '''Test the GUI in its default state'''
         #self.widget.mapper
-        self.assertIsInstance(self.widget.proxy, QtGui.QIdentityProxyModel)
+        self.assertIsInstance(self.widget.proxy, QtCore.QIdentityProxyModel)
         self.assertIsInstance(self.widget.lstParams.itemDelegate(), QtGui.QStyledItemDelegate)
         self.assertTrue(self.widget.lstParams.model().columnReadOnly(0))
Index: src/sas/qtgui/Plotting/WindowTitle.py
===================================================================
--- src/sas/qtgui/Plotting/WindowTitle.py	(revision 83eb5208b8acb86b064162274de583670f72da47)
+++ src/sas/qtgui/Plotting/WindowTitle.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -3,9 +3,9 @@
 from "Graph_n" to any ASCII text.
 """
-from PyQt4 import QtGui
+from PyQt5 import QtWidgets
 
 from sas.qtgui.Plotting.UI.WindowTitleUI import Ui_WindowTitle
 
-class WindowTitle(QtGui.QDialog, Ui_WindowTitle):
+class WindowTitle(QtWidgets.QDialog, Ui_WindowTitle):
     """ Simple GUI for a single line text query """
     def __init__(self, parent=None, new_title=""):
Index: src/sas/qtgui/Plotting/rangeSlider.py
===================================================================
--- src/sas/qtgui/Plotting/rangeSlider.py	(revision 83eb5208b8acb86b064162274de583670f72da47)
+++ src/sas/qtgui/Plotting/rangeSlider.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -23,7 +23,9 @@
 """
 
-from PyQt4 import QtGui, QtCore
-
-class RangeSlider(QtGui.QSlider):
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+
+class RangeSlider(QtWidgets.QSlider):
     """ A slider for ranges.
     
@@ -46,6 +48,6 @@
         self._high = self.maximum()
         
-        self.pressed_control = QtGui.QStyle.SC_None
-        self.hover_control = QtGui.QStyle.SC_None
+        self.pressed_control = QtWidgets.QStyle.SC_None
+        self.hover_control = QtWidgets.QStyle.SC_None
         self.click_offset = 0
         
@@ -90,5 +92,5 @@
 
         for i, value in enumerate([self._low, self._high]):
-            opt = QtGui.QStyleOptionSlider()
+            opt = QtWidgets.QStyleOptionSlider()
             self.initStyleOption(opt)
 
@@ -107,5 +109,5 @@
                 slider_max = gr.bottom() - handle_length + 1
 
-            opt.subControls = QtGui.QStyle.SC_SliderGroove | QtGui.QStyle.SC_SliderHandle
+            opt.subControls = QtWidgets.QStyle.SC_SliderGroove | QtWidgets.QStyle.SC_SliderHandle
 
             # draw the first slider with inverted appearance, then the second 
@@ -131,5 +133,5 @@
                 # do not highlight the second part when has focus to avoid 
                 # drawing of partially overlapped semi-transparent backgrounds
-                opt.state &= ~QtGui.QStyle.State_HasFocus
+                opt.state &= ~QtWidgets.QStyle.State_HasFocus
 
                 opt.sliderValue = 0
@@ -157,13 +159,13 @@
 
             if self.tickPosition() != self.NoTicks:
-                opt.subControls |= QtGui.QStyle.SC_SliderTickmarks
+                opt.subControls |= QtWidgets.QStyle.SC_SliderTickmarks
 
             if self.pressed_control:
                 opt.activeSubControls = self.pressed_control
-                opt.state |= QtGui.QStyle.State_Sunken
+                opt.state |= QtWidgets.QStyle.State_Sunken
             else:
                 opt.activeSubControls = self.hover_control
 
-            style.drawComplexControl(QtGui.QStyle.CC_Slider, opt, painter, self)
+            style.drawComplexControl(QtWidgets.QStyle.CC_Slider, opt, painter, self)
             
         
@@ -181,5 +183,5 @@
                 
         if button:
-            opt = QtGui.QStyleOptionSlider()
+            opt = QtWidgets.QStyleOptionSlider()
             self.initStyleOption(opt)
 
@@ -206,5 +208,5 @@
 
             if self.active_slider == 0:
-                self.pressed_control = QtGui.QStyle.SC_SliderHandle
+                self.pressed_control = QtWidgets.QStyle.SC_SliderHandle
                 self.click_offset = self.__pixelPosToRangeValue(self.__pick(event.pos()))
                 self.triggerAction(self.SliderMove)
@@ -215,13 +217,13 @@
 
     def mouseReleaseEvent(self, event):
-        if self.pressed_control != QtGui.QStyle.SC_SliderHandle:
+        if self.pressed_control != QtWidgets.QStyle.SC_SliderHandle:
             event.ignore()
             return
 
         self.setSliderDown(False)
-        return QtGui.QSlider.mouseReleaseEvent(self, event)
+        return QtWidgets.QSlider.mouseReleaseEvent(self, event)
                                 
     def mouseMoveEvent(self, event):
-        if self.pressed_control != QtGui.QStyle.SC_SliderHandle:
+        if self.pressed_control != QtWidgets.QStyle.SC_SliderHandle:
             event.ignore()
             return
@@ -229,5 +231,5 @@
         event.accept()
         new_pos = self.__pixelPosToRangeValue(self.__pick(event.pos()))
-        opt = QtGui.QStyleOptionSlider()
+        opt = QtWidgets.QStyleOptionSlider()
         self.initStyleOption(opt)
 
@@ -274,5 +276,5 @@
            
     def __pixelPosToRangeValue(self, pos):
-        opt = QtGui.QStyleOptionSlider()
+        opt = QtWidgets.QStyleOptionSlider()
         self.initStyleOption(opt)
         style = QtGui.QApplication.style()
Index: src/sas/qtgui/Utilities/GuiUtils.py
===================================================================
--- src/sas/qtgui/Utilities/GuiUtils.py	(revision 895e7359d4338c6297f2baacf8a64deb50de5590)
+++ src/sas/qtgui/Utilities/GuiUtils.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -14,6 +14,7 @@
 import logging
 
-from PyQt4 import QtCore
-from PyQt4 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
 
 from periodictable import formula as Formula
@@ -309,5 +310,4 @@
     object_item = QtGui.QStandardItem()
     object_item.setText(name)
-    #object_item.setData(QtCore.QVariant(update_data))
     object_item.setData(update_data)
 
@@ -586,5 +586,5 @@
     }
     # Query user for filename.
-    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
+    filename = QtWidgets.QFileDialog.getSaveFileName(**kwargs)
 
     # User cancelled.
@@ -618,5 +618,5 @@
     }
     # Query user for filename.
-    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
+    filename = QtWidgets.QFileDialog.getSaveFileName(**kwargs)
 
     # User cancelled.
Index: src/sas/qtgui/Utilities/IPythonWidget.py
===================================================================
--- src/sas/qtgui/Utilities/IPythonWidget.py	(revision fef38e8f19a097daafbdbdd6edb786c11fb2b995)
+++ src/sas/qtgui/Utilities/IPythonWidget.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -1,3 +1,7 @@
-from PyQt4 import QtCore, QtGui, QtSvg
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+
+##from PyQt4 import QtSvg
 
 def new_load_qt(api_options):
Index: src/sas/qtgui/Utilities/SasviewLogger.py
===================================================================
--- src/sas/qtgui/Utilities/SasviewLogger.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/Utilities/SasviewLogger.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -3,11 +3,11 @@
 import logging
 
-from PyQt4 import QtCore
+from PyQt5.QtCore import *
 
 
-class XStream(QtCore.QObject):
+class XStream(QObject):
     _stdout = None
     _stderr = None
-    messageWritten = QtCore.pyqtSignal(str)
+    messageWritten = pyqtSignal(str)
 
     def flush(self):
Index: src/sas/qtgui/convertUI.py
===================================================================
--- src/sas/qtgui/convertUI.py	(revision b0b09b9740526b0b3838f642e43599409dfd8772)
+++ src/sas/qtgui/convertUI.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -4,10 +4,10 @@
 def pyrrc(in_file, out_file):
     """ Run the pyrcc4 script"""
-    execute = 'pyrcc4 -py3 %s -o %s' % (in_file, out_file)
+    execute = 'pyrcc5 %s -o %s' % (in_file, out_file)
     os.system(execute)
 
 def pyuic(in_file, out_file):
     """ Run the pyuic5 script"""
-    execute = 'pyuic4 -o %s %s' % (out_file, in_file)
+    execute = 'pyuic5 -o %s %s' % (out_file, in_file)
     os.system(execute)
 
Index: src/sas/sasgui/plottools/config.py
===================================================================
--- src/sas/sasgui/plottools/config.py	(revision a2a1c20ad523859505a1a68749ea84048384021f)
+++ src/sas/sasgui/plottools/config.py	(revision 0849aec6ceb97781213ef369f98e5eb61ec8cad3)
@@ -32,5 +32,6 @@
 #plot_version = "0.98"
 #plot_backend = "WXAgg"
-plot_backend = "Qt4Agg"
+print("SET MPL BACKEND TO Qt5")
+plot_backend = "Qt5Agg"
 
 # Sort out matplotlib version
