From 8df46bc265d2f6cdcabee8c31491dd37517bce4c Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 5 May 2023 15:38:07 +0200
Subject: [PATCH] QREDataLoaderProperties catch nullptr

---
 CHANGELOG                                    |  4 ++
 GUI/View/Loaders/QREDataLoader.cpp           | 14 +++---
 GUI/View/Loaders/QREDataLoaderProperties.cpp | 46 +++++++++++++-------
 3 files changed, 43 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 4379ef5f289..3d8e1dc32ce 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+BornAgain-20.3
+  > Hotfix:
+    * Prevent crash in QRE loader (#589)
+
 BornAgain-20.2, released 2023.05.04
   > Hotfix:
     * Correct polarized specular computation without user provided pol matrices (#549)
diff --git a/GUI/View/Loaders/QREDataLoader.cpp b/GUI/View/Loaders/QREDataLoader.cpp
index 62666840a2a..6d312d8d766 100644
--- a/GUI/View/Loaders/QREDataLoader.cpp
+++ b/GUI/View/Loaders/QREDataLoader.cpp
@@ -112,11 +112,12 @@ void QREDataLoader::populateImportSettingsWidget(QWidget* parent)
     m_propertiesWidget->m_ui->linesToSkipEdit->setText(m_importSettings.linesToSkip);
 
     for (const auto dataType : {DataType::Q, DataType::R, DataType::dR}) {
-        m_propertiesWidget->columnSpinBox((int)dataType)
-            ->setValue(m_importSettings.columnDefinitions[dataType].column + 1); // view is 1-based
+        if (QSpinBox* sb = m_propertiesWidget->columnSpinBox((int)dataType))
+            // view is 1-based
+            sb->setValue(m_importSettings.columnDefinitions[dataType].column + 1);
 
-        m_propertiesWidget->factorSpinBox((int)dataType)
-            ->setValue(m_importSettings.columnDefinitions[dataType].factor);
+        if (QDoubleSpinBox* sb = m_propertiesWidget->factorSpinBox((int)dataType))
+            sb->setValue(m_importSettings.columnDefinitions[dataType].factor);
     }
 
     m_propertiesWidget->m_ui->enableErrorCheckBox->setChecked(
@@ -618,7 +619,10 @@ void QREDataLoader::applyImportSettings()
     for (const auto dataType : m_importSettings.columnDefinitions.keys()) {
         auto& colDef = m_importSettings.columnDefinitions[dataType];
 
-        colDef.column = m_propertiesWidget->columnSpinBox((int)dataType)->value() - 1;
+        if (const auto* sb = m_propertiesWidget->columnSpinBox((int)dataType))
+            colDef.column = sb->value() - 1;
+        else
+            ASSERT(false);
         colDef.factor = m_propertiesWidget->factor((int)dataType);
     }
 
diff --git a/GUI/View/Loaders/QREDataLoaderProperties.cpp b/GUI/View/Loaders/QREDataLoaderProperties.cpp
index 57c54ce3f42..8d13bc893f2 100644
--- a/GUI/View/Loaders/QREDataLoaderProperties.cpp
+++ b/GUI/View/Loaders/QREDataLoaderProperties.cpp
@@ -40,17 +40,23 @@ QREDataLoaderProperties::QREDataLoaderProperties()
         // In the following: disable the checkbox before signaling propertyChanged to suppress ghost
         // value changes in case the propertiesChanged signals triggers long calculations (the
         // spinbox would see a timeout in its "pressed"-loop and generate a second value change)
-        connect(columnSpinBox(dataType), QOverload<int>::of(&QSpinBox::valueChanged), [=]() {
-            columnSpinBox(dataType)->setEnabled(false);
+        connect(columnSpinBox(dataType), QOverload<int>::of(&QSpinBox::valueChanged), [&]() {
+            QSpinBox* sb = columnSpinBox(dataType);
+            if (sb)
+                sb->setEnabled(false);
             emit propertiesChanged();
-            columnSpinBox(dataType)->setEnabled(true);
+            if (sb)
+                sb->setEnabled(true);
         });
 
         connect(factorSpinBox(dataType), QOverload<double>::of(&QDoubleSpinBox::valueChanged),
-                [=]() {
-                    factorSpinBox(dataType)->setEnabled(false);
+                [&]() {
+                    QDoubleSpinBox* sb = factorSpinBox(dataType);
+                    if (sb)
+                        sb->setEnabled(false);
                     emit propertiesChanged();
-                    factorSpinBox(dataType)->setEnabled(true);
+                    if (sb)
+                        sb->setEnabled(true);
                 });
     }
 }
@@ -59,8 +65,10 @@ void QREDataLoaderProperties::allowFactors(bool b)
 {
     m_allowFactors = b;
     for (int dataType = 0; dataType < 3; dataType++) {
-        factorLabel(dataType)->setVisible(b);
-        factorSpinBox(dataType)->setVisible(b);
+        if (auto* label = factorLabel(dataType))
+            label->setVisible(b);
+        if (auto* sb = factorSpinBox(dataType))
+            sb->setVisible(b);
     }
 
     updateErrorEnabling(m_ui->enableErrorCheckBox->isChecked());
@@ -68,8 +76,8 @@ void QREDataLoaderProperties::allowFactors(bool b)
 
 double QREDataLoaderProperties::factor(int dataType) const
 {
-    auto* const spinBox = factorSpinBox(dataType);
-    return spinBox->isVisible() ? spinBox->value() : 1.0;
+    auto* const sb = factorSpinBox(dataType);
+    return sb && sb->isVisible() ? sb->value() : 1.0;
 }
 
 void QREDataLoaderProperties::updateErrorEnabling(bool enabled) const
@@ -100,20 +108,26 @@ void QREDataLoaderProperties::onErrorEnablingChanged()
 QSpinBox* QREDataLoaderProperties::columnSpinBox(int dataType) const
 {
     const int lineInLayout = dataType;
-    return dynamic_cast<QSpinBox*>(
-        m_ui->gridLayout->itemAtPosition(lineInLayout, columnColumn)->widget());
+    QLayoutItem* item = m_ui->gridLayout->itemAtPosition(lineInLayout, columnColumn);
+    if (!item)
+        return {};
+    return dynamic_cast<QSpinBox*>(item->widget());
 }
 
 QDoubleSpinBox* QREDataLoaderProperties::factorSpinBox(int dataType) const
 {
     const int lineInLayout = dataType;
-    return dynamic_cast<QDoubleSpinBox*>(
-        m_ui->gridLayout->itemAtPosition(lineInLayout, factorColumn)->widget());
+    QLayoutItem* item = m_ui->gridLayout->itemAtPosition(lineInLayout, factorColumn);
+    if (!item)
+        return {};
+    return dynamic_cast<QDoubleSpinBox*>(item->widget());
 }
 
 QLabel* QREDataLoaderProperties::factorLabel(int dataType) const
 {
     const int lineInLayout = dataType;
-    return dynamic_cast<QLabel*>(
-        m_ui->gridLayout->itemAtPosition(lineInLayout, factorLabelColumn)->widget());
+    QLayoutItem* item = m_ui->gridLayout->itemAtPosition(lineInLayout, factorLabelColumn);
+    if (!item)
+        return {};
+    return dynamic_cast<QLabel*>(item->widget());
 }
-- 
GitLab