BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
SessionItem.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/BaseItem/SessionItem.cpp
6 //! @brief Implements class SessionItem
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 
23 
24 //! Constructs new item with given model type. The type must be defined.
25 SessionItem::SessionItem(const QString& modelType)
26  : m_parent(nullptr)
27  , m_model(nullptr)
28  , m_properties(new SessionItemData)
29  , m_tags(new SessionItemTags)
30 {
31  ASSERT(!modelType.isEmpty());
32 
35  setDecimals(3);
36  setLimits(RealLimits::nonnegative());
37 }
38 
39 //! Destructor deletes all its children and request parent to delete this item.
40 
42 {
43  if (m_mapper)
44  m_mapper->callOnItemDestroy();
45 
46  QVector<SessionItem*>::const_iterator it;
47  for (it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
48  SessionItem* child = *it;
49  if (child)
50  child->setModel(nullptr);
51  delete child;
52  }
53  m_children.clear();
54  if (m_parent && m_model)
55  m_parent->childDeleted(this);
56 }
57 
58 //! Returns model of this item.
59 
61 {
62  return m_model;
63 }
64 
65 //! Returns parent of this item.
66 
68 {
69  return m_parent;
70 }
71 
72 //! Returns model index of this item.
73 
74 QModelIndex SessionItem::index() const
75 {
76  return model() ? model()->indexOfItem(const_cast<SessionItem*>(this)) : QModelIndex();
77 }
78 
79 //! Indicates whether this SessionItem has any child items
80 
82 {
83  return numberOfChildren() > 0;
84 }
85 
86 //! Returns total number of children.
87 
89 {
90  return m_children.size();
91 }
92 
93 //! Returns vector of all children.
94 
95 QVector<SessionItem*> SessionItem::children() const
96 {
97  return m_children;
98 }
99 
100 //! Returns the child at the given row.
101 
103 {
104  return m_children.value(row, nullptr);
105 }
106 
107 //! Returns row index of given child.
108 
109 int SessionItem::rowOfChild(SessionItem* child) const // TODO arg -> const
110 {
111  return m_children.indexOf(child);
112 }
113 
114 //! Returns the first child of the given type.
115 
116 SessionItem* SessionItem::getChildOfType(const QString& type) const
117 {
118  for (auto* child : m_children)
119  if (child->modelType() == type)
120  return child;
121 
122  return nullptr;
123 }
124 
125 //! Returns a vector of all children of the given type.
126 
127 QVector<SessionItem*> SessionItem::childrenOfType(const QString& model_type) const
128 {
129  QVector<SessionItem*> result;
130  for (auto* child : m_children)
131  if (child->modelType() == model_type)
132  result.append(child);
133 
134  return result;
135 }
136 
137 //! Removes row from item and returns the item.
138 
140 {
141  SessionItem* item = childAt(row);
142  QString tag = tagFromItem(item);
143  auto items = getItems(tag);
144  return takeItem(items.indexOf(item), tag);
145 }
146 
147 //! Returns the index of the given item within its parent. Returns -1 when no parent is set.
148 int SessionItem::parentRow() // TODO -> const
149 {
150  if (parentItem())
151  return parentItem()->rowOfChild(this);
152  return -1;
153 }
154 
155 
156 //! Add new tag to this item with given name, min, max and types.
157 //! max = -1 -> unlimited, modelTypes empty -> all types allowed
158 
159 bool SessionItem::registerTag(const QString& name, int min, int max, QStringList modelTypes)
160 {
161  return m_tags->registerTag(name, min, max, modelTypes);
162 }
163 
164 //! Returns true if tag is available.
165 
166 bool SessionItem::isTag(const QString& name) const
167 {
168  return m_tags->isValid(name);
169 }
170 
172 {
173  return m_tags.get();
174 }
175 
176 //! Returns the tag name of given item when existing.
177 
178 QString SessionItem::tagFromItem(const SessionItem* item) const
179 {
180  int index = m_children.indexOf(const_cast<SessionItem*>(item));
181  return m_tags->tagFromIndex(index);
182 }
183 
184 //! Returns true if model type can be added to default tag.
185 
186 bool SessionItem::acceptsAsDefaultItem(const QString& item_name) const
187 {
188  return m_tags->isValid(defaultTag(), item_name);
189 }
190 
191 //! Returns vector of acceptable default tag types.
192 
194 {
195  return m_tags->modelTypesForTag(defaultTag()).toVector();
196 }
197 
198 //! Returns item in given row of given tag.
199 
200 SessionItem* SessionItem::getItem(const QString& tag, int row) const
201 {
202  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
203 
204  if (!m_tags->isValid(tagName))
205  return nullptr;
206 
207  if (m_tags->childCount(tagName) == 0)
208  return nullptr;
209 
210  if (row < 0 || row >= m_tags->childCount(tagName))
211  return nullptr;
212 
213  int index = m_tags->indexFromTagRow(tagName, row);
214  ASSERT(index >= 0);
215  ASSERT(index < m_children.size());
216  return m_children[index];
217 }
218 
219 //! Returns vector of all items of given tag.
220 
221 QVector<SessionItem*> SessionItem::getItems(const QString& tag) const
222 {
223  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
224  if (!m_tags->isValid(tagName))
225  return QVector<SessionItem*>();
226 
227  int index = m_tags->tagStartIndex(tagName);
228  ASSERT(index >= 0 && index <= m_children.size());
229  return m_children.mid(index, m_tags->childCount(tagName));
230 }
231 
232 //! Insert item into given tag into given row.
233 void SessionItem::insertChild(int row, SessionItem* item, const QString& tag)
234 {
235  ASSERT(item);
236  ASSERT(!item->parentItem());
237 
238  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
239  ASSERT(m_tags->isValid(tagName, item->modelType()));
240 
241  int index = m_tags->insertIndexFromTagRow(tagName, row);
242  ASSERT(index >= 0);
243  ASSERT(index <= m_children.size());
244 
245  if (m_model)
246  m_model->beginInsertRows(this->index(), index, index);
247 
248  item->setParentAndModel(this, m_model);
249  m_children.insert(index, item);
250 
251  m_tags->addChild(tagName);
252  if (m_model)
253  m_model->endInsertRows();
254 }
255 
256 //! Remove item from given row from given tag.
257 
258 SessionItem* SessionItem::takeItem(int row, const QString& tag)
259 {
260  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
261  ASSERT(m_tags->isValid(tagName));
262  ASSERT(!m_tags->isSingleItemTag(tagName));
263 
264  int index = m_tags->indexFromTagRow(tagName, row);
265  ASSERT(index >= 0 && index <= m_children.size());
266 
267  if (m_model)
268  m_model->beginRemoveRows(this->index(), index, index);
269  SessionItem* result = m_children.takeAt(index);
270  result->setParentAndModel(nullptr, nullptr);
271 
272  m_tags->removeChild(tagName);
273  if (m_model)
274  m_model->endRemoveRows();
275  return result;
276 }
277 
278 SessionItem* SessionItem::addProperty(const QString& name, const QVariant& variant)
279 {
280  ASSERT(!isTag(name));
281 
283  property->setDisplayName(name);
285  insertChild(0, property, name);
286  property->setValue(variant);
287  return property;
288 }
289 
290 //! Directly access value of item under given tag.
291 
292 QVariant SessionItem::getItemValue(const QString& tag) const
293 {
294  ASSERT(isTag(tag));
295  return getItem(tag)->value();
296 }
297 
298 //! Directly set value of item under given tag.
299 
300 void SessionItem::setItemValue(const QString& tag, const QVariant& variant) const
301 {
302  ASSERT(isTag(tag));
303  getItem(tag)->setValue(variant);
304 }
305 
306 SessionItem* SessionItem::addGroupProperty(const QString& groupTag, const GroupInfo& groupInfo)
307 {
310  ASSERT(groupItem);
311  groupItem->setGroupInfo(groupInfo);
312  registerTag(groupTag, 1, 1, {GroupItem::M_TYPE});
313  groupItem->setDisplayName(groupTag);
314  insertChild(0, groupItem, groupTag);
315  return groupItem;
316 }
317 
318 //! Set the current type of group item.
319 
320 SessionItem* SessionItem::setGroupProperty(const QString& groupTag, const QString& modelType) const
321 {
322  return item<GroupItem>(groupTag)->setCurrentType(modelType);
323 }
324 
325 //! Access subitem of group item.
326 
327 SessionItem* SessionItem::getGroupItem(const QString& groupName) const
328 {
329  return item<GroupItem>(groupName)->currentItem();
330 }
331 
332 //! Returns corresponding variant under given role, invalid variant when role is not present.
333 
334 QVariant SessionItem::roleProperty(int role) const
335 {
336  return m_properties->data(role);
337 }
338 
339 //! Set variant to role, create role if not present yet.
340 
341 bool SessionItem::setRoleProperty(int role, const QVariant& value)
342 {
343  bool result = m_properties->setData(role, value);
344  if (result)
345  emitDataChanged(role);
346  return result;
347 }
348 
349 //! Returns vector of all present roles.
350 
351 QVector<int> SessionItem::getRoles() const
352 {
353  return m_properties->roles();
354 }
355 
356 //! Notify model about data changes.
357 
359 {
360  if (m_model) {
361  QModelIndex index = m_model->indexOfItem(this);
362  m_model->dataChanged(index, index.sibling(index.row(), 1), QVector<int>() << role);
363  }
364 }
365 
366 //! Get model type.
367 
368 QString SessionItem::modelType() const
369 {
370  return roleProperty(SessionFlags::ModelTypeRole).toString();
371 }
372 
373 //! Get value.
374 
375 QVariant SessionItem::value() const
376 {
377  return roleProperty(Qt::DisplayRole);
378 }
379 
380 //! Set value, ensure that variant types match.
381 
382 bool SessionItem::setValue(QVariant value)
383 {
384  ASSERT(GUI::Util::Variant::CompatibleVariantTypes(this->value(), value));
385  return setRoleProperty(Qt::DisplayRole, value);
386 }
387 
388 //! Get default tag
389 
390 QString SessionItem::defaultTag() const
391 {
392  return roleProperty(SessionFlags::DefaultTagRole).toString();
393 }
394 
395 //! Set default tag
396 
397 void SessionItem::setDefaultTag(const QString& tag)
398 {
400 }
401 
402 //! Get display name of item, append index if ambigue.
403 
405 {
406  QString result = roleProperty(SessionFlags::DisplayNameRole).toString();
407 
408  if (hasModelType<PropertyItem>() || hasModelType<GroupItem>())
409  return result;
410 
411  if (m_parent) {
412  QString tag = m_parent->tagFromItem(this);
413  // if only one child of this type is allowed, return name without change
415  return result;
416 
417  int index = m_parent->getCopyNumberOfChild(this);
418  if (index >= 0)
419  return result + QString::number(index);
420  }
421  return result;
422 }
423 
424 //! Set display name
425 
426 void SessionItem::setDisplayName(const QString& display_name)
427 {
429 }
430 
431 //! Get item name, return display name if no name is set.
432 QString SessionItem::itemName() const
433 {
434  return isTag(P_NAME) ? getItemValue(P_NAME).toString() : displayName();
435 }
436 
437 //! Set item name, add property if necessary.
438 void SessionItem::setItemName(const QString& name)
439 {
440  if (isTag(P_NAME))
442  else
444 }
445 
447 {
448  return P_NAME == name;
449 }
450 
451 //! Flags accessors.
452 
453 void SessionItem::setEnabled(bool enabled)
454 {
456 }
457 
458 void SessionItem::setEditable(bool enabled)
459 {
461 }
462 
464 {
465  return flags() & SessionFlags::ENABLED;
466 }
467 
469 {
470  return flags() & SessionFlags::EDITABLE;
471 }
472 
473 RealLimits SessionItem::limits() const
474 {
475  return roleProperty(SessionFlags::LimitsRole).value<RealLimits>();
476 }
477 
478 SessionItem& SessionItem::setLimits(const RealLimits& value)
479 {
480  setRoleProperty(SessionFlags::LimitsRole, QVariant::fromValue<RealLimits>(value));
481  return *this;
482 }
483 
485 {
486  return roleProperty(SessionFlags::DecimalRole).toInt();
487 }
488 
490 {
492  return *this;
493 }
494 
495 QString SessionItem::toolTip() const
496 {
497  return roleProperty(Qt::ToolTipRole).toString();
498 }
499 
500 SessionItem& SessionItem::setToolTip(const QString& tooltip)
501 {
502  setRoleProperty(Qt::ToolTipRole, tooltip);
503  return *this;
504 }
505 
506 //! Returns the current model mapper of this item. Creates new one if necessary.
507 
509 {
510  if (!m_mapper) {
511  m_mapper = std::make_unique<ModelMapper>();
512  m_mapper->setItem(this);
513  }
514  return m_mapper.get();
515 }
516 
518 {
519  return QByteArray();
520 }
521 
522 void SessionItem::deserializeBinaryData(const QByteArray&) {}
523 
524 void SessionItem::writeNonSessionItems(QXmlStreamWriter*) const {}
525 
526 void SessionItem::readNonSessionItems(QXmlStreamReader*) {}
527 
529 {
530  return true;
531 }
532 
534 {
535  int index = rowOfChild(child);
536  ASSERT(index != -1);
537  m_children.replace(index, nullptr);
538 }
539 
541 {
542  setModel(model);
543  m_parent = parent;
544 }
545 
547 {
548  m_model = model;
549 
550  if (m_mapper)
551  m_mapper->setItem(this);
552 
553  for (auto& child : m_children)
554  child->setModel(model);
555 }
556 
558 {
560 
561  if (!flags.isValid())
563 
564  return flags.toInt();
565 }
566 
567 //! internal
568 void SessionItem::changeFlags(bool enabled, int flag)
569 {
570  int flags = this->flags();
571  if (enabled)
572  flags |= flag;
573  else
574  flags &= ~flag;
575 
577 }
578 
579 //! internal
581 {
582  if (!item)
583  return -1;
584  int result = -1;
585  int count = 0;
586  QString model_type = item->modelType();
587  // check child items:
588  for (auto* p_child_item : m_children) {
589  QString child_type = p_child_item->modelType();
590  if (p_child_item == item)
591  result = count;
592  if (child_type == model_type && !p_child_item->isTag(P_NAME))
593  ++count;
594  }
595  if (count > 1)
596  return result;
597  return -1;
598 }
Defines class GroupItem.
Defines namespace GUI::Model::ItemFactory.
Defines class PropertyItem.
Defines class SessionFlags.
Defines class SessionItemData.
Defines class SessionItemTags.
Defines class SessionModel.
Defines namespace GUI::Util::Variant.
Defines info for GroupProperty, i.e. collection of model types, their labels and the name of default ...
Definition: GroupInfo.h:25
static constexpr auto M_TYPE
Definition: GroupItem.h:30
static constexpr auto M_TYPE
Definition: PropertyItem.h:22
Handles all data roles for SessionItem.
Holds all tag info for SessionItem.
bool isSingleItemTag(const QString &tagName) const
Base class for a GUI data item.
Definition: SessionItem.h:204
bool isTag(const QString &name) const
Returns true if tag is available.
void setParentAndModel(SessionItem *parent, SessionModel *model)
QString itemName() const
Get item name, return display name if no name is set.
void setItemName(const QString &name)
Set item name, add property if necessary.
int decimals() const
virtual ~SessionItem()
Destructor deletes all its children and request parent to delete this item.
Definition: SessionItem.cpp:41
T & groupItem(const QString &groupName) const
Definition: SessionItem.h:413
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag. name is the tag name and the display name....
SessionItem & setDecimals(int n)
QVector< QString > acceptableDefaultItemTypes() const
Returns vector of acceptable default tag types.
SessionItem * getGroupItem(const QString &groupName) const
Access subitem of group item.
bool registerTag(const QString &name, int min=0, int max=-1, QStringList modelTypes={})
Add new tag to this item with given name, min, max and types. max = -1 -> unlimited,...
QVector< SessionItem * > getItems(const QString &tag="") const
Returns vector of all items of given tag.
SessionItem(const QString &modelType)
Constructs new item with given model type. The type must be defined.
Definition: SessionItem.cpp:25
std::unique_ptr< SessionItemData > m_properties
Definition: SessionItem.h:333
int numberOfChildren() const
Returns total number of children.
Definition: SessionItem.cpp:88
void insertChild(int row, SessionItem *item, const QString &tag="")
Insert item into given tag into given row.
QString displayName() const
Get display name of item, append index if ambigue.
QVariant value() const
Get value.
QVector< int > getRoles() const
Returns vector of all present roles.
int flags() const
bool isEnabled() const
bool setValue(QVariant value)
Set value, ensure that variant types match.
int rowOfChild(SessionItem *child) const
Returns row index of given child.
const SessionItemTags * sessionItemTags() const
int getCopyNumberOfChild(const SessionItem *item) const
internal
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
void setItemValue(const QString &tag, const QVariant &variant) const
Directly set value of item under given tag.
bool acceptsAsDefaultItem(const QString &item_name) const
Returns true if model type can be added to default tag.
bool isEditable() const
QVector< SessionItem * > m_children
Definition: SessionItem.h:332
void setDisplayName(const QString &display_name)
Set display name.
QString defaultTag() const
Get default tag.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
SessionModel * m_model
Definition: SessionItem.h:331
virtual void deserializeBinaryData(const QByteArray &data)
void setDefaultTag(const QString &tag)
Set default tag.
QString toolTip() const
SessionItem * takeRow(int row)
Removes row from item and returns the item.
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:60
SessionItem * takeItem(int row, const QString &tag)
Remove item from given row from given tag.
T * item(const QString &tag) const
Definition: SessionItem.h:353
virtual QByteArray serializeBinaryData() const
static constexpr auto P_NAME
Definition: SessionItem.h:208
SessionItem * parentItem() const
Returns parent of this item.
Definition: SessionItem.cpp:67
SessionItem * addGroupProperty(const QString &groupTag, const GroupInfo &groupInfo)
QVector< T * > items(const QString &tag="") const
Definition: SessionItem.h:361
SessionItem * setGroupProperty(const QString &groupTag, const QString &modelType) const
Set the current type of group item.
virtual bool allowWritingChildToXml(SessionItem *child) const
QVariant roleProperty(int role) const
Returns corresponding variant under given role, invalid variant when role is not present.
int parentRow()
Returns the index of the given item within its parent. Returns -1 when no parent is set.
void emitDataChanged(int role=Qt::DisplayRole)
Notify model about data changes.
void setEditable(bool enabled)
virtual void writeNonSessionItems(QXmlStreamWriter *writer) const
std::unique_ptr< SessionItemTags > m_tags
Definition: SessionItem.h:334
QVector< SessionItem * > children() const
Returns vector of all children.
Definition: SessionItem.cpp:95
RealLimits limits() const
SessionItem * childAt(int row) const
Returns the child at the given row.
SessionItem & setToolTip(const QString &tooltip)
static bool isItemNamePropertyName(const QString &name)
QVector< T * > childrenOfType() const
Definition: SessionItem.h:372
QString modelType() const
Get model type.
QString tagFromItem(const SessionItem *item) const
Returns the tag name of given item when existing.
void setEnabled(bool enabled)
Flags accessors.
SessionItem * m_parent
Definition: SessionItem.h:330
bool setRoleProperty(int role, const QVariant &value)
Set the contained role property to the given value. See also setTranslatorForRolePropertySetter.
QModelIndex index() const
Returns model index of this item.
Definition: SessionItem.cpp:74
std::unique_ptr< ModelMapper > m_mapper
Definition: SessionItem.h:335
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
void setModel(SessionModel *model)
bool hasChildren() const
Indicates whether this SessionItem has any child items.
Definition: SessionItem.cpp:81
virtual void readNonSessionItems(QXmlStreamReader *reader)
SessionItem * getChildOfType(const QString &type) const
Returns the first child of the given type.
SessionItem & setLimits(const RealLimits &value)
void childDeleted(SessionItem *child)
void changeFlags(bool enabled, int flag)
internal
Base class for a GUI data collection. A collection is e.g. all real data (RealDataModel)....
Definition: SessionModel.h:42
QModelIndex indexOfItem(SessionItem *item) const
SessionItem * CreateItem(const QString &model_name, SessionItem *parent=nullptr)
create SessionItem of specific type and parent
Definition: ItemFactory.cpp:19
QString const & name(EShape k)
Definition: particles.cpp:20
bool CompatibleVariantTypes(const QVariant &oldValue, const QVariant &newValue)
Returns true if variants has compatible types.
Definition: VariantUtil.cpp:25