Skip to content
Snippets Groups Projects
Commit ff5c1420 authored by Matthias Puchner's avatar Matthias Puchner
Browse files

simplify UI; add missing modified signal

parent 2e7b7648
No related branches found
No related tags found
1 merge request!627Minor changes
Pipeline #56259 passed
......@@ -63,7 +63,7 @@ QString alignmentTitle(RectangularDetector::EDetectorArrangement a)
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM:
return "Perpendicular to reflected beam";
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS:
return "Perpendicular to reflected beam (dpos)";
return "Perpendicular to reflected beam (intersection unknown)";
default:
ASSERT(false);
}
......
......@@ -15,6 +15,7 @@
#include "GUI/View/Instrument/DetectorAlignmentEditor.h"
#include "GUI/Model/Item/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>
......@@ -23,356 +24,26 @@
#include <QGroupBox>
#include <QStackedLayout>
//==================================================================================================
// DetectorAlignmentForm
//==================================================================================================
/// abstract interface of all detector alignment forms
class DetectorAlignmentForm : public QWidget {
public:
/// Set type if not already the matching one and display parameters of distribution
virtual void setItem(RectangularDetectorItem* item) = 0;
protected:
DetectorAlignmentForm(QWidget* parent, std::function<void()> dataChangedSlot)
: QWidget(parent)
, dataChanged(dataChangedSlot)
{
}
std::function<void()> dataChanged;
};
//==================================================================================================
// GenericDetectorAlignmentForm
//==================================================================================================
/// Alignment form for the generic case
class GenericDetectorAlignmentForm : public DetectorAlignmentForm {
public:
GenericDetectorAlignmentForm(QWidget* parent, std::function<void()> dataChangedSlot);
void setItem(RectangularDetectorItem* item) override;
private slots:
void onU0ValueChanged(double u0);
void onV0ValueChanged(double v0);
private:
QDoubleSpinBox* m_u0SpinBox;
QDoubleSpinBox* m_v0SpinBox;
VectorEditor* m_normalEditor;
VectorEditor* m_directionEditor;
RectangularDetectorItem* m_item;
};
GenericDetectorAlignmentForm::GenericDetectorAlignmentForm(QWidget* parent,
std::function<void()> dataChangedSlot)
: DetectorAlignmentForm(parent, dataChangedSlot)
, m_item(nullptr)
{
auto* layout = new QHBoxLayout(this);
auto* gbox = new QGroupBox("Intersection of normal and detector", this);
auto* form = new QFormLayout(gbox);
layout->addWidget(gbox);
m_u0SpinBox = new QDoubleSpinBox(gbox);
m_u0SpinBox->setDecimals(3);
m_u0SpinBox->setRange(std::numeric_limits<double>::lowest(),
std::numeric_limits<double>::max());
m_u0SpinBox->setSingleStep(0.01);
m_u0SpinBox->setToolTip("u-coordinate of intersection of normal vector "
"and detector plane, \n in local detector coordinates");
connect(m_u0SpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
&GenericDetectorAlignmentForm::onU0ValueChanged);
form->addRow("u0 [mm]:", m_u0SpinBox);
m_v0SpinBox = new QDoubleSpinBox(gbox);
m_v0SpinBox->setDecimals(3);
m_v0SpinBox->setRange(std::numeric_limits<double>::lowest(),
std::numeric_limits<double>::max());
m_v0SpinBox->setSingleStep(0.01);
m_v0SpinBox->setToolTip("v-coordinate of intersection of normal vector "
"and detector plane, \n in local detector coordinates");
connect(m_v0SpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
&GenericDetectorAlignmentForm::onV0ValueChanged);
form->addRow("v0 [mm]:", m_v0SpinBox);
m_normalEditor = new VectorEditor(
"Normal vector",
"Normal of the detector plane with length equal to the sample detector distance (%1)",
this);
layout->addWidget(m_normalEditor);
connect(m_normalEditor, &VectorEditor::vectorChanged, [=]() { dataChanged(); });
m_directionEditor = new VectorEditor(
"Detector axis direction vector",
"Detector axis direction vector w.r.t. the sample coordinate system (%1)", this);
layout->addWidget(m_directionEditor);
connect(m_directionEditor, &VectorEditor::vectorChanged, [=]() { dataChanged(); });
}
void GenericDetectorAlignmentForm::setItem(RectangularDetectorItem* item)
{
m_item = item;
m_u0SpinBox->setValue(m_item->u0());
m_v0SpinBox->setValue(m_item->v0());
m_normalEditor->setVector(m_item->normalVector());
m_directionEditor->setVector(m_item->directionVector());
}
void GenericDetectorAlignmentForm::onU0ValueChanged(double u0)
{
if (m_item && m_item->u0() != u0) {
m_item->setU0(u0);
dataChanged();
}
}
void GenericDetectorAlignmentForm::onV0ValueChanged(double v0)
{
if (m_item && m_item->v0() != v0) {
m_item->setV0(v0);
dataChanged();
}
}
//==================================================================================================
// PerpendicularDetectorAlignmentForm
//==================================================================================================
/// Abstract alignment form for the perpendicular case
class PerpendicularDetectorAlignmentForm : public DetectorAlignmentForm {
public:
void setItem(RectangularDetectorItem* item) override;
protected:
PerpendicularDetectorAlignmentForm(const QString& title, const QString& tooltip,
QWidget* parent, std::function<void()> dataChangedSlot);
RectangularDetectorItem* item() const;
private slots:
void onU0ValueChanged(double u0);
void onV0ValueChanged(double v0);
void onDistanceValueChanged(double distance);
private:
virtual double getU0() const = 0;
virtual double getV0() const = 0;
virtual void setU0(double u0) = 0;
virtual void setV0(double v0) = 0;
QDoubleSpinBox* m_u0SpinBox;
QDoubleSpinBox* m_v0SpinBox;
QDoubleSpinBox* m_distanceSpinBox;
RectangularDetectorItem* m_item;
};
//--------------------------------------------------------------------------------------------------
// public member functions
//--------------------------------------------------------------------------------------------------
void PerpendicularDetectorAlignmentForm::setItem(RectangularDetectorItem* item)
{
m_item = item;
m_u0SpinBox->setValue(getU0());
m_v0SpinBox->setValue(getV0());
m_distanceSpinBox->setValue(m_item->distance());
}
//--------------------------------------------------------------------------------------------------
// protected member functions
//--------------------------------------------------------------------------------------------------
PerpendicularDetectorAlignmentForm::PerpendicularDetectorAlignmentForm(
const QString& title, const QString& tooltip, QWidget* parent,
std::function<void()> dataChangedSlot)
: DetectorAlignmentForm(parent, dataChangedSlot)
, m_item(nullptr)
{
auto* layout = new QHBoxLayout(this);
auto* gbox = new QGroupBox(title, this);
auto* form = new QFormLayout(gbox);
layout->addWidget(gbox);
m_u0SpinBox = new QDoubleSpinBox(gbox);
m_u0SpinBox->setDecimals(3);
m_u0SpinBox->setRange(std::numeric_limits<double>::lowest(),
std::numeric_limits<double>::max());
m_u0SpinBox->setSingleStep(0.01);
m_u0SpinBox->setToolTip(tooltip.arg("u-coordinate"));
connect(m_u0SpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
&PerpendicularDetectorAlignmentForm::onU0ValueChanged);
form->addRow("u0 [mm]:", m_u0SpinBox);
m_v0SpinBox = new QDoubleSpinBox(gbox);
m_v0SpinBox->setDecimals(3);
m_v0SpinBox->setRange(std::numeric_limits<double>::lowest(),
std::numeric_limits<double>::max());
m_v0SpinBox->setSingleStep(0.01);
m_v0SpinBox->setToolTip(tooltip.arg("v-coordinate"));
connect(m_v0SpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
&PerpendicularDetectorAlignmentForm::onV0ValueChanged);
form->addRow("v0 [mm]:", m_v0SpinBox);
m_distanceSpinBox = new QDoubleSpinBox(gbox);
m_distanceSpinBox->setDecimals(3);
m_distanceSpinBox->setRange(0, std::numeric_limits<double>::max());
m_distanceSpinBox->setSingleStep(0.01);
m_distanceSpinBox->setToolTip("Distance in [mm] from the sample origin to the detector plane");
connect(m_distanceSpinBox, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
&PerpendicularDetectorAlignmentForm::onDistanceValueChanged);
form->addRow("Distance [mm]:", m_distanceSpinBox);
}
RectangularDetectorItem* PerpendicularDetectorAlignmentForm::item() const
{
return m_item;
}
//--------------------------------------------------------------------------------------------------
// private slots
//--------------------------------------------------------------------------------------------------
void PerpendicularDetectorAlignmentForm::onU0ValueChanged(double u0)
{
setU0(u0);
}
void PerpendicularDetectorAlignmentForm::onV0ValueChanged(double v0)
{
setV0(v0);
}
void PerpendicularDetectorAlignmentForm::onDistanceValueChanged(double distance)
{
if (m_item && m_item->distance() != distance) {
m_item->setDistance(distance);
dataChanged();
}
}
//==================================================================================================
// ReflectedBeamDetectorAlignmentForm
//==================================================================================================
/// detector alignment form for the perpendicular case where the reflected beam is used
class ReflectedBeamDetectorAlignmentForm : public PerpendicularDetectorAlignmentForm {
public:
ReflectedBeamDetectorAlignmentForm(const QString& title, const QString& tooltip,
QWidget* parent, std::function<void()> dataChangedSlot);
private:
double getU0() const override;
double getV0() const override;
void setU0(double u0) override;
void setV0(double v0) override;
};
//--------------------------------------------------------------------------------------------------
// public member functions
//--------------------------------------------------------------------------------------------------
ReflectedBeamDetectorAlignmentForm::ReflectedBeamDetectorAlignmentForm(
const QString& title, const QString& tooltip, QWidget* parent,
std::function<void()> dataChangedSlot)
: PerpendicularDetectorAlignmentForm(title, tooltip, parent, dataChangedSlot)
{
}
//--------------------------------------------------------------------------------------------------
// private slots
//--------------------------------------------------------------------------------------------------
double ReflectedBeamDetectorAlignmentForm::getU0() const
{
return item()->u0();
}
double ReflectedBeamDetectorAlignmentForm::getV0() const
{
return item()->v0();
}
void ReflectedBeamDetectorAlignmentForm::setU0(double u0)
{
if (item() && item()->u0() != u0) {
item()->setU0(u0);
dataChanged();
}
}
void ReflectedBeamDetectorAlignmentForm::setV0(double v0)
{
if (item() && item()->v0() != v0) {
item()->setV0(v0);
dataChanged();
}
}
//==================================================================================================
// DirectBeamDetectorAlignmentForm
//==================================================================================================
/// detector alignment form for the perpendicular case where the direct beam is used
class DirectBeamDetectorAlignmentForm : public PerpendicularDetectorAlignmentForm {
public:
DirectBeamDetectorAlignmentForm(const QString& title, const QString& tooltip, QWidget* parent,
std::function<void()> dataChangedSlot);
private:
double getU0() const override;
double getV0() const override;
void setU0(double u0) override;
void setV0(double v0) override;
};
//--------------------------------------------------------------------------------------------------
// public member functions
//--------------------------------------------------------------------------------------------------
DirectBeamDetectorAlignmentForm::DirectBeamDetectorAlignmentForm(
const QString& title, const QString& tooltip, QWidget* parent,
std::function<void()> dataChangedSlot)
: PerpendicularDetectorAlignmentForm(title, tooltip, parent, dataChangedSlot)
namespace {
QString alignmentDescription(RectangularDetector::EDetectorArrangement a)
{
}
//--------------------------------------------------------------------------------------------------
// private slots
//--------------------------------------------------------------------------------------------------
double DirectBeamDetectorAlignmentForm::getU0() const
{
return item()->directBeamU0();
}
double DirectBeamDetectorAlignmentForm::getV0() const
{
return item()->directBeamV0();
}
void DirectBeamDetectorAlignmentForm::setU0(double u0)
{
if (item() && item()->directBeamU0() != u0) {
item()->setDirectBeamU0(u0);
dataChanged();
}
}
void DirectBeamDetectorAlignmentForm::setV0(double v0)
{
if (item() && item()->directBeamV0() != v0) {
item()->setDirectBeamV0(v0);
dataChanged();
switch (a) {
case RectangularDetector::GENERIC:
return "Intersection of normal and detector";
case RectangularDetector::PERPENDICULAR_TO_SAMPLE:
return "Intersection of sample x-axis and detector";
case RectangularDetector::PERPENDICULAR_TO_DIRECT_BEAM:
return "Intersection of direct beam and detector";
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM:
return "Intersection of reflected beam and detector";
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS:
return "Intersection of direct beam and detector";
default:
ASSERT(false);
}
}
//==================================================================================================
// DetectorAlignmentEditor
//==================================================================================================
} // namespace
DetectorAlignmentEditor::DetectorAlignmentEditor(QWidget* parent, RectangularDetectorItem* item)
: QWidget(parent)
......@@ -380,48 +51,85 @@ DetectorAlignmentEditor::DetectorAlignmentEditor(QWidget* parent, RectangularDet
{
ASSERT(m_item);
m_formLayout = new QFormLayout(this);
auto* m_combo = GUI::Util::createSelectionCombo(this, item->detectorAlignmentSelection(),
[=](int) { createAligmentWidgets(); });
m_formLayout->setContentsMargins(0, 15, 0, 0);
m_formLayout->setSpacing(8);
auto* m_combo =
GUI::Util::createSelectionCombo(this, item->detectorAlignmentSelection(), [=](int) {
createAligmentWidgets();
emit dataChanged();
});
m_formLayout->addRow("Alignment:", m_combo);
createAligmentWidgets();
}
DoubleSpinBox* DetectorAlignmentEditor::createSpinBox(QFormLayout* parentFormLayout,
const DoubleDescriptor& d)
{
auto* sb = GUI::Util::createSpinBox(parentFormLayout, d);
connect(sb, qOverload<double>(&DoubleSpinBox::baseValueChanged), [=](double v) {
if (d.get() != v) {
d.set(v);
emit dataChanged();
}
});
return sb;
}
void DetectorAlignmentEditor::createAligmentWidgets()
{
while (m_formLayout->rowCount() > 1)
m_formLayout->removeRow(1);
const QString descr = alignmentDescription(m_item->detectorAlignment());
switch (m_item->detectorAlignment()) {
case RectangularDetector::GENERIC:
m_formLayout->addRow(new GenericDetectorAlignmentForm(this, [=]() { dataChanged(); }));
break;
case RectangularDetector::PERPENDICULAR_TO_SAMPLE:
m_formLayout->addRow(new ReflectedBeamDetectorAlignmentForm(
"Intersection of sample x-axis and detector",
"Point where the sample x-axis intersects with the detector plane (%1)", this,
[=]() { dataChanged(); }));
break;
case RectangularDetector::PERPENDICULAR_TO_DIRECT_BEAM:
m_formLayout->addRow(new DirectBeamDetectorAlignmentForm(
"Intersection of direct beam and detector",
"Point where the direct beam hits the detector plane (%1)", this,
[=]() { dataChanged(); }));
break;
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM:
m_formLayout->addRow(new ReflectedBeamDetectorAlignmentForm(
"Intersection of reflected beam and detector",
"Point where the reflected beam hits the detector plane (%1)", this,
[=]() { dataChanged(); }));
break;
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS:
m_formLayout->addRow(new DirectBeamDetectorAlignmentForm(
"Intersection of direct beam and detector",
"Point where the direct beam hits the detector plane (%1)", this,
[=]() { dataChanged(); }));
break;
case 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);
} break;
case RectangularDetector::PERPENDICULAR_TO_SAMPLE: // fall-through!
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM: {
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);
} break;
case RectangularDetector::PERPENDICULAR_TO_DIRECT_BEAM: // fall-through!
case RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS: {
auto* gbox = new QGroupBox(descr, this);
auto* form = new QFormLayout(gbox);
createSpinBox(form, m_item->directBeamU0());
createSpinBox(form, m_item->directBeamV0());
createSpinBox(form, m_item->distance());
m_formLayout->addRow(gbox);
} break;
default:
break;
ASSERT(false);
}
}
......@@ -23,6 +23,8 @@ class QStackedLayout;
class DetectorAlignmentForm;
class RectangularDetectorItem;
class QFormLayout;
class DoubleSpinBox;
class DoubleDescriptor;
/// Widget for selecting the alignment of a detector (combo box) and input of the corresponding
/// values
......@@ -37,6 +39,7 @@ signals:
private:
void createAligmentWidgets();
DoubleSpinBox* createSpinBox(QFormLayout* parentFormLayout, const DoubleDescriptor& d);
private:
RectangularDetectorItem* m_item;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment