Index: src/sas/qtgui/DataExplorer.py
===================================================================
--- src/sas/qtgui/DataExplorer.py	(revision 481ff261d4487dbfcc8eabb342125294e0c6f514)
+++ src/sas/qtgui/DataExplorer.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
@@ -2,4 +2,5 @@
 import sys
 import os
+import time
 import logging
 
@@ -16,4 +17,6 @@
 from sas.sascalc.dataloader.loader import Loader
 from sas.sasgui.guiframe.data_manager import DataManager
+from sas.sasgui.guiframe.dataFitting import Data1D
+from sas.sasgui.guiframe.dataFitting import Data2D
 
 from DroppableDataLoadWidget import DroppableDataLoadWidget
@@ -57,4 +60,13 @@
         self._helpView = QtWebKit.QWebView()
 
+        # Context menu in the treeview
+        #self.treeView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
+        #self.actionDataInfo.triggered.connect(self.contextDataInfo)
+        #self.treeView.addAction(self.actionDataInfo)
+
+        # Custom context menu
+        self.treeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+        self.treeView.customContextMenuRequested.connect(self.onCustomContextMenu)
+
         # Connect the comboboxes
         self.cbSelect.currentIndexChanged.connect(self.selectData)
@@ -62,5 +74,5 @@
         #self.closeEvent.connect(self.closeEvent)
         # self.aboutToQuit.connect(self.closeEvent)
-
+        self.communicator = self.parent.communicator()
         self.communicator.fileReadSignal.connect(self.loadFromURL)
 
@@ -133,5 +145,5 @@
         # get content of dir into a list
         path_str = [os.path.join(os.path.abspath(folder), filename)
-                        for filename in os.listdir(folder)]
+                    for filename in os.listdir(folder)]
 
         self.loadFromURL(path_str)
@@ -144,6 +156,9 @@
         delete_msg = "This operation will delete the checked data sets and all the dependents." +\
                      "\nDo you want to continue?"
-        reply = QtGui.QMessageBox.question(self, 'Warning', delete_msg,
-                QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
+        reply = QtGui.QMessageBox.question(self,
+                                           'Warning',
+                                           delete_msg,
+                                           QtGui.QMessageBox.Yes,
+                                           QtGui.QMessageBox.No)
 
         if reply == QtGui.QMessageBox.No:
@@ -201,5 +216,4 @@
 
         # Set the signal handlers
-        self.communicator = self._perspective.communicator()
         self.communicator.updateModelFromPerspectiveSignal.connect(self.updateModelFromPerspective)
 
@@ -254,4 +268,8 @@
                     theories_copied += 1
                     new_item = self.recursivelyCloneItem(subitem)
+                    # Append a "unique" descriptor to the name
+                    time_bit = str(time.time())[7:-1].replace('.','')
+                    new_name = new_item.text() + '_@' + time_bit
+                    new_item.setText(new_name)
                     self.theory_model.appendRow(new_item)
             self.theory_model.reset()
@@ -261,7 +279,7 @@
             return
         elif theories_copied == 1:
-            freeze_msg = "1 theory sent to Theory tab"
+            freeze_msg = "1 theory copied to the Theory tab as a data set"
         elif theories_copied > 1:
-            freeze_msg = "%i theories sent to Theory tab" % theories_copied
+            freeze_msg = "%i theories copied to the Theory tab as data sets" % theories_copied
         else:
             freeze_msg = "Unexpected number of theories copied: %i" % theories_copied
@@ -313,9 +331,8 @@
             return
 
-        #if type(paths) == QtCore.QStringList:
         if isinstance(paths, QtCore.QStringList):
             paths = [str(f) for f in paths]
 
-        if paths.__class__.__name__ != "list":
+        if type(paths) is not list:
             paths = [paths]
 
@@ -335,5 +352,8 @@
         error_message = ""
 
-        for p_file in path:
+        number_of_files = len(path)
+        self.communicator.progressBarUpdateSignal.emit(0.0)
+
+        for index, p_file in enumerate(path):
             basename = os.path.basename(p_file)
             _, extension = os.path.splitext(basename)
@@ -406,4 +426,7 @@
                 info = "error"
 
+            current_percentage = int(100.0* index/number_of_files)
+            self.communicator.progressBarUpdateSignal.emit(current_percentage)
+
         if any_error or error_message:
             self.communicator.statusBarUpdateSignal.emit(error_message)
@@ -412,4 +435,5 @@
             message = "Loading Data Complete! "
         message += log_msg
+        self.communicator.progressBarUpdateSignal.emit(-1)
 
         return output, message
@@ -461,5 +485,5 @@
 
                 try:
-                    is1D = item.child(0).data().toPyObject().__class__.__name__ == 'Data1D'
+                    is1D = type(item.child(0).data().toPyObject()) is Data1D
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -475,5 +499,5 @@
 
                 try:
-                    is1D = item.child(0).data().toPyObject().__class__.__name__ == 'Data1D'
+                    is1D = type(item.child(0).data().toPyObject()) is Data1D
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -489,5 +513,5 @@
                 item.setCheckState(QtCore.Qt.Unchecked)
                 try:
-                    is2D = item.child(0).data().toPyObject().__class__.__name__ == 'Data2D'
+                    is2D = type(item.child(0).data().toPyObject()) is Data2D
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -503,5 +527,5 @@
 
                 try:
-                    is2D = item.child(0).data().toPyObject().__class__.__name__ == 'Data2D'
+                    is2D = type(item.child(0).data().toPyObject()) is Data2D
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -516,4 +540,19 @@
             raise Exception, msg
 
+    def contextDataInfo(self):
+        """
+        """
+        print("contextDataInfo TRIGGERED")
+        pass
+
+    def onCustomContextMenu(self, position):
+        """
+        """
+        print "onCustomContextMenu triggered at point ", position.x(), position.y()
+        index = self.treeView.indexAt(position)
+        if index.isValid():
+            print "VALID CONTEXT MENU"
+    #    self.context_menu.exec(self.treeView.mapToGlobal(position))
+        pass
 
     def loadComplete(self, output):
@@ -521,7 +560,9 @@
         Post message to status bar and update the data manager
         """
+        assert type(output) == tuple
+
         # Reset the model so the view gets updated.
         self.model.reset()
-        assert type(output) == tuple
+        self.communicator.progressBarUpdateSignal.emit(-1)
 
         output_data = output[0]
