diff --git a/Code/Mantid/Framework/API/src/ParameterTie.cpp b/Code/Mantid/Framework/API/src/ParameterTie.cpp
index 3b71b74f17d2facd819c1bb9943148d1ef99c017..a719385ce3cfec4471a7a492afd56fe82ca9a334 100644
--- a/Code/Mantid/Framework/API/src/ParameterTie.cpp
+++ b/Code/Mantid/Framework/API/src/ParameterTie.cpp
@@ -103,6 +103,7 @@ namespace API
       i++;
     }
 
+    m_expression = "";
     while(boost::regex_search(start,end,res,rx))
     {
       m_expression.append(start,res[0].first);
diff --git a/Code/Mantid/MantidPlot/CMakeLists.txt b/Code/Mantid/MantidPlot/CMakeLists.txt
index e3a0adb7606078ce3d4374afe23152a119609bea..be3a9959d4221b3fcea5646dde21279ec4386469 100644
--- a/Code/Mantid/MantidPlot/CMakeLists.txt
+++ b/Code/Mantid/MantidPlot/CMakeLists.txt
@@ -763,6 +763,7 @@ include_directories ( ${CMAKE_CURRENT_BINARY_DIR} )
 qt4_add_resources ( RES_FILES ${PROJECT_SOURCE_DIR}/Images/images.qrc )
 qt4_add_resources ( RES_FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/icons.qrc )
 qt4_add_resources ( RES_FILES ${PROJECT_SOURCE_DIR}/MantidQt/SliceViewer/icons/SliceViewerIcons.qrc )
+qt4_add_resources ( RES_FILES ${PROJECT_SOURCE_DIR}/MantidQt/CustomInterfaces/icons/CustomInterfacesIcons.qrc )
 qt4_add_resources ( RES_FILES ${PROJECT_SOURCE_DIR}/Vates/VatesSimpleGui/ViewWidgets/icons/ViewWidgetsIcons.qrc )
 
 ###########################################################################
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
index 2c14d45c6bd0a3df07311218e24c3c612debfce4..01fa2bc88e9304358293ef35abc988736cb37f8d 100644
--- a/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
+++ b/Code/Mantid/MantidQt/CustomInterfaces/CMakeLists.txt
@@ -36,6 +36,7 @@ set ( SRC_FILES
 	src/MSDFit.cpp
 	src/MantidEV.cpp
 	src/MantidEVWorker.cpp
+    src/MultiDatasetFit.cpp
 	src/Muon/ALCBaselineModellingModel.cpp
 	src/Muon/ALCBaselineModellingPresenter.cpp
 	src/Muon/ALCBaselineModellingView.cpp
@@ -120,6 +121,7 @@ set ( INC_FILES
 	inc/MantidQtCustomInterfaces/MSDFit.h
 	inc/MantidQtCustomInterfaces/MantidEV.h
 	inc/MantidQtCustomInterfaces/MantidEVWorker.h
+	inc/MantidQtCustomInterfaces/MultiDatasetFit.h
 	inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingModel.h
 	inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingPresenter.h
 	inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingView.h
@@ -205,6 +207,7 @@ set ( MOC_FILES inc/MantidQtCustomInterfaces/Background.h
                 inc/MantidQtCustomInterfaces/IndirectTab.h
                 inc/MantidQtCustomInterfaces/JumpFit.h
                 inc/MantidQtCustomInterfaces/MSDFit.h
+                inc/MantidQtCustomInterfaces/MultiDatasetFit.h
                 inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingPresenter.h
                 inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingView.h
                 inc/MantidQtCustomInterfaces/Muon/ALCDataLoadingPresenter.h
@@ -236,7 +239,8 @@ set ( MOC_FILES inc/MantidQtCustomInterfaces/Background.h
                 inc/MantidQtCustomInterfaces/StepScan.h
 )
 
-set ( UI_FILES inc/MantidQtCustomInterfaces/CreateMDWorkspace.ui
+set ( UI_FILES inc/MantidQtCustomInterfaces/AddWorkspace.ui
+               inc/MantidQtCustomInterfaces/CreateMDWorkspace.ui
                inc/MantidQtCustomInterfaces/CreateMDWorkspaceAlgDialog.ui
                inc/MantidQtCustomInterfaces/DirectConvertToEnergy.ui
                inc/MantidQtCustomInterfaces/IndirectBayes.ui
@@ -249,6 +253,7 @@ set ( UI_FILES inc/MantidQtCustomInterfaces/CreateMDWorkspace.ui
                inc/MantidQtCustomInterfaces/IndirectSassena.ui
                inc/MantidQtCustomInterfaces/IndirectSimulation.ui
                inc/MantidQtCustomInterfaces/JumpFit.ui
+               inc/MantidQtCustomInterfaces/MultiDatasetFit.ui
                inc/MantidQtCustomInterfaces/Muon/ALCBaselineModellingView.ui
                inc/MantidQtCustomInterfaces/Muon/ALCDataLoadingView.ui
                inc/MantidQtCustomInterfaces/Muon/ALCInterface.ui
@@ -265,6 +270,7 @@ set ( UI_FILES inc/MantidQtCustomInterfaces/CreateMDWorkspace.ui
                inc/MantidQtCustomInterfaces/Stretch.ui
                inc/MantidQtCustomInterfaces/MantidEV.ui
                inc/MantidQtCustomInterfaces/StepScan.ui
+			   inc/MantidQtCustomInterfaces/EditLocalParameterDialog.ui
 )
 
 set ( TEST_FILES
@@ -296,8 +302,9 @@ else ( ${Boost_VERSION} GREATER 104799 AND ${qt_version} VERSION_GREATER 4.7.3 )
 endif ( ${Boost_VERSION} GREATER 104799 AND ${qt_version} VERSION_GREATER 4.7.3 )
 
 qt4_wrap_cpp ( MOCCED_FILES ${MOC_FILES} OPTIONS ${extra_options} )
+qt4_add_resources ( RES_FILES icons/CustomInterfacesIcons.qrc )
 
-set ( ALL_SRC ${SRC_FILES} ${MOCCED_FILES} )
+set ( ALL_SRC ${SRC_FILES} ${MOCCED_FILES} )#${RES_FILES})
 
 qt4_wrap_ui ( UI_HDRS ${UI_FILES} ) 
 include_directories ( ${CMAKE_CURRENT_BINARY_DIR} )
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/icons/CustomInterfacesIcons.qrc b/Code/Mantid/MantidQt/CustomInterfaces/icons/CustomInterfacesIcons.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..a9dba762f557dc591637a434ab628092634b27c5
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/icons/CustomInterfacesIcons.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/MultiDatasetFit/icons">
+        <file>zoom.png</file>
+        <file>panning.png</file>
+    </qresource>
+</RCC>
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/icons/panning.png b/Code/Mantid/MantidQt/CustomInterfaces/icons/panning.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b48aa1d092071beec4bc7214a01cc4cecbef555
Binary files /dev/null and b/Code/Mantid/MantidQt/CustomInterfaces/icons/panning.png differ
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/icons/zoom.png b/Code/Mantid/MantidQt/CustomInterfaces/icons/zoom.png
new file mode 100644
index 0000000000000000000000000000000000000000..b6f49f6d1ed122aad52117d51e6abeb26ddb2ad3
Binary files /dev/null and b/Code/Mantid/MantidQt/CustomInterfaces/icons/zoom.png differ
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/AddWorkspace.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/AddWorkspace.ui
new file mode 100644
index 0000000000000000000000000000000000000000..091bbe5a6bd025941a8e8b9d65a08c08fa4dec23
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/AddWorkspace.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddWorkspace</class>
+ <widget class="QDialog" name="AddWorkspace">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>349</width>
+    <height>171</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Add Workspace</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Select data</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <layout class="QGridLayout" name="gridLayout" columnstretch="0,0">
+        <item row="0" column="1">
+         <widget class="QComboBox" name="cbWorkspaceName">
+          <property name="toolTip">
+           <string>Select a workspace for fitting</string>
+          </property>
+          <property name="editable">
+           <bool>true</bool>
+          </property>
+          <property name="insertPolicy">
+           <enum>QComboBox::NoInsert</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="label_3">
+          <property name="text">
+           <string>Workspace Indices</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QLineEdit" name="leWSIndices">
+          <property name="toolTip">
+           <string>List of workspace indices. For example, 1,3,5,10-20</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="0">
+         <widget class="QLabel" name="label">
+          <property name="text">
+           <string>Workspace</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1">
+         <widget class="QCheckBox" name="cbAllSpectra">
+          <property name="toolTip">
+           <string>Check to select all spectra in the workspace</string>
+          </property>
+          <property name="text">
+           <string>All Spectra</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>11</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>AddWorkspace</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>AddWorkspace</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EditLocalParameterDialog.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EditLocalParameterDialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..cf485339ee42a1d75200864d04b7abdd291839cd
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EditLocalParameterDialog.ui
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EditLocalParameterDialog</class>
+ <widget class="QDialog" name="EditLocalParameterDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Edit parameter values</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTableWidget" name="tableWidget">
+     <column>
+      <property name="text">
+       <string>Parameter</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Value</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>EditLocalParameterDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>EditLocalParameterDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.h
new file mode 100644
index 0000000000000000000000000000000000000000..185b48f983775e327f6022a9e3ba2e7b0aa16098
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.h
@@ -0,0 +1,224 @@
+#ifndef MULTIDATASETFIT_H_
+#define MULTIDATASETFIT_H_
+
+#include "MantidQtAPI/UserSubWindow.h"
+#include "MantidAPI/AlgorithmObserver.h"
+#include "MantidQtAPI/WorkspaceObserver.h"
+#include "ui_MultiDatasetFit.h"
+#include "ui_AddWorkspace.h"
+#include "ui_EditLocalParameterDialog.h"
+
+#include <boost/shared_ptr.hpp>
+#include <QMap>
+#include <vector>
+
+// Forward declarations
+class QwtPlot;
+class QwtPlotZoomer;
+class QwtPlotPanner;
+class QwtPlotMagnifier;
+class QTableWidget;
+class QComboBox;
+class QPushButton;
+
+namespace Mantid
+{
+namespace API
+{
+  class IFunction;
+  class IAlgorithm;
+}
+}
+
+namespace MantidQt
+{
+
+// Forward declarations
+namespace MantidWidgets
+{
+  class FunctionBrowser;
+}
+
+namespace API
+{
+  class AlgorithmRunner;
+}
+
+namespace CustomInterfaces
+{
+
+// Forward declarations
+class PlotController;
+class DatasetPlotData;
+
+/**
+ * Class MultiDatasetFitDialog implements a dialog for setting up a multi-dataset fit
+ * and displaying the results.
+ */
+
+class MultiDatasetFit: public API::UserSubWindow
+{
+  Q_OBJECT
+public:
+  /// The name of the interface as registered into the factory
+  static std::string name() { return "Multi dataset fitting"; }
+  // This interface's categories.
+  static QString categoryInfo() { return "General"; }
+  /// Constructor
+  MultiDatasetFit(QWidget *parent = NULL);
+  ~MultiDatasetFit();
+  /// Get the name of the output workspace
+  QString getOutputWorkspaceName() const {return QString::fromStdString(m_outputWorkspaceName);}
+  /// Workspace name for the i-th spectrum
+  std::string getWorkspaceName(int i) const;
+  /// Workspace index of the i-th spectrum
+  int getWorkspaceIndex(int i) const;
+  /// Total number of spectra (datasets).
+  int getNumberOfSpectra() const;
+  /// Get value of a local parameter
+  double getLocalParameterValue(const QString& parName, int i) const;
+  /// Display info about the plot.
+  void showPlotInfo();
+  /// Check that the data sets in the table are valid
+  void checkDataSets();
+
+signals:
+  void dataTableUpdated();
+
+public slots:
+  void setLocalParameterValue(const QString& parName, int i, double value);
+  void reset();
+
+private slots:
+  void addWorkspace();
+  void workspaceSelectionChanged();
+  void removeSelectedSpectra();
+  void fit();
+  void editLocalParameterValues(const QString& parName);
+  void finishFit(bool);
+  void updateLocalParameters(int index);
+
+protected:
+  /// To be overridden to set the appropriate layout
+  virtual void initLayout();
+
+private:
+  void createPlotToolbar();
+  void addWorkspaceSpectrum(const QString &wsName, int wsIndex);
+  boost::shared_ptr<Mantid::API::IFunction> createFunction() const;
+  void initLocalParameter(const QString& parName)const;
+  void updateParameters(const Mantid::API::IFunction& fun);
+  void showInfo(const QString& text);
+  bool eventFilter(QObject *widget, QEvent *evn);
+  void showFunctionBrowserInfo();
+  void showTableInfo();
+  void removeDataSets(std::vector<int>& rows);
+
+  /// The form generated by Qt Designer
+  Ui::MultiDatasetFit m_uiForm;
+  /// Controls the plot and plotted data.
+  PlotController *m_plotController;
+  /// Function editor
+  MantidWidgets::FunctionBrowser *m_functionBrowser;
+  /// Name of the output workspace
+  std::string m_outputWorkspaceName;
+  /// Storage for local paramtere values
+  mutable QMap<QString,QVector<double>> m_localParameterValues;
+  /// Fit algorithm runner
+  boost::shared_ptr<API::AlgorithmRunner> m_fitRunner;
+};
+
+/*==========================================================================================*/
+/**
+  * A dialog for selecting a workspace from the ADS.
+  */
+class AddWorkspaceDialog: public QDialog
+{
+  Q_OBJECT
+public:
+  AddWorkspaceDialog(QWidget *parent);
+  QString workspaceName() const {return m_workspaceName;} 
+  std::vector<int> workspaceIndices() const {return m_wsIndices;}
+private slots:
+  void accept();
+  void reject();
+  void workspaceNameChanged(const QString&);
+  void selectAllSpectra(int state);
+private:
+  /// Name of the selected workspace
+  QString m_workspaceName;
+  /// Selected workspace index
+  std::vector<int> m_wsIndices;
+  /// Maximum index in the selected workspace
+  int m_maxIndex;
+  Ui::AddWorkspace m_uiForm;
+};
+
+/*==========================================================================================*/
+/**
+  * A class for controlling the plot widget and the displayed data.
+  */
+class PlotController: public QObject
+{
+  Q_OBJECT
+public:
+  PlotController(MultiDatasetFit *parent, QwtPlot *plot, QTableWidget *table, QComboBox *plotSelector, QPushButton *prev, QPushButton *next);
+  ~PlotController();
+  void clear();
+  void update();
+  int getCurrentIndex() const {return m_currentIndex;}
+  bool isZoomEnabled() const;
+  bool isPanEnabled() const;
+signals:
+  void currentIndexChanged(int);
+public slots:
+  void enableZoom();
+  void enablePan();
+private slots:
+  void tableUpdated();
+  void prevPlot();
+  void nextPlot();
+  void plotDataSet(int);
+private:
+  MultiDatasetFit *owner() const {return static_cast<MultiDatasetFit*>(parent());}
+  /// The plot widget
+  QwtPlot *m_plot;
+  /// The zoomer
+  QwtPlotZoomer *m_zoomer;
+  /// The panner
+  QwtPlotPanner *m_panner;
+  /// The magnifier
+  QwtPlotMagnifier *m_magnifier;
+
+  /// The workspace table
+  QTableWidget *m_table;
+  QComboBox *m_plotSelector;
+  QPushButton *m_prevPlot;
+  QPushButton *m_nextPlot;
+  QMap<int,boost::shared_ptr<DatasetPlotData>> m_plotData;
+  int m_currentIndex;
+};
+
+/*==========================================================================================*/
+/**
+  * A dialog for displaying and editing values of local parameters.
+  */
+class EditLocalParameterDialog: public QDialog
+{
+  Q_OBJECT
+public:
+  EditLocalParameterDialog(MultiDatasetFit *parent, const QString &parName);
+private slots:
+  //void accept();
+  //void reject();
+  void valueChanged(int,int);
+private:
+  MultiDatasetFit *owner() const {return static_cast<MultiDatasetFit*>(parent());}
+  Ui::EditLocalParameterDialog m_uiForm;
+  QString m_parName;
+};
+
+} // CustomInterfaces
+} // MantidQt
+
+#endif /*MULTIDATASETFITDIALOG_H_*/
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.ui
new file mode 100644
index 0000000000000000000000000000000000000000..c2b680fd31c25c646e454c2d30e1e7b77f37c6bc
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/MultiDatasetFit.ui
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MultiDatasetFit</class>
+ <widget class="QMainWindow" name="MultiDatasetFit">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>895</width>
+    <height>604</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Multi-dataset fitting</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout_3" stretch="1,0">
+    <item>
+     <widget class="QSplitter" name="hSplitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QWidget" name="verticalLayoutWidget_2">
+       <layout class="QVBoxLayout" name="browserLayout">
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_3">
+          <item>
+           <widget class="QPushButton" name="btnFit">
+            <property name="toolTip">
+             <string>Start multi-dataset fitting</string>
+            </property>
+            <property name="text">
+             <string>&amp;Fit</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QSplitter" name="vSplitter">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <widget class="QWidget" name="layoutWidget">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QTableWidget" name="dataTable">
+           <property name="editTriggers">
+            <set>QAbstractItemView::NoEditTriggers</set>
+           </property>
+           <column>
+            <property name="text">
+             <string>Workspace</string>
+            </property>
+           </column>
+           <column>
+            <property name="text">
+             <string>WS Index</string>
+            </property>
+           </column>
+          </widget>
+         </item>
+         <item>
+          <layout class="QVBoxLayout" name="verticalLayout_2">
+           <item>
+            <widget class="QPushButton" name="btnAddWorkspace">
+             <property name="toolTip">
+              <string>Add one or more spectra from a workspace</string>
+             </property>
+             <property name="text">
+              <string>&amp;Add Workspace</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="btnRemove">
+             <property name="toolTip">
+              <string>Remove selected spectra</string>
+             </property>
+             <property name="text">
+              <string>&amp;Remove</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="verticalSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>40</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="verticalLayoutWidget">
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout">
+           <item>
+            <widget class="QPushButton" name="btnPrev">
+             <property name="toolTip">
+              <string>Display previous data set</string>
+             </property>
+             <property name="text">
+              <string>&lt;</string>
+             </property>
+             <property name="shortcut">
+              <string>Alt+,</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QComboBox" name="cbPlotSelector">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>200</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="toolTip">
+              <string>Select a data set</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="btnNext">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+             <property name="toolTip">
+              <string>Display next data set</string>
+             </property>
+             <property name="text">
+              <string>&gt;</string>
+             </property>
+             <property name="shortcut">
+              <string>Alt+.</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="horizontalSpacer">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <widget class="QwtPlot" name="plot">
+           <property name="frameShape">
+            <enum>QFrame::StyledPanel</enum>
+           </property>
+           <property name="frameShadow">
+            <enum>QFrame::Raised</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </widget>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLabel" name="infoBar">
+      <property name="text">
+       <string>infoBar</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header location="global">qwt_plot.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>btnAddWorkspace</tabstop>
+  <tabstop>dataTable</tabstop>
+  <tabstop>btnRemove</tabstop>
+  <tabstop>btnPrev</tabstop>
+  <tabstop>btnFit</tabstop>
+  <tabstop>btnNext</tabstop>
+  <tabstop>cbPlotSelector</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9f2694392965fc4a44092c1a2f33868aa212aa7
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomInterfaces/src/MultiDatasetFit.cpp
@@ -0,0 +1,1124 @@
+#include "MantidQtCustomInterfaces/MultiDatasetFit.h"
+#include "MantidQtMantidWidgets/FunctionBrowser.h"
+#include "MantidQtAPI/AlgorithmRunner.h"
+
+#include "MantidAPI/AnalysisDataService.h"
+#include "MantidAPI/FunctionFactory.h"
+#include "MantidAPI/MultiDomainFunction.h"
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/ParameterTie.h"
+#include "MantidKernel/ArrayProperty.h"
+#include "MantidKernel/ArrayBoundedValidator.h"
+
+#include "qtpropertybrowser.h"
+
+#include <QDialog>
+#include <QHeaderView>
+#include <QMessageBox>
+#include <QToolBar>
+#include <QActionGroup>
+
+#include <boost/make_shared.hpp>
+#include <qwt_plot_curve.h>
+#include <qwt_plot_zoomer.h>
+#include <qwt_plot_panner.h>
+#include <qwt_plot_magnifier.h>
+#include <Poco/ActiveResult.h>
+
+#include <vector>
+#include <algorithm>
+
+namespace{
+  const int wsColumn = 0;
+  const int wsIndexColumn = 1;
+}
+
+namespace MantidQt
+{
+namespace CustomInterfaces
+{
+
+/*==========================================================================================*/
+/*                              AddWorkspaceDialog                                          */
+/*==========================================================================================*/
+AddWorkspaceDialog::AddWorkspaceDialog(QWidget *parent):QDialog(parent)
+{
+  m_uiForm.setupUi(this);
+  // populate the combo box with names of eligible workspaces
+  QStringList workspaceNames;
+  auto wsNames = Mantid::API::AnalysisDataService::Instance().getObjectNames();
+  for(auto name = wsNames.begin(); name != wsNames.end(); ++name)
+  {
+    auto ws = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::MatrixWorkspace>( *name );
+    if ( ws )
+    {
+      workspaceNames << QString::fromStdString( *name );
+    }
+  }
+  connect(m_uiForm.cbWorkspaceName,SIGNAL(currentIndexChanged(const QString&)),this,SLOT(workspaceNameChanged(const QString&)));
+  m_uiForm.cbWorkspaceName->addItems( workspaceNames );
+
+  connect(m_uiForm.cbAllSpectra,SIGNAL(stateChanged(int)),this,SLOT(selectAllSpectra(int)));
+}
+
+/**
+ * Slot. Reacts on change of workspace name in the selection combo box.
+ * @param wsName :: Name of newly selected workspace.
+ */
+void AddWorkspaceDialog::workspaceNameChanged(const QString& wsName)
+{
+  auto ws = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::MatrixWorkspace>( wsName.toStdString() );
+  if ( ws )
+  {
+    int maxValue = static_cast<int>(ws->getNumberHistograms()) - 1;
+    if ( maxValue < 0 ) maxValue = 0;
+    m_maxIndex = maxValue;
+    if ( m_uiForm.cbAllSpectra->isChecked() )
+    {
+      m_uiForm.leWSIndices->setText(QString("0-%1").arg(m_maxIndex));
+    }
+    else
+    {
+      m_uiForm.leWSIndices->clear();
+    }
+  }
+  else
+  {
+    m_maxIndex = 0;
+    m_uiForm.leWSIndices->clear();
+    m_uiForm.cbAllSpectra->setChecked(false);
+  }
+}
+
+/**
+ * Slot. Called when "All Spectra" check box changes its state
+ */
+void AddWorkspaceDialog::selectAllSpectra(int state)
+{
+  if ( state == Qt::Checked )
+  {
+    m_uiForm.leWSIndices->setText(QString("0-%1").arg(m_maxIndex));
+    m_uiForm.leWSIndices->setEnabled(false);
+  }
+  else
+  {
+    m_uiForm.leWSIndices->setEnabled(true);
+  }
+
+}
+
+/**
+ * Called on close if selection accepted.
+ */
+void AddWorkspaceDialog::accept()
+{
+  m_workspaceName = m_uiForm.cbWorkspaceName->currentText();
+  m_wsIndices.clear();
+  QString indexInput = m_uiForm.leWSIndices->text();
+  if ( !m_workspaceName.isEmpty() && !indexInput.isEmpty() )
+  {
+    auto validator = boost::make_shared<Mantid::Kernel::ArrayBoundedValidator<int>>(0,m_maxIndex);
+    Mantid::Kernel::ArrayProperty<int> prop("Indices",validator);
+    std::string err = prop.setValue( indexInput.toStdString() );
+    if ( err.empty() )
+    {
+      m_wsIndices = prop;
+    }
+    else
+    {
+      QMessageBox::warning(this, "MantidPlot - Error", QString("Some of the indices are outside the allowed range [0,%1]").arg(m_maxIndex));
+    }
+  }
+  QDialog::accept();
+}
+
+/**
+ * Called on close if selection rejected.
+ */
+void AddWorkspaceDialog::reject()
+{
+  m_workspaceName.clear();
+  m_wsIndices.clear();
+  QDialog::reject();
+}
+
+/*==========================================================================================*/
+/*                                DatasetPlotData                                           */
+/*==========================================================================================*/
+
+/**
+ * Contains graphics for a single data set: fitting data, claculated result, difference.
+ */
+class DatasetPlotData
+{
+public:
+  DatasetPlotData(const QString& wsName, int wsIndex, const QString& outputWSName);
+  ~DatasetPlotData();
+  void show(QwtPlot *plot);
+  void hide();
+  QwtDoubleRect boundingRect() const;
+private:
+  // no copying
+  DatasetPlotData(const DatasetPlotData&);
+  DatasetPlotData& operator=(const DatasetPlotData&);
+  void setData(const Mantid::API::MatrixWorkspace *ws, int wsIndex, const Mantid::API::MatrixWorkspace *outputWS);
+  QwtPlotCurve *m_dataCurve;
+  QwtPlotCurve *m_calcCurve;
+  QwtPlotCurve *m_diffCurve;
+};
+
+/**
+ * Constructor.
+ * @param wsName :: Name of a MatrixWorkspace with the data for fitting.
+ * @param wsIndex :: Workspace index of a spectrum in wsName to plot.
+ * @param outputWSName :: Name of the Fit's output workspace containing at least 3 spectra:
+ *    #0 - original data (the same as in wsName[wsIndex]), #1 - calculated data, #3 - difference.
+ *    If empty - ignore this workspace.
+ */
+DatasetPlotData::DatasetPlotData(const QString& wsName, int wsIndex, const QString& outputWSName):
+  m_dataCurve(new QwtPlotCurve(wsName + QString(" (%1)").arg(wsIndex))),
+  m_calcCurve(NULL),
+  m_diffCurve(NULL)
+{
+  // get the data workspace
+  auto ws = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::MatrixWorkspace>( wsName.toStdString() );
+  if ( !ws )
+  {
+    QString mess = QString("Workspace %1 either doesn't exist or isn't a MatrixWorkspace").arg(wsName);
+    throw std::runtime_error( mess.toStdString() );
+  }
+  // check that the index is in range
+  if ( static_cast<size_t>(wsIndex) >= ws->getNumberHistograms() )
+  {
+    QString mess = QString("Spectrum %1 doesn't exist in workspace %2").arg(wsIndex).arg(wsName);
+    throw std::runtime_error( mess.toStdString() );
+  }
+
+  // get the data workspace
+  Mantid::API::MatrixWorkspace_sptr outputWS;
+  if ( !outputWSName.isEmpty() )
+  {
+    outputWS = Mantid::API::AnalysisDataService::Instance().retrieveWS<Mantid::API::MatrixWorkspace>( outputWSName.toStdString() );
+    if ( !outputWS )
+    {
+      QString mess = QString("Workspace %1 either doesn't exist or isn't a MatrixWorkspace").arg(outputWSName);
+      throw std::runtime_error( mess.toStdString() );
+    }
+  }
+
+  // create the curves
+  setData( ws.get(), wsIndex, outputWS.get() );
+
+}
+
+/**
+ * Destructor.
+ */
+DatasetPlotData::~DatasetPlotData()
+{
+  m_dataCurve->detach();
+  delete m_dataCurve;
+  if ( m_calcCurve )
+  {
+    m_calcCurve->detach();
+    delete m_calcCurve;
+  }
+  if ( m_diffCurve )
+  {
+    m_diffCurve->detach();
+    delete m_diffCurve;
+  }
+}
+
+/**
+ * Set the data to the curves.
+ * @param ws :: A Fit's input workspace.
+ * @param wsIndex :: Workspace index of a spectrum to costruct the plot data for.
+ * @param outputWS :: The output workspace from Fit containing the calculated spectrum.
+ */
+void DatasetPlotData::setData(const Mantid::API::MatrixWorkspace *ws, int wsIndex, const Mantid::API::MatrixWorkspace *outputWS)
+{
+  std::vector<double> xValues = ws->readX(wsIndex);
+  if ( ws->isHistogramData() )
+  {
+    auto xend = xValues.end() - 1;
+    for(auto x = xValues.begin(); x != xend; ++x)
+    {
+      *x = (*x + *(x+1))/2;
+    }
+    xValues.pop_back();
+  }
+  m_dataCurve->setData( xValues.data(), ws->readY(wsIndex).data(), static_cast<int>(xValues.size()) );
+
+  if ( outputWS && outputWS->getNumberHistograms() >= 3 )
+  {
+    m_calcCurve = new QwtPlotCurve("calc");
+    m_calcCurve->setData( xValues.data(), outputWS->readY(1).data(), static_cast<int>(xValues.size()) );
+    QPen penCalc("red");
+    m_calcCurve->setPen(penCalc);
+    m_diffCurve = new QwtPlotCurve("diff");
+    m_diffCurve->setData( xValues.data(), outputWS->readY(2).data(), static_cast<int>(xValues.size()) );
+    QPen penDiff("green");
+    m_diffCurve->setPen(penDiff);
+  }
+}
+
+/**
+ * Show the curves on a plot.
+ */
+void DatasetPlotData::show(QwtPlot *plot)
+{
+  m_dataCurve->attach(plot);
+  if ( m_calcCurve )
+  {
+    m_calcCurve->attach(plot);
+  }
+  if ( m_diffCurve )
+  {
+    m_diffCurve->attach(plot);
+  }
+}
+
+/**
+ * Hide the curves from any plot.
+ */
+void DatasetPlotData::hide()
+{
+  m_dataCurve->detach();
+  if ( m_calcCurve )
+  {
+    m_calcCurve->detach();
+  }
+  if ( m_diffCurve )
+  {
+    m_diffCurve->detach();
+  }
+}
+
+/**
+ * Get the bounding rect including all plotted data.
+ */
+QwtDoubleRect DatasetPlotData::boundingRect() const
+{
+  QwtDoubleRect rect = m_dataCurve->boundingRect();
+  if ( m_calcCurve )
+  {
+    rect = rect.united( m_calcCurve->boundingRect() );
+  }
+  if ( m_diffCurve )
+  {
+    rect = rect.united( m_diffCurve->boundingRect() );
+  }
+  return rect;
+}
+
+/*==========================================================================================*/
+/*                                PlotController                                            */
+/*==========================================================================================*/
+
+PlotController::PlotController(MultiDatasetFit *parent,QwtPlot *plot, QTableWidget *table, QComboBox *plotSelector, QPushButton *prev, QPushButton *next):
+  QObject(parent),m_plot(plot),m_table(table),m_plotSelector(plotSelector),m_prevPlot(prev),m_nextPlot(next),m_currentIndex(-1)
+{
+  connect(parent,SIGNAL(dataTableUpdated()),this,SLOT(tableUpdated()));
+  connect(prev,SIGNAL(clicked()),this,SLOT(prevPlot()));
+  connect(next,SIGNAL(clicked()),this,SLOT(nextPlot()));
+  connect(plotSelector,SIGNAL(currentIndexChanged(int)),this,SLOT(plotDataSet(int)));
+
+  m_zoomer = new QwtPlotZoomer(QwtPlot::xBottom, QwtPlot::yLeft,
+      QwtPicker::DragSelection | QwtPicker::CornerToCorner, QwtPicker::AlwaysOff, plot->canvas());
+
+  m_panner = new QwtPlotPanner( plot->canvas() );
+  m_panner->setEnabled(false);
+
+  m_magnifier = new QwtPlotMagnifier( plot->canvas() );
+  m_magnifier->setEnabled( false );
+}
+
+PlotController::~PlotController()
+{
+  m_plotData.clear();
+}
+
+/**
+ * Slot. Respond to changes in the data table.
+ */
+void PlotController::tableUpdated()
+{
+  m_plotSelector->blockSignals(true);
+  m_plotSelector->clear();
+  int rowCount = m_table->rowCount();
+  for(int row = 0; row < rowCount; ++row)
+  {
+    QString itemText = QString("%1 (%2)").arg(m_table->item(row,wsColumn)->text(),m_table->item(row,wsIndexColumn)->text());
+    m_plotSelector->insertItem( itemText );
+  }
+  m_plotData.clear();
+  m_currentIndex = -1;
+  m_plotSelector->blockSignals(false);
+  plotDataSet( m_plotSelector->currentIndex() );
+}
+
+/**
+ * Display the previous plot if there is one.
+ */
+void PlotController::prevPlot()
+{
+  int index = m_plotSelector->currentIndex();
+  if ( index > 0 )
+  {
+    --index;
+    m_plotSelector->setCurrentIndex( index );
+  }
+}
+
+/**
+ * Display the next plot if there is one.
+ */
+void PlotController::nextPlot()
+{
+  int index = m_plotSelector->currentIndex();
+  if ( index < m_plotSelector->count() - 1 )
+  {
+    ++index;
+    m_plotSelector->setCurrentIndex( index );
+  }
+}
+
+/**
+ * Plot a data set.
+ * @param index :: Index (row) of the data set in the table.
+ */
+void PlotController::plotDataSet(int index)
+{
+  if ( index < 0 || index >= m_table->rowCount() )
+  {
+    clear();
+    owner()->checkDataSets();
+    m_plot->replot();
+    return;
+  }
+
+  bool resetZoom = m_plotData.isEmpty();
+
+  // create data if index is displayed for the first time
+  if ( !m_plotData.contains(index) )
+  {
+    QString wsName = m_table->item( index, wsColumn )->text();
+    int wsIndex = m_table->item( index, wsIndexColumn )->text().toInt();
+    QString outputWorkspaceName = owner()->getOutputWorkspaceName();
+    if ( !outputWorkspaceName.isEmpty() )
+    {
+      outputWorkspaceName += QString("_%1").arg(index);
+    }
+    try
+    {
+      auto value = boost::make_shared<DatasetPlotData>( wsName, wsIndex, outputWorkspaceName );
+      m_plotData.insert(index, value );
+    }
+    catch(...)
+    {
+      clear();
+      owner()->checkDataSets();
+      m_plot->replot();
+      return;
+    }
+  }
+
+  // hide the previously shown data
+  if ( m_currentIndex > -1 ) 
+  {
+    m_plotData[m_currentIndex]->hide();
+  }
+
+  // try to keep the zooming from the previous view
+  // but if zoom rect doesn't show any data reset zoom base to show all
+  auto dataRect = m_plotData[index]->boundingRect();
+  auto zoomRect = m_zoomer->zoomRect();
+  if ( !zoomRect.intersects( dataRect ) )
+  {
+    m_plot->setAxisAutoScale(QwtPlot::xBottom);
+    m_plot->setAxisAutoScale(QwtPlot::yLeft);
+  }
+
+  // show the new data
+  m_plotData[index]->show( m_plot );
+  m_plot->replot();
+  // the idea is to set the zoom base (the largest view) to the data's bounding rect
+  // but it looks like the base is set to the union of dataRect and current zoomRect
+  m_zoomer->setZoomBase( dataRect );
+  // if it's first data set ever set the zoomer's base
+  // if it's not done the base is set to some default rect that has nothing to do with the data
+  if ( resetZoom ) 
+  {
+    m_zoomer->setZoomBase(true);
+  }
+  // change the current data set index
+  m_currentIndex = index;
+  emit currentIndexChanged( index );
+}
+
+void PlotController::clear()
+{
+  m_plotData.clear();
+}
+
+void PlotController::update()
+{
+  plotDataSet( m_currentIndex );
+}
+
+void PlotController::enableZoom()
+{
+  m_zoomer->setEnabled(true);
+  m_panner->setEnabled(false);
+  m_magnifier->setEnabled(false);
+  m_plot->canvas()->setCursor(QCursor(Qt::CrossCursor));
+  owner()->showPlotInfo();
+}
+
+void PlotController::enablePan()
+{
+  m_zoomer->setEnabled(false);
+  m_panner->setEnabled(true);
+  m_magnifier->setEnabled(true);
+  m_plot->canvas()->setCursor(Qt::pointingHandCursor);
+  owner()->showPlotInfo();
+}
+
+bool PlotController::isZoomEnabled() const
+{
+  return m_zoomer->isEnabled();
+}
+
+bool PlotController::isPanEnabled() const
+{
+  return m_panner->isEnabled();
+}
+
+/*==========================================================================================*/
+/*                               EditLocalParameterDialog                                   */
+/*==========================================================================================*/
+
+EditLocalParameterDialog::EditLocalParameterDialog(MultiDatasetFit *parent, const QString &parName):
+  QDialog(parent),m_parName(parName)
+{
+  m_uiForm.setupUi(this);
+  QHeaderView *header = m_uiForm.tableWidget->horizontalHeader();
+  header->setResizeMode(0,QHeaderView::Stretch);
+  header->setResizeMode(1,QHeaderView::Stretch);
+  connect(m_uiForm.tableWidget,SIGNAL(cellChanged(int,int)),this,SLOT(valueChanged(int,int)));
+
+  auto multifit = owner();
+  auto n = static_cast<int>( multifit->getNumberOfSpectra() );
+  for(int i = 0; i < n; ++i)
+  {
+    m_uiForm.tableWidget->insertRow(i);
+    auto cell = new QTableWidgetItem( QString("f%1.").arg(i) + parName );
+    m_uiForm.tableWidget->setItem( i, 0, cell );
+    cell = new QTableWidgetItem( QString::number(multifit->getLocalParameterValue(parName,i)) );
+    m_uiForm.tableWidget->setItem( i, 1, cell );
+  }
+}
+
+/**
+ * Slot. Called when a value changes.
+ * @param row :: Row index of the changed cell.
+ * @param col :: Column index of the changed cell.
+ */
+void EditLocalParameterDialog::valueChanged(int row, int col)
+{
+  if ( col == 1 )
+  {
+    QString text = m_uiForm.tableWidget->item(row,col)->text();
+    try
+    {
+      double value = text.toDouble();
+      owner()->setLocalParameterValue(m_parName,row,value);
+    }
+    catch(std::exception&)
+    {
+      // restore old value
+      m_uiForm.tableWidget->item(row,col)->setText( QString::number(owner()->getLocalParameterValue(m_parName,row)) );
+    }
+  }
+}
+
+/*==========================================================================================*/
+/*                                    MultiDatasetFit                                       */
+/*==========================================================================================*/
+
+//Register the class with the factory
+DECLARE_SUBWINDOW(MultiDatasetFit);
+
+/**
+ * Constructor
+ * @param parent :: The parent widget
+ */
+MultiDatasetFit::MultiDatasetFit(QWidget *parent)
+:UserSubWindow(parent)
+{
+}
+
+MultiDatasetFit::~MultiDatasetFit()
+{
+  m_plotController->clear();
+}
+
+/**
+ * Initilize the layout.
+ */
+void MultiDatasetFit::initLayout()
+{
+  m_uiForm.setupUi(this);
+  m_uiForm.hSplitter->setStretchFactor(0,0);
+  m_uiForm.hSplitter->setStretchFactor(1,1);
+  m_uiForm.vSplitter->setStretchFactor(0,0);
+  m_uiForm.vSplitter->setStretchFactor(1,1);
+
+  QHeaderView *header = m_uiForm.dataTable->horizontalHeader();
+  header->setResizeMode(0,QHeaderView::Stretch);
+  header->setResizeMode(1,QHeaderView::Fixed);
+
+  m_uiForm.btnRemove->setEnabled( false );
+
+  connect(m_uiForm.btnAddWorkspace,SIGNAL(clicked()),this,SLOT(addWorkspace()));
+  connect(m_uiForm.btnRemove,SIGNAL(clicked()),this,SLOT(removeSelectedSpectra()));
+  connect(m_uiForm.dataTable,SIGNAL(itemSelectionChanged()), this,SLOT(workspaceSelectionChanged()));
+  connect(m_uiForm.btnFit,SIGNAL(clicked()),this,SLOT(fit()));
+  connect(this,SIGNAL(dataTableUpdated()),this,SLOT(reset()));
+
+  m_plotController = new PlotController(this,
+                                        m_uiForm.plot,
+                                        m_uiForm.dataTable,
+                                        m_uiForm.cbPlotSelector,
+                                        m_uiForm.btnPrev,
+                                        m_uiForm.btnNext);
+  connect(m_plotController,SIGNAL(currentIndexChanged(int)),this,SLOT(updateLocalParameters(int)));
+
+  m_functionBrowser = new MantidQt::MantidWidgets::FunctionBrowser(NULL, true);
+  m_uiForm.browserLayout->addWidget( m_functionBrowser );
+  connect(m_functionBrowser,SIGNAL(localParameterButtonClicked(const QString&)),this,SLOT(editLocalParameterValues(const QString&)));
+  connect(m_functionBrowser,SIGNAL(functionStructureChanged()),this,SLOT(reset()));
+
+  createPlotToolbar();
+
+  // filters
+  m_functionBrowser->installEventFilter( this );
+  m_uiForm.plot->installEventFilter( this );
+  m_uiForm.dataTable->installEventFilter( this );
+
+  showInfo( "Add some data, define fitting function" );
+}
+
+void MultiDatasetFit::createPlotToolbar()
+{
+  auto toolBar = new QToolBar(this);
+  auto group = new QActionGroup(this);
+ 
+  auto action = new QAction(this);
+  action->setIcon(QIcon(":/MultiDatasetFit/icons/zoom.png"));
+  action->setCheckable(true);
+  action->setChecked(true);
+  action->setToolTip("Zooming tool");
+  connect(action,SIGNAL(triggered()),m_plotController,SLOT(enableZoom()));
+  group->addAction(action);
+
+  action = new QAction(this);
+  action->setIcon(QIcon(":/MultiDatasetFit/icons/panning.png"));
+  action->setCheckable(true);
+  action->setToolTip("Panning tool");
+  connect(action,SIGNAL(triggered()),m_plotController,SLOT(enablePan()));
+  group->addAction(action);
+
+  toolBar->addActions(group->actions());
+
+  m_uiForm.horizontalLayout->insertWidget(3,toolBar);
+}
+
+/**
+ * Show a dialog to select a workspace.
+ */
+void MultiDatasetFit::addWorkspace()
+{
+  AddWorkspaceDialog dialog(this);
+  if ( dialog.exec() == QDialog::Accepted )
+  {
+    QString wsName = dialog.workspaceName().stripWhiteSpace();
+    // if name is empty assume that there are no workspaces in the ADS
+    if ( wsName.isEmpty() ) return;
+    if ( Mantid::API::AnalysisDataService::Instance().doesExist( wsName.toStdString()) )
+    {
+      auto indices = dialog.workspaceIndices();
+      for(auto i = indices.begin(); i != indices.end(); ++i)
+      {
+        addWorkspaceSpectrum( wsName, *i );
+      }
+      emit dataTableUpdated();
+    }
+    else
+    {
+      QMessageBox::warning(this,"MantidPlot - Warning",QString("Workspace \"%1\" doesn't exist.").arg(wsName));
+    }
+  }
+}
+
+/**
+ * Add a spectrum from a workspace to the table.
+ * @param wsName :: Name of a workspace.
+ * @param wsIndex :: Index of a spectrum in the workspace (workspace index).
+ */
+void MultiDatasetFit::addWorkspaceSpectrum(const QString &wsName, int wsIndex)
+{
+  int row = m_uiForm.dataTable->rowCount();
+  m_uiForm.dataTable->insertRow(row);
+
+  auto cell = new QTableWidgetItem( wsName );
+  m_uiForm.dataTable->setItem( row, wsColumn, cell );
+  cell = new QTableWidgetItem( QString::number(wsIndex) );
+  m_uiForm.dataTable->setItem( row, wsIndexColumn, cell );
+}
+
+/**
+ * Slot. Called when selection in the data table changes.
+ */
+void MultiDatasetFit::workspaceSelectionChanged()
+{
+  auto selection = m_uiForm.dataTable->selectionModel();
+  bool enableRemoveButton = selection->hasSelection();
+  if ( enableRemoveButton )
+  {
+    enableRemoveButton = selection->selectedRows().size() > 0;
+  }
+
+  m_uiForm.btnRemove->setEnabled( enableRemoveButton );
+}
+
+/**
+ * Slot. Called when "Remove" button is pressed.
+ */
+void MultiDatasetFit::removeSelectedSpectra()
+{
+  auto ranges = m_uiForm.dataTable->selectedRanges();
+  if ( ranges.isEmpty() ) return;
+  std::vector<int> rows;
+  for(auto range = ranges.begin(); range != ranges.end(); ++range)
+  {
+    for(int row = range->topRow(); row <= range->bottomRow(); ++row)
+    {
+      rows.push_back( row );
+    }
+  }
+  removeDataSets( rows );
+}
+
+/**
+ * Create a multi-domain function to fit all the spectra in the data table.
+ */
+boost::shared_ptr<Mantid::API::IFunction> MultiDatasetFit::createFunction() const
+{
+  // number of spectra to fit == size of the multi-domain function
+  size_t nOfDataSets = getNumberOfSpectra();
+  if ( nOfDataSets == 0 )
+  {
+    throw std::runtime_error("There are no data sets specified.");
+  }
+
+  // description of a single function
+  QString funStr = m_functionBrowser->getFunctionString();
+
+  if ( nOfDataSets == 1 )
+  {
+    return Mantid::API::FunctionFactory::Instance().createInitialized( funStr.toStdString() );
+  }
+
+  bool isComposite = (std::find(funStr.begin(),funStr.end(),';') != funStr.end());
+  if ( isComposite )
+  {
+    funStr = ";(" + funStr + ")";
+  }
+  else
+  {
+    funStr = ";" + funStr;
+  }
+
+  QString multiFunStr = "composite=MultiDomainFunction,NumDeriv=1";
+  for(size_t i = 0; i < nOfDataSets; ++i)
+  {
+    multiFunStr += funStr;
+  }
+
+  // add the global ties
+  QStringList globals = m_functionBrowser->getGlobalParameters();
+  QString globalTies;
+  if ( !globals.isEmpty() )
+  {
+    globalTies = "ties=(";
+    bool isFirst = true;
+    foreach(QString par, globals)
+    {
+      if ( !isFirst ) globalTies += ",";
+      else
+        isFirst = false;
+
+      for(size_t i = 1; i < nOfDataSets; ++i)
+      {
+        globalTies += QString("f%1.").arg(i) + par + "=";
+      }
+      globalTies += QString("f0.%1").arg(par);
+    }
+    globalTies += ")";
+    multiFunStr += ";" + globalTies;
+  }
+
+  // create the multi-domain function
+  std::string tmpStr = multiFunStr.toStdString();
+  auto fun = Mantid::API::FunctionFactory::Instance().createInitialized( tmpStr );
+  boost::shared_ptr<Mantid::API::MultiDomainFunction> multiFun = boost::dynamic_pointer_cast<Mantid::API::MultiDomainFunction>( fun );
+  if ( !multiFun )
+  {
+    throw std::runtime_error("Failed to create the MultiDomainFunction");
+  }
+  
+  auto globalParams = m_functionBrowser->getGlobalParameters();
+
+  // set the domain indices, initial local parameter values and ties
+  for(size_t i = 0; i < nOfDataSets; ++i)
+  {
+    multiFun->setDomainIndex(i,i);
+    auto fun1 = multiFun->getFunction(i);
+    for(size_t j = 0; j < fun1->nParams(); ++j)
+    {
+      auto tie = fun1->getTie(j);
+      if ( tie )
+      {
+        // if a local parameter has a constant tie (is fixed) set tie's value to 
+        // the value of the local parameter
+        if ( tie->isConstant() )
+        {
+          QString parName = QString::fromStdString(fun1->parameterName(j));
+          if ( !globalParams.contains(parName) )
+          {
+            std::string expr = boost::lexical_cast<std::string>( getLocalParameterValue(parName,static_cast<int>(i)) );
+            tie->set( expr );
+          }
+        }
+      }
+      else
+      {
+        // if local parameter isn't tied set its local value
+        QString parName = QString::fromStdString(fun1->parameterName(j));
+        if ( !globalParams.contains(parName) )
+        {
+          fun1->setParameter(j, getLocalParameterValue(parName,static_cast<int>(i)));
+        }
+      }
+    }
+  }
+  assert( multiFun->nFunctions() == nOfDataSets );
+
+  return fun;
+}
+
+/**
+ * Run the fitting algorithm.
+ */
+void MultiDatasetFit::fit()
+{
+  if ( !m_functionBrowser->hasFunction() )
+  {
+    QMessageBox::warning( this, "MantidPlot - Warning","Function wasn't set." );
+    return;
+  }
+
+  try
+  {
+    auto fun = createFunction();
+    auto fit = Mantid::API::AlgorithmManager::Instance().create("Fit");
+    fit->initialize();
+    fit->setProperty("Function", fun );
+    fit->setPropertyValue("InputWorkspace", getWorkspaceName(0));
+    fit->setProperty("WorkspaceIndex", getWorkspaceIndex(0));
+
+    m_outputWorkspaceName = "out";
+    fit->setPropertyValue("Output",m_outputWorkspaceName);
+    m_outputWorkspaceName += "_Workspace";
+
+    int n = getNumberOfSpectra();
+    for(int ispec = 1; ispec < n; ++ispec)
+    {
+      std::string suffix = boost::lexical_cast<std::string>(ispec);
+      fit->setPropertyValue( "InputWorkspace_" + suffix, getWorkspaceName(ispec) );
+      fit->setProperty( "WorkspaceIndex_" + suffix, getWorkspaceIndex(ispec) );
+    }
+
+    m_fitRunner.reset( new API::AlgorithmRunner() );
+    connect( m_fitRunner.get(),SIGNAL(algorithmComplete(bool)), this, SLOT(finishFit(bool)), Qt::QueuedConnection );
+
+    m_fitRunner->startAlgorithm(fit);
+
+  }
+  catch(std::exception& e)
+  {
+    QString mess(e.what());
+    const int maxSize = 500;
+    if ( mess.size() > maxSize )
+    {
+      mess = mess.mid(0,maxSize);
+      mess += "...";
+    }
+    QMessageBox::critical( this, "MantidPlot - Error", QString("Fit failed:\n\n  %1").arg(mess) );
+  }
+}
+
+/**
+ * Get the workspace name of the i-th spectrum.
+ * @param i :: Index of a spectrum in the data table.
+ */
+std::string MultiDatasetFit::getWorkspaceName(int i) const
+{
+  return m_uiForm.dataTable->item(i, wsColumn)->text().toStdString();
+}
+
+/**
+ * Get the workspace index of the i-th spectrum.
+ * @param i :: Index of a spectrum in the data table.
+ */
+int MultiDatasetFit::getWorkspaceIndex(int i) const
+{
+  return m_uiForm.dataTable->item(i, wsIndexColumn)->text().toInt();
+}
+
+/**
+ * Get the number of spectra to fit to.
+ */
+int MultiDatasetFit::getNumberOfSpectra() const
+{
+  return m_uiForm.dataTable->rowCount();
+}
+
+/**
+ * Start an editor to display and edit individual local parameter values.
+ * @param parName :: Fully qualified name for a local parameter (Global unchecked).
+ */
+void MultiDatasetFit::editLocalParameterValues(const QString& parName)
+{
+  EditLocalParameterDialog dialog(this,parName);
+  dialog.exec();
+}
+
+/**
+ * Get value of a local parameter
+ * @param parName :: Name of a parameter.
+ * @param i :: Data set index.
+ */
+double MultiDatasetFit::getLocalParameterValue(const QString& parName, int i) const
+{
+  if ( !m_localParameterValues.contains(parName) || m_localParameterValues[parName].size() != getNumberOfSpectra() )
+  {
+    initLocalParameter(parName);
+  }
+  return m_localParameterValues[parName][i];
+}
+
+void MultiDatasetFit::setLocalParameterValue(const QString& parName, int i, double value)
+{
+  if ( !m_localParameterValues.contains(parName) || m_localParameterValues[parName].size() != getNumberOfSpectra() )
+  {
+    initLocalParameter(parName);
+  }
+  m_localParameterValues[parName][i] = value;
+}
+
+/**
+ * Init a local parameter. Define initial values for all datasets.
+ * @param parName :: Name of parametere to init.
+ */
+void MultiDatasetFit::initLocalParameter(const QString& parName)const
+{
+  double value = m_functionBrowser->getParameter(parName);
+  QVector<double> values( static_cast<int>(getNumberOfSpectra()), value );
+  m_localParameterValues[parName] = values;
+}
+
+void MultiDatasetFit::reset()
+{
+  m_localParameterValues.clear();
+}
+
+void MultiDatasetFit::finishFit(bool)
+{
+  m_plotController->clear();
+  m_plotController->update();
+  Mantid::API::IFunction_sptr fun = m_fitRunner->getAlgorithm()->getProperty("Function");
+  updateParameters( *fun );
+}
+
+/**
+ * Update the interface to have the sametparameter values as in a function.
+ */
+void MultiDatasetFit::updateParameters(const Mantid::API::IFunction& fun)
+{
+  m_localParameterValues.clear();
+  auto cfun = dynamic_cast<const Mantid::API::CompositeFunction*>( &fun );
+  if ( cfun && cfun->nFunctions() > 0 )
+  {
+    auto qLocalParameters = m_functionBrowser->getLocalParameters();
+    std::vector<std::string> localParameters;
+    foreach(QString par, qLocalParameters)
+    {
+      localParameters.push_back( par.toStdString() );
+    }
+    size_t currentIndex = static_cast<size_t>( m_plotController->getCurrentIndex() );
+    for(size_t i = 0; i < cfun->nFunctions(); ++i)
+    {
+      auto sfun = cfun->getFunction(i);
+      if ( i == currentIndex )
+      {
+        m_functionBrowser->updateParameters( *sfun );
+      }
+      for(int j = 0; j < qLocalParameters.size(); ++j)
+      {
+        setLocalParameterValue( qLocalParameters[j], static_cast<int>(i), sfun->getParameter(localParameters[j]) );
+      }
+    }
+  }
+  else
+  {
+    m_functionBrowser->updateParameters( fun );
+  }
+}
+
+/**
+ * Update the local parameters in the function browser to show values corresponding
+ * to a particular dataset.
+ * @param index :: Index of a dataset.
+ */
+void MultiDatasetFit::updateLocalParameters(int index)
+{
+  auto localParameters = m_functionBrowser->getLocalParameters();
+  foreach(QString par, localParameters)
+  {
+    m_functionBrowser->setParameter( par, getLocalParameterValue( par, index ) );
+  }
+}
+
+/**
+ * Show a message in the info bar at the bottom of the interface.
+ */
+void MultiDatasetFit::showInfo(const QString& text)
+{
+  m_uiForm.infoBar->setText(text);
+}
+
+bool MultiDatasetFit::eventFilter(QObject *widget, QEvent *evn)
+{
+  if ( evn->type() == QEvent::Enter )
+  {
+    if ( qobject_cast<QObject*>( m_functionBrowser ) == widget )
+    {
+      showFunctionBrowserInfo();
+    }
+    else if ( qobject_cast<QObject*>( m_uiForm.plot ) == widget )
+    {
+      showPlotInfo();
+    }
+    else if ( qobject_cast<QObject*>( m_uiForm.dataTable ) == widget )
+    {
+      showTableInfo();
+    }
+    else
+    {
+      showInfo("");
+    }
+  }
+  return false;
+}
+
+/**
+ * Show info about the function browser.
+ */
+void MultiDatasetFit::showFunctionBrowserInfo()
+{
+  if ( m_functionBrowser->hasFunction() )
+  {
+    showInfo( "Use context menu to add more functions. Set parameters and attributes." );
+  }
+  else
+  {
+    showInfo( "Use context menu to add a function." );
+  }
+}
+
+/**
+ * Show info about the plot.
+ */
+void MultiDatasetFit::showPlotInfo()
+{
+  QString text = "Use Alt+. and Alt+, to change the data set. ";
+
+  if ( m_plotController->isZoomEnabled() )
+  {
+    text += "Click and drag to zoom in. Use middle or right button to zoom out";
+  }
+  else if ( m_plotController->isPanEnabled() )
+  {
+    text += "Click and drag to move. Use mouse wheel to zoom in and out.";
+  }
+  
+  showInfo( text );
+}
+
+void MultiDatasetFit::showTableInfo()
+{
+  if ( getNumberOfSpectra() > 0 )
+  {
+    showInfo("Select spectra by selecting rows. For multiple selection use Shift or Ctrl keys.");
+  }
+  else
+  {
+    showInfo("Add some data sets. Click \"Add Workspace\" button.");
+  }
+}
+
+/**
+ * Check that the data sets in the table are valid and remove invalid ones.
+ */
+void MultiDatasetFit::checkDataSets()
+{
+  std::vector<int> rows;
+  int nrows = getNumberOfSpectra();
+  auto& ADS = Mantid::API::AnalysisDataService::Instance();
+  for( int row = 0; row < nrows; ++row)
+  {
+    auto wsName = getWorkspaceName( row );
+    auto i = getWorkspaceIndex( row );
+    if ( !ADS.doesExist( wsName ) )
+    {
+      rows.push_back( row );
+      continue;
+    }
+    auto ws = ADS.retrieveWS<Mantid::API::MatrixWorkspace>( wsName );
+    if ( !ws || i >= static_cast<int>( ws->getNumberHistograms() ) )
+    {
+      rows.push_back( row );
+      continue;
+    }
+  }
+
+  removeDataSets( rows );
+}
+
+void MultiDatasetFit::removeDataSets( std::vector<int>& rows )
+{
+  if ( rows.empty() ) return;
+  std::sort( rows.begin(), rows.end() );
+  for(auto row = rows.rbegin(); row != rows.rend(); ++row)
+  {
+    m_uiForm.dataTable->removeRow( *row );
+  }
+  emit dataTableUpdated();
+}
+
+/*==========================================================================================*/
+} // CustomInterfaces
+} // MantidQt
diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h
index eb357a5945f2a93af8b3b754487c3e8bff314d73..1f2b9aba85fc93265981ab8a6cd13ccd17ae6d40 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h
+++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/FunctionBrowser.h
@@ -80,7 +80,7 @@ public:
   };
 
   /// Constructor
-  FunctionBrowser(QWidget *parent = NULL);
+  FunctionBrowser(QWidget *parent = NULL, bool multi = false);
   /// Destructor
   ~FunctionBrowser();
   /// Clear the contents
@@ -93,6 +93,12 @@ public:
   QString getFunctionString();
   /// Return the function
   Mantid::API::IFunction_sptr getFunction(QtProperty* prop = NULL, bool attributesOnly = false);
+  /// Check if a function is set
+  bool hasFunction() const;
+  /// Get a list of names of global parameters
+  QStringList getGlobalParameters() const;
+  /// Get a list of names of local parameters
+  QStringList getLocalParameters() const;
 
   /// Return a function with specified index
   Mantid::API::IFunction_sptr getFunctionByIndex(const QString& index);
@@ -102,6 +108,14 @@ public:
 
   /// Update the function parameter value
   void setParameter(const QString& funcIndex, const QString& paramName, double value);
+  /// Get a value of a parameter
+  double getParameter(const QString& funcIndex, const QString& paramName) const;
+  /// Update the function parameter value
+  void setParameter(const QString& paramName, double value);
+  /// Get a value of a parameter
+  double getParameter(const QString& paramName) const;
+  /// Update parameter values in the browser to match those of a function.
+  void updateParameters(const Mantid::API::IFunction& fun);
 
 signals:
   /// User selects a different function (or one of it's sub-properties)
@@ -112,6 +126,11 @@ signals:
   /// @param paramName :: Name of the changed parameter
   void parameterChanged(const QString& funcIndex, const QString& paramName);
 
+  /// In multi-dataset context a button value editor was clicked
+  void localParameterButtonClicked(const QString& parName);
+
+  void functionStructureChanged();
+
 protected:
   /// Create the Qt property browser
   void createBrowser();
@@ -138,7 +157,7 @@ protected:
   /// Update function index properties 
   void updateFunctionIndices(QtProperty* prop = NULL, QString index = "");
   /// Get property of the overall function
-  AProperty getFunctionProperty();
+  AProperty getFunctionProperty() const;
   /// Check if property is a function group
   bool isFunction(QtProperty* prop) const;
   /// Check if property is a function attribute
@@ -162,7 +181,9 @@ protected:
   /// Get the function index for a property
   QString getIndex(QtProperty* prop) const;
   /// Get function property for the index
-  QtProperty* getFunctionProperty(const QString& index);
+  QtProperty* getFunctionProperty(const QString& index)const;
+  /// Split a qualified parameter name into function index and local parameter name.
+  QStringList splitParameterName(const QString& paramName) const;
 
   /// Add a tie property
   AProperty addTieProperty(QtProperty* prop, QString tie);
@@ -222,6 +243,7 @@ protected slots:
   void attributeVectorDoubleChanged(QtProperty*);
   /// Called when a function parameter property is changed
   void parameterChanged(QtProperty*);
+  void parameterButtonClicked(QtProperty*);
 
 protected:
   /// Manager for function group properties
@@ -295,11 +317,13 @@ protected:
   /// Index of currently selected function. Gets updated in updateCurrentFunctionIndex()
   boost::optional<QString> m_currentFunctionIndex;
 
+  /// Set true if the constructed function is intended to be used in a multi-dataset fit
+  bool m_multiDataset;
+
   friend class CreateAttributePropertyForFunctionBrowser;
   friend class SetAttributeFromProperty;
 };
 
-
 } // MantidWidgets
 
 } // MantidQt
diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp
index 68d07530a20272ceca8d812953f856e655bc870f..874e0423532f04af14b9dda86758be24108fb236 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp
+++ b/Code/Mantid/MantidQt/MantidWidgets/src/FunctionBrowser.cpp
@@ -40,6 +40,8 @@
 #endif
 #include "qteditorfactory.h"
 #include "DoubleEditorFactory.h"
+#include "CompositeEditorFactory.h"
+#include "ButtonEditorFactory.h"
 #if defined(__INTEL_COMPILER)
   #pragma warning enable 1125
 #elif defined(__GNUC__)
@@ -65,6 +67,9 @@
 
 #include <algorithm>
 
+namespace{
+  const char * globalOptionName = "Global";
+}
 
 namespace MantidQt
 {
@@ -74,9 +79,10 @@ namespace MantidWidgets
 /**
  * Constructor
  * @param parent :: The parent widget.
+ * @param multi  :: Option to use the browser for multi-dataset fitting.
  */
-FunctionBrowser::FunctionBrowser(QWidget *parent)
-:QWidget(parent)
+FunctionBrowser::FunctionBrowser(QWidget *parent, bool multi)
+  :QWidget(parent),m_multiDataset(multi)
 {
   // create m_browser
   createBrowser();
@@ -101,6 +107,12 @@ FunctionBrowser::~FunctionBrowser()
  */
 void FunctionBrowser::createBrowser()
 {
+  QStringList options;
+  if ( m_multiDataset )
+  {
+    options << globalOptionName;
+  }
+
   /* Create property managers: they create, own properties, get and set values  */
   m_functionManager = new QtGroupPropertyManager(this);
   m_parameterManager = new QtDoublePropertyManager(this);
@@ -121,15 +133,30 @@ void FunctionBrowser::createBrowser()
   // create editor factories
   QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(this);
   DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(this);
+
+  QtAbstractEditorFactory<QtDoublePropertyManager> *parameterEditorFactory(NULL);
+  if ( m_multiDataset )
+  {
+    auto buttonFactory = new DoubleButtonEditorFactory(this);
+    auto compositeFactory = new CompositeEditorFactory<QtDoublePropertyManager>(this,buttonFactory);
+    compositeFactory->setSecondaryFactory(globalOptionName, doubleEditorFactory);
+    parameterEditorFactory = compositeFactory;
+    connect(buttonFactory,SIGNAL(buttonClicked(QtProperty*)), this,SLOT(parameterButtonClicked(QtProperty*)));
+  }
+  else
+  {
+    parameterEditorFactory = doubleEditorFactory;
+  }
+  
   QtLineEditFactory *lineEditFactory = new QtLineEditFactory(this);
   QtCheckBoxFactory *checkBoxFactory = new QtCheckBoxFactory(this);
   FilenameDialogEditorFactory* filenameDialogEditorFactory = new FilenameDialogEditorFactory(this);
   FormulaDialogEditorFactory* formulaDialogEditFactory = new FormulaDialogEditorFactory(this);
   WorkspaceEditorFactory* workspaceEditorFactory = new WorkspaceEditorFactory(this);
 
-  m_browser = new QtTreePropertyBrowser();
+  m_browser = new QtTreePropertyBrowser(NULL,options);
   // assign factories to property managers
-  m_browser->setFactoryForManager(m_parameterManager, doubleEditorFactory);
+  m_browser->setFactoryForManager(m_parameterManager, parameterEditorFactory);
   m_browser->setFactoryForManager(m_attributeStringManager, lineEditFactory);
   m_browser->setFactoryForManager(m_attributeDoubleManager, doubleEditorFactory);
   m_browser->setFactoryForManager(m_attributeIntManager, spinBoxFactory);
@@ -238,6 +265,7 @@ void FunctionBrowser::setFunction(Mantid::API::IFunction_sptr fun)
 {
   clear();
   addFunction(NULL,fun);
+  emit functionStructureChanged();
 }
 
 /**
@@ -378,7 +406,12 @@ FunctionBrowser::AProperty FunctionBrowser::addParameterProperty(QtProperty* par
     throw std::runtime_error("Unexpected error in FunctionBrowser [3]");
   }
   QtProperty* prop = m_parameterManager->addProperty(paramName);
+  m_parameterManager->setDecimals(prop,6);
   m_parameterManager->setValue(prop,paramValue);
+  if ( m_multiDataset )
+  {
+    prop->setOption(globalOptionName,false);
+  }
   return addProperty(parent,prop);
 }
 
@@ -710,7 +743,7 @@ void FunctionBrowser::updateFunctionIndices(QtProperty* prop, QString index)
 /**
  * Get property of the overall function.
  */
-FunctionBrowser::AProperty FunctionBrowser::getFunctionProperty()
+FunctionBrowser::AProperty FunctionBrowser::getFunctionProperty() const
 {
   auto props = m_browser->properties();
   if ( props.isEmpty() )
@@ -725,6 +758,39 @@ FunctionBrowser::AProperty FunctionBrowser::getFunctionProperty()
   return m_properties[prop];
 }
 
+/**
+ * Get a list of names of global parameters
+ */
+QStringList FunctionBrowser::getGlobalParameters() const
+{
+  QStringList out;
+  for(auto propIt = m_properties.begin(); propIt != m_properties.end(); ++propIt)
+  {
+    QtProperty *prop = propIt->prop;
+    if ( prop->hasOption(globalOptionName) && prop->checkOption(globalOptionName) )
+    {
+      out << getIndex(prop) + prop->propertyName();
+    }
+  }
+  return out;
+}
+
+/**
+ * Get a list of names of local parameters
+ */
+QStringList FunctionBrowser::getLocalParameters() const
+{
+  QStringList out;
+  for(auto propIt = m_properties.begin(); propIt != m_properties.end(); ++propIt)
+  {
+    QtProperty *prop = propIt->prop;
+    if ( prop->hasOption(globalOptionName) && !prop->checkOption(globalOptionName) )
+    {
+      out << getIndex(prop) + prop->propertyName();
+    }
+  }
+  return out;
+}
 
 /**
  * Check if property is a function group
@@ -736,7 +802,7 @@ bool FunctionBrowser::isFunction(QtProperty* prop) const
 }
 
 /**
- * Check if property is a function attribute
+ * Check if property is any of the string attributes
  * @param prop :: Property to check
  */
 bool FunctionBrowser::isStringAttribute(QtProperty* prop) const
@@ -852,7 +918,7 @@ QString FunctionBrowser::getIndex(QtProperty* prop) const
  * @param index :: Function index to search, or empty string for top-level function
  * @return Function property, or NULL if not found
  */
-QtProperty* FunctionBrowser::getFunctionProperty(const QString& index)
+QtProperty* FunctionBrowser::getFunctionProperty(const QString& index) const
 {
   // Might not be the most efficient way to do it. m_functionManager might be searched instead,
   // but it is not being kept up-to-date at the moment (is not cleared).
@@ -1277,6 +1343,7 @@ void FunctionBrowser::addFunction()
   {// the browser is empty - add first function
     addFunction(NULL,f);
   }
+  emit functionStructureChanged();
 }
 
 /**
@@ -1444,6 +1511,84 @@ void FunctionBrowser::setParameter(const QString& funcIndex, const QString& para
   }
 }
 
+/**
+ * Get a value of a parameter
+ * @param funcIndex :: Index of the function
+ * @param paramName :: Parameter name
+ */
+double FunctionBrowser::getParameter(const QString& funcIndex, const QString& paramName) const
+{
+  if (auto prop = getFunctionProperty(funcIndex))
+  {
+    auto children = prop->subProperties();
+    foreach(QtProperty* child, children)
+    {
+      if (isParameter(child) && child->propertyName() == paramName)
+      {
+        return m_parameterManager->value(child);
+      }
+    }
+  }
+  throw std::runtime_error("Unknown function parameter " + (funcIndex + paramName).toStdString());
+}
+
+/**
+ * Split a qualified parameter name into function index and local parameter name.
+ * @param paramName :: Fully qualified parameter name (includes function index)
+ * @return :: A string list with the first item is the function index and the second
+ *   item is the param local name.
+ */
+QStringList FunctionBrowser::splitParameterName(const QString& paramName) const
+{
+  QString functionIndex;
+  QString parameterName = paramName;
+  int j = paramName.lastIndexOf('.');
+  if ( j > 0 )
+  {
+    ++j;
+    functionIndex = paramName.mid(0,j);
+    parameterName = paramName.mid(j);
+  }
+  QStringList res;
+  res << functionIndex << parameterName;
+  return res;
+}
+
+/**
+ * Updates the function parameter value
+ * @param paramName :: Fully qualified parameter name (includes function index)
+ * @param value :: New value
+ */
+void FunctionBrowser::setParameter(const QString& paramName, double value)
+{
+  QStringList name = splitParameterName(paramName);
+  setParameter(name[0],name[1],value);
+}
+
+/**
+ * Get a value of a parameter
+ * @param paramName :: Fully qualified parameter name (includes function index)
+ */
+double FunctionBrowser::getParameter(const QString& paramName) const
+{
+  QStringList name = splitParameterName(paramName);
+  return getParameter(name[0],name[1]);
+}
+
+/**
+ * Update parameter values in the browser to match those of a function.
+ * @param fun :: A function to copy the values from. It must have the same
+ *   type (composition) as the function in the browser.
+ */
+void FunctionBrowser::updateParameters(const Mantid::API::IFunction& fun)
+{
+  auto paramNames = fun.getParameterNames();
+  for(auto par = paramNames.begin(); par != paramNames.end(); ++par)
+  {
+    setParameter( QString::fromStdString(*par), fun.getParameter(*par) );
+  }
+}
+
 /**
  * Return FunctionFactory function string
  */
@@ -1465,6 +1610,7 @@ void FunctionBrowser::removeFunction()
   if (!isFunction(prop)) return;
   removeProperty(prop);
   updateFunctionIndices();
+  emit functionStructureChanged();
 }
 
 /**
@@ -1673,6 +1819,15 @@ void FunctionBrowser::parameterChanged(QtProperty* prop)
   emit parameterChanged(getIndex(prop), prop->propertyName());
 }
 
+void FunctionBrowser::parameterButtonClicked(QtProperty *prop)
+{
+  emit localParameterButtonClicked(getIndex(prop) + prop->propertyName());
+}
+
+bool FunctionBrowser::hasFunction() const
+{
+  return ! m_functionManager->properties().isEmpty();
+}
 
 } // MantidWidgets
 } // MantidQt
diff --git a/Code/Mantid/QtPropertyBrowser/CMakeLists.txt b/Code/Mantid/QtPropertyBrowser/CMakeLists.txt
index 1602611929eff1e9c95c4154f96b2ee21d0d7c6a..7c29f5f3e662163dae3b50d1fda730ecd743bc92 100644
--- a/Code/Mantid/QtPropertyBrowser/CMakeLists.txt
+++ b/Code/Mantid/QtPropertyBrowser/CMakeLists.txt
@@ -40,7 +40,7 @@ qt4_generate_moc (
   ${CMAKE_CURRENT_BINARY_DIR}/moc_qtpropertymanager.cpp
 )
 qt4_generate_moc (
-  src/qteditorfactory.h
+  src/qteditorfactory.h 
   ${CMAKE_CURRENT_BINARY_DIR}/moc_qteditorfactory.cpp
 )
 qt4_generate_moc (
@@ -103,6 +103,7 @@ set (
 )
 
 qt4_wrap_cpp ( EXTRA_MOCS src/DoubleEditorFactory.h 
+                          src/ButtonEditorFactory.h
                           src/ParameterPropertyManager.h
 )
 
diff --git a/Code/Mantid/QtPropertyBrowser/src/ButtonEditorFactory.h b/Code/Mantid/QtPropertyBrowser/src/ButtonEditorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..5377cf692879688e245cffffb3c0e317619f4930
--- /dev/null
+++ b/Code/Mantid/QtPropertyBrowser/src/ButtonEditorFactory.h
@@ -0,0 +1,73 @@
+#ifndef BUTTONEDITORFACTORY_H
+#define BUTTONEDITORFACTORY_H
+
+#include "qtpropertymanager.h"
+#include <QPushButton>
+
+class QT_QTPROPERTYBROWSER_EXPORT ButtonEditor: public QPushButton
+{
+  Q_OBJECT
+public:
+  ButtonEditor(QtProperty *property, QWidget *parent):
+    QPushButton("...",parent), m_property(property)
+  {
+    connect(this,SIGNAL(clicked()),this,SLOT(sendClickedSignal()));
+  }
+Q_SIGNALS:
+  void buttonClicked(QtProperty *);
+private Q_SLOTS:
+  void sendClickedSignal()
+  {
+    emit buttonClicked(m_property);
+  }
+
+private:
+  QtProperty* m_property;
+};
+
+template <class ManagerType>
+class ButtonEditorFactory : public QtAbstractEditorFactory<ManagerType>
+{
+//  Q_OBJECT
+public:
+  ButtonEditorFactory(QObject *parent)
+    : QtAbstractEditorFactory<ManagerType>(parent)
+  {
+  }
+
+protected:
+  void connectPropertyManager(ManagerType *manager)
+  {
+    (void) manager; // Unused
+    // Do nothing
+  }
+
+  void disconnectPropertyManager(ManagerType *manager)
+  {
+    (void) manager; // Unused
+    // Do nothing
+  }
+
+  QWidget *createEditor(ManagerType *manager, QtProperty *property, QWidget *parent)
+  {
+    (void) manager; // Unused
+    auto button = new ButtonEditor(property, parent);
+    this->connect(button,SIGNAL(buttonClicked(QtProperty *)),this,SIGNAL(buttonClicked(QtProperty *)));
+    return button;
+  }
+};
+
+class QT_QTPROPERTYBROWSER_EXPORT DoubleButtonEditorFactory: public ButtonEditorFactory<QtDoublePropertyManager>
+{
+  Q_OBJECT
+
+public:
+  DoubleButtonEditorFactory(QObject *parent):ButtonEditorFactory<QtDoublePropertyManager>(parent){}
+
+Q_SIGNALS:
+  void buttonClicked(QtProperty *);
+
+};
+
+
+#endif // BUTTONEDITORFACTORY_H
diff --git a/Code/Mantid/QtPropertyBrowser/src/CompositeEditorFactory.h b/Code/Mantid/QtPropertyBrowser/src/CompositeEditorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..236cefcc8eb965c6805119e439ed05c846e64d22
--- /dev/null
+++ b/Code/Mantid/QtPropertyBrowser/src/CompositeEditorFactory.h
@@ -0,0 +1,66 @@
+#ifndef COMPOSITEEDITORFACTORY_H
+#define COMPOSITEEDITORFACTORY_H
+
+#include "qtpropertybrowser.h"
+#include <QPushButton>
+
+/**
+ * Composite factory for a particular property manger type.
+ * Client must specify a secondary factory for properties with a particular
+ * option set. If this option is set crates editor using the scondary factory.
+ * Creates the default editor (with the factory passed to the constructor)
+ * if the option isn't set or property doesn't have this option.
+ * @param ManagerType :: Manager class to use
+ */
+template <class ManagerType>
+class CompositeEditorFactory : public QtAbstractEditorFactory<ManagerType>
+{
+  typedef QtAbstractEditorFactory<ManagerType> FactoryBaseType;
+public:
+  CompositeEditorFactory(QObject *parent, FactoryBaseType *defaultFactory)
+    : QtAbstractEditorFactory<ManagerType>(parent), 
+    m_defaultFactory(defaultFactory),
+    m_secondaryFactory(NULL)
+  {
+  }
+
+  void setSecondaryFactory( const QString &optionName, FactoryBaseType *factory )
+  {
+    m_optionName = optionName;
+    m_secondaryFactory = factory;
+  }
+
+protected:
+  void connectPropertyManager(ManagerType *manager)
+  {
+    (void) manager; // Unused
+    // Do nothing
+  }
+
+  void disconnectPropertyManager(ManagerType *manager)
+  {
+    (void) manager; // Unused
+    // Do nothing
+  }
+
+  QWidget *createEditor(ManagerType *manager, QtProperty *property, QWidget *parent)
+  {
+    if ( !m_secondaryFactory )
+    {
+      throw std::logic_error("Secondary editor factory isn't set.");
+    }
+
+    if ( property->hasOption(m_optionName) && property->checkOption(m_optionName) )
+    {
+      return m_secondaryFactory->createEditor( manager, property, parent );
+    }
+
+    return m_defaultFactory->createEditor( manager, property, parent );
+  }
+private:
+  FactoryBaseType *m_defaultFactory;
+  FactoryBaseType *m_secondaryFactory;
+  QString m_optionName;
+};
+
+#endif // COMPOSITEEDITORFACTORY_H
diff --git a/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.cpp b/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.cpp
index f38d0230ae103673212edec018aff471e2346b40..32964e20387c3b6d4f914704eddca3fcbfdc1cc4 100644
--- a/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.cpp
+++ b/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.cpp
@@ -106,6 +106,7 @@ public:
 
     QSet<QtProperty *> m_parentItems;
     QList<QtProperty *> m_subItems;
+    QMap<QString,bool> m_options;
 
     QString m_toolTip;
     QString m_statusTip;
@@ -527,6 +528,22 @@ void QtProperty::removeSubProperty(QtProperty *property)
     }
 }
 
+bool QtProperty::hasOption(const QString &opt) const
+{
+  return d_ptr->m_options.contains(opt);
+}
+
+bool QtProperty::checkOption(const QString &opt) const
+{
+  if ( !d_ptr->m_options.contains(opt) ) return false;
+  return d_ptr->m_options[opt];
+}
+
+void QtProperty::setOption(const QString &opt, bool on)
+{
+  d_ptr->m_options[opt] = on;
+}
+
 /**
     \internal
 */
diff --git a/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.h b/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.h
index 544f7765f19b125e3b6b8c62067ceea48fe6de2e..756389241b184b653683172d9e082e0f4bf9b0de 100644
--- a/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.h
+++ b/Code/Mantid/QtPropertyBrowser/src/qtpropertybrowser.h
@@ -145,6 +145,10 @@ public:
     void addSubProperty(QtProperty *property);
     void insertSubProperty(QtProperty *property, QtProperty *afterProperty);
     void removeSubProperty(QtProperty *property);
+
+    bool hasOption(const QString &opt) const;
+    bool checkOption(const QString &opt) const;
+    void setOption(const QString &opt, bool on);
 protected:
     explicit QtProperty(QtAbstractPropertyManager *manager);
     void propertyChanged();
@@ -204,6 +208,10 @@ protected Q_SLOTS:
     friend class QtAbstractPropertyBrowser;
 };
 
+template <class PropertyManager>
+class CompositeEditorFactory;
+
+
 template <class PropertyManager>
 class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase
 {
@@ -255,6 +263,7 @@ public:
         return 0;
     }
 protected:
+    friend class CompositeEditorFactory<PropertyManager>;
     virtual void connectPropertyManager(PropertyManager *manager) = 0;
     virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property,
                 QWidget *parent) = 0;
diff --git a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp
index c53fb787eb348d661a47ac392675d7f44da189f7..500b031701796236b458cbf9172f875a55cd78b5 100644
--- a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp
+++ b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.cpp
@@ -97,6 +97,8 @@
 #include <QtGui/QFocusEvent>
 #include <QtGui/QStyle>
 #include <QtGui/QPalette>
+#include <QtGui/qcheckbox.h>
+#include <QtGui/qlineedit.h>
 
 #include <iostream>
 
@@ -104,6 +106,43 @@
 QT_BEGIN_NAMESPACE
 #endif
 
+class PropertyOptionCheckBox: public QWidget
+{
+  Q_OBJECT
+public:
+  PropertyOptionCheckBox(QWidget *parent,QtProperty *property, const QString &optionName):
+    QWidget(parent),
+    m_property(property),
+    m_optionName(optionName),
+    m_checked(property->checkOption(optionName))
+  {
+    setFocusPolicy(Qt::StrongFocus);
+  }
+  void paintEvent (QPaintEvent*)
+  {
+      QStyleOptionButton opt;
+      auto state = isChecked() ? QStyle::State_On : QStyle::State_Off;
+      opt.state |= state;
+      opt.rect = rect();
+      opt.rect.setWidth(opt.rect.height());
+      QPainter painter(this);
+      QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox,&opt,&painter);
+  }
+  void mousePressEvent (QMouseEvent* event)
+  {
+    event->accept();
+    setChecked( ! isChecked() );
+    m_property->setOption( m_optionName, isChecked() );
+    update();
+  }
+  void setChecked(bool on){m_checked = on;}
+  bool isChecked() const {return m_checked;}
+private:
+  QtProperty *m_property;
+  QString m_optionName;
+  bool m_checked;
+};
+
 class QtPropertyEditorView;
 
 class QtTreePropertyBrowserPrivate
@@ -113,7 +152,7 @@ class QtTreePropertyBrowserPrivate
 
 public:
     QtTreePropertyBrowserPrivate();
-    void init(QWidget *parent);
+    void init(QWidget *parent, const QStringList &options);
 
     void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
     void propertyRemoved(QtBrowserItem *index);
@@ -145,6 +184,8 @@ public:
 
     QTreeWidgetItem *editedItem() const;
 
+    const QStringList& options() const {return m_options;}
+
 private:
     void updateItem(QTreeWidgetItem *item);
 
@@ -161,6 +202,7 @@ private:
     bool m_markPropertiesWithoutValue;
     bool m_browserChangedBlocked;
     QIcon m_expandIcon;
+    QStringList m_options; // options that can be associated with QtProperties
 };
 
 // ------------ QtPropertyEditorView
@@ -255,6 +297,7 @@ void QtPropertyEditorView::mousePressEvent(QMouseEvent *event)
 {
     QTreeWidget::mousePressEvent(event);
     QTreeWidgetItem *item = itemAt(event->pos());
+    auto index = currentIndex();
 
     if (item) {
         if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton)
@@ -265,6 +308,10 @@ void QtPropertyEditorView::mousePressEvent(QMouseEvent *event)
             if (event->pos().x() + header()->offset() < 20)
                 item->setExpanded(!item->isExpanded());
         }
+        else if (index.column() == 2)
+        {
+          editItem(item,2);
+        }
     }
 }
 
@@ -374,6 +421,20 @@ QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent,
             return editor;
         }
     }
+    if (index.column() > 1 && m_editorPrivate) {
+      QtProperty *property = m_editorPrivate->indexToProperty(index);
+      int optionIndex = index.column() - 2;
+      if ( optionIndex >= m_editorPrivate->options().size() )
+      {
+        return NULL;
+      }
+      QString optionName = m_editorPrivate->options()[optionIndex];
+      if ( property->hasOption(optionName) )
+      {
+        QWidget *editor = new PropertyOptionCheckBox(parent,property,optionName);
+        return editor;
+      }
+    }
     return 0;
 }
 
@@ -424,6 +485,25 @@ void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewIt
         painter->drawLine(right, option.rect.y(), right, option.rect.bottom());
     }
     painter->restore();
+    if ( index.column() > 1 )
+    {
+      QtProperty *property = m_editorPrivate->indexToProperty(index);
+      int optionIndex = index.column() - 2;
+      if ( optionIndex >= m_editorPrivate->options().size() )
+      {
+        return;
+      }
+      QString optionName = m_editorPrivate->options()[optionIndex];
+      if ( property->hasOption(optionName) )
+      {
+        QStyleOptionButton opt;
+        auto state = property->checkOption(optionName) ? QStyle::State_On : QStyle::State_Off;
+        opt.state |= state;
+        opt.rect = option.rect;
+        opt.rect.setWidth(opt.rect.height());
+        QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox,&opt,painter);
+      }
+    }
 }
 
 QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option,
@@ -483,7 +563,7 @@ static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style)
     return rc;
 }
 
-void QtTreePropertyBrowserPrivate::init(QWidget *parent)
+void QtTreePropertyBrowserPrivate::init(QWidget *parent, const QStringList &options)
 {
     QHBoxLayout *layout = new QHBoxLayout(parent);
     layout->setMargin(0);
@@ -492,10 +572,17 @@ void QtTreePropertyBrowserPrivate::init(QWidget *parent)
     m_treeWidget->setIconSize(QSize(18, 18));
     layout->addWidget(m_treeWidget);
 
-    m_treeWidget->setColumnCount(2);
+    m_options = options;
+    const int columnCount = 2 + m_options.size();
+    m_treeWidget->setColumnCount( columnCount );
     QStringList labels;
     labels.append(QApplication::translate("QtTreePropertyBrowser", "Property", 0, QApplication::UnicodeUTF8));
     labels.append(QApplication::translate("QtTreePropertyBrowser", "Value", 0, QApplication::UnicodeUTF8));
+    // add optional columns
+    for(auto opt = m_options.begin(); opt != m_options.end(); ++opt)
+    {
+      labels.append(QApplication::translate("QtTreePropertyBrowser", *opt, 0, QApplication::UnicodeUTF8));
+    }
     m_treeWidget->setHeaderLabels(labels);
     m_treeWidget->setAlternatingRowColors(true);
     m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed);
@@ -790,13 +877,13 @@ void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem)
 /**
     Creates a property browser with the given \a parent.
 */
-QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent)
+QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent, const QStringList &options)
     : QtAbstractPropertyBrowser(parent)
 {
     d_ptr = new QtTreePropertyBrowserPrivate;
     d_ptr->q_ptr = this;
 
-    d_ptr->init(this);
+    d_ptr->init(this,options);
     connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*)));
 }
 
diff --git a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.h b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.h
index f664609d79e3ca4a25ae844b06708f6ef50da2d7..eedded423ddd08f40be4e32637bf8950e95b3ebc 100644
--- a/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.h
+++ b/Code/Mantid/QtPropertyBrowser/src/qttreepropertybrowser.h
@@ -118,7 +118,7 @@ public:
         ResizeToContents
     };
 
-    QtTreePropertyBrowser(QWidget *parent = 0);
+    QtTreePropertyBrowser(QWidget *parent = 0, const QStringList &options = QStringList());
     ~QtTreePropertyBrowser();
 
     int indentation() const;