Index: src/sas/qtgui/MainWindow/DataExplorer.py
===================================================================
--- src/sas/qtgui/MainWindow/DataExplorer.py	(revision 6bc0840f26b427a0c4015b3221f9359d76e89e1d)
+++ src/sas/qtgui/MainWindow/DataExplorer.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -225,12 +225,31 @@
         Called when the "Open Project" menu item chosen.
         """
+        # check if any items loaded and warn about data deletion
+        if self.model.rowCount() > 0:
+            msg = "This operation will set remove all data, plots and analyses from"
+            msg += " SasView before loading the project. Do you wish to continue?"
+            msgbox = QtWidgets.QMessageBox(self)
+            msgbox.setIcon(QtWidgets.QMessageBox.Warning)
+            msgbox.setText(msg)
+            msgbox.setWindowTitle("Project Load")
+            # custom buttons
+            button_yes = QtWidgets.QPushButton("Yes")
+            msgbox.addButton(button_yes, QtWidgets.QMessageBox.YesRole)
+            button_no = QtWidgets.QPushButton("No")
+            msgbox.addButton(button_no, QtWidgets.QMessageBox.RejectRole)
+            retval = msgbox.exec_()
+            if retval == QtWidgets.QMessageBox.RejectRole:
+                # cancel fit
+                return
+
         kwargs = {
             'parent'    : self,
             'caption'   : 'Open Project',
-            'filter'    : 'Project (*.json);;All files (*.*)',
+            'filter'    : 'Project Files (*.json);;Old Project Files (*.svs);;All files (*.*)',
             'options'   : QtWidgets.QFileDialog.DontUseNativeDialog
         }
         filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0]
         if filename:
+            self.deleteAllItems()
             self.readProject(filename)
 
@@ -374,6 +393,17 @@
         Read out datasets and fitpages from file
         """
-        with open(filename, 'r') as infile:
-            all_data = GuiUtils.readDataFromFile(infile)
+        # Find out the filetype based on extension
+        ext = os.path.splitext(filename)[1]
+        all_data = {}
+        if 'svs' in ext.lower():
+            # backward compatibility mode.
+            datasets = GuiUtils.readProjectFromSVS(filename)
+            #[[item_1, state_1], [item_2, state_2],...]
+
+            # Convert fitpage properties and update the dict
+            all_data = GuiUtils.convertFromSVS(datasets)
+        else:
+            with open(filename, 'r') as infile:
+                all_data = GuiUtils.readDataFromFile(infile)
 
         for key, value in all_data.items():
@@ -420,4 +450,8 @@
             if not value: continue
             new_data = value[0]
+            from sas.sascalc.dataloader.data_info import Data1D as old_data1d
+            from sas.sascalc.dataloader.data_info import Data2D as old_data2d
+            if isinstance(new_data, (old_data1d, old_data2d)):
+                new_data = self.manager.create_gui_data(value[0], new_data.filename)
             assert isinstance(new_data, (Data1D, Data2D))
             properties = value[1]
@@ -1202,5 +1236,5 @@
         self.actionQuick3DPlot.triggered.connect(self.quickData3DPlot)
         self.actionEditMask.triggered.connect(self.showEditDataMask)
-        self.actionDelete.triggered.connect(self.deleteItem)
+        self.actionDelete.triggered.connect(self.deleteSelectedItem)
         self.actionFreezeResults.triggered.connect(self.freezeSelectedItems)
 
@@ -1415,5 +1449,20 @@
                 self.freezeItem(item_to_copy)
 
-    def deleteItem(self):
+    def deleteAllItems(self):
+        """
+        Deletes all datasets from both model and theory_model
+        """
+        deleted_items = [self.model.item(row) for row in range(self.model.rowCount())
+                         if self.model.item(row).isCheckable()]
+        deleted_names = [item.text() for item in deleted_items]
+        # Let others know we deleted data
+        self.communicator.dataDeletedSignal.emit(deleted_items)
+        # update stored_data
+        self.manager.update_stored_data(deleted_names)
+
+        # Clear the model
+        self.model.clear()
+
+    def deleteSelectedItem(self):
         """
         Delete the current item
@@ -1432,20 +1481,27 @@
             return
 
+        indices = self.current_view.selectedIndexes()
+        self.deleteIndices(indices)
+
+    def deleteIndices(self, indices):
+        """
+        Delete model idices from the current view
+        """
+        proxy = self.current_view.model()
+        model = proxy.sourceModel()
+
+        deleted_items = []
+        deleted_names = []
+
         # Every time a row is removed, the indices change, so we'll just remove
         # rows and keep calling selectedIndexes until it returns an empty list.
-        indices = self.current_view.selectedIndexes()
-
-        proxy = self.current_view.model()
-        model = proxy.sourceModel()
-
-        deleted_items = []
-        deleted_names = []
-
         while len(indices) > 0:
             index = indices[0]
-            row_index = proxy.mapToSource(index)
-            item_to_delete = model.itemFromIndex(row_index)
+            #row_index = proxy.mapToSource(index)
+            #item_to_delete = model.itemFromIndex(row_index)
+            item_to_delete = model.itemFromIndex(index)
             if item_to_delete and item_to_delete.isCheckable():
-                row = row_index.row()
+                #row = row_index.row()
+                row = index.row()
 
                 # store the deleted item details so we can pass them on later
Index: src/sas/qtgui/MainWindow/GuiManager.py
===================================================================
--- src/sas/qtgui/MainWindow/GuiManager.py	(revision 874875175cbb93b53c1b431ab154ab62644c5a69)
+++ src/sas/qtgui/MainWindow/GuiManager.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -464,5 +464,5 @@
         self._workspace.actionOpen_Project.triggered.connect(self.actionOpen_Project)
         self._workspace.actionOpen_Analysis.triggered.connect(self.actionOpen_Analysis)
-        self._workspace.actionSave.triggered.connect(self.actionSave)
+        self._workspace.actionSave.triggered.connect(self.actionSave_Project)
         self._workspace.actionSave_Analysis.triggered.connect(self.actionSave_Analysis)
         self._workspace.actionQuit.triggered.connect(self.actionQuit)
@@ -557,5 +557,5 @@
         pass
 
-    def actionSave(self):
+    def actionSave_Project(self):
         """
         Menu Save Project
Index: src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py	(revision a24eacf3b3a9ca51fe5e34059e28454573779b5f)
+++ src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -854,5 +854,5 @@
 
         # Attempt at deleting
-        self.form.deleteItem()
+        self.form.deleteSelectedItem()
 
         # Test the warning dialog called once
@@ -868,5 +868,5 @@
         self.form.current_view.selectionModel().select(select_index, QtCore.QItemSelectionModel.Rows)
         # delete it. now for good
-        self.form.deleteItem()
+        self.form.deleteSelectedItem()
 
         # Test the warning dialog called once
Index: src/sas/qtgui/Utilities/GuiUtils.py
===================================================================
--- src/sas/qtgui/Utilities/GuiUtils.py	(revision aed159f2c55235b1eb207e55b5601081f66c913c)
+++ src/sas/qtgui/Utilities/GuiUtils.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -295,4 +295,5 @@
     resultPlotUpdateSignal = QtCore.pyqtSignal(list)
 
+def updateModelItemWithPlot(item, update_data, name="", checkbox_state=None):
     """
     Adds a checkboxed row named "name" to QStandardItem
@@ -1287,4 +1288,104 @@
     return new_stored_data
 
+def readProjectFromSVS(filepath):
+    """
+    Read old SVS file and convert to the project dictionary
+    """
+    from sas.sascalc.dataloader.readers.cansas_reader import Reader as CansasReader
+    from sas.sascalc.fit.pagestate import Reader
+
+    loader = Loader()
+    loader.associate_file_reader('.svs', Reader)
+    temp = loader.load(filepath)
+    state_reader = Reader()
+    data_svs, state_svs = state_reader.read(filepath)
+
+    output = []
+    if isinstance(temp, list) and isinstance(state_svs, list):
+        for item, state in zip(temp, state_svs):
+            output.append([item, state])
+    else:
+        output[temp, state_svs]
+    return output
+
+def convertFromSVS(datasets):
+    """
+    Read in properties from SVS and convert into a simple dict
+    """
+    content = {}
+    for dataset in datasets:
+        # we already have data - interested only in properties
+        #[[item_1, state_1], [item_2, state_2],...]
+        data = dataset[0]
+        params = dataset[1]
+        content[params.data_id] = {}
+        content[params.data_id]['fit_data'] = [data, {'checked': 2}, []]
+        param_dict = {}
+        param_dict['fitpage_category'] = [params.categorycombobox]
+        param_dict['fitpage_model'] = [params.formfactorcombobox]
+        param_dict['fitpage_structure'] = [params.structurecombobox]
+        param_dict['2D_params'] = [str(params.is_2D)]
+        param_dict['chainfit_params'] = ["False"]
+        param_dict['data_id'] = [params.data_id]
+        param_dict['data_name'] = [params.data_name]
+        param_dict['is_data'] = [str(params.is_data)]
+        param_dict['magnetic_params'] = [str(params.magnetic_on)]
+        param_dict['model_name'] = [params.formfactorcombobox]
+        param_dict['polydisperse_params'] = [str(params.enable_disp)]
+        param_dict['q_range_max'] = [str(params.qmax)]
+        param_dict['q_range_min'] = [str(params.qmin)]
+        # Smearing is a bit trickier. 4.x has multiple keywords,
+        # one for each combobox option
+        if params.enable_smearer:
+            if params.slit_smearer:
+                w = 1
+            elif params.pinhole_smearer:
+                w = 2
+            else:
+                w = 0
+            param_dict['smearing'] = [str(w)]
+        # weighting is a bit trickier. 4.x has multiple keywords,
+        # one for each radio box.
+        if params.dI_noweight:
+            w = 2
+        elif params.dI_didata:
+            w = 3
+        elif params.dI_sqrdata:
+            w = 4
+        elif params.dI_idata:
+            w = 5
+        else:
+            w = 2
+        param_dict['weighting'] = [str(w)]
+
+        # 4.x multi_factor is really the multiplicity
+        if params.multi_factor is not None:
+            param_dict['multiplicity'] = [str(int(params.multi_factor))]
+
+        # playing with titles
+        data.filename = params.file
+        data.title = params.data_name
+        data.name = params.data_name
+
+        # main parameters
+        for p in params.parameters:
+            p_name = p[1]
+            param_dict[p_name] = [str(p[0]), str(p[2]), None, str(p[5][1]), str(p[6][1])]
+        # orientation parameters
+        if params.is_2D:
+            for p in params.orientation_params:
+                p_name = p[1]
+                param_dict[p_name] = [str(p[0]), str(p[2]), None, str(p[5][1]), str(p[6][1])]
+
+        # disperse parameters
+        if params.enable_disp:
+            for p in params.fittable_param:
+                p_name = p[1]
+                param_dict[p_name] = [str(p[0]), str(p[2]), None, str(35), str(3)]
+
+        # magnetic parameters
+
+        content[params.data_id]['fit_params'] = param_dict
+    return content
 
 def enum(*sequential, **named):
Index: src/sas/sascalc/dataloader/readers/cansas_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision b8080e1affadb04559f0597dfddc5506d2044e9d)
+++ src/sas/sascalc/dataloader/readers/cansas_reader.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -184,5 +184,5 @@
             if CANSAS_NS.get(self.cansas_version).get("ns") == value.rsplit(" ")[0]:
                 return True
-        if ext == "svs":
+        if ext == ".svs":
             return True # Why is this required?
         # If we get to this point then file isn't valid CanSAS
Index: src/sas/sascalc/fit/pagestate.py
===================================================================
--- src/sas/sascalc/fit/pagestate.py	(revision b8080e1affadb04559f0597dfddc5506d2044e9d)
+++ src/sas/sascalc/fit/pagestate.py	(revision b1b71ad1ed5ead42519d7e4b99f61af65d85f3aa)
@@ -1249,12 +1249,13 @@
 
             else:
-                self.call_back(format=ext)
+                #self.call_back(format=ext)
                 raise RuntimeError("%s is not a file" % path)
 
             # Return output consistent with the loader's api
             if len(output) == 0:
-                self.call_back(state=None, datainfo=None, format=ext)
+                #self.call_back(state=None, datainfo=None, format=ext)
                 return None
             else:
+                states=[]
                 for data in output:
                     # Call back to post the new state
@@ -1281,5 +1282,5 @@
                         if isinstance(data.run_name, dict):
                             # Note: key order in dict is not guaranteed, so sort
-                            name = data.run_name.keys()[0]
+                            name = list(data.run_name.keys())[0]
                         else:
                             name = data.run_name
@@ -1289,13 +1290,14 @@
                     state.version = fitstate.version
                     # store state in fitting
-                    self.call_back(state=state, datainfo=data, format=ext)
+                    #self.call_back(state=state, datainfo=data, format=ext)
                     self.state = state
+                    states.append(state)
                 simfitstate = self._parse_simfit_state(entry)
                 if simfitstate is not None:
-                    self.call_back(state=simfitstate)
-
-                return output
+                    #self.call_back(state=simfitstate)
+                    states.append(simfitstate)
+                return (output, states)
         except:
-            self.call_back(format=ext)
+            #self.call_back(format=ext)
             raise
 
