From b1521e02f9ff800aef5f36a621d5e5e85802018f Mon Sep 17 00:00:00 2001
From: Dmitry Yurov <d.yurov@fz-juelich.de>
Date: Fri, 22 Jun 2018 13:34:23 +0200
Subject: [PATCH] DiffItemController introduced

Redmine: #2051
---
 .../FitWidgets/FitComparisonController.cpp    | 96 ++++++++++++++++++-
 1 file changed, 94 insertions(+), 2 deletions(-)

diff --git a/GUI/coregui/Views/FitWidgets/FitComparisonController.cpp b/GUI/coregui/Views/FitWidgets/FitComparisonController.cpp
index 5d53d1c62c4..ebc5cdd9518 100644
--- a/GUI/coregui/Views/FitWidgets/FitComparisonController.cpp
+++ b/GUI/coregui/Views/FitWidgets/FitComparisonController.cpp
@@ -13,10 +13,29 @@
 // ************************************************************************** //
 
 #include "FitComparisonController.h"
-#include "SessionModel.h"
+#include "AxesItems.h"
+#include "IntensityDataFunctions.h"
 #include "IntensityDataItem.h"
+#include "JobItem.h"
 #include "PropertyRepeater.h"
-#include "AxesItems.h"
+#include "RealDataItem.h"
+#include "SessionModel.h"
+
+class DiffItemController : public QObject
+{
+public:
+    DiffItemController(const QString& data_type, QObject* parent);
+    ~DiffItemController() override;
+    void setItem(JobItem* job_item);
+    void updateDiffData();
+    DataItem* diffItem();
+    void subscribe();
+    void unsubscribe();
+private:
+    JobItem* m_current_item;
+    SessionModel* m_tempIntensityDataModel;
+    DataItem* m_diff_item;
+};
 
 FitComparisonController2D::FitComparisonController2D(QObject* parent)
     : QObject(parent)
@@ -74,3 +93,76 @@ void FitComparisonController2D::createRelativeDifferenceItem()
     m_relativeDiffItem = dynamic_cast<IntensityDataItem*>(
         m_tempIntensityDataModel->insertNewItem(Constants::IntensityDataType));
 }
+
+DiffItemController::DiffItemController(const QString& data_type, QObject* parent)
+    : QObject(parent)
+    , m_current_item(nullptr)
+    , m_tempIntensityDataModel(new SessionModel("TempIntensityDataModel", this))
+    , m_diff_item(dynamic_cast<DataItem*>(m_tempIntensityDataModel->insertNewItem(data_type)))
+{
+    assert(m_diff_item);
+}
+
+DiffItemController::~DiffItemController()
+{
+    unsubscribe();
+}
+
+void DiffItemController::setItem(JobItem* job_item)
+{
+    assert(job_item);
+    if (m_current_item)
+        unsubscribe();
+    m_current_item = job_item;
+    subscribe();
+    updateDiffData();
+}
+
+void DiffItemController::updateDiffData()
+{
+    assert(m_current_item);
+
+    auto sim_data = m_current_item->dataItem();
+    auto real_data = m_current_item->realDataItem()->dataItem();
+    assert(sim_data && real_data);
+
+    if (!sim_data->getOutputData()) // job failed
+        return;
+
+    m_diff_item->setOutputData(IntensityDataFunctions::createRelativeDifferenceData(
+                                   *sim_data->getOutputData(), *real_data->getOutputData())
+                               .release());
+}
+
+DataItem* DiffItemController::diffItem()
+{
+    return m_diff_item;
+}
+
+void DiffItemController::subscribe()
+{
+    if (!m_current_item) {
+        assert(false);
+        return;
+    }
+
+    // on simulation data change
+    m_current_item->dataItem()->mapper()->setOnValueChange([this]() { updateDiffData(); }, this);
+
+    // on diff item units change
+    m_diff_item->mapper()->setOnPropertyChange(
+        [this](const QString& name) {
+            if (name == DataItem::P_AXES_UNITS)
+                m_diff_item->updateAxesUnits(m_current_item->instrumentItem());
+        },
+        this);
+}
+
+void DiffItemController::unsubscribe()
+{
+    if (!m_current_item)
+        return;
+    m_current_item->dataItem()->mapper()->unsubscribe(this);
+    m_diff_item->mapper()->unsubscribe(this);
+    m_current_item = nullptr;
+}
-- 
GitLab