BornAgain  1.19.79
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/Model/BaseItem/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 
17 
18 ModelMapper::ModelMapper(QObject* parent)
19  : QObject(parent)
20  , m_active(true)
21  , m_model(nullptr)
22  , m_item(nullptr)
23 {
24 }
25 
27 {
28  if (item) {
29  m_item = item;
30  setModel(item->model());
31  }
32 }
33 
34 void ModelMapper::setOnValueChange(std::function<void(void)> f, const void* caller)
35 {
36  m_onValueChange.emplace_back(f, caller);
37 }
38 
39 void ModelMapper::setOnPropertyChange(std::function<void(QString)> f, const void* caller)
40 {
41  auto ff = [=](SessionItem* /*item*/, const QString& property) { f(property); };
42  m_onPropertyChange.emplace_back(ff, caller);
43 }
44 
45 void ModelMapper::setOnPropertyChange(std::function<void(SessionItem*, QString)> f,
46  const void* caller)
47 {
48  m_onPropertyChange.emplace_back(f, caller);
49 }
50 
51 //! Calls back on child property change, report childItem and property name.
52 
53 void ModelMapper::setOnChildPropertyChange(std::function<void(SessionItem*, QString)> f,
54  const void* caller)
55 {
56  m_onChildPropertyChange.emplace_back(f, caller);
57 }
58 
59 //! Calls back when number of children has changed, reports newChild.
60 //! newChild == nullptr denotes the case when number of children has decreased.
61 
62 void ModelMapper::setOnChildrenChange(std::function<void(SessionItem*)> f, const void* caller)
63 {
64  m_onChildrenChange.emplace_back(f, caller);
65 }
66 
67 void ModelMapper::setOnItemDestroy(std::function<void(SessionItem*)> f, const void* caller)
68 {
69  m_onItemDestroy.emplace_back(f, caller);
70 }
71 
72 void ModelMapper::setOnAboutToRemoveChild(std::function<void(SessionItem*)> f, const void* caller)
73 {
74  m_onAboutToRemoveChild.emplace_back(f, caller);
75 }
76 
77 //! Cancels all subscriptions of given caller
78 void ModelMapper::unsubscribe(const void* caller)
79 {
86 }
87 
89 {
90  if (m_model) {
91  disconnect(m_model, &SessionModel::dataChanged, this, &ModelMapper::onDataChanged);
92  disconnect(m_model, &SessionModel::rowsInserted, this, &ModelMapper::onRowsInserted);
93  disconnect(m_model, &SessionModel::rowsAboutToBeRemoved, this,
95  disconnect(m_model, &SessionModel::rowsRemoved, this, &ModelMapper::onRowRemoved);
96  }
97  m_model = model;
98  if (m_model) {
99  connect(m_model, &SessionModel::dataChanged, this, &ModelMapper::onDataChanged);
100  connect(m_model, &SessionModel::rowsInserted, this, &ModelMapper::onRowsInserted);
101  connect(m_model, &SessionModel::rowsAboutToBeRemoved, this,
103  connect(m_model, &SessionModel::rowsRemoved, this, &ModelMapper::onRowRemoved);
104  }
105 }
106 
108 {
109  if (item == nullptr || item == m_model->rootItem())
110  return -1;
111  if (item == m_item)
112  return level;
113 
114  return nestlingDepth(item->parentItem(), level + 1);
115 }
116 
118 {
119  if (m_active && !m_onValueChange.empty())
120  for (const auto& f : m_onValueChange)
121  f.first();
122 }
123 
125 {
126  if (m_active)
127  for (const auto& f : m_onPropertyChange)
128  f.first(m_item, name);
129 }
130 
132 {
133  if (m_active)
134  for (const auto& f : m_onChildPropertyChange)
135  f.first(item, name);
136 }
137 
139 {
140  if (m_active)
141  for (const auto& f : m_onChildrenChange)
142  f.first(item);
143 }
144 
146 {
147  if (m_active)
148  for (const auto& f : m_onAboutToRemoveChild)
149  f.first(item);
150 }
151 
152 //! Notifies subscribers if an item owning given mapper is about to be destroyed
154 {
155  if (m_active)
156  for (const auto& f : m_onItemDestroy)
157  f.first(m_item);
158 }
159 
161 {
162  m_item = nullptr;
163  setModel(nullptr);
164  m_onValueChange.clear();
165  m_onPropertyChange.clear();
166  m_onChildPropertyChange.clear();
167  m_onChildrenChange.clear();
168  m_onItemDestroy.clear();
169  m_onAboutToRemoveChild.clear();
170 }
171 
172 void ModelMapper::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
173  const QVector<int>& /*roles*/)
174 {
175  if (topLeft.parent() != bottomRight.parent())
176  return; // range must be from the same parent
177 
178  SessionItem* item = m_model->itemForIndex(topLeft);
179 
180  int nestling = nestlingDepth(item);
181  if (nestling == 0)
183 
184  if (nestling == 1) {
185  // something happened with our children
186  if (SessionItem* item = m_model->itemForIndex(topLeft)) {
187  // only care f
188  const QString tag = m_item->tagFromItem(item);
189  if (!tag.isEmpty())
191  }
192  }
193  if (nestling > 1) {
194  if (SessionItem* parent = item->parentItem()) {
195  const QString tag = parent->tagFromItem(item);
196  if (!tag.isEmpty())
197  callOnChildPropertyChange(parent, tag);
198  }
199  }
200 }
201 
202 void ModelMapper::onRowsInserted(const QModelIndex& parent, int first, int /*last*/)
203 {
204  SessionItem* newChild = m_model->itemForIndex(m_model->index(first, 0, parent));
205 
206  if (nestlingDepth(newChild) == 1)
207  callOnChildrenChange(newChild);
208 }
209 
210 void ModelMapper::onBeginRemoveRows(const QModelIndex& parent, int first, int /*last*/)
211 {
212  SessionItem* oldChild = m_model->itemForIndex(m_model->index(first, 0, parent));
213 
214  int nestling = nestlingDepth(m_model->itemForIndex(parent));
215 
216  if (oldChild && nestling == 0)
217  callOnAboutToRemoveChild(oldChild);
218 
219  if (m_item == oldChild)
220  m_aboutToDelete = m_model->index(first, 0, parent);
221 }
222 
223 void ModelMapper::onRowRemoved(const QModelIndex& parent, int first, int /*last*/)
224 {
225  if (nestlingDepth(m_model->itemForIndex(parent)) == 0)
226  callOnChildrenChange(nullptr);
227 
228  if (m_aboutToDelete.isValid() && m_aboutToDelete == m_model->index(first, 0, parent))
229  clearMapper();
230 }
Defines class ModelMapper.
Defines class SessionModel.
ModelMapper(QObject *parent=nullptr)
Definition: ModelMapper.cpp:18
void unsubscribe(const void *caller)
Cancels all subscriptions of given caller.
Definition: ModelMapper.cpp:78
void setOnAboutToRemoveChild(std::function< void(SessionItem *)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:72
void onBeginRemoveRows(const QModelIndex &parent, int first, int last)
void callOnPropertyChange(const QString &name)
void onRowRemoved(const QModelIndex &parent, int first, int last)
void clearMapper()
void callOnChildPropertyChange(SessionItem *item, const QString &name)
void callOnItemDestroy()
Notifies subscribers if an item owning given mapper is about to be destroyed.
void setOnItemDestroy(std::function< void(SessionItem *)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:67
void callOnValueChange()
void clean_container(U &v, const void *caller)
removes all callbacks related to given caller
Definition: ModelMapper.h:98
void callOnChildrenChange(SessionItem *item)
void setOnChildrenChange(std::function< void(SessionItem *)> f, const void *caller=nullptr)
Calls back when number of children has changed, reports newChild. newChild == nullptr denotes the cas...
Definition: ModelMapper.cpp:62
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles={})
std::vector< call_item_t > m_onChildrenChange
Definition: ModelMapper.h:91
std::vector< call_t > m_onValueChange
Definition: ModelMapper.h:88
QModelIndex m_aboutToDelete
Definition: ModelMapper.h:94
void setItem(SessionItem *item)
Definition: ModelMapper.cpp:26
void setModel(SessionModel *model)
Definition: ModelMapper.cpp:88
SessionModel * m_model
Definition: ModelMapper.h:80
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:39
bool m_active
Definition: ModelMapper.h:79
std::vector< call_item_str_t > m_onPropertyChange
Definition: ModelMapper.h:89
SessionItem * m_item
Definition: ModelMapper.h:81
int nestlingDepth(SessionItem *item, int level=0)
std::vector< call_item_str_t > m_onChildPropertyChange
Definition: ModelMapper.h:90
void callOnAboutToRemoveChild(SessionItem *item)
std::vector< call_item_t > m_onItemDestroy
Definition: ModelMapper.h:92
void onRowsInserted(const QModelIndex &parent, int first, int last)
void setOnValueChange(std::function< void(void)> f, const void *caller=nullptr)
Definition: ModelMapper.cpp:34
void setOnChildPropertyChange(std::function< void(SessionItem *, QString)> f, const void *caller=nullptr)
Calls back on child property change, report childItem and property name.
Definition: ModelMapper.cpp:53
std::vector< call_item_t > m_onAboutToRemoveChild
Definition: ModelMapper.h:93
Base class for a GUI data item.
Definition: SessionItem.h:204
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:60
SessionItem * parentItem() const
Returns parent of this item.
Definition: SessionItem.cpp:67
QString tagFromItem(const SessionItem *item) const
Returns the tag name of given item when existing.
Base class for a GUI data collection. A collection is e.g. all real data (RealDataModel)....
Definition: SessionModel.h:42
SessionItem * itemForIndex(const QModelIndex &index) const
QModelIndex index(int row, int column, const QModelIndex &parent) const override
SessionItem * rootItem() const
QString const & name(EShape k)
Definition: particles.cpp:20