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 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/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 #include <QDebug>
24 
25 const QString SessionItem::P_NAME = "Name";
26 
27 //! Constructs new item with given model type. The type must be defined.
28 SessionItem::SessionItem(const QString& modelType)
29  : m_parent(nullptr)
30  , m_model(nullptr)
31  , m_properties(new SessionItemData)
32  , m_tags(new SessionItemTags)
33 {
34  ASSERT(!modelType.isEmpty());
35 
38  setDecimals(3);
40 }
41 
42 //! Destructor deletes all its children and request parent to delete this item.
43 
45 {
46  if (m_mapper)
47  m_mapper->callOnItemDestroy();
48 
49  QVector<SessionItem*>::const_iterator it;
50  for (it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
51  SessionItem* child = *it;
52  if (child)
53  child->setModel(nullptr);
54  delete child;
55  }
56  m_children.clear();
57  if (m_parent && m_model)
58  m_parent->childDeleted(this);
59 
60  for (IPathTranslator* translator : m_translators)
61  delete translator;
62 }
63 
64 //! Returns model of this item.
65 
67 {
68  return m_model;
69 }
70 
71 //! Returns parent of this item.
72 
74 {
75  return m_parent;
76 }
77 
78 //! Returns model index of this item.
79 
80 QModelIndex SessionItem::index() const
81 {
82  return model() ? model()->indexOfItem(const_cast<SessionItem*>(this)) : QModelIndex();
83 }
84 
85 //! Indicates whether this SessionItem has any child items
86 
88 {
89  return numberOfChildren() > 0;
90 }
91 
92 //! Returns total number of children.
93 
95 {
96  return m_children.size();
97 }
98 
99 //! Returns vector of all children.
100 
101 QVector<SessionItem*> SessionItem::children() const
102 {
103  return m_children;
104 }
105 
106 //! Returns the child at the given row.
107 
109 {
110  return m_children.value(row, nullptr);
111 }
112 
113 //! Returns row index of given child.
114 
116 {
117  return m_children.indexOf(child);
118 }
119 
120 //! Returns the first child of the given type.
121 
122 SessionItem* SessionItem::getChildOfType(const QString& type) const
123 {
124  for (auto child : m_children)
125  if (child->modelType() == type)
126  return child;
127 
128  return nullptr;
129 }
130 
131 //! Returns a vector of all children of the given type.
132 
133 QVector<SessionItem*> SessionItem::getChildrenOfType(const QString& model_type) const
134 {
135  QVector<SessionItem*> result;
136  for (auto child : m_children)
137  if (child->modelType() == model_type)
138  result.append(child);
139 
140  return result;
141 }
142 
143 //! Removes row from item and returns the item.
144 
146 {
147  SessionItem* item = childAt(row);
148  QString tag = tagFromItem(item);
149  auto items = getItems(tag);
150  return takeItem(items.indexOf(item), tag);
151 }
152 
153 //! Add new tag to this item with given name, min, max and types.
154 //! max = -1 -> unlimited, modelTypes empty -> all types allowed
155 
156 bool SessionItem::registerTag(const QString& name, int min, int max, QStringList modelTypes)
157 {
158  return m_tags->registerTag(name, min, max, modelTypes);
159 }
160 
161 //! Returns true if tag is available.
162 
163 bool SessionItem::isTag(const QString& name) const
164 {
165  return m_tags->isValid(name);
166 }
167 
169 {
170  return m_tags.get();
171 }
172 
173 //! Returns the tag name of given item when existing.
174 
175 QString SessionItem::tagFromItem(const SessionItem* item) const
176 {
177  int index = m_children.indexOf(const_cast<SessionItem*>(item));
178  return m_tags->tagFromIndex(index);
179 }
180 
181 //! Returns true if model type can be added to default tag.
182 
183 bool SessionItem::acceptsAsDefaultItem(const QString& item_name) const
184 {
185  return m_tags->isValid(defaultTag(), item_name);
186 }
187 
188 //! Returns vector of acceptable default tag types.
189 
191 {
192  return m_tags->modelTypesForTag(defaultTag()).toVector();
193 }
194 
195 //! Returns item in given row of given tag.
196 
197 SessionItem* SessionItem::getItem(const QString& tag, int row) const
198 {
199  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
200 
201  if (!m_tags->isValid(tagName))
202  return nullptr;
203 
204  if (m_tags->childCount(tagName) == 0)
205  return nullptr;
206 
207  if (row < 0 || row >= m_tags->childCount(tagName))
208  return nullptr;
209 
210  int index = m_tags->indexFromTagRow(tagName, row);
211  ASSERT(index >= 0);
212  ASSERT(index < m_children.size());
213  return m_children[index];
214 }
215 
216 //! Returns vector of all items of given tag.
217 
218 QVector<SessionItem*> SessionItem::getItems(const QString& tag) const
219 {
220  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
221  if (!m_tags->isValid(tagName))
222  return QVector<SessionItem*>();
223 
224  int index = m_tags->tagStartIndex(tagName);
225  ASSERT(index >= 0 && index <= m_children.size());
226  return m_children.mid(index, m_tags->childCount(tagName));
227 }
228 
229 //! Insert item into given tag into given row.
230 bool SessionItem::insertItem(int row, SessionItem* item, const QString& tag)
231 {
232  ASSERT(item);
233  ASSERT(!item->parent());
234 
235  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
236  ASSERT(m_tags->isValid(tagName, item->modelType()));
237 
238  int index = m_tags->insertIndexFromTagRow(tagName, row);
239  ASSERT(index >= 0);
240  ASSERT(index <= m_children.size());
241 
242  if (m_model)
243  m_model->beginInsertRows(this->index(), index, index);
244 
245  item->setParentAndModel(this, m_model);
246  m_children.insert(index, item);
247 
248  m_tags->addChild(tagName);
249  if (m_model)
250  m_model->endInsertRows();
251 
252  return true;
253 }
254 
255 //! Remove item from given row from given tag.
256 
257 SessionItem* SessionItem::takeItem(int row, const QString& tag)
258 {
259  const QString tagName = tag.isEmpty() ? defaultTag() : tag;
260  ASSERT(m_tags->isValid(tagName));
261  ASSERT(!m_tags->isSingleItemTag(tagName));
262 
263  int index = m_tags->indexFromTagRow(tagName, row);
264  ASSERT(index >= 0 && index <= m_children.size());
265 
266  if (m_model)
267  m_model->beginRemoveRows(this->index(), index, index);
268  SessionItem* result = m_children.takeAt(index);
269  result->setParentAndModel(nullptr, nullptr);
270 
271  m_tags->removeChild(tagName);
272  if (m_model)
273  m_model->endRemoveRows();
274  return result;
275 }
276 
277 //! Add new property item and register new tag.
278 
279 SessionItem* SessionItem::addProperty(const QString& name, const QVariant& variant)
280 {
281  ASSERT(!isTag(name));
282 
283  SessionItem* property = ItemFactory::CreateItem("Property");
284  property->setDisplayName(name);
285  registerTag(name, 1, 1, QStringList() << "Property");
286  bool success = insertItem(0, property, name);
287  ASSERT(success);
288 
289  property->setValue(variant);
290  return property;
291 }
292 
293 //! Directly access value of item under given tag.
294 
295 QVariant SessionItem::getItemValue(const QString& tag) const
296 {
297  ASSERT(isTag(tag));
298  return getItem(tag)->value();
299 }
300 
301 //! Directly set value of item under given tag.
302 
303 void SessionItem::setItemValue(const QString& tag, const QVariant& variant)
304 {
305  ASSERT(isTag(tag));
306  getItem(tag)->setValue(variant);
307 }
308 
309 //! Creates new group item and register new tag, returns GroupItem.
310 
311 SessionItem* SessionItem::addGroupProperty(const QString& groupTag, const QString& groupType)
312 {
313  SessionItem* result(0);
314 
315  if (SessionItemUtils::IsValidGroup(groupType)) {
316  // create group item
317  GroupInfo groupInfo = SessionItemUtils::GetGroupInfo(groupType);
318  GroupItem* groupItem = dynamic_cast<GroupItem*>(ItemFactory::CreateItem("GroupProperty"));
319  ASSERT(groupItem);
320  groupItem->setGroupInfo(groupInfo);
321  registerTag(groupTag, 1, 1, QStringList() << "GroupProperty");
322  result = groupItem;
323  } else {
324  // # migration Remove this branch at any convenient occasion. It is not used anymore.
325  // # migration Suggestion is to throw if not SessionItemUtils::IsValidGroup(groupType)
326  qWarning() << "SessionItem::addGroupProperty() is obsolete for single property items. Use "
327  "::addProperty<> instead.";
328  // create single item
329  registerTag(groupTag, 1, 1, QStringList() << groupType);
330  result = ItemFactory::CreateItem(groupType);
331  }
332  ASSERT(result);
333  result->setDisplayName(groupTag);
334  bool success = insertItem(0, result, groupTag);
335  ASSERT(success);
336  return result;
337 }
338 
339 //! Set the current type of group item.
340 
341 SessionItem* SessionItem::setGroupProperty(const QString& groupTag, const QString& modelType) const
342 {
343  return item<GroupItem>(groupTag)->setCurrentType(modelType);
344 }
345 
346 //! Access subitem of group item.
347 
348 SessionItem* SessionItem::getGroupItem(const QString& groupName) const
349 {
350  return item<GroupItem>(groupName)->currentItem();
351 }
352 
353 //! Returns corresponding variant under given role, invalid variant when role is not present.
354 
355 QVariant SessionItem::roleProperty(int role) const
356 {
357  return m_properties->data(role);
358 }
359 
360 //! Set variant to role, create role if not present yet.
361 
362 bool SessionItem::setRoleProperty(int role, const QVariant& value)
363 {
364  bool result = m_properties->setData(role, value);
365  if (result)
366  emitDataChanged(role);
367  return result;
368 }
369 
370 //! Returns vector of all present roles.
371 
372 QVector<int> SessionItem::getRoles() const
373 {
374  return m_properties->roles();
375 }
376 
377 //! Notify model about data changes.
378 
380 {
381  if (m_model) {
382  QModelIndex index = m_model->indexOfItem(this);
383  m_model->dataChanged(index, index.sibling(index.row(), 1), QVector<int>() << role);
384  }
385 }
386 
387 //! Get model type.
388 
389 QString SessionItem::modelType() const
390 {
391  return roleProperty(SessionFlags::ModelTypeRole).toString();
392 }
393 
394 //! Get value.
395 
396 QVariant SessionItem::value() const
397 {
398  return roleProperty(Qt::DisplayRole);
399 }
400 
401 //! Set value, ensure that variant types match.
402 
403 bool SessionItem::setValue(QVariant value)
404 {
406  return setRoleProperty(Qt::DisplayRole, value);
407 }
408 
409 //! Get default tag
410 
411 QString SessionItem::defaultTag() const
412 {
413  return roleProperty(SessionFlags::DefaultTagRole).toString();
414 }
415 
416 //! Set default tag
417 
418 void SessionItem::setDefaultTag(const QString& tag)
419 {
421 }
422 
423 //! Get display name of item, append index if ambigue.
424 
426 {
427  QString result = roleProperty(SessionFlags::DisplayNameRole).toString();
428 
429  if (modelType() == "Property" || modelType() == "GroupProperty" || modelType() == "Parameter"
430  || modelType() == "Parameter Label")
431  return result;
432 
433  if (m_parent) {
434  QString tag = m_parent->tagFromItem(this);
435  // if only one child of this type is allowed, return name without change
437  return result;
438 
439  int index = m_parent->getCopyNumberOfChild(this);
440  if (index >= 0)
441  return result + QString::number(index);
442  }
443  return result;
444 }
445 
446 //! Set display name
447 
448 void SessionItem::setDisplayName(const QString& display_name)
449 {
451 }
452 
453 //! Get item name, return display name if no name is set.
454 QString SessionItem::itemName() const
455 {
456  return isTag(P_NAME) ? getItemValue(P_NAME).toString() : displayName();
457 }
458 
459 //! Set item name, add property if necessary.
460 void SessionItem::setItemName(const QString& name)
461 {
462  if (isTag(P_NAME))
464  else
466 }
467 
468 //! Flags accessors.
469 
470 void SessionItem::setVisible(bool enabled)
471 {
473 }
474 
475 void SessionItem::setEnabled(bool enabled)
476 {
478 }
479 
480 void SessionItem::setEditable(bool enabled)
481 {
483 }
484 
486 {
487  return flags() & SessionFlags::VISIBLE;
488 }
489 
491 {
492  return flags() & SessionFlags::ENABLED;
493 }
494 
496 {
497  return flags() & SessionFlags::EDITABLE;
498 }
499 
501 {
503 }
504 
506 {
507  setRoleProperty(SessionFlags::LimitsRole, QVariant::fromValue<RealLimits>(value));
508  return *this;
509 }
510 
512 {
513  return roleProperty(SessionFlags::DecimalRole).toInt();
514 }
515 
517 {
519  return *this;
520 }
521 
522 QString SessionItem::toolTip() const
523 {
524  return roleProperty(Qt::ToolTipRole).toString();
525 }
526 
527 SessionItem& SessionItem::setToolTip(const QString& tooltip)
528 {
530  return *this;
531 }
532 
533 QString SessionItem::editorType() const
534 {
535  const auto variant = roleProperty(SessionFlags::CustomEditorRole);
536  return variant.isValid() ? variant.toString() : "Default";
537 }
538 
539 SessionItem& SessionItem::setEditorType(const QString& editorType)
540 {
542  return *this;
543 }
544 
545 //! Returns the current model mapper of this item. Creates new one if necessary.
546 
548 {
549  if (!m_mapper) {
550  m_mapper = std::unique_ptr<ModelMapper>(new ModelMapper);
551  m_mapper->setItem(this);
552  }
553  return m_mapper.get();
554 }
555 
556 QStringList SessionItem::translateList(const QStringList& list) const
557 {
558  QStringList result = list;
559  for (const IPathTranslator* translator : m_translators)
560  result = translator->translate(result);
561  // TODO consider adding displayName before translators
562  result << displayName();
563  return result;
564 }
565 
567 {
568  m_translators.push_back(translator.clone());
569 }
570 
572 {
573  return QByteArray();
574 }
575 
576 void SessionItem::deserializeBinaryData(const QByteArray&) {}
577 
579 {
580  int index = rowOfChild(child);
581  ASSERT(index != -1);
582  m_children.replace(index, nullptr);
583 }
584 
586 {
587  setModel(model);
588  m_parent = parent;
589 }
590 
592 {
593  m_model = model;
594 
595  if (m_mapper)
596  m_mapper->setItem(this);
597 
598  for (auto& child : m_children)
599  child->setModel(model);
600 }
601 
603 {
605 
606  if (!flags.isValid())
608 
609  return flags.toInt();
610 }
611 
612 //! internal
613 void SessionItem::changeFlags(bool enabled, int flag)
614 {
615  int flags = this->flags();
616  if (enabled)
617  flags |= flag;
618  else
619  flags &= ~flag;
620 
622 }
623 
624 //! internal
626 {
627  if (!item)
628  return -1;
629  int result = -1;
630  int count = 0;
631  QString model_type = item->modelType();
632  // check child items:
633  for (auto p_child_item : m_children) {
634  QString child_type = p_child_item->modelType();
635  if (p_child_item == item)
636  result = count;
637  if (child_type == model_type && !p_child_item->isTag(P_NAME))
638  ++count;
639  }
640  if (count > 1)
641  return result;
642  return -1;
643 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines class GUIHelpers functions.
Defines class GroupItem.
Defines class ItemFactory.
Defines interface IParameterTranslator and subclasses.
Defines class SessionItemData.
Defines class SessionItemTags.
Defines namespace SessionItemUtils.
Defines class SessionModel.
Defines info for GroupProperty, i.e.
Definition: GroupInfo.h:25
virtual IPathTranslator * clone() const =0
Limits for a real fit parameter.
Definition: RealLimits.h:24
static RealLimits nonnegative()
Creates an object which can have only positive values with 0. included.
Definition: RealLimits.cpp:115
Handles all data roles for SessionItem.
Holds all tag info for SessionItem.
bool isSingleItemTag(const QString &tagName)
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.
SessionItemTags * sessionItemTags()
int decimals() const
virtual ~SessionItem()
Destructor deletes all its children and request parent to delete this item.
Definition: SessionItem.cpp:44
T & groupItem(const QString &groupName) const
Definition: SessionItem.h:168
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag.
SessionItem & setDecimals(int n)
QVector< QString > acceptableDefaultItemTypes() const
Returns vector of acceptable default tag types.
bool insertItem(int row, SessionItem *item, const QString &tag="")
Insert item into given tag into given row.
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.
QVector< SessionItem * > getItems(const QString &tag="") const
Returns vector of all items of given tag.
bool isVisible() const
std::unique_ptr< SessionItemData > m_properties
Definition: SessionItem.h:145
int numberOfChildren() const
Returns total number of children.
Definition: SessionItem.cpp:94
QString displayName() const
Get display name of item, append index if ambigue.
QVariant value() const
Get value.
void setVisible(bool enabled)
Flags accessors.
QVector< int > getRoles() const
Returns vector of all present roles.
int flags() const
SessionItem & setEditorType(const QString &editorType)
bool isEnabled() const
bool setValue(QVariant value)
Set value, ensure that variant types match.
virtual QStringList translateList(const QStringList &list) const
int rowOfChild(SessionItem *child) const
Returns row index of given child.
QString editorType() const
static const QString P_NAME
Definition: SessionItem.h:37
int getCopyNumberOfChild(const SessionItem *item) const
internal
QVariant getItemValue(const QString &tag) const
Directly access 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:144
SessionItem(const QString &modelType="")
Constructs new item with given model type. The type must be defined.
Definition: SessionItem.cpp:28
void setDisplayName(const QString &display_name)
Set display name.
QString defaultTag() const
Get default tag.
SessionItem * addGroupProperty(const QString &groupTag, const QString &groupType)
Creates new group item and register new tag, returns GroupItem.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
SessionModel * m_model
Definition: SessionItem.h:143
SessionItem * parent() const
Returns parent of this item.
Definition: SessionItem.cpp:73
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.
void addTranslator(const IPathTranslator &translator)
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:66
QVector< IPathTranslator * > m_translators
Definition: SessionItem.h:148
SessionItem * takeItem(int row, const QString &tag)
Remove item from given row from given tag.
T * item(const QString &tag) const
Definition: SessionItem.h:151
void setItemValue(const QString &tag, const QVariant &variant)
Directly set value of item under given tag.
virtual QByteArray serializeBinaryData() const
SessionItem * setGroupProperty(const QString &groupTag, const QString &modelType) const
Set the current type of group item.
QVariant roleProperty(int role) const
Returns corresponding variant under given role, invalid variant when role is not present.
void emitDataChanged(int role=Qt::DisplayRole)
Notify model about data changes.
void setEditable(bool enabled)
std::unique_ptr< SessionItemTags > m_tags
Definition: SessionItem.h:146
QVector< SessionItem * > children() const
Returns vector of all children.
RealLimits limits() const
SessionItem * childAt(int row) const
Returns the child at the given row.
SessionItem & setToolTip(const QString &tooltip)
QVector< SessionItem * > getChildrenOfType(const QString &model_type) const
Returns a vector of all children of the given type.
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)
SessionItem * m_parent
Definition: SessionItem.h:142
bool setRoleProperty(int role, const QVariant &value)
Set variant to role, create role if not present yet.
QModelIndex index() const
Returns model index of this item.
Definition: SessionItem.cpp:80
std::unique_ptr< ModelMapper > m_mapper
Definition: SessionItem.h:147
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:87
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
QModelIndex indexOfItem(SessionItem *item) const
SessionItem * CreateItem(const QString &model_name, SessionItem *parent=nullptr)
create SessionItem of specific type and parent
Definition: ItemFactory.cpp:30
std::string model_type
Definition: types.h:23
QString const & name(EShape k)
Definition: particles.cpp:21
QVariant ToolTipRole(const SessionItem &item, int ncol=0)
Returns tooltip for given item.
bool CompatibleVariantTypes(const QVariant &oldValue, const QVariant &newValue)
Returns true if variants has compatible types.
bool IsValidGroup(const QString &group_type)
Returns true if there is registered group.
GroupInfo GetGroupInfo(const QString &group_type)
Returns GroupInfo for group property construction.