BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
FormLayouter.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/SampleDesigner/FormLayouter.cpp
6 //! @brief Implements class FormLayouter
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2021
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
22 
23 #include <QFormLayout>
24 #include <QGroupBox>
25 #include <QLabel>
26 #include <QPushButton>
27 
28 namespace {
29 
30 QWidget* createSpinBox(QWidget* parentWidget, const UIntDescriptor& d, SampleEditorController* ec)
31 {
32  auto* spinBox = new QSpinBox(parentWidget);
33  spinBox->setFocusPolicy(Qt::StrongFocus);
34  spinBox->setKeyboardTracking(false);
35  spinBox->setToolTip(d.tooltip);
36  spinBox->setMaximum(std::numeric_limits<int>::max());
37  spinBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
38 
39  if (d.limits.hasLowerLimit())
40  spinBox->setMinimum(static_cast<int>(d.limits.lowerLimit()));
41  if (d.limits.hasUpperLimit())
42  spinBox->setMaximum(static_cast<int>(d.limits.upperLimit()));
43 
44  spinBox->setValue(d.get());
45 
46  QObject::connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
47  [=](int newValue) { ec->setInt(newValue, d); });
48 
49  return spinBox;
50 }
51 
52 } // namespace
53 
55  : m_ec(ec)
56 {
57  if (parent->layout() != nullptr) {
58  m_formLayout = dynamic_cast<QFormLayout*>(parent->layout());
59  if (m_formLayout == nullptr) {
60  auto* collapser =
61  GroupBoxCollapser::findInstalledCollapser(dynamic_cast<QGroupBox*>(parent));
62  if (collapser)
63  m_formLayout = dynamic_cast<QFormLayout*>(collapser->contentArea()->layout());
64  }
65  ASSERT(m_formLayout);
66  } else {
67  m_formLayout = new QFormLayout(parent);
68  m_formLayout->setFormAlignment(Qt::AlignLeft | Qt::AlignBottom);
69  m_formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
70  }
71 }
72 
73 QFormLayout* FormLayouter::layout()
74 {
75  return m_formLayout;
76 }
77 
78 void FormLayouter::setContentsMargins(int left, int top, int right, int bottom)
79 {
80  m_formLayout->setContentsMargins(left, top, right, bottom);
81 }
82 
83 int FormLayouter::addRow(const QString& label, QWidget* w)
84 {
85  insertRow(m_formLayout->rowCount(), label, w);
86  return m_formLayout->rowCount() - 1;
87 }
88 
89 void FormLayouter::insertRow(int row, QString label, QWidget* w)
90 {
91  if (!label.endsWith(":"))
92  label += ":";
93  m_formLayout->insertRow(row, LayerEditorUtils::createBoldLabel(label), w);
94 }
95 
96 int FormLayouter::addGroupOfValues(const QString& labelText, const DoubleDescriptors& values)
97 {
98  auto* w = new QWidget(m_formLayout->parentWidget());
99  w->setObjectName("PropertyBaseWidget");
100  w->setAttribute(Qt::WA_StyledBackground, true);
101  w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}");
102 
103  auto* gridLayout = new QGridLayout(w);
104  gridLayout->setContentsMargins(0, 0, 0, 0);
105  gridLayout->setSpacing(6);
106 
107  LayerEditorUtils::addMultiPropertyToGrid(gridLayout, 0, values, m_ec, true);
108 
109  return addRow(labelText, w);
110 }
111 
112 int FormLayouter::addVector(const VectorDescriptor& d, bool vertically /*= true*/)
113 {
114  auto* w = new QWidget(m_formLayout->parentWidget());
115  w->setObjectName("PropertyBaseWidget");
116  w->setAttribute(Qt::WA_StyledBackground, true);
117  w->setStyleSheet("#PropertyBaseWidget {background-color: transparent}");
118 
119  auto* gridLayout = new QGridLayout(w);
120  gridLayout->setContentsMargins(0, 0, 0, 0);
121  gridLayout->setSpacing(6);
122 
123  LayerEditorUtils::addMultiPropertyToGrid(gridLayout, 0, {d.x, d.y, d.z}, m_ec, vertically,
124  true);
125 
126  return addRow(d.label, w);
127 }
128 
129 void FormLayouter::setRowVisible(int row, bool visible)
130 {
131  m_formLayout->itemAt(row, QFormLayout::LabelRole)->widget()->setVisible(visible);
132  m_formLayout->itemAt(row, QFormLayout::FieldRole)->widget()->setVisible(visible);
133 }
134 
136 {
137  m_formLayout->removeRow(row);
138 }
139 
140 void FormLayouter::addStructureEditingRow(QPushButton* button)
141 {
142  auto* w = new QWidget(m_formLayout->parentWidget());
143  auto* l = new QHBoxLayout(w);
144  l->setContentsMargins(0, 0, 0, 0);
145  l->setAlignment(Qt::AlignLeft);
146  l->setSizeConstraint(QLayout::SetMinimumSize);
147  l->addWidget(button);
148  l->addStretch();
149  addRow(w);
150 }
152 {
153  auto* editor = createSpinBox(m_formLayout->parentWidget(), d, m_ec);
154  return addRow(d.label, editor);
155 }
156 
158 {
159  insertValue(m_formLayout->rowCount(), d);
160  return m_formLayout->rowCount() - 1;
161 }
162 
163 int FormLayouter::addValue(const DoubleDescriptor& d, function<void(double)> onValueChange)
164 {
165  insertValue(m_formLayout->rowCount(), d, onValueChange);
166  return m_formLayout->rowCount() - 1;
167 }
168 
170 {
171  auto* ec = m_ec; // to allow copy-capture in the following lambda
172  insertValue(row, d, [ec, d](double newValue) { ec->setDouble(newValue, d); });
173 }
174 
176  function<void(double)> onValueChange)
177 {
178  auto labelText = d.label;
179  if (!labelText.endsWith(":"))
180  labelText += ":";
181 
182  auto* label = LayerEditorUtils::createBoldLabel(labelText);
183  label->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
184  label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
185 
186  auto* editor = new DoubleSpinBox(m_formLayout->parentWidget(), d);
187  QObject::connect(editor, &DoubleSpinBox::baseValueChanged, onValueChange);
188 
189  label->setBuddy(editor);
190 
191  LayerEditorUtils::updateLabelUnit(label, editor);
192  m_formLayout->insertRow(row, label, editor);
193 }
194 
195 int FormLayouter::addRow(QWidget* w)
196 {
197  m_formLayout->addRow(w);
198  return m_formLayout->rowCount() - 1;
199 }
200 
201 void FormLayouter::insertRow(int row, QWidget* w)
202 {
203  m_formLayout->insertRow(row, w);
204 }
QList< DoubleDescriptor > DoubleDescriptors
Defines class DoubleSpinBox.
Defines classes FormLayouter.
Defines class GroupBoxCollapser.
Defines class LayerEditorUtils.
Defines class SampleEditorController.
Defines class UIntDescriptor.
Defines class VectorDescriptor.
Describes properties of a double value which are necessary to allow GUI representation,...
QString label
A label text (short, no trailing colon)
SpinBox for DoubleDescriptors, supporting units.
Definition: DoubleSpinBox.h:22
void baseValueChanged(double newBaseValue)
Emitted whenever the value changes.
int addGroupOfValues(const QString &labelText, const DoubleDescriptors &values)
Adds a row with a bold printed label and a set of DoubleDescriptors.
void addStructureEditingRow(QPushButton *button)
Adds a button for structure editing.
QFormLayout * layout()
The layout where this layouter is operating on.
QFormLayout * m_formLayout
Definition: FormLayouter.h:166
int addRow(QWidget *w)
Convenience method to add a widget.
int addValue(const DoubleDescriptor &d)
Adds a row with a bold printed label and a DoubleSpinBox.
void insertValue(int row, const DoubleDescriptor &d)
Inserts a row with a bold printed label and a DoubleSpinBox.
SampleEditorController * m_ec
Definition: FormLayouter.h:165
void insertRow(int row, QWidget *w)
Convenience method to insert a widget.
int addVector(const VectorDescriptor &d, bool vertically=true)
Adds a row with a bold printed label and the 3 values of a 3D vector.
FormLayouter(QWidget *parent, SampleEditorController *ec)
Create a layouter which operates on the given parent widget.
void removeRow(int row)
Convenience method to remove a row.
void setRowVisible(int row, bool visible)
Shows or hides the widgets in a row.
void setContentsMargins(int left, int top, int right, int bottom)
Convenience method to set the contents margins.
static GroupBoxCollapser * findInstalledCollapser(QGroupBox *groupBox)
Class to modify a sample from the layer oriented sample editor.
void setInt(int newValue, UIntDescriptor d)
void setDouble(double newValue, DoubleDescriptor d)
Describes properties of a uint value which are necessary to allow GUI representation,...
QString label
A label text (short, no trailing colon)
QString tooltip
Tooltip text.
RealLimits limits
Limits of the value.
function< uint()> get
function to get the current value
Describes properties of a 3D vector, consisting of three double values.
DoubleDescriptor y
DoubleDescriptor x
QString label
A label text (short, no trailing colon)
DoubleDescriptor z
QSpinBox * createSpinBox(QWidget *parent, const UIntDescriptor &d, std::function< void(uint)> slot=nullptr)
Create a spin box with the information found in a UIntDescriptor.
Definition: WidgetUtils.cpp:24
void addMultiPropertyToGrid(QGridLayout *m_gridLayout, int firstCol, const DoubleDescriptors &valueDescriptors, SampleEditorController *ec, bool vertically, bool addSpacer)
Create DoubleSpinBoxes for the DoubeDescriptors and connect them to SampleEditorController::setDouble...
void updateLabelUnit(QLabel *label)
QLabel * createBoldLabel(const QString &text)