Index: src/sas/qtgui/DataExplorer.py
===================================================================
--- src/sas/qtgui/DataExplorer.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/DataExplorer.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -13,6 +13,4 @@
 
 # SAS
-import GuiUtils
-from Plotter import Plotter
 from sas.sascalc.dataloader.loader import Loader
 from sas.sasgui.guiframe.data_manager import DataManager
@@ -20,4 +18,7 @@
 from sas.sasgui.guiframe.dataFitting import Data2D
 
+import GuiUtils
+import PlotHelper
+from Plotter import Plotter
 from DroppableDataLoadWidget import DroppableDataLoadWidget
 
@@ -46,4 +47,7 @@
         # Be careful with twisted threads.
         self.mutex = QMutex()
+
+        # Active plots
+        self.active_plots = []
 
         # Connect the buttons
@@ -54,4 +58,5 @@
         self.cmdSendTo.clicked.connect(self.sendData)
         self.cmdNew.clicked.connect(self.newPlot)
+        self.cmdAppend.clicked.connect(self.appendPlot)
         self.cmdHelp.clicked.connect(self.displayHelp)
         self.cmdHelp_2.clicked.connect(self.displayHelp)
@@ -76,4 +81,7 @@
         self.communicator = self.parent.communicator()
         self.communicator.fileReadSignal.connect(self.loadFromURL)
+        self.communicator.activeGraphsSignal.connect(self.updateGraphCombo)
+        self.cbgraph.editTextChanged.connect(self.enableGraphCombo)
+        self.cbgraph.currentIndexChanged.connect(self.enableGraphCombo)
 
         # Proxy model for showing a subset of Data1D/Data2D content
@@ -97,4 +105,6 @@
         self.freezeView.setModel(self.theory_proxy)
 
+        self.enableGraphCombo(None)
+
     def closeEvent(self, event):
         """
@@ -110,4 +120,11 @@
         self._helpView.load(QtCore.QUrl(_TreeLocation))
         self._helpView.show()
+
+    def enableGraphCombo(self, combo_text):
+        """
+        Enables/disables "Assign Plot" elements
+        """
+        self.cbgraph.setEnabled(len(PlotHelper.currentPlots()) > 0)
+        self.cmdAppend.setEnabled(len(PlotHelper.currentPlots()) > 0)
 
     def loadFromURL(self, url):
@@ -187,6 +204,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:
@@ -263,11 +283,14 @@
             if not outer_item:
                 continue
-            for inner_index in xrange(outer_item.rowCount()): # Should be just two rows: data and Info
+            # Should be just two rows: data and Info
+            for inner_index in xrange(outer_item.rowCount()):
                 subitem = outer_item.child(inner_index)
-                if subitem and subitem.isCheckable() and subitem.checkState() == QtCore.Qt.Checked:
+                if subitem and \
+                   subitem.isCheckable() and \
+                   subitem.checkState() == QtCore.Qt.Checked:
                     theories_copied += 1
                     new_item = self.recursivelyCloneItem(subitem)
                     # Append a "unique" descriptor to the name
-                    time_bit = str(time.time())[7:-1].replace('.','')
+                    time_bit = str(time.time())[7:-1].replace('.', '')
                     new_name = new_item.text() + '_@' + time_bit
                     new_item.setText(new_name)
@@ -300,4 +323,19 @@
         return new_item
 
+    def updateGraphCombo(self, graph_list):
+        """
+        Modify Graph combo box on graph add/delete
+        """
+        orig_text = self.cbgraph.currentText()
+        self.cbgraph.clear()
+        graph_titles = []
+        for graph in graph_list:
+            graph_titles.append("Graph"+str(graph))
+        self.cbgraph.insertItems(0, graph_titles)
+        ind = self.cbgraph.findText(orig_text)
+        if ind > 0:
+            self.cbgraph.setCurrentIndex(ind)
+        pass
+
     def newPlot(self):
         """
@@ -306,14 +344,46 @@
         TODO: Add 2D-functionality
         """
-
         plots = GuiUtils.plotsFromCheckedItems(self.model)
 
         # Call show on requested plots
-        new_plot = Plotter()
+        new_plot = Plotter(self)
         for plot_set in plots:
             new_plot.data(plot_set)
             new_plot.plot()
 
+        # Update the global plot counter
+        title = "Graph"+str(PlotHelper.idOfPlot(new_plot))
+        new_plot.setWindowTitle(title)
+
+        # Add the plot to the workspace
+        self.parent.workspace().addWindow(new_plot)
+
+        # Show the plot
         new_plot.show()
+
+        # Update the active chart list
+        self.active_plots.append(title)
+
+    def appendPlot(self):
+        """
+        Add data set(s) to the existing matplotlib chart
+
+        TODO: Add 2D-functionality
+        """
+        # new plot data
+        new_plots = GuiUtils.plotsFromCheckedItems(self.model)
+
+        # old plot data
+        plot_id = self.cbgraph.currentText()
+        plot_id = int(plot_id[5:])
+
+        assert plot_id in PlotHelper.currentPlots(), "No such plot: Graph%s"%str(plot_id)
+
+        old_plot = PlotHelper.plotById(plot_id)
+
+        # Add new data to the old plot
+        for plot_set in new_plots:
+            old_plot.data(plot_set)
+            old_plot.plot()
 
     def chooseFiles(self):
@@ -424,5 +494,4 @@
                 else:
                     error_message += "%s\n" % str(p_file)
-                info = "error"
 
             current_percentage = int(100.0* index/number_of_files)
@@ -563,5 +632,5 @@
         Post message to status bar and update the data manager
         """
-        assert type(output) == tuple
+        assert isinstance(output, tuple)
 
         # Reset the model so the view gets updated.
Index: src/sas/qtgui/GuiManager.py
===================================================================
--- src/sas/qtgui/GuiManager.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/GuiManager.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -63,6 +63,6 @@
 
         # Fork off logging messages to the Log Window
-        XStream.stdout().messageWritten.connect( self.listWidget.insertPlainText  )
-        XStream.stderr().messageWritten.connect( self.listWidget.insertPlainText  )
+        XStream.stdout().messageWritten.connect(self.listWidget.insertPlainText)
+        XStream.stderr().messageWritten.connect(self.listWidget.insertPlainText)
 
         # Log the start of the session
@@ -138,7 +138,7 @@
         self.statusLabel = QtGui.QLabel()
         self.statusLabel.setText("Welcome to SasView")
-        self._workspace.statusbar.addPermanentWidget(self.statusLabel,1)
+        self._workspace.statusbar.addPermanentWidget(self.statusLabel, 1)
         self._workspace.statusbar.addPermanentWidget(self.progress, stretch=0)
-        self.progress.setRange(0,100)
+        self.progress.setRange(0, 100)
         self.progress.setValue(0)
         self.progress.setTextVisible(True)
@@ -150,4 +150,10 @@
         """
         pass
+
+    def workspace(self):
+        """
+        Accessor for the main window workspace
+        """
+        return self._workspace.workspace
 
     def updatePerspective(self, data):
@@ -186,5 +192,5 @@
         Update progress bar with the required value (0-100)
         """
-        assert(-1 <= value <= 100)
+        assert -1 <= value <= 100
         if value == -1:
             self.progress.setVisible(False)
@@ -253,6 +259,6 @@
                              % (content))
                 version_info = json.loads(content)
-            except:
-                logging.info("Failed to connect to www.sasview.org")
+            except ValueError, ex:
+                logging.info("Failed to connect to www.sasview.org:", ex)
         self.processVersion(version_info)
 
Index: src/sas/qtgui/GuiUtils.py
===================================================================
--- src/sas/qtgui/GuiUtils.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/GuiUtils.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -217,4 +217,7 @@
     progressBarUpdateSignal = QtCore.pyqtSignal(int)
 
+    # Workspace charts added/removed
+    activeGraphsSignal = QtCore.pyqtSignal(list)
+
 
 def updateModelItem(item, update_data, name=""):
Index: src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision a95260d0b50d991d1b735919b9d32d2648cb395f)
+++ src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -58,5 +58,5 @@
         self._helpView = QtWebKit.QWebView()
         self.detailsDialog = DetailsDialog(self)
-        self._plotter = Plotter(self)
+        # self._plotter = Plotter(self)
 
         self._low_extrapolate = False
@@ -159,4 +159,5 @@
         """
         """
+        self._plotter = Plotter(self)
         if self._low_extrapolate or self._high_extrapolate:
             self._plotter.show()
Index: src/sas/qtgui/PlotHelper.py
===================================================================
--- src/sas/qtgui/PlotHelper.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
+++ src/sas/qtgui/PlotHelper.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -0,0 +1,57 @@
+"""
+`Singleton` plot helper module
+All its variables are bound to the module,
+which can not be instantiated repeatedly so IDs are session-specific.
+"""
+import sys
+
+this = sys.modules[__name__]
+
+this._plots = {}
+this._plot_id = 0
+
+def clear():
+    """
+    Reset the plot dictionary
+    """
+    this._plots = {}
+
+def addPlot(plot):
+    """
+    Adds a new plot to the current dictionary of plots
+    """
+    this._plot_id += 1
+    this._plots[this._plot_id] = plot
+
+def deletePlot(plot_id):
+    """
+    Deletes an existing plot from the dictionary
+    """
+    assert plot_id in this._plots
+    del this._plots[plot_id]
+
+def currentPlots():
+    """
+    Returns a list of IDs for all currently active plots
+    """
+    return this._plots.keys()
+
+def plotById(plot_id):
+    """
+    Returns the plot referenced by the ID
+    """
+    assert plot_id in this._plots
+
+    return this._plots[plot_id]
+
+def idOfPlot(plot):
+    """
+    Returns the ID of the plot
+    """
+    plot_id = None
+    for key in this._plots.keys():
+        if this._plots[key] == plot:
+            plot_id = key
+            break
+
+    return plot_id
Index: src/sas/qtgui/Plotter.py
===================================================================
--- src/sas/qtgui/Plotter.py	(revision a95260d0b50d991d1b735919b9d32d2648cb395f)
+++ src/sas/qtgui/Plotter.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -1,2 +1,4 @@
+import logging
+
 from PyQt4 import QtGui
 
@@ -9,7 +11,12 @@
 import matplotlib.pyplot as plt
 
+import PlotHelper
+
 class Plotter(QtGui.QDialog):
     def __init__(self, parent=None):
         super(Plotter, self).__init__(parent)
+
+        # Required for the communicator
+        self.parent = parent
 
         # a figure instance to plot on
@@ -39,32 +46,32 @@
         self._ax = self.figure.add_subplot(self._current_plot)
 
+        # Notify the helper
+        PlotHelper.addPlot(self)
+        # Notify the listeners
+        self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
 
     def data(self, data=None):
-        """
-        """
+        """ data setter """
         self._data = data
 
     def title(self, title=""):
-        """
-        """
+        """ title setter """
         self._title = title
 
     def id(self, id=""):
-        """
-        """
+        """ id setter """
         self._id = id
 
     def x_label(self, xlabel=""):
-        """
-        """
+        """ x-label setter """
         self._xlabel = xlabel
 
     def y_label(self, ylabel=""):
-        """
-        """
+        """ y-label setter """
         self._ylabel = ylabel
 
     def clean(self):
         """
+        Redraw the graph
         """
         self.figure.delaxes(self._ax)
@@ -73,5 +80,5 @@
     def plot(self):
         """
-        plot self._data
+        Plot self._data
         """
         # create an axis
@@ -92,2 +99,13 @@
         # refresh canvas
         self.canvas.draw()
+
+    def closeEvent(self, event):
+        """
+        Overwrite the close event adding helper notification
+        """
+        # Please remove me from your database.
+        PlotHelper.deletePlot(PlotHelper.idOfPlot(self))
+        # Notify the listeners
+        self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
+        event.accept()
+
Index: src/sas/qtgui/UI/DataExplorerUI.py
===================================================================
--- src/sas/qtgui/UI/DataExplorerUI.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UI/DataExplorerUI.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -131,5 +131,4 @@
         self.cbgraph.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
         self.cbgraph.setObjectName(_fromUtf8("cbgraph"))
-        self.cbgraph.addItem(_fromUtf8(""))
         self.gridLayout_3.addWidget(self.cbgraph, 1, 1, 1, 1)
         self.gridLayout_2.addWidget(self.groupBox_3, 0, 0, 1, 1)
@@ -227,5 +226,4 @@
         self.cmdNew.setText(_translate("DataLoadWidget", "Create New", None))
         self.cmdAppend.setText(_translate("DataLoadWidget", "Append to", None))
-        self.cbgraph.setItemText(0, _translate("DataLoadWidget", "Graph1", None))
         self.cmdHelp.setText(_translate("DataLoadWidget", "Help", None))
         DataLoadWidget.setTabText(DataLoadWidget.indexOf(self.dataTab), _translate("DataLoadWidget", "Data", None))
Index: src/sas/qtgui/UI/DataExplorerUI.ui
===================================================================
--- src/sas/qtgui/UI/DataExplorerUI.ui	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UI/DataExplorerUI.ui	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -252,9 +252,4 @@
             <enum>QComboBox::AdjustToContents</enum>
            </property>
-           <item>
-            <property name="text">
-             <string>Graph1</string>
-            </property>
-           </item>
           </widget>
          </item>
Index: src/sas/qtgui/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -17,4 +17,5 @@
 from UnitTesting.TestUtils import QtSignalSpy
 from Plotter import Plotter
+import PlotHelper
 
 app = QApplication(sys.argv)
@@ -39,4 +40,6 @@
             def perspective(self):
                 return MyPerspective()
+            def workspace(self):
+                return None
 
         self.form = DataExplorerWindow(None, dummy_manager())
@@ -505,4 +508,10 @@
         loader = Loader()
         manager = DataManager()
+        PlotHelper.clear()
+        self.form.enableGraphCombo(None)
+
+        # Make sure the controls are disabled
+        self.assertFalse(self.form.cbgraph.isEnabled())
+        self.assertFalse(self.form.cmdAppend.isEnabled())
 
         # get Data1D
@@ -517,4 +526,7 @@
         self.form.plotsFromCheckedItems = MagicMock(return_value=new_data)
 
+        # Mask plotting
+        self.form.parent.workspace = MagicMock()
+
         # Call the plotting method
         self.form.newPlot()
@@ -522,4 +534,70 @@
         # The plot was displayed
         self.assertTrue(Plotter.show.called)
+
+        # The plot was registered
+        self.assertEqual(len(PlotHelper.currentPlots()), 1)
+
+        self.assertTrue(self.form.cbgraph.isEnabled())
+        self.assertTrue(self.form.cmdAppend.isEnabled())
+
+    def testAppendPlot(self):
+        """
+        Creating new plots from Data1D/2D
+        """
+        loader = Loader()
+        manager = DataManager()
+
+        PlotHelper.clear()
+        self.form.enableGraphCombo(None)
+
+        # Make sure the controls are disabled
+        self.assertFalse(self.form.cbgraph.isEnabled())
+        self.assertFalse(self.form.cmdAppend.isEnabled())
+
+        # get Data1D
+        p_file="cyl_400_20.txt"
+        output_object = loader.load(p_file)
+        new_data = [manager.create_gui_data(output_object, p_file)]
+
+        # Mask plotting
+        self.form.parent.workspace = MagicMock()
+
+        # Mask the plot show call
+        Plotter.show = MagicMock()
+
+        # Mask retrieval of the data
+        self.form.plotsFromCheckedItems = MagicMock(return_value=new_data)
+
+        # Call the plotting method
+        self.form.newPlot()
+
+        # Call the plotting method again, so we have 2 graphs
+        self.form.newPlot()
+
+        # See that we have two plots
+        self.assertEqual(len(PlotHelper.currentPlots()), 2)
+
+        # Add data to plot #1
+        self.form.cbgraph.setCurrentIndex(1)
+        self.form.appendPlot()
+
+        # See that we still have two plots
+        self.assertEqual(len(PlotHelper.currentPlots()), 2)
+
+    def testUpdateGraphCombo(self):
+        """
+        Test the combo box update
+        """
+        PlotHelper.clear()
+
+        graph_list=[1,2,3]
+        self.form.updateGraphCombo(graph_list)
+
+        self.assertEqual(self.form.cbgraph.count(), 3)
+        self.assertEqual(self.form.cbgraph.currentText(), 'Graph1')
+
+        graph_list=[]
+        self.form.updateGraphCombo(graph_list)
+        self.assertEqual(self.form.cbgraph.count(), 0)
 
     def testUpdateModelFromPerspective(self):
Index: src/sas/qtgui/UnitTesting/PlotHelperTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/PlotHelperTest.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
+++ src/sas/qtgui/UnitTesting/PlotHelperTest.py	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -0,0 +1,51 @@
+import unittest
+
+# Tested module
+import PlotHelper
+
+class PlotHelperTest(unittest.TestCase):
+    '''Test the Plot helper functions'''
+    def setUp(self):
+        '''Empty'''
+        pass
+
+    def tearDown(self):
+        '''Empty'''
+        pass
+
+    def testDefaults(self):
+        """ default method variables values """
+        self.assertIsInstance(PlotHelper._plots, dict)
+        self.assertEqual(PlotHelper._plots, {})
+        self.assertEqual(PlotHelper._plot_id, 0)
+
+    def testFunctions(self):
+        """ Adding a plot """
+        plot = "I am a plot. Really."
+        PlotHelper.addPlot(plot)
+        plot_id = PlotHelper.idOfPlot(plot)
+
+        # We can't guarantee unique values for plot_id, as
+        # the tests are executed in random order, so just
+        # make sure we get consecutive values for 2 plots
+        plot2 = "I am also a plot."
+        PlotHelper.addPlot(plot2)
+        plot_id_2 = PlotHelper.idOfPlot(plot2)
+        self.assertEqual(plot_id_2 - plot_id, 1)
+
+        # Other properties
+        self.assertEqual(PlotHelper.currentPlots(), [plot_id, plot_id_2])
+        self.assertEqual(PlotHelper.plotById(plot_id), plot)
+        self.assertEqual(PlotHelper.plotById(plot_id_2), plot2)
+
+        # Delete a graph
+        PlotHelper.deletePlot(plot_id)
+        self.assertEqual(PlotHelper.currentPlots(), [plot_id_2])
+
+        # Add another graph to see the counter
+        plot3 = "Just another plot. Move along."
+        PlotHelper.addPlot(plot3)
+        self.assertEqual(PlotHelper.idOfPlot(plot3), plot_id_2 + 1)
+
+if __name__ == "__main__":
+    unittest.main()
Index: src/sas/qtgui/run_tests.sh
===================================================================
--- src/sas/qtgui/run_tests.sh	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/run_tests.sh	(revision 8cb6cd6e52ab1f1031a89aeaad89921ef6ed9e98)
@@ -8,2 +8,3 @@
 python -m UnitTesting.DroppableDataLoadWidgetTest
 python -m UnitTesting.SasviewLoggerTest
+python -m UnitTesting.PlotHelperTest
