From 01d5e0f90644bebbd5d2cc6aa0e2414a0b98b7d1 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 13 Jan 2023 09:40:38 +0100
Subject: [PATCH 01/10] read: pass projectDir

---
 GUI/Model/Model/ApplicationModels.cpp | 6 +++---
 GUI/Model/Model/ApplicationModels.h   | 2 +-
 GUI/Model/Model/JobModel.cpp          | 2 +-
 GUI/Model/Model/JobModel.h            | 2 +-
 GUI/Model/Model/RealModel.cpp         | 2 +-
 GUI/Model/Model/RealModel.h           | 2 +-
 GUI/Model/Project/ProjectDocument.cpp | 2 +-
 7 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/GUI/Model/Model/ApplicationModels.cpp b/GUI/Model/Model/ApplicationModels.cpp
index f9810d1e5e5..637d895aa6d 100644
--- a/GUI/Model/Model/ApplicationModels.cpp
+++ b/GUI/Model/Model/ApplicationModels.cpp
@@ -62,19 +62,19 @@ void ApplicationModels::writeTo(QXmlStreamWriter* w) const
     w->writeEndElement();
 }
 
-void ApplicationModels::readFrom(QXmlStreamReader* r, MessageService* messageService)
+void ApplicationModels::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
 {
     try {
         QString tag = r->name().toString();
 
         // real model
         if (tag == Tag::RealModel) {
-            m_realDataModel->readFrom(r, messageService);
+            m_realDataModel->readFromProject(r, projectDir, messageService);
             XML::gotoEndElementOfTag(r, tag);
 
             // job model
         } else if (tag == Tag::JobModel) {
-            m_jobModel->readFrom(r, messageService);
+            m_jobModel->readFromProject(r, projectDir, messageService);
             XML::gotoEndElementOfTag(r, tag);
         }
     } catch (DeserializationException& ex) {
diff --git a/GUI/Model/Model/ApplicationModels.h b/GUI/Model/Model/ApplicationModels.h
index f6363270aad..eaf1b016246 100644
--- a/GUI/Model/Model/ApplicationModels.h
+++ b/GUI/Model/Model/ApplicationModels.h
@@ -34,7 +34,7 @@ public:
     JobModel* jobModel() const;
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r, MessageService* messageService);
+    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService);
 
     //! Returns all data items
     QVector<DataItem*> dataItems() const;
diff --git a/GUI/Model/Model/JobModel.cpp b/GUI/Model/Model/JobModel.cpp
index 50e3739f215..8e9bb03caf2 100644
--- a/GUI/Model/Model/JobModel.cpp
+++ b/GUI/Model/Model/JobModel.cpp
@@ -147,7 +147,7 @@ void JobModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void JobModel::readFrom(QXmlStreamReader* r, MessageService* messageService /*= 0*/)
+void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService /*= 0*/)
 {
     Q_UNUSED(messageService);
     clear();
diff --git a/GUI/Model/Model/JobModel.h b/GUI/Model/Model/JobModel.h
index d72f9664b60..3bfa5945682 100644
--- a/GUI/Model/Model/JobModel.h
+++ b/GUI/Model/Model/JobModel.h
@@ -48,7 +48,7 @@ public:
     QVector<DataItem*> dataItems() const;
 
     void writeTo(QXmlStreamWriter* w) const override;
-    void readFrom(QXmlStreamReader* r, MessageService* messageService = nullptr) override;
+    void readFromProject(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService = nullptr);
 
     void runJob(JobItem* jobItem);
     void cancelJob(JobItem* jobItem);
diff --git a/GUI/Model/Model/RealModel.cpp b/GUI/Model/Model/RealModel.cpp
index c78dc0de088..7c08c5a1c32 100644
--- a/GUI/Model/Model/RealModel.cpp
+++ b/GUI/Model/Model/RealModel.cpp
@@ -65,7 +65,7 @@ void RealModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void RealModel::readFrom(QXmlStreamReader* r, MessageService* messageService /*= 0*/)
+void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService /*= 0*/)
 {
     Q_UNUSED(messageService);
     clear();
diff --git a/GUI/Model/Model/RealModel.h b/GUI/Model/Model/RealModel.h
index 32a474d800a..ec1a681c5af 100644
--- a/GUI/Model/Model/RealModel.h
+++ b/GUI/Model/Model/RealModel.h
@@ -31,7 +31,7 @@ public:
     QVector<DataItem*> dataItems() const;
     void clear() override;
     void writeTo(QXmlStreamWriter* w) const override;
-    void readFrom(QXmlStreamReader* r, MessageService* messageService = nullptr) override;
+    void readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService = nullptr);
 
     RealItem* createRealItem();
     RealItem* insertSpecularDataItem();
diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp
index 2cf7cb2eec1..791847670e2 100644
--- a/GUI/Model/Project/ProjectDocument.cpp
+++ b/GUI/Model/Project/ProjectDocument.cpp
@@ -391,7 +391,7 @@ ProjectDocument::ReadResult ProjectDocument::readProject(QIODevice* device,
                             m_lastViewActive = XML::readUIntAttribute(&r, XML::Attrib::value);
                             XML::gotoEndElementOfTag(&r, tag);
                         } else
-                            m_applicationModels.readFrom(&r, &messageService);
+                            m_applicationModels.readFrom(&r, projectDir(), &messageService);
                     }
                 }
             }
-- 
GitLab


From 534d16237d017db0dbcfce41f4e0ce0839e9e4f2 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 13 Jan 2023 11:54:20 +0100
Subject: [PATCH 02/10] add exception handling to DataItem::loadDatafield

---
 GUI/Model/Data/DataItem.cpp        | 23 +++++++++++++++--------
 GUI/Model/Data/DataItem.h          |  5 +++--
 GUI/Model/Data/RealItem.cpp        |  8 +++++---
 GUI/Model/Data/RealItem.h          |  3 ++-
 GUI/Model/Job/JobItem.cpp          |  4 ++--
 GUI/Model/Job/JobItem.h            |  6 +++---
 GUI/Model/Model/JobModel.cpp       |  5 ++---
 GUI/Model/Model/RealModel.cpp      |  5 ++---
 GUI/Model/Project/IOService.cpp    |  4 ++--
 GUI/Support/IO/SaveLoadInterface.h |  6 ++++--
 10 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/GUI/Model/Data/DataItem.cpp b/GUI/Model/Data/DataItem.cpp
index 9bd071213af..a961bbbd744 100644
--- a/GUI/Model/Data/DataItem.cpp
+++ b/GUI/Model/Data/DataItem.cpp
@@ -12,11 +12,12 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/Model/Data/DataItem.h"
 #include "Device/IO/IOFactory.h"
+#include "GUI/Model/Data/DataItem.h"
 #include "GUI/Model/Model/SessionXML.h"
 #include "GUI/Support/XML/UtilXML.h"
 #include "GUI/Util/Error.h"
+#include "GUI/Util/MessageService.h"
 
 namespace {
 namespace Tag {
@@ -86,17 +87,23 @@ bool DataItem::containsNonXMLData() const
     return static_cast<bool>(m_datafield);
 }
 
-bool DataItem::loadData(const QString& projectDir)
+QString DataItem::loadDatafield(const QString& projectDir, MessageService* messageService)
 {
+    ASSERT(messageService);
     const QString filename = fileName(projectDir);
-    auto* data = IOFactory::readDatafield(filename.toStdString());
-    if (!data)
-        return false;
-    setDatafield(data);
-    return true;
+    try {
+        auto* data = IOFactory::readDatafield(filename.toStdString());
+        if (!data)
+            throw std::runtime_error("Datafield is not created for file: " + filename.toStdString());
+        setDatafield(data);
+    } catch (const std::exception& ex) {
+        messageService->addWarning(this, QString(ex.what()));
+        return QString(ex.what());
+    }
+    return {};
 }
 
-bool DataItem::saveData(const QString& projectDir)
+bool DataItem::saveDatafield(const QString& projectDir)
 {
     if (!containsNonXMLData())
         return false;
diff --git a/GUI/Model/Data/DataItem.h b/GUI/Model/Data/DataItem.h
index ea4eaae38ae..3897801a2f2 100644
--- a/GUI/Model/Data/DataItem.h
+++ b/GUI/Model/Data/DataItem.h
@@ -26,6 +26,7 @@
 class ComboProperty;
 class ImportDataInfo;
 class InstrumentItem;
+class MessageService;
 
 //! Abstract base class for IntensityDataItem and SpecularDataItem.
 //! Owns one simulated data set of type Datafield.
@@ -55,8 +56,8 @@ public:
     void setFileName(const QString& filename);
     QDateTime lastModified() const override;
     bool containsNonXMLData() const override;
-    bool loadData(const QString& projectDir) override;
-    bool saveData(const QString& projectDir) override;
+    QString loadDatafield(const QString& projectDir, MessageService *messageService) override;
+    bool saveDatafield(const QString& projectDir) override;
 
     void setLastModified(const QDateTime& dtime);
 
diff --git a/GUI/Model/Data/RealItem.cpp b/GUI/Model/Data/RealItem.cpp
index 1f3d9570d4a..4701fed832e 100644
--- a/GUI/Model/Data/RealItem.cpp
+++ b/GUI/Model/Data/RealItem.cpp
@@ -12,11 +12,11 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/Model/Data/RealItem.h"
 #include "Device/Data/DataUtils.h"
 #include "GUI/Model/Data/IntensityDataItem.h"
 #include "GUI/Model/Data/JobItemUtils.h"
 #include "GUI/Model/Data/ProjectionItems.h"
+#include "GUI/Model/Data/RealItem.h"
 #include "GUI/Model/Data/SpecularDataItem.h"
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/Model/Device/MaskItems.h"
@@ -387,8 +387,9 @@ inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, cons
     return item;
 }
 
-void RealItem::readFrom(QXmlStreamReader* r)
+void RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService)
 {
+    ASSERT(messageService);
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
 
@@ -418,7 +419,8 @@ void RealItem::readFrom(QXmlStreamReader* r)
 
             // data
         } else if (tag == Tag::Data) {
-            m_dataItem.reset(readItemToEnd<DataItem>(r, this, tag));
+            m_dataItem.reset(readItemToEnd<DataItem>(r, this, tag));            
+            m_dataItem->loadDatafield(projectDir, messageService);
 
             // native data
         } else if (tag == Tag::NativeData) {
diff --git a/GUI/Model/Data/RealItem.h b/GUI/Model/Data/RealItem.h
index fde384d3edb..ef69c6e6df8 100644
--- a/GUI/Model/Data/RealItem.h
+++ b/GUI/Model/Data/RealItem.h
@@ -24,6 +24,7 @@ class ImportDataInfo;
 class InstrumentItem;
 class IntensityDataItem;
 class MaskContainerItem;
+class MessageService;
 class SpecularDataItem;
 
 //! Provides access to experimental data, for display and fitting.
@@ -102,7 +103,7 @@ public:
     void deserializeBinaryData(const QByteArray& data) override;
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r);
+    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
 
     // other
 
diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index 4d2271982b2..19307957fd0 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -543,7 +543,7 @@ inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, cons
     return item;
 }
 
-void JobItem::readFrom(QXmlStreamReader* r)
+void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -626,7 +626,7 @@ void JobItem::readFrom(QXmlStreamReader* r)
 
             // real item
         } else if (tag == Tag::RealItem) {
-            createRealItem()->readFrom(r);
+            createRealItem()->readFrom(r, projectDir, messageService);
             // jobItem and its realItem have to reference the same instrument
             m_realItem->linkToInstrument(instrumentItem());
             XML::gotoEndElementOfTag(r, tag);
diff --git a/GUI/Model/Job/JobItem.h b/GUI/Model/Job/JobItem.h
index d372c3e4772..0b19a91392f 100644
--- a/GUI/Model/Job/JobItem.h
+++ b/GUI/Model/Job/JobItem.h
@@ -20,7 +20,6 @@
 #include "GUI/Model/Descriptor/SelectionProperty.h"
 #include "GUI/Support/Data/JobStatus.h"
 #include "GUI/Support/Data/SimulationOptionsItem.h"
-
 #include <QDateTime>
 #include <optional>
 
@@ -29,10 +28,11 @@ class FitParameterContainerItem;
 class FitSuiteItem;
 class Instrument2DItem;
 class IntensityDataItem;
-class SampleItem;
+class MessageService;
 class ParameterContainerItem;
 class ParameterTreeItems;
 class RealItem;
+class SampleItem;
 class SimulationResult;
 
 class BA_CORE_API_ JobItem : public JobRealBase {
@@ -133,7 +133,7 @@ public:
     // write/read
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r);
+    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
 
 signals:
     void jobNameChanged(const QString& name);
diff --git a/GUI/Model/Model/JobModel.cpp b/GUI/Model/Model/JobModel.cpp
index 8e9bb03caf2..273853ab236 100644
--- a/GUI/Model/Model/JobModel.cpp
+++ b/GUI/Model/Model/JobModel.cpp
@@ -147,9 +147,8 @@ void JobModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService /*= 0*/)
+void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
 {
-    Q_UNUSED(messageService);
     clear();
 
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
@@ -161,7 +160,7 @@ void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, M
         // job
         if (tag == Tag::Job) {
             auto* jobItem = createJobItem();
-            jobItem->readFrom(r);
+            jobItem->readFrom(r, projectDir, messageService);
             // Create the not stored parameter tuning tree
             ParameterTreeBuilder(jobItem, false).build();
             XML::gotoEndElementOfTag(r, tag);
diff --git a/GUI/Model/Model/RealModel.cpp b/GUI/Model/Model/RealModel.cpp
index 7c08c5a1c32..fda0d60ffc7 100644
--- a/GUI/Model/Model/RealModel.cpp
+++ b/GUI/Model/Model/RealModel.cpp
@@ -65,9 +65,8 @@ void RealModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService /*= 0*/)
+void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
 {
-    Q_UNUSED(messageService);
     clear();
 
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
@@ -78,7 +77,7 @@ void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir,
 
         // real item
         if (tag == Tag::RealData) {
-            createRealItem()->readFrom(r);
+            createRealItem()->readFrom(r, projectDir, messageService);
             XML::gotoEndElementOfTag(r, tag);
 
         } else
diff --git a/GUI/Model/Project/IOService.cpp b/GUI/Model/Project/IOService.cpp
index a85e82f5469..1e676948723 100644
--- a/GUI/Model/Project/IOService.cpp
+++ b/GUI/Model/Project/IOService.cpp
@@ -64,7 +64,7 @@ void DatafieldIOService::saveDataFiles(const QString& projectDir)
 
     for (SaveLoadInterface* item : dataInterfaces()) {
         if (m_history.wasModifiedSinceLastSave(projectDir, item))
-            item->saveData(projectDir);
+            item->saveDatafield(projectDir);
         newHistory.markAsSaved(item);
     }
 
@@ -83,7 +83,7 @@ void DatafieldIOService::loadDataFiles(const QString& projectDir, MessageService
 
     for (SaveLoadInterface* item : dataInterfaces()) {
         try {
-            item->loadData(projectDir);
+            item->loadDatafield(projectDir, messageService);
             newHistory.markAsSaved(item);
             // handling crash of GUI during job run and non-existing file
             if (auto* jobItem = parentJobItem(item)) {
diff --git a/GUI/Support/IO/SaveLoadInterface.h b/GUI/Support/IO/SaveLoadInterface.h
index 912c869e087..10159b308d8 100644
--- a/GUI/Support/IO/SaveLoadInterface.h
+++ b/GUI/Support/IO/SaveLoadInterface.h
@@ -18,6 +18,8 @@
 #include <QDateTime>
 #include <QString>
 
+class MessageService;
+
 //! Abstract base class to handle non-XML data save and load.
 
 //! Inherited (mix-in) by DataItem
@@ -27,10 +29,10 @@ public:
     virtual ~SaveLoadInterface() = default;
 
     //! Loads non-XML data from _projectDir_ and returns success flag.
-    virtual bool loadData(const QString& projectDir) = 0;
+    virtual QString loadDatafield(const QString& projectDir, MessageService *messageService) = 0;
 
     //! Saves non-XML data in _projectDir_ and returns success flag.
-    virtual bool saveData(const QString& projectDir) = 0;
+    virtual bool saveDatafield(const QString& projectDir) = 0;
 
     //! Checks if object owns non-XML data
     virtual bool containsNonXMLData() const = 0;
-- 
GitLab


From 95222c165cd78e4932d7b9f1d5ab2ee9ee947892 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 13 Jan 2023 13:45:24 +0100
Subject: [PATCH 03/10] allow missing datafield files

---
 GUI/View/PlotComparison/FitComparisonWidget.cpp   | 3 ++-
 GUI/View/PlotComparison/FitComparisonWidget1D.cpp | 3 ++-
 GUI/View/Projection/ProjectionsPlot.cpp           | 2 +-
 GUI/View/Toplevel/SimulationView.cpp              | 2 ++
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/GUI/View/PlotComparison/FitComparisonWidget.cpp b/GUI/View/PlotComparison/FitComparisonWidget.cpp
index 80aa4c51805..0bfe7fc2998 100644
--- a/GUI/View/PlotComparison/FitComparisonWidget.cpp
+++ b/GUI/View/PlotComparison/FitComparisonWidget.cpp
@@ -141,7 +141,8 @@ void FitComparisonWidget::connectItems()
 void FitComparisonWidget::updateDiffData()
 {
     ASSERT(simuIntensityDataItem() && diffIntensityDataItem() && realIntensityDataItem());
-    ASSERT(simuIntensityDataItem()->datafield() && realIntensityDataItem()->datafield());
+    if(!simuIntensityDataItem()->datafield() || !realIntensityDataItem()->datafield())
+        return;
 
     diffIntensityDataItem()->setDatafield(DiffUtil::relativeDifferenceField(
         *simuIntensityDataItem()->datafield(), *realIntensityDataItem()->datafield()));
diff --git a/GUI/View/PlotComparison/FitComparisonWidget1D.cpp b/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
index 43e0e7b0886..51476e02df1 100644
--- a/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
+++ b/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
@@ -130,7 +130,8 @@ void FitComparisonWidget1D::connectItems()
 void FitComparisonWidget1D::updateDiffData()
 {
     ASSERT(simuSpecularDataItem() && diffSpecularDataItem() && realSpecularDataItem());
-    ASSERT(simuSpecularDataItem()->datafield() && realSpecularDataItem()->datafield());
+    if(!simuSpecularDataItem()->datafield() || !realSpecularDataItem()->datafield())
+        return;
 
     diffSpecularDataItem()->setDatafield(DiffUtil::relativeDifferenceField(
         *simuSpecularDataItem()->datafield(), *realSpecularDataItem()->datafield()));
diff --git a/GUI/View/Projection/ProjectionsPlot.cpp b/GUI/View/Projection/ProjectionsPlot.cpp
index e35a42b030a..6db63835422 100644
--- a/GUI/View/Projection/ProjectionsPlot.cpp
+++ b/GUI/View/Projection/ProjectionsPlot.cpp
@@ -244,7 +244,7 @@ void ProjectionsPlot::clearAll()
 
 void ProjectionsPlot::setGraphFromItem(QCPGraph* graph, SessionItem* item)
 {
-    if (!intensityItem())
+    if (!intensityItem() || !intensityItem()->datafield())
         return;
 
     std::unique_ptr<Datafield> field;
diff --git a/GUI/View/Toplevel/SimulationView.cpp b/GUI/View/Toplevel/SimulationView.cpp
index a7864ad4dcc..68fb17827fa 100644
--- a/GUI/View/Toplevel/SimulationView.cpp
+++ b/GUI/View/Toplevel/SimulationView.cpp
@@ -229,6 +229,8 @@ QString SimulationView::validateSimulationSetup(bool validateRealData) const
         append("The experimental data does not fit in the selected instrument. Try linking "
                "them in Import Tab.");
 
+    if (!selectedRealItem()->dataItem()->datafield())
+        append("The experimental data does not contain data values.");
     return messages;
 }
 
-- 
GitLab


From 1d83681ba6d614c3b29d2fa8399c27d5071d327f Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 13 Jan 2023 16:20:18 +0100
Subject: [PATCH 04/10] mv reading datafield files to serialization stack

---
 GUI/Model/Data/IntensityDataItem.cpp          |  8 +++--
 GUI/Model/Data/IntensityDataItem.h            |  1 +
 GUI/Model/Data/RealItem.cpp                   | 23 ++++++++++---
 GUI/Model/Data/RealItem.h                     |  2 +-
 GUI/Model/Data/SpecularDataItem.cpp           | 19 +++++++----
 GUI/Model/Job/JobItem.cpp                     | 32 ++++++++++++++++++-
 GUI/Model/Project/IOService.cpp               |  1 -
 GUI/Model/Project/ProjectDocument.cpp         |  2 +-
 .../PlotComparison/FitComparisonWidget.cpp    |  9 ++++--
 GUI/View/Toplevel/SimulationView.cpp          |  5 +--
 10 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/GUI/Model/Data/IntensityDataItem.cpp b/GUI/Model/Data/IntensityDataItem.cpp
index fd33e1ed0d0..09ceb2289ba 100644
--- a/GUI/Model/Data/IntensityDataItem.cpp
+++ b/GUI/Model/Data/IntensityDataItem.cpp
@@ -19,7 +19,6 @@
 #include "GUI/Model/Device/AxesItems.h"
 #include "GUI/Model/Device/MaskItems.h"
 #include "GUI/Model/Device/MaskUnitsConverter.h"
-#include "GUI/Model/Model/SessionXML.h"
 #include "GUI/Support/IO/ImportDataInfo.h"
 #include "GUI/Support/XML/UtilXML.h"
 #include "GUI/Util/Error.h"
@@ -67,8 +66,10 @@ IntensityDataItem::IntensityDataItem()
 }
 
 void IntensityDataItem::setDatafield(Datafield* data)
-{
-    ASSERT(data && "Assertion failed in IntensityDataItem::setDatafield: nullptr data passed");
+{    
+    if (!data)
+        DataItem::setDatafield(data);
+
     if (data->rank() != 2)
         throw Error("Error in IntensityDataItem::setDatafield: cannot handle non-2D data");
     DataItem::setDatafield(data);
@@ -264,6 +265,7 @@ void IntensityDataItem::updateDataRange()
         return;
 
     computeDataRange();
+    emit alignRanges();
 }
 
 void IntensityDataItem::computeDataRange()
diff --git a/GUI/Model/Data/IntensityDataItem.h b/GUI/Model/Data/IntensityDataItem.h
index 190d940a230..98bfd11b992 100644
--- a/GUI/Model/Data/IntensityDataItem.h
+++ b/GUI/Model/Data/IntensityDataItem.h
@@ -119,6 +119,7 @@ signals:
     void projectionCreated();
     void projectionPositionChanged(SessionItem* projection);
     void projectionGone(SessionItem* projection);
+    void alignRanges();
 
 private:
     void updateAxesZoomLevel();
diff --git a/GUI/Model/Data/RealItem.cpp b/GUI/Model/Data/RealItem.cpp
index 4701fed832e..838e11b8d70 100644
--- a/GUI/Model/Data/RealItem.cpp
+++ b/GUI/Model/Data/RealItem.cpp
@@ -28,6 +28,7 @@
 #include "GUI/Support/XML/UtilXML.h"
 #include "GUI/Util/DeserializationException.h"
 #include "GUI/Util/Error.h"
+#include "GUI/Util/MessageService.h"
 
 namespace {
 namespace Tag {
@@ -387,12 +388,13 @@ inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, cons
     return item;
 }
 
-void RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService)
+QString RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService)
 {
     ASSERT(messageService);
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
 
+    QString dataError, nativeDataError;
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
 
@@ -402,7 +404,7 @@ void RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageS
             if (binary_version == 1) {
                 QString valueAsBase64 = r->readElementText(QXmlStreamReader::SkipChildElements);
                 const auto data = QByteArray::fromBase64(
-                    valueAsBase64.toLatin1()); // #baimport add a unit test for this!
+                            valueAsBase64.toLatin1()); // #baimport add a unit test for this!
                 deserializeBinaryData(data);
             }
             XML::gotoEndElementOfTag(r, tag);
@@ -419,14 +421,15 @@ void RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageS
 
             // data
         } else if (tag == Tag::Data) {
-            m_dataItem.reset(readItemToEnd<DataItem>(r, this, tag));            
-            m_dataItem->loadDatafield(projectDir, messageService);
+            m_dataItem.reset(readItemToEnd<DataItem>(r, this, tag));
+            dataError = m_dataItem->loadDatafield(projectDir, messageService);
 
             // native data
         } else if (tag == Tag::NativeData) {
             m_nativeDataItem.reset(readItemToEnd<DataItem>(r, this, tag));
+            nativeDataError == m_nativeDataItem->loadDatafield(projectDir, messageService);
 
-            // native data
+            // native data units
         } else if (tag == Tag::NativeDataUnits) {
             XML::readAttribute(r, XML::Attrib::value, &m_nativeDataUnits);
             XML::gotoEndElementOfTag(r, tag);
@@ -434,6 +437,16 @@ void RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageS
         } else
             r->skipCurrentElement();
     }
+
+    // return error message
+    if(dataError.isEmpty() && nativeDataError.isEmpty())
+        return {};
+    else  if(!dataError.isEmpty() && nativeDataError.isEmpty())
+        return (dataError);
+    else  if(dataError.isEmpty() && !nativeDataError.isEmpty())
+        return (nativeDataError);
+    else
+        return (dataError + "\n" + nativeDataError);
 }
 
 void RealItem::copyTo(RealItem* const realdata_dst) const
diff --git a/GUI/Model/Data/RealItem.h b/GUI/Model/Data/RealItem.h
index ef69c6e6df8..295a58a0b26 100644
--- a/GUI/Model/Data/RealItem.h
+++ b/GUI/Model/Data/RealItem.h
@@ -103,7 +103,7 @@ public:
     void deserializeBinaryData(const QByteArray& data) override;
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
+    QString readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
 
     // other
 
diff --git a/GUI/Model/Data/SpecularDataItem.cpp b/GUI/Model/Data/SpecularDataItem.cpp
index 8b6a3a834b4..d0c78f0448c 100644
--- a/GUI/Model/Data/SpecularDataItem.cpp
+++ b/GUI/Model/Data/SpecularDataItem.cpp
@@ -71,13 +71,13 @@ SpecularDataItem::SpecularDataItem()
 
 void SpecularDataItem::setDatafield(Datafield* data)
 {
-    if (data != nullptr) {
-        if (data->rank() != 1)
-            throw Error("Error in SpecularDataItem::setDatafield: cannot handle non-1D data");
-        DataItem::setDatafield(data);
-        updateAxesZoomLevel();
-    } else
+    if (!data)
         DataItem::setDatafield(data);
+
+    if (data->rank() != 1)
+        throw Error("Error in SpecularDataItem::setDatafield: cannot handle non-1D data");
+    DataItem::setDatafield(data);
+    updateAxesZoomLevel();
 }
 
 double SpecularDataItem::xMin() const
@@ -339,5 +339,10 @@ QPair<double, double> SpecularDataItem::dataRange() const
 
 void SpecularDataItem::resetView()
 {
-    setAxesRangeToData();
+    if(m_datafield)
+        setAxesRangeToData();
+    else {
+        setLowerX(xMin());
+        setUpperX(xMax());
+    }
 }
diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index 19307957fd0..aa0a61f87e7 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -548,6 +548,7 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
 
+    QString realError, simError;
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
 
@@ -626,7 +627,7 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
 
             // real item
         } else if (tag == Tag::RealItem) {
-            createRealItem()->readFrom(r, projectDir, messageService);
+            realError = createRealItem()->readFrom(r, projectDir, messageService);
             // jobItem and its realItem have to reference the same instrument
             m_realItem->linkToInstrument(instrumentItem());
             XML::gotoEndElementOfTag(r, tag);
@@ -634,6 +635,7 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
             // simulated data
         } else if (tag == Tag::SimulatedData) {
             m_simulatedDataItem.reset(readItemToEnd<DataItem>(r, this, Tag::SimulatedData));
+            simError = m_simulatedDataItem->loadDatafield(projectDir, messageService);
 
             // diff data
         } else if (tag == Tag::DiffData) {
@@ -647,6 +649,34 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
         } else
             r->skipCurrentElement();
     }
+
+    QString errorMessage;
+
+    // Handling corrupted file on disk
+    if(!realError.isEmpty() || !simError.isEmpty()) {
+        QString addition;
+        if(!realError.isEmpty() && simError.isEmpty())
+            addition = realError;
+        else  if(realError.isEmpty() && !simError.isEmpty())
+            addition = simError;
+        else
+            addition = realError + "\n" + simError;
+
+        errorMessage = QString("Load of the data from disk failed with '%1'").arg(addition);
+    }
+
+    // Handling crash of GUI during job run and non-existing file
+    if (m_status == JobStatus::Running) {
+        if(errorMessage.isEmpty())
+            errorMessage = "Possible GUI crash while job was running";
+        else
+            errorMessage += "\n. Also possible GUI crashed while job was running";
+    }
+
+    if(!errorMessage.isEmpty()) {
+        setComments(errorMessage);
+        m_status = JobStatus::Failed;
+    }
 }
 
 //! Updates the name of file to store intensity data.
diff --git a/GUI/Model/Project/IOService.cpp b/GUI/Model/Project/IOService.cpp
index 1e676948723..9f4380bf9db 100644
--- a/GUI/Model/Project/IOService.cpp
+++ b/GUI/Model/Project/IOService.cpp
@@ -80,7 +80,6 @@ void DatafieldIOService::saveDataFiles(const QString& projectDir)
 void DatafieldIOService::loadDataFiles(const QString& projectDir, MessageService* messageService)
 {
     DatafieldDirHistory newHistory;
-
     for (SaveLoadInterface* item : dataInterfaces()) {
         try {
             item->loadDatafield(projectDir, messageService);
diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp
index 791847670e2..d6df6574a13 100644
--- a/GUI/Model/Project/ProjectDocument.cpp
+++ b/GUI/Model/Project/ProjectDocument.cpp
@@ -205,7 +205,7 @@ ProjectDocument::ReadResult ProjectDocument::loadProjectFile(const QString& proj
         if (result == ReadResult::error)
             return result;
 
-        m_dataService->loadDataFiles(projectDir(), &messageService);
+//        m_dataService->loadDataFiles(projectDir(), &messageService);
         connectModels();
 
         if (!messageService.warnings().empty())
diff --git a/GUI/View/PlotComparison/FitComparisonWidget.cpp b/GUI/View/PlotComparison/FitComparisonWidget.cpp
index 0bfe7fc2998..7f0602f88d3 100644
--- a/GUI/View/PlotComparison/FitComparisonWidget.cpp
+++ b/GUI/View/PlotComparison/FitComparisonWidget.cpp
@@ -126,10 +126,15 @@ void FitComparisonWidget::connectItems()
                         &DataItem::copyXYRangesFromItem, Qt::UniqueConnection);
 
     // sync Z range between sumulated and real
-    // simu --> real
+    connect(simuIntensityDataItem(), &IntensityDataItem::alignRanges, [=]{
+        GUI::View::RangeUtils::setCommonRangeZ(mainIntensityDataItems());
+    });
+
+    // sync Z range: simu --> real
     connect(simuIntensityDataItem(), &DataItem::updateOtherPlots, realIntensityDataItem(),
             &IntensityDataItem::copyZRangeFromItem, Qt::UniqueConnection);
-    // real --> simu
+
+    // sync Z range: real --> simu
     connect(realIntensityDataItem(), &DataItem::updateOtherPlots, simuIntensityDataItem(),
             &IntensityDataItem::copyZRangeFromItem, Qt::UniqueConnection);
 
diff --git a/GUI/View/Toplevel/SimulationView.cpp b/GUI/View/Toplevel/SimulationView.cpp
index 68fb17827fa..fd4ea1b65c6 100644
--- a/GUI/View/Toplevel/SimulationView.cpp
+++ b/GUI/View/Toplevel/SimulationView.cpp
@@ -229,8 +229,9 @@ QString SimulationView::validateSimulationSetup(bool validateRealData) const
         append("The experimental data does not fit in the selected instrument. Try linking "
                "them in Import Tab.");
 
-    if (!selectedRealItem()->dataItem()->datafield())
-        append("The experimental data does not contain data values.");
+    if (selectedRealItem() &&
+            (!selectedRealItem()->dataItem() || !selectedRealItem()->dataItem()->datafield()))
+        append("The experimental data does not contain values.");
     return messages;
 }
 
-- 
GitLab


From d65a9026d923e1fc65a850c6908fc5b318f34bca Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 13 Jan 2023 18:08:35 +0100
Subject: [PATCH 05/10] clang-format

---
 GUI/Model/Data/DataItem.cpp                       |  5 +++--
 GUI/Model/Data/DataItem.h                         |  2 +-
 GUI/Model/Data/IntensityDataItem.cpp              |  2 +-
 GUI/Model/Data/RealItem.cpp                       | 13 +++++++------
 GUI/Model/Data/RealItem.h                         |  3 ++-
 GUI/Model/Data/SpecularDataItem.cpp               |  2 +-
 GUI/Model/Job/JobItem.cpp                         | 13 +++++++------
 GUI/Model/Job/JobItem.h                           |  2 +-
 GUI/Model/Model/ApplicationModels.cpp             |  3 ++-
 GUI/Model/Model/ApplicationModels.h               |  2 +-
 GUI/Model/Model/JobModel.cpp                      |  3 ++-
 GUI/Model/Model/JobModel.h                        |  3 ++-
 GUI/Model/Model/RealModel.cpp                     |  3 ++-
 GUI/Model/Model/RealModel.h                       |  3 ++-
 GUI/Model/Project/ProjectDocument.cpp             |  2 +-
 GUI/Support/IO/SaveLoadInterface.h                |  2 +-
 GUI/View/PlotComparison/FitComparisonWidget.cpp   |  7 +++----
 GUI/View/PlotComparison/FitComparisonWidget1D.cpp |  2 +-
 GUI/View/Toplevel/SimulationView.cpp              |  4 ++--
 19 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/GUI/Model/Data/DataItem.cpp b/GUI/Model/Data/DataItem.cpp
index a961bbbd744..e9f23ae5f6b 100644
--- a/GUI/Model/Data/DataItem.cpp
+++ b/GUI/Model/Data/DataItem.cpp
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#include "Device/IO/IOFactory.h"
 #include "GUI/Model/Data/DataItem.h"
+#include "Device/IO/IOFactory.h"
 #include "GUI/Model/Model/SessionXML.h"
 #include "GUI/Support/XML/UtilXML.h"
 #include "GUI/Util/Error.h"
@@ -94,7 +94,8 @@ QString DataItem::loadDatafield(const QString& projectDir, MessageService* messa
     try {
         auto* data = IOFactory::readDatafield(filename.toStdString());
         if (!data)
-            throw std::runtime_error("Datafield is not created for file: " + filename.toStdString());
+            throw std::runtime_error("Datafield is not created for file: "
+                                     + filename.toStdString());
         setDatafield(data);
     } catch (const std::exception& ex) {
         messageService->addWarning(this, QString(ex.what()));
diff --git a/GUI/Model/Data/DataItem.h b/GUI/Model/Data/DataItem.h
index 3897801a2f2..7ef567cb42a 100644
--- a/GUI/Model/Data/DataItem.h
+++ b/GUI/Model/Data/DataItem.h
@@ -56,7 +56,7 @@ public:
     void setFileName(const QString& filename);
     QDateTime lastModified() const override;
     bool containsNonXMLData() const override;
-    QString loadDatafield(const QString& projectDir, MessageService *messageService) override;
+    QString loadDatafield(const QString& projectDir, MessageService* messageService) override;
     bool saveDatafield(const QString& projectDir) override;
 
     void setLastModified(const QDateTime& dtime);
diff --git a/GUI/Model/Data/IntensityDataItem.cpp b/GUI/Model/Data/IntensityDataItem.cpp
index 09ceb2289ba..a8f76997042 100644
--- a/GUI/Model/Data/IntensityDataItem.cpp
+++ b/GUI/Model/Data/IntensityDataItem.cpp
@@ -66,7 +66,7 @@ IntensityDataItem::IntensityDataItem()
 }
 
 void IntensityDataItem::setDatafield(Datafield* data)
-{    
+{
     if (!data)
         DataItem::setDatafield(data);
 
diff --git a/GUI/Model/Data/RealItem.cpp b/GUI/Model/Data/RealItem.cpp
index 838e11b8d70..a9fd8908d75 100644
--- a/GUI/Model/Data/RealItem.cpp
+++ b/GUI/Model/Data/RealItem.cpp
@@ -12,11 +12,11 @@
 //
 //  ************************************************************************************************
 
+#include "GUI/Model/Data/RealItem.h"
 #include "Device/Data/DataUtils.h"
 #include "GUI/Model/Data/IntensityDataItem.h"
 #include "GUI/Model/Data/JobItemUtils.h"
 #include "GUI/Model/Data/ProjectionItems.h"
-#include "GUI/Model/Data/RealItem.h"
 #include "GUI/Model/Data/SpecularDataItem.h"
 #include "GUI/Model/Device/InstrumentItems.h"
 #include "GUI/Model/Device/MaskItems.h"
@@ -388,7 +388,8 @@ inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, cons
     return item;
 }
 
-QString RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService)
+QString RealItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
+                           MessageService* messageService)
 {
     ASSERT(messageService);
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
@@ -404,7 +405,7 @@ QString RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, Messa
             if (binary_version == 1) {
                 QString valueAsBase64 = r->readElementText(QXmlStreamReader::SkipChildElements);
                 const auto data = QByteArray::fromBase64(
-                            valueAsBase64.toLatin1()); // #baimport add a unit test for this!
+                    valueAsBase64.toLatin1()); // #baimport add a unit test for this!
                 deserializeBinaryData(data);
             }
             XML::gotoEndElementOfTag(r, tag);
@@ -439,11 +440,11 @@ QString RealItem::readFrom(QXmlStreamReader* r, const QString &projectDir, Messa
     }
 
     // return error message
-    if(dataError.isEmpty() && nativeDataError.isEmpty())
+    if (dataError.isEmpty() && nativeDataError.isEmpty())
         return {};
-    else  if(!dataError.isEmpty() && nativeDataError.isEmpty())
+    else if (!dataError.isEmpty() && nativeDataError.isEmpty())
         return (dataError);
-    else  if(dataError.isEmpty() && !nativeDataError.isEmpty())
+    else if (dataError.isEmpty() && !nativeDataError.isEmpty())
         return (nativeDataError);
     else
         return (dataError + "\n" + nativeDataError);
diff --git a/GUI/Model/Data/RealItem.h b/GUI/Model/Data/RealItem.h
index 295a58a0b26..790c9fd844e 100644
--- a/GUI/Model/Data/RealItem.h
+++ b/GUI/Model/Data/RealItem.h
@@ -103,7 +103,8 @@ public:
     void deserializeBinaryData(const QByteArray& data) override;
 
     void writeTo(QXmlStreamWriter* w) const;
-    QString readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
+    QString readFrom(QXmlStreamReader* r, const QString& projectDir,
+                     MessageService* messageService);
 
     // other
 
diff --git a/GUI/Model/Data/SpecularDataItem.cpp b/GUI/Model/Data/SpecularDataItem.cpp
index d0c78f0448c..d4fbd2da125 100644
--- a/GUI/Model/Data/SpecularDataItem.cpp
+++ b/GUI/Model/Data/SpecularDataItem.cpp
@@ -339,7 +339,7 @@ QPair<double, double> SpecularDataItem::dataRange() const
 
 void SpecularDataItem::resetView()
 {
-    if(m_datafield)
+    if (m_datafield)
         setAxesRangeToData();
     else {
         setLowerX(xMin());
diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index aa0a61f87e7..ebbcf2e5514 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -543,7 +543,8 @@ inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, cons
     return item;
 }
 
-void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
+void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
+                       MessageService* messageService)
 {
     const uint version = XML::readUIntAttribute(r, XML::Attrib::version);
     Q_UNUSED(version)
@@ -653,11 +654,11 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
     QString errorMessage;
 
     // Handling corrupted file on disk
-    if(!realError.isEmpty() || !simError.isEmpty()) {
+    if (!realError.isEmpty() || !simError.isEmpty()) {
         QString addition;
-        if(!realError.isEmpty() && simError.isEmpty())
+        if (!realError.isEmpty() && simError.isEmpty())
             addition = realError;
-        else  if(realError.isEmpty() && !simError.isEmpty())
+        else if (realError.isEmpty() && !simError.isEmpty())
             addition = simError;
         else
             addition = realError + "\n" + simError;
@@ -667,13 +668,13 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageSe
 
     // Handling crash of GUI during job run and non-existing file
     if (m_status == JobStatus::Running) {
-        if(errorMessage.isEmpty())
+        if (errorMessage.isEmpty())
             errorMessage = "Possible GUI crash while job was running";
         else
             errorMessage += "\n. Also possible GUI crashed while job was running";
     }
 
-    if(!errorMessage.isEmpty()) {
+    if (!errorMessage.isEmpty()) {
         setComments(errorMessage);
         m_status = JobStatus::Failed;
     }
diff --git a/GUI/Model/Job/JobItem.h b/GUI/Model/Job/JobItem.h
index 0b19a91392f..62b2e2cd91f 100644
--- a/GUI/Model/Job/JobItem.h
+++ b/GUI/Model/Job/JobItem.h
@@ -133,7 +133,7 @@ public:
     // write/read
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService *messageService);
+    void readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService);
 
 signals:
     void jobNameChanged(const QString& name);
diff --git a/GUI/Model/Model/ApplicationModels.cpp b/GUI/Model/Model/ApplicationModels.cpp
index 637d895aa6d..a211ca70551 100644
--- a/GUI/Model/Model/ApplicationModels.cpp
+++ b/GUI/Model/Model/ApplicationModels.cpp
@@ -62,7 +62,8 @@ void ApplicationModels::writeTo(QXmlStreamWriter* w) const
     w->writeEndElement();
 }
 
-void ApplicationModels::readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
+void ApplicationModels::readFrom(QXmlStreamReader* r, const QString& projectDir,
+                                 MessageService* messageService)
 {
     try {
         QString tag = r->name().toString();
diff --git a/GUI/Model/Model/ApplicationModels.h b/GUI/Model/Model/ApplicationModels.h
index eaf1b016246..761426516a1 100644
--- a/GUI/Model/Model/ApplicationModels.h
+++ b/GUI/Model/Model/ApplicationModels.h
@@ -34,7 +34,7 @@ public:
     JobModel* jobModel() const;
 
     void writeTo(QXmlStreamWriter* w) const;
-    void readFrom(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService);
+    void readFrom(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService);
 
     //! Returns all data items
     QVector<DataItem*> dataItems() const;
diff --git a/GUI/Model/Model/JobModel.cpp b/GUI/Model/Model/JobModel.cpp
index 273853ab236..35877ef7ae6 100644
--- a/GUI/Model/Model/JobModel.cpp
+++ b/GUI/Model/Model/JobModel.cpp
@@ -147,7 +147,8 @@ void JobModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
+void JobModel::readFromProject(QXmlStreamReader* r, const QString& projectDir,
+                               MessageService* messageService)
 {
     clear();
 
diff --git a/GUI/Model/Model/JobModel.h b/GUI/Model/Model/JobModel.h
index 3bfa5945682..3cfe2a69585 100644
--- a/GUI/Model/Model/JobModel.h
+++ b/GUI/Model/Model/JobModel.h
@@ -48,7 +48,8 @@ public:
     QVector<DataItem*> dataItems() const;
 
     void writeTo(QXmlStreamWriter* w) const override;
-    void readFromProject(QXmlStreamReader* r, const QString &projectDir, MessageService* messageService = nullptr);
+    void readFromProject(QXmlStreamReader* r, const QString& projectDir,
+                         MessageService* messageService = nullptr);
 
     void runJob(JobItem* jobItem);
     void cancelJob(JobItem* jobItem);
diff --git a/GUI/Model/Model/RealModel.cpp b/GUI/Model/Model/RealModel.cpp
index fda0d60ffc7..ecfa524c3b7 100644
--- a/GUI/Model/Model/RealModel.cpp
+++ b/GUI/Model/Model/RealModel.cpp
@@ -65,7 +65,8 @@ void RealModel::writeTo(QXmlStreamWriter* w) const
     }
 }
 
-void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService)
+void RealModel::readFromProject(QXmlStreamReader* r, const QString& projectDir,
+                                MessageService* messageService)
 {
     clear();
 
diff --git a/GUI/Model/Model/RealModel.h b/GUI/Model/Model/RealModel.h
index ec1a681c5af..b2d02680a44 100644
--- a/GUI/Model/Model/RealModel.h
+++ b/GUI/Model/Model/RealModel.h
@@ -31,7 +31,8 @@ public:
     QVector<DataItem*> dataItems() const;
     void clear() override;
     void writeTo(QXmlStreamWriter* w) const override;
-    void readFromProject(QXmlStreamReader* r, const QString& projectDir, MessageService* messageService = nullptr);
+    void readFromProject(QXmlStreamReader* r, const QString& projectDir,
+                         MessageService* messageService = nullptr);
 
     RealItem* createRealItem();
     RealItem* insertSpecularDataItem();
diff --git a/GUI/Model/Project/ProjectDocument.cpp b/GUI/Model/Project/ProjectDocument.cpp
index d6df6574a13..32a3bbf49be 100644
--- a/GUI/Model/Project/ProjectDocument.cpp
+++ b/GUI/Model/Project/ProjectDocument.cpp
@@ -205,7 +205,7 @@ ProjectDocument::ReadResult ProjectDocument::loadProjectFile(const QString& proj
         if (result == ReadResult::error)
             return result;
 
-//        m_dataService->loadDataFiles(projectDir(), &messageService);
+        //        m_dataService->loadDataFiles(projectDir(), &messageService);
         connectModels();
 
         if (!messageService.warnings().empty())
diff --git a/GUI/Support/IO/SaveLoadInterface.h b/GUI/Support/IO/SaveLoadInterface.h
index 10159b308d8..d1893fe73a4 100644
--- a/GUI/Support/IO/SaveLoadInterface.h
+++ b/GUI/Support/IO/SaveLoadInterface.h
@@ -29,7 +29,7 @@ public:
     virtual ~SaveLoadInterface() = default;
 
     //! Loads non-XML data from _projectDir_ and returns success flag.
-    virtual QString loadDatafield(const QString& projectDir, MessageService *messageService) = 0;
+    virtual QString loadDatafield(const QString& projectDir, MessageService* messageService) = 0;
 
     //! Saves non-XML data in _projectDir_ and returns success flag.
     virtual bool saveDatafield(const QString& projectDir) = 0;
diff --git a/GUI/View/PlotComparison/FitComparisonWidget.cpp b/GUI/View/PlotComparison/FitComparisonWidget.cpp
index 7f0602f88d3..27c906dbb75 100644
--- a/GUI/View/PlotComparison/FitComparisonWidget.cpp
+++ b/GUI/View/PlotComparison/FitComparisonWidget.cpp
@@ -126,9 +126,8 @@ void FitComparisonWidget::connectItems()
                         &DataItem::copyXYRangesFromItem, Qt::UniqueConnection);
 
     // sync Z range between sumulated and real
-    connect(simuIntensityDataItem(), &IntensityDataItem::alignRanges, [=]{
-        GUI::View::RangeUtils::setCommonRangeZ(mainIntensityDataItems());
-    });
+    connect(simuIntensityDataItem(), &IntensityDataItem::alignRanges,
+            [=] { GUI::View::RangeUtils::setCommonRangeZ(mainIntensityDataItems()); });
 
     // sync Z range: simu --> real
     connect(simuIntensityDataItem(), &DataItem::updateOtherPlots, realIntensityDataItem(),
@@ -146,7 +145,7 @@ void FitComparisonWidget::connectItems()
 void FitComparisonWidget::updateDiffData()
 {
     ASSERT(simuIntensityDataItem() && diffIntensityDataItem() && realIntensityDataItem());
-    if(!simuIntensityDataItem()->datafield() || !realIntensityDataItem()->datafield())
+    if (!simuIntensityDataItem()->datafield() || !realIntensityDataItem()->datafield())
         return;
 
     diffIntensityDataItem()->setDatafield(DiffUtil::relativeDifferenceField(
diff --git a/GUI/View/PlotComparison/FitComparisonWidget1D.cpp b/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
index 51476e02df1..1efbfc8e4a7 100644
--- a/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
+++ b/GUI/View/PlotComparison/FitComparisonWidget1D.cpp
@@ -130,7 +130,7 @@ void FitComparisonWidget1D::connectItems()
 void FitComparisonWidget1D::updateDiffData()
 {
     ASSERT(simuSpecularDataItem() && diffSpecularDataItem() && realSpecularDataItem());
-    if(!simuSpecularDataItem()->datafield() || !realSpecularDataItem()->datafield())
+    if (!simuSpecularDataItem()->datafield() || !realSpecularDataItem()->datafield())
         return;
 
     diffSpecularDataItem()->setDatafield(DiffUtil::relativeDifferenceField(
diff --git a/GUI/View/Toplevel/SimulationView.cpp b/GUI/View/Toplevel/SimulationView.cpp
index fd4ea1b65c6..4900e11898b 100644
--- a/GUI/View/Toplevel/SimulationView.cpp
+++ b/GUI/View/Toplevel/SimulationView.cpp
@@ -229,8 +229,8 @@ QString SimulationView::validateSimulationSetup(bool validateRealData) const
         append("The experimental data does not fit in the selected instrument. Try linking "
                "them in Import Tab.");
 
-    if (selectedRealItem() &&
-            (!selectedRealItem()->dataItem() || !selectedRealItem()->dataItem()->datafield()))
+    if (selectedRealItem()
+        && (!selectedRealItem()->dataItem() || !selectedRealItem()->dataItem()->datafield()))
         append("The experimental data does not contain values.");
     return messages;
 }
-- 
GitLab


From 9dcddd2b223c4db2f7820de01c18ee33f711bac3 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <svechnikovmv@gmail.com>
Date: Mon, 16 Jan 2023 14:18:48 +0100
Subject: [PATCH 06/10] fix setDatafield

---
 GUI/Model/Data/IntensityDataItem.cpp | 17 ++++++++---------
 GUI/Model/Data/SpecularDataItem.cpp  | 12 ++++++------
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/GUI/Model/Data/IntensityDataItem.cpp b/GUI/Model/Data/IntensityDataItem.cpp
index a8f76997042..1c023a99af7 100644
--- a/GUI/Model/Data/IntensityDataItem.cpp
+++ b/GUI/Model/Data/IntensityDataItem.cpp
@@ -67,16 +67,15 @@ IntensityDataItem::IntensityDataItem()
 
 void IntensityDataItem::setDatafield(Datafield* data)
 {
-    if (!data)
+    if (data != nullptr) {
+        if (data->rank() != 2)
+            throw Error("Error in IntensityDataItem::setDatafield: cannot handle non-2D data");
+        DataItem::setDatafield(data);
+        updateAxesZoomLevel();
+        updateAxesLabels();
+        updateDataRange();
+    } else
         DataItem::setDatafield(data);
-
-    if (data->rank() != 2)
-        throw Error("Error in IntensityDataItem::setDatafield: cannot handle non-2D data");
-    DataItem::setDatafield(data);
-
-    updateAxesZoomLevel();
-    updateAxesLabels();
-    updateDataRange();
 }
 
 double IntensityDataItem::xMin() const
diff --git a/GUI/Model/Data/SpecularDataItem.cpp b/GUI/Model/Data/SpecularDataItem.cpp
index d4fbd2da125..f57bb1b27fb 100644
--- a/GUI/Model/Data/SpecularDataItem.cpp
+++ b/GUI/Model/Data/SpecularDataItem.cpp
@@ -71,13 +71,13 @@ SpecularDataItem::SpecularDataItem()
 
 void SpecularDataItem::setDatafield(Datafield* data)
 {
-    if (!data)
+    if (data != nullptr) {
+        if (data->rank() != 1)
+            throw Error("Error in SpecularDataItem::setDatafield: cannot handle non-1D data");
+        DataItem::setDatafield(data);
+        updateAxesZoomLevel();
+    } else
         DataItem::setDatafield(data);
-
-    if (data->rank() != 1)
-        throw Error("Error in SpecularDataItem::setDatafield: cannot handle non-1D data");
-    DataItem::setDatafield(data);
-    updateAxesZoomLevel();
 }
 
 double SpecularDataItem::xMin() const
-- 
GitLab


From a71a3cb691e5b1eb7f524d37b59a0995fcfe1ff4 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <svechnikovmv@gmail.com>
Date: Mon, 16 Jan 2023 14:26:22 +0100
Subject: [PATCH 07/10] typo fix

---
 GUI/Model/Job/JobItem.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index ebbcf2e5514..21254b2fb62 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -666,12 +666,12 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
         errorMessage = QString("Load of the data from disk failed with '%1'").arg(addition);
     }
 
-    // Handling crash of GUI during job run and non-existing file
+    // Handling previous crash of GUI during job run
     if (m_status == JobStatus::Running) {
         if (errorMessage.isEmpty())
             errorMessage = "Possible GUI crash while job was running";
         else
-            errorMessage += "\n. Also possible GUI crashed while job was running";
+            errorMessage += "\n. Also possibly GUI crashed while job was running";
     }
 
     if (!errorMessage.isEmpty()) {
-- 
GitLab


From 4545283f287fd9a2738e69b160251916021539c2 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Tue, 17 Jan 2023 18:33:37 +0100
Subject: [PATCH 08/10] JobItem: rm save/load DiffItem

---
 GUI/Model/Job/JobItem.cpp | 19 ++++---------------
 GUI/Model/Job/JobItem.h   |  2 +-
 2 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index 21254b2fb62..f6ec9db1868 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -56,7 +56,6 @@ const QString Status("Status");
 const QString Progress("Progress");
 const QString RealItem("RealItem");
 const QString SimulatedData("SimulatedData");
-const QString DiffData("DiffData");
 const QString FitSuite("FitSuite");
 
 } // namespace Tag
@@ -354,7 +353,7 @@ DataItem* JobItem::simulatedDataItem()
     return m_simulatedDataItem.get();
 }
 
-void JobItem::createDiffDataItem()
+DataItem* JobItem::createDiffDataItem()
 {
     ASSERT(!diffDataItem());
     m_diffDataItem.reset(createNewDataItem());
@@ -365,6 +364,8 @@ void JobItem::createDiffDataItem()
 
     if (isSpecularJob())
         dynamic_cast<SpecularDataItem*>(diffDataItem())->setDiffPlotStyle();
+
+    return m_diffDataItem.get();
 }
 
 DataItem* JobItem::diffDataItem()
@@ -520,13 +521,6 @@ void JobItem::writeTo(QXmlStreamWriter* w) const
         w->writeEndElement();
     }
 
-    // diff data
-    if (m_diffDataItem) {
-        w->writeStartElement(Tag::DiffData);
-        XML::writeItemAndChildItems(w, m_diffDataItem.get());
-        w->writeEndElement();
-    }
-
     // fit suite
     if (m_fitSuiteItem) {
         w->writeStartElement(Tag::FitSuite);
@@ -629,8 +623,7 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
             // real item
         } else if (tag == Tag::RealItem) {
             realError = createRealItem()->readFrom(r, projectDir, messageService);
-            // jobItem and its realItem have to reference the same instrument
-            m_realItem->linkToInstrument(instrumentItem());
+            createDiffDataItem()->copyXYRangesFromItem(m_realItem->dataItem());
             XML::gotoEndElementOfTag(r, tag);
 
             // simulated data
@@ -638,10 +631,6 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
             m_simulatedDataItem.reset(readItemToEnd<DataItem>(r, this, Tag::SimulatedData));
             simError = m_simulatedDataItem->loadDatafield(projectDir, messageService);
 
-            // diff data
-        } else if (tag == Tag::DiffData) {
-            m_diffDataItem.reset(readItemToEnd<DataItem>(r, this, Tag::DiffData));
-
             // fit suite
         } else if (tag == Tag::FitSuite) {
             createFitSuiteItem()->readFrom(r);
diff --git a/GUI/Model/Job/JobItem.h b/GUI/Model/Job/JobItem.h
index 62b2e2cd91f..00558feac42 100644
--- a/GUI/Model/Job/JobItem.h
+++ b/GUI/Model/Job/JobItem.h
@@ -122,7 +122,7 @@ public:
     IntensityDataItem* intensityDataItem();
     DataItem* simulatedDataItem();
 
-    void createDiffDataItem();
+    DataItem *createDiffDataItem();
     DataItem* diffDataItem();
 
     RealItem* createRealItem();
-- 
GitLab


From 0fa3ebcae3698fd4d9d87f9a2916b411bfce4eae Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Tue, 17 Jan 2023 18:37:34 +0100
Subject: [PATCH 09/10] mv gotoEndElementOfTag to readFrom

---
 GUI/Model/Data/RealItem.cpp | 6 +++---
 GUI/Model/Job/JobItem.cpp   | 5 ++---
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/GUI/Model/Data/RealItem.cpp b/GUI/Model/Data/RealItem.cpp
index a9fd8908d75..d024b90130c 100644
--- a/GUI/Model/Data/RealItem.cpp
+++ b/GUI/Model/Data/RealItem.cpp
@@ -383,9 +383,7 @@ void RealItem::writeTo(QXmlStreamWriter* w) const
 template <class T>
 inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, const QString& tag)
 {
-    T* item = dynamic_cast<T*>(XML::readItemAndChildItems(reader, parent_item, tag));
-    XML::gotoEndElementOfTag(reader, tag);
-    return item;
+    return dynamic_cast<T*>(XML::readItemAndChildItems(reader, parent_item, tag));
 }
 
 QString RealItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
@@ -424,11 +422,13 @@ QString RealItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
         } else if (tag == Tag::Data) {
             m_dataItem.reset(readItemToEnd<DataItem>(r, this, tag));
             dataError = m_dataItem->loadDatafield(projectDir, messageService);
+            XML::gotoEndElementOfTag(r, tag);
 
             // native data
         } else if (tag == Tag::NativeData) {
             m_nativeDataItem.reset(readItemToEnd<DataItem>(r, this, tag));
             nativeDataError == m_nativeDataItem->loadDatafield(projectDir, messageService);
+            XML::gotoEndElementOfTag(r, tag);
 
             // native data units
         } else if (tag == Tag::NativeDataUnits) {
diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp
index f6ec9db1868..5573281ca66 100644
--- a/GUI/Model/Job/JobItem.cpp
+++ b/GUI/Model/Job/JobItem.cpp
@@ -532,9 +532,7 @@ void JobItem::writeTo(QXmlStreamWriter* w) const
 template <class T>
 inline T* readItemToEnd(QXmlStreamReader* reader, SessionItem* parent_item, const QString& tag)
 {
-    T* item = dynamic_cast<T*>(XML::readItemAndChildItems(reader, parent_item, tag));
-    XML::gotoEndElementOfTag(reader, tag);
-    return item;
+    return dynamic_cast<T*>(XML::readItemAndChildItems(reader, parent_item, tag));
 }
 
 void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
@@ -630,6 +628,7 @@ void JobItem::readFrom(QXmlStreamReader* r, const QString& projectDir,
         } else if (tag == Tag::SimulatedData) {
             m_simulatedDataItem.reset(readItemToEnd<DataItem>(r, this, Tag::SimulatedData));
             simError = m_simulatedDataItem->loadDatafield(projectDir, messageService);
+            XML::gotoEndElementOfTag(r, tag);
 
             // fit suite
         } else if (tag == Tag::FitSuite) {
-- 
GitLab


From 1c5db778a22501973cad6040e8ed3feede174744 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Tue, 17 Jan 2023 18:43:53 +0100
Subject: [PATCH 10/10] clang-format

---
 GUI/Model/Job/JobItem.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GUI/Model/Job/JobItem.h b/GUI/Model/Job/JobItem.h
index 00558feac42..9259b5bc290 100644
--- a/GUI/Model/Job/JobItem.h
+++ b/GUI/Model/Job/JobItem.h
@@ -122,7 +122,7 @@ public:
     IntensityDataItem* intensityDataItem();
     DataItem* simulatedDataItem();
 
-    DataItem *createDiffDataItem();
+    DataItem* createDiffDataItem();
     DataItem* diffDataItem();
 
     RealItem* createRealItem();
-- 
GitLab