BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
LayerForm.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/SampleDesigner/LayerForm.cpp
6 //! @brief Implements class LayerForm
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 
20 #include "GUI/Util/ActionFactory.h"
25 
26 #include <QLineEdit>
27 #include <QMenu>
28 #include <QPushButton>
29 #include <memory>
30 
32  : QGroupBox(parent)
33  , m_layer(layer)
34  , m_ec(ec)
35 {
36  setTitle(m_layer->layerName());
37  m_layouter = std::make_unique<FormLayouter>(this, ec);
38  m_layouter->setContentsMargins(6, 6, 0, 6);
40 
42  ActionFactory::createRemoveAction(this, "layer", [=] { ec->removeLayer(layer); });
43 
44  auto* chooseColorAction = new QAction(this);
45  chooseColorAction->setText("Choose color");
46  chooseColorAction->setIcon(QIcon(":/images/palette.svg"));
47  chooseColorAction->setIconText("Choose color");
48  chooseColorAction->setToolTip("Choose a color for this layer");
49  auto* menu = new QMenu(this);
50  chooseColorAction->setMenu(menu);
51 
52  for (const auto& col : LayerEditorUtils::predefinedLayerColors()) {
53  QPixmap p(64, 64);
54  p.fill(col);
55  auto* ca = menu->addAction(QIcon(p), "");
56  connect(ca, &QAction::triggered, [=]() {
57  layer->setColor(col);
58  updateColor();
59  });
60  }
61 
62  m_moveButton = new WidgetMoverButton(this, this, 1);
63  m_moveButton->setToolTip("Move layer up/down");
68 
69  auto* showInRealSpaceAction = ActionFactory::createShowInRealSpaceAction(
70  this, "layer", [=] { m_ec->requestViewInRealSpace(layer); });
71 
72  m_collapser->addAction(showInRealSpaceAction);
73  m_collapser->addAction(chooseColorAction);
77 
78  QColor bckgroundCol = m_layer->color();
79  setStyleSheet("QGroupBox {background-color: " + bckgroundCol.name(QColor::HexRgb) + "}");
80 
81  m_layouter->addRow("Material:", new MaterialInplaceForm(this, layer, ec));
83  m_layouter->addValue(m_layer->numSlices());
84  m_roughnessRow = m_layouter->addSelection(m_layer->roughness());
85 
86  // -- layouts
87  for (auto* layout : layer->layouts())
88  m_layouter->addRow(new ParticleLayoutForm(this, layout, ec));
89 
90  // -- Button for adding a new layout
91  auto* btn = new QPushButton("Add particle layout", this);
92  connect(btn, &QPushButton::clicked, [=] { ec->addLayout(this); });
94  m_layouter->addStructureEditingRow(btn);
95 
96  // listen to changes in materials to update the title (contains the material name). Necessary
97  // to reflect e.g. a name change done in the material editor.
99 
101 }
102 
104 {
105  m_removeAction->setVisible(b);
106 
107  for (auto* w : m_structureEditingWidgets)
108  w->setVisible(b);
109 
110  if (b && m_ec->sampleItem()->layers().size() < 2)
111  m_moveButton->setVisible(false);
112 }
113 
115 {
116  QColor bckgroundCol = m_layer->color();
117  setStyleSheet("QGroupBox {background-color: " + bckgroundCol.name(QColor::HexRgb) + "}");
118 }
119 
121 {
122  int i = m_ec->sampleItem()->layers().indexOf(m_layer);
123  m_collapser->setTitle("Layer " + QString::number(i)
124  + " Material: " + m_layer->materialName());
125 }
126 
128 {
129  m_collapser->setExpanded(true);
130 }
131 
133 {
134  if (m_roughnessRow == -1)
135  return;
136 
137  updateTitle();
138 
139  const auto* sample = m_ec->sampleItem();
140  const bool isFirstLayer = sample->layers().first() == m_layer;
141  const bool isLastLayer = sample->layers().last() == m_layer;
142  const bool thicknessIsSemiInfinite =
143  (isFirstLayer || isLastLayer) && (sample->layers().size() != 1);
144  const bool thicknessIsInfinite = sample->layers().size() == 1;
145 
146  m_layouter->setRowVisible(m_roughnessRow, !isFirstLayer);
147 
148  if (m_thicknessRow == -1)
149  return;
150  QWidget* w = m_layouter->layout()->itemAt(m_thicknessRow, QFormLayout::FieldRole)->widget();
151  if (thicknessIsSemiInfinite || thicknessIsInfinite) {
152  auto* info = qobject_cast<QLineEdit*>(w);
153  if (info == nullptr) {
154  m_layouter->removeRow(m_thicknessRow);
155  info = new QLineEdit(this);
156  info->setEnabled(false);
157  info->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
158  m_layouter->insertRow(m_thicknessRow, m_layer->thickness().label, info);
159  }
160  info->setText(thicknessIsSemiInfinite ? "Semi-infinite" : "Infinite");
161  } else if (!thicknessIsSemiInfinite && !thicknessIsInfinite
162  && (qobject_cast<QLineEdit*>(w) != nullptr)) {
163  m_layouter->removeRow(m_thicknessRow);
164  m_layouter->insertValue(m_thicknessRow, m_layer->thickness());
165  }
166 
167  if (m_ec->sampleItem()->layers().size() < 2)
168  m_moveButton->setVisible(false);
169 }
170 
172 {
173  int index = m_layer->layouts().indexOf(newLayoutItem);
174  const int rowInLayout = m_layouter->layout()->rowCount() - m_layer->layouts().size() + index;
175 
176  m_layouter->insertRow(rowInLayout, new ParticleLayoutForm(this, newLayoutItem, m_ec));
177 }
178 
180 {
181  int index = m_layer->layouts().indexOf(layoutItem);
182  const int rowInLayout =
183  m_layouter->layout()->rowCount() - m_layer->layouts().size() - 1 + index; // -1: btn
184 
185  m_layouter->removeRow(rowInLayout);
186 }
187 
189 {
190  return m_layer;
191 }
Defines class ActionFactory.
Defines class GroupBoxCollapser.
Defines class LayerForm.
Defines class LayerItem.
Defines class MaterialInplaceForm.
Defines class MaterialItem.
Defines class MaterialItems.
Defines class MultiLayerItem.
Defines class ParticleLayoutForm.
Defines class WidgetMoverButton.
static QAction * createShowInRealSpaceAction(QObject *parent, const QString &what, std::function< void()> slot=nullptr)
Create "show in RealSpace" action.
static QAction * createRemoveAction(QObject *parent, const QString &what, std::function< void()> slot=nullptr)
Create "remove" action.
QString label
A label text (short, no trailing colon)
void setExpanded(bool expanded=true)
Expand/collapse the content area.
void addAction(QAction *action)
Add a tool button to the title bar, connected to the given action.
void addWidget(QWidget *widget)
Add a widget to the title bar.
static GroupBoxCollapser * installIntoGroupBox(QGroupBox *groupBox, bool expanded=true)
void setTitle(const QString &title)
Set the title of the group box. Do not use the method groupBox->setTitle() any more once the add-on i...
QString materialName() const
GroupBoxCollapser * m_collapser
Definition: LayerForm.h:46
int m_thicknessRow
Definition: LayerForm.h:51
void updateColor()
Definition: LayerForm.cpp:114
QAction * m_removeAction
Definition: LayerForm.h:49
LayerItem * m_layer
Definition: LayerForm.h:48
void updateLayerPositionDependentElements()
Definition: LayerForm.cpp:132
void updateTitle()
Definition: LayerForm.cpp:120
void onAboutToRemoveLayout(ParticleLayoutItem *layoutItem)
Definition: LayerForm.cpp:179
void expand()
Definition: LayerForm.cpp:127
WidgetMoverButton * m_moveButton
Definition: LayerForm.h:54
std::unique_ptr< FormLayouter > m_layouter
Definition: LayerForm.h:47
SampleEditorController * m_ec
Definition: LayerForm.h:52
LayerForm(QWidget *parent, LayerItem *layer, SampleEditorController *ec)
Definition: LayerForm.cpp:31
LayerItem * layerItem() const
Definition: LayerForm.cpp:188
void enableStructureEditing(bool b)
Definition: LayerForm.cpp:103
void onLayoutAdded(ParticleLayoutItem *layoutItem)
Definition: LayerForm.cpp:171
QList< QWidget * > m_structureEditingWidgets
Definition: LayerForm.h:53
int m_roughnessRow
Definition: LayerForm.h:50
QColor color() const
Definition: LayerItem.cpp:153
UIntDescriptor numSlices() const
Definition: LayerItem.cpp:131
void setColor(const QColor &color)
Definition: LayerItem.cpp:158
QVector< ParticleLayoutItem * > layouts() const
Definition: LayerItem.cpp:136
DoubleDescriptor thickness() const
Definition: LayerItem.cpp:97
QString layerName() const
Definition: LayerItem.cpp:75
SelectionDescriptor< LayerBasicRoughnessItem * > roughness()
Definition: LayerItem.cpp:102
Form to select a material and to edit it in-place.
void materialChanged(MaterialItem *materialItem)
QVector< LayerItem * > layers() const
Form for editing a particle layout.
Class to modify a sample from the layer oriented sample editor.
MultiLayerItem * sampleItem() const
The item on which this controller operates.
void requestViewInRealSpace(SampleItem item)
MaterialItems * materialItems() const
The materials of the current document.
void onStoppedToMoveLayer(QWidget *widgetToMove, QWidget *moveAboveThisWidget)
void addLayout(LayerForm *layerItem)
void removeLayer(LayerItem *layerItem)
Button to move a widget vertically in a layout.
void finishedMoving(QWidget *widgetToMove, QWidget *moveAboveThisWidget)
QList< QColor > predefinedLayerColors()