BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
sldelementcontroller.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file gui2/sldeditor/sldelementcontroller.cpp
6 //! @brief Implements class CLASS?
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
18 #include "gui2/model/sampleitems.h"
19 #include "gui2/model/samplemodel.h"
27 #include "mvvm/model/modelutils.h"
29 #include <iostream>
30 
31 using namespace ModelView;
32 
33 namespace gui2 {
34 
35 //! Contructor
36 SLDElementController::SLDElementController(MaterialModel* material_model, SampleModel* sample_model,
37  SLDElementModel* sld_model, GraphicsScene* scene_item)
38  : p_material_model(material_model)
39  , p_sample_model(sample_model)
40  , p_sld_model(sld_model)
41  , p_scene_item(scene_item)
42 {
46  buildSLD();
47 }
48 
50 {
51  clearScene();
52 }
53 
54 //! Connect with signals of MaterialModel
56 {
57  auto on_mat_data_change = [this](SessionItem* item, int) { updateToView(item); };
58  p_material_model->mapper()->setOnDataChange(on_mat_data_change, this);
59 
60  auto on_mat_model_destroyed = [this](SessionModel*) { p_material_model = nullptr; };
61  p_material_model->mapper()->setOnModelDestroyed(on_mat_model_destroyed, this);
62 }
63 
64 // FIXME Consider switching to ModelHasChangedController, or ModelListener.
65 // See quicksimcontroller.h or materialpropertycontroller.h as an example.
66 
67 //! Connect with signals of SampleModel
69 {
70  auto on_sam_data_change = [this](SessionItem* item, int) { updateToView(item); };
71  p_sample_model->mapper()->setOnDataChange(on_sam_data_change, this);
72 
73  auto on_sam_item_inserted = [this](SessionItem*, TagRow) { buildSLD(); };
74  p_sample_model->mapper()->setOnItemInserted(on_sam_item_inserted, this);
75 
76  auto on_sam_item_removed = [this](SessionItem*, TagRow) { buildSLD(); };
77  p_sample_model->mapper()->setOnItemRemoved(on_sam_item_removed, this);
78 
79  auto on_sam_model_destroyed = [this](SessionModel*) { p_sample_model = nullptr; };
80  p_sample_model->mapper()->setOnModelDestroyed(on_sam_model_destroyed, this);
81 }
82 
83 //! Connect with signals of SLDViewModel
85 {
86  auto on_sld_model_destroyed = [this](SessionModel*) { p_sld_model = nullptr; };
87  p_sld_model->mapper()->setOnModelDestroyed(on_sld_model_destroyed, this);
88 }
89 
90 //! Disconnect with signals of MaterialModel
92 {
94 }
95 
96 //! Disconnect with signals of SampleModel
98 {
100 }
101 
102 //! Disconnect with signals of SLDViewModel
104 {
105  p_sld_model->mapper()->unsubscribe(this);
106 }
107 
108 //! Set the scene of the current controller to be passed to the LayerElementControllers
110 {
111  p_scene_item = scene;
112  buildSLD();
113 }
114 
115 //! Updates all material properties in LayerItems to get new material colors and labels
117 {
118  if (!p_sld_model)
119  return;
120  if (!p_sample_model)
121  return;
122  if (!p_material_model)
123  return;
124  if (!p_scene_item)
125  return;
126 
128  clearScene();
129 
130  if (p_sample_model->rootItem()->childrenCount() == 0)
131  return;
133  if (identifiers.size() == 0)
134  return;
135 
136  buildLayerControllers(identifiers);
137  updateToView();
140 }
141 
142 //! Remove all LayerElementControllers and their items from scene and memory
144 {
145  if (!p_scene_item)
146  return;
147  if (!p_sld_model)
148  return;
149 
150  for (size_t i = 0; i < m_layer_controllers.size(); ++i) {
151  m_layer_controllers.at(i)->disconnectFormModel();
152  m_layer_controllers.at(i)->unsetScene();
153  m_layer_controllers.at(i)->deleteViewItems();
154  }
155  m_layer_controllers.clear();
156  p_sld_model->clear();
157 }
158 
159 //! Get the identifiers of all layeritems in the sample model in order of appearance
161 {
162  string_vec output;
163 
164  auto children = item->children();
165  for (int i = 0; i < item->childrenCount(); ++i) {
166  if (dynamic_cast<MultiLayerItem*>(children.at(i))) {
167  auto child = dynamic_cast<MultiLayerItem*>(children.at(i));
168  for (int j = 0; j < child->property<int>(MultiLayerItem::P_NREPETITIONS); ++j) {
169  auto child_output = getIdentifierVector(child);
170  output.insert(output.end(), child_output.begin(), child_output.end());
171  }
172  } else if (dynamic_cast<LayerItem*>(children.at(i))) {
173  auto child = dynamic_cast<LayerItem*>(children.at(i));
174  output.push_back(child->identifier());
175  }
176  }
177  return output;
178 }
179 
180 //! Build and set up the layer controllers
182 {
183  if (!p_scene_item)
184  return;
185  if (!p_sld_model)
186  return;
187 
188  for (auto& identifier : identifiers) {
189  auto layer_element_item = p_sld_model->addLayer();
190  auto layer_element_controller =
191  std::make_unique<LayerElementController>(layer_element_item);
192  layer_element_controller->autoPopulate();
193  layer_element_controller->setScene(p_scene_item);
194  layer_element_controller->connectToModel();
195  layer_element_controller->setSampleItemId(identifier);
196  m_layer_controllers.push_back(std::move(layer_element_controller));
197  }
198 
199  for (size_t i = 0; i < m_layer_controllers.size() - 1; ++i) {
200  m_layer_controllers.at(i)->setLayerBelow(m_layer_controllers.at(i + 1).get());
201  }
202 
203  if (m_layer_controllers.size() > 0) {
204  m_layer_controllers.at(0)->topSegment()->stretchRight(true);
205  m_layer_controllers.at(0)->topSegment()->setFlag(QGraphicsItem::ItemIsMovable, false);
206  }
207  if (m_layer_controllers.size() > 1) {
208  m_layer_controllers.at(1)->sideSegment()->setFlag(QGraphicsItem::ItemIsMovable, false);
209  m_layer_controllers.at(m_layer_controllers.size() - 1)->topSegment()->stretchLeft(true);
210  }
211 }
212 
213 //! Connect the layer controllers
215 {
216  for (const auto& layer_controller : m_layer_controllers) {
217  QObject::connect(layer_controller.get(), &LayerElementController::heightChanged, this,
219  QObject::connect(layer_controller.get(), &LayerElementController::widthChanged, this,
221  QObject::connect(layer_controller.get(), &LayerElementController::roughnessChanged, this,
223  }
224 }
225 
226 //! Disconnect the layer controllers
228 {
229  for (const auto& layer_controller : m_layer_controllers) {
230  QObject::disconnect(layer_controller.get(), &LayerElementController::heightChanged, this,
232  QObject::disconnect(layer_controller.get(), &LayerElementController::widthChanged, this,
234  QObject::disconnect(layer_controller.get(), &LayerElementController::roughnessChanged, this,
236  }
237 }
238 
239 //! Update the view items with the changes in the material or layer models
241 {
242  if (item && dynamic_cast<MultiLayerItem*>(item->parent())) {
243  buildSLD();
244  return;
245  }
246 
247  for (const auto& layer_controller : m_layer_controllers) {
248  auto layer_item =
249  dynamic_cast<LayerItem*>(p_sample_model->findItem(layer_controller->sampleItemId()));
250  if (!layer_item) {
251  buildSLD();
252  return;
253  }
254  auto roughness_item = layer_item->item<RoughnessItem>(LayerItem::P_ROUGHNESS);
255  auto material_item = dynamic_cast<SLDMaterialItem*>(p_material_model->findItem(
256  layer_item->property<ExternalProperty>(LayerItem::P_MATERIAL).identifier()));
257 
258  layer_controller->layerElementItem()->setProperty(
260  roughness_item->property<double>(RoughnessItem::P_SIGMA));
261  layer_controller->layerElementItem()->setProperty(
262  LayerElementItem::P_WIDTH, layer_item->property<double>(LayerItem::P_THICKNESS));
263 
264  if (material_item) {
265  layer_controller->layerElementItem()->setProperty(
267  material_item->property<double>(SLDMaterialItem::P_SLD_REAL));
268  layer_controller->layerElementItem()->setProperty(
270  material_item->property<QColor>(SLDMaterialItem::P_COLOR));
271  layer_controller->layerElementItem()->setProperty(
273  material_item->property<QColor>(SLDMaterialItem::P_COLOR));
274  } else {
275  layer_controller->layerElementItem()->setProperty(LayerElementItem::P_HEIGHT, 1e-6);
276  layer_controller->layerElementItem()->setProperty(LayerElementItem::P_TOP_BRUSH_COLOR,
277  QColor("red"));
278  layer_controller->layerElementItem()->setProperty(LayerElementItem::P_SIDE_BRUSH_COLOR,
279  QColor("red"));
280  }
281  }
282 }
283 
284 //! Update the material and layer models from the view items
285 void SLDElementController::updateThicknessFromView(std::string identifier, double value)
286 {
287  auto layer_item = dynamic_cast<LayerItem*>(p_sample_model->findItem(identifier));
288  layer_item->setProperty(LayerItem::P_THICKNESS, value);
289 }
290 
291 //! Update the material and layer models from the view items
292 void SLDElementController::updateSLDFromView(std::string identifier, double value)
293 {
294  auto layer_item = dynamic_cast<LayerItem*>(p_sample_model->findItem(identifier));
295  auto material_item = dynamic_cast<SLDMaterialItem*>(p_material_model->findItem(
296  layer_item->property<ExternalProperty>(LayerItem::P_MATERIAL).identifier()));
297  if (material_item)
298  material_item->setProperty(SLDMaterialItem::P_SLD_REAL, value);
299 }
300 
301 //! Update the material and layer models from the view items
302 void SLDElementController::updateRoughnessFromView(std::string identifier, double value)
303 {
304  auto layer_item = dynamic_cast<LayerItem*>(p_sample_model->findItem(identifier));
305  auto roughness_item = layer_item->item<RoughnessItem>(LayerItem::P_ROUGHNESS);
306  roughness_item->setProperty(RoughnessItem::P_SIGMA, value);
307 }
308 
309 } // namespace gui2
Property to carry text, color and identifier.
std::string identifier() const
void setOnItemRemoved(Callbacks::item_tagrow_t f, Callbacks::slot_t client) override
Sets callback to be notified on item remove.
Definition: modelmapper.cpp:69
void setOnItemInserted(Callbacks::item_tagrow_t f, Callbacks::slot_t client) override
Sets callback to be notified on item insert.
Definition: modelmapper.cpp:61
void setOnModelDestroyed(Callbacks::model_t f, Callbacks::slot_t client) override
Sets the callback for notifications on model destruction.
Definition: modelmapper.cpp:84
void setOnDataChange(Callbacks::item_int_t f, Callbacks::slot_t client) override
Sets callback to be notified on item's data change.
Definition: modelmapper.cpp:53
void unsubscribe(Callbacks::slot_t client) override
Removes given client from all subscriptions.
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
SessionItem * parent() const
Returns parent item. Will return nullptr if item doesn't have a parent.
int childrenCount() const
Returns total number of children in all tags.
std::vector< SessionItem * > children() const
Returns vector of children formed from all chidlren from all tags.
T property(const std::string &tag) const
Returns data stored in property item.
Definition: sessionitem.h:181
T * item(const std::string &tag) const
Returns first item under given tag casted to a specified type.
Definition: sessionitem.h:156
void setProperty(const std::string &tag, const T &value)
Sets value to property item.
Definition: sessionitem.h:190
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
ModelMapper * mapper()
Returns model mapper. Can be used to subscribe to various model's signal.
SessionItem * findItem(const identifier_type &id)
Returns SessionItem for given identifier.
SessionItem * rootItem() const
Returns root item of the model.
void clear(std::function< void(SessionItem *)> callback={})
Removes all items from the model.
Aggregate to hold (tag, row) information for SessionModel.
Definition: tagrow.h:25
Custom graphics scene to show QCustomPlot with additional elements on top.
Definition: graphicsscene.h:34
void widthChanged(std::string id, double value) const
void roughnessChanged(std::string id, double value) const
void heightChanged(std::string id, double value) const
static const std::string P_SIDE_BRUSH_COLOR
static const std::string P_TOP_BRUSH_COLOR
static const std::string P_HEIGHT
static const std::string P_WIDTH
static const std::string P_ROUGHNESS
Layer with name, thickness and reference to material.
Definition: sampleitems.h:39
static const std::string P_MATERIAL
Definition: sampleitems.h:42
static const std::string P_THICKNESS
Definition: sampleitems.h:43
static const std::string P_ROUGHNESS
Definition: sampleitems.h:44
static const std::string P_COLOR
Definition: materialitems.h:42
Model to hold MaterialItems.
Definition: materialmodel.h:35
Multi layer capable of holding layers and other multi-layers.
Definition: sampleitems.h:51
static const std::string P_NREPETITIONS
Definition: sampleitems.h:55
Item to represent the roughness of the layer.
Definition: sampleitems.h:28
static const std::string P_SIGMA
Definition: sampleitems.h:30
void updateThicknessFromView(std::string identifier, double value)
Update the material and layer models from the view items.
void disconnectMaterialModel() const
Disconnect with signals of MaterialModel.
void connectMaterialModel()
Connect with signals of MaterialModel.
void clearScene()
Remove all LayerElementControllers and their items from scene and memory.
void updateRoughnessFromView(std::string identifier, double value)
Update the material and layer models from the view items.
void disconnectSLDElementModel() const
Disconnect with signals of SLDViewModel.
void updateSLDFromView(std::string identifier, double value)
Update the material and layer models from the view items.
string_vec getIdentifierVector(ModelView::SessionItem *item)
Get the identifiers of all layeritems in the sample model in order of appearance.
void disconnectLayerControllers()
Disconnect the layer controllers.
void disconnectLayerModel() const
Disconnect with signals of SampleModel.
void connectLayerControllers()
Connect the layer controllers.
std::vector< std::string > string_vec
void setScene(GraphicsScene *scene)
Set the scene of the current controller to be passed to the LayerElementControllers.
void connectLayerModel()
Connect with signals of SampleModel.
void connectSLDElementModel()
Connect with signals of SLDViewModel.
void updateToView(ModelView::SessionItem *item=nullptr)
Update the view items with the changes in the material or layer models.
void buildSLD()
Updates all material properties in LayerItems to get new material colors and labels.
void buildLayerControllers(string_vec &identifiers)
Build and set up the layer controllers.
The model of the sld layer visual representation.
LayerElementItem * addLayer()
Add a layer item.
Represents material based on scattering length density.
Definition: materialitems.h:57
static const std::string P_SLD_REAL
Definition: materialitems.h:59
Model to hold layers and multi-layers.
Definition: samplemodel.h:24
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
materialitems.h Collection of materials to populate MaterialModel.
Based on Qt example "codeeditor" Copyright (C) 2016 The Qt Company Ltd.
Definition: app_constants.h:20
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?