BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
viewmodelcontroller.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // qt-mvvm: Model-view-view-model framework for large GUI applications
4 //
5 //! @file mvvm/viewmodel/mvvm/viewmodel/viewmodelcontroller.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 Gennady Pospelov et al, Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
18 #include "mvvm/model/itemutils.h"
19 #include "mvvm/model/modelutils.h"
20 #include "mvvm/model/path.h"
21 #include "mvvm/model/sessionitem.h"
27 #include <map>
28 #include <stdexcept>
29 
30 using namespace ModelView;
31 
32 namespace {
33 
34 //! Returns true if given SessionItem role is valid for view
35 bool isValidItemRole(const ViewItem* view, int item_role)
36 {
37  if (view->item_role() == item_role)
38  return true;
39 
40  if (item_role == ItemDataRole::APPEARANCE || item_role == ItemDataRole::TOOLTIP)
41  return true;
42  return false;
43 }
44 
45 } // namespace
46 
50  std::unique_ptr<ChildrenStrategyInterface> m_childrenStrategy;
51  std::unique_ptr<RowStrategyInterface> m_rowStrategy;
52  std::map<SessionItem*, ViewItem*> m_itemToVview; //! correspondence of item and its view
54 
56  : m_self(controller), m_viewModel(view_model)
57  {
58  }
59 
61  {
62  const std::string msg("Error in ViewModelController: ");
63  if (!m_viewModel)
64  throw std::runtime_error(msg + "ViewModel is not defined");
65 
66  if (!m_rowStrategy)
67  throw std::runtime_error(msg + "RowStrategy is not defined");
68 
69  if (!m_childrenStrategy)
70  throw std::runtime_error(msg + "Children is not defined");
71  }
72 
74  {
76  m_itemToVview.clear();
79  }
80 
81  void iterate(const SessionItem* item, ViewItem* parent)
82  {
83  ViewItem* origParent(parent);
84  for (auto child : m_childrenStrategy->children(item)) {
85  auto row = m_rowStrategy->constructRow(child);
86  if (!row.empty()) {
87  auto next_parent = row.at(0).get();
88  m_viewModel->appendRow(parent, std::move(row));
89  m_itemToVview[child] = next_parent;
90  parent = next_parent; // labelItem
91  iterate(child, parent);
92  }
93  parent = origParent;
94  }
95  }
96 
97  //! Remove row of ViewItem's corresponding to given item.
98 
100  {
101  auto pos = m_itemToVview.find(item);
102  if (pos != m_itemToVview.end()) {
103  auto view = pos->second;
104  m_viewModel->removeRow(view->parent(), view->row());
105  m_itemToVview.erase(pos);
106  }
107  }
108 
110  {
111  for (auto child : view->children()) {
112  auto pos = std::find_if(m_itemToVview.begin(), m_itemToVview.end(),
113  [child](const auto& it) { return it.second == child; });
114  if (pos != m_itemToVview.end())
115  m_itemToVview.erase(pos);
116  }
117 
118  m_viewModel->clearRows(view);
119  }
120 
121  void insert_view(SessionItem* parent, const TagRow& tagrow)
122  {
123  auto child = parent->getItem(tagrow.tag, tagrow.row);
124  auto children = m_childrenStrategy->children(parent);
125  auto index = Utils::IndexOfItem(children, child);
126  if (index == -1)
127  return;
128 
129  auto pos = m_itemToVview.find(parent);
130  if (pos == m_itemToVview.end())
131  return;
132 
133  auto parent_view = pos->second;
134 
135  auto row = m_rowStrategy->constructRow(child);
136  if (!row.empty()) {
137  auto next_parent = row.at(0).get();
138  m_viewModel->insertRow(parent_view, index, std::move(row));
139  m_itemToVview[child] = next_parent;
140  parent_view = next_parent; // labelItem
141  iterate(child, parent_view);
142  }
143  }
144 
145  std::vector<ViewItem*> findViews(const SessionItem* item) const
146  {
147  if (item == m_viewModel->rootItem()->item())
148  return {m_viewModel->rootItem()};
149 
150  std::vector<ViewItem*> result;
151  auto on_index = [&](const QModelIndex& index) {
152  auto view_item = m_viewModel->itemFromIndex(index);
153  if (view_item->item() == item)
154  result.push_back(view_item);
155  };
156  Utils::iterate_model(m_viewModel, QModelIndex(), on_index);
157  return result;
158  }
159 
161  {
163  m_viewModel->setRootViewItem(std::make_unique<RootViewItem>(item));
164  init_view_model();
165  }
166 };
167 
169  : ModelListener(session_model)
170  , p_impl(std::make_unique<ViewModelControllerImpl>(this, view_model))
171 {
172  auto on_data_change = [this](SessionItem* item, int role) { onDataChange(item, role); };
173  setOnDataChange(on_data_change);
174 
175  auto on_item_inserted = [this](SessionItem* item, TagRow tagrow) {
176  onItemInserted(item, std::move(tagrow));
177  };
178  setOnItemInserted(on_item_inserted);
179 
180  auto on_item_removed = [this](SessionItem* item, TagRow tagrow) {
181  onItemRemoved(item, std::move(tagrow));
182  };
183  setOnItemRemoved(on_item_removed);
184 
185  auto on_about_to_remove = [this](SessionItem* item, TagRow tagrow) {
186  onAboutToRemoveItem(item, std::move(tagrow));
187  };
188  setOnAboutToRemoveItem(on_about_to_remove);
189 
190  auto on_model_destroyed = [this](auto) {
191  p_impl->m_viewModel->setRootViewItem(std::make_unique<RootViewItem>(nullptr));
192  };
193  setOnModelDestroyed(on_model_destroyed);
194 
195  auto on_model_reset = [this](auto) {
196  auto root_item = Utils::ItemFromPath(*model(), p_impl->m_rootItemPath);
197  p_impl->setRootSessionItemIntern(root_item ? root_item : model()->rootItem());
198  p_impl->m_viewModel->endResetModel();
199  };
200  setOnModelReset(on_model_reset);
201 
202  auto on_model_about_to_be_reset = [this](auto) { p_impl->m_viewModel->beginResetModel(); };
203  setOnModelAboutToBeReset(on_model_about_to_be_reset);
204 }
205 
207 {
208  p_impl->m_viewModel = view_model;
209 }
210 
212 
214  std::unique_ptr<ChildrenStrategyInterface> children_strategy)
215 {
216  p_impl->m_childrenStrategy = std::move(children_strategy);
217 }
218 
219 void ViewModelController::setRowStrategy(std::unique_ptr<RowStrategyInterface> row_strategy)
220 {
221  p_impl->m_rowStrategy = std::move(row_strategy);
222 }
223 
224 //! Returns SessionModel handled by this controller.
225 
227 {
228  return model();
229 }
230 
232 {
233  if (!item)
234  throw std::runtime_error(
235  "Error in ViewModelController: atttemp to set nulptr as root item");
236 
237  if (item->model() != model())
238  throw std::runtime_error(
239  "Error in ViewModelController: atttemp to use item from alien model as new root.");
240 
241  p_impl->m_viewModel->beginResetModel();
242  p_impl->setRootSessionItemIntern(item);
243  p_impl->m_viewModel->endResetModel();
244 }
245 
247 {
248  return p_impl->m_viewModel->rootItem()->item();
249 }
250 
251 //! Returns all ViewItem's displaying given SessionItem.
252 
253 std::vector<ViewItem*> ViewModelController::findViews(const SessionItem* item) const
254 {
255  return p_impl->findViews(item);
256 }
257 
259 {
260  return p_impl->m_rowStrategy->horizontalHeaderLabels();
261 }
262 
264 {
265  for (auto view : findViews(item)) {
266  // inform corresponding LabelView and DataView
267  if (isValidItemRole(view, role)) {
268  auto index = p_impl->m_viewModel->indexFromItem(view);
269  p_impl->m_viewModel->dataChanged(index, index, Utils::ItemRoleToQtRole(role));
270  }
271  }
272 }
273 
275 {
276  p_impl->insert_view(parent, tagrow);
277 }
278 
280 
282 {
283  auto item_to_remove = parent->getItem(tagrow.tag, tagrow.row);
284  if (item_to_remove == rootSessionItem()
285  || Utils::IsItemAncestor(rootSessionItem(), item_to_remove)) {
286  // special case when user removes SessionItem which is one of ancestors of our root item
287  // or root item iteslf
288  p_impl->m_viewModel->beginResetModel();
289  p_impl->m_viewModel->setRootViewItem(std::make_unique<RootViewItem>(nullptr));
290  p_impl->m_itemToVview.clear();
291  p_impl->m_rootItemPath = {};
292  p_impl->m_viewModel->endResetModel();
293  } else {
294  p_impl->remove_row_of_views(item_to_remove);
295  }
296 }
297 
299 {
300  auto views = findViews(item);
301  if (views.empty())
302  return;
303 
304  for (auto view : views)
305  p_impl->remove_children_of_view(view);
306 
307  p_impl->iterate(item, views.at(0));
308 }
Defines class CLASS?
void setOnItemRemoved(Callbacks::item_tagrow_t f, Callbacks::slot_t client={}) override
Sets callback to be notified on item remove.
void setOnItemInserted(Callbacks::item_tagrow_t f, Callbacks::slot_t client={}) override
Sets callback to be notified on item insert.
void setOnModelDestroyed(Callbacks::model_t f, Callbacks::slot_t client={}) override
Sets the callback for notifications on model destruction.
void setOnAboutToRemoveItem(Callbacks::item_tagrow_t f, Callbacks::slot_t client={}) override
Sets callback to be notified when the item is about to be removed.
void setOnModelAboutToBeReset(Callbacks::model_t f, Callbacks::slot_t client={}) override
Sets the callback to be notified before model's full reset (root item recreated).
void setOnDataChange(Callbacks::item_int_t f, Callbacks::slot_t client={}) override
Sets callback to be notified on item's data change.
void setOnModelReset(Callbacks::model_t f, Callbacks::slot_t client={}) override
Sets the callback to be notified after model was fully reset (root item recreated).
Templated class for all objects willing to listen for changes in concrete SessionModel.
Definition: modellistener.h:26
Supports navigation through SessionModel.
Definition: path.h:35
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
SessionItem * getItem(const std::string &tag, int row=0) const
Returns item at given row of given tag.
SessionModel * model() const
Returns the model to which given item belongs to.
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
Aggregate to hold (tag, row) information for SessionModel.
Definition: tagrow.h:25
std::string tag
Definition: tagrow.h:27
Represents the view of SessionItem's data in a single cell of ViewModel.
Definition: viewitem.h:29
int row() const
Returns the row where the item is located in its parent's child table, or -1 if the item has no paren...
Definition: viewitem.cpp:181
int item_role() const
Definition: viewitem.cpp:173
std::vector< ViewItem * > children() const
Definition: viewitem.cpp:237
ViewItem * parent() const
Definition: viewitem.cpp:158
SessionItem * item() const
Definition: viewitem.cpp:168
Base class for all view models to show content of SessionModel in Qt views.
Definition: viewmodelbase.h:31
void removeRow(ViewItem *parent, int row)
void appendRow(ViewItem *parent, std::vector< std::unique_ptr< ViewItem >> items)
Appends row of items to given parent.
ViewItem * rootItem() const
Returns a pointer to invisible root item.
void clearRows(ViewItem *parent)
void insertRow(ViewItem *parent, int row, std::vector< std::unique_ptr< ViewItem >> items)
Insert a row of items at index 'row' to given parent.
void setRootViewItem(std::unique_ptr< ViewItem > root_item)
Sets new root item. Previous item will be deleted, model will be reset.
ViewItem * itemFromIndex(const QModelIndex &index) const
Returns a pointer to the RefViewItem associated with the given index.
Propagates changes from SessionModel to its ViewModelBase.
void setChildrenStrategy(std::unique_ptr< ChildrenStrategyInterface > children_strategy)
void setRootSessionItem(SessionItem *item)
std::unique_ptr< ViewModelControllerImpl > p_impl
virtual void onAboutToRemoveItem(SessionItem *parent, TagRow tagrow)
std::vector< ViewItem * > findViews(const ModelView::SessionItem *item) const
Returns all ViewItem's displaying given SessionItem.
virtual void onItemRemoved(SessionItem *parent, TagRow tagrow)
void update_branch(const SessionItem *item)
ViewModelController(SessionModel *session_model, ViewModelBase *view_model=nullptr)
void setViewModel(ViewModelBase *view_model)
SessionModel * sessionModel() const
Returns SessionModel handled by this controller.
virtual void onDataChange(SessionItem *item, int role)
void setRowStrategy(std::unique_ptr< RowStrategyInterface > row_strategy)
QStringList horizontalHeaderLabels() const
virtual void onItemInserted(SessionItem *parent, TagRow tagrow)
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
const int TOOLTIP
tooltip for item's data
Definition: mvvm_types.h:34
const int APPEARANCE
appearance flag
Definition: mvvm_types.h:32
MVVM_VIEWMODEL_EXPORT QVector< int > ItemRoleToQtRole(int role)
Returns vector of Qt roles corresponding to given ItemDataRole.
int IndexOfItem(It begin, It end, const T &item)
Returns index corresponding to the first occurance of the item in the container.
MVVM_VIEWMODEL_EXPORT void iterate_model(const QAbstractItemModel *model, const QModelIndex &parent, const std::function< void(const QModelIndex &child)> &fun)
Iterates through QAbstractItem model.
MVVM_MODEL_EXPORT SessionItem * ItemFromPath(const SessionModel &moodel, const Path &path)
Returns item found in the model following given Path.
Definition: modelutils.cpp:36
MVVM_MODEL_EXPORT Path PathFromItem(const SessionItem *item)
Constructs path to find given item. Item must belong to a model.
Definition: modelutils.cpp:22
MVVM_MODEL_EXPORT bool IsItemAncestor(const SessionItem *item, const SessionItem *candidate)
Returns true if 'candidate' is one of ancestor of given item.
Definition: itemutils.cpp:156
materialitems.h Collection of materials to populate MaterialModel.
Definition: filesystem.h:81
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
std::unique_ptr< RowStrategyInterface > m_rowStrategy
Path m_rootItemPath
correspondence of item and its view
std::unique_ptr< ChildrenStrategyInterface > m_childrenStrategy
std::vector< ViewItem * > findViews(const SessionItem *item) const
void iterate(const SessionItem *item, ViewItem *parent)
void remove_row_of_views(SessionItem *item)
Remove row of ViewItem's corresponding to given item.
ViewModelControllerImpl(ViewModelController *controller, ViewModelBase *view_model)
void insert_view(SessionItem *parent, const TagRow &tagrow)
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?