BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ModelMapper.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/ModelMapper.cpp
6 //! @brief Implements class ModelMapper
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 
17 ModelMapper::ModelMapper(QObject* parent)
18  : QObject(parent), m_active(true), m_model(nullptr), m_item(nullptr)
19 {
20 }
21 
23 {
24  if (item) {
25  m_item = item;
26  setModel(item->model());
27  }
28 }
29 
30 void ModelMapper::setOnValueChange(std::function<void(void)> f, const void* caller)
31 {
32  m_onValueChange.push_back(call_t(f, caller));
33 }
34 
35 void ModelMapper::setOnPropertyChange(std::function<void(QString)> f, const void* caller)
36 {
37  auto ff = [=](SessionItem* /*item*/, const QString& property) { f(property); };
38  m_onPropertyChange.push_back(call_item_str_t(ff, caller));
39 }
40 
41 void ModelMapper::setOnPropertyChange(std::function<void(SessionItem*, QString)> f,
42  const void* caller)
43 {
44  m_onPropertyChange.push_back(call_item_str_t(f, caller));
45 }
46 
47 //! Calls back on child property change, report childItem and property name.
48 
49 void ModelMapper::setOnChildPropertyChange(std::function<void(SessionItem*, QString)> f,
50  const void* caller)
51 {
52  m_onChildPropertyChange.push_back(call_item_str_t(f, caller));
53 }
54 
55 //! Calls back when parent has changed, reports newParent.
56 //! If newParent=0, the item is about being to be removed from children. Method parent()
57 //! will still report old parent.
58 //! If newParent!=0, it is just the same as parent().
59 
60 void ModelMapper::setOnParentChange(std::function<void(SessionItem*)> f, const void* caller)
61 {
62  m_onParentChange.push_back(call_item_t(f, caller));
63 }
64 
65 //! Calls back when number of children has changed, reports newChild.
66 //! newChild == nullptr denotes the case when number of children has decreased.
67 
68 void ModelMapper::setOnChildrenChange(std::function<void(SessionItem*)> f, const void* caller)
69 {
70  m_onChildrenChange.push_back(call_item_t(f, caller));
71 }
72 
73 void ModelMapper::setOnSiblingsChange(std::function<void()> f, const void* caller)
74 {
75  m_onSiblingsChange.push_back(call_t(f, caller));
76 }
77 
78 //! Calls back on any change in children (number of children or their properties),
79 //! reports childItem.
80 //! childItem == nullptr denotes the case when child was removed.
81 
82 void ModelMapper::setOnAnyChildChange(std::function<void(SessionItem*)> f, const void* caller)
83 {
84  m_onAnyChildChange.push_back(call_item_t(f, caller));
85 }
86 
87 void ModelMapper::setOnItemDestroy(std::function<void(SessionItem*)> f, const void* caller)
88 {
89  m_onItemDestroy.push_back(call_item_t(f, caller));
90 }
91 
92 void ModelMapper::setOnAboutToRemoveChild(std::function<void(SessionItem*)> f, const void* caller)
93 {
94  m_onAboutToRemoveChild.push_back(call_item_t(f, caller));
95 }
96 
97 //! Cancells all subscribtion of given caller
98 void ModelMapper::unsubscribe(const void* caller)
99 {
109 }
110 
112 {
113  if (m_model) {
114  disconnect(m_model, &SessionModel::dataChanged, this, &ModelMapper::onDataChanged);
115  disconnect(m_model, &SessionModel::rowsInserted, this, &ModelMapper::onRowsInserted);
116  disconnect(m_model, &SessionModel::rowsAboutToBeRemoved, this,
118  disconnect(m_model, &SessionModel::rowsRemoved, this, &ModelMapper::onRowRemoved);
119  }
120  m_model = model;
121  if (m_model) {
122  connect(m_model, &SessionModel::dataChanged, this, &ModelMapper::onDataChanged);
123  connect(m_model, &SessionModel::rowsInserted, this, &ModelMapper::onRowsInserted);
124  connect(m_model, &SessionModel::rowsAboutToBeRemoved, this,
126  connect(m_model, &SessionModel::rowsRemoved, this, &ModelMapper::onRowRemoved);
127  }
128 }
129 
131 {
132  if (item == nullptr || item == m_model->rootItem())
133  return -1;
134  if (item == m_item)
135  return level;
136 
137  return nestlingDepth(item->parent(), level + 1);
138 }
139 
141 {
142  if (m_active && m_onValueChange.size() > 0)
143  for (auto f : m_onValueChange)
144  f.first();
145 }
146 
148 {
149  if (m_active)
150  for (auto f : m_onPropertyChange)
151  f.first(m_item, name);
152 }
153 
155 {
156  if (m_active)
157  for (auto f : m_onChildPropertyChange)
158  f.first(item, name);
159 }
160 
162 {
163  if (m_active)
164  for (auto f : m_onParentChange)
165  f.first(new_parent);
166 }
167 
169 {
170  if (m_active)
171  for (auto f : m_onChildrenChange)
172  f.first(item);
173 }
174 
176 {
177  if (m_active)
178  for (auto f : m_onSiblingsChange)
179  f.first();
180 }
181 
183 {
184  if (m_active)
185  for (auto f : m_onAnyChildChange)
186  f.first(item);
187 }
188 
190 {
191  if (m_active)
192  for (auto f : m_onAboutToRemoveChild)
193  f.first(item);
194 }
195 
196 //! Notifies subscribers if an item owning given mapper is about to be destroyed
198 {
199  if (m_active)
200  for (auto f : m_onItemDestroy)
201  f.first(m_item);
202 }
203 
205 {
206  m_item = nullptr;
207  setModel(nullptr);
208  m_onValueChange.clear();
209  m_onPropertyChange.clear();
210  m_onChildPropertyChange.clear();
211  m_onParentChange.clear();
212  m_onChildrenChange.clear();
213  m_onSiblingsChange.clear();
214  m_onAnyChildChange.clear();
215  m_onItemDestroy.clear();
216  m_onAboutToRemoveChild.clear();
217 }
218 
219 void ModelMapper::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
220  const QVector<int>& /*roles*/)
221 {
222  if (topLeft.parent() != bottomRight.parent())
223  return; // range must be from the same parent
224 
225  SessionItem* item = m_model->itemForIndex(topLeft);
226 
227  int nestling = nestlingDepth(item);
228  if (nestling == 0)
230 
231  if (nestling == 1) {
232  // something happened with our children
233  if (SessionItem* item = m_model->itemForIndex(topLeft)) {
234  // only care f
235  const QString tag = m_item->tagFromItem(item);
236  if (!tag.isEmpty()) {
238  }
239  }
240  }
241  if (nestling > 1) {
242  if (SessionItem* parent = item->parent()) {
243  const QString tag = parent->tagFromItem(item);
244  if (!tag.isEmpty()) {
245  callOnChildPropertyChange(parent, tag);
246  }
247  }
248  }
249  if (nestling > 0)
250  callOnAnyChildChange(item);
251 }
252 
253 void ModelMapper::onRowsInserted(const QModelIndex& parent, int first, int /*last*/)
254 {
255  SessionItem* newChild = m_model->itemForIndex(m_model->index(first, 0, parent));
256 
257  int nestling = nestlingDepth(newChild);
258 
259  if (newChild)
260  if (m_item == newChild)
262  if (nestling == 1)
263  callOnChildrenChange(newChild);
264  if (SessionItem* parent = newChild->parent()) {
265  QVector<SessionItem*> items = parent->getChildrenOfType(newChild->modelType());
266  for (auto sibling : items)
267  if (m_item == sibling)
269  }
270  if (nestling > 0) {
271  callOnAnyChildChange(newChild);
272  }
273 }
274 
275 void ModelMapper::onBeginRemoveRows(const QModelIndex& parent, int first, int /*last*/)
276 {
277  SessionItem* oldChild = m_model->itemForIndex(m_model->index(first, 0, parent));
278 
279  int nestling = nestlingDepth(m_model->itemForIndex(parent));
280 
281  if (oldChild) {
282  if (m_item == oldChild)
283  callOnParentChange(nullptr);
284  if (nestling == 0)
285  callOnAboutToRemoveChild(oldChild);
286  }
287 
288  if (m_item == oldChild)
289  m_aboutToDelete = m_model->index(first, 0, parent);
290 }
291 
292 void ModelMapper::onRowRemoved(const QModelIndex& parent, int first, int /*last*/)
293 {
294  int nestling = nestlingDepth(m_model->itemForIndex(parent));
295 
296  if (nestling >= 0 || m_model->itemForIndex(parent) == m_item->parent()) {
297  callOnAnyChildChange(nullptr);
299  }
300  if (nestling == 0)
301  callOnChildrenChange(nullptr);
302 
303  if (m_aboutToDelete.isValid() && m_aboutToDelete == m_model->index(first, 0, parent))
304  clearMapper();
305 }
Defines class SessionModel.
void unsubscribe(const void *caller)
Cancells all subscribtion of given caller.
Definition: ModelMapper.cpp:98
void setOnItemDestroy(std::function< void(SessionItem *)> f, const void *caller=0)
Definition: ModelMapper.cpp:87
std::vector< call_item_t > m_onAnyChildChange
Definition: ModelMapper.h:101
void setOnAnyChildChange(std::function< void(SessionItem *)> f, const void *caller=0)
Calls back on any change in children (number of children or their properties), reports childItem.
Definition: ModelMapper.cpp:82
void onBeginRemoveRows(const QModelIndex &parent, int first, int last)
void callOnPropertyChange(const QString &name)
void onRowRemoved(const QModelIndex &parent, int first, int last)
void setOnValueChange(std::function< void(void)> f, const void *caller=0)
Definition: ModelMapper.cpp:30
void clearMapper()
std::vector< call_item_t > m_onParentChange
Definition: ModelMapper.h:98
void callOnChildPropertyChange(SessionItem *item, const QString &name)
std::pair< std::function< void(SessionItem *, QString)>, const void * > call_item_str_t
Definition: ModelMapper.h:93
void callOnItemDestroy()
Notifies subscribers if an item owning given mapper is about to be destroyed.
void setOnChildPropertyChange(std::function< void(SessionItem *, QString)> f, const void *caller=0)
Calls back on child property change, report childItem and property name.
Definition: ModelMapper.cpp:49
void callOnValueChange()
void clean_container(U &v, const void *caller)
removes all callbacks related to given caller
Definition: ModelMapper.h:107
void callOnAnyChildChange(SessionItem *item)
std::pair< std::function< void(SessionItem *)>, const void * > call_item_t
Definition: ModelMapper.h:92
void callOnChildrenChange(SessionItem *item)
void setOnAboutToRemoveChild(std::function< void(SessionItem *)> f, const void *caller=0)
Definition: ModelMapper.cpp:92
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=0)
Definition: ModelMapper.cpp:35
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles={})
std::vector< call_item_t > m_onChildrenChange
Definition: ModelMapper.h:99
std::vector< call_t > m_onValueChange
Definition: ModelMapper.h:95
QModelIndex m_aboutToDelete
Definition: ModelMapper.h:104
void setItem(SessionItem *item)
Definition: ModelMapper.cpp:22
void setOnChildrenChange(std::function< void(SessionItem *)> f, const void *caller=0)
Calls back when number of children has changed, reports newChild.
Definition: ModelMapper.cpp:68
std::vector< call_t > m_onSiblingsChange
Definition: ModelMapper.h:100
void setModel(SessionModel *model)
SessionModel * m_model
Definition: ModelMapper.h:87
std::pair< std::function< void(void)>, const void * > call_t
Definition: ModelMapper.h:90
bool m_active
Definition: ModelMapper.h:86
std::vector< call_item_str_t > m_onPropertyChange
Definition: ModelMapper.h:96
SessionItem * m_item
Definition: ModelMapper.h:88
void callOnSiblingsChange()
int nestlingDepth(SessionItem *item, int level=0)
std::vector< call_item_str_t > m_onChildPropertyChange
Definition: ModelMapper.h:97
void callOnAboutToRemoveChild(SessionItem *item)
void setOnSiblingsChange(std::function< void(void)> f, const void *caller=0)
Definition: ModelMapper.cpp:73
std::vector< call_item_t > m_onItemDestroy
Definition: ModelMapper.h:102
void setOnParentChange(std::function< void(SessionItem *)> f, const void *caller=0)
Calls back when parent has changed, reports newParent.
Definition: ModelMapper.cpp:60
ModelMapper(QObject *parent=0)
Definition: ModelMapper.cpp:17
void callOnParentChange(SessionItem *new_parent)
void onRowsInserted(const QModelIndex &parent, int first, int last)
std::vector< call_item_t > m_onAboutToRemoveChild
Definition: ModelMapper.h:103
SessionItem * parent() const
Returns parent of this item.
Definition: SessionItem.cpp:73
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:66
QString modelType() const
Get model type.
QString tagFromItem(const SessionItem *item) const
Returns the tag name of given item when existing.
SessionItem * itemForIndex(const QModelIndex &index) const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
SessionItem * rootItem() const
QString const & name(EShape k)
Definition: particles.cpp:21