Index: src/sas/qtgui/Utilities/GuiUtils.py
===================================================================
--- src/sas/qtgui/Utilities/GuiUtils.py	(revision 63467b61b55727b3a1e6bd20f8e86e6b45006844)
+++ src/sas/qtgui/Utilities/GuiUtils.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
@@ -285,4 +285,7 @@
     # Tell the data explorer to switch tabs
     changeDataExplorerTabSignal = QtCore.pyqtSignal(int)
+
+    # Plot fitting results (FittingWidget->GuiManager)
+    resultPlotUpdateSignal = QtCore.pyqtSignal(list)
 
 def updateModelItemWithPlot(item, update_data, name=""):
Index: src/sas/qtgui/Utilities/PlotView.py
===================================================================
--- src/sas/qtgui/Utilities/PlotView.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
+++ src/sas/qtgui/Utilities/PlotView.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
@@ -0,0 +1,230 @@
+from __future__ import with_statement, print_function
+
+# The Figure object is used to create backend-independent plot representations.
+from matplotlib.figure import Figure
+GUI_TOOLKIT = "qt5"
+from matplotlib.backends.qt_compat import QtCore, QtWidgets
+
+class EmbeddedPylab(object):
+    """
+    Define a 'with' context manager that lets you use pylab commands to
+    plot on an embedded canvas.  This is useful for wrapping existing
+    scripts in a GUI, and benefits from being more familiar than the
+    underlying object oriented interface.
+
+    As a convenience, the pylab module is returned on entry.
+
+    Example
+    -------
+
+    The following example shows how to use the WxAgg backend in a wx panel::
+
+        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
+        from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as Toolbar
+        from matplotlib.figure import Figure
+
+        class PlotPanel(wx.Panel):
+            def __init__(self, *args, **kw):
+                wx.Panel.__init__(self, *args, **kw)
+
+                figure = Figure(figsize=(1,1), dpi=72)
+                canvas = FigureCanvas(self, wx.ID_ANY, figure)
+                self.pylab_interface = EmbeddedPylab(canvas)
+
+                # Instantiate the matplotlib navigation toolbar and explicitly show it.
+                mpl_toolbar = Toolbar(canvas)
+                mpl_toolbar.Realize()
+
+                # Create a vertical box sizer to manage the widgets in the main panel.
+                sizer = wx.BoxSizer(wx.VERTICAL)
+                sizer.Add(canvas, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, border=0)
+                sizer.Add(mpl_toolbar, 0, wx.EXPAND|wx.ALL, border=0)
+
+                # Associate the sizer with its container.
+                self.SetSizer(sizer)
+                sizer.Fit(self)
+
+            def plot(self, *args, **kw):
+                with self.pylab_interface as pylab:
+                    pylab.clf()
+                    pylab.plot(*args, **kw)
+
+    Similar patterns should work for the other backends.  Check the source code
+    in matplotlib.backend_bases.* for examples showing how to use matplotlib
+    with other GUI toolkits.
+    """
+    def __init__(self, canvas):
+        # delay loading pylab until matplotlib.use() is called
+        from matplotlib.backend_bases import FigureManagerBase
+        self.fm = FigureManagerBase(canvas, -1)
+    def __enter__(self):
+        # delay loading pylab until matplotlib.use() is called
+        import pylab
+        from matplotlib._pylab_helpers import Gcf
+        Gcf.set_active(self.fm)
+        return pylab
+    def __exit__(self, *args, **kw):
+        # delay loading pylab until matplotlib.use() is called
+        from matplotlib._pylab_helpers import Gcf
+        Gcf._activeQue = [f for f in Gcf._activeQue if f is not self.fm]
+        try:
+            del Gcf.figs[-1]
+        except KeyError:
+            pass
+
+
+class _PlotViewShared(object):
+    title = 'Plot'
+    default_size = (600, 400)
+    pylab_interface = None  # type: EmbeddedPylab
+    plot_state = None
+    model = None
+    _calculating = False
+    _need_plot =  False
+    _need_newmodel = False
+
+    def set_model(self, model):
+        self.model = model
+        if not self._is_shown():
+            self._need_newmodel = True
+        else:
+            self._redraw(newmodel=True)
+
+    def update_model(self, model):
+        #print "profile update model"
+        if self.model != model:  # ignore updates to different models
+            return
+
+        if not self._is_shown():
+            self._need_newmodel = True
+        else:
+            self._redraw(newmodel=True)
+
+    def update_parameters(self, model):
+        #print "profile update parameters"
+        if self.model != model:
+            return
+
+        if not self._is_shown():
+            self._need_plot = True
+        else:
+            self._redraw(newmodel=self._need_newmodel)
+
+    def _show(self):
+        #print "showing theory"
+        if self._need_newmodel:
+            self._redraw(newmodel=True)
+        elif self._need_plot:
+            self._redraw(newmodel=False)
+
+    def _redraw(self, newmodel=False):
+        self._need_newmodel = newmodel
+        if self._calculating:
+            # That means that I've entered the thread through a
+            # wx.Yield for the currently executing redraw.  I need
+            # to cancel the running thread and force it to start
+            # the calculation over.
+            self.cancel_calculation = True
+            #print "canceling calculation"
+            return
+
+        with self.pylab_interface as pylab:
+            self._calculating = True
+
+            #print "calling again"
+            while True:
+                #print "restarting"
+                # We are restarting the calculation, so clear the reset flag
+                self.cancel_calculation = False
+
+                if self._need_newmodel:
+                    self.newmodel()
+                    if self.cancel_calculation:
+                        continue
+                    self._need_newmodel = False
+                self.plot()
+                if self.cancel_calculation:
+                    continue
+                pylab.draw()
+                break
+        self._need_plot = False
+        self._calculating = False
+
+    def get_state(self):
+        #print "returning state",self.model,self.plot_state
+        return self.model, self.plot_state
+
+    def set_state(self, state):
+        self.model, self.plot_state = state
+        #print "setting state",self.model,self.plot_state
+        self.plot()
+
+    def menu(self):
+        """
+        Return a model specific menu
+        """
+        return None
+
+    def newmodel(self, model=None):
+        """
+        New or updated model structure.  Do any sort or precalculation you
+        need.  plot will be called separately when you are done.
+
+        For long calculations, periodically perform wx.YieldIfNeeded()
+        and then if self.cancel_calculation is True, return from the plot.
+        """
+        pass
+
+    def plot(self):
+        """
+        Plot to the current figure.  If model has a plot method,
+        just use that.
+
+        For long calculations, periodically perform wx.YieldIfNeeded()
+        and then if self.cancel_calculation is True, return from the plot.
+        """
+        if hasattr(self.model, 'plot'):
+            self.model.plot()
+        else:
+            raise NotImplementedError("PlotPanel needs a plot method")
+
+class PlotView(QtWidgets.QWidget, _PlotViewShared):
+    def __init__(self, *args, **kw):
+        QtWidgets.QWidget.__init__(self, *args, **kw)
+        #import matplotlib.backends.backend_qt4agg
+        #matplotlib.backends.backend_qt4agg.DEBUG = True
+        from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
+        from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Toolbar
+
+        #QtWidgets.QWidget.__init__(self, *args, **kw)
+
+        # Can specify name on
+        if 'title' in kw:
+            self.title = kw['title']
+
+        # Instantiate a figure object that will contain our plots.
+        figure = Figure(figsize=(1,1), dpi=72)
+
+        # Initialize the figure canvas, mapping the figure object to the plot
+        # engine backend.
+        canvas = FigureCanvas(figure)
+
+        # Wx-Pylab magic ...
+        # Make our canvas an active figure manager for pylab so that when
+        # pylab plotting statements are executed they will operate on our
+        # canvas and not create a new frame and canvas for display purposes.
+        # This technique allows this application to execute code that uses
+        # pylab stataments to generate plots and embed these plots in our
+        # application window(s).  Use _activate_figure() to set.
+        self.pylab_interface = EmbeddedPylab(canvas)
+
+        # Instantiate the matplotlib navigation toolbar and explicitly show it.
+        mpl_toolbar = Toolbar(canvas, self, False)
+
+        layout = QtWidgets.QVBoxLayout()
+        layout.addWidget(canvas)
+        layout.addWidget(mpl_toolbar)
+        self.setLayout(layout)
+
+    def _is_shown(self):
+        return IS_MAC or self.IsShown()
Index: src/sas/qtgui/Utilities/ResultPanel.py
===================================================================
--- src/sas/qtgui/Utilities/ResultPanel.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
+++ src/sas/qtgui/Utilities/ResultPanel.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
@@ -0,0 +1,99 @@
+"""
+FitPanel class contains fields allowing to fit  models and  data
+
+"""
+import sys
+import datetime
+
+from PyQt5 import QtCore
+from PyQt5 import QtGui
+from PyQt5 import QtWidgets
+
+from bumps.dream.stats import var_stats, format_vars
+
+
+class ResultPanel(QtWidgets.QTabWidget):
+    """
+    FitPanel class contains fields allowing to fit  models and  data
+
+    :note: For Fit to be performed the user should check at least one parameter
+        on fit Panel window.
+
+    """
+    ## Internal name for the AUI manager
+    window_name = "Result panel"
+    windowClosedSignal = QtCore.pyqtSignal()
+
+    def __init__(self, parent, manager=None, *args, **kwargs):
+        """
+        """
+        super(ResultPanel, self).__init__(parent)
+        self.manager = manager
+        self.communicator = self.manager.communicator()
+        self.setMinimumSize(400, 400)
+
+        self.updateBumps() # patch bumps ## TEMPORARY ##
+
+        # the following two imports will move to the top once
+        # the monkeypatching is gone
+        from bumps.gui.convergence_view import ConvergenceView
+        from bumps.gui.uncertainty_view import UncertaintyView, CorrelationView, TraceView
+
+
+        self.convergenceView = ConvergenceView()
+        self.uncertaintyView = UncertaintyView()
+        self.correlationView = CorrelationView()
+        self.traceView = TraceView()
+        self.show()
+
+    def updateBumps(self):
+        """
+        Monkeypatching bumps plot viewer to allow Qt
+        """
+        from . import PlotView
+        import bumps.gui
+        sys.modules['bumps.gui.plot_view'] = PlotView
+
+    def onPlotResults(self, results):
+        # Clear up previous results
+        for view in (self.convergenceView, self.correlationView,
+                     self.uncertaintyView, self.traceView):
+            view.close()
+
+        result = results[0][0]
+        filename = result.data.sas_data.filename
+        current_time = datetime.datetime.now().strftime("%I:%M%p, %B %d, %Y")
+        self.setWindowTitle(self.window_name + " - " + filename + " - " + current_time)
+        if hasattr(result, 'convergence'):
+            best, pop = result.convergence[:, 0], result.convergence[:, 1:]
+            self.convergenceView.update(best, pop)
+            self.addTab(self.convergenceView, "Convergence")
+            self.convergenceView.show()
+        else:
+            self.convergenceView.close()
+        if hasattr(result, 'uncertainty_state'):
+            stats = var_stats(result.uncertainty_state.draw())
+            msg = format_vars(stats)
+            self.correlationView.update(result.uncertainty_state)
+            self.correlationView.show()
+            self.addTab(self.correlationView, "Correlation")
+
+            self.uncertaintyView.update((result.uncertainty_state, stats))
+            self.uncertaintyView.show()
+            self.addTab(self.uncertaintyView, "Uncertainty")
+
+            self.traceView.update(result.uncertainty_state)
+            self.traceView.show()
+            self.addTab(self.traceView, "Parameter Trace")
+        else:
+            for view in (self.correlationView, self.uncertaintyView, self.traceView):
+                view.close()
+
+    def closeEvent(self, event):
+        """
+        Overwrite QDialog close method to allow for custom widget close
+        """
+        # notify the parent so it hides this window
+        self.windowClosedSignal.emit()
+        event.ignore()
+
