From 7b6a6e58d0d567436e20c82dc8ee14b50a9a04c0 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Fri, 18 Feb 2022 12:27:37 +0100 Subject: [PATCH] simplify UI creation --- .../Instrument/DetectorAlignmentEditor.cpp | 85 ++++++------ GUI/View/Instrument/DetectorAlignmentEditor.h | 6 +- GUI/View/Instrument/EnvironmentEditor.cpp | 3 +- .../Instrument/PolarizationAnalysisEditor.cpp | 122 +++++++----------- .../Instrument/PolarizationAnalysisEditor.h | 18 +-- GUI/View/Tool/WidgetUtils.cpp | 6 + GUI/View/Tool/WidgetUtils.h | 5 + 7 files changed, 117 insertions(+), 128 deletions(-) diff --git a/GUI/View/Instrument/DetectorAlignmentEditor.cpp b/GUI/View/Instrument/DetectorAlignmentEditor.cpp index d4a1e31399b..61c2d88fa2b 100644 --- a/GUI/View/Instrument/DetectorAlignmentEditor.cpp +++ b/GUI/View/Instrument/DetectorAlignmentEditor.cpp @@ -14,15 +14,11 @@ #include "GUI/View/Instrument/DetectorAlignmentEditor.h" #include "GUI/Model/Device/RectangularDetectorItem.h" -#include "GUI/Util/ComboProperty.h" #include "GUI/View/Edit/DoubleSpinBox.h" -#include "GUI/View/Instrument/VectorEditor.h" #include "GUI/View/Tool/WidgetUtils.h" #include <QComboBox> -#include <QDoubleSpinBox> #include <QFormLayout> -#include <QGroupBox> -#include <QStackedLayout> +#include <QLabel> namespace { QString alignmentDescription(RectangularDetector::EDetectorArrangement a) @@ -68,7 +64,7 @@ DoubleSpinBox* DetectorAlignmentEditor::createSpinBox(QFormLayout* parentFormLay const DoubleDescriptor& d) { auto* sb = GUI::Util::createSpinBox(parentFormLayout, d); - connect(sb, qOverload<double>(&DoubleSpinBox::baseValueChanged), [=](double v) { + connect(sb, &DoubleSpinBox::baseValueChanged, [=](double v) { if (d.get() != v) { d.set(v); emit dataChanged(); @@ -77,44 +73,59 @@ DoubleSpinBox* DetectorAlignmentEditor::createSpinBox(QFormLayout* parentFormLay return sb; } +DoubleSpinBox* DetectorAlignmentEditor::createSpinBox(QWidget* parent, const DoubleDescriptor& d) +{ + auto* sb = new DoubleSpinBox(parent, d); + connect(sb, &DoubleSpinBox::baseValueChanged, [=](double v) { + if (d.get() != v) { + d.set(v); + emit dataChanged(); + } + }); + return sb; +} + +void DetectorAlignmentEditor::addVector(QFormLayout* parentLayout, const VectorDescriptor& d) +{ + auto* layout = new QHBoxLayout; + + const auto add = [&](const DoubleDescriptor& d) { + layout->addWidget(new QLabel(GUI::Util::labelWithUnit(d) + ":")); + layout->addWidget(createSpinBox(parentLayout->parentWidget(), d)); + }; + + add(d.x); + add(d.y); + add(d.z); + + layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); + + parentLayout->addRow(d.label + ":", layout); +} + void DetectorAlignmentEditor::createAligmentWidgets() { while (m_formLayout->rowCount() > 1) m_formLayout->removeRow(1); const QString descr = alignmentDescription(m_item->detectorAlignment()); + auto* layout = new QFormLayout(this); + layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); + layout->setContentsMargins(0, 0, 0, 0); + m_formLayout->addRow("", layout); + if (m_item->detectorAlignment() == RectangularDetector::GENERIC) { - auto* layout = new QHBoxLayout(this); - auto* gbox = new QGroupBox(descr, this); - auto* form = new QFormLayout(gbox); - - createSpinBox(form, m_item->u0()); - createSpinBox(form, m_item->v0()); - - auto* normalEditor = new VectorEditor( - "Normal vector", - "Normal of the detector plane with length equal to the sample detector distance (%1)", - this); - normalEditor->setVector(m_item->normalVector()); - connect(normalEditor, &VectorEditor::vectorChanged, [=]() { dataChanged(); }); - - auto* directionEditor = new VectorEditor( - "Detector axis direction vector", - "Detector axis direction vector w.r.t. the sample coordinate system (%1)", this); - directionEditor->setVector(m_item->directionVector()); - connect(directionEditor, &VectorEditor::vectorChanged, [=]() { dataChanged(); }); - - layout->addWidget(gbox); - layout->addWidget(normalEditor); - layout->addWidget(directionEditor); - - m_formLayout->addRow(layout); + addVector(layout, m_item->normalVector()); + addVector(layout, m_item->directionVector()); + auto* layoutUV = new QFormLayout; + createSpinBox(layoutUV, m_item->u0()); + createSpinBox(layoutUV, m_item->v0()); + layout->addRow(descr + ":", layoutUV); } else { - auto* gbox = new QGroupBox(descr, this); - auto* form = new QFormLayout(gbox); - createSpinBox(form, m_item->u0()); - createSpinBox(form, m_item->v0()); - createSpinBox(form, m_item->distance()); - m_formLayout->addRow(gbox); + auto* layoutUVD = new QFormLayout; + createSpinBox(layoutUVD, m_item->u0()); + createSpinBox(layoutUVD, m_item->v0()); + createSpinBox(layoutUVD, m_item->distance()); + layout->addRow(descr + ":", layoutUVD); } } diff --git a/GUI/View/Instrument/DetectorAlignmentEditor.h b/GUI/View/Instrument/DetectorAlignmentEditor.h index dd138d0e365..be96d94ec09 100644 --- a/GUI/View/Instrument/DetectorAlignmentEditor.h +++ b/GUI/View/Instrument/DetectorAlignmentEditor.h @@ -16,15 +16,13 @@ #define BORNAGAIN_GUI_VIEW_INSTRUMENT_DETECTORALIGNMENTEDITOR_H #include <QWidget> -#include <array> -class QComboBox; -class QStackedLayout; class DetectorAlignmentForm; class RectangularDetectorItem; class QFormLayout; class DoubleSpinBox; class DoubleDescriptor; +class VectorDescriptor; /// Widget for selecting the alignment of a detector (combo box) and input of the corresponding /// values @@ -40,6 +38,8 @@ signals: private: void createAligmentWidgets(); DoubleSpinBox* createSpinBox(QFormLayout* parentFormLayout, const DoubleDescriptor& d); + DoubleSpinBox* createSpinBox(QWidget* parent, const DoubleDescriptor& d); + void addVector(QFormLayout* parentLayout, const VectorDescriptor& d); private: RectangularDetectorItem* m_item; diff --git a/GUI/View/Instrument/EnvironmentEditor.cpp b/GUI/View/Instrument/EnvironmentEditor.cpp index 2c5a431ae00..b646e578aef 100644 --- a/GUI/View/Instrument/EnvironmentEditor.cpp +++ b/GUI/View/Instrument/EnvironmentEditor.cpp @@ -26,6 +26,7 @@ EnvironmentEditor::EnvironmentEditor(QWidget* parent, InstrumentItem* instrument { ASSERT(instrument); m_formLayout = new QFormLayout(this); + m_formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); auto* backgroundTypeCombo = GUI::Util::createSelectionCombo(this, instrument->backgroundSelection(), [=](int) { @@ -49,7 +50,7 @@ void EnvironmentEditor::createBackgroundWidgets() spinbox->setSingleStep(0.01); m_formLayout->addRow("Background value:", spinbox); - connect(spinbox, qOverload<double>(&DoubleSpinBox::baseValueChanged), [=](double newValue) { + connect(spinbox, &DoubleSpinBox::baseValueChanged, [=](double newValue) { p->setBackgroundValue(newValue); emit dataChanged(); }); diff --git a/GUI/View/Instrument/PolarizationAnalysisEditor.cpp b/GUI/View/Instrument/PolarizationAnalysisEditor.cpp index 5246f09b1ec..0ff106134c2 100644 --- a/GUI/View/Instrument/PolarizationAnalysisEditor.cpp +++ b/GUI/View/Instrument/PolarizationAnalysisEditor.cpp @@ -13,15 +13,13 @@ // ************************************************************************************************ #include "GUI/View/Instrument/PolarizationAnalysisEditor.h" -#include "GUI/Model/Device/DetectorItems.h" #include "GUI/Model/Device/InstrumentItems.h" -#include "GUI/View/Instrument/VectorEditor.h" +#include "GUI/View/Edit/DoubleSpinBox.h" #include "GUI/View/Tool/GroupBoxCollapser.h" +#include "GUI/View/Tool/WidgetUtils.h" #include <QCheckBox> -#include <QDoubleSpinBox> #include <QFormLayout> -#include <QGridLayout> -#include <QGroupBox> +#include <QLabel> PolarizationAnalysisEditor::PolarizationAnalysisEditor(QWidget* parent, InstrumentItem* instrument) : QGroupBox("Polarization analysis", parent) @@ -31,88 +29,60 @@ PolarizationAnalysisEditor::PolarizationAnalysisEditor(QWidget* parent, Instrume auto* layout = new QVBoxLayout(this); - m_checkbox = new QCheckBox("add polarizer and analyzer to instrument"); - m_checkbox->setChecked(m_instrument->withPolarizerAnalyzer()); - layout->addWidget(m_checkbox); + auto* checkbox = new QCheckBox(QString("Enable %1").arg(title())); + checkbox->setChecked(m_instrument->withPolarizerAnalyzer()); + layout->addWidget(checkbox); - m_polarizerAnalyzerWidget = new QWidget(this); - auto* grid = new QGridLayout(m_polarizerAnalyzerWidget); - grid->setContentsMargins(0, 8, 0, 0); + auto* polarizerAnalyzerWidget = new QWidget(this); + auto* formlayout = new QFormLayout(polarizerAnalyzerWidget); + formlayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint); - m_polarizerEditor = new VectorEditor("Polarizer (Bloch vector)", - "Polarization of the beam, given as the Bloch vector (%1)", - m_polarizerAnalyzerWidget); - grid->addWidget(m_polarizerEditor, 0, 0); + addVector(formlayout, m_instrument->polarization()); + addVector(formlayout, m_instrument->analyzerDirection()); + formlayout->addRow(GUI::Util::labelWithUnit(m_instrument->analyzerEfficiency()) + ":", + createSpinBox(polarizerAnalyzerWidget, m_instrument->analyzerEfficiency())); + formlayout->addRow( + GUI::Util::labelWithUnit(m_instrument->analyzerTotalTransmission()) + ":", + createSpinBox(polarizerAnalyzerWidget, m_instrument->analyzerTotalTransmission())); - m_analyzerEditor = - new VectorEditor("Analyzer orientation", "Direction of the polarization analysis (%1)", - m_polarizerAnalyzerWidget); - grid->addWidget(m_analyzerEditor, 0, 1); + layout->addWidget(polarizerAnalyzerWidget); + polarizerAnalyzerWidget->setVisible(m_instrument->withPolarizerAnalyzer()); - auto* propertiesEditor = new QGroupBox("Analyzer properties", m_polarizerAnalyzerWidget); - { - auto* form = new QFormLayout(propertiesEditor); - - auto* m_efficiencySpinbox = new QDoubleSpinBox(propertiesEditor); - m_efficiencySpinbox->setToolTip("Efficiency of the polarization analysis"); - m_efficiencySpinbox->setDecimals(4); - m_efficiencySpinbox->setRange(std::numeric_limits<double>::lowest(), - std::numeric_limits<double>::max()); - form->addRow("Efficiency:", m_efficiencySpinbox); - - auto* m_transmissionSpinbox = new QDoubleSpinBox(propertiesEditor); - m_transmissionSpinbox->setToolTip("Total transmission of the polarization analysis"); - m_transmissionSpinbox->setDecimals(4); - m_transmissionSpinbox->setRange(0, std::numeric_limits<double>::max()); - form->addRow("Transmission:", m_transmissionSpinbox); - - connect(m_efficiencySpinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, - &PolarizationAnalysisEditor::onEfficiencyValueChanged); - connect(m_transmissionSpinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), this, - &PolarizationAnalysisEditor::onTransmissionValueChanged); - m_efficiencySpinbox->setValue(instrument->analyzerEfficiency()); - m_transmissionSpinbox->setValue(instrument->analyzerTotalTransmission()); - } - - - grid->addWidget(propertiesEditor, 0, 2); - layout->addWidget(m_polarizerAnalyzerWidget); - m_polarizerAnalyzerWidget->setEnabled(m_instrument->withPolarizerAnalyzer()); - - m_polarizerEditor->setVector(m_instrument->polarization()); - m_analyzerEditor->setVector(m_instrument->analyzerDirection()); - - connect(m_checkbox, &QCheckBox::toggled, this, &PolarizationAnalysisEditor::onCheckBoxToggled); - connect(m_polarizerEditor, &VectorEditor::vectorChanged, this, - &PolarizationAnalysisEditor::dataChanged); - connect(m_analyzerEditor, &VectorEditor::vectorChanged, this, - &PolarizationAnalysisEditor::dataChanged); + connect(checkbox, &QCheckBox::toggled, [=](bool b) { + polarizerAnalyzerWidget->setVisible(b); + m_instrument->setWithPolarizerAnalyzer(b); + emit dataChanged(); + }); GroupBoxCollapser::installIntoGroupBox(this); } -void PolarizationAnalysisEditor::onCheckBoxToggled() +DoubleSpinBox* PolarizationAnalysisEditor::createSpinBox(QWidget* parent, const DoubleDescriptor& d) { - const bool enabled = m_checkbox->isChecked(); - m_polarizerAnalyzerWidget->setEnabled(enabled); - if (enabled != m_instrument->withPolarizerAnalyzer()) { - m_instrument->setWithPolarizerAnalyzer(enabled); - emit dataChanged(); - } + auto* sb = new DoubleSpinBox(parent, d); + connect(sb, &DoubleSpinBox::baseValueChanged, [=](double v) { + if (d.get() != v) { + d.set(v); + emit dataChanged(); + } + }); + return sb; } -void PolarizationAnalysisEditor::onEfficiencyValueChanged(double efficiency) +void PolarizationAnalysisEditor::addVector(QFormLayout* parentLayout, const VectorDescriptor& d) { - if (m_instrument->analyzerEfficiency() != efficiency) { - m_instrument->setAnalyzerEfficiency(efficiency); - emit dataChanged(); - } -} + auto* layout = new QHBoxLayout; -void PolarizationAnalysisEditor::onTransmissionValueChanged(double transmission) -{ - if (m_instrument->analyzerTotalTransmission() != transmission) { - m_instrument->setAnalyzerTotalTransmission(transmission); - emit dataChanged(); - } + const auto add = [&](const DoubleDescriptor& d) { + layout->addWidget(new QLabel(GUI::Util::labelWithUnit(d) + ":")); + layout->addWidget(createSpinBox(parentLayout->parentWidget(), d)); + }; + + add(d.x); + add(d.y); + add(d.z); + + layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); + + parentLayout->addRow(d.label + ":", layout); } diff --git a/GUI/View/Instrument/PolarizationAnalysisEditor.h b/GUI/View/Instrument/PolarizationAnalysisEditor.h index 20ed7ff7bfa..9bfceca2f0a 100644 --- a/GUI/View/Instrument/PolarizationAnalysisEditor.h +++ b/GUI/View/Instrument/PolarizationAnalysisEditor.h @@ -18,8 +18,10 @@ #include <QGroupBox> class InstrumentItem; -class QCheckBox; -class VectorEditor; +class DoubleSpinBox; +class DoubleDescriptor; +class QFormLayout; +class VectorDescriptor; //! Polarization analysis editor (beam polarization, analyzer properties) for instrument editors. //! Operates on Instrument2DItem. @@ -33,16 +35,10 @@ public: signals: void dataChanged(); -private slots: - void onCheckBoxToggled(); - void onEfficiencyValueChanged(double efficiency); - void onTransmissionValueChanged(double transmission); - private: - QCheckBox* m_checkbox; - QWidget* m_polarizerAnalyzerWidget; - VectorEditor* m_polarizerEditor; - VectorEditor* m_analyzerEditor; + DoubleSpinBox* createSpinBox(QWidget* parent, const DoubleDescriptor& d); + void addVector(QFormLayout* parentLayout, const VectorDescriptor& d); + InstrumentItem* m_instrument; }; diff --git a/GUI/View/Tool/WidgetUtils.cpp b/GUI/View/Tool/WidgetUtils.cpp index 77c3e2b4cd7..21da61ee522 100644 --- a/GUI/View/Tool/WidgetUtils.cpp +++ b/GUI/View/Tool/WidgetUtils.cpp @@ -16,6 +16,7 @@ #include "GUI/Model/Descriptor/UIntDescriptor.h" #include "GUI/View/Edit/DoubleSpinBox.h" #include <QFormLayout> +#include <QLabel> #include <QSpinBox> QSpinBox* GUI::Util::createSpinBox(QWidget* parent, const UIntDescriptor& d, @@ -71,3 +72,8 @@ QString GUI::Util::labelWithUnit(const QString& label, variant<QString, Unit> un return label; } + +QString GUI::Util::labelWithUnit(const DoubleDescriptor& d) +{ + return labelWithUnit(d.label, d.unit); +} diff --git a/GUI/View/Tool/WidgetUtils.h b/GUI/View/Tool/WidgetUtils.h index 8526a374429..cea8aaf0b05 100644 --- a/GUI/View/Tool/WidgetUtils.h +++ b/GUI/View/Tool/WidgetUtils.h @@ -101,6 +101,11 @@ DoubleSpinBox* createSpinBox(QFormLayout* parentLayout, const DoubleDescriptor& //! No trailing ':' will be appended QString labelWithUnit(const QString& label, std::variant<QString, Unit> unit); +//! Create a label with an optional unit in brackets, both taken from the given descriptor. +//! +//! No trailing ':' will be appended +QString labelWithUnit(const DoubleDescriptor& d); + } // namespace GUI::Util #endif // BORNAGAIN_GUI_VIEW_TOOL_WIDGETUTILS_H -- GitLab