From d5e099050603321cb6b7d07afb9daa0ed409c869 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 13:07:54 +0100
Subject: [PATCH 01/11] GUI instrument editor: show units

---
 GUI/View/Instrument/AlphaScanEditor.cpp |  2 +-
 GUI/View/Instrument/GISASBeamEditor.cpp | 13 +++++++------
 GUI/View/Instrument/ScanEditor.cpp      |  2 +-
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/GUI/View/Instrument/AlphaScanEditor.cpp b/GUI/View/Instrument/AlphaScanEditor.cpp
index 744c1a98aba..f7d31fa9859 100644
--- a/GUI/View/Instrument/AlphaScanEditor.cpp
+++ b/GUI/View/Instrument/AlphaScanEditor.cpp
@@ -20,7 +20,7 @@
 #include "GUI/View/Instrument/DistributionPlot.h"
 
 AlphaScanEditor::AlphaScanEditor(QWidget* parent, GrazingScanItem* item, bool allow_distr)
-    : CollapsibleGroupBox("Grazing angles", parent, item->expandGroupBox)
+    : CollapsibleGroupBox("Grazing angles (deg)", parent, item->expandGroupBox)
     , m_item(item)
 {
     auto* layout = new QHBoxLayout;
diff --git a/GUI/View/Instrument/GISASBeamEditor.cpp b/GUI/View/Instrument/GISASBeamEditor.cpp
index b7098f9773b..e4a7522dcf2 100644
--- a/GUI/View/Instrument/GISASBeamEditor.cpp
+++ b/GUI/View/Instrument/GISASBeamEditor.cpp
@@ -58,20 +58,21 @@ GISASBeamEditor::GISASBeamEditor(QWidget* parent, BeamItem* item)
     layout->addLayout(form);
 
     // Main row: fixed values or distributions for wavelength and angles of incidence
-    auto* wavelengthEditor = new DistributionEditor(
-        "Wavelength", MeanConfig{true}, GUI::ID::Distributions::All, this, item->wavelengthItem());
+    auto* wavelengthEditor =
+        new DistributionEditor("Wavelength (nm)", MeanConfig{true}, GUI::ID::Distributions::All,
+                               this, item->wavelengthItem());
     connect(wavelengthEditor, &DistributionEditor::distributionChanged, this,
             &GISASBeamEditor::dataChanged);
 
     auto* inclinationEditor =
-        new DistributionEditor("Grazing angle", MeanConfig{false}, GUI::ID::Distributions::All,
-                               this, item->beamDistributionItem());
+        new DistributionEditor("Grazing angle (deg)", MeanConfig{false},
+                               GUI::ID::Distributions::All, this, item->beamDistributionItem());
     connect(inclinationEditor, &DistributionEditor::distributionChanged, this,
             &GISASBeamEditor::dataChanged);
 
     auto* azimuthalEditor =
-        new DistributionEditor("Azimuthal angle", MeanConfig{false}, GUI::ID::Distributions::All,
-                               this, item->azimuthalAngleItem());
+        new DistributionEditor("Azimuthal angle (deg)", MeanConfig{false},
+                               GUI::ID::Distributions::All, this, item->azimuthalAngleItem());
     connect(azimuthalEditor, &DistributionEditor::distributionChanged, this,
             &GISASBeamEditor::dataChanged);
 
diff --git a/GUI/View/Instrument/ScanEditor.cpp b/GUI/View/Instrument/ScanEditor.cpp
index 38ec5471759..2a9acedec8e 100644
--- a/GUI/View/Instrument/ScanEditor.cpp
+++ b/GUI/View/Instrument/ScanEditor.cpp
@@ -42,7 +42,7 @@ ScanEditor::ScanEditor(QWidget* parent, ScanItem* item, InstrumentNotifier* ec,
     form->addRow("Intensity:", intensityLineEdit);
 
     auto* wavelengthEditor =
-        new DistributionEditor("Wavelength", MeanConfig{true}, GUI::ID::Distributions::Symmetric,
+        new DistributionEditor("Wavelength (nm)", MeanConfig{true}, GUI::ID::Distributions::Symmetric,
                                this, item->wavelengthItem(), allow_distr);
     layout->addWidget(wavelengthEditor);
 
-- 
GitLab


From 9c2c5a2129913c7c63ff2a27ff46a26714238bb0 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 13:18:58 +0100
Subject: [PATCH 02/11] split DistrSelector from DistrEditor sources

---
 GUI/View/Instrument/AlphaScanEditor.cpp      |   2 +-
 GUI/View/Instrument/DistributionEditor.cpp   | 140 -----------------
 GUI/View/Instrument/DistributionEditor.h     |  59 +-------
 GUI/View/Instrument/DistributionSelector.cpp | 149 +++++++++++++++++++
 GUI/View/Instrument/DistributionSelector.h   |  72 +++++++++
 5 files changed, 226 insertions(+), 196 deletions(-)
 create mode 100644 GUI/View/Instrument/DistributionSelector.cpp
 create mode 100644 GUI/View/Instrument/DistributionSelector.h

diff --git a/GUI/View/Instrument/AlphaScanEditor.cpp b/GUI/View/Instrument/AlphaScanEditor.cpp
index f7d31fa9859..af46f9ebafd 100644
--- a/GUI/View/Instrument/AlphaScanEditor.cpp
+++ b/GUI/View/Instrument/AlphaScanEditor.cpp
@@ -16,7 +16,7 @@
 #include "GUI/Model/Beam/GrazingScanItem.h"
 #include "GUI/Model/Descriptor/DistributionItems.h"
 #include "GUI/View/Device/SphericalAxisForm.h"
-#include "GUI/View/Instrument/DistributionEditor.h"
+#include "GUI/View/Instrument/DistributionSelector.h"
 #include "GUI/View/Instrument/DistributionPlot.h"
 
 AlphaScanEditor::AlphaScanEditor(QWidget* parent, GrazingScanItem* item, bool allow_distr)
diff --git a/GUI/View/Instrument/DistributionEditor.cpp b/GUI/View/Instrument/DistributionEditor.cpp
index 8233c76fd5a..1b3b1335e19 100644
--- a/GUI/View/Instrument/DistributionEditor.cpp
+++ b/GUI/View/Instrument/DistributionEditor.cpp
@@ -15,147 +15,7 @@
 #include "GUI/View/Instrument/DistributionEditor.h"
 #include "GUI/Model/Beam/BeamDistributionItem.h"
 #include "GUI/Model/Descriptor/DistributionItems.h"
-#include "GUI/Support/XML/Backup.h"
 #include "GUI/View/Instrument/DistributionPlot.h"
-#include "GUI/View/Numeric/ComboUtil.h"
-#include "GUI/View/Numeric/DoubleSpinBox.h"
-#include "GUI/View/Numeric/NumWidgetUtil.h"
-#include "GUI/View/Numeric/ScientificSpinBox.h"
-
-//==================================================================================================
-// DistributionSelector
-//==================================================================================================
-
-DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config,
-                                           GUI::ID::Distributions distributions, QWidget* parent,
-                                           BeamDistributionItem* item, bool allow_distr)
-    : QWidget(parent)
-    , m_item(item)
-    , m_meanConfig(std::move(mean_config))
-    , m_distributions(distributions)
-{
-    ASSERT(item);
-    m_formLayout = new QFormLayout(this);
-
-    m_distributionCombo =
-        GUI::Util::createComboBoxFromProperty(item->distributionSelection(), [this](int) {
-            createDistributionWidgets();
-            emit distributionChanged();
-        });
-    m_distributionCombo->setEnabled(allow_distr);
-    m_formLayout->addRow("Distribution:", m_distributionCombo);
-
-    createDistributionWidgets();
-}
-
-void DistributionSelector::createDistributionWidgets()
-{
-    while (m_formLayout->rowCount() > 1)
-        m_formLayout->removeRow(1);
-
-    if (auto* it = dynamic_cast<DistributionCosineItem*>(m_item->distributionItem())) {
-        createMeanSpinBox(it->mean());
-        createSpinBox(it->hwhm());
-        createNumSamplesSpinBox(it);
-    } else if (auto* it = dynamic_cast<DistributionGateItem*>(m_item->distributionItem())) {
-        auto* minSpinbox = createSpinBox(it->minimum());
-        auto* maxSpinbox = createSpinBox(it->maximum());
-        connect(minSpinbox, &DoubleSpinBox::baseValueChanged, [it, maxSpinbox](double d) {
-            if (d > it->maximum()) {
-                it->setMaximum(d);
-                maxSpinbox->updateValue();
-            }
-        });
-        connect(maxSpinbox, &DoubleSpinBox::baseValueChanged, [it, minSpinbox](double d) {
-            if (d < it->minimum()) {
-                it->setMinimum(d);
-                minSpinbox->updateValue();
-            }
-        });
-        createNumSamplesSpinBox(it);
-    } else if (auto* it = dynamic_cast<DistributionGaussianItem*>(m_item->distributionItem())) {
-        createMeanSpinBox(it->mean());
-        createSpinBox(it->standardDeviation());
-        createNumSamplesSpinBox(it);
-        createSpinBox(it->relSamplingWidth());
-    } else if (auto* it = dynamic_cast<DistributionLogNormalItem*>(m_item->distributionItem())) {
-        createSpinBox(it->median());
-        createSpinBox(it->scaleParameter());
-        createNumSamplesSpinBox(it);
-        createSpinBox(it->relSamplingWidth());
-    } else if (auto* it = dynamic_cast<DistributionLorentzItem*>(m_item->distributionItem())) {
-        createMeanSpinBox(it->mean());
-        createSpinBox(it->hwhm());
-        createNumSamplesSpinBox(it);
-        createSpinBox(it->relSamplingWidth());
-    } else if (auto* it = dynamic_cast<DistributionNoneItem*>(m_item->distributionItem())) {
-        createMeanSpinBox(it->mean());
-    } else if (auto* it = dynamic_cast<DistributionTrapezoidItem*>(m_item->distributionItem())) {
-        createSpinBox(it->center());
-        createSpinBox(it->leftWidth());
-        createSpinBox(it->middleWidth());
-        createSpinBox(it->rightWidth());
-        createNumSamplesSpinBox(it);
-    }
-}
-
-void DistributionSelector::createNumSamplesSpinBox(DistributionItem* dist)
-{
-    ASSERT(dist);
-    m_formLayout->addRow("Number of samples:",
-                         GUI::Util::createIntSpinbox([dist] { return dist->numberOfSamples(); },
-                                                     [this, dist](int v) {
-                                                         dist->setNumberOfSamples(v);
-                                                         emit distributionChanged();
-                                                     },
-                                                     RealLimits::lowerLimited(1)));
-}
-
-DoubleSpinBox* DistributionSelector::createSpinBox(DoubleProperty& d)
-{
-    auto* sb = GUI::Util::createDoubleSpinBoxRow(m_formLayout, d);
-    connect(sb, &DoubleSpinBox::baseValueChanged, [this, &d](double v) {
-        d.setValue(v);
-        emit distributionChanged();
-    });
-    return sb;
-}
-
-void DistributionSelector::createMeanSpinBox(DoubleProperty& d)
-{
-    if (m_meanConfig) {
-        if (m_meanConfig->scientific) {
-            auto* sb = GUI::Util::createScientificSpinBox(m_formLayout, d);
-            connect(sb, &ScientificSpinBox::valueChanged, [this, &d](double v) {
-                d.setValue(v);
-                emit distributionChanged();
-            });
-        } else
-            createSpinBox(d);
-    }
-}
-
-BeamDistributionItem* DistributionSelector::item() const
-{
-    return m_item;
-}
-
-GUI::ID::Distributions DistributionSelector::distributions() const
-{
-    return m_distributions;
-}
-
-void DistributionSelector::refresh()
-{
-    QSignalBlocker b(m_distributionCombo);
-    m_distributionCombo->setCurrentIndex(m_item->distributionSelection().currentIndex());
-    createDistributionWidgets();
-}
-
-
-//==================================================================================================
-// DistributionEditor
-//==================================================================================================
 
 DistributionEditor::DistributionEditor(const QString& title,
                                        const std::optional<MeanConfig>& mean_config,
diff --git a/GUI/View/Instrument/DistributionEditor.h b/GUI/View/Instrument/DistributionEditor.h
index 2ddba425638..d64df017310 100644
--- a/GUI/View/Instrument/DistributionEditor.h
+++ b/GUI/View/Instrument/DistributionEditor.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit reflection and scattering
 //
 //! @file      GUI/View/Instrument/DistributionEditor.h
-//! @brief     A widget for selecting a distribution and setting its parameters
+//! @brief     A widget for selecting a distribution and setting its parameters.
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -15,68 +15,17 @@
 #ifndef BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONEDITOR_H
 #define BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONEDITOR_H
 
+#include "GUI/View/Instrument/DistributionSelector.h" // MeanConfig
 #include "GUI/Support/Data/ID.h"
 #include "GUI/View/Widget/GroupBoxes.h"
 #include <optional>
 
 class BeamDistributionItem;
-class DistributionForm;
-class DistributionItem;
 class DistributionPlot;
-class DoubleProperty;
 class DoubleSpinBox;
-class QComboBox;
-class QFormLayout;
-class QSpinBox;
-class QStackedLayout;
-class ScientificSpinBox;
 
-
-//! configuration to control how the user can enter a mean value
-struct MeanConfig {
-    bool scientific; //!< whether to use a scientific number notation
-};
-
-/// Widget for selecting a distribution (combo box) and input of the corresponding values
-/// with respect to the given distribution (e.g. mean and deviation for gauss distribution)
-
-class DistributionSelector : public QWidget {
-    Q_OBJECT
-public:
-    /// \param mean_config controls how the mean value is shown and can be input.
-    ///                    If this parameter is \c nullopt then the mean value can not be input
-    ///                    and only symmetric distributions are provided
-    /// \pre ! mean_config && distributions == Distributions::Symmetric
-    ///      (i.e. the combination of all distributions without mean input is currently not
-    ///       supported)
-    DistributionSelector(std::optional<MeanConfig> mean_config,
-                         GUI::ID::Distributions distributions, QWidget* parent,
-                         BeamDistributionItem* item, bool allow_distr);
-
-    BeamDistributionItem* item() const;
-    GUI::ID::Distributions distributions() const;
-    void refresh();
-
-signals:
-    void distributionChanged();
-
-private:
-    void createDistributionWidgets();
-    void createNumSamplesSpinBox(DistributionItem* dist);
-    DoubleSpinBox* createSpinBox(DoubleProperty& d);
-    void createMeanSpinBox(DoubleProperty& d);
-
-private:
-    BeamDistributionItem* m_item;
-    std::optional<MeanConfig> m_meanConfig;
-    GUI::ID::Distributions m_distributions;
-    QFormLayout* m_formLayout;
-    QComboBox* m_distributionCombo;
-};
-
-
-/// DistributionSelector as above but contained in a GroupBox with a title and a button
-/// to open the distribution dialog
+//! DistributionSelector contained in a GroupBox with a title and a button
+//! to open the distribution dialog
 
 class DistributionEditor : public CollapsibleGroupBox {
     Q_OBJECT
diff --git a/GUI/View/Instrument/DistributionSelector.cpp b/GUI/View/Instrument/DistributionSelector.cpp
new file mode 100644
index 00000000000..1328a3e6f68
--- /dev/null
+++ b/GUI/View/Instrument/DistributionSelector.cpp
@@ -0,0 +1,149 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/View/Instrument/DistributionSelector.cpp
+//! @brief     Implements classes DistributionSelector.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#include "GUI/View/Instrument/DistributionSelector.h"
+#include "GUI/Model/Beam/BeamDistributionItem.h"
+#include "GUI/Model/Descriptor/DistributionItems.h"
+#include "GUI/Support/XML/Backup.h"
+#include "GUI/View/Instrument/DistributionPlot.h"
+#include "GUI/View/Numeric/ComboUtil.h"
+#include "GUI/View/Numeric/DoubleSpinBox.h"
+#include "GUI/View/Numeric/NumWidgetUtil.h"
+#include "GUI/View/Numeric/ScientificSpinBox.h"
+
+DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config,
+                                           GUI::ID::Distributions distributions, QWidget* parent,
+                                           BeamDistributionItem* item, bool allow_distr)
+    : QWidget(parent)
+    , m_item(item)
+    , m_meanConfig(std::move(mean_config))
+    , m_distributions(distributions)
+{
+    ASSERT(item);
+    m_formLayout = new QFormLayout(this);
+
+    m_distributionCombo =
+        GUI::Util::createComboBoxFromProperty(item->distributionSelection(), [this](int) {
+            createDistributionWidgets();
+            emit distributionChanged();
+        });
+    m_distributionCombo->setEnabled(allow_distr);
+    m_formLayout->addRow("Distribution:", m_distributionCombo);
+
+    createDistributionWidgets();
+}
+
+void DistributionSelector::createDistributionWidgets()
+{
+    while (m_formLayout->rowCount() > 1)
+        m_formLayout->removeRow(1);
+
+    if (auto* it = dynamic_cast<DistributionCosineItem*>(m_item->distributionItem())) {
+        createMeanSpinBox(it->mean());
+        createSpinBox(it->hwhm());
+        createNumSamplesSpinBox(it);
+    } else if (auto* it = dynamic_cast<DistributionGateItem*>(m_item->distributionItem())) {
+        auto* minSpinbox = createSpinBox(it->minimum());
+        auto* maxSpinbox = createSpinBox(it->maximum());
+        connect(minSpinbox, &DoubleSpinBox::baseValueChanged, [it, maxSpinbox](double d) {
+            if (d > it->maximum()) {
+                it->setMaximum(d);
+                maxSpinbox->updateValue();
+            }
+        });
+        connect(maxSpinbox, &DoubleSpinBox::baseValueChanged, [it, minSpinbox](double d) {
+            if (d < it->minimum()) {
+                it->setMinimum(d);
+                minSpinbox->updateValue();
+            }
+        });
+        createNumSamplesSpinBox(it);
+    } else if (auto* it = dynamic_cast<DistributionGaussianItem*>(m_item->distributionItem())) {
+        createMeanSpinBox(it->mean());
+        createSpinBox(it->standardDeviation());
+        createNumSamplesSpinBox(it);
+        createSpinBox(it->relSamplingWidth());
+    } else if (auto* it = dynamic_cast<DistributionLogNormalItem*>(m_item->distributionItem())) {
+        createSpinBox(it->median());
+        createSpinBox(it->scaleParameter());
+        createNumSamplesSpinBox(it);
+        createSpinBox(it->relSamplingWidth());
+    } else if (auto* it = dynamic_cast<DistributionLorentzItem*>(m_item->distributionItem())) {
+        createMeanSpinBox(it->mean());
+        createSpinBox(it->hwhm());
+        createNumSamplesSpinBox(it);
+        createSpinBox(it->relSamplingWidth());
+    } else if (auto* it = dynamic_cast<DistributionNoneItem*>(m_item->distributionItem())) {
+        createMeanSpinBox(it->mean());
+    } else if (auto* it = dynamic_cast<DistributionTrapezoidItem*>(m_item->distributionItem())) {
+        createSpinBox(it->center());
+        createSpinBox(it->leftWidth());
+        createSpinBox(it->middleWidth());
+        createSpinBox(it->rightWidth());
+        createNumSamplesSpinBox(it);
+    }
+}
+
+void DistributionSelector::createNumSamplesSpinBox(DistributionItem* dist)
+{
+    ASSERT(dist);
+    m_formLayout->addRow("Number of samples:",
+                         GUI::Util::createIntSpinbox([dist] { return dist->numberOfSamples(); },
+                                                     [this, dist](int v) {
+                                                         dist->setNumberOfSamples(v);
+                                                         emit distributionChanged();
+                                                     },
+                                                     RealLimits::lowerLimited(1)));
+}
+
+DoubleSpinBox* DistributionSelector::createSpinBox(DoubleProperty& d)
+{
+    auto* sb = GUI::Util::createDoubleSpinBoxRow(m_formLayout, d);
+    connect(sb, &DoubleSpinBox::baseValueChanged, [this, &d](double v) {
+        d.setValue(v);
+        emit distributionChanged();
+    });
+    return sb;
+}
+
+void DistributionSelector::createMeanSpinBox(DoubleProperty& d)
+{
+    if (m_meanConfig) {
+        if (m_meanConfig->scientific) {
+            auto* sb = GUI::Util::createScientificSpinBox(m_formLayout, d);
+            connect(sb, &ScientificSpinBox::valueChanged, [this, &d](double v) {
+                d.setValue(v);
+                emit distributionChanged();
+            });
+        } else
+            createSpinBox(d);
+    }
+}
+
+BeamDistributionItem* DistributionSelector::item() const
+{
+    return m_item;
+}
+
+GUI::ID::Distributions DistributionSelector::distributions() const
+{
+    return m_distributions;
+}
+
+void DistributionSelector::refresh()
+{
+    QSignalBlocker b(m_distributionCombo);
+    m_distributionCombo->setCurrentIndex(m_item->distributionSelection().currentIndex());
+    createDistributionWidgets();
+}
diff --git a/GUI/View/Instrument/DistributionSelector.h b/GUI/View/Instrument/DistributionSelector.h
new file mode 100644
index 00000000000..8f22f2db764
--- /dev/null
+++ b/GUI/View/Instrument/DistributionSelector.h
@@ -0,0 +1,72 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/View/Instrument/DistributionSelector.h
+//! @brief     A widget for selecting a distribution and setting its parameters
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#ifndef BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONSELECTOR_H
+#define BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONSELECTOR_H
+
+#include "GUI/Support/Data/ID.h"
+#include <optional>
+#include <QWidget>
+
+class BeamDistributionItem;
+class DistributionItem;
+class DoubleProperty;
+class DoubleSpinBox;
+class QComboBox;
+class QFormLayout;
+class ScientificSpinBox;
+
+
+//! configuration to control how the user can enter a mean value
+struct MeanConfig {
+    bool scientific; //!< whether to use a scientific number notation
+};
+
+/// Widget for selecting a distribution (combo box) and input of the corresponding values
+/// with respect to the given distribution (e.g. mean and deviation for gauss distribution)
+
+class DistributionSelector : public QWidget {
+    Q_OBJECT
+public:
+    /// \param mean_config controls how the mean value is shown and can be input.
+    ///                    If this parameter is \c nullopt then the mean value can not be input
+    ///                    and only symmetric distributions are provided
+    /// \pre ! mean_config && distributions == Distributions::Symmetric
+    ///      (i.e. the combination of all distributions without mean input is currently not
+    ///       supported)
+    DistributionSelector(std::optional<MeanConfig> mean_config,
+                         GUI::ID::Distributions distributions, QWidget* parent,
+                         BeamDistributionItem* item, bool allow_distr);
+
+    BeamDistributionItem* item() const;
+    GUI::ID::Distributions distributions() const;
+    void refresh();
+
+signals:
+    void distributionChanged();
+
+private:
+    void createDistributionWidgets();
+    void createNumSamplesSpinBox(DistributionItem* dist);
+    DoubleSpinBox* createSpinBox(DoubleProperty& d);
+    void createMeanSpinBox(DoubleProperty& d);
+
+    BeamDistributionItem* m_item;
+    std::optional<MeanConfig> m_meanConfig;
+    GUI::ID::Distributions m_distributions;
+    QFormLayout* m_formLayout;
+    QComboBox* m_distributionCombo;
+};
+
+#endif // BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONSELECTOR_H
-- 
GitLab


From 1d60b32d778b1e9ece1fa0d7760e23c24b8e1a25 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 14:49:28 +0100
Subject: [PATCH 03/11] Beam and scan parameters in hbox

---
 GUI/View/Instrument/ScanEditor.cpp | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/GUI/View/Instrument/ScanEditor.cpp b/GUI/View/Instrument/ScanEditor.cpp
index 2a9acedec8e..318b83ffaa5 100644
--- a/GUI/View/Instrument/ScanEditor.cpp
+++ b/GUI/View/Instrument/ScanEditor.cpp
@@ -30,27 +30,32 @@ ScanEditor::ScanEditor(QWidget* parent, ScanItem* item, InstrumentNotifier* ec,
     auto* layout = new QVBoxLayout;
     body()->setLayout(layout);
 
-    auto* form = new QFormLayout();
-    form->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
+    // ... Intensity
+
+    auto* form = new QFormLayout;
     layout->addLayout(form);
+    form->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
     auto* intensityLineEdit = new QLineEdit(this);
+    form->addRow("Intensity:", intensityLineEdit);
     intensityLineEdit->setToolTip("Correction factor for normalized intensity");
     auto* validator = new FixupDoubleValidator(intensityLineEdit);
+    intensityLineEdit->setValidator(validator);
     validator->setNotation(QDoubleValidator::ScientificNotation);
     validator->setRange(0.0, 1e32, 1000);
-    intensityLineEdit->setValidator(validator);
-    form->addRow("Intensity:", intensityLineEdit);
+
+    auto* hLayout = new QHBoxLayout;
+    layout->addLayout(hLayout);
 
     auto* wavelengthEditor =
         new DistributionEditor("Wavelength (nm)", MeanConfig{true}, GUI::ID::Distributions::Symmetric,
                                this, item->wavelengthItem(), allow_distr);
-    layout->addWidget(wavelengthEditor);
+    hLayout->addWidget(wavelengthEditor);
 
     auto* inclinationEditor = new AlphaScanEditor(this, item->grazingScanItem(), allow_distr);
-    layout->addWidget(inclinationEditor);
+    hLayout->addWidget(inclinationEditor);
 
     auto* footprintEditor = new FootprintForm(this, item);
-    layout->addWidget(footprintEditor);
+    hLayout->addWidget(footprintEditor);
 
     intensityLineEdit->setText(QString::number(item->intensity()));
 
-- 
GitLab


From 1c35596feb1ba2f8594029778994c7a40ccc0bd1 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 14:51:21 +0100
Subject: [PATCH 04/11] revert recent addition to style sheet: no min-height
 for spinboxes

---
 GUI/styles/Base.stylesheet | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/GUI/styles/Base.stylesheet b/GUI/styles/Base.stylesheet
index 8c1b7023377..2b22e0b3b01 100644
--- a/GUI/styles/Base.stylesheet
+++ b/GUI/styles/Base.stylesheet
@@ -356,13 +356,6 @@ QScrollBar::sub-line:horizontal
     subcontrol-origin: margin;
 }
 
-QSpinBox,
-QDoubleSpinBox,
-ScientificSpinBox
-{
-    min-height: 30px;
-}
-
 QSpinBox::up-button,
 QDoubleSpinBox::up-button,
 ScientificSpinBox::up-button
-- 
GitLab


From 6db09ef9de2457fcb15c625e24ea1907ae715337 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 15:00:15 +0100
Subject: [PATCH 05/11] rm include

---
 GUI/View/Instrument/DetectorEditor.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/View/Instrument/DetectorEditor.cpp b/GUI/View/Instrument/DetectorEditor.cpp
index 59c43b7747c..b8fa36f3cd3 100644
--- a/GUI/View/Instrument/DetectorEditor.cpp
+++ b/GUI/View/Instrument/DetectorEditor.cpp
@@ -16,7 +16,6 @@
 #include "GUI/Model/Detector/DetectorItem.h"
 #include "GUI/Model/Detector/ResolutionFunctionItems.h"
 #include "GUI/Model/Device/InstrumentItems.h"
-#include "GUI/Support/Tool/LayoutUtil.h"
 #include "GUI/View/Numeric/ComboUtil.h"
 #include "GUI/View/Numeric/DoubleSpinBox.h"
 #include "GUI/View/Numeric/NumWidgetUtil.h"
-- 
GitLab


From 11c3e5f528241960951958e473e2d0b7006e5b80 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 15:07:22 +0100
Subject: [PATCH 06/11] new std init order

---
 GUI/View/Instrument/DetectorEditor.cpp | 37 +++++++++++++-------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/GUI/View/Instrument/DetectorEditor.cpp b/GUI/View/Instrument/DetectorEditor.cpp
index b8fa36f3cd3..f29bf39fa30 100644
--- a/GUI/View/Instrument/DetectorEditor.cpp
+++ b/GUI/View/Instrument/DetectorEditor.cpp
@@ -59,18 +59,23 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
 
     //... x-axis controls
 
+    auto* xAxisGroupBox = new StaticGroupBox("X axis", this);
+    xyrow->addWidget(xAxisGroupBox);
+
     auto* xAxisFormLayout = new QFormLayout;
+    xAxisGroupBox->body()->setLayout(xAxisFormLayout);
 
     auto* xAxisNbinsSpinBox = new SafeSpinBox;
+    xAxisFormLayout->addRow("# bins:", xAxisNbinsSpinBox);
     xAxisNbinsSpinBox->setRange(1, 65536);
     xAxisNbinsSpinBox->setValue(detectorItem->xSize());
     connect(xAxisNbinsSpinBox, &QSpinBox::valueChanged, [this, detectorItem](int newValue) {
         detectorItem->setXSize(newValue);
         emit dataChanged();
     });
-    xAxisFormLayout->addRow("# bins:", xAxisNbinsSpinBox);
 
     auto* widthSpinBox = new DoubleSpinBox(detectorItem->width());
+
     connect(widthSpinBox, &DoubleSpinBox::baseValueChanged, [this, detectorItem](double newValue) {
         detectorItem->setWidth(newValue);
         emit dataChanged();
@@ -79,43 +84,40 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
 
     ::createSpinBox(xAxisFormLayout, detectorItem->u0(), this);
 
-    auto* xAxisGroupBox = new StaticGroupBox("X axis", this);
-    xAxisGroupBox->body()->setLayout(xAxisFormLayout);
-    xyrow->addWidget(xAxisGroupBox);
-
     //... y-axis controls
 
+    auto* yAxisGroupBox = new StaticGroupBox("Y axis", this);
+    xyrow->addWidget(yAxisGroupBox);
+
     auto* yAxisFormLayout = new QFormLayout;
+    yAxisGroupBox->body()->setLayout(yAxisFormLayout);
 
     auto* yAxisNbinsSpinBox = new SafeSpinBox;
+    yAxisFormLayout->addRow("# bins:", yAxisNbinsSpinBox);
     yAxisNbinsSpinBox->setRange(1, 65536);
     yAxisNbinsSpinBox->setValue(detectorItem->ySize());
     connect(yAxisNbinsSpinBox, &QSpinBox::valueChanged, [this, detectorItem](int newValue) {
         detectorItem->setYSize(newValue);
         emit dataChanged();
     });
-    yAxisFormLayout->addRow("# bins:", yAxisNbinsSpinBox);
 
     auto* heightSpinBox = new DoubleSpinBox(detectorItem->height());
+    yAxisFormLayout->addRow("Height (mm):", heightSpinBox);
     connect(heightSpinBox, &DoubleSpinBox::baseValueChanged, [this, detectorItem](double newValue) {
         detectorItem->setHeight(newValue);
         emit dataChanged();
     });
-    yAxisFormLayout->addRow("Height (mm):", heightSpinBox);
 
     ::createSpinBox(yAxisFormLayout, detectorItem->v0(), this);
 
-    auto* yAxisGroupBox = new StaticGroupBox("Y axis", this);
-    yAxisGroupBox->body()->setLayout(yAxisFormLayout);
-    xyrow->addWidget(yAxisGroupBox);
-
     //... resolution controls
 
-    auto resolutionLayout = new QFormLayout;
-    resolutionLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
-
     auto* resolutionForm = new StaticGroupBox("Resolution function", this);
+    xyrow->addWidget(resolutionForm);
+
+    auto resolutionLayout = new QFormLayout;
     resolutionForm->body()->setLayout(resolutionLayout);
+    resolutionLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
 
     auto updateResolutionForm = [parent = this, layout = resolutionLayout,
                                  item = detectorItem]() -> void {
@@ -148,14 +150,13 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
 
     updateResolutionForm();
 
-    xyrow->addWidget(resolutionForm);
-
     //... detector alignment controls
 
     auto* aliLine = new QHBoxLayout;
     layout->addLayout(aliLine);
 
     QFormLayout* alignmentForm = new QFormLayout;
+    aliLine->addLayout(alignmentForm);
     alignmentForm->addRow("Alignment:",
                           GUI::Util::createSafeComboBox(
                               [detectorItem] { return detectorItem->detectorAlignmentCombo(); },
@@ -163,9 +164,9 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
                                   detectorItem->setDetectorAlignment(t);
                                   emit dataChanged();
                               }));
-    aliLine->addLayout(alignmentForm);
 
     auto* detposLayout = new QFormLayout;
-    createSpinBox(detposLayout, detectorItem->distance(), this);
     aliLine->addLayout(detposLayout);
+
+    ::createSpinBox(detposLayout, detectorItem->distance(), this);
 }
-- 
GitLab


From eb9d39731a818cd3a4a1da6df8d289b6f4024d41 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 15:15:39 +0100
Subject: [PATCH 07/11] + local var

---
 GUI/View/Instrument/AlphaScanEditor.cpp    |  2 +-
 GUI/View/Instrument/DetectorEditor.cpp     | 19 ++++++++++---------
 GUI/View/Instrument/DistributionEditor.h   |  2 +-
 GUI/View/Instrument/DistributionSelector.h |  2 +-
 GUI/View/Instrument/ScanEditor.cpp         |  6 +++---
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/GUI/View/Instrument/AlphaScanEditor.cpp b/GUI/View/Instrument/AlphaScanEditor.cpp
index af46f9ebafd..eecbfd42b3f 100644
--- a/GUI/View/Instrument/AlphaScanEditor.cpp
+++ b/GUI/View/Instrument/AlphaScanEditor.cpp
@@ -16,8 +16,8 @@
 #include "GUI/Model/Beam/GrazingScanItem.h"
 #include "GUI/Model/Descriptor/DistributionItems.h"
 #include "GUI/View/Device/SphericalAxisForm.h"
-#include "GUI/View/Instrument/DistributionSelector.h"
 #include "GUI/View/Instrument/DistributionPlot.h"
+#include "GUI/View/Instrument/DistributionSelector.h"
 
 AlphaScanEditor::AlphaScanEditor(QWidget* parent, GrazingScanItem* item, bool allow_distr)
     : CollapsibleGroupBox("Grazing angles (deg)", parent, item->expandGroupBox)
diff --git a/GUI/View/Instrument/DetectorEditor.cpp b/GUI/View/Instrument/DetectorEditor.cpp
index f29bf39fa30..212a7410d6f 100644
--- a/GUI/View/Instrument/DetectorEditor.cpp
+++ b/GUI/View/Instrument/DetectorEditor.cpp
@@ -155,15 +155,16 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
     auto* aliLine = new QHBoxLayout;
     layout->addLayout(aliLine);
 
-    QFormLayout* alignmentForm = new QFormLayout;
-    aliLine->addLayout(alignmentForm);
-    alignmentForm->addRow("Alignment:",
-                          GUI::Util::createSafeComboBox(
-                              [detectorItem] { return detectorItem->detectorAlignmentCombo(); },
-                              [this, detectorItem](const QString& t) {
-                                  detectorItem->setDetectorAlignment(t);
-                                  emit dataChanged();
-                              }));
+    auto* aliForm = new QFormLayout;
+    aliLine->addLayout(aliForm);
+
+    auto* aliCombo = GUI::Util::createSafeComboBox(
+        [detectorItem] { return detectorItem->detectorAlignmentCombo(); },
+        [this, detectorItem](const QString& t) {
+            detectorItem->setDetectorAlignment(t);
+            emit dataChanged();
+        });
+    aliForm->addRow("Alignment:", aliCombo);
 
     auto* detposLayout = new QFormLayout;
     aliLine->addLayout(detposLayout);
diff --git a/GUI/View/Instrument/DistributionEditor.h b/GUI/View/Instrument/DistributionEditor.h
index d64df017310..95e096efed7 100644
--- a/GUI/View/Instrument/DistributionEditor.h
+++ b/GUI/View/Instrument/DistributionEditor.h
@@ -15,8 +15,8 @@
 #ifndef BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONEDITOR_H
 #define BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONEDITOR_H
 
-#include "GUI/View/Instrument/DistributionSelector.h" // MeanConfig
 #include "GUI/Support/Data/ID.h"
+#include "GUI/View/Instrument/DistributionSelector.h" // MeanConfig
 #include "GUI/View/Widget/GroupBoxes.h"
 #include <optional>
 
diff --git a/GUI/View/Instrument/DistributionSelector.h b/GUI/View/Instrument/DistributionSelector.h
index 8f22f2db764..dc3f94cf7b7 100644
--- a/GUI/View/Instrument/DistributionSelector.h
+++ b/GUI/View/Instrument/DistributionSelector.h
@@ -16,8 +16,8 @@
 #define BORNAGAIN_GUI_VIEW_INSTRUMENT_DISTRIBUTIONSELECTOR_H
 
 #include "GUI/Support/Data/ID.h"
-#include <optional>
 #include <QWidget>
+#include <optional>
 
 class BeamDistributionItem;
 class DistributionItem;
diff --git a/GUI/View/Instrument/ScanEditor.cpp b/GUI/View/Instrument/ScanEditor.cpp
index 318b83ffaa5..81baff39f4a 100644
--- a/GUI/View/Instrument/ScanEditor.cpp
+++ b/GUI/View/Instrument/ScanEditor.cpp
@@ -46,9 +46,9 @@ ScanEditor::ScanEditor(QWidget* parent, ScanItem* item, InstrumentNotifier* ec,
     auto* hLayout = new QHBoxLayout;
     layout->addLayout(hLayout);
 
-    auto* wavelengthEditor =
-        new DistributionEditor("Wavelength (nm)", MeanConfig{true}, GUI::ID::Distributions::Symmetric,
-                               this, item->wavelengthItem(), allow_distr);
+    auto* wavelengthEditor = new DistributionEditor("Wavelength (nm)", MeanConfig{true},
+                                                    GUI::ID::Distributions::Symmetric, this,
+                                                    item->wavelengthItem(), allow_distr);
     hLayout->addWidget(wavelengthEditor);
 
     auto* inclinationEditor = new AlphaScanEditor(this, item->grazingScanItem(), allow_distr);
-- 
GitLab


From 5c2170974c8fe5582644f55d09d3115b8b6a6671 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 15:53:12 +0100
Subject: [PATCH 08/11] merge fcts -> GUI::Util::createComboBox

---
 GUI/View/Data/IntensityDataPropertyWidget.cpp   |  2 +-
 GUI/View/FitControl/MinimizerSettingsWidget.cpp |  4 ++--
 GUI/View/Instrument/DetectorEditor.cpp          | 13 +++++++------
 GUI/View/Numeric/ComboUtil.cpp                  | 15 ++++-----------
 GUI/View/Numeric/ComboUtil.h                    | 15 +++++----------
 5 files changed, 19 insertions(+), 30 deletions(-)

diff --git a/GUI/View/Data/IntensityDataPropertyWidget.cpp b/GUI/View/Data/IntensityDataPropertyWidget.cpp
index ad149622d80..33f9a469814 100644
--- a/GUI/View/Data/IntensityDataPropertyWidget.cpp
+++ b/GUI/View/Data/IntensityDataPropertyWidget.cpp
@@ -73,7 +73,7 @@ void IntensityDataPropertyWidget::createPanelElements()
                                           item->setCurrentGradient(newVal);
                                       gProjectDocument.value()->setModified();
                                   },
-                                  &m_updaters));
+                                  false, &m_updaters));
 
     m_mainLayout->addRow(GUI::Util::createCheckBox(
         "Interpolate", [this] { return currentData2DItem()->isInterpolated(); },
diff --git a/GUI/View/FitControl/MinimizerSettingsWidget.cpp b/GUI/View/FitControl/MinimizerSettingsWidget.cpp
index 3627bde25b2..67e6d9182f0 100644
--- a/GUI/View/FitControl/MinimizerSettingsWidget.cpp
+++ b/GUI/View/FitControl/MinimizerSettingsWidget.cpp
@@ -61,7 +61,7 @@ void MinimizerSettingsWidget::setMinContainerItem(MinimizerContainerItem* contai
                                  m_containerItem->setCurrentObjectiveMetric(t);
                                  gProjectDocument.value()->setModified();
                              },
-                             &m_updaters,
+                             false, &m_updaters,
                              "Objective metric to use for estimating distance between simulated "
                              "and experimental data"));
     m_mainLayout->addRow("Norm function:",
@@ -71,7 +71,7 @@ void MinimizerSettingsWidget::setMinContainerItem(MinimizerContainerItem* contai
                                  m_containerItem->setCurrentNormFunction(t);
                                  gProjectDocument.value()->setModified();
                              },
-                             &m_updaters,
+                             false, &m_updaters,
                              "Normalization to use for estimating distance between simulated and "
                              "experimental data"));
 
diff --git a/GUI/View/Instrument/DetectorEditor.cpp b/GUI/View/Instrument/DetectorEditor.cpp
index 212a7410d6f..3a2984c9034 100644
--- a/GUI/View/Instrument/DetectorEditor.cpp
+++ b/GUI/View/Instrument/DetectorEditor.cpp
@@ -158,12 +158,13 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
     auto* aliForm = new QFormLayout;
     aliLine->addLayout(aliForm);
 
-    auto* aliCombo = GUI::Util::createSafeComboBox(
-        [detectorItem] { return detectorItem->detectorAlignmentCombo(); },
-        [this, detectorItem](const QString& t) {
-            detectorItem->setDetectorAlignment(t);
-            emit dataChanged();
-        });
+    auto* aliCombo =
+        GUI::Util::createComboBox([detectorItem] { return detectorItem->detectorAlignmentCombo(); },
+                                  [this, detectorItem](const QString& t) {
+                                      detectorItem->setDetectorAlignment(t);
+                                      emit dataChanged();
+                                  },
+                                  true);
     aliForm->addRow("Alignment:", aliCombo);
 
     auto* detposLayout = new QFormLayout;
diff --git a/GUI/View/Numeric/ComboUtil.cpp b/GUI/View/Numeric/ComboUtil.cpp
index 43b2653d6d9..885a1af0caf 100644
--- a/GUI/View/Numeric/ComboUtil.cpp
+++ b/GUI/View/Numeric/ComboUtil.cpp
@@ -21,9 +21,8 @@
 using std::function;
 
 QComboBox* GUI::Util::createComboBox(function<ComboProperty()> comboFunction,
-                                     function<void(const QString&)> slot,
-                                     QList<function<void()>>* updaters, QString tooltip,
-                                     bool isScrollable)
+                                     function<void(const QString&)> slot, bool inScrollArea,
+                                     QList<function<void()>>* updaters, QString tooltip)
 {
     QComboBox* combo = new QComboBox;
     combo->addItems(comboFunction().values());
@@ -35,7 +34,8 @@ QComboBox* GUI::Util::createComboBox(function<ComboProperty()> comboFunction,
         for (int index = 0; index < combo->count(); index++)
             combo->setItemData(index, comboFunction().toolTips().at(index), Qt::ToolTipRole);
 
-    if (!isScrollable)
+    if (inScrollArea)
+        // Ignore mouse wheel events, since they may be meant for scrolling at large.
         WheelEventEater::install(combo);
 
     QObject::connect(combo, &QComboBox::currentTextChanged, [=] { slot(combo->currentText()); });
@@ -49,13 +49,6 @@ QComboBox* GUI::Util::createComboBox(function<ComboProperty()> comboFunction,
     return combo;
 }
 
-QComboBox* GUI::Util::createSafeComboBox(function<ComboProperty()> comboFunction,
-                                         function<void(const QString&)> slot,
-                                         QList<function<void()>>* updaters, QString tooltip)
-{
-    return createComboBox(comboFunction, slot, updaters, tooltip, false);
-}
-
 QComboBox* GUI::Util::createUnitsComboBox(const QStringList& list, function<QString()> currentUnits,
                                           function<void(const QString&)> slot,
                                           QList<function<void()>>* updaters, bool isScrollable)
diff --git a/GUI/View/Numeric/ComboUtil.h b/GUI/View/Numeric/ComboUtil.h
index bc56f83c15c..914bdb33070 100644
--- a/GUI/View/Numeric/ComboUtil.h
+++ b/GUI/View/Numeric/ComboUtil.h
@@ -27,20 +27,15 @@ namespace GUI::Util {
 //!
 //! The combo box will be filled with the available options and will get the found tooltips,
 //! the common one and individual for each item. The current text will be just passes to "slot"
-//! function. Furthermore, the combo box can prohibit accidental changes by the mouse wheel.
-//! Otherwise it would be dangerous if the combo is on a scrollable form - unintended and unnoticed
-//! changes would take place when just scrolling through the form.
+//! function.
+//!
+//! If this combox box resides in a scroll area, we ignore mouse wheel events.
 //!
 //! The combo can be updated from outside using "updaters" list.
 //!
 QComboBox* createComboBox(std::function<ComboProperty()> comboFunction,
-                          std::function<void(const QString&)> slot,
-                          QList<std::function<void()>>* updaters = nullptr, QString tooltip = "",
-                          bool isScrollable = true);
-QComboBox* createSafeComboBox(std::function<ComboProperty()> comboFunction,
-                              std::function<void(const QString&)> slot,
-                              QList<std::function<void()>>* updaters = nullptr,
-                              QString tooltip = "");
+                          std::function<void(const QString&)> slot, bool inScrollArea,
+                          QList<std::function<void()>>* updaters = nullptr, QString tooltip = "");
 
 QComboBox* createUnitsComboBox(const QStringList& list, std::function<QString()> currentUnits,
                                std::function<void(const QString&)> slot,
-- 
GitLab


From 784699f702b844ecab4151ab111b4f5134226438 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 16:36:35 +0100
Subject: [PATCH 09/11] unified arg inScrollArea

---
 GUI/View/Device/BackgroundForm.cpp           |  8 +++++---
 GUI/View/Device/FootprintForm.cpp            |  8 +++++---
 GUI/View/Instrument/DetectorEditor.cpp       |  6 ++++--
 GUI/View/Instrument/DistributionSelector.cpp |  8 +++++---
 GUI/View/Numeric/ComboUtil.cpp               | 12 ++++++------
 GUI/View/Numeric/ComboUtil.h                 | 16 ++++++----------
 6 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/GUI/View/Device/BackgroundForm.cpp b/GUI/View/Device/BackgroundForm.cpp
index be97a24f045..bb5f7cd3e9d 100644
--- a/GUI/View/Device/BackgroundForm.cpp
+++ b/GUI/View/Device/BackgroundForm.cpp
@@ -28,11 +28,13 @@ BackgroundForm::BackgroundForm(QWidget* parent, InstrumentItem* instrument)
     m_formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
     body()->setLayout(m_formLayout);
 
-    auto* backgroundTypeCombo =
-        GUI::Util::createComboBoxFromProperty(instrument->backgroundSelection(), [this](int) {
+    auto* backgroundTypeCombo = GUI::Util::createComboBoxFromProperty(
+        instrument->backgroundSelection(),
+        [this](int) {
             createBackgroundWidgets();
             emit dataChanged();
-        });
+        },
+        true);
     m_formLayout->addRow("Background type:", backgroundTypeCombo);
 
     createBackgroundWidgets();
diff --git a/GUI/View/Device/FootprintForm.cpp b/GUI/View/Device/FootprintForm.cpp
index 4afc058c7d6..cb821387f9a 100644
--- a/GUI/View/Device/FootprintForm.cpp
+++ b/GUI/View/Device/FootprintForm.cpp
@@ -29,11 +29,13 @@ FootprintForm::FootprintForm(QWidget* parent, SourceItem* item)
     body()->setLayout(m_formLayout);
     m_formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
     ASSERT(item->footprintSelection().currentItem());
-    auto* typeCombo =
-        GUI::Util::createComboBoxFromProperty(item->footprintSelection(), [this](int) {
+    auto* typeCombo = GUI::Util::createComboBoxFromProperty(
+        item->footprintSelection(),
+        [this](int) {
             updateFootprintWidgets();
             emit dataChanged();
-        });
+        },
+        false);
     m_formLayout->addRow("Type:", typeCombo);
 
     updateFootprintWidgets();
diff --git a/GUI/View/Instrument/DetectorEditor.cpp b/GUI/View/Instrument/DetectorEditor.cpp
index 3a2984c9034..e942cca0d61 100644
--- a/GUI/View/Instrument/DetectorEditor.cpp
+++ b/GUI/View/Instrument/DetectorEditor.cpp
@@ -142,10 +142,12 @@ DetectorEditor::DetectorEditor(QWidget* parent, GISASInstrumentItem* instrItem)
     };
 
     auto* typeCombo = GUI::Util::createComboBoxFromProperty(
-        detectorItem->resolutionFunctionSelection(), [this, updateResolutionForm](int) {
+        detectorItem->resolutionFunctionSelection(),
+        [this, updateResolutionForm](int) {
             updateResolutionForm();
             emit dataChanged();
-        });
+        },
+        false);
     resolutionLayout->addRow("Type:", typeCombo);
 
     updateResolutionForm();
diff --git a/GUI/View/Instrument/DistributionSelector.cpp b/GUI/View/Instrument/DistributionSelector.cpp
index 1328a3e6f68..f2bec183c0b 100644
--- a/GUI/View/Instrument/DistributionSelector.cpp
+++ b/GUI/View/Instrument/DistributionSelector.cpp
@@ -33,11 +33,13 @@ DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config
     ASSERT(item);
     m_formLayout = new QFormLayout(this);
 
-    m_distributionCombo =
-        GUI::Util::createComboBoxFromProperty(item->distributionSelection(), [this](int) {
+    m_distributionCombo = GUI::Util::createComboBoxFromProperty(
+        item->distributionSelection(),
+        [this](int) {
             createDistributionWidgets();
             emit distributionChanged();
-        });
+        },
+        false);
     m_distributionCombo->setEnabled(allow_distr);
     m_formLayout->addRow("Distribution:", m_distributionCombo);
 
diff --git a/GUI/View/Numeric/ComboUtil.cpp b/GUI/View/Numeric/ComboUtil.cpp
index 885a1af0caf..34854e5287f 100644
--- a/GUI/View/Numeric/ComboUtil.cpp
+++ b/GUI/View/Numeric/ComboUtil.cpp
@@ -49,16 +49,16 @@ QComboBox* GUI::Util::createComboBox(function<ComboProperty()> comboFunction,
     return combo;
 }
 
-QComboBox* GUI::Util::createUnitsComboBox(const QStringList& list, function<QString()> currentUnits,
-                                          function<void(const QString&)> slot,
-                                          QList<function<void()>>* updaters, bool isScrollable)
+QComboBox* GUI::Util::createStringComboBox(const QStringList& list, function<QString()> current,
+                                           function<void(const QString&)> slot, bool inScrollArea,
+                                           QList<function<void()>>* updaters)
 {
     QComboBox* combo = new QComboBox;
     combo->addItems(list);
     combo->setMaxCount(list.size());
-    combo->setCurrentText(currentUnits());
+    combo->setCurrentText(current());
 
-    if (!isScrollable)
+    if (inScrollArea)
         WheelEventEater::install(combo);
 
     QObject::connect(combo, &QComboBox::currentTextChanged, [=] { slot(combo->currentText()); });
@@ -66,7 +66,7 @@ QComboBox* GUI::Util::createUnitsComboBox(const QStringList& list, function<QStr
     if (updaters)
         (*updaters) << [=]() {
             QSignalBlocker b(combo);
-            combo->setCurrentText(currentUnits());
+            combo->setCurrentText(current());
         };
 
     return combo;
diff --git a/GUI/View/Numeric/ComboUtil.h b/GUI/View/Numeric/ComboUtil.h
index 914bdb33070..34f6ea8df57 100644
--- a/GUI/View/Numeric/ComboUtil.h
+++ b/GUI/View/Numeric/ComboUtil.h
@@ -32,15 +32,13 @@ namespace GUI::Util {
 //! If this combox box resides in a scroll area, we ignore mouse wheel events.
 //!
 //! The combo can be updated from outside using "updaters" list.
-//!
 QComboBox* createComboBox(std::function<ComboProperty()> comboFunction,
                           std::function<void(const QString&)> slot, bool inScrollArea,
                           QList<std::function<void()>>* updaters = nullptr, QString tooltip = "");
 
-QComboBox* createUnitsComboBox(const QStringList& list, std::function<QString()> currentUnits,
-                               std::function<void(const QString&)> slot,
-                               QList<std::function<void()>>* updaters = nullptr,
-                               bool isScrollable = true);
+QComboBox* createStringComboBox(const QStringList& list, std::function<QString()> current,
+                                std::function<void(const QString&)> slot, bool inScrollArea,
+                                QList<std::function<void()>>* updaters = nullptr);
 
 //! Create a combo box with the information found in a selection property.
 //!
@@ -52,11 +50,9 @@ QComboBox* createUnitsComboBox(const QStringList& list, std::function<QString()>
 //!
 //! Changes in the combobox will be notified to the SelectionProperty already. The additional (and
 //! optional) slot can be used to be notified about an already executed change.
-//!
 template <typename T>
-QComboBox* createComboBoxFromProperty(SelectionProperty<T>& d,
-                                      std::function<void(int)> slot = nullptr,
-                                      bool isScrollable = false)
+QComboBox* createComboBoxFromProperty(SelectionProperty<T>& d, std::function<void(int)> slot,
+                                      bool inScrollArea)
 {
     QComboBox* combo = new QComboBox;
     combo->addItems(d.options());
@@ -64,7 +60,7 @@ QComboBox* createComboBoxFromProperty(SelectionProperty<T>& d,
     combo->setToolTip(d.tooltip());
     combo->setCurrentIndex(d.currentIndex());
 
-    if (!isScrollable)
+    if (inScrollArea)
         WheelEventEater::install(combo);
 
     QObject::connect(combo, &QComboBox::currentIndexChanged, [&d, slot](int index) {
-- 
GitLab


From d61f5521969eb07ce3079816c60463d0adaaf17b Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 16:38:53 +0100
Subject: [PATCH 10/11] rm circular include

---
 GUI/Model/Detector/DetectorItem.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/GUI/Model/Detector/DetectorItem.h b/GUI/Model/Detector/DetectorItem.h
index 1afd8c01382..8342453e7a8 100644
--- a/GUI/Model/Detector/DetectorItem.h
+++ b/GUI/Model/Detector/DetectorItem.h
@@ -18,7 +18,6 @@
 #include "Device/Detector/FlatDetector.h"
 #include "GUI/Model/Descriptor/SelectionProperty.h"
 #include "GUI/Model/Descriptor/VectorProperty.h"
-#include "GUI/Model/Detector/DetectorItem.h"
 #include "GUI/Model/Detector/ResolutionFunctionItemCatalog.h"
 #include "GUI/Model/Mask/MaskItems.h"
 #include "GUI/Support/Data/ComboProperty.h"
-- 
GitLab


From c2e11b083f6fb390ce58a1cdb296721970a3399b Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Fri, 3 Nov 2023 18:29:00 +0100
Subject: [PATCH 11/11] sort-lines

---
 GUI/Model/Beam/SourceItems.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/GUI/Model/Beam/SourceItems.cpp b/GUI/Model/Beam/SourceItems.cpp
index 01b13071806..6328e1f6a2b 100644
--- a/GUI/Model/Beam/SourceItems.cpp
+++ b/GUI/Model/Beam/SourceItems.cpp
@@ -30,15 +30,15 @@ namespace {
 
 namespace Tag {
 
-const QString Intensity("Intensity");
-const QString Wavelength("Wavelength");
 const QString AzimuthalAngle("AzimuthalAngle");
-const QString InclinationAngle("InclinationAngle");
-const QString GrazingScan("GrazingScan");
-const QString Footprint("Footprint");
 const QString BaseData("BaseData");
 const QString ExpandBeamParametersGroupbox("ExpandBeamParametersGroupbox");
 const QString ExpandFootprintGroupbox("ExpandFootprintGroupbox");
+const QString Footprint("Footprint");
+const QString GrazingScan("GrazingScan");
+const QString InclinationAngle("InclinationAngle");
+const QString Intensity("Intensity");
+const QString Wavelength("Wavelength");
 
 } // namespace Tag
 
-- 
GitLab