BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
LayerEditorUtils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/SampleDesigner/LayerEditorUtils.cpp
6 //! @brief Implements class LayerEditorUtils
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 
30 
31 #include <QLabel>
32 #include <QMenu>
33 #include <QPushButton>
34 
35 namespace {
36 
37 void updateLabelUnit(QLabel* label, const QString& unit)
38 {
39  QString text = label->text();
40  const bool hasColon = text.indexOf(":") > 0;
41  text = text.left(text.indexOf("["));
42  text = text.trimmed();
43  if (text.endsWith(":"))
44  text.chop(1);
45 
46  if (!unit.isEmpty())
47  text += " [" + unit + "]";
48  if (hasColon)
49  text += ":";
50  label->setText(text);
51 }
52 
53 } // namespace
54 
56 {
57  ::updateLabelUnit(label, editor->displayUnitAsString());
58 }
59 
61 {
62  if (auto* editor = dynamic_cast<DoubleSpinBox*>(label->buddy()))
63  ::updateLabelUnit(label, editor->displayUnitAsString());
64 }
65 
66 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
67  const DoubleDescriptors& valueDescriptors,
68  SampleEditorController* ec, bool vertically,
69  bool addSpacer)
70 {
71  const auto setNewValue = [=](double newValue, DoubleDescriptor d) {
72  ec->setDouble(newValue, d);
73  };
74 
75  addMultiPropertyToGrid(m_gridLayout, firstCol, valueDescriptors, setNewValue, vertically,
76  addSpacer);
77 }
78 
79 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
80  const DoubleDescriptors& valueDescriptors,
81  function<void(double, DoubleDescriptor)> setNewValue,
82  bool vertically, bool addSpacer)
83 {
84  int col = firstCol;
85  for (const auto& valueDescriptor : valueDescriptors) {
86  auto* editor = new DoubleSpinBox(m_gridLayout->parentWidget(), valueDescriptor);
87  QObject::connect(editor, &DoubleSpinBox::baseValueChanged,
88  [=](double newValue) { setNewValue(newValue, valueDescriptor); });
89 
90  QString labeltext = valueDescriptor.label;
91  if (!vertically && !labeltext.endsWith(":"))
92  labeltext += ":";
93  auto* label = new QLabel(labeltext, m_gridLayout->parentWidget());
94  label->setBuddy(editor); // necessary for unit-updating
95  LayerEditorUtils::updateLabelUnit(label, editor);
96 
97  if (vertically) {
98  m_gridLayout->addWidget(label, 0, col);
99  m_gridLayout->addWidget(editor, 1, col);
100  col++;
101  } else {
102  m_gridLayout->addWidget(label, 1, col++);
103  m_gridLayout->addWidget(editor, 1, col++);
104  }
105  }
106  if (addSpacer)
107  m_gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), 0, col);
108 }
109 
110 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
111  const DoubleDescriptors& valueDescriptors,
112  SampleEditorController* ec, bool addSpacer)
113 {
114  addMultiPropertyToGrid(m_gridLayout, firstCol, valueDescriptors, ec,
115  valueDescriptors.size() > 1, addSpacer);
116 }
117 
118 void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol,
120  bool vertically, bool addSpacer)
121 {
122  addMultiPropertyToGrid(m_gridLayout, firstCol, {v.x, v.y, v.z}, ec, vertically, addSpacer);
123 }
124 
125 
126 void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol,
127  const VectorDescriptor& v,
128  function<void(double, DoubleDescriptor)> setNewValue,
129  bool vertically, bool addSpacer)
130 {
131  addMultiPropertyToGrid(m_gridLayout, firstCol, {v.x, v.y, v.z}, setNewValue, vertically,
132  addSpacer);
133 }
134 
135 QLabel* LayerEditorUtils::createBoldLabel(const QString& text)
136 {
137  auto* l = new QLabel(text);
138  QFont f = l->font();
139  f.setBold(true);
140  l->setFont(f);
141  return l;
142 }
143 
145 {
146  if (!item)
147  return {};
148 
149  return item->rotationValues();
150 }
151 
153 {
154  return item->valueDescriptors();
155 }
156 
158 {
159  return item->valueDescriptors();
160 }
161 
163 {
164  return item->geometryValues();
165 }
166 
168 {
169  if (r)
170  return {r->sigma(), r->hurst(), r->lateralCorrelationLength()};
171 
172  return {};
173 }
174 
176  ItemWithParticles* itemWithParticles,
177  bool allowAbundance,
179  bool allowRemove /*= true*/)
180 {
181  if (auto* composition = dynamic_cast<ParticleCompositionItem*>(itemWithParticles))
182  return new ParticleCompositionForm(parentWidget, composition, ec, allowRemove);
183 
184  if (auto* coreShell = dynamic_cast<ParticleCoreShellItem*>(itemWithParticles))
185  return new ParticleCoreShellForm(parentWidget, coreShell, ec, allowRemove);
186 
187  if (auto* meso = dynamic_cast<MesoCrystalItem*>(itemWithParticles))
188  return new MesoCrystalForm(parentWidget, meso, ec, allowRemove);
189 
190  if (auto* particle = dynamic_cast<ParticleItem*>(itemWithParticles))
191  return new ParticleForm(parentWidget, particle, allowAbundance, ec, allowRemove);
192 
193  ASSERT(false);
194  return nullptr;
195 }
196 
198  QWidget* parentWidget, std::function<void(FormFactorItemCatalog::Type t)> slotAddFormFactor,
199  std::function<void(ItemWithParticlesCatalog::Type t)> slotAddParticle)
200 {
201  auto* btn = new QPushButton("Add particle", parentWidget);
202 
203  auto* menu = new QMenu(btn);
204  QMenu* menuForEntries = menu;
205 
206  const auto group = [&](const QString& title) { menuForEntries = menu->addMenu(title); };
207 
208  group("Hard particles");
209  for (const auto type : FormFactorItemCatalog::hardParticleTypes()) {
210  const auto ui = FormFactorItemCatalog::uiInfo(type);
211  QAction* a = menuForEntries->addAction(QIcon(ui.iconPath), ui.menuEntry);
212  a->setToolTip(ui.description);
213  QObject::connect(a, &QAction::triggered, [=]() { slotAddFormFactor(type); });
214  }
215 
216  group("Ripples");
217  for (const auto type : FormFactorItemCatalog::rippleTypes()) {
218  const auto ui = FormFactorItemCatalog::uiInfo(type);
219  QAction* a = menuForEntries->addAction(QIcon(ui.iconPath), ui.menuEntry);
220  a->setToolTip(ui.description);
221  QObject::connect(a, &QAction::triggered, [=]() { slotAddFormFactor(type); });
222  }
223 
224  group("Particle assemblies");
225  for (const auto type :
228  const auto ui = ItemWithParticlesCatalog::uiInfo(type);
229  QAction* a = menuForEntries->addAction(QIcon(ui.iconPath), ui.menuEntry);
230  a->setToolTip(ui.description);
231  QObject::connect(a, &QAction::triggered, [=]() { slotAddParticle(type); });
232  }
233 
234  btn->setMenu(menu);
235 
236  return btn;
237 }
238 
240 {
241  static QList<QColor> colors = {QColor(230, 255, 213), QColor(194, 252, 240),
242  QColor(239, 228, 176), QColor(200, 191, 231),
243  QColor(253, 205, 193), QColor(224, 193, 253)};
244 
245  return colors;
246 }
QList< DoubleDescriptor > DoubleDescriptors
Defines class DoubleSpinBox.
Defines FormFactorItems classes.
Defines classes FormLayouter.
Defines class LayerEditorUtils.
Defines classes LayerRoughnessItems.
Defines class MesoCrystalForm.
Defines class MesoCrystalItem.
Defines class ParticleCompositionForm.
Defines class ParticleCompositionItem.
Defines class ParticleCoreShellForm.
Defines class ParticleCoreShellItem.
Defines class ParticleForm.
Defines class ParticleItem.
Defines Profile1DItem's classes.
Defines class VectorDescriptor.
Describes properties of a double value which are necessary to allow GUI representation,...
SpinBox for DoubleDescriptors, supporting units.
Definition: DoubleSpinBox.h:22
QString displayUnitAsString() const
The display unit as human readable string.
void baseValueChanged(double newBaseValue)
Emitted whenever the value changes.
static QVector< Type > hardParticleTypes()
static UiInfo uiInfo(Type t)
UiInfo on the given type.
static QVector< Type > rippleTypes()
virtual DoubleDescriptors geometryValues() const =0
static UiInfo uiInfo(Type t)
UiInfo on the given type.
DoubleDescriptor lateralCorrelationLength() const
DoubleDescriptor sigma() const
DoubleDescriptor hurst() const
Form for editing a mesocrystal.
Form for editing a particle composition.
Form for editing a core/shell particle.
Form for editing a particle.
Definition: ParticleForm.h:25
virtual DoubleDescriptors valueDescriptors() const
virtual DoubleDescriptors valueDescriptors() const
virtual DoubleDescriptors rotationValues() const =0
Class to modify a sample from the layer oriented sample editor.
void setDouble(double newValue, DoubleDescriptor d)
Describes properties of a 3D vector, consisting of three double values.
DoubleDescriptor y
DoubleDescriptor x
DoubleDescriptor z
QList< QColor > predefinedLayerColors()
QWidget * createWidgetForItemWithParticles(QWidget *parentWidget, ItemWithParticles *itemWithParticles, bool allowAbundance, SampleEditorController *ec, bool allowRemove=true)
DoubleDescriptors doubleDescriptorsOfItem(LayerBasicRoughnessItem *item)
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 addVectorToGrid(QGridLayout *m_gridLayout, int firstCol, const VectorDescriptor &v, SampleEditorController *ec, bool vertically, bool addSpacer)
Create DoubleSpinBoxes for the DoubeDescriptors and connect them to SampleEditorController::setDouble...
void updateLabelUnit(QLabel *label)
QPushButton * createAddParticleButton(QWidget *parentWidget, std::function< void(FormFactorItemCatalog::Type t)> slotAddFormFactor, std::function< void(ItemWithParticlesCatalog::Type t)> slotAddParticle)
QLabel * createBoldLabel(const QString &text)