From 5765b43470d08f917569dba1c8da96deeab76daf Mon Sep 17 00:00:00 2001
From: Martyn Gigg <martyn.gigg@stfc.ac.uk>
Date: Tue, 8 Feb 2011 11:38:20 +0000
Subject: [PATCH] Implemented a custom dialog for the Load algorithm. It now
 dynamically generates its properties from those that the concrete loaer has,
 Refs #2329. Also fixed a problem with loading grouped nexus files through the
 Load algorithm, Re #2362

---
 .../Framework/API/src/AlgorithmProxy.cpp      |   8 +-
 .../inc/MantidDataHandling/Load.h             |   6 +-
 .../Framework/DataHandling/src/Load.cpp       |  89 ++---
 .../Framework/DataHandling/test/LoadTest.h    |  21 +
 .../API/inc/MantidQtAPI/AlgorithmDialog.h     |  62 ++-
 .../API/inc/MantidQtAPI/MantidWidget.h        |  28 +-
 .../API/inc/MantidQtAPI/PythonRunner.h        |   2 +-
 .../MantidQt/API/src/AlgorithmDialog.cpp      | 358 ++++++++++--------
 .../Mantid/MantidQt/API/src/GenericDialog.cpp |   5 -
 .../MantidQt/CustomDialogs/CMakeLists.txt     |   8 +-
 .../MantidQt/CustomDialogs/CustomDialogs.pro  |  10 +-
 .../inc/MantidQtCustomDialogs/LoadDialog.h    | 113 ++++++
 .../MantidQt/CustomDialogs/src/LoadDialog.cpp | 284 ++++++++++++++
 .../inc/MantidQtMantidWidgets/MWDiag.h        |   1 +
 .../inc/MantidQtMantidWidgets/MWRunFiles.h    |  21 +-
 .../inc/MantidQtMantidWidgets/MWRunFiles.ui   |  88 +++--
 .../MantidQt/MantidWidgets/src/MWRunFiles.cpp |  54 ++-
 17 files changed, 816 insertions(+), 342 deletions(-)
 create mode 100644 Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h
 create mode 100644 Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp

diff --git a/Code/Mantid/Framework/API/src/AlgorithmProxy.cpp b/Code/Mantid/Framework/API/src/AlgorithmProxy.cpp
index 3dd1aa5c35f..2ab783b8573 100644
--- a/Code/Mantid/Framework/API/src/AlgorithmProxy.cpp
+++ b/Code/Mantid/Framework/API/src/AlgorithmProxy.cpp
@@ -155,12 +155,8 @@ void AlgorithmProxy::setRethrows(const bool rethrow)
 void AlgorithmProxy::setPropertyValue(const std::string &name, const std::string &value)
 {
   createConcreteAlg(true);
-  const size_t numPropsAtStart = m_alg->propertyCount();
   m_alg->setPropertyValue(name, value);
-  if( numPropsAtStart != m_alg->propertyCount() )
-  {
-    copyPropertiesFrom(*m_alg);
-  }
+  copyPropertiesFrom(*m_alg);
   m_alg.reset();
 }
 
@@ -171,7 +167,7 @@ void AlgorithmProxy::setPropertyValue(const std::string &name, const std::string
 
 /** 
  * Creates an unmanaged instance of the actual algorithm and sets its properties
- * @param initOenly If true then the algorithm will only having its init step run, otherwise observers will 
+ * @param initOnly If true then the algorithm will only having its init step run, otherwise observers will 
  * also be added and rethrows will be true
  */
 void AlgorithmProxy::createConcreteAlg(bool initOnly)
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
index 048a7fdefd4..05b7b30d111 100644
--- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
@@ -72,11 +72,11 @@ namespace Mantid
       API::IAlgorithm_sptr createLoader(const std::string & name, const double startProgress = -1.0, 
 					const double endProgress=-1.0, const bool logging = true) const;
       /// Set the output workspace(s)
-      void setOutputWorkspace(API::IAlgorithm_sptr&);
+      void setOutputWorkspace(const API::IAlgorithm_sptr loader);
 
     private:
-      /// A list of property names that have been dynamically set
-      std::list<std::string> m_loaderProps;
+      /// The base properties
+      std::set<std::string> m_baseProps;
      };
 
   } // namespace DataHandling
diff --git a/Code/Mantid/Framework/DataHandling/src/Load.cpp b/Code/Mantid/Framework/DataHandling/src/Load.cpp
index dc48976c32f..f8d12fd54bc 100644
--- a/Code/Mantid/Framework/DataHandling/src/Load.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/Load.cpp
@@ -23,7 +23,7 @@ namespace Mantid
     //--------------------------------------------------------------------------
 
     /// Default constructor
-    Load::Load() : IDataFileChecker(), m_loaderProps()
+    Load::Load() : IDataFileChecker(), m_baseProps()
     {
     }
 
@@ -35,11 +35,22 @@ namespace Mantid
     void Load::setPropertyValue(const std::string &name, const std::string &value)
     {
       IDataFileChecker::setPropertyValue(name, value);
+      
+      IAlgorithm_sptr loader;
       if( name == "Filename" )
       {
-  	IAlgorithm_sptr loader = getFileLoader(getPropertyValue(name));
-  	declareLoaderProperties(loader);
+	loader = getFileLoader(getPropertyValue(name));
+      }
+      else
+      {
+	const std::string loaderName = getProperty("LoaderName");
+	if( !loaderName.empty() )
+	{
+	  loader = API::AlgorithmManager::Instance().createUnmanaged(loaderName);
+	  loader->initialize();
+	}
       }
+      if( loader ) declareLoaderProperties(loader);
     }
     
     //--------------------------------------------------------------------------
@@ -124,6 +135,8 @@ namespace Mantid
 
       if( !winningLoader )
       {
+	// Clear what may have been here previously
+	setPropertyValue("LoaderName", "");
         throw std::runtime_error("Cannot find a loader for \"" + filePath + "\"");
       }
       setPropertyValue("LoaderName", winningLoader->name());
@@ -137,18 +150,17 @@ namespace Mantid
      */
     void Load::declareLoaderProperties(const IAlgorithm_sptr loader)
     {
-      if( !m_loaderProps.empty() )
+      const std::vector<Property*> existingProps = this->getProperties();      
+      for( size_t i = 0; i < existingProps.size(); ++i )
       {
-	std::list<std::string>::const_iterator cend = m_loaderProps.end();
-	for( std::list<std::string>::const_iterator citr = m_loaderProps.begin();
-	     citr != cend; ++citr )
+	const std::string name = existingProps[i]->name();
+	if( m_baseProps.find(name) != m_baseProps.end() )
 	{
-	  this->removeProperty(*citr);
+	  continue;
 	}
-	m_loaderProps.clear();
+	this->removeProperty(name);
       }
 
-
       const std::vector<Property*> &loaderProps = loader->getProperties();
       size_t numProps(loaderProps.size());
       for (size_t i = 0; i < numProps; ++i)
@@ -163,9 +175,6 @@ namespace Mantid
 	  // Already exists as a static property
 	  continue;
 	}
-	// Save just in case a this function is called again so that we
-	// can remove the dynamically generated properties
-	m_loaderProps.push_back(loadProp->name());
       }
     }
 
@@ -192,7 +201,7 @@ namespace Mantid
       declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
         "The name of the file to read, including its full or relative\n"
         "path. (N.B. case sensitive if running on Linux).");
-      declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace", "",Direction::Output, true), 
+      declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace", "",Direction::Output), 
         "The name of the workspace that will be created, filled with the\n"
         "read-in data and stored in the Analysis Data Service.");
       BoundedValidator<int> *mustBePositive = new BoundedValidator<int>();
@@ -204,6 +213,13 @@ namespace Mantid
         "Load a particular entry, if supported by the file format (default: Load all entries)");
       declareProperty("LoaderName", std::string(""), "A string containing the name of the concrete loader used", 
         Direction::Output);
+
+      const std::vector<Property*> & props = this->getProperties();
+      for( size_t i = 0; i < this->propertyCount(); ++i )
+      {
+	m_baseProps.insert(props[i]->name());
+      }
+
     }
 
     /** 
@@ -216,7 +232,6 @@ namespace Mantid
       {
 	throw std::invalid_argument("Cannot find loader, LoaderName property has not been set.");
       }     
-      
       IAlgorithm_sptr loader = createLoader(loaderName);
       g_log.information() << "Using " << loaderName << " version " << loader->version() << ".\n";
        // Get the list of properties for the Load algorithm
@@ -286,37 +301,25 @@ namespace Mantid
      * Set the output workspace(s) if the load's return workspace has type API::Workspace
      * @param load :: Shared pointer to load algorithm
      */
-    void Load::setOutputWorkspace(API::IAlgorithm_sptr& load)
+    void Load::setOutputWorkspace(const API::IAlgorithm_sptr load)
     {
-      try
+      Workspace_sptr childWS = load->getProperty("OutputWorkspace");
+      if( WorkspaceGroup_sptr wsGroup = boost::dynamic_pointer_cast<WorkspaceGroup>(childWS) )
       {
-        Workspace_sptr ws = load->getProperty("OutputWorkspace"); 
-        WorkspaceGroup_sptr wsg = boost::dynamic_pointer_cast<WorkspaceGroup>(ws);
-        if (wsg)
-        {
-          setProperty("OutputWorkspace",ws);
-          std::vector<std::string> names = wsg->getNames();
-          for(size_t i = 0; i < names.size(); ++i)
-          {
-            std::ostringstream propName;
-            propName << "OutputWorkspace_" << (i+1);
-            DataObjects::Workspace2D_sptr memberwsws1 = load->getProperty(propName.str());
-
-            std::string memberwsName = load->getPropertyValue(propName.str());
-            declareProperty(new WorkspaceProperty<>(propName.str(),memberwsName,Direction::Output));
-            setProperty(propName.str(),boost::dynamic_pointer_cast<MatrixWorkspace>(memberwsws1));
-          }
-        }
-        else
-        { 
-          setProperty("OutputWorkspace",ws);
-        }
-      }
-      catch(std::runtime_error&)
-      {
-        MatrixWorkspace_sptr mws=load->getProperty("OutputWorkspace");
-        setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(mws));
+	std::vector<std::string> names = wsGroup->getNames();
+	const size_t numMembers(names.size());
+	const std::string baseName("OutputWorkspace_");
+	for( size_t i = 0; i < numMembers; ++i )
+	{
+	  std::ostringstream propName;
+	  propName << baseName << (i+1);
+	  declareProperty(new WorkspaceProperty<Workspace>(propName.str(), load->getPropertyValue(propName.str()),
+							   Direction::Output));
+	  Workspace_sptr memberWS = load->getProperty(propName.str());
+	  setProperty(propName.str(), memberWS);
+	}
       }
+      setProperty("OutputWorkspace", childWS);
     }
 
   } // namespace DataHandling
diff --git a/Code/Mantid/Framework/DataHandling/test/LoadTest.h b/Code/Mantid/Framework/DataHandling/test/LoadTest.h
index 0b3bb5c4935..0ae5598cf6f 100644
--- a/Code/Mantid/Framework/DataHandling/test/LoadTest.h
+++ b/Code/Mantid/Framework/DataHandling/test/LoadTest.h
@@ -8,6 +8,8 @@
 #include "MantidAPI/WorkspaceGroup.h"
 #include "MantidAPI/AnalysisDataService.h"
 
+#include "MantidAPI/AlgorithmManager.h"
+
 using namespace Mantid::API;
 using namespace Mantid::DataObjects;
 using namespace Mantid::DataHandling;
@@ -16,6 +18,25 @@ class LoadTest : public CxxTest::TestSuite
 {
 public:
 
+  void testViaProxy()
+  {
+    IAlgorithm_sptr proxy = AlgorithmManager::Instance().create("Load");
+    TS_ASSERT_EQUALS(proxy->existsProperty("Filename"), true);
+    TS_ASSERT_EQUALS(proxy->existsProperty("OutputWorkspace"), true);
+    
+    TS_ASSERT_THROWS_NOTHING(proxy->setPropertyValue("Filename","IRS38633.raw"));
+    TS_ASSERT_EQUALS(proxy->existsProperty("Cache"), true);
+    TS_ASSERT_EQUALS(proxy->existsProperty("LoadLogFiles"), true);
+
+    proxy->setPropertyValue("Filename","IRS38633.raw");
+    TS_ASSERT_EQUALS(proxy->existsProperty("Cache"), true);
+    TS_ASSERT_EQUALS(proxy->existsProperty("LoadLogFiles"), true);
+
+    TS_ASSERT_THROWS_NOTHING(proxy->setPropertyValue("Filename","LOQ49886.nxs"));   
+    TS_ASSERT_EQUALS(proxy->existsProperty("Cache"), false);
+    TS_ASSERT_EQUALS(proxy->existsProperty("LoadLogFiles"), false);
+  }
+
   void testFindLoader()
   {
     Load loader;
diff --git a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h
index 382e8dc1da2..c2df93b4f7c 100644
--- a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h
+++ b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/AlgorithmDialog.h
@@ -117,20 +117,37 @@ protected:
   /// Parse out the values entered into the dialog boxes. Use storePropertyValue()
   /// to store the <name, value> pair in the base class so that they can be retrieved later
   virtual void parseInput();
+
+  /// Save the input history of an accepted dialog
+  virtual void saveInput();
   //@}
 
   /** @name Algorithm information */
+  // InterfaceManager needs to be able to reset the algorithm as I can't pass it in use a 
+  // constructor
+  friend class InterfaceManagerImpl;
+  
+  /// Set the algorithm associated with this dialog
+  void setAlgorithm(Mantid::API::IAlgorithm*);
+  
   /// Get the algorithm pointer
   Mantid::API::IAlgorithm* getAlgorithm() const;
 
   /// Get a pointer to the named property 
   Mantid::Kernel::Property* getAlgorithmProperty(const QString & propName) const;
+  /// Return a true if the given property requires user input
+  bool requiresUserInput(const QString & propName) const;
 
+  /// Get an input value from the form, dealing with blank inputs etc
+  QString getInputValue(const QString& propName) const;
   /// Get a property validator label
   QLabel* getValidatorMarker(const QString & propname) const;
   
   /// Adds a property (name,value) pair to the stored map
   void storePropertyValue(const QString & name, const QString & value);
+
+  /// Set the properties that have been parsed from the dialog
+  bool setPropertyValues();
   //@}
 
   /** @name Dialog information */
@@ -151,7 +168,7 @@ protected:
   /** @name Helper functions */
   //@{
   ///Tie a widget to a property
-  QWidget* tie(QWidget* widget, const QString & property, QLayout* parent_layout);
+  QWidget* tie(QWidget* widget, const QString & property, QLayout* parent_layout, bool readHistory = true);
   
   /// Open a file dialog to select a file.
   QString openFileDialog(const QString & propName);
@@ -186,52 +203,29 @@ protected:
   virtual void accept();
 
   /// Help button clicked;
-  void helpClicked();
+  virtual void helpClicked();
 
   /// Replace WS
   void replaceWSClicked(QWidget *outputEdit);
 
 private:
-  // This is so that it can set the algorithm and initialize the layout.
-  // I can't pass the algorithm as an argument to the constructor as I am using
-  // the DynamicFactory
-  friend class InterfaceManagerImpl;
-  
-  /// Set the algorithm associated with this dialog
-  void setAlgorithm(Mantid::API::IAlgorithm*);
 
   /// Parse out the input from the dialog
   void parse();
-
-  /// Set the properties that have been parsed from the dialog
-  bool setPropertyValues();
-
-  /// Save the input history of an accepted dialog
-  void saveInput();
-    
   /// Set a list of suggested values  
   void setPresetValues(const QString & presetValues);
-
   /// Set comma-separated-list of enabled parameter names
   void setEnabledNames(const QString & enabledNames);
-  
   /// Test if the given name's widget should be left enabled
   bool isInEnabledList(const QString& propName) const;
-
   /// Set whether this is intended for use from a script or not
   void isForScript(bool forScript);
-
   /// Set an optional message to be displayed at the top of the dialog
   void setOptionalMessage(const QString & message);
-
-  /// This sets up the labels that are to be used to mark whether a property is valid.
-  void createValidatorLabels();
-  
   /// Retrieve a text value for a property from a widget
   QString getValue(QWidget *widget);
-
   /// Set a value based on any old input that we have
-  void setValue(QWidget *widget, const QString & property);
+  void setPreviousValue(QWidget *widget, const QString & property);
     
 private:
   /** @name Member variables. */
@@ -241,28 +235,20 @@ private:
 
   ///The name of the algorithm
   QString m_algName;
-
-  /// The properties associated with this algorithm
-  QHash<QString, Mantid::Kernel::Property*> m_algProperties;
-
+  /// The properties associated with this dialog
+  QStringList m_algProperties;
   /// A map of property <name, value> pairs that have been taken from the dialog
   QHash<QString, QString> m_propertyValueMap;
-
   /// A list pointers to PropertyWidget objects
   QHash<QString, QWidget*> m_tied_properties;
-  
   /// A boolean indicating whether this is for a script or not
   bool m_forScript;
-
   /// A list of property names that have been passed from Python
   QStringList m_python_arguments;
-
   /// A list of property names that should have their widgets enabled
   QStringList m_enabledNames;
-
   /// The message string to be displayed at the top of the widget; if it exists.
   QString m_strMessage;
-
   /// Is the message string empty or not
   bool m_msgAvailable;
 
@@ -270,7 +256,9 @@ private:
   bool m_isInitialized;
 
   /// A list of labels to use as validation markers
-  QHash<QString, QLabel*> m_validators;
+  mutable QHash<QString, QLabel*> m_validators;
+  /// A list of property names whose widgets handle their own validation
+  QStringList m_noValidation;
 
   /// Store a list of the names of input workspace boxes
   QVector<QWidget*> m_inputws_opts;
diff --git a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/MantidWidget.h b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/MantidWidget.h
index 34a73f0d121..d285a03ffc8 100644
--- a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/MantidWidget.h
+++ b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/MantidWidget.h
@@ -1,21 +1,21 @@
 #ifndef MANTIDQTAPI_MANTIDWIDGET_H_
 #define MANTIDQTAPI_MANTIDWIDGET_H_
 
+#include "DllOption.h"
 #include "MantidQtAPI/PythonRunner.h"
 #include <QWidget>
-#include "DllOption.h"
-#include <boost/shared_ptr.hpp>
+#include <QVariant>
 
-/** The ase class from which mantid custom widgets are derived it contains
-*  some useful functions
-*/
 namespace MantidQt
 {
   namespace API
   {
     /** 
-    This is the base class all customised user interfaces that do not wish to be tied
-    to a specific Mantid algorithm but rather customised for user's requirements
+    This is the base class all customised widgets that do not wish to be tied
+    to a specific Mantid algorithm but rather customised for user's requirements.
+    
+    The virtual function getUserInput() must be implemented to return what the widget considers
+    as user input.
 
     @author Martyn Gigg, Tessella Support Services plc
     @date 18/03/2009
@@ -45,8 +45,15 @@ namespace MantidQt
     Q_OBJECT
 
     public:
-      /// empty virtual destructor
-      ~MantidWidget(){}
+
+    /// Returns a QVariant containing what the widget classes as user input so that
+    /// input can be returned through a common interface.
+    virtual QVariant getUserInput() const { return QVariant(); }
+    /**
+     * Sets a value on a mantid widget through a common interface
+     * @param :: value The value as a QVariant
+     */
+    virtual void setUserInput(const QVariant & value)  { Q_UNUSED(value); }
 
     signals:
       void runAsPythonScript(const QString& code);
@@ -54,7 +61,8 @@ namespace MantidQt
     protected:
       /// Default constructor
       MantidWidget(QWidget *parent = NULL);
-      /// Run python code that is passed to it and, optionally, return anything it wrote to standard output as a string
+      /// Run python code that is passed to it and, optionally, return 
+      /// anything it wrote to standard output as a string
       QString runPythonCode(const QString & code, bool no_output = false);
 
     private:
diff --git a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/PythonRunner.h b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/PythonRunner.h
index 0a83e206edd..8dddeae1c6c 100644
--- a/Code/Mantid/MantidQt/API/inc/MantidQtAPI/PythonRunner.h
+++ b/Code/Mantid/MantidQt/API/inc/MantidQtAPI/PythonRunner.h
@@ -1,8 +1,8 @@
 #ifndef MANTIDQTAPI_PYTHONRUNNER_H_
 #define MANTIDQTAPI_PYTHONRUNNER_H_
 
-#include <QObject>
 #include "DllOption.h"
+#include <QObject>
 #include <QString>
 
 /** The ase class from which mantid custom widgets are derived it contains
diff --git a/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp b/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp
index e957d4485c8..68592535981 100644
--- a/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp
+++ b/Code/Mantid/MantidQt/API/src/AlgorithmDialog.cpp
@@ -3,8 +3,9 @@
 //----------------------------------
 #include "MantidQtAPI/AlgorithmDialog.h"
 #include "MantidQtAPI/AlgorithmInputHistory.h"
-
+#include "MantidQtAPI/MantidWidget.h"
 #include "MantidAPI/FileProperty.h"
+#include "MantidAPI/IWorkspaceProperty.h"
 
 #include <QIcon>
 #include <QLabel>
@@ -31,7 +32,7 @@ AlgorithmDialog::AlgorithmDialog(QWidget* parent) :
   QDialog(parent), m_algorithm(NULL), m_algName(""), m_algProperties(), 
   m_propertyValueMap(), m_tied_properties(), m_forScript(false), m_python_arguments(), 
   m_enabledNames(), m_strMessage(""), m_msgAvailable(false), m_isInitialized(false), 
-  m_validators(), m_inputws_opts(), m_outputws_fields(), m_wsbtn_tracker(), 
+  m_validators(), m_noValidation(), m_inputws_opts(), m_outputws_fields(), m_wsbtn_tracker(), 
   m_signal_mapper(new QSignalMapper())
 {
   connect(m_signal_mapper, SIGNAL(mapped(QWidget*)), this, SLOT(replaceWSClicked(QWidget*)));
@@ -56,9 +57,6 @@ void AlgorithmDialog::initializeLayout()
   //Set the icon
   setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png"));
   
-  // Fill the map of properties<->validator markers 
-  createValidatorLabels();
-
   // These containers are for ensuring the 'replace input workspace; button works correctly
   // Store all combo boxes that relate to an input workspace
   m_inputws_opts.clear();
@@ -101,6 +99,51 @@ void AlgorithmDialog::parseInput()
 {
 }
 
+/**
+ * Save the property values to the input history
+ */
+void AlgorithmDialog::saveInput()
+{
+  AlgorithmInputHistory::Instance().clearAlgorithmInput(m_algName);
+  QStringList::const_iterator pend = m_algProperties.end();
+  for( QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr )
+  {
+    Mantid::Kernel::Property* p = getAlgorithmProperty(*pitr);
+    if ( p->remember() )
+    {
+      QString pName = *pitr;
+      QString value = m_propertyValueMap.value(pName);
+      AlgorithmInputHistory::Instance().storeNewValue(m_algName, QPair<QString, QString>(pName, value));
+    }
+  }
+}
+
+
+/**
+ * Set the algorithm pointer
+ * @param alg :: A pointer to the algorithm
+ */
+void AlgorithmDialog::setAlgorithm(Mantid::API::IAlgorithm* alg)
+{
+  m_algorithm = alg;
+  m_algName = QString::fromStdString(alg->name());
+  m_algProperties.clear();
+  m_tied_properties.clear();
+  std::vector<Mantid::Kernel::Property*>::const_iterator iend = alg->getProperties().end();
+  for( std::vector<Mantid::Kernel::Property*>::const_iterator itr = alg->getProperties().begin(); itr != iend;
+       ++itr )
+  {
+    Mantid::Kernel::Property *p = *itr;
+    if( dynamic_cast<Mantid::API::IWorkspaceProperty*>(p) || p->direction() != Mantid::Kernel::Direction::Output )
+    {
+      m_algProperties.append(QString::fromStdString(p->name())); 
+    }
+  }
+  
+  m_validators.clear();
+  m_noValidation.clear();
+}
+
 /**
  * Get the algorithm pointer
  * @returns A pointer to the algorithm that is associated with the dialog
@@ -116,17 +159,59 @@ Mantid::API::IAlgorithm* AlgorithmDialog::getAlgorithm() const
  */
 Mantid::Kernel::Property* AlgorithmDialog::getAlgorithmProperty(const QString & propName) const
 {
-  if( m_algProperties.contains(propName) ) return m_algProperties.value(propName);
+  if( m_algProperties.contains(propName) ) 
+  {
+    return m_algorithm->getProperty(propName.toStdString());
+  }
   else return NULL;
 }
 
+/**
+ * Return a true if the given property requires user input
+ * @param propName :: The name of the property
+ */
+bool AlgorithmDialog::requiresUserInput(const QString & propName) const
+{
+  return m_algProperties.contains(propName);
+}
+
+/** 
+ * Get an input value from the form, dealing with blank inputs etc
+ * @param propName :: The name of the property
+ */
+QString AlgorithmDialog::getInputValue(const QString& propName) const
+{
+  QString value = m_propertyValueMap.value(propName);
+  if( value.isEmpty() ) 
+  {
+    Mantid::Kernel::Property* prop = getAlgorithmProperty(propName);
+    if( prop ) return QString::fromStdString(prop->getDefault());
+    else return "";
+  }
+  else return value;
+  return value;
+}
+
 /**
  * Get a property validator label
  */
 QLabel* AlgorithmDialog::getValidatorMarker(const QString & propname) const
 {
-  if( m_validators.contains(propname) ) return m_validators.value(propname);
-  return m_validators.value(propname);
+  if( m_noValidation.contains(propname) ) return NULL;
+  QLabel *validLbl(NULL);
+  if( !m_validators.contains(propname) )
+  {
+    validLbl = new QLabel("*", const_cast<AlgorithmDialog*>(this)); 
+    QPalette pal = validLbl->palette();
+    pal.setColor(QPalette::WindowText, Qt::darkRed);
+    validLbl->setPalette(pal);
+    m_validators[propname] = validLbl;
+  }
+  else
+  {
+    validLbl = m_validators.value(propname);
+  }
+  return validLbl;
 }
 
 /**
@@ -139,6 +224,41 @@ void AlgorithmDialog::storePropertyValue(const QString & name, const QString & v
   m_propertyValueMap.insert(name, value);
 }
 
+/**
+ * Set the properties that have been parsed from the dialog.
+ * @returns A boolean that indicates if the validation was successful.
+ */
+bool AlgorithmDialog::setPropertyValues()
+{
+  QStringList::const_iterator pend = m_algProperties.end();
+  bool allValid(true);
+  for( QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr )
+  {
+    const QString pName = *pitr;
+    QString value = getInputValue(pName);
+    QLabel *validator = getValidatorMarker(pName);
+    std::string error("");
+    Mantid::Kernel::Property *p = getAlgorithmProperty(pName);
+    try
+    {
+      //m_algorithm->setPropertyValue(pName.toStdString(), value.toStdString());
+      error = p->setValue(value.toStdString());
+    }
+    catch(std::exception & err_details)
+    {
+      error = err_details.what();
+      allValid = false;
+    }
+    if( validator )
+    {
+      validator->setToolTip(QString::fromStdString(error));
+      if( error.empty() ) validator->hide();
+      else validator->show();
+    }
+  }
+  return allValid;
+}
+
 /**
  * Return the message string
  * @returns the message string
@@ -197,42 +317,57 @@ bool AlgorithmDialog::isWidgetEnabled(const QString & propName) const
  * Tie together an input widget and a property
  * @param widget :: The widget that will collect the input
  * @param property :: The name of the property to tie the given widget to
- * @param An :: optional pointer to a QLayout class that is reponsible for managing the passed widget.
+ * @param parent_layout :: An optional pointer to a QLayout class that is reponsible for managing the passed widget.
  * If given, a validator label will be added for the given input widget
+ * @param readHistory :: If true then a history value will be retrieved
  * @returns A NULL pointer if a valid label was successfully add to a passed parent_layout otherwise it
  * returns a pointer to the QLabel instance marking the validity
  */
-QWidget* AlgorithmDialog::tie(QWidget* widget, const QString & property, QLayout *parent_layout)
+QWidget* AlgorithmDialog::tie(QWidget* widget, const QString & property, QLayout *parent_layout, 
+			      bool readHistory)
 {
   if( m_tied_properties.contains(property) )
   {
     m_tied_properties.remove(property);
   }
-  Mantid::Kernel::Property * prop=getAlgorithmProperty(property);
-  if(prop) 
+  Mantid::Kernel::Property * prop = getAlgorithmProperty(property);
+  if( prop ) 
   { //Set a few things on the widget
-    QString docstring = QString::fromStdString(prop->documentation());
-    widget->setToolTip(docstring);
+    widget->setToolTip(QString::fromStdString(prop->documentation()));
   }
   widget->setEnabled(isWidgetEnabled(property));
-  setValue(widget, property);
   m_tied_properties.insert(property, widget);
-  QLabel *validlbl = getValidatorMarker(property);
-  //  if( !parent_layout ) return validlbl;
-  
-  int item_index = parent_layout->indexOf(widget);
-  if( QBoxLayout *box = qobject_cast<QBoxLayout*>(parent_layout) )
+
+  // If the widget's layout has been given then assume that a validator is required, else assume not
+  QWidget* validlbl(NULL);
+  if( parent_layout )
   {
-    box->insertWidget(item_index + 1, validlbl);
+    // Check if the validator is already there
+    validlbl = getValidatorMarker(property);
+    if( validlbl )
+    {
+      int item_index = parent_layout->indexOf(widget);
+      if( QBoxLayout *box = qobject_cast<QBoxLayout*>(parent_layout) )
+      {
+	box->insertWidget(item_index + 1, validlbl);
+      }
+      else if( QGridLayout *grid = qobject_cast<QGridLayout*>(parent_layout) )
+      {
+	int row(0), col(0), span(0);
+	grid->getItemPosition(item_index, &row, &col, &span, &span);
+	grid->addWidget(validlbl, row, col + 1);
+      }
+      else {}
+    }
   }
-  else if( QGridLayout *grid = qobject_cast<QGridLayout*>(parent_layout) )
+  else
   {
-    int row(0), col(0), span(0);
-    grid->getItemPosition(item_index, &row, &col, &span, &span);
-    grid->addWidget(validlbl, row, col + 1);
+    m_noValidation.append(property);
   }
-  else 
+
+  if( readHistory )
   {
+    setPreviousValue(widget, property);
   }
 
   return validlbl;
@@ -573,23 +708,6 @@ void AlgorithmDialog::replaceWSClicked(QWidget *outputEdit)
 //------------------------------------------------------
 // Private member functions
 //------------------------------------------------------
-/**
- * Set the algorithm pointer
- * @param alg :: A pointer to the algorithm
- */
-void AlgorithmDialog::setAlgorithm(Mantid::API::IAlgorithm* alg)
-{
-  m_algorithm = alg;
-  m_algName = QString::fromStdString(alg->name());
-  m_algProperties.clear();
-  std::vector<Mantid::Kernel::Property*>::const_iterator iend = alg->getProperties().end();
-  for( std::vector<Mantid::Kernel::Property*>::const_iterator itr = alg->getProperties().begin(); itr != iend;
-       ++itr )
-  {
-    m_algProperties.insert(QString::fromStdString((*itr)->name()), *itr); 
-  }
-}
-
 /**
  * Parse out information from the dialog
  */
@@ -607,86 +725,6 @@ void AlgorithmDialog::parse()
   parseInput();
 }
 
-
-/**
- * Set the properties that have been parsed from the dialog.
- * @returns A boolean that indicates if the validation was successful.
- */
-bool AlgorithmDialog::setPropertyValues()
-{
-  QHash<QString, Mantid::Kernel::Property*>::const_iterator pend = m_algProperties.end();
-  bool allValid(true);
-  for( QHash<QString, Mantid::Kernel::Property*>::const_iterator pitr = m_algProperties.begin();
-       pitr != pend; ++pitr )
-  {
-    Mantid::Kernel::Property *prop = pitr.value();
-    QString pName = pitr.key();
-    QString value = m_propertyValueMap.value(pName);
-    QLabel *validator = getValidatorMarker(pitr.key());
-
-    std::string error = "";
-    if ( !value.isEmpty() )
-    {//if there something in the box then use it
-      try
-      {
-        error = prop->setValue(value.toStdString());
-      }
-      catch(std::exception & err_details)
-      {
-        error = err_details.what();
-      }
-    }
-    else
-    {//else use the default which may or may not be a valid property value
-      try
-      {
-        error = prop->setValue(prop->getDefault());
-      }
-      catch(std::exception& err_details)
-      {
-        error = err_details.what();
-      }
-    }
-
-    if( error.empty() )
-    {//no error
-      if( validator ) validator->hide();
-      //Store value for future input if it is not default
-    }
-    else
-    {//the property could not be set
-      allValid = false;
-      if( validator && validator->parent() )
-      {
-        //a description of the problem will be visible to users if they their mouse pointer lingers over validator star mark
-        validator->setToolTip(  QString::fromStdString(error) );
-        validator->show();
-      }
-    }
-  }
-  return allValid;
-}
-
-/**
-* Save the property values to the input history
-*/
-void AlgorithmDialog::saveInput()
-{
-  AlgorithmInputHistory::Instance().clearAlgorithmInput(m_algName);
-  QHash<QString, Mantid::Kernel::Property*>::const_iterator pend = m_algProperties.end();
-
-  for( QHash<QString, Mantid::Kernel::Property*>::const_iterator pitr = m_algProperties.begin();
-    pitr != pend; ++pitr )
-  {
-    if ( pitr.value()->remember() )
-    {
-      QString pName = pitr.key();
-      QString value = m_propertyValueMap.value(pName);
-      AlgorithmInputHistory::Instance().storeNewValue(m_algName, QPair<QString, QString>(pName, value));
-    }
-  }
-}
-
 /**
   * Set a list of values for the properties
   * @param presetValues :: A string containing a list of "name=value" pairs with each separated by an '|' character
@@ -744,27 +782,9 @@ void AlgorithmDialog::setOptionalMessage(const QString & message)
   if( message.isEmpty() ) m_msgAvailable = false;
 }
 
-/**
- * This sets up the labels that are to be used to mark whether a property is valid. It has
- * a default implmentation but can be overridden if some other marker is required
- */ 
-void AlgorithmDialog::createValidatorLabels()
-{
-  QHash<QString, Mantid::Kernel::Property*>::const_iterator pend = m_algProperties.end();
-  for( QHash<QString, Mantid::Kernel::Property*>::const_iterator pitr = m_algProperties.begin();
-       pitr != pend; ++pitr )
-  {
-    QLabel *validLbl = new QLabel("*");
-    QPalette pal = validLbl->palette();
-    pal.setColor(QPalette::WindowText, Qt::darkRed);
-    validLbl->setPalette(pal);
-    m_validators[pitr.key()] = validLbl;
-  }
-}
-
 /**
  * Get a value from a widget. The function needs to know about the types of widgets
- * that are being used. Currently it knows about QComboBox, QLineEdit and QCheckBox
+ * that are being used. Currently it knows about QComboBox, QLineEdit, QCheckBox and MWRunFiles
  * @param widget :: A pointer to the widget
  */
 QString AlgorithmDialog::getValue(QWidget *widget)
@@ -788,6 +808,10 @@ QString AlgorithmDialog::getValue(QWidget *widget)
       return QString("0");
     }
   }
+  else if( MantidWidget *mtd_widget = qobject_cast<MantidWidget*>(widget) )
+  {
+    return mtd_widget->getUserInput().toString();
+  }
   else
   {
     QMessageBox::warning(this, windowTitle(), 
@@ -803,7 +827,7 @@ QString AlgorithmDialog::getValue(QWidget *widget)
  * @param widget :: A pointer to the widget
  * @param property :: The property name
  */
-void AlgorithmDialog::setValue(QWidget *widget, const QString & propName)
+void AlgorithmDialog::setPreviousValue(QWidget *widget, const QString & propName)
 {
   // Get the value from either the previous input store or from Python argument
   QString value("");
@@ -835,23 +859,9 @@ void AlgorithmDialog::setValue(QWidget *widget, const QString & propName)
     {
       opts->setCurrentIndex(index);
     }
+    return;
   }
-  else if( QLineEdit *textfield = qobject_cast<QLineEdit*>(widget) )
-  {
-    if( !isForScript() )
-    {
-      textfield->setText(value);
-    }
-    else
-    {
-      //Need to check if this is the default value as we don't fill them in if they are
-      if( m_python_arguments.contains(propName) || !property->isDefault() )
-      {
-	textfield->setText(value);
-      }
-    }
-  }
-  else if( QCheckBox *checker = qobject_cast<QCheckBox*>(widget) )
+  if( QCheckBox *checker = qobject_cast<QCheckBox*>(widget) )
   {
     if( value.isEmpty() && dynamic_cast<Mantid::Kernel::PropertyWithValue<bool>* >(property) )
     {
@@ -865,12 +875,32 @@ void AlgorithmDialog::setValue(QWidget *widget, const QString & propName)
     {
       checker->setCheckState(Qt::Checked);
     }
-    
+    return;
   }
-  else
+
+  QLineEdit *textfield = qobject_cast<QLineEdit*>(widget);
+  MantidWidget *mtdwidget = qobject_cast<MantidWidget*>(widget);
+  if( textfield || mtdwidget )	    
   {
-    QMessageBox::warning(this, windowTitle(), 
-			 QString("Cannot set value for ") + widget->metaObject()->className() + 
-			 ". Update AlgorithmDialog::setValue() to cope with this widget.");
+    if( !isForScript() )
+    {
+      if( textfield ) textfield->setText(value);
+      else mtdwidget->setUserInput(value);
+    }
+    else
+    {
+      //Need to check if this is the default value as we don't fill them in if they are
+      if( m_python_arguments.contains(propName) || !property->isDefault() )
+      {
+	if( textfield ) textfield->setText(value);
+	else mtdwidget->setUserInput(value);
+      }
+    }
+    return;
   }
+  
+  // Reaching here means we have a widget type we don't understand. Tell the developer
+  QMessageBox::warning(this, windowTitle(), 
+		       QString("Cannot set value for ") + widget->metaObject()->className() + 
+		       ". Update AlgorithmDialog::setValue() to cope with this widget.");
 }
diff --git a/Code/Mantid/MantidQt/API/src/GenericDialog.cpp b/Code/Mantid/MantidQt/API/src/GenericDialog.cpp
index 86158db6571..fbe912f3354 100644
--- a/Code/Mantid/MantidQt/API/src/GenericDialog.cpp
+++ b/Code/Mantid/MantidQt/API/src/GenericDialog.cpp
@@ -142,11 +142,8 @@ void GenericDialog::initLayout()
       //For everything else render a text box
       else 
       {
-        
-
         QLineEdit *textBox = new QLineEdit;
         nameLbl->setBuddy(textBox);
-        
         //check this is a masked property
         Mantid::Kernel::MaskedProperty<std::string> * maskedProp = dynamic_cast<Mantid::Kernel::MaskedProperty<std::string> *>(prop);
         if(maskedProp)
@@ -155,8 +152,6 @@ void GenericDialog::initLayout()
         }
         m_editBoxes[textBox] = propName;
 
-        
-
         //Add the widgets to the grid
         m_inputGrid->addWidget(nameLbl, row, 0, 0);
         m_inputGrid->addWidget(textBox, row, 1, 0);
diff --git a/Code/Mantid/MantidQt/CustomDialogs/CMakeLists.txt b/Code/Mantid/MantidQt/CustomDialogs/CMakeLists.txt
index 3cf0d3a4eb8..ecfcd16c551 100644
--- a/Code/Mantid/MantidQt/CustomDialogs/CMakeLists.txt
+++ b/Code/Mantid/MantidQt/CustomDialogs/CMakeLists.txt
@@ -1,4 +1,5 @@
 set ( SRC_FILES src/CreateSampleShapeDialog.cpp
+                src/LoadDialog.cpp
                 src/LoadAsciiDialog.cpp
                 src/LoadDAEDialog.cpp
                 src/LoadRawDialog.cpp
@@ -10,6 +11,7 @@ set ( SRC_FILES src/CreateSampleShapeDialog.cpp
 
 # Include files aren't required, but this makes them appear in Visual Studio
 set ( INC_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.h
+                inc/MantidQtCustomDialogs/LoadDialog.h
                 inc/MantidQtCustomDialogs/LoadAsciiDialog.h
                 inc/MantidQtCustomDialogs/LoadDAEDialog.h
                 inc/MantidQtCustomDialogs/LoadRawDialog.h
@@ -20,6 +22,7 @@ set ( INC_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.h
 )
 
 set ( MOC_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.h
+                inc/MantidQtCustomDialogs/LoadDialog.h
                 inc/MantidQtCustomDialogs/LoadAsciiDialog.h
                 inc/MantidQtCustomDialogs/LoadDAEDialog.h
                 inc/MantidQtCustomDialogs/LoadRawDialog.h
@@ -36,6 +39,9 @@ set ( UI_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.ui
 )
 
 include_directories ( inc )
+include_directories ( ../MantidWidgets/inc )
+include_directories ( ${CMAKE_CURRENT_BINARY_DIR}/../MantidWidgets )
+include_directories ( ${CMAKE_CURRENT_BINARY_DIR}/../API )
 
 qt4_wrap_cpp ( MOCCED_FILES ${MOC_FILES} )
 
@@ -48,4 +54,4 @@ set_target_properties ( CustomDialogs PROPERTIES OUTPUT_NAME MantidQtCustomDialo
 # Add to the 'MantidQt' group in VS
 set_property ( TARGET CustomDialogs PROPERTY FOLDER "MantidQt" )
 
-target_link_libraries ( CustomDialogs MantidQtAPI )
\ No newline at end of file
+target_link_libraries ( CustomDialogs MantidQtAPI )
diff --git a/Code/Mantid/MantidQt/CustomDialogs/CustomDialogs.pro b/Code/Mantid/MantidQt/CustomDialogs/CustomDialogs.pro
index 8350ce05c2c..c290980b851 100644
--- a/Code/Mantid/MantidQt/CustomDialogs/CustomDialogs.pro
+++ b/Code/Mantid/MantidQt/CustomDialogs/CustomDialogs.pro
@@ -32,9 +32,9 @@ SOURCES = $$SRCDIR/LoadRawDialog.cpp \
     $$SRCDIR/MantidGLWidget.cpp \
     $$SRCDIR/PlotAsymmetryByLogValueDialog.cpp \
     $$SRCDIR/LoadDAEDialog.cpp \
-    $$SRCDIR/LoadAsciiDialog.cpp 
-    
-    
+    $$SRCDIR/LoadAsciiDialog.cpp \
+    $$SRCDIR/LoadDialog.cpp
+        
 HEADERS = $$HEADERDIR/LoadRawDialog.h \
     $$HEADERDIR/LOQScriptInputDialog.h \
     $$HEADERDIR/CreateSampleShapeDialog.h \
@@ -42,8 +42,8 @@ HEADERS = $$HEADERDIR/LoadRawDialog.h \
     $$HEADERDIR/MantidGLWidget.h \
     $$HEADERDIR/PlotAsymmetryByLogValueDialog.h \
     $$HEADERDIR/LoadDAEDialog.h \
-    $$HEADERDIR/LoadAsciiDialog.h 
-    
+    $$HEADERDIR/LoadAsciiDialog.h \
+    $$HEADERDIR/LoadDialog.h
     
 UI_DIR = $$HEADERDIR
 
diff --git a/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h
new file mode 100644
index 00000000000..d0fc453b1ea
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomDialogs/inc/MantidQtCustomDialogs/LoadDialog.h
@@ -0,0 +1,113 @@
+#ifndef MANTIDQT_CUSTOM_DIALOGS_LOADDIALOG_H
+#define MANTIDQT_CUSTOM_DIALOGS_LOADDIALOG_H
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include "MantidQtAPI/AlgorithmDialog.h"
+
+//------------------------------------------------------------------------------
+// Qt Forward declarations
+//------------------------------------------------------------------------------
+class QLineEdit;
+class QBoxLayout;
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QSignalMapper;
+
+namespace MantidQt
+{
+  //------------------------------------------------------------------------------
+  // Mantid Forward declarations
+  //------------------------------------------------------------------------------
+  namespace MantidWidgets
+  {
+    class MWRunFiles;
+  }
+
+  namespace CustomDialogs
+  {
+
+    /** 
+      This class gives specialised dialog for the Load algorithm. It requires that the specific 
+      load algorithm has at least 2 properties with these names:
+
+      <UL>
+      <LI>Filename - A text property containing the filename </LI>
+      <LI>OutputWorkspace - A text property containing the name of the OutputWorkspace </LI>
+      </UL>
+
+      There is no UI form as the most of the thing is dynamic.
+
+      @author Martyn Gigg, Tessella plc
+      @date 31/01/2011
+      
+      Copyright &copy; 2011 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+      
+      This file is part of Mantid.
+      
+      Mantid is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published by
+      the Free Software Foundation; either version 3 of the License, or
+      (at your option) any later version.
+      
+      Mantid is distributed in the hope that it will be useful,
+      but WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+      GNU General Public License for more details.
+      
+      You should have received a copy of the GNU General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+      
+      File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+      Code Documentation is available at: <http://doxygen.mantidproject.org>    
+    */
+    class LoadDialog : public API::AlgorithmDialog
+    {
+      Q_OBJECT
+      
+    public:
+      /// Default constructor
+      LoadDialog(QWidget *parent = NULL);
+
+    private:
+      /// Initialize the layout
+      void initLayout();
+      /// Save the input history
+      void saveInput();
+      /// Create the widgets and layouts that are static, i.e do not depend on 
+      /// the specific load algorithm
+      void createStaticWidgets(QBoxLayout* layout);
+      /// Tie static widgets to their properties
+      void tieStaticWidgets(const bool readHistory);
+      /// Clears all of the widgets from the old layout
+      void setupDynamicLayout();
+      /// Create the widgets for a given property
+      QBoxLayout* createWidgetsForProperty(const Mantid::Kernel::Property* prop, 
+					   QGridLayout *loaderGrid);
+
+    private slots:
+      /// Create the widgets and layouts that are dynamic, i.e they depend on 
+      /// the specific load algorithm
+      void createDynamicWidgets();
+      /// Override the help button clicked method
+      void helpClicked();
+
+    private:
+      /// A widget for the filename text input
+      MantidWidgets::MWRunFiles *m_fileWidget;
+      /// The workspace name widget
+      QLineEdit *m_wkspaceWidget;
+      /// The HBox layout for the workspace line
+      QHBoxLayout *m_wkspaceLayout;
+      /// The top-level layout
+      QVBoxLayout *m_dialogLayout;
+      /// The dynamic layout
+      QGridLayout *m_loaderLayout;
+    };
+
+  }
+}
+
+#endif //MANTIDQT_CUSTOM_DIALOGS_LOADDIALOG_H
diff --git a/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp b/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp
new file mode 100644
index 00000000000..fbabc3e9b55
--- /dev/null
+++ b/Code/Mantid/MantidQt/CustomDialogs/src/LoadDialog.cpp
@@ -0,0 +1,284 @@
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+#include "MantidQtCustomDialogs/LoadDialog.h"
+#include "MantidQtMantidWidgets/MWRunFiles.h"
+// Qt
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QUrl>
+#include <QDesktopServices>
+// Mantid
+#include "MantidKernel/Property.h"
+#include "MantidKernel/MaskedProperty.h"
+#include "MantidAPI/IWorkspaceProperty.h"
+#include "MantidAPI/FileProperty.h"
+
+namespace MantidQt
+{
+  namespace CustomDialogs
+  {
+    // Declare the dialog. Name must match the class name
+    DECLARE_DIALOG(LoadDialog);
+
+    //--------------------------------------------------------------------------
+    // Public methods
+    //---------------------------------------------------------------------------
+
+    /// Default constructor
+    LoadDialog:: LoadDialog(QWidget *parent) 
+      : API::AlgorithmDialog(parent), m_fileWidget(NULL), m_wkspaceWidget(NULL), 
+	m_wkspaceLayout(NULL), m_dialogLayout(NULL), m_loaderLayout(NULL)
+					       
+    {
+      QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+      setSizePolicy(sizePolicy);
+    }
+
+    //--------------------------------------------------------------------------
+    // Private methods (non-slot)
+    //---------------------------------------------------------------------------
+
+    /// Initialize the layout
+    void LoadDialog::initLayout()
+    {
+      m_dialogLayout = new QVBoxLayout(this);
+      createStaticWidgets(m_dialogLayout);
+      m_dialogLayout->addLayout(createDefaultButtonLayout());
+	    
+      // Now we have the static widgets in place, connect the file editing finished signal and
+      // then tie the widget so that this will trigger the dynamic form generation if
+      // there is any input history
+
+      // Connect the file finder's file found signal to the dynamic property create method.
+      // When the file text is set the Load algorithm finds the concrete loader and then we
+      // know what extra properties to create
+      connect(m_fileWidget, SIGNAL(fileEditingFinished()), this, SLOT(createDynamicWidgets()));
+      tieStaticWidgets(true);
+    }
+    
+    /**
+     * Save the input after OK is clicked
+     */
+    void LoadDialog::saveInput()
+    {
+      m_fileWidget->saveSettings("Mantid/Algorithms/Load");
+      AlgorithmDialog::saveInput();
+    }
+
+    /**
+     * Create the widgets and layouts that are static, i.e do not depend on 
+     * the specific load algorithm
+     * @param layout The layout to hold the widgets
+     */
+    void LoadDialog::createStaticWidgets(QBoxLayout *widgetLayout)
+    {
+      QVBoxLayout *staticLayout = new QVBoxLayout();
+      if( isMessageAvailable() )
+      {
+	QLabel *inputMessage = new QLabel(this);
+	inputMessage->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+	inputMessage->setText(getOptionalMessage());
+	QHBoxLayout *msgArea = new QHBoxLayout;
+	msgArea->addWidget(inputMessage);
+	staticLayout->addLayout(msgArea);
+      }
+
+      // Filename widget
+      m_fileWidget = new MantidWidgets::MWRunFiles(this);
+      m_fileWidget->setLabelText("File");
+      m_fileWidget->isForRunFiles(true);
+      m_fileWidget->allowMultipleFiles(false);
+      m_fileWidget->isOptional(false);
+      m_fileWidget->doMultiEntry(false);
+      m_fileWidget->readSettings("Mantid/Algorithms/Load");
+      QHBoxLayout *propLine = new QHBoxLayout;
+      propLine->addWidget(m_fileWidget);
+      staticLayout->addLayout(propLine);
+	
+      // Workspace property
+      m_wkspaceLayout = new QHBoxLayout;
+      m_wkspaceLayout->addWidget(new QLabel("Workspace"));
+      m_wkspaceWidget = new QLineEdit(this);
+      m_wkspaceLayout->addWidget(m_wkspaceWidget);
+      staticLayout->addLayout(m_wkspaceLayout);
+    
+      // Add to the static layout
+      widgetLayout->addLayout(staticLayout);
+    }
+
+    /**
+     * Tie static widgets to their properties
+     * @param readHistory :: If true then the history will be re read.
+     */
+    void LoadDialog::tieStaticWidgets(const bool readHistory)
+    {
+      tie(m_wkspaceWidget, "OutputWorkspace", m_wkspaceLayout, readHistory);
+      tie(m_fileWidget, "Filename", NULL, readHistory);
+    }
+
+    /**
+     * Clear the old widgets for a new Loader type
+     */
+    void LoadDialog::setupDynamicLayout()
+    {
+      // Remove the old widgets if necessary
+      if( m_loaderLayout )
+      {
+	m_dialogLayout->takeAt(1);
+	QLayoutItem *child;
+	while( (child = m_loaderLayout->takeAt(0)) != NULL ) 
+	{
+	  delete child->widget();
+	  delete child;
+	}
+	delete m_loaderLayout;
+	m_loaderLayout = NULL;
+	this->adjustSize();
+      }	
+      
+      m_loaderLayout = new QGridLayout;
+      m_dialogLayout->insertLayout(1, m_loaderLayout);
+      // Remove the old workspace validator label as it's simpler to just create another one
+      QLayoutItem *child = m_wkspaceLayout->takeAt(2);
+      if( child )
+      {
+	delete child->widget();
+	delete child;
+      } 
+    }
+    
+    /**
+     * Return a layout containing suitable widgets for the given property
+     * @param prop A pointer to the algorithm property
+     * @param loaderGrid A layout where the widgets are to be placed
+     */
+    QBoxLayout* LoadDialog::createWidgetsForProperty(const Mantid::Kernel::Property* prop,
+						     QGridLayout *loaderGrid)
+    {
+      using namespace Mantid::API;
+      using namespace Mantid::Kernel;
+      using MantidQt::MantidWidgets::MWRunFiles;
+
+      QString propName = QString::fromStdString(prop->name());
+      QWidget *inputWidget(NULL);
+      bool addValidator(true);
+      const int row = loaderGrid->rowCount();
+
+      // Boolean properties use the name labels differently
+      if( const FileProperty* fileType = dynamic_cast<const FileProperty*>(prop) )
+      {
+	MWRunFiles *fileFinder = new MWRunFiles();
+	inputWidget = fileFinder;
+	fileFinder->setLabelText(propName);
+	fileFinder->isForRunFiles(false);
+	fileFinder->isOptional(fileType->isOptional());
+	fileFinder->doMultiEntry(false);
+	// Ensure this spans the whole width of the grid
+	loaderGrid->addWidget(inputWidget, row, 0, 1, 3);
+	addValidator = false;
+      }
+      else
+      {
+	QLabel *nameLbl = new QLabel(propName);
+	nameLbl->setToolTip(QString::fromStdString(prop->documentation()));
+	if( dynamic_cast<const PropertyWithValue<bool>* >(prop) )
+	{
+	  QCheckBox *checkBox = new QCheckBox();
+	  inputWidget = checkBox;
+	  addValidator = false;
+	} 
+	// Options box
+	else if( !prop->allowedValues().empty() )
+	{
+	  QComboBox *optionsBox = new QComboBox();
+	  inputWidget = optionsBox;
+	  std::set<std::string> items = prop->allowedValues();
+	  std::set<std::string>::const_iterator vend = items.end();
+	  for(std::set<std::string>::const_iterator vitr = items.begin(); vitr != vend; 
+	      ++vitr)
+	  {
+	    optionsBox->addItem(QString::fromStdString(*vitr));
+	  }
+	  addValidator = false;
+	}
+	// else render a text box
+	else
+	{
+	  QLineEdit *textBox = new QLineEdit();
+	  inputWidget = textBox;
+	  if( dynamic_cast<const MaskedProperty<std::string> *>(prop) )
+	  {
+	    textBox->setEchoMode(QLineEdit::Password);
+	  }
+	}
+	nameLbl->setBuddy(inputWidget);	
+	loaderGrid->addWidget(nameLbl, row, 0);
+	loaderGrid->addWidget(inputWidget, row, 1);
+      }
+
+      if( addValidator ) tie(inputWidget, propName, loaderGrid);
+      else tie(inputWidget, propName, NULL);
+
+      return NULL;
+    }
+
+    //--------------------------------------------------------------------------
+    // Private methods (slot)
+    //---------------------------------------------------------------------------
+
+    /**
+     * Create the widgets and layouts that are dynamic
+     */
+    void LoadDialog::createDynamicWidgets()
+    {
+      using namespace Mantid::API;
+      using namespace Mantid::Kernel;
+
+      if( !m_fileWidget->isValid() ) return;
+      // First step is the get the specific loader that is reponsible
+      IAlgorithm *loadAlg = getAlgorithm();
+      const std::string filename = m_fileWidget->getFirstFilename().toStdString();
+      if( filename.empty() ) return;
+      try
+      {
+	loadAlg->setPropertyValue("Filename", filename);
+      }
+      catch(std::exception & exc)
+      {
+	m_fileWidget->setFileProblem(QString::fromStdString(exc.what()));
+	return;
+      }
+      // Reset the algorithm pointer so that the base class re-reads the properties and drops links from
+      // old widgets meaning they are safe to remove
+      this->setAlgorithm(loadAlg);
+
+      setupDynamicLayout();
+      tieStaticWidgets(false);
+      const std::vector<Property*> & inputProps = loadAlg->getProperties();
+      for( size_t i = 0; i < inputProps.size(); ++i )
+      {
+	const Property* prop = inputProps[i];
+	const QString propName = QString::fromStdString(prop->name());
+	if( propName == "OutputWorkspace" || propName == "Filename" ) continue;
+	if( requiresUserInput(propName) )
+	{
+	  createWidgetsForProperty(prop, m_loaderLayout);
+	}
+      }
+
+      // Attempt to set any values that may have been retrieved
+      setPropertyValues();
+    }
+
+    /// Override the help button clicked method
+    void LoadDialog::helpClicked()
+    {
+      const std::string & loaderName = getAlgorithm()->getPropertyValue("LoaderName");
+      QString helpPage = (loaderName.empty()) ? QString("Load") : QString::fromStdString(loaderName);
+      QDesktopServices::openUrl(QUrl(QString("http://www.mantidproject.org/") + helpPage));
+    }
+      
+  }
+}
diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWDiag.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWDiag.h
index ec58db6a8ad..323ef947345 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWDiag.h
+++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWDiag.h
@@ -7,6 +7,7 @@
 #include <QSettings>
 #include <QStringList>
 #include <QComboBox>
+#include <boost/shared_ptr.hpp>
 
 //-----------------------------------------------
 // Forward declarations
diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h
index f4434128235..1c56c2a1f7f 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h
+++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.h
@@ -53,11 +53,11 @@ namespace MantidQt
       Q_PROPERTY(QStringList fileExtensions READ getFileExtensions WRITE setFileExtensions)
 
     public:
-      /// Flags for workspace entries
-      enum
-      {
-        NO_ENTRY_NUM = -1,                       ///< error in the entry number setting
-        ALL_ENTRIES = -2                         ///< use all entries (i.e. entry number was left blank)
+      /// Flags for workspace entries
+      enum
+      {
+        NO_ENTRY_NUM = -1,                       ///< error in the entry number setting
+        ALL_ENTRIES = -2                         ///< use all entries (i.e. entry number was left blank)
       };
 
       ///Default constructor
@@ -83,7 +83,12 @@ namespace MantidQt
       QStringList getFilenames() const;
       QString getFirstFilename() const;
       int getEntryNum() const;
-
+      /// Overridden from base class to retrieve user input through a common interface
+      QVariant getUserInput() const;      
+      /// Sets a value on the widget through a common interface
+      void setUserInput(const QVariant & value);
+      /// flag a problem with the file the user entered, an empty string means no error
+      void setFileProblem(const QString & message);
       /// Read settings from the given group
       void readSettings(const QString & group);
       /// Save settings in the given group
@@ -108,12 +113,10 @@ namespace MantidQt
       QStringList getFileExtensionsFromAlgorithm(const QString & algName, const QString &propName);
       /// Open a file dialog
       QString openFileDia();
-      /// flag a problem with the file the user entered, an empty string means no error
-      void setFileProblem(const QString & message);
       /// flag a problem with the supplied entry number, an empty string means no error
       void setEntryNumProblem(const QString & message);
       /// displays the validator red star if either m_fileProblem or m_entryNumProblem are not empty
-      void refreshvalidator();
+      void refreshValidator();
 
     private slots:
       /// Browse clicked slot
diff --git a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.ui b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.ui
index 5ac5e82d236..9a37da8e458 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.ui
+++ b/Code/Mantid/MantidQt/MantidWidgets/inc/MantidQtMantidWidgets/MWRunFiles.ui
@@ -1,69 +1,73 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>MWRunFiles</class>
- <widget class="QWidget" name="MWRunFiles" >
-  <property name="geometry" >
+ <widget class="QWidget" name="MWRunFiles">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>231</width>
+    <width>238</width>
     <height>41</height>
    </rect>
   </property>
-  <property name="sizePolicy" >
-   <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
     <horstretch>0</horstretch>
-    <verstretch>41</verstretch>
+    <verstretch>0</verstretch>
    </sizepolicy>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout" >
-   <property name="verticalSpacing" >
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="sizeConstraint">
+    <enum>QLayout::SetFixedSize</enum>
+   </property>
+   <property name="verticalSpacing">
     <number>0</number>
    </property>
-   <property name="margin" >
+   <property name="margin">
     <number>0</number>
    </property>
-   <item row="0" column="1" >
-    <widget class="QLineEdit" name="fileEditor" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="fileEditor">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
        <horstretch>0</horstretch>
        <verstretch>20</verstretch>
       </sizepolicy>
      </property>
     </widget>
    </item>
-   <item row="0" column="5" >
-    <widget class="QPushButton" name="browseBtn" >
-     <property name="text" >
+   <item row="0" column="5">
+    <widget class="QPushButton" name="browseBtn">
+     <property name="text">
       <string>Browse</string>
      </property>
     </widget>
    </item>
-   <item row="0" column="0" >
-    <widget class="QLabel" name="textLabel" >
-     <property name="text" >
+   <item row="0" column="0">
+    <widget class="QLabel" name="textLabel">
+     <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
-   <item row="0" column="3" >
-    <widget class="QLineEdit" name="entryNum" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Maximum" >
+   <item row="0" column="3">
+    <widget class="QLineEdit" name="entryNum">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
        <horstretch>40</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="minimumSize" >
+     <property name="minimumSize">
       <size>
        <width>30</width>
        <height>0</height>
       </size>
      </property>
-     <property name="maximumSize" >
+     <property name="maximumSize">
       <size>
        <width>20</width>
        <height>16777215</height>
@@ -71,20 +75,20 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="4" >
-    <widget class="QLabel" name="valid" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+   <item row="0" column="4">
+    <widget class="QLabel" name="valid">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
        <horstretch>20</horstretch>
        <verstretch>20</verstretch>
       </sizepolicy>
      </property>
-     <property name="palette" >
+     <property name="palette">
       <palette>
        <active>
-        <colorrole role="WindowText" >
-         <brush brushstyle="SolidPattern" >
-          <color alpha="255" >
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
            <red>170</red>
            <green>0</green>
            <blue>0</blue>
@@ -93,9 +97,9 @@
         </colorrole>
        </active>
        <inactive>
-        <colorrole role="WindowText" >
-         <brush brushstyle="SolidPattern" >
-          <color alpha="255" >
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
            <red>170</red>
            <green>0</green>
            <blue>0</blue>
@@ -104,9 +108,9 @@
         </colorrole>
        </inactive>
        <disabled>
-        <colorrole role="WindowText" >
-         <brush brushstyle="SolidPattern" >
-          <color alpha="255" >
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
            <red>118</red>
            <green>116</green>
            <blue>108</blue>
@@ -116,7 +120,7 @@
        </disabled>
       </palette>
      </property>
-     <property name="text" >
+     <property name="text">
       <string>*</string>
      </property>
     </widget>
diff --git a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp
index 2fe1f02722b..c5dcfa26523 100644
--- a/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp
+++ b/Code/Mantid/MantidQt/MantidWidgets/src/MWRunFiles.cpp
@@ -26,10 +26,10 @@ MWRunFiles::MWRunFiles(QWidget *parent) : MantidWidget(parent),
   m_uiForm.setupUi(this);
 
   connect(m_uiForm.fileEditor, SIGNAL(textChanged(const QString &)), this, SIGNAL(fileTextChanged(const QString&)));
-  connect(m_uiForm.fileEditor, SIGNAL(editingFinished()), this, SLOT(findFiles()));
-  connect(m_uiForm.fileEditor, SIGNAL(editingFinished()), this, SIGNAL(fileEditingFinished()));
   connect(m_uiForm.browseBtn, SIGNAL(clicked()), this, SLOT(browseClicked()));
 
+  connect(m_uiForm.fileEditor, SIGNAL(editingFinished()), this, SIGNAL(fileEditingFinished()));
+  connect(this, SIGNAL(fileEditingFinished()), this, SLOT(findFiles()));
   connect(m_uiForm.entryNum, SIGNAL(textChanged(const QString &)), this, SLOT(checkEntry()));
   connect(m_uiForm.entryNum, SIGNAL(editingFinished()), this, SLOT(checkEntry()));
 
@@ -141,7 +141,7 @@ void MWRunFiles::doMultiEntry(const bool multiEntry)
   {
     m_uiForm.entryNum->hide();
   }
-  refreshvalidator();
+  refreshValidator();
 }
 
 /**
@@ -238,6 +238,39 @@ int MWRunFiles::getEntryNum() const
   return NO_ENTRY_NUM;
 }
 
+/**
+ * Retrieve user input from this widget. NOTE: This knows nothing of periods yet
+ * @returns A qvariant
+ */
+QVariant MWRunFiles::getUserInput() const
+{
+  return QVariant(m_uiForm.fileEditor->text());
+}
+
+/**
+ * Sets a value on the widget through a common interface. The 
+ * QVariant is assumed to be text and to contain a file string. Note that this
+ * is primarily here for use within the AlgorithmDialog
+ * @param value A QVariant containing user text
+ */
+void MWRunFiles::setUserInput(const QVariant & value)
+{
+  m_uiForm.fileEditor->setText(value.toString());
+  emit fileEditingFinished();
+}
+
+/**
+ * Flag a problem with the file the user entered, an empty string means no error but
+ * there may be an error with the entry box if enabled. Errors passed here are shown first
+ * @param A message to include or "" for no error
+ */
+void MWRunFiles::setFileProblem(const QString & message)
+{
+  m_fileProblem = message;
+  refreshValidator();
+}
+
+
 /**
 * Save settings to the given group
 * @param group :: The name of the group key to save to
@@ -484,16 +517,6 @@ QString MWRunFiles::openFileDia()
   return filenames.join(", ");
 }
 
-/**
-* Flag a problem with the file the user entered, an empty string means no error but
-* there may be an error with the entry box if enabled. Errors passed here are shown first
-* @param A message to include or "" for no error
-*/
-void MWRunFiles::setFileProblem(const QString & message)
-{
-  m_fileProblem = message;
-  refreshvalidator();
-}
 
 /** flag a problem with the supplied entry number, an empty string means no error.
 *  file errors take precedence of these errors
@@ -502,13 +525,13 @@ void MWRunFiles::setFileProblem(const QString & message)
 void MWRunFiles::setEntryNumProblem(const QString & message)
 {
   m_entryNumProblem = message;
-  refreshvalidator();
+  refreshValidator();
 }
 
 /** Checks the data m_fileProblem and m_entryNumProblem to see if the validator label
 *  needs to be displayed
 */
-void MWRunFiles::refreshvalidator()
+void MWRunFiles::refreshValidator()
 {
   if ( ! m_fileProblem.isEmpty() )
   {
@@ -548,7 +571,6 @@ void MWRunFiles::browseClicked()
   {
     m_uiForm.fileEditor->setText(uFile);
   }
-  findFiles();
   emit fileEditingFinished();
 }
 /** Currently just checks that entryNum contains an int > 0 and hence might be a
-- 
GitLab