BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
sessionitem.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/model/mvvm/model/sessionitem.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 
15 #include "mvvm/model/sessionitem.h"
21 #include "mvvm/model/taginfo.h"
24 #include <stdexcept>
25 
26 using namespace ModelView;
27 
28 namespace {
29 int appearance(const ModelView::SessionItem& item)
30 {
31  const int default_appearance = Appearance::EDITABLE | Appearance::ENABLED;
33  : default_appearance;
34 }
35 } // namespace
36 
38  SessionItem* m_self{nullptr};
39  SessionItem* m_parent{nullptr};
40  SessionModel* m_model{nullptr};
41  std::unique_ptr<ItemMapper> m_mapper;
42  std::unique_ptr<SessionItemData> m_data;
43  std::unique_ptr<SessionItemTags> m_tags;
45 
47  : m_self(this_item)
48  , m_data(std::make_unique<SessionItemData>())
49  , m_tags(std::make_unique<SessionItemTags>())
50  {
51  }
52 
53  bool do_setData(const Variant& variant, int role)
54  {
55  bool result = m_data->setData(variant, role);
56  if (result && m_model)
57  m_model->mapper()->callOnDataChange(m_self, role);
58  return result;
59  }
60 };
61 
62 SessionItem::SessionItem(model_type modelType) : p_impl(std::make_unique<SessionItemImpl>(this))
63 {
64  p_impl->m_modelType = std::move(modelType);
66  setData(p_impl->m_modelType, ItemDataRole::DISPLAY);
67 }
68 
70 {
71  if (p_impl->m_mapper)
72  p_impl->m_mapper->callOnItemDestroy();
73 
74  if (p_impl->m_model)
75  p_impl->m_model->unregisterFromPool(this);
76 }
77 
78 //! Returns item's model type.
79 
81 {
82  return p_impl->m_modelType;
83 }
84 
85 //! Returns unique identifier.
86 
87 std::string SessionItem::identifier() const
88 {
89  return data<std::string>(ItemDataRole::IDENTIFIER);
90 }
91 
92 //! Returns display name.
93 
94 std::string SessionItem::displayName() const
95 {
96  return data<std::string>(ItemDataRole::DISPLAY);
97 }
98 
99 //! Sets display name (fluent interface).
100 
102 {
104  return this;
105 }
106 
107 //! Returns the model to which given item belongs to. Will return nullptr if item doesn't have a
108 //! model.
109 
111 {
112  return p_impl->m_model;
113 }
114 
115 //! Returns parent item. Will return nullptr if item doesn't have a parent.
116 
118 {
119  return p_impl->m_parent;
120 }
121 
122 //! Returns TagRow of this item under which it is accessible through its parent.
123 
125 {
126  return parent() ? parent()->tagRowOfItem(this) : TagRow();
127 }
128 
129 //! Returns true if item has data on board with given role.
130 
131 bool SessionItem::hasData(int role) const
132 {
133  return p_impl->m_data->hasData(role);
134 }
135 
136 //! Returns pointer to item's data container (const version).
137 
139 {
140  return p_impl->m_data.get();
141 }
142 
143 //! Returns pointer to item's data container (non-const version).
144 
146 {
147  return const_cast<SessionItemData*>(static_cast<const SessionItem*>(this)->itemData());
148 }
149 
150 //! Returns total number of children in all tags.
151 
153 {
154  return static_cast<int>(children().size());
155 }
156 
157 //! Returns vector of children formed from all chidlren from all tags.
158 
159 std::vector<SessionItem*> SessionItem::children() const
160 {
161  return p_impl->m_tags->allitems();
162 }
163 
164 //! Returns number of items in given tag.
165 
166 int SessionItem::itemCount(const std::string& tag) const
167 {
168  return p_impl->m_tags->itemCount(tag);
169 }
170 
171 //! Returns item at given row of given tag.
172 
173 SessionItem* SessionItem::getItem(const std::string& tag, int row) const
174 {
175  return p_impl->m_tags->getItem({tag, row});
176 }
177 
178 //! Returns all children stored at given tag.
179 
180 std::vector<SessionItem*> SessionItem::getItems(const std::string& tag) const
181 {
182  return p_impl->m_tags->getItems(tag);
183 }
184 
185 //! Returns pair of tag and row corresponding to given item.
186 //! Returns {"", -1} if given item doesn't belong to children.
187 
189 {
190  return p_impl->m_tags->tagRowOfItem(item);
191 }
192 
193 //! Returns pointer to internal collection of tag-registered items (const version).
194 
196 {
197  return p_impl->m_tags.get();
198 }
199 
200 //! Registers tag to hold items under given name.
201 
202 void SessionItem::registerTag(const TagInfo& tagInfo, bool set_as_default)
203 {
204  p_impl->m_tags->registerTag(tagInfo, set_as_default);
205 }
206 
207 //! Returns pointer to internal collection of tag-registered items (non-const version).
208 
210 {
211  return const_cast<SessionItemTags*>(static_cast<const SessionItem*>(this)->itemTags());
212 }
213 
214 //! Insert item into given tag under the given row.
215 
216 bool SessionItem::insertItem(SessionItem* item, const TagRow& tagrow)
217 {
218  // think of passing unique_ptr directly
219 
220  if (!item)
221  throw std::runtime_error("SessionItem::insertItem() -> Invalid item.");
222 
223  if (item->parent())
224  throw std::runtime_error("SessionItem::insertItem() -> Existing parent.");
225 
226  if (item->model())
227  throw std::runtime_error("SessionItem::insertItem() -> Existing model.");
228 
229  auto result = p_impl->m_tags->insertItem(item, tagrow);
230  if (result) {
231  item->setParent(this);
232  item->setModel(model());
233 
234  if (p_impl->m_model) {
235  // FIXME think of actual_tagrow removal if input tag,row will be always valid
236  auto actual_tagrow = tagRowOfItem(item);
237  p_impl->m_model->mapper()->callOnItemInserted(this, actual_tagrow);
238  }
239  }
240 
241  return result;
242 }
243 
244 //! Removes item from given row from given tag, returns it to the caller.
245 
247 {
248  if (!p_impl->m_tags->canTakeItem(tagrow))
249  return nullptr;
250 
251  if (p_impl->m_model)
252  p_impl->m_model->mapper()->callOnItemAboutToBeRemoved(this, tagrow);
253 
254  auto result = p_impl->m_tags->takeItem(tagrow);
255  result->setParent(nullptr);
256  result->setModel(nullptr);
257  // FIXME remaining problem is that ItemMapper still looking to the model
258  if (p_impl->m_model)
259  p_impl->m_model->mapper()->callOnItemRemoved(this, tagrow);
260 
261  return result;
262 }
263 
264 //! Returns true if this item has `editable` flag set.
265 //! The data value of an editable item normally can be changed when it appears in trees and tables.
266 
268 {
269  return appearance(*this) & Appearance::EDITABLE;
270 }
271 
272 //! Sets `editable` flag to given value (fluent interface).
273 
275 {
277  return this;
278 }
279 
280 //! Returns true if this item has `enabled` flag set.
281 //! Enabled items appear in normal color, disabled items are grayed out.
282 
284 {
285  return appearance(*this) & Appearance::ENABLED;
286 }
287 
288 //! Sets `enabled` flag to given value (fluent interface).
289 
291 {
293  return this;
294 }
295 
296 //! Returns item tooltip, if exists.
297 
298 std::string SessionItem::toolTip() const
299 {
300  return hasData(ItemDataRole::TOOLTIP) ? data<std::string>(ItemDataRole::TOOLTIP)
301  : std::string();
302 }
303 
304 //! Sets item tooltip (fluent interface).
305 
306 SessionItem* SessionItem::setToolTip(const std::string& tooltip)
307 {
308  setData(tooltip, ItemDataRole::TOOLTIP);
309  return this;
310 }
311 
312 //! Returns editor type.
313 
314 std::string SessionItem::editorType() const
315 {
316  return hasData(ItemDataRole::EDITORTYPE) ? data<std::string>(ItemDataRole::EDITORTYPE)
317  : std::string();
318 }
319 
320 //! Sets editor type (fluent interface).
321 //! Allows creating custom editors in the cells of Qt trees and tables.
322 
323 SessionItem* SessionItem::setEditorType(const std::string& editor_type)
324 {
325  setData(editor_type, ItemDataRole::EDITORTYPE);
326  return this;
327 }
328 
329 //! Sets the data for given role. Method invented to hide implementaiton details.
330 
331 bool SessionItem::set_data_internal(const Variant& value, int role, bool direct)
332 {
333  // If model is present, and undo stack is enabled, will forward request to the model
334  // (unless user explicitely asks for direct processing via direct=true flag).
335  const bool act_through_model = !direct && model() && model()->undoStack();
336  return act_through_model ? model()->setData(this, value, role)
337  : p_impl->do_setData(value, role);
338 }
339 
340 //! Returns data for given role. Method invented to hide implementaiton details and avoid
341 //! placing sessionitemdata.h into 'sessionitem.h' header.
342 
344 {
345  return p_impl->m_data->data(role);
346 }
347 
349 {
350  p_impl->m_parent = parent;
351 }
352 
354 {
355  if (p_impl->m_model)
356  p_impl->m_model->unregisterFromPool(this);
357 
358  p_impl->m_model = model;
359 
360  if (p_impl->m_model)
361  p_impl->m_model->registerInPool(this);
362 
363  for (auto child : children())
364  child->setModel(model);
365 }
366 
367 void SessionItem::setAppearanceFlag(int flag, bool value)
368 {
369  int flags = appearance(*this);
370  if (value)
371  flags |= flag;
372  else
373  flags &= ~flag;
374 
375  // By setting data with internal method we are bypassing the model, and so undo/redo.
376  // So current convention is to not invoke undo when changing appearance properties.
377  // Shall we change it?
378  p_impl->do_setData(flags, ItemDataRole::APPEARANCE);
379 }
380 
381 //! Returns item mapper. Allows subscribing to various events happening to the item.
382 
384 {
385  if (!p_impl->m_mapper)
386  p_impl->m_mapper = std::make_unique<ItemMapper>(this);
387  return p_impl->m_mapper.get();
388 }
389 
390 void SessionItem::setDataAndTags(std::unique_ptr<SessionItemData> data,
391  std::unique_ptr<SessionItemTags> tags)
392 {
393  p_impl->m_data = std::move(data);
394  p_impl->m_tags = std::move(tags);
395 }
Provides notifications on various changes for a specific item.
Definition: itemmapper.h:32
Handles data roles for SessionItem.
Collection of SessionItem's containers according to their tags.
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
SessionItemTags * itemTags()
Returns pointer to internal collection of tag-registered items (non-const version).
std::unique_ptr< SessionItemImpl > p_impl
Definition: sessionitem.h:133
std::string identifier() const
Returns unique identifier.
Definition: sessionitem.cpp:87
int itemCount(const std::string &tag) const
Returns number of items in given tag.
TagRow tagRowOfItem(const SessionItem *item) const
Returns pair of tag and row corresponding to given item.
std::vector< SessionItem * > getItems(const std::string &tag) const
Returns all children stored at given tag.
SessionItem * setEditable(bool value)
Sets editable flag to given value (fluent interface).
SessionItem * setEnabled(bool value)
Sets enabled flag to given value (fluent interface).
SessionItem * takeItem(const TagRow &tagrow)
Removes item from given row from given tag, returns it to the caller.
SessionItem * setToolTip(const std::string &tooltip)
Sets item tooltip (fluent interface).
SessionItem * getItem(const std::string &tag, int row=0) const
Returns item at given row of given tag.
bool hasData(int role=ItemDataRole::DATA) const
Returns true if item has data on board with given role.
SessionItem(model_type modelType=Constants::BaseType)
Definition: sessionitem.cpp:62
void setDataAndTags(std::unique_ptr< SessionItemData > data, std::unique_ptr< SessionItemTags > tags)
std::string editorType() const
Returns editor type.
bool isEnabled() const
Returns true if this item has enabled flag set.
void setAppearanceFlag(int flag, bool value)
void registerTag(const TagInfo &tagInfo, bool set_as_default=false)
Registers tag to hold items under given name.
bool setData(const T &value, int role=ItemDataRole::DATA, bool direct=false)
Sets data for a given role.
Definition: sessionitem.h:141
std::string toolTip() const
Returns item tooltip, if exists.
bool isEditable() const
Returns true if this item has editable flag set.
SessionItem * setEditorType(const std::string &editor_type)
Sets editor type (fluent interface).
SessionItem * parent() const
Returns parent item. Will return nullptr if item doesn't have a parent.
bool set_data_internal(const Variant &value, int role, bool direct)
Sets the data for given role. Method invented to hide implementaiton details.
SessionModel * model() const
Returns the model to which given item belongs to.
int childrenCount() const
Returns total number of children in all tags.
void setParent(SessionItem *parent)
T data(int role=ItemDataRole::DATA) const
Returns data of given type T for given role.
Definition: sessionitem.h:148
ItemMapper * mapper()
Returns item mapper. Allows subscribing to various events happening to the item.
std::vector< SessionItem * > children() const
Returns vector of children formed from all chidlren from all tags.
SessionItemData * itemData()
Returns pointer to item's data container (non-const version).
virtual std::string displayName() const
Returns display name.
Definition: sessionitem.cpp:94
bool insertItem(SessionItem *item, const TagRow &tagrow)
Insert item into given tag under the given row.
TagRow tagRow() const
Returns TagRow of this item under which it is accessible through its parent.
T * item(const std::string &tag) const
Returns first item under given tag casted to a specified type.
Definition: sessionitem.h:156
Variant data_internal(int role) const
Returns data for given role.
virtual SessionItem * setDisplayName(const std::string &name)
Sets display name (fluent interface).
model_type modelType() const
Returns item's model type.
Definition: sessionitem.cpp:80
void setModel(SessionModel *model)
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
bool setData(SessionItem *item, const Variant &value, int role)
Sets the data for given item.
UndoStackInterface * undoStack() const
Returns command stack to perform undo/redo.
Holds info about single tag for SessionItem.
Definition: taginfo.h:28
Aggregate to hold (tag, row) information for SessionModel.
Definition: tagrow.h:25
static identifier_type generate()
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
const int TOOLTIP
tooltip for item's data
Definition: mvvm_types.h:34
const int EDITORTYPE
type of custom editor for the data role
Definition: mvvm_types.h:35
const int APPEARANCE
appearance flag
Definition: mvvm_types.h:32
const int DISPLAY
display name
Definition: mvvm_types.h:31
const int IDENTIFIER
unique identifier
Definition: mvvm_types.h:29
materialitems.h Collection of materials to populate MaterialModel.
std::string model_type
Definition: types.h:23
QString const & name(EShape k)
Definition: particles.cpp:21
Definition: filesystem.h:81
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
bool do_setData(const Variant &variant, int role)
Definition: sessionitem.cpp:53
std::unique_ptr< SessionItemTags > m_tags
Definition: sessionitem.cpp:43
SessionItemImpl(SessionItem *this_item)
Definition: sessionitem.cpp:46
std::unique_ptr< SessionItemData > m_data
Definition: sessionitem.cpp:42
std::unique_ptr< ItemMapper > m_mapper
Definition: sessionitem.cpp:41
Defines class CLASS?
Defines class CLASS?
QVariant Variant
Definition: variant.h:23