diff --git a/docs/source/interfaces/Engineering Diffraction.rst b/docs/source/interfaces/Engineering Diffraction.rst
index a3d34483279ef69db96d061e3e0f5ae5be09ebe7..ebd3ef8a4450eb61320f84bd5a74823252543b97 100644
--- a/docs/source/interfaces/Engineering Diffraction.rst	
+++ b/docs/source/interfaces/Engineering Diffraction.rst	
@@ -335,24 +335,24 @@ Fitting
 .. warning:: The input workspace must be converted into a focused file
 			 first. The steps to complete this are found here: :ref:`focus-Engineering_Diffraction-ref`
 
-The Fitting tab provides a graphical interface which fits an expected
-diffraction pattern and visualises them. The pattern is specified by
-providing a list of dSpacing values where Bragg peaks are expected.
+The Fitting tab provides a graphical interface which fits and
+visualises an expected diffraction pattern. The pattern is specified
+by providing a list of dSpacing values where Bragg peaks are expected.
 The algorithm :ref:`EnggFitPeaks<algm-EnggFitPeaks>` is used to
 background fit peaks in those areas using a peak fitting function.
 
 To use the Fitting tab, user is required to follow these steps:
 
-1. A focused file as Focus Run input by browsing or entering single/multi
-   run number, *User may click Load button to load the focused file to the
+1. Load run(s) to perform fitting on by browsing for focused nexus
+   files *User may click Load button to load the focused file to the
    canvas*
 2. List of expected peaks which can be either by browsing a (*CSV*) file,
    manually selecting peaks from the canvas using peak picker tool after
    loading the focused file or by entering the peaks list within the text-field
 3. Next click on the *Fit* button if you would like to fit single focused
    file or you can click *Fit All* button which will enable user to
-   batch-process all the runs and banks when a range of run number is given,
-   *Fit All* process may also be used when when a single run number is given
+   batch-process all the runs and banks when several files are loaded.
+   *Fit All* process may also be used when a single run number is given
    or a file is browsed
 
 .. _ExpectedPeaks-Engineering_Diffraction-ref:
@@ -362,44 +362,25 @@ Parameters
 
 These parameters are required to process Fitting successfully:
 
-Focused Run #:
-  Focused workspace directory or selected using the browse button.
-  Users may also select the file/s by simply entering the file run number
-  or a range of consecutive run number separated by dash (`-`), for
-  example: "194547-194550" or "241391-241399". 
-  
-  It is  compulsory for these file/s to be located within the focused output directory.
-  Focused workspace can be generated with the help of
-  :ref:`focus-Engineering_Diffraction-ref` tab, the output folder
-  directory can be set in the :ref:`setting-Engineering_Diffraction-ref`
-  tab under the *Focusing settings* section.
-  
-  When a valid range of consecutive run numbers is given, the interface will
-  automatically import and add the run number/s to the list on the right side
-  of the graph, from where each run number can be selected from by click on it.
-  The interface will then automatically update the Plot Bank combo-box
-  according to the bank files found for each entered/selected run-number.
+Focused Run files:
+  .nxs files containing focused diffraction data. These should be the result
+  of focusing data with the :ref:`focus-Engineering_Diffraction-ref` tab.
 
 Peaks:
   A list of dSpacing values to be translated into TOF to find expected
   peaks. These peaks can be manually written or imported by selecting a
   (*CSV*) file.
 
-Plot Bank/Bank List:
-  These GUI widgets will only be enabled when multiple focused bank
-  files are found within the working directory or focused output directory.
-  This would enable user to select the desired bank which they would like to
-  plot with the help of Plot Bank combo-box or Bank List.
 
 Output
 ^^^^^^
 
 Once the Fit button has been clicked Mantid will process the data. Please wait
 until the Fitting process has completed. Upon completion you should be able to
-view on the Fitting tab which will contain:
+view the Fitting tab which will contain:
 
 - The focused workspace plotted in the background in gray crosses.
-- The expected peaks plotted in various colours over lapping the
+- The expected peaks plotted in various colours overlapping the
   focused workspace peaks.
 
 Within the :ref:`Preview-Engineering_Diffraction-ref` section a user is
diff --git a/docs/source/release/v3.12.0/diffraction.rst b/docs/source/release/v3.12.0/diffraction.rst
index 4780fb6604e94559fb886774c44a522d68fe770a..024f0496cdc5a37455361c86839fc7ae49df4653 100644
--- a/docs/source/release/v3.12.0/diffraction.rst
+++ b/docs/source/release/v3.12.0/diffraction.rst
@@ -33,9 +33,10 @@ Engineering Diffraction
   latest version of GSAS-II, allowing Rietveld and Pawley refinement
   within Mantid.
 - Usability improvements in the GUI:
-  - The "Invalid RB number" popup window in the GUI has been replaced with a more user-friendly message
-  - Improved progress reporting for Calibration and Focus
-
+  + The "Invalid RB number" popup window in the GUI has been replaced with a more user-friendly message
+  + Improved progress reporting for Calibration and Focus
+  + Enabled multi-run fitting and plotting in the Fitting tab
+     
 Single Crystal Diffraction
 --------------------------
 - :ref:`FilterPeaks <algm-FilterPeaks>` now supports filtering peaks by TOF, d-spacing, and wavelength.
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.cpp b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.cpp
index 80927dd5a03df8b1ab38b0055aff33c21d591fac..0120f9b14f2a63dd968424523328156969c204d3 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.cpp
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.cpp
@@ -150,7 +150,6 @@ void EnggDiffFittingModel::createFittedPeaksWS(const int runNumber,
   const auto focusedWS = getFocusedWorkspace(runNumber, bank);
 
   const size_t numberOfPeaks = fitFunctionParams->rowCount();
-  const std::string fittedPeaksWSName = "engggui_fitting_single_peaks";
 
   for (size_t i = 0; i < numberOfPeaks; ++i) {
     const auto functionDescription = createFunctionString(fitFunctionParams, i);
@@ -169,26 +168,28 @@ void EnggDiffFittingModel::createFittedPeaksWS(const int runNumber,
                             singlePeakWSName);
 
     if (i == 0) {
-      cloneWorkspace(focusedWS, fittedPeaksWSName);
-      setDataToClonedWS(singlePeakWSName, fittedPeaksWSName);
+      cloneWorkspace(focusedWS, FITTED_PEAKS_WS_NAME);
+      setDataToClonedWS(singlePeakWSName, FITTED_PEAKS_WS_NAME);
     } else {
       const std::string clonedWSName =
           "__engggui_cloned_peaks_" + std::to_string(i);
       cloneWorkspace(focusedWS, clonedWSName);
       setDataToClonedWS(singlePeakWSName, clonedWSName);
 
-      appendSpectra(fittedPeaksWSName, clonedWSName);
+      appendSpectra(FITTED_PEAKS_WS_NAME, clonedWSName);
     }
   }
 
   const std::string alignedWSName = FOCUSED_WS_NAME + "_d";
-  alignDetectors(getFocusedWorkspace(runNumber, bank), alignedWSName);
-  alignDetectors(fittedPeaksWSName, fittedPeaksWSName);
+  cloneWorkspace(focusedWS, alignedWSName);
+  alignDetectors(alignedWSName, alignedWSName);
+
+  alignDetectors(FITTED_PEAKS_WS_NAME, FITTED_PEAKS_WS_NAME);
 
   const auto &ADS = Mantid::API::AnalysisDataService::Instance();
 
   const auto fittedPeaksWS =
-      ADS.retrieveWS<Mantid::API::MatrixWorkspace>(fittedPeaksWSName);
+      ADS.retrieveWS<Mantid::API::MatrixWorkspace>(FITTED_PEAKS_WS_NAME);
   addToRunMap(runNumber, bank, m_fittedPeaksMap, fittedPeaksWS);
 
   const auto alignedFocusedWS =
@@ -196,6 +197,21 @@ void EnggDiffFittingModel::createFittedPeaksWS(const int runNumber,
   addToRunMap(runNumber, bank, m_alignedWorkspaceMap, alignedFocusedWS);
 }
 
+size_t EnggDiffFittingModel::getNumFocusedWorkspaces() const {
+  size_t numWorkspaces = 0;
+
+  for (const auto &bank : m_focusedWorkspaceMap) {
+    numWorkspaces += bank.size();
+  }
+  return numWorkspaces;
+}
+
+bool EnggDiffFittingModel::hasFittedPeaksForRun(const int runNumber,
+                                                const size_t bank) const {
+  return m_fittedPeaksMap[bank - 1].find(runNumber) !=
+         m_fittedPeaksMap[bank - 1].end();
+}
+
 Mantid::API::MatrixWorkspace_sptr
 EnggDiffFittingModel::getAlignedWorkspace(const int runNumber,
                                           const size_t bank) const {
@@ -255,7 +271,7 @@ void EnggDiffFittingModel::rebinToFocusedWorkspace(
 
 void EnggDiffFittingModel::cloneWorkspace(
     const Mantid::API::MatrixWorkspace_sptr inputWorkspace,
-    const std::string &outputWSName) {
+    const std::string &outputWSName) const {
   auto cloneWSAlg =
       Mantid::API::AlgorithmManager::Instance().create("CloneWorkspace");
   cloneWSAlg->initialize();
@@ -275,7 +291,7 @@ void EnggDiffFittingModel::setDataToClonedWS(const std::string &wsToCopyName,
 }
 
 void EnggDiffFittingModel::appendSpectra(const std::string &ws1Name,
-                                         const std::string &ws2Name) {
+                                         const std::string &ws2Name) const {
   auto appendSpectraAlg =
       Mantid::API::AlgorithmManager::Instance().create("AppendSpectra");
 
@@ -363,8 +379,8 @@ void EnggDiffFittingModel::loadWorkspace(const std::string &filename,
   loadAlg->execute();
 }
 
-void EnggDiffFittingModel::renameWorkspace(API::MatrixWorkspace_sptr inputWS,
-                                           const std::string &newName) {
+void EnggDiffFittingModel::renameWorkspace(API::Workspace_sptr inputWS,
+                                           const std::string &newName) const {
   auto renameAlg = API::AlgorithmManager::Instance().create("RenameWorkspace");
   renameAlg->setProperty("InputWorkspace", inputWS);
   renameAlg->setProperty("OutputWorkspace", newName);
@@ -402,6 +418,64 @@ std::vector<int> EnggDiffFittingModel::getAllRunNumbers() const {
   return runNumbers;
 }
 
+void EnggDiffFittingModel::mergeTables(
+    const API::ITableWorkspace_sptr tableToCopy,
+    API::ITableWorkspace_sptr targetTable) const {
+  for (size_t i = 0; i < tableToCopy->rowCount(); ++i) {
+    API::TableRow rowToCopy = tableToCopy->getRow(i);
+    API::TableRow newRow = targetTable->appendRow();
+
+    for (size_t j = 0; j < tableToCopy->columnCount(); ++j) {
+      double valueToCopy;
+      rowToCopy >> valueToCopy;
+      newRow << valueToCopy;
+    }
+  }
+}
+
+void EnggDiffFittingModel::addAllFitResultsToADS() const {
+  auto fitParamsTable = Mantid::API::WorkspaceFactory::Instance().createTable();
+  renameWorkspace(fitParamsTable, FIT_RESULTS_TABLE_NAME);
+
+  const auto runNumberBankPairs = getRunNumbersAndBankIDs();
+
+  for (const auto &runNumberBankPair : runNumberBankPairs) {
+    const int runNumber = runNumberBankPair.first;
+    const size_t bank = runNumberBankPair.second;
+
+    const auto singleWSFitResults = getFitResults(runNumber, bank);
+
+    if (runNumberBankPair == *runNumberBankPairs.begin()) {
+      // First element - copy column headings over
+      const auto columnHeaders = singleWSFitResults->getColumnNames();
+      for (const auto &header : columnHeaders) {
+        fitParamsTable->addColumn("double", header);
+      }
+    }
+    mergeTables(singleWSFitResults, fitParamsTable);
+  }
+}
+
+void EnggDiffFittingModel::addAllFittedPeaksToADS() const {
+  const auto runNumberBankPairs = getRunNumbersAndBankIDs();
+  if (runNumberBankPairs.size() < 1) {
+    return;
+  }
+  const auto firstWSLabel = runNumberBankPairs[0];
+  auto fittedPeaksWS =
+      getFittedPeaksWS(firstWSLabel.first, firstWSLabel.second);
+  cloneWorkspace(fittedPeaksWS, FITTED_PEAKS_WS_NAME);
+
+  for (size_t i = 1; i < runNumberBankPairs.size(); ++i) {
+    const auto wsLabel = runNumberBankPairs[i];
+    const int runNumber = wsLabel.first;
+    const size_t bank = wsLabel.second;
+
+    auto wsToAppend = getFittedPeaksWS(runNumber, bank);
+    appendSpectra(FITTED_PEAKS_WS_NAME, wsToAppend->getName());
+  }
+}
+
 namespace {
 
 std::string stripWSNameFromFilename(const std::string &fullyQualifiedFilename) {
@@ -537,6 +611,8 @@ const std::string EnggDiffFittingModel::FOCUSED_WS_NAME =
     "engggui_fitting_focused_ws";
 const std::string EnggDiffFittingModel::FIT_RESULTS_TABLE_NAME =
     "engggui_fitting_fitpeaks_params";
+const std::string EnggDiffFittingModel::FITTED_PEAKS_WS_NAME =
+    "engggui_fitting_single_peaks";
 
 const double EnggDiffFittingModel::DEFAULT_DIFA = 0.0;
 const double EnggDiffFittingModel::DEFAULT_DIFC = 18400.0;
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.h b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.h
index f5366fa79eb90a1004703211d83c0655cab9a507..da71e2494d5ddbb6fecb80c167f66f381927de9e 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.h
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingModel.h
@@ -49,6 +49,15 @@ public:
 
   void createFittedPeaksWS(const int runNumber, const size_t bank) override;
 
+  size_t getNumFocusedWorkspaces() const override;
+
+  void addAllFitResultsToADS() const override;
+
+  void addAllFittedPeaksToADS() const override;
+
+  bool hasFittedPeaksForRun(const int runNumber,
+                            const size_t bank) const override;
+
 protected:
   void addFocusedWorkspace(const int runNumber, const size_t bank,
                            const Mantid::API::MatrixWorkspace_sptr ws,
@@ -57,6 +66,9 @@ protected:
   void addFitResults(const int runNumber, const size_t bank,
                      const Mantid::API::ITableWorkspace_sptr ws);
 
+  void mergeTables(const Mantid::API::ITableWorkspace_sptr tableToCopy,
+                   Mantid::API::ITableWorkspace_sptr targetTable) const;
+
 private:
   static const size_t MAX_BANKS = 2;
   static const double DEFAULT_DIFC;
@@ -64,6 +76,7 @@ private:
   static const double DEFAULT_TZERO;
   static const std::string FOCUSED_WS_NAME;
   static const std::string FIT_RESULTS_TABLE_NAME;
+  static const std::string FITTED_PEAKS_WS_NAME;
 
   RunMap<MAX_BANKS, Mantid::API::MatrixWorkspace_sptr> m_focusedWorkspaceMap;
   RunMap<MAX_BANKS, std::string> m_wsFilenameMap;
@@ -96,12 +109,13 @@ private:
                                const std::string &outputWSName);
 
   void cloneWorkspace(const Mantid::API::MatrixWorkspace_sptr inputWorkspace,
-                      const std::string &outputWSName);
+                      const std::string &outputWSName) const;
 
   void setDataToClonedWS(const std::string &wsToCopyName,
                          const std::string &targetWSName);
 
-  void appendSpectra(const std::string &ws1Name, const std::string &ws2Name);
+  void appendSpectra(const std::string &ws1Name,
+                     const std::string &ws2Name) const;
 
   std::tuple<double, double, double>
   getDifcDifaTzero(Mantid::API::MatrixWorkspace_const_sptr ws);
@@ -119,8 +133,8 @@ private:
 
   void loadWorkspace(const std::string &filename, const std::string &wsName);
 
-  void renameWorkspace(Mantid::API::MatrixWorkspace_sptr inputWS,
-                       const std::string &newName);
+  void renameWorkspace(Mantid::API::Workspace_sptr inputWS,
+                       const std::string &newName) const;
 
   void groupWorkspaces(const std::vector<std::string> &workspaceNames,
                        const std::string &outputWSName);
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresWorker.h b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresWorker.h
index 743a3bdacc548f44da0146b013e72eeda28aadbc..7159b3b7a8ab96094ed8fcb77be2881dfdc26091 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresWorker.h
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresWorker.h
@@ -41,16 +41,22 @@ class EnggDiffFittingWorker : public QObject {
 
 public:
   // for fitting (single peak fits)
-  EnggDiffFittingWorker(EnggDiffFittingPresenter *pres, const int runNumber,
-                        const size_t bank, const std::string &ExpectedPeaks)
-      : m_pres(pres), m_runNumber(runNumber), m_bank(bank),
-        m_expectedPeaks(ExpectedPeaks) {}
+  EnggDiffFittingWorker(
+      EnggDiffFittingPresenter *pres,
+      const std::vector<std::pair<int, size_t>> &runNumberBankPairs,
+      const std::string &expectedPeaks)
+      : m_pres(pres), m_runNumberBankPairs(runNumberBankPairs),
+        m_expectedPeaks(expectedPeaks) {}
 
 private slots:
 
   void fitting() {
     try {
-      m_pres->doFitting(m_runNumber, m_bank, m_expectedPeaks);
+      for (const auto &runNumberBankPair : m_runNumberBankPairs) {
+        const int runNumber = runNumberBankPair.first;
+        const size_t bank = runNumberBankPair.second;
+        m_pres->doFitting(runNumber, bank, m_expectedPeaks);
+      }
     } catch (std::exception &ex) {
       Mantid::Kernel::Logger log("EngineeringDiffractionFitting");
       log.error(ex.what());
@@ -65,8 +71,7 @@ private:
   EnggDiffFittingPresenter *m_pres;
 
   /// sample run to process
-  const int m_runNumber;
-  const size_t m_bank;
+  const std::vector<std::pair<int, size_t>> m_runNumberBankPairs;
   // parameters for fitting, list of peaks
   const std::string m_expectedPeaks;
 };
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.cpp b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.cpp
index 4a90eab4eaa92e0b50f39e999f0f60ce81e6fc98..58f440e8060f1725eda1af331a32432c16db39f6 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.cpp
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.cpp
@@ -1,11 +1,11 @@
 #include "EnggDiffFittingPresenter.h"
+#include "EnggDiffFittingPresWorker.h"
+#include "IEnggDiffFittingModel.h"
 #include "MantidAPI/Axis.h"
 #include "MantidAPI/MatrixWorkspace.h"
 #include "MantidAPI/Run.h"
 #include "MantidAPI/WorkspaceFactory.h"
 #include "MantidQtWidgets/LegacyQwt/QwtHelper.h"
-#include "IEnggDiffFittingModel.h"
-#include "EnggDiffFittingPresWorker.h"
 
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
@@ -85,8 +85,6 @@ std::string generateXAxisLabel(Mantid::Kernel::Unit_const_sptr unit) {
 }
 }
 
-int EnggDiffFittingPresenter::g_fitting_runno_counter = 0;
-
 /**
  * Constructs a presenter for a fitting tab/widget view, which has a
  * handle on the current calibration (produced and updated elsewhere).
@@ -102,7 +100,8 @@ EnggDiffFittingPresenter::EnggDiffFittingPresenter(
     boost::shared_ptr<IEnggDiffractionParam> mainParam)
     : m_fittingFinishedOK(false), m_workerThread(nullptr),
       m_mainCalib(mainCalib), m_mainParam(mainParam), m_view(view),
-      m_model(std::move(model)), m_viewHasClosed(false) {}
+      m_model(std::move(model)), m_viewHasClosed(false), m_multiRunMode(false) {
+}
 
 EnggDiffFittingPresenter::~EnggDiffFittingPresenter() { cleanup(); }
 
@@ -143,10 +142,6 @@ void EnggDiffFittingPresenter::notify(
     processStart();
     break;
 
-  case IEnggDiffFittingPresenter::FittingRunNo:
-    fittingRunNoChanged();
-    break;
-
   case IEnggDiffFittingPresenter::Load:
     processLoad();
     break;
@@ -196,12 +191,13 @@ EnggDiffFittingPresenter::outFilesUserDir(const std::string &addToDir) {
 }
 
 void EnggDiffFittingPresenter::startAsyncFittingWorker(
-    const int runNumber, const size_t bank, const std::string &expectedPeaks) {
+    const std::vector<std::pair<int, size_t>> &runNumberBankPairs,
+    const std::string &expectedPeaks) {
 
   delete m_workerThread;
   m_workerThread = new QThread(this);
   EnggDiffFittingWorker *worker =
-      new EnggDiffFittingWorker(this, runNumber, bank, expectedPeaks);
+      new EnggDiffFittingWorker(this, runNumberBankPairs, expectedPeaks);
   worker->moveToThread(m_workerThread);
 
   connect(m_workerThread, SIGNAL(started()), worker, SLOT(fitting()));
@@ -238,15 +234,18 @@ void EnggDiffFittingPresenter::fittingFinished() {
 
     m_view->showStatus("Single peak fitting process finished. Ready");
 
+    if (!m_view->listWidgetHasSelectedRow()) {
+      m_view->setFittingListWidgetCurrentRow(0);
+    }
+
+    if (m_multiRunMode) {
+      m_model->addAllFitResultsToADS();
+      m_model->addAllFittedPeaksToADS();
+    }
+
     try {
       // should now plot the focused workspace when single peak fitting
       // process fails
-      const auto listLabel = m_view->getFittingListWidgetCurrentValue();
-      int runNumber;
-      size_t bank;
-      std::tie(runNumber, bank) =
-          runAndBankNumberFromListWidgetLabel(listLabel);
-
       plotFitPeaksCurves();
 
     } catch (std::runtime_error &re) {
@@ -276,496 +275,32 @@ void EnggDiffFittingPresenter::fittingFinished() {
     m_view->showStatus(
         "Single peak fitting process did not complete successfully");
   }
-  // Reset once whole process is completed
-  g_multi_run.clear();
   // enable the GUI
+  m_view->enableFitAllButton(m_model->getNumFocusedWorkspaces() > 1);
   m_view->enableCalibrateFocusFitUserActions(true);
-}
-
-// Fitting Tab Run Number & Bank handling here
-void EnggDiffFittingPresenter::fittingRunNoChanged() {
-
-  // receive the run number from the text-field
-  const std::string userPathInput = m_view->getFittingRunNo();
-
-  if (m_previousInput == userPathInput || userPathInput.empty()) {
-    // Short circuit the checks and skip any warnings
-    // or errors as the user has not changed anything
-    // just clicked the box. Additionally this resolves an
-    // issue where QT will return the cursor and produce a new
-    // warning when the current warning is closed
-    return;
-  } else {
-    m_previousInput = userPathInput;
-  }
-
-  // file name
-  const Poco::Path pocoUserPathInput(userPathInput);
-
-  std::vector<std::string> foundFullFilePaths;
-
-  // returns empty if no directory is found
-  const std::string parsedUserInput = pocoUserPathInput.toString();
-
-  // split directory if 'ENGINX_' found by '_.'
-  std::vector<std::string> splitBaseName;
-  if (parsedUserInput.find(m_view->getCurrentInstrument() + "_") !=
-      std::string::npos) {
-    boost::split(splitBaseName, parsedUserInput, boost::is_any_of("_."));
-  }
-
-  try {
-    // if input file is a directory and successfully splitBaseName
-    // or when default bank is set or changed, the text-field is updated with
-    // selected bank directory which would trigger this function again
-    if (pocoUserPathInput.isFile() && !splitBaseName.empty()) {
-      foundFullFilePaths = processFullPathInput(pocoUserPathInput);
-      // if given a multi-run
-    } else if (userPathInput.find("-") != std::string::npos) {
-      foundFullFilePaths = processMultiRun(userPathInput);
-      // try to process using single run
-    } else {
-      foundFullFilePaths = processSingleRun(userPathInput);
-    }
-  } catch (std::invalid_argument &ia) {
-    // If something went wrong stop and print error only
-    g_log.error("Failed to process user input. Error was: ");
-    g_log.error(ia.what());
-    return;
-  }
-
-  // if single or multi run-number
-  // set the text-field to directory here to the first in
-  // the vector if its not empty
-  if (foundFullFilePaths.empty()) {
-    m_view->userWarning(
-        "Error finding file(s)",
-        "Unable to find one or more files with a name matching the run"
-        " number or range input. Please check the files are present in"
-        " the focused output directory and the input is correct.");
-  } else if (!pocoUserPathInput.isFile()) {
-    // foundFiles is not empty and this is a directory
-    const std::string firstDir = foundFullFilePaths[0];
-    m_view->setFittingRunNo(firstDir);
-  }
-}
-
-/**
-  * Verifies and uses the user input path (i.e. a browsed file)
-  * to update drop down for available banks and various widgets on the GUI
-  *
-  * @param filePath The user entered file path as a Poco Path
-  *
-  * @return The full file path as a vector of strings to make this
-  * consistent with the other file processing methods
-  */
-std::vector<std::string>
-EnggDiffFittingPresenter::processFullPathInput(const Poco::Path &filePath) {
-
-  std::vector<std::string> foundRunNumbers;
-  std::vector<std::string> foundFullFilePaths;
-
-  // Handle files the user browsed to separately
-  try {
-    foundRunNumbers =
-        getAllBrowsedFilePaths(filePath.toString(), foundFullFilePaths);
-  } catch (std::runtime_error &e) {
-    const std::string eMsg(e.what());
-    g_log.error("Error loading browsed file: " + eMsg);
-
-    m_view->userWarning(
-        "Run Number Not Found",
-        "The run number specified could not be located "
-        "in the focused output directory. Please check that the "
-        "correct directory is set for Output Folder under Focusing Settings "
-        "on the settings tab and that the input is correct");
-    // Bring it back to a known state of 0 found
-    foundFullFilePaths.clear();
-    return foundFullFilePaths;
-  }
-
-  // Update UI to reflect found files
-  // Update the list of files found in the view
-  m_view->setFittingRunNumVec(foundFullFilePaths);
-
-  const bool multiRunMode = m_view->getFittingMultiRunMode();
-  const bool singleRunMode = m_view->getFittingSingleRunMode();
-  // if not run mode or bank mode: to avoid recreating widgets
-  if (!multiRunMode && !singleRunMode) {
-    // Skips this step if it is multiple run because widget already
-    // updated
-    setRunNoItems(foundRunNumbers, false);
-  }
-
-  return foundFullFilePaths;
+  m_multiRunMode = false;
 }
 
 void EnggDiffFittingPresenter::processSelectRun() {
   const auto listLabel = m_view->getFittingListWidgetCurrentValue();
-  int runNumber;
-  size_t bank;
-  std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(listLabel);
-
-  const auto ws = m_model->getFocusedWorkspace(runNumber, bank);
-  plotFocusedFile(false, ws);
-}
-
-/**
-  * Takes the full path of a file which has been selected through
-  * browse, the run number the user has input and stores the
-  * full file paths of all files (specifically all banks) associated
-  * with that run number. Then updates the view to display all run
-  * numbers for multi-runs
-  *
-  * @param inputFullPath The user inputted path in the view
-  * @param foundFullFilePaths The full paths of all associated files found
-  *
-  * @return Vector of all run numbers for which a full file path was found
-  */
-std::vector<std::string> EnggDiffFittingPresenter::getAllBrowsedFilePaths(
-    const std::string &inputFullPath,
-    std::vector<std::string> &foundFullFilePaths) {
-  // to track the FittingRunnoChanged loop number
-  if (g_fitting_runno_counter == 0) {
-    g_multi_run_directories.clear();
-  }
-
-  g_fitting_runno_counter++;
-
-  // Files take the form 'ENGINX_123456_focused_bank_1' so create
-  // a string similar to 'ENGINX_123456_focused_bank' to allow us
-  // to search for additional banks]
-  const std::string baseName = getBaseNameFromStr(inputFullPath);
-  const std::vector<std::string> splitBaseName =
-      splitFittingDirectory(baseName);
-
-  // TODO look at removal of hard coded filename positions
-  // Produced <INST>_<RunNumber>_focused for subsequent lookup
-  const std::string baseFilenamePrefix =
-      splitBaseName[0] + "_" + splitBaseName[1] + "_" + splitBaseName[2];
-
-  Poco::Path pocoFullFilePath;
-  if (!pocoFullFilePath.tryParse(inputFullPath)) {
-    // File path isn't valid
-    m_view->userWarning("Bad file path entered",
-                        "The entered file path could not "
-                        " be opened. Please check the file and/or directory "
-                        "exists.");
-
-    throw std::runtime_error(
-        "The file path entered could not be parsed"
-        " this usually indicates a syntax error or bad path input");
-  }
-
-  const std::string workingDirectory = pocoFullFilePath.parent().toString();
-
-  // Find all files which match this baseFilenamePrefix -
-  // like a poor mans regular expression for files
-  if (!findFilePathFromBaseName(workingDirectory, baseFilenamePrefix,
-                                foundFullFilePaths)) {
-    // I can't see this ever being thrown if the user is browsing to files but
-    // better to be safe and give an informative message
-    throw std::runtime_error("Could not find any files matching the generated"
-                             " pattern: " +
-                             baseFilenamePrefix);
-  }
-
-  // Store the run number as found
-  std::vector<std::string> runNoVec;
-  runNoVec.push_back(splitBaseName[1]);
-
-  return runNoVec;
-}
-
-/**
-  * Processes a multi run input to the interface
-  * such as '12345-12350' by splitting it into '12345' to '12350'
-  * then calling enableMultiRun
-  * @param userInput The user input from the view
-  *
-  * @return List of found full file paths for the files specified
-  */
-std::vector<std::string>
-EnggDiffFittingPresenter::processMultiRun(const std::string &userInput) {
-
-  // Split user input into the first and last run number
-  std::vector<std::string> firstLastRunNoVec;
-  boost::split(firstLastRunNoVec, userInput, boost::is_any_of("-"));
-
-  // Then store them in their own strings
-  std::string firstRun;
-  std::string lastRun;
-  if (!firstLastRunNoVec.empty()) {
-    firstRun = firstLastRunNoVec[0];
-    lastRun = firstLastRunNoVec[1];
-
-    m_view->setFittingMultiRunMode(true);
-  }
-  return enableMultiRun(firstRun, lastRun);
-}
-
-std::vector<std::string> EnggDiffFittingPresenter::processSingleRun(
-    const std::string &userInputBasename) {
-
-  const auto focusDir = m_view->focusingDir();
-
-  // Check there is a folder to search for this file
-  // this will be changed to respect user directories as well later
-  if (focusDir.empty()) {
-    m_view->userWarning("Focus directory not set.",
-                        "Please check that a valid directory is "
-                        "set for Output Folder under Focusing Settings on the "
-                        "settings tab. "
-                        "Please try again");
-
-    m_view->enableFitAllButton(false);
-  }
-
-  // Next check input is a run number only as this is currently all
-  // that we can handle
-  if (!isDigit(userInputBasename)) {
-    m_view->userWarning(
-        "Invalid Run Number",
-        "Invalid format of run number has been entered. There was"
-        " non-numeric digits present in the input. Please try again");
-    m_view->enableFitAllButton(false);
-    throw std::invalid_argument("User input contained non-numeric characters");
-  }
-
-  if (userInputBasename.empty()) {
-
-    m_view->userWarning("Invalid Run Number",
-                        "Invalid format of run number has been entered. "
-                        " The input was blank. Please try again");
-    m_view->enableFitAllButton(false);
-    throw std::invalid_argument("User input was blank");
-  }
-
-  if (g_fitting_runno_counter == 0) {
-    g_multi_run_directories.clear();
-  }
-
-  // to track the FittingRunnoChanged loop number
-  g_fitting_runno_counter++;
-
-  // Inform the view we are using single run mode
-  m_view->setFittingSingleRunMode(true);
-
-  std::vector<std::string> foundFilePaths;
-  const bool wasFound =
-      findFilePathFromBaseName(focusDir, userInputBasename, foundFilePaths);
-
-  if (!wasFound) {
-    // Skip all UI update code
-    return foundFilePaths;
-  }
-
-  const bool fittingMultiRunMode = m_view->getFittingMultiRunMode();
-  if (!fittingMultiRunMode) {
-    // Wrap the current run number in a vector and pass through
-    // We cant use an initializer list as MSVC doesn't support this yet
-    std::vector<std::string> strFocusedFileVector;
-    strFocusedFileVector.push_back(userInputBasename);
-    setRunNoItems(strFocusedFileVector, false);
-  }
-
-  // Update the list of found runs shown in the view
-  m_view->setFittingRunNumVec(foundFilePaths);
-
-  // add bank to the combo-box and list view
-  // recreates bank widget for every run (multi-run) depending on
-  // number of banks file found for given run number in folder
-
-  return foundFilePaths;
-}
-
-/**
-  * Finds the full file path (including extensions) for files that
-  * match the given base filename (without ext) in the given folder.
-  *
-  * @param directoryToSearch The directory to search for these files
-  * @param baseFileNamesToFind The base filename to find in this folder
-  * @param foundFullFilePath Holds the path of the files if one was found
-  * which matched the given base filename
-  *
-  * @return True if any files were found or false if none were
-  */
-bool EnggDiffFittingPresenter::findFilePathFromBaseName(
-    const std::string &directoryToSearch,
-    const std::string &baseFileNamesToFind,
-    std::vector<std::string> &foundFullFilePath) {
-
-  bool found = false;
-
-  // Ask for an iterator of all files/folders in 'directoryToSearch'
-  Poco::DirectoryIterator directoryIter;
-  Poco::DirectoryIterator directoryIterEnd;
-
-  try {
-    directoryIter = directoryToSearch;
-  } catch (Poco::FileNotFoundException) {
-    // UNIX will throw if the directory is blank however Windows
-    // will continue then fail to find the file in a non existent
-    // directory - this ultimately results in the same thing.
-    return false;
-  }
-
-  try {
-    // Walk through every file within that folder looking for required files
-    while (directoryIter != directoryIterEnd) {
-
-      // Get files and not folders (don't recurse down)
-      if (directoryIter->isFile()) {
-
-        // Store the full path so if we get a matching file we know its path
-        const std::string fullPathToCheck = directoryIter->path();
-
-        // Get base name e.g. (ENGINX0012345)
-        // Poco forces us to create a file from path to ask for base name
-        // There must be a better way of doing this
-        const Poco::Path PocoFileName = directoryIter->path();
-        const std::string baseFileName = PocoFileName.getBaseName();
-
-        // Look for the user input by comparing the base name of the
-        // current file with the user input
-        if (baseFileName.find(baseFileNamesToFind) != std::string::npos) {
-          foundFullFilePath.emplace_back(fullPathToCheck);
-          found = true;
-
-          // if only first loop in Fitting Runno then add directory
-          if (g_fitting_runno_counter == 1) {
-            g_multi_run_directories.push_back(fullPathToCheck);
-          }
-        }
-      }
-      ++directoryIter;
-    }
-
-  } catch (std::runtime_error &re) {
-    m_view->userWarning("Invalid file",
-                        "File not found in the following directory; " +
-                            directoryToSearch + ". " + re.what());
-  }
-
-  return found;
-}
-
-/**
-  * Tests the user input for a multi run is valid and generates
-  * all values between that range (e.g. 1-10 produces 1,2,3...)
-  * to then look up those runs in the focus directory and find
-  * their full file paths. Additionally it updates the GUI to reflect
-  * if all runs were found or not
-  *
-  * @param firstRun The first run number of the range as a string
-  * @param lastRun The last run number of the range as a string
-  *
-  * @return A vector containing all file paths which were found
-  */
-std::vector<std::string>
-EnggDiffFittingPresenter::enableMultiRun(const std::string &firstRun,
-                                         const std::string &lastRun) {
-
-  std::vector<std::string> fittingRunNoDirVec;
-
-  // Perform input checks first
-  // Are both values either side of '-' the user input digits
-  if (!isDigit(firstRun) || !isDigit(lastRun)) {
-    m_view->userWarning("Invalid Run Number",
-                        "Invalid format of multi-run number has been entered. "
-                        "Please try again");
-    m_view->enableFitAllButton(false);
-    throw std::invalid_argument("Both values are not numerical entries");
-  }
-
-  // Convert strings to integers for remainder of function
-  const int firstNum = std::stoi(firstRun);
-  const int lastNum = std::stoi(lastRun);
-  const size_t range = abs(lastNum - firstNum);
-
-  // Cap the maximum number of runs we can process at 200
-  constexpr size_t maximumNumberOfRuns = 200;
-
-  if (range > maximumNumberOfRuns) {
-    m_view->userWarning("Range too large",
-                        "The specified run number range is too large."
-                        " A maximum of 200 entries can be processed a time.");
-    m_view->enableFitAllButton(false);
-    throw std::invalid_argument("Number of runs is greater than 200");
-  }
-
-  // By performing this check we can make optimizations and assumptions
-  // about the ordering of values
-  if (firstNum > lastNum) {
-    m_view->userWarning("Range not ascending",
-                        "The range specified was not ascending. "
-                        "The last run number needs to be"
-                        " larger than the start run number");
-    throw std::invalid_argument("Run range is not ascending");
-  }
-
-  std::string workingDirectory = m_view->focusingDir();
-
-  if (workingDirectory.empty()) {
-    m_view->userWarning("Invalid Input",
-                        "Please check that a valid directory is "
-                        "set for Output Folder under Focusing Settings on the "
-                        "settings tab. "
-                        "Please try again");
-    throw std::invalid_argument("Focus directory not set correctly");
-  }
-
-  // --- All checks complete lets process the multi run input ---
-
-  // Reserve the number of elements needed so we don't allocate multiple times
-  std::vector<std::string> RunNumberVec;
-  RunNumberVec.reserve(range);
-
-  for (int i = firstNum; i <= lastNum; i++) {
-    // Populate vector with list of runs
-    RunNumberVec.push_back(std::to_string(i));
-  }
-
-  // clear previous directories set before findFilePathsFromBaseName
-  if (g_fitting_runno_counter == 0) {
-    g_multi_run_directories.clear();
-  }
-  // to track the FittingRunnoChanged loop number
-  g_fitting_runno_counter++;
-
-  // rewrite the vector of run number which is available
-  std::vector<std::string> foundRunNumber;
-
-  bool foundAllRuns = true;
+  if (listLabel) {
+    int runNumber;
+    size_t bank;
+    std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(*listLabel);
 
-  for (const auto &runNumber : RunNumberVec) {
-    // Get full path for every run selected
-    std::vector<std::string> foundFileNames;
-    if (findFilePathFromBaseName(workingDirectory, runNumber, foundFileNames)) {
-      // Append those that were found with fittingRunNoDirVec
-      fittingRunNoDirVec.insert(fittingRunNoDirVec.end(),
-                                foundFileNames.cbegin(), foundFileNames.cend());
+    if (m_model->hasFittedPeaksForRun(runNumber, bank)) {
+      plotFitPeaksCurves();
     } else {
-      // We couldn't find this one - set the flag and break out of loop
-      foundAllRuns = false;
-      break;
+      const auto ws = m_model->getFocusedWorkspace(runNumber, bank);
+      plotFocusedFile(m_model->hasFittedPeaksForRun(runNumber, bank), ws);
     }
   }
-
-  if (foundAllRuns) {
-    setRunNoItems(RunNumberVec, true);
-  } else {
-    // Set the size to 0 as some were not found
-    fittingRunNoDirVec.clear();
-  }
-
-  return fittingRunNoDirVec;
 }
 
 void EnggDiffFittingPresenter::processStart() {}
 
 void EnggDiffFittingPresenter::processLoad() {
-  const std::string filenames = m_view->getFittingRunNo();
+  const std::string filenames = m_view->getFocusedFileNames();
   if (filenames.empty()) {
     m_view->userWarning("No file selected", "Please enter filename(s) to load");
     return;
@@ -797,6 +332,8 @@ void EnggDiffFittingPresenter::processLoad() {
   std::for_each(
       listWidgetLabels.begin(), listWidgetLabels.end(),
       [&](const std::string &listLabel) { m_view->addRunNoItem(listLabel); });
+
+  m_view->enableFitAllButton(m_model->getNumFocusedWorkspaces() > 1);
 }
 
 void EnggDiffFittingPresenter::processShutDown() {
@@ -813,21 +350,27 @@ void EnggDiffFittingPresenter::processLogMsg() {
 }
 
 void EnggDiffFittingPresenter::processFitAllPeaks() {
+  m_multiRunMode = true;
   std::string fittingPeaks = m_view->getExpectedPeaksInput();
 
   const std::string normalisedPeakCentres = stripExtraCommas(fittingPeaks);
   m_view->setPeakList(normalisedPeakCentres);
 
+  const auto workspaceLabels = m_model->getRunNumbersAndBankIDs();
+
   g_log.debug() << "Focused files found are: " << normalisedPeakCentres << '\n';
-  for (const auto &dir : g_multi_run_directories) {
-    g_log.debug() << dir << '\n';
+  for (const auto &workspaceLabel : workspaceLabels) {
+    g_log.debug() << listWidgetLabelFromRunAndBankNumber(
+                         workspaceLabel.first, workspaceLabel.second) << '\n';
   }
 
-  if (!g_multi_run_directories.empty()) {
+  if (!workspaceLabels.empty()) {
 
-    for (size_t i = 0; i < g_multi_run_directories.size(); i++) {
+    for (const auto &workspaceLabel : workspaceLabels) {
+      const int runNumber = workspaceLabel.first;
+      const size_t bank = workspaceLabel.second;
       try {
-        validateFittingInputs(g_multi_run_directories[i],
+        validateFittingInputs(m_model->getWorkspaceFilename(runNumber, bank),
                               normalisedPeakCentres);
       } catch (std::invalid_argument &ia) {
         m_view->userWarning("Error in the inputs required for fitting",
@@ -836,39 +379,33 @@ void EnggDiffFittingPresenter::processFitAllPeaks() {
       }
     }
 
-    const std::string outWSName = "engggui_fitting_fit_peak_ws";
     g_log.notice() << "EnggDiffraction GUI: starting new multi-run "
-                      "single peak fits into workspace '" +
-                          outWSName + "'. This "
-                                      "may take some seconds... \n";
-
+                   << "single peak fits. This may take some seconds...\n";
     m_view->showStatus("Fitting multi-run single peaks...");
 
     // disable GUI to avoid any double threads
     m_view->enableCalibrateFocusFitUserActions(false);
     m_view->enableFitAllButton(false);
 
-    // doFitting()
-    // WORK OUT WHAT TO DO HERE
-    // startAsyncFittingWorker(g_multi_run_directories, fitPeaksData);
-
+    startAsyncFittingWorker(workspaceLabels, normalisedPeakCentres);
   } else {
     m_view->userWarning("Error in the inputs required for fitting",
-                        "Invalid files have been selected for Fit All process");
-    m_view->enableFitAllButton(false);
+                        "No runs were loaded for fitting");
   }
 }
 
 void EnggDiffFittingPresenter::processFitPeaks() {
-  if (!m_view->listWidgetHasSelectedRow()) {
+  const auto listLabel = m_view->getFittingListWidgetCurrentValue();
+
+  if (!listLabel) {
     m_view->userWarning("No run selected",
                         "Please select a run to fit from the list");
     return;
   }
-  const auto listLabel = m_view->getFittingListWidgetCurrentValue();
+
   int runNumber;
   size_t bank;
-  std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(listLabel);
+  std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(*listLabel);
   std::string fittingPeaks = m_view->getExpectedPeaksInput();
 
   const std::string normalisedPeakCentres = stripExtraCommas(fittingPeaks);
@@ -897,7 +434,8 @@ void EnggDiffFittingPresenter::processFitPeaks() {
   // disable GUI to avoid any double threads
   m_view->enableCalibrateFocusFitUserActions(false);
 
-  startAsyncFittingWorker(runNumber, bank, normalisedPeakCentres);
+  startAsyncFittingWorker({std::make_pair(runNumber, bank)},
+                          normalisedPeakCentres);
 }
 
 void EnggDiffFittingPresenter::validateFittingInputs(
@@ -928,25 +466,6 @@ void EnggDiffFittingPresenter::validateFittingInputs(
   }
 }
 
-/**
-* Splits the file name in to sections of '_' and 'ENGINX' text
-* within the filename
-*
-* @param selectedfPath is the selected file's path
-*
-* @return std::vector<std::string> of splitted file name with run
-* number & bank
-*/
-std::vector<std::string> EnggDiffFittingPresenter::splitFittingDirectory(
-    const std::string &selectedfPath) {
-
-  Poco::Path PocofPath(selectedfPath);
-  std::string selectedbankfName = PocofPath.getBaseName();
-  std::vector<std::string> splitBaseName;
-  boost::split(splitBaseName, selectedbankfName, boost::is_any_of("_."));
-  return splitBaseName;
-}
-
 void EnggDiffFittingPresenter::doFitting(const int runNumber, const size_t bank,
                                          const std::string &expectedPeaks) {
   g_log.notice() << "EnggDiffraction GUI: starting new fitting with run "
@@ -1090,61 +609,6 @@ void EnggDiffFittingPresenter::fittingWriteFile(const std::string &fileDir) {
   }
 }
 
-void EnggDiffFittingPresenter::setRunNoItems(
-    const std::vector<std::string> &runNumVector, bool multiRun) {
-  try {
-    if (!runNumVector.empty()) {
-
-      // delete previous run number added to the list
-      m_view->clearFittingListWidget();
-
-      // enable fit button only when run number provided
-      m_view->enableFitAllButton(true);
-
-      for (size_t i = 0; i < runNumVector.size(); i++) {
-
-        std::string currentRun = (runNumVector[i]);
-
-        // adding to widget
-        m_view->addRunNoItem(currentRun);
-        g_multi_run.push_back(currentRun);
-      }
-
-      // change to selected run number item
-      if (multiRun) {
-        m_view->enableFittingListWidget(true);
-
-        auto currentIndex = m_view->getFittingListWidgetCurrentRow();
-        if (currentIndex == -1)
-          m_view->setFittingListWidgetCurrentRow(0);
-      } else {
-        m_view->enableFittingListWidget(false);
-      }
-    }
-
-    else {
-      // upon invalid file
-      // disable the widgets when only one related file found
-      m_view->enableFittingListWidget(false);
-      m_view->enableFitAllButton(false);
-      m_view->clearFittingListWidget();
-
-      m_view->userWarning(
-          "Run Number Not Found",
-          "The run number specified could not be located "
-          "in the focused output directory. Please check that the "
-          "correct directory is set for Output Folder under Focusing Settings "
-          "on the settings tab.");
-    }
-
-  } catch (std::runtime_error &re) {
-    m_view->userWarning("Unable to insert items: ",
-                        "Could not add list widget; " +
-                            static_cast<std::string>(re.what()) +
-                            ". Please try again");
-  }
-}
-
 bool EnggDiffFittingPresenter::isDigit(const std::string &text) const {
   return std::all_of(text.cbegin(), text.cend(), ::isdigit);
 }
@@ -1199,9 +663,14 @@ void EnggDiffFittingPresenter::plotFitPeaksCurves() {
     m_view->resetCanvas();
 
     const auto listLabel = m_view->getFittingListWidgetCurrentValue();
+    if (!listLabel) {
+      m_view->userWarning("Invalid run number or bank",
+                          "Tried to plot a focused file which does not exist");
+      return;
+    }
     int runNumber;
     size_t bank;
-    std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(listLabel);
+    std::tie(runNumber, bank) = runAndBankNumberFromListWidgetLabel(*listLabel);
     const auto ws = m_model->getAlignedWorkspace(runNumber, bank);
 
     // plots focused workspace
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.h b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.h
index fb6e72d6124b1e4adbbd0b37705fd4587eb730bb..fac5c57504bbdfe00b4006e11faea57d3c3a50dd 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.h
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingPresenter.h
@@ -80,9 +80,6 @@ public:
 
   void plotFitPeaksCurves();
 
-  void setRunNoItems(const std::vector<std::string> &runNumVector,
-                     bool multiRun);
-
 protected:
   void processStart();
   void processLoad();
@@ -97,7 +94,6 @@ protected:
 protected slots:
 
   void fittingFinished();
-  void fittingRunNoChanged();
 
 private:
   bool isDigit(const std::string &text) const;
@@ -105,25 +101,15 @@ private:
   void warnFileNotFound(const std::exception &ex);
 
   // Methods related single peak fits
-  virtual void startAsyncFittingWorker(const int runNumber, const size_t bank,
-                                       const std::string &expectedPeaks);
+  virtual void startAsyncFittingWorker(
+      const std::vector<std::pair<int, size_t>> &runNumberBankPairs,
+      const std::string &expectedPeaks);
 
   std::string getBaseNameFromStr(const std::string &filePath) const;
 
   void validateFittingInputs(const std::string &focusedRunNo,
                              const std::string &expectedPeaks);
 
-  // TODO make this const when the global is removed
-  bool findFilePathFromBaseName(const std::string &directoryToSearch,
-                                const std::string &baseFileNamesToFind,
-                                std::vector<std::string> &foundFullFilePath);
-
-  std::vector<std::string>
-  splitFittingDirectory(const std::string &selectedfPath);
-
-  std::vector<std::string> enableMultiRun(const std::string &firstRun,
-                                          const std::string &lastRun);
-
   void browsePeaksToFit();
 
   void addPeakToList();
@@ -134,34 +120,12 @@ private:
 
   void fittingWriteFile(const std::string &fileDir);
 
-  std::vector<std::string>
-  getAllBrowsedFilePaths(const std::string &inputFullPath,
-                         std::vector<std::string> &foundFullFilePaths);
-
-  std::vector<std::string> processMultiRun(const std::string &userInput);
-
-  std::vector<std::string>
-  processSingleRun(const std::string &userInputBasename);
-
-  std::vector<std::string> processFullPathInput(const Poco::Path &pocoFilePath);
-
-  static int g_fitting_runno_counter;
-
-  // name of the workspace with the focused ws being used for fitting
-  static const std::string g_focusedFittingWSName;
-
-  // input run number - used for output file name
-  std::vector<std::string> g_multi_run;
-
   // Holds the previous user input so we can short circuit further checks
   std::string m_previousInput;
 
   /// true if the last fitting completed successfully
   bool m_fittingFinishedOK;
 
-  // directories of all the run numbers when multi-run option
-  std::vector<std::string> g_multi_run_directories;
-
   QThread *m_workerThread;
 
   /// interface for the 'current' calibration
@@ -181,6 +145,9 @@ private:
 
   /// Handle the user selecting a different run to plot
   void processSelectRun();
+
+  /// Whether the user is doing fitting on multiple runs
+  bool m_multiRunMode;
 };
 
 } // namespace CustomInterfaces
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.cpp b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.cpp
index 1b9bd973d2869d03cac5ccb50a5f28ed8936255b..ea8e973b8a5db1584603c498c204251b59ea1a75 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.cpp
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.cpp
@@ -93,13 +93,6 @@ void EnggDiffFittingViewQtWidget::doSetup() {
   connect(m_ui.lineEdit_pushButton_run_num, SIGNAL(returnPressed()), this,
           SLOT(loadClicked()));
 
-  connect(this, SIGNAL(getBanks()), this, SLOT(FittingRunNo()));
-
-  connect(this, SIGNAL(setBank()), this, SLOT(listViewFittingRun()));
-
-  connect(m_ui.listWidget_fitting_run_num, SIGNAL(itemSelectionChanged()), this,
-          SLOT(listViewFittingRun()));
-
   connect(m_ui.pushButton_fitting_browse_peaks, SIGNAL(released()), this,
           SLOT(browseClicked()));
 
@@ -234,10 +227,6 @@ void EnggDiffFittingViewQtWidget::fitAllClicked() {
   m_presenter->notify(IEnggDiffFittingPresenter::FitAllPeaks);
 }
 
-void EnggDiffFittingViewQtWidget::FittingRunNo() {
-  m_presenter->notify(IEnggDiffFittingPresenter::FittingRunNo);
-}
-
 void EnggDiffFittingViewQtWidget::addClicked() {
   m_presenter->notify(IEnggDiffFittingPresenter::addPeaks);
 }
@@ -250,32 +239,6 @@ void EnggDiffFittingViewQtWidget::saveClicked() {
   m_presenter->notify(IEnggDiffFittingPresenter::savePeaks);
 }
 
-void EnggDiffFittingViewQtWidget::setBankDir(int idx) {
-
-  const size_t runNoDirSize = m_fitting_runno_dir_vec.size();
-  // idx must correspond to an element and the vector cant be empty
-  if (size_t(idx) < runNoDirSize && runNoDirSize > 0) {
-
-    std::string bankDir = m_fitting_runno_dir_vec[idx];
-    Poco::Path fpath(bankDir);
-
-    setFittingRunNo(bankDir);
-  }
-}
-
-void EnggDiffFittingViewQtWidget::listViewFittingRun() {
-
-  if (m_fittingMutliRunMode) {
-    auto listView = m_ui.listWidget_fitting_run_num;
-    auto currentRow = listView->currentRow();
-    auto item = listView->item(currentRow);
-    QString itemText = item->text();
-
-    setFittingRunNo(itemText.toStdString());
-    FittingRunNo();
-  }
-}
-
 void EnggDiffFittingViewQtWidget::listWidget_fitting_run_num_clicked(
     QListWidgetItem *clickedItem) {
   const auto label = clickedItem->text();
@@ -474,16 +437,15 @@ void EnggDiffFittingViewQtWidget::browseFitFocusedRun() {
     return;
   }
 
-  // MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory(paths[0]);
-  setFittingRunNo(paths.join(",").toStdString());
-  // getBanks();
+  setFocusedFileNames(paths.join(",").toStdString());
 }
 
-void EnggDiffFittingViewQtWidget::setFittingRunNo(const std::string &path) {
-  m_ui.lineEdit_pushButton_run_num->setText(QString::fromStdString(path));
+void EnggDiffFittingViewQtWidget::setFocusedFileNames(
+    const std::string &paths) {
+  m_ui.lineEdit_pushButton_run_num->setText(QString::fromStdString(paths));
 }
 
-std::string EnggDiffFittingViewQtWidget::getFittingRunNo() const {
+std::string EnggDiffFittingViewQtWidget::getFocusedFileNames() const {
   return m_ui.lineEdit_pushButton_run_num->text().toStdString();
 }
 
@@ -503,9 +465,12 @@ int EnggDiffFittingViewQtWidget::getFittingListWidgetCurrentRow() const {
   return m_ui.listWidget_fitting_run_num->currentRow();
 }
 
-std::string
+boost::optional<std::string>
 EnggDiffFittingViewQtWidget::getFittingListWidgetCurrentValue() const {
-  return m_ui.listWidget_fitting_run_num->currentItem()->text().toStdString();
+  if (listWidgetHasSelectedRow()) {
+    return m_ui.listWidget_fitting_run_num->currentItem()->text().toStdString();
+  }
+  return boost::none;
 }
 
 bool EnggDiffFittingViewQtWidget::listWidgetHasSelectedRow() const {
diff --git a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.h b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.h
index 920069365ea4a95888b4621ca7be359b9474ff34..89bc6b600821fad94c19b146669433e309cc8797 100644
--- a/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.h
+++ b/qt/scientific_interfaces/EnggDiffraction/EnggDiffFittingViewQtWidget.h
@@ -89,9 +89,9 @@ public:
 
   std::vector<std::string> logMsgs() const override { return m_logMsgs; }
 
-  void setFittingRunNo(const std::string &path) override;
+  void setFocusedFileNames(const std::string &paths) override;
 
-  std::string getFittingRunNo() const override;
+  std::string getFocusedFileNames() const override;
 
   void enableFitAllButton(bool enable) const override;
 
@@ -101,7 +101,8 @@ public:
 
   int getFittingListWidgetCurrentRow() const override;
 
-  std::string getFittingListWidgetCurrentValue() const override;
+  boost::optional<std::string>
+  getFittingListWidgetCurrentValue() const override;
 
   bool listWidgetHasSelectedRow() const override;
 
@@ -176,14 +177,11 @@ private slots:
   void loadClicked();
   void fitClicked();
   void fitAllClicked();
-  void FittingRunNo();
   void addClicked();
   void browseClicked();
   void saveClicked();
   void plotSeparateWindow();
   void showToolTipHelp();
-  void setBankDir(int idx);
-  void listViewFittingRun();
   void listWidget_fitting_run_num_clicked(QListWidgetItem *listWidget);
 
 private:
diff --git a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingModel.h b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingModel.h
index ac9cc49425f3920971e11561242f32bf67bb1700..75dd6c5ff5d0ad509382a464c90814375b198269 100644
--- a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingModel.h
+++ b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingModel.h
@@ -47,6 +47,15 @@ public:
                                     const std::string &filename) const = 0;
 
   virtual void createFittedPeaksWS(const int runNumber, const size_t bank) = 0;
+
+  virtual size_t getNumFocusedWorkspaces() const = 0;
+
+  virtual void addAllFitResultsToADS() const = 0;
+
+  virtual void addAllFittedPeaksToADS() const = 0;
+
+  virtual bool hasFittedPeaksForRun(const int runNumber,
+                                    const size_t bank) const = 0;
 };
 
 } // namespace MantidQt
diff --git a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingPresenter.h b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingPresenter.h
index 8c5d25fd1c42f84a9168994e56e7faf43188ea6b..b4feb86ea796b4b48241f163b46762a588fd3cb4 100644
--- a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingPresenter.h
+++ b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingPresenter.h
@@ -42,17 +42,16 @@ public:
   /// These are user actions, triggered from the (passive) view, that need
   /// handling by the presenter
   enum Notification {
-    Start,        ///< Start and setup interface
-    FittingRunNo, ///< Creates widgets and handles multi/run numbers
-    Load,         ///< Load the focused file to the canvas
-    FitPeaks,     ///< Preforms single peak fits
-    FitAllPeaks,  ///< Preforms multiple runs in sequence single peak fits
-    addPeaks,     ///< Adds peak to the list
-    browsePeaks,  ///< Browse peaks to the list
-    savePeaks,    ///< Save the peaks list
-    ShutDown,     ///< closing the interface
-    LogMsg,       ///< need to send a message to the Mantid log system
-    selectRun,    ///< update plot with new run selected from list widget
+    Start,       ///< Start and setup interface
+    Load,        ///< Load the focused file to the canvas
+    FitPeaks,    ///< Preforms single peak fits
+    FitAllPeaks, ///< Preforms multiple runs in sequence single peak fits
+    addPeaks,    ///< Adds peak to the list
+    browsePeaks, ///< Browse peaks to the list
+    savePeaks,   ///< Save the peaks list
+    ShutDown,    ///< closing the interface
+    LogMsg,      ///< need to send a message to the Mantid log system
+    selectRun,   ///< update plot with new run selected from list widget
   };
 
   /**
diff --git a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingView.h b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingView.h
index a0b5a7bc9708eacb21246104770976d804c267c2..0a6e94ba927da53912e8981cba387c96276569d4 100644
--- a/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingView.h
+++ b/qt/scientific_interfaces/EnggDiffraction/IEnggDiffFittingView.h
@@ -9,6 +9,7 @@
 
 #include <string>
 #include <vector>
+#include <boost/optional.hpp>
 
 class QwtData;
 
@@ -51,11 +52,12 @@ public:
   virtual ~IEnggDiffFittingView() = default;
 
   /**
-   * returns directory of the file name to preform fitting on
+   * Get value of the input files text box
    *
-   * @return directory as std::string
+   * @return (hopefully) comma-separated list of focused files to load for
+   * fitting
    */
-  virtual std::string getFittingRunNo() const = 0;
+  virtual std::string getFocusedFileNames() const = 0;
 
   /**
    * A list of dSpacing values to be translated into TOF
@@ -155,7 +157,8 @@ public:
   /**
   * @return The text on the current selected row of the list widget
   */
-  virtual std::string getFittingListWidgetCurrentValue() const = 0;
+  virtual boost::optional<std::string>
+  getFittingListWidgetCurrentValue() const = 0;
 
   /**
   * @return Whether the list widget currently has an item selected
@@ -170,11 +173,11 @@ public:
   virtual void setFittingListWidgetCurrentRow(int idx) const = 0;
 
   /**
-   * sets the fitting run number according to path
+   * Set value of the text box for input filenames
    *
-   * @param path of the selected focused run file
+   * @param path Comma-separated list of files to add
    */
-  virtual void setFittingRunNo(const std::string &path) = 0;
+  virtual void setFocusedFileNames(const std::string &path) = 0;
 
   /**
    * gets the global vector in view containing focused file directory
diff --git a/qt/scientific_interfaces/test/EnggDiffFittingModelMock.h b/qt/scientific_interfaces/test/EnggDiffFittingModelMock.h
index 7804bee1797f949b95afd2e6eba9e1b3e1ccc234..a1beceaf42ba80227a9e889c0d79f1c3e89f702c 100644
--- a/qt/scientific_interfaces/test/EnggDiffFittingModelMock.h
+++ b/qt/scientific_interfaces/test/EnggDiffFittingModelMock.h
@@ -55,8 +55,17 @@ public:
 
   MOCK_METHOD2(createFittedPeaksWS,
                void(const int runNumber, const size_t bank));
+
+  MOCK_CONST_METHOD0(getNumFocusedWorkspaces, size_t());
+
+  MOCK_CONST_METHOD0(addAllFitResultsToADS, void());
+
+  MOCK_CONST_METHOD0(addAllFittedPeaksToADS, void());
+
+  MOCK_CONST_METHOD2(hasFittedPeaksForRun,
+                     bool(const int runNumber, const size_t bank));
 };
 
 GCC_DIAG_ON_SUGGEST_OVERRIDE
 
-#endif // MANTID_CUSTOM_INTERFACES_ENGGDIFFFITTINGMODELMOCK_H
\ No newline at end of file
+#endif // MANTID_CUSTOM_INTERFACES_ENGGDIFFFITTINGMODELMOCK_H
diff --git a/qt/scientific_interfaces/test/EnggDiffFittingModelTest.h b/qt/scientific_interfaces/test/EnggDiffFittingModelTest.h
index 2c953c450cc14437b4c4f528918102d264de7f1c..7728152d21767483e989c7b24f0acbc392896588 100644
--- a/qt/scientific_interfaces/test/EnggDiffFittingModelTest.h
+++ b/qt/scientific_interfaces/test/EnggDiffFittingModelTest.h
@@ -30,6 +30,9 @@ public:
 
   void addFitParams(const int runNumber, const size_t bank,
                     Mantid::API::ITableWorkspace_sptr ws);
+
+  void mergeTablesExposed(API::ITableWorkspace_sptr tableToCopy,
+                          API::ITableWorkspace_sptr targetTable);
 };
 
 inline void EnggDiffFittingModelAddWSExposed::addWorkspace(
@@ -44,6 +47,12 @@ inline void EnggDiffFittingModelAddWSExposed::addFitParams(
   addFitResults(runNumber, bank, ws);
 }
 
+inline void EnggDiffFittingModelAddWSExposed::mergeTablesExposed(
+    API::ITableWorkspace_sptr tableToCopy,
+    API::ITableWorkspace_sptr targetTable) {
+  mergeTables(tableToCopy, targetTable);
+}
+
 void addSampleWorkspaceToModel(const int runNumber, const int bank,
                                EnggDiffFittingModelAddWSExposed &model) {
   API::MatrixWorkspace_sptr ws =
@@ -99,6 +108,23 @@ API::ITableWorkspace_sptr createFitParamsTable() {
   return table;
 }
 
+template <size_t numColumns, size_t numRows>
+API::ITableWorkspace_sptr createDummyTable(
+    const std::array<std::string, numColumns> &columnHeadings,
+    const std::array<std::array<double, numColumns>, numRows> tableContents) {
+  auto table = API::WorkspaceFactory::Instance().createTable();
+  for (const auto &header : columnHeadings) {
+    table->addColumn("double", header);
+  }
+  for (const auto &row : tableContents) {
+    API::TableRow newRow = table->appendRow();
+    for (const auto value : row) {
+      newRow << value;
+    }
+  }
+  return table;
+}
+
 } // anonymous namespace
 
 class EnggDiffFittingModelTest : public CxxTest::TestSuite {
@@ -187,6 +213,59 @@ public:
     TS_ASSERT_EQUALS(fittedPeaksWS->getNumberHistograms(), 4);
   }
 
+  void test_getNumFocusedWorkspaces() {
+    auto model = EnggDiffFittingModelAddWSExposed();
+
+    addSampleWorkspaceToModel(123, 1, model);
+    addSampleWorkspaceToModel(456, 2, model);
+    addSampleWorkspaceToModel(789, 1, model);
+
+    TS_ASSERT_EQUALS(model.getNumFocusedWorkspaces(), 3);
+  }
+
+  void test_mergeTables() {
+    auto model = EnggDiffFittingModelAddWSExposed();
+
+    const size_t numberOfColumns = 3;
+    const size_t numberOfRows = 2;
+
+    const std::array<std::string, numberOfColumns> columnHeadings = {
+        {"X", "Y", "Z"}};
+
+    const std::array<std::array<double, numberOfColumns>, numberOfRows>
+        targetTableValues = {{{{1, 2, 3}}, {{4, 5, 6}}}};
+
+    auto targetTable = createDummyTable(columnHeadings, targetTableValues);
+
+    const std::array<std::array<double, numberOfColumns>, numberOfRows>
+        copyTableValues = {{{{7, 8, 9}}, {{10, 11, 12}}}};
+
+    auto copyTable = createDummyTable(columnHeadings, copyTableValues);
+
+    TS_ASSERT_THROWS_NOTHING(model.mergeTablesExposed(copyTable, targetTable));
+
+    TS_ASSERT_EQUALS(targetTable->columnCount(), numberOfColumns);
+    TS_ASSERT_EQUALS(targetTable->rowCount(), numberOfRows * 2);
+
+    for (size_t rowIndex = 0; rowIndex < numberOfRows * 2; ++rowIndex) {
+      std::cout << "ROW " << rowIndex << "\n";
+      API::TableRow row = targetTable->getRow(rowIndex);
+      const double expectedX = static_cast<double>(rowIndex) * 3 + 1;
+      const double expectedY = static_cast<double>(rowIndex) * 3 + 2;
+      const double expectedZ = static_cast<double>(rowIndex) * 3 + 3;
+
+      // x, y and z must be initialized to keep RHEL7 happy
+      auto x = expectedX + 1;
+      auto y = expectedY + 1;
+      auto z = expectedZ + 1;
+
+      TS_ASSERT_THROWS_NOTHING(row >> x >> y >> z);
+      TS_ASSERT_EQUALS(x, expectedX);
+      TS_ASSERT_EQUALS(y, expectedY);
+      TS_ASSERT_EQUALS(z, expectedZ);
+    }
+  }
+
 private:
   const static std::string FOCUSED_WS_FILENAME;
   const static int FOCUSED_WS_RUN_NUMBER;
diff --git a/qt/scientific_interfaces/test/EnggDiffFittingPresenterTest.h b/qt/scientific_interfaces/test/EnggDiffFittingPresenterTest.h
index 9d4471766a1a0b39cdb861c55a1350f2bfd550dd..a5e0bab0b4338db3f871707d325f3d1c03c4a4be 100644
--- a/qt/scientific_interfaces/test/EnggDiffFittingPresenterTest.h
+++ b/qt/scientific_interfaces/test/EnggDiffFittingPresenterTest.h
@@ -1,10 +1,10 @@
 #ifndef MANTID_CUSTOMINTERFACES_ENGGDIFFFITTINGPRESENTERTEST_H
 #define MANTID_CUSTOMINTERFACES_ENGGDIFFFITTINGPRESENTERTEST_H
 
+#include "../EnggDiffraction/EnggDiffFittingPresenter.h"
 #include "MantidAPI/FrameworkManager.h"
 #include "MantidKernel/make_unique.h"
 #include "MantidTestHelpers/WorkspaceCreationHelper.h"
-#include "../EnggDiffraction/EnggDiffFittingPresenter.h"
 
 #include "EnggDiffFittingModelMock.h"
 #include "EnggDiffFittingViewMock.h"
@@ -33,8 +33,12 @@ public:
 
 private:
   // not async at all
-  void startAsyncFittingWorker(const int runNumber, const size_t bank,
-                               const std::string &ExpectedPeaks) override {
+  void startAsyncFittingWorker(
+      const std::vector<std::pair<int, size_t>> &runNumberBankPairs,
+      const std::string &ExpectedPeaks) override {
+    assert(runNumberBankPairs.size() == 1);
+    const auto runNumber = runNumberBankPairs[0].first;
+    const auto bank = runNumberBankPairs[0].second;
     doFitting(runNumber, bank, ExpectedPeaks);
     fittingFinished();
   }
@@ -105,7 +109,7 @@ public:
     MantidQt::CustomInterfaces::EnggDiffFittingPresenter pres(
         &mockView, std::move(mockModel), nullptr, nullptr);
 
-    EXPECT_CALL(mockView, getFittingRunNo()).Times(1).WillOnce(Return(""));
+    EXPECT_CALL(mockView, getFocusedFileNames()).Times(1).WillOnce(Return(""));
 
     EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1);
     EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
@@ -131,9 +135,9 @@ public:
     MantidQt::CustomInterfaces::EnggDiffFittingPresenter pres(
         &mockView, std::move(mockModel), nullptr, nullptr);
 
-    EXPECT_CALL(mockView, listWidgetHasSelectedRow())
+    EXPECT_CALL(mockView, getFittingListWidgetCurrentValue())
         .Times(1)
-        .WillOnce(Return(false));
+        .WillOnce(Return(boost::none));
 
     // should not get to the point where the status is updated
     EXPECT_CALL(mockView, setPeakList(testing::_)).Times(0);
@@ -157,9 +161,9 @@ public:
     EnggDiffFittingPresenterNoThread pres(&mockView);
 
     // inputs from user
-    EXPECT_CALL(mockView, listWidgetHasSelectedRow())
+    EXPECT_CALL(mockView, getFittingListWidgetCurrentValue())
         .Times(1)
-        .WillOnce(Return(false));
+        .WillOnce(Return(boost::none));
 
     // should not get to the point where the status is updated
     EXPECT_CALL(mockView, setPeakList(testing::_)).Times(0);
@@ -186,12 +190,10 @@ public:
 
     EnggDiffFittingPresenterNoThread pres(&mockView, std::move(mockModel));
 
-    EXPECT_CALL(mockView, listWidgetHasSelectedRow())
-        .Times(1)
-        .WillOnce(Return(true));
     EXPECT_CALL(mockView, getFittingListWidgetCurrentValue())
         .Times(1)
-        .WillOnce(Return("123_1"));
+        .WillOnce(Return(boost::optional<std::string>(
+            boost::optional<std::string>("123_1"))));
     EXPECT_CALL(*mockModel_ptr, getWorkspaceFilename(testing::_, testing::_))
         .Times(1)
         .WillOnce(Return(""));
@@ -219,197 +221,27 @@ public:
         testing::Mock::VerifyAndClearExpectations(mockModel_ptr))
   }
 
-  // Fitting test begin here
-  void test_fitting_runno_valid_single_run() {
-    testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-
-    // inputs from user
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(1)
-        .WillRepeatedly(Return(std::string(g_focusedBankFile)));
-
-    EXPECT_CALL(mockView, getFittingRunNumVec()).Times(0);
-
-    // should not get to the point where the status is updated
-    EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
-
-    // No errors/0 warnings. There will be no errors or warnings
-    EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
-    EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(2);
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-  }
-
-  void test_fitting_runno_invalid_run() {
-    testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-
-    // inputs from user - invalid run given this can't be numerical
-    // only as that has the chance of matching a file so use a prefix
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(1)
-        .WillOnce(Return(std::string("ENGINX1")));
-
-    // should not get to the point where the status is updated
-    EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
-    EXPECT_CALL(mockView, getFittingRunNumVec()).Times(0);
-
-    // No errors/1 warnings. There will be an warning for invalid run number
-    EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
-    EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(2);
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-  }
-
-  void test_fitting_with_blank_input() {
-    testing::StrictMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(1)
-        .WillOnce(Return(std::string("")));
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-
-    testing::Mock::VerifyAndClearExpectations(&mockView);
-  }
-
-  void test_fitting_file_not_found_with_multiple_runs() {
-    testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-    // 23931-23934
-    std::vector<std::string> RunNumDir;
-    RunNumDir.emplace_back("241391");
-    RunNumDir.emplace_back("241392");
-    RunNumDir.emplace_back("241393");
-    RunNumDir.emplace_back("241394");
-
-    // empty vector
-    std::vector<std::string> splittedFileVec;
-
-    // inputs from user - given multiple run
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(1)
-        .WillOnce(Return(g_focusedFittingRunNo));
-
-    EXPECT_CALL(mockView, getFittingRunNumVec()).Times(0);
-
-    // SplitFittingDir()
-
-    // could possibly feature to create unique path
-    EXPECT_CALL(mockView, focusingDir()).Times(1);
-
-    // should not get to the point where the status is updated
-    EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
-
-    // No errors/1 warnings. The warning will be produced because there
-    // is no focus output directory within the settings tab
-    EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
-    EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1);
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-  }
-
-  void diable_test_fitting_runno_single_run() {
-    testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-
-    // focus directory need to be set for this in the settings
-
-    // 23931-23934
-    std::vector<std::string> RunNumDir;
-    RunNumDir.emplace_back("241391");
-
-    // empty vector
-    std::vector<std::string> splittedFileVec;
-
-    // inputs from user - given multiple run
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(2)
-        .WillRepeatedly(Return("241391"));
-
-    EXPECT_CALL(mockView, getFittingRunNumVec())
-        .Times(1)
-        .WillOnce(Return(RunNumDir));
-
-    EXPECT_CALL(mockView, getFittingMultiRunMode())
-        .Times(1)
-        .WillOnce(Return(false));
-
-    EXPECT_CALL(mockView, setFittingRunNumVec(testing::_)).Times(1);
-
-    EXPECT_CALL(mockView, addRunNoItem(testing::_)).Times(1);
-
-    EXPECT_CALL(mockView, addBankItem(testing::_)).Times(1);
-
-    EXPECT_CALL(mockView, focusingDir()).Times(0);
-
-    // should not get to the point where the status is updated
-    EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
-
-    // No errors/0 warnings.
-    EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
-    EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0);
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-  }
-
-  void test_fitting_runno_browsed_run_add_run_item() {
-    testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
-    // Tests the browse directory file
-    std::vector<std::string> RunNumDir;
-    RunNumDir.emplace_back("241395");
-
-    std::vector<std::string> splittedFileVec;
-    splittedFileVec.emplace_back("ENGINX");
-    splittedFileVec.emplace_back("241395");
-    splittedFileVec.emplace_back("focused");
-    splittedFileVec.emplace_back("bank");
-    splittedFileVec.emplace_back("1");
-
-    // inputs from user - given multiple run
-    EXPECT_CALL(mockView, getFittingRunNo())
-        .Times(1)
-        .WillOnce(Return(g_focusedBankFile));
-
-    EXPECT_CALL(mockView, getFittingRunNumVec()).Times(0);
-
-    EXPECT_CALL(mockView, getFittingMultiRunMode()).Times(0);
-
-    EXPECT_CALL(mockView, setFittingRunNumVec(testing::_)).Times(0);
-
-    EXPECT_CALL(mockView, addBankItem(testing::_)).Times(0);
-
-    EXPECT_CALL(mockView, setBankIdComboBox(testing::_)).Times(0);
-
-    EXPECT_CALL(mockView, addRunNoItem(testing::_)).Times(0);
-
-    EXPECT_CALL(mockView, setFittingListWidgetCurrentRow(testing::_)).Times(0);
-
-    EXPECT_CALL(mockView, focusingDir()).Times(0);
-
-    // No errors/1 warnings. File entered is not found
-    EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
-    EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(2);
-
-    pres.notify(IEnggDiffFittingPresenter::FittingRunNo);
-  }
-
   // Fit All Peaks test begin here
   void test_fit_all_runno_valid_single_run() {
     testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
+    auto mockModel = Mantid::Kernel::make_unique<
+        testing::NiceMock<MockEnggDiffFittingModel>>();
+    auto *mockModel_ptr = mockModel.get();
+
+    EnggDiffFittingPresenterNoThread pres(&mockView, std::move(mockModel));
 
-    EXPECT_CALL(mockView, getFittingRunNo()).Times(0);
     EXPECT_CALL(mockView, getExpectedPeaksInput())
         .Times(1)
         .WillOnce(Return("2.3445,3.3433,4.5664"));
 
+    EXPECT_CALL(*mockModel_ptr, getRunNumbersAndBankIDs())
+        .Times(1)
+        .WillOnce(Return(
+            std::vector<std::pair<int, size_t>>({std::make_pair(123, 1)})));
+
     EXPECT_CALL(mockView, setPeakList(testing::_)).Times(1);
 
-    EXPECT_CALL(mockView, enableFitAllButton(testing::_)).Times(1);
+    EXPECT_CALL(mockView, enableFitAllButton(testing::_)).Times(0);
 
     // should not get to the point where the status is updated
     EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
@@ -425,9 +257,12 @@ public:
   // This would test the fitting tab with invalid expected peaks but should only
   // produce a warning
   void test_fit_all_with_invalid_expected_peaks() {
-    return; // EARLY RETURN, AS FIT ALL IS NOT YET ENABLED
     testing::NiceMock<MockEnggDiffFittingView> mockView;
-    EnggDiffFittingPresenterNoThread pres(&mockView);
+    auto mockModel = Mantid::Kernel::make_unique<
+        testing::NiceMock<MockEnggDiffFittingModel>>();
+    auto *mockModel_ptr = mockModel.get();
+
+    EnggDiffFittingPresenterNoThread pres(&mockView, std::move(mockModel));
 
     // inputs from user
     EXPECT_CALL(mockView, getExpectedPeaksInput())
@@ -435,6 +270,11 @@ public:
         .WillOnce(Return(",3.5,7.78,r43d"));
     EXPECT_CALL(mockView, setPeakList(testing::_)).Times(1);
 
+    EXPECT_CALL(*mockModel_ptr, getRunNumbersAndBankIDs())
+        .Times(1)
+        .WillOnce(Return(
+            std::vector<std::pair<int, size_t>>({std::make_pair(123, 1)})));
+
     // should not get to the point where the status is updated
     EXPECT_CALL(mockView, showStatus(testing::_)).Times(0);
 
@@ -442,7 +282,7 @@ public:
     EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
     EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1);
 
-    pres.notify(IEnggDiffFittingPresenter::FitPeaks);
+    pres.notify(IEnggDiffFittingPresenter::FitAllPeaks);
     TSM_ASSERT(
         "Mock not used as expected. Some EXPECT_CALL conditions were not "
         "satisfied.",
@@ -698,7 +538,7 @@ public:
         nullptr, nullptr);
 
     EXPECT_CALL(mockView, setPeakList(testing::_)).Times(0);
-    EXPECT_CALL(mockView, getFittingRunNo()).Times(0);
+    EXPECT_CALL(mockView, getFocusedFileNames()).Times(0);
     EXPECT_CALL(mockView, getFittingRunNumVec()).Times(0);
     EXPECT_CALL(mockView, focusingDir()).Times(0);
 
diff --git a/qt/scientific_interfaces/test/EnggDiffFittingViewMock.h b/qt/scientific_interfaces/test/EnggDiffFittingViewMock.h
index 48ae082bf897677d2af0ad0c2123bc47ffed3798..e654e5c3eff7fdcfd4a2bdc08fdf8a0bd62e9bae 100644
--- a/qt/scientific_interfaces/test/EnggDiffFittingViewMock.h
+++ b/qt/scientific_interfaces/test/EnggDiffFittingViewMock.h
@@ -40,7 +40,7 @@ public:
   MOCK_METHOD1(enggRunPythonCode, std::string(const std::string &));
 
   // virtual std::string fittingRunNo() const;
-  MOCK_CONST_METHOD0(getFittingRunNo, std::string());
+  MOCK_CONST_METHOD0(getFocusedFileNames, std::string());
 
   // virtual std::string getExpectedPeaksInput() const;
   MOCK_CONST_METHOD0(getExpectedPeaksInput, std::string());
@@ -103,7 +103,8 @@ public:
   MOCK_CONST_METHOD1(setFittingListWidgetCurrentRow, void(int idx));
 
   // gets current value of the fitting list widget
-  MOCK_CONST_METHOD0(getFittingListWidgetCurrentValue, std::string());
+  MOCK_CONST_METHOD0(getFittingListWidgetCurrentValue,
+                     boost::optional<std::string>());
 
   // sets the peak list according to the QString given
   MOCK_CONST_METHOD1(setPeakList, void(const std::string &peakList));
@@ -118,7 +119,7 @@ public:
   MOCK_METHOD1(setFittingRunNumVec, void(std::vector<std::string> assignVec));
 
   // sets the fitting run number according to path
-  MOCK_METHOD1(setFittingRunNo, void(const std::string &path));
+  MOCK_METHOD1(setFocusedFileNames, void(const std::string &path));
 
   // To determine whether the current loop is multi-run or single to avoid
   // regenerating the list - view widget when not required