Index: src/sas/qtgui/Calculators/UnitTesting/GenericScatteringCalculatorTest.py
===================================================================
--- src/sas/qtgui/Calculators/UnitTesting/GenericScatteringCalculatorTest.py	(revision 8137a026acec58973ff538483287bd64937d50a1)
+++ src/sas/qtgui/Calculators/UnitTesting/GenericScatteringCalculatorTest.py	(revision c02721c4e06ef72ac9df56ad7390b73484c3d35c)
@@ -186,4 +186,6 @@
         # wait a bit for data to be loaded
         time.sleep(0.1)
+        QtWidgets.qApp.processEvents()
+
         # check updated values in ui, read from loaded file
         self.assertEqual(self.widget.txtData.text(), 'sld_file.sld')
@@ -250,4 +252,6 @@
 
         time.sleep(1)
+        QtWidgets.qApp.processEvents()
+
         # check updated values in ui, read from loaded file
         # TODO to be changed
@@ -310,4 +314,5 @@
         self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
         time.sleep(2)
+        QtWidgets.qApp.processEvents()
 
         self.assertEqual(self.widget.txtData.text(), 'A_Raw_Example-1.omf')
@@ -396,4 +401,5 @@
         self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
         time.sleep(1)
+        QtWidgets.qApp.processEvents()
 
         self.assertTrue(self.widget.cmdDraw.isEnabled())
@@ -417,10 +423,13 @@
 
         time.sleep(0.1)
+        QtWidgets.qApp.processEvents()
 
         filename1 = "test"
         QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=[filename1, ''])
 
-        QTest.mouseClick(self.widget.cmdSave, Qt.LeftButton)
+        #QTest.mouseClick(self.widget.cmdSave, Qt.LeftButton)
         self.widget.onSaveFile()
+        QtWidgets.qApp.processEvents()
+
         self.assertTrue(os.path.isfile(filename1 + '.sld'))
         self.assertTrue(os.path.getsize(filename1 + '.sld') > 0)
Index: src/sas/qtgui/Calculators/UnitTesting/SLDCalculatorTest.py
===================================================================
--- src/sas/qtgui/Calculators/UnitTesting/SLDCalculatorTest.py	(revision 9ce69ec3193ed870f2129f02525b0537ca161f76)
+++ src/sas/qtgui/Calculators/UnitTesting/SLDCalculatorTest.py	(revision 6edd344fa796b585fa45b51c842214a9caa8024e)
@@ -13,7 +13,7 @@
 
 # Local
-from sas.qtgui.Calculators.SldPanel import SldResult
+#from sas.qtgui.Calculators.SldPanel import SldResult
 from sas.qtgui.Calculators.SldPanel import SldPanel
-from sas.qtgui.Calculators.SldPanel import sldAlgorithm
+from sas.qtgui.Calculators.SldPanel import neutronSldAlgorithm, xraySldAlgorithm
 from sas.qtgui.Utilities.GuiUtils import FormulaValidator
 
@@ -22,11 +22,4 @@
 if not QtWidgets.QApplication.instance():
     app = QtWidgets.QApplication(sys.argv)
-
-class SldResultTest(unittest.TestCase):
-    """ Test the simple container class"""
-    def testObjectSize(self):
-        results = SldResult(0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
-                            0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
-        self.assertEqual(sys.getsizeof(results), 56)
 
 
@@ -38,8 +31,8 @@
         wavelength = 6.0
         
-        results = sldAlgorithm( molecular_formula,
+        results = neutronSldAlgorithm( molecular_formula,
                                 mass_density,
                                 wavelength)
-        self.assertIsInstance(results, SldResult)
+        #self.assertIsInstance(results, SldResult)
         self.assertAlmostEqual(results.neutron_length, 0.175463, 5)
         self.assertAlmostEqual(results.neutron_inc_xs, 5.365857, 5)
@@ -51,8 +44,8 @@
         wavelength = 666.0
         
-        results = sldAlgorithm( molecular_formula,
+        results = neutronSldAlgorithm( molecular_formula,
                                 mass_density,
                                 wavelength)
-        self.assertIsInstance(results, SldResult)
+        #self.assertIsInstance(results, SldResult)
         self.assertAlmostEqual(results.neutron_length,   0.059402, 5)
         self.assertAlmostEqual(results.neutron_inc_xs,   0.145427, 5)
@@ -128,13 +121,5 @@
 
         # Assure the mass density field is set
-        #self.assertEqual(self.widget.ui.editNeutronIncXs.text(), '43.4')
         self.assertEqual(self.widget.ui.editNeutronIncXs.text(), '2.89')
-
-        # Reset the widget
-        self.widget.modelReset()
-       
-        self.assertEqual(self.widget.ui.editMolecularFormula.text(), "H2O")
-        self.assertEqual(self.widget.ui.editMassDensity.text(), "1")
-        self.assertEqual(self.widget.ui.editWavelength.text(), "6")
 
     def testHelp(self):
Index: src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py	(revision 0989bad7947a795a616529562dfa130518a575ad)
+++ src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py	(revision c02721c4e06ef72ac9df56ad7390b73484c3d35c)
@@ -740,5 +740,5 @@
                                 caption="Save As",
                                 directory='cyl_400_20_out.txt',
-                                filter='Text files (*.txt);;CanSAS 1D files(*.xml)',
+                                filter='Text files (*.txt);;CanSAS 1D files(*.xml);;NXcanSAS files (*.h5)',
                                 parent=None)
         QFileDialog.getSaveFileName.assert_called_once()
@@ -763,5 +763,5 @@
                                 caption="Save As",
                                 directory='P123_D2O_10_percent_out.dat',
-                                filter='IGOR/DAT 2D file in Q_map (*.dat)',
+                                filter='IGOR/DAT 2D file in Q_map (*.dat);;NXcanSAS files (*.h5)',
                                 parent=None)
         QFileDialog.getSaveFileName.assert_called_once()
Index: src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py
===================================================================
--- src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py	(revision 0989bad7947a795a616529562dfa130518a575ad)
+++ src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py	(revision c02721c4e06ef72ac9df56ad7390b73484c3d35c)
@@ -147,5 +147,5 @@
         """
         self.manager.processVersion = MagicMock()
-        version = {'version'     : '4.2.0',
+        version = {'version'     : '4.2.1',
                    'update_url'  : 'http://www.sasview.org/sasview.latestversion', 
                    'download_url': 'https://github.com/SasView/sasview/releases'}
Index: src/sas/qtgui/Perspectives/Fitting/ComplexConstraint.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ComplexConstraint.py	(revision cf9f39e5e737436edc70fa14348eedd3e53ad0fd)
+++ src/sas/qtgui/Perspectives/Fitting/ComplexConstraint.py	(revision 460bdf4c052ff6f671c1ffdf9c6c48fe91b180f1)
@@ -150,7 +150,7 @@
         param2 = self.cbParam2.currentText()
         if source == "cbParam1":
-            self.txtParam.setText(self.tab_names[0] + ":" + param1)
+            self.txtParam.setText(self.cbModel1.currentText() + ":" + param1)
         else:
-            self.txtConstraint.setText(self.tab_names[1] + "." + param2)
+            self.txtConstraint.setText(self.cbModel2.currentText() + "." + param2)
         # Check if any of the parameters are polydisperse
         params_list = [param1, param2]
Index: src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py	(revision 14e1ff0d1f5ac266749e22c8f7fa56d727ccfea8)
+++ src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py	(revision 770c42cb0be1ffe38c43f20f9123bbcd6bb1142d)
@@ -432,8 +432,9 @@
         """
         item = self.tblConstraints.item(row, column)
-        if column != 0: return
-        # Update the tabs for fitting list
-        constraint = self.available_constraints[row]
-        constraint.active = (item.checkState() == QtCore.Qt.Checked)
+        if column == 0:
+            # Update the tabs for fitting list
+            constraint = self.available_constraints[row]
+            constraint.active = (item.checkState() == QtCore.Qt.Checked)
+            return
         # Update the constraint formula
         constraint = self.available_constraints[row]
@@ -470,4 +471,5 @@
         self.cmdFit.setStyleSheet('QPushButton {color: black;}')
         self.cmdFit.setText("Fit")
+        self.is_running = False
 
         # Notify the parent about completed fitting
@@ -515,4 +517,5 @@
         self.cmdFit.setStyleSheet('QPushButton {color: black;}')
         self.cmdFit.setText("Fit")
+        self.is_running = False
 
         # Notify the parent about completed fitting
@@ -549,4 +552,5 @@
         self.cmdFit.setStyleSheet('QPushButton {color: black;}')
         self.cmdFit.setText("Fit")
+        self.is_running = False
 
         # Notify the parent about completed fitting
@@ -769,5 +773,6 @@
             item = self.uneditableItem(label)
             item = QtWidgets.QTableWidgetItem(label)
-            item.setFlags(item.flags() ^ QtCore.Qt.ItemIsUserCheckable)
+            # Why was this set to non-interactive??
+            #item.setFlags(item.flags() ^ QtCore.Qt.ItemIsUserCheckable)
             item.setCheckState(QtCore.Qt.Checked)
             self.tblConstraints.insertRow(pos)
Index: src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision f5e2a10a96d515dd975853c6c54b801e4f37b6a4)
+++ src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision c7e73e7c9b524a33a096684ea9e57c350e0df3f1)
@@ -166,4 +166,5 @@
             if cbox:
                 view.setIndexWidget(item2.index(), cbox)
+
         rows.append(row)
 
@@ -202,5 +203,5 @@
         item1 = QtGui.QStandardItem(item_name)
         item1.setData(param.name, QtCore.Qt.UserRole)
-        item1.setCheckable(True)
+        item1.setCheckable(False)
         item1.setEditable(False)
 
@@ -219,4 +220,5 @@
         # Append to the model and use the combobox, if required
         if None not in (model, view):
+
             if row_num is None:
                 model.appendRow(row)
@@ -224,7 +226,13 @@
                 model.insertRow(row_num, row)
                 row_num += 1
-
             if cbox:
+                item1.setCheckable(False)
+                item3.setText("")
+                item4.setText("")
+                item3.setEditable(False)
+                item4.setEditable(False)
                 view.setIndexWidget(item2.index(), cbox)
+            else:
+                item1.setCheckable(True)
 
         rows.append(row)
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision c149fba985009ceab4afc61937f209ab90df4cc0)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 73fb50331d043c9535e144e78fd8d9a580798d50)
@@ -1161,4 +1161,9 @@
         if category == CATEGORY_STRUCTURE:
             model = None
+        # copy original clipboard
+        cb = QtWidgets.QApplication.clipboard()
+        cb_text = cb.text()
+        # get the screenshot of the current param state
+        self.onCopyToClipboard("")
 
         # Reset parameters to fit
@@ -1168,4 +1173,8 @@
 
         self.respondToModelStructure(model=model, structure_factor=structure)
+        # recast the original parameters into the model
+        self.onParameterPaste()
+        # revert to the original clipboard
+        cb.setText(cb_text)
 
     def resetParametersToFit(self):
@@ -2030,4 +2039,5 @@
         if not self.data_is_loaded:
             self.createDefaultDataset()
+            self.smearing_widget.updateData(self.data)
         self.calculateQGridForModel()
 
@@ -2870,8 +2880,4 @@
         self.createNewIndex(weighted_data)
 
-        # Plot residuals if actual data
-        if not self.data_is_loaded:
-            return
-
         # Calculate difference between return_data and logic.data
         self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.data)
@@ -2879,4 +2885,8 @@
         chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True)
         self.lblChi2Value.setText(chi2_repr)
+
+        # Plot residuals if actual data
+        if not self.data_is_loaded:
+            return
 
         residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data)
Index: src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py	(revision 17e6a2b1ddaf02c92de000d39b51da0de039314b)
+++ src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py	(revision dc3b34eb2b03545c0e60b8cb7cb064048d8faa07)
@@ -173,7 +173,9 @@
             self.rbWeighting2.setEnabled(True)
             self.rbWeighting2.setChecked(True)
+            self.onWeightingChoice(self.rbWeighting2)
         else:
             self.rbWeighting2.setEnabled(False)
             self.rbWeighting1.setChecked(True)
+            self.onWeightingChoice(self.rbWeighting1)
 
     def updateQRange(self, q_range_min, q_range_max, npts):
Index: src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py	(revision a5f7bf46609d4b1b0851bfc34037a998c20f161e)
+++ src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py	(revision 73fb50331d043c9535e144e78fd8d9a580798d50)
@@ -64,7 +64,13 @@
         self.kernel_model = None
         # dQ data variables
-        smear_type = None
-        dq_l = None
-        dq_r = None
+        self.smear_type = None
+        self.dq_l = None
+        self.dq_r = None
+
+        # current pinhole/slot values
+        self.pinhole = 0.0
+        self.slit_height = 0.0
+        self.slit_width = 0.0
+
         # Let only floats in the line edits
         self.txtSmearDown.setValidator(GuiUtils.DoubleValidator())
@@ -109,4 +115,6 @@
         Update control elements based on data and model passed
         """
+        # retain the index
+        cur_index = self.cbSmearing.currentIndex()
         self.cbSmearing.clear()
         self.cbSmearing.addItem("None")
@@ -117,4 +125,6 @@
         model = self.kernel_model
         self.updateKernelModel(model)
+        # already has the required setup so modify the index
+        self.cbSmearing.setCurrentIndex(cur_index)
 
     def updateKernelModel(self, kernel_model=None):
@@ -184,4 +194,14 @@
         # Recalculate the smearing
         index = self.cbSmearing.currentIndex()
+        ## update the backup values based on model choice
+        smearing, accuracy, d_down, d_up = self.state()
+        # don't save the state if dQ Data
+        if smearing == "Custom Pinhole Smear":
+            self.pinhole = d_down
+            self.accuracy = accuracy
+        elif smearing == 'Custom Slit Smear':
+            self.slit_height = d_up
+            self.slit_width = d_down
+
         self.onIndexChange(index)
 
@@ -221,4 +241,6 @@
             self.lblSmearUp.setText('<html><head/><body><p>dQ/Q</p></body></html>')
             self.lblUnitUp.setText('%')
+        self.txtSmearUp.setText(str(self.pinhole))
+
         self.txtSmearDown.setEnabled(True)
         self.txtSmearUp.setEnabled(True)
@@ -234,4 +256,6 @@
         self.lblUnitDown.setText('<html><head/><body><p>Ã
 <span style=" vertical-align:super;">-1</span></p></body></html>')
+        self.txtSmearDown.setText(str(self.slit_height))
+        self.txtSmearUp.setText(str(self.slit_width))
         self.txtSmearDown.setEnabled(True)
         self.txtSmearUp.setEnabled(True)
@@ -277,9 +301,9 @@
             accuracy = str(self.model.item(MODEL.index('ACCURACY')).text())
             try:
-                d_down = float(self.model.item(MODEL.index('PINHOLE_MIN')).text())
+                d_down = float(self.txtSmearUp.text())
             except ValueError:
                 d_down = None
             try:
-                d_up = float(self.model.item(MODEL.index('PINHOLE_MAX')).text())
+                d_up = float(self.txtSmearDown.text())
             except ValueError:
                 d_up = None
@@ -292,6 +316,4 @@
         """
         # Update the model -> controls update automatically
-        #if smearing is not None:
-            #self.model.item(MODEL.index('SMEARING')).setText(smearing)
         if accuracy is not None:
             self.model.item(MODEL.index('ACCURACY')).setText(accuracy)
@@ -347,4 +369,7 @@
         if d_height is None:
             d_height = 0.0
+
+        self.slit_width = d_width
+        self.slit_height = d_height
 
         if isinstance(self.data, Data2D):
Index: src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py	(revision 0989bad7947a795a616529562dfa130518a575ad)
+++ src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py	(revision 6edd344fa796b585fa45b51c842214a9caa8024e)
@@ -205,4 +205,5 @@
         model_index = self.widget.cbModel.findText("be_polyelectrolyte")
         self.widget.cbModel.setCurrentIndex(model_index)
+        QtWidgets.qApp.processEvents()
 
         # check the enablement of controls
@@ -242,8 +243,8 @@
         self.widget.show()
         # Change the category index so we have some models
-        category_index = self.widget.cbCategory.findText("Shape Independent")
+        category_index = self.widget.cbCategory.findText("Cylinder")
         self.widget.cbCategory.setCurrentIndex(category_index)
         # Change the model to one that supports structure factors
-        model_index = self.widget.cbModel.findText('fractal_core_shell')
+        model_index = self.widget.cbModel.findText('cylinder')
         self.widget.cbModel.setCurrentIndex(model_index)
 
@@ -260,6 +261,6 @@
         self.widget.cbStructureFactor.setCurrentIndex(structure_index)
 
-        # We have 3 more param rows now (radius_effective is removed), and a new heading
-        self.assertEqual(self.widget._model_model.rowCount(), rowcount+4)
+        # We have 3 more param rows now (radius_effective is removed), and new headings
+        self.assertEqual(self.widget._model_model.rowCount(), rowcount+7)
 
         # Switch models
@@ -1229,4 +1230,5 @@
         model_index = self.widget.cbModel.findText("pringle")
         self.widget.cbModel.setCurrentIndex(model_index)
+        QtWidgets.qApp.processEvents()
 
         # make sure the parameters are different than before
Index: src/sas/qtgui/Plotting/Plotter.py
===================================================================
--- src/sas/qtgui/Plotting/Plotter.py	(revision 033b1f2daaad682d400e8d592e8850c77c76ed5f)
+++ src/sas/qtgui/Plotting/Plotter.py	(revision 033b1f2daaad682d400e8d592e8850c77c76ed5f)
@@ -19,4 +19,11 @@
 import sas.qtgui.Utilities.GuiUtils as GuiUtils
 import sas.qtgui.Plotting.PlotUtilities as PlotUtilities
+
+def _legendResize(width):
+    """
+    resize factor for the legend, based on total canvas width
+    """
+    # The factor 4.0 was chosen to look similar in size/ratio to what we had in 4.x
+    return (width/100.0)+4.0
 
 class PlotterWidget(PlotterBase):
@@ -200,5 +207,7 @@
 
         if self.showLegend:
-            self.legend = ax.legend(loc='upper right', shadow=True)
+            width=_legendResize(self.canvas.size().width())
+
+            self.legend = ax.legend(loc='upper right', shadow=True, prop={'size':width})
             if self.legend:
                 self.legend.set_picker(True)
@@ -212,4 +221,14 @@
         # refresh canvas
         self.canvas.draw_idle()
+
+    def onResize(self, event):
+        """
+        Resize the legend window/font on canvas resize
+        """
+        if not self.showLegend:
+            return
+        width = _legendResize(event.width)
+        # resize the legend to follow the canvas width.
+        self.legend.prop.set_size(width)
 
     def createContextMenu(self):
Index: src/sas/qtgui/Plotting/PlotterBase.py
===================================================================
--- src/sas/qtgui/Plotting/PlotterBase.py	(revision 8fad50b6fe76dab5d0e3bf9354f49fe14e9db9cb)
+++ src/sas/qtgui/Plotting/PlotterBase.py	(revision b016f171dcf6aededb288405b9bf26ba698712b4)
@@ -111,4 +111,6 @@
         self.contextMenu = QtWidgets.QMenu(self)
         self.toolbar = NavigationToolbar(self.canvas, self)
+        cid = self.canvas.mpl_connect('resize_event', self.onResize)
+
         layout.addWidget(self.toolbar)
         if not quickplot:
@@ -244,4 +246,10 @@
         raise NotImplementedError("Context menu method must be implemented in derived class.")
 
+    def onResize(self, event):
+        """
+        Redefine default resize event
+        """
+        pass
+
     def contextMenuEvent(self, event):
         """
Index: src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py
===================================================================
--- src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py	(revision d32a594acc82ad29555832f498167b51564c75f3)
+++ src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py	(revision d32a594acc82ad29555832f498167b51564c75f3)
@@ -410,5 +410,5 @@
 
         # Replace data in plot
-        self.plotter.replacePlot(1, data2)
+        self.plotter.replacePlot("Test name", data2)
 
         # See that the labels changed
Index: src/sas/qtgui/Utilities/UnitTesting/TabbedModelEditorTest.py
===================================================================
--- src/sas/qtgui/Utilities/UnitTesting/TabbedModelEditorTest.py	(revision 80468f6c91cf372023748231c493da2c7009a763)
+++ src/sas/qtgui/Utilities/UnitTesting/TabbedModelEditorTest.py	(revision c02721c4e06ef72ac9df56ad7390b73484c3d35c)
@@ -204,4 +204,5 @@
         self.widget.editor_widget.txtEditor.toPlainText = MagicMock(return_value=boring_text)
         self.widget.writeFile = MagicMock()
+        self.widget.plugin_widget.is_python = MagicMock()
         #invoke the method
         self.widget.updateFromEditor()
