Index: src/sas/qtgui/MainWindow/DataExplorer.py
===================================================================
--- src/sas/qtgui/MainWindow/DataExplorer.py	(revision 133812c7ffae92cd47338d64c4d757261f78a6a6)
+++ src/sas/qtgui/MainWindow/DataExplorer.py	(revision e5ae812f0eed528ccbbb352ea37a563795d26902)
@@ -457,4 +457,6 @@
                 self.chkBatch.setChecked(True if value=='True' else False)
                 continue
+            if 'cs_tab' in key:
+                continue
             # send newly created items to the perspective
             self.updatePerspectiveWithProperties(key, value)
@@ -462,4 +464,9 @@
         # See if there are any batch pages defined and create them, if so
         self.updateWithBatchPages(all_data)
+
+        # Only now can we create/assign C&S pages.
+        for key, value in all_data.items():
+            if 'cs_tab' in key:
+                self.updatePerspectiveWithProperties(key, value)
 
     def updateWithBatchPages(self, all_data):
@@ -488,5 +495,4 @@
                 self._perspective().setData(data_item=items, is_batch=True)
                 self._perspective().updateFromParameters(page)
-
         pass
 
@@ -494,7 +500,8 @@
         """
         """
-        data_dict = {key:value['fit_data']}
-        # Create new model items in the data explorer
-        items = self.updateModelFromData(data_dict)
+        if 'fit_data' in value:
+            data_dict = {key:value['fit_data']}
+            # Create new model items in the data explorer
+            items = self.updateModelFromData(data_dict)
 
         if 'fit_params' in value:
@@ -512,4 +519,10 @@
                 # Assign parameters to the most recent (current) page.
                 self._perspective().updateFromParameters(page)
+        if 'cs_tab' in key and 'is_constraint' in value:
+            # Create a C&S page
+            self._perspective().addConstraintTab()
+            # Modify the tab
+            self._perspective().updateFromParameters(value)
+
         pass # debugger
 
Index: src/sas/qtgui/MainWindow/GuiManager.py
===================================================================
--- src/sas/qtgui/MainWindow/GuiManager.py	(revision 133812c7ffae92cd47338d64c4d757261f78a6a6)
+++ src/sas/qtgui/MainWindow/GuiManager.py	(revision e5ae812f0eed528ccbbb352ea37a563795d26902)
@@ -594,4 +594,10 @@
             analysis[id] = data_content
 
+        # standalone constraint pages
+        for keys, values in params.items():
+            if not 'is_constraint' in values[0]:
+                continue
+            analysis[keys] = values[0]
+
         with open(filename, 'w') as outfile:
             GuiUtils.saveData(outfile, analysis)
@@ -1177,7 +1183,8 @@
             out_f.write("#Application appearance custom configuration\n")
             for key, item in config.__dict__.items():
-                if key[:2] != "__":
-                    if isinstance(item, str):
-                        item = '"' + item + '"'
-                    out_f.write("%s = %s\n" % (key, str(item)))
+                if key[:2] == "__":
+                    continue
+                if isinstance(item, str):
+                    item = '"' + item + '"'
+                out_f.write("%s = %s\n" % (key, str(item)))
         pass # debugger anchor
Index: src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py	(revision aed053275d5f293f1f6495be4c78e4b18fc52b41)
+++ src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py	(revision e5ae812f0eed528ccbbb352ea37a563795d26902)
@@ -31,4 +31,5 @@
         # To keep with previous SasView values, use 300 as the start offset
         self.page_id = 301
+        self.tab_id = self.page_id
 
         # Are we chain fitting?
@@ -693,2 +694,78 @@
         # Update the tab
         constrained_tab.addConstraintToRow(constraint, constrained_row)
+
+    def getFitPage(self):
+        """
+        Retrieves the state of this page
+        """
+        param_list = []
+
+        param_list.append(['is_constraint', 'True'])
+        param_list.append(['data_id', "cs_tab"+str(self.page_id)])
+        param_list.append(['current_type', self.currentType])
+        param_list.append(['is_chain_fitting', str(self.is_chain_fitting)])
+        param_list.append(['special_case', self.cbCases.currentText()])
+
+        return param_list
+
+    def getFitModel(self):
+        """
+        Retrieves current model
+        """
+        model_list = []
+
+        checked_models = {}
+        for row in range(self.tblTabList.rowCount()):
+            model_name = self.tblTabList.item(row,1).data(0)
+            active = self.tblTabList.item(row,0).checkState()# == QtCore.Qt.Checked
+            checked_models[model_name] = str(active)
+
+        checked_constraints = {}
+        for row in range(self.tblConstraints.rowCount()):
+            model_name = self.tblConstraints.item(row,0).data(0)
+            active = self.tblConstraints.item(row,0).checkState()# == QtCore.Qt.Checked
+            checked_constraints[model_name] = str(active)
+
+        model_list.append(['checked_models', checked_models])
+        model_list.append(['checked_constraints', checked_constraints])
+        return model_list
+
+    def createPageForParameters(self, parameters=None):
+        """
+        Update the page with passed parameter values
+        """
+        # checked models
+        if not 'checked_models' in parameters:
+            return
+        models = parameters['checked_models'][0]
+        for model, check_state in models.items():
+            for row in range(self.tblTabList.rowCount()):
+                model_name = self.tblTabList.item(row,1).data(0)
+                if model_name != model:
+                    continue
+                # check/uncheck item
+                self.tblTabList.item(row,0).setCheckState(int(check_state))
+
+        if not 'checked_constraints' in parameters:
+            return
+        # checked constraints
+        models = parameters['checked_constraints'][0]
+        for model, check_state in models.items():
+            for row in range(self.tblConstraints.rowCount()):
+                model_name = self.tblConstraints.item(row,0).data(0)
+                if model_name != model:
+                    continue
+                # check/uncheck item
+                self.tblConstraints.item(row,0).setCheckState(int(check_state))
+
+        # fit/batch radio
+        isBatch = parameters['current_type'][0] == 'BatchPage'
+        if isBatch:
+            self.btnBatch.toggle()
+
+        # chain
+        is_chain = parameters['is_chain_fitting'][0] == 'True'
+        if isBatch:
+            self.chkChain.setChecked(is_chain)
+
+
Index: src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py	(revision ebcdb028e10e042622af7e7cce371902d3f511be)
+++ src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py	(revision e5ae812f0eed528ccbbb352ea37a563795d26902)
@@ -39,7 +39,4 @@
         self.maxIndex = 1
 
-        ## Index of the current tab
-        #self.currentTab = 0
-
         # The default optimizer
         self.optimizer = 'Levenberg-Marquardt'
@@ -121,5 +118,4 @@
         for i, tab in enumerate(self.tabs):
             tab_data = self.getSerializedFitpage(tab)
-            if tab.tab_id is None: continue
             if 'data_id' not in tab_data: continue
             id = tab_data['data_id'][0]
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 133812c7ffae92cd47338d64c4d757261f78a6a6)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision e5ae812f0eed528ccbbb352ea37a563795d26902)
@@ -1952,5 +1952,5 @@
         Emits plotRequestedSignal for all plots found in the given model under the provided item name.
         """
-        fitpage_name = "" if self.tab_id is None else "M"+str(self.tab_id)
+        fitpage_name = self.kernel_module.name
         plots = GuiUtils.plotsFromFilename(item_name, item_model)
         # Has the fitted data been shown?
@@ -3524,4 +3524,5 @@
         param_list.append(['data_name', filenames])
         param_list.append(['data_id', data_ids])
+        param_list.append(['tab_name', self.modelName()])
         # option tab
         param_list.append(['q_range_min', str(self.q_range_min)])
@@ -3596,6 +3597,13 @@
             except:
                 pass
-
-            param_list.append([param_name, param_checked, param_value, param_error, param_min, param_max])
+            # Do we have any constraints on this parameter?
+            constraint = self.getConstraintForRow(row)
+            cons = ()
+            if constraint is not None:
+                value = constraint.value
+                func = constraint.func
+                cons = (value, func)
+
+            param_list.append([param_name, param_checked, param_value, param_error, param_min, param_max, cons])
 
         def gatherPolyParams(row):
@@ -3705,4 +3713,6 @@
                 self.updateMultiplicityCombo(multip)
 
+        if 'tab_name' in line_dict.keys():
+            self.kernel_module.name = line_dict['tab_name'][0]
         if 'polydisperse_params' in line_dict.keys():
             self.chkPolydispersity.setChecked(line_dict['polydisperse_params'][0]=='True')
@@ -3827,5 +3837,5 @@
             ioffset = 0
             joffset = 0
-            if len(param_dict[param_name])>4:
+            if len(param_dict[param_name])>5:
                 # error values are not editable - no need to update
                 ioffset = 1
@@ -3840,4 +3850,14 @@
             except:
                 pass
+
+            # constraints
+            cons = param_dict[param_name][4+ioffset]
+            if cons is not None and cons:
+                value = cons[0]
+                function = cons[1]
+                constraint = Constraint()
+                constraint.value = value
+                constraint.func = function
+                self.addConstraintToRow(constraint=constraint, row=row)
 
             self.setFocus()
