BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FitParameterProxyModel.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/FitParameterProxyModel.cpp
6 //! @brief Implements class FitParameterAbsModel
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 
22 #include <QMimeData>
23 
25 
27  QObject* parent)
28  : QAbstractItemModel(parent), m_root_item(fitParContainer)
29 {
30  addColumn(PAR_NAME, "Name", "Name of fit parameter");
31  addColumn(PAR_TYPE, FitParameterItem::P_TYPE, "Fit parameter limits type");
32  addColumn(PAR_VALUE, FitParameterItem::P_START_VALUE, "Starting value of fit parameter");
33  addColumn(PAR_MIN, FitParameterItem::P_MIN, "Lower bound on fit parameter value");
34  addColumn(PAR_MAX, FitParameterItem::P_MAX, "Upper bound on fit parameter value");
35 
36  connectModel(fitParContainer->model());
37 
39  [this](SessionItem* parentItem) {
40  if (parentItem != m_root_item) {
41  throw GUIHelpers::Error(
42  "FitParameterProxyModel::FitParameterProxyModel() -> Error. "
43  "Wrong item reported.");
44  }
45  m_root_item = 0;
46  },
47  this);
48 }
49 
51 {
52  if (m_root_item) {
53  m_root_item->mapper()->unsubscribe(this);
54  }
55 }
56 
57 Qt::ItemFlags FitParameterProxyModel::flags(const QModelIndex& index) const
58 {
59  if (!m_root_item)
60  return Qt::NoItemFlags;
61 
62  Qt::ItemFlags returnVal = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
63  if (SessionItem* item = itemForIndex(index)) {
64  if (item->isEditable() && index.column() != 0)
65  returnVal |= Qt::ItemIsEditable;
66  if (item->parent()->modelType() == "FitParameterLink" && index.column() == 0) {
67  returnVal |= Qt::ItemIsDragEnabled;
68  }
69  const bool allow_one_fit_parameter_to_have_more_than_one_link = true;
70  if (allow_one_fit_parameter_to_have_more_than_one_link) {
71  // drop is allowed to fit parameter container, and, to FitParameterItem itself.
72  // (i.e. we can have more than one link in single FitParameterItem)
73  if (item->modelType() == "FitParameter"
74  || item->modelType() == "FitParameterContainer") {
75  returnVal |= Qt::ItemIsDropEnabled;
76  }
77  } else {
78  // drop is allowed only to fit parameter container
79  // (i.e. only one link is allowed in FitParameterItem)
80  if (item->modelType() == "FitParameterContainer") {
81  returnVal |= Qt::ItemIsDropEnabled;
82  }
83  }
84  }
85  return returnVal;
86 }
87 
88 QModelIndex FitParameterProxyModel::index(int row, int column, const QModelIndex& parent) const
89 {
90  if (!m_root_item || row < 0 || column < 0 || column >= columnCount(QModelIndex())
91  || (parent.isValid() && parent.column() != 0))
92  return QModelIndex();
93 
94  SessionItem* parent_item = itemForIndex(parent);
95  ASSERT(parent_item);
96 
97  if (parent_item->modelType() == "FitParameterContainer") {
98  if (SessionItem* fitParItem = parent_item->childAt(row)) {
99  SessionItem* itemToPack = fitParItem;
100  if (column != 0) {
101  itemToPack = fitParItem->getItem(m_columnNames.value(column));
102  }
103  return createIndex(row, column, itemToPack);
104  }
105  } else if (parent_item->modelType() == "FitParameter" && column == 0) {
106  QVector<SessionItem*> links = parent_item->getItems(FitParameterItem::T_LINK);
107  if (row < links.size()) {
108  if (SessionItem* linkItem = links.at(row)) {
109  return createIndex(row, column, linkItem->getItem(FitParameterLinkItem::P_LINK));
110  }
111  }
112  }
113  return QModelIndex();
114 }
115 
116 QModelIndex FitParameterProxyModel::parent(const QModelIndex& child) const
117 {
118  if (!m_root_item)
119  return QModelIndex();
120 
121  if (!child.isValid())
122  return QModelIndex();
123 
124  if (SessionItem* child_item = itemForIndex(child)) {
125  if (SessionItem* parent_item = child_item->parent()) {
126  if (!isValidSourceItem(parent_item))
127  return QModelIndex();
128  if (parent_item->modelType() == "FitParameterLink") {
129  SessionItem* fitPar = parent_item->parent();
130  if (!isValidSourceItem(fitPar))
131  return QModelIndex();
132  return createIndex(ParentRow(*fitPar), 0, fitPar);
133  }
134  }
135  }
136  return QModelIndex();
137 }
138 
139 int FitParameterProxyModel::rowCount(const QModelIndex& parent) const
140 {
141  if (!m_root_item)
142  return 0;
143 
144  if (parent.isValid() && parent.column() != 0)
145  return 0;
146 
147  SessionItem* parent_item = itemForIndex(parent);
148  if (parent_item != m_root_item && !isValidSourceItem(parent_item))
149  return 0;
150 
151  if (parent_item->modelType() == "FitParameterContainer") {
152  return parent_item->numberOfChildren();
153  } else if (parent_item->modelType() == "FitParameter") {
154  return parent_item->getItems(FitParameterItem::T_LINK).size();
155  }
156  return 0;
157 }
158 
159 int FitParameterProxyModel::columnCount(const QModelIndex& parent) const
160 {
161  if (!m_root_item)
162  return 0;
163 
164  if (parent.isValid() && parent.column() != 0)
165  return 0;
166 
167  if (!parent.isValid())
168  return MAX_COLUMNS;
169 
170  if (parent.isValid()) {
171  if (SessionItem* parentItem = itemForIndex(parent)) {
172  if (parentItem->modelType() == "FitParameter") {
173  return (parentItem->getItems(FitParameterItem::T_LINK).size() ? 1 : 0);
174  }
175  }
176  }
177  return 0;
178 }
179 
180 QVariant FitParameterProxyModel::data(const QModelIndex& index, int role) const
181 {
182  if (!m_root_item)
183  return QVariant();
184 
185  if (!index.isValid() || index.column() < 0 || index.column() >= MAX_COLUMNS)
186  return QVariant();
187 
188  if (SessionItem* item = itemForIndex(index)) {
189  if (role == Qt::DisplayRole || role == Qt::EditRole) {
190  if (item->modelType() == "FitParameter") {
191  return item->displayName();
192  } else {
193  return item->value();
194  }
195  } else if (role == Qt::ForegroundRole && !item->isEditable()) {
196  return QVariant(QColor(Qt::gray));
197  } else if (role == Qt::ToolTipRole && item->displayName() == FitParameterLinkItem::P_LINK) {
198  return item->value();
199  }
200  }
201  return QVariant();
202 }
203 
204 bool FitParameterProxyModel::setData(const QModelIndex& index, const QVariant& value, int role)
205 {
206  if (!m_root_item)
207  return false;
208 
209  if (!index.isValid())
210  return false;
211  if (SessionItem* item = itemForIndex(index)) {
212  if (role == Qt::EditRole) {
213  item->setValue(value);
214  emit dataChanged(index, index);
215  return true;
216  }
217  }
218  return false;
219 }
220 
222 {
223  QStringList types;
224  types << SessionXML::LinkMimeType;
225  return types;
226 }
227 
228 QMimeData* FitParameterProxyModel::mimeData(const QModelIndexList& indexes) const
229 {
230  QMimeData* mimeData = new QMimeData();
231  QModelIndex index = indexes.first();
232  if (index.isValid()) {
233  if (SessionItem* item = itemForIndex(index)) {
234  QString path = item->value().toString();
235  mimeData->setData(SessionXML::LinkMimeType, path.toLatin1());
236  }
237  }
238  return mimeData;
239 }
240 
241 bool FitParameterProxyModel::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row,
242  int column, const QModelIndex& parent) const
243 {
244  Q_UNUSED(data);
245  Q_UNUSED(action);
246  Q_UNUSED(row);
247  bool drop_is_possible(false);
248  if (parent.isValid())
249  drop_is_possible = true;
250  if (!parent.isValid() && row == -1 && column == -1)
251  drop_is_possible = true;
252  return drop_is_possible;
253 }
254 
255 bool FitParameterProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row,
256  int column, const QModelIndex& parent)
257 {
258  Q_UNUSED(action);
259  Q_UNUSED(row);
260  Q_UNUSED(column);
261 
262  if (parent.isValid()) {
263  if (SessionItem* fitParItem = itemForIndex(parent)) {
264  ASSERT(fitParItem->modelType() == "FitParameter");
266  m_root_item, QString::fromLatin1(data->data(SessionXML::LinkMimeType)));
267  ASSERT(parItem);
269  }
270  } else {
272  m_root_item, QString::fromLatin1(data->data(SessionXML::LinkMimeType)));
273  ASSERT(parItem);
275  }
276  return true;
277 }
278 
279 QVariant FitParameterProxyModel::headerData(int section, Qt::Orientation orientation,
280  int role) const
281 {
282  if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
283  return m_columnNames.value(section);
284  } else if (role == Qt::ToolTipRole) {
285  return m_columnToolTips.value(section);
286  }
287  return QVariant();
288 }
289 
290 void FitParameterProxyModel::onSourceDataChanged(const QModelIndex& topLeft,
291  const QModelIndex& bottomRight,
292  const QVector<int>& roles)
293 {
294  Q_UNUSED(bottomRight);
295 
296  JobModel* sourceModel = qobject_cast<JobModel*>(sender());
298  SessionItem* sourceItem = sourceModel->itemForIndex(topLeft);
299 
300  QModelIndex itemIndex = indexOfItem(sourceItem);
301 
302  if (itemIndex.isValid())
303  emit dataChanged(itemIndex, itemIndex, roles);
304 }
305 
306 void FitParameterProxyModel::onSourceRowsRemoved(const QModelIndex& parent, int first, int last)
307 {
308  Q_UNUSED(parent);
309  Q_UNUSED(first);
310  Q_UNUSED(last);
311  beginResetModel();
312  endResetModel();
313 }
314 
316 {
317  if (!m_root_item)
318  return;
319  beginResetModel();
320  endResetModel();
321 }
322 
323 void FitParameterProxyModel::connectModel(QAbstractItemModel* sourceModel, bool isConnect)
324 {
326  if (isConnect) {
327  connect(sourceModel, &QAbstractItemModel::dataChanged, this,
329  connect(sourceModel, &QAbstractItemModel::rowsRemoved, this,
331  connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, this,
333  } else {
334  disconnect(sourceModel, &QAbstractItemModel::dataChanged, this,
336  disconnect(sourceModel, &QAbstractItemModel::rowsRemoved, this,
338  disconnect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, this,
340  }
341 }
342 
344  const QString& tooltip)
345 {
346  m_columnNames[id] = name;
347  m_columnToolTips[id] = tooltip;
348 }
349 
351 {
352  if (!m_root_item)
353  return QModelIndex();
354 
355  if (SessionItem* parent_item = item->parent()) {
356  if (parent_item->modelType() == "FitParameterContainer") {
357  if (item->modelType() == "FitParameter") {
358  return createIndex(ParentRow(*item), 0, item);
359  }
360  } else if (parent_item->modelType() == "FitParameter") {
361 
362  QString tag = parent_item->tagFromItem(item);
363  int col = m_columnNames.key(tag, -1);
364  if (col > 0) {
365  return createIndex(ParentRow(*parent_item), col, item);
366  }
367  } else if (parent_item->modelType() == "FitParameterLink") {
368  QVector<SessionItem*> links = parent_item->parent()->getItems(FitParameterItem::T_LINK);
369  return createIndex(links.indexOf(parent_item), 0, item);
370  }
371  }
372  return QModelIndex();
373 }
374 
375 SessionItem* FitParameterProxyModel::itemForIndex(const QModelIndex& index) const
376 {
377  if (!m_root_item)
378  return 0;
379 
380  if (index.isValid()) {
381  SessionItem* item = static_cast<SessionItem*>(index.internalPointer());
382  if (item) {
383  if (!isValidSourceItem(item)) {
384  return 0;
385  }
386  return item;
387  }
388  }
389  return m_root_item;
390 }
391 
393 {
395  return m_root_item->model();
396 }
397 
398 //! Returns true if given item still exists in source model
400 {
401  if (item == m_root_item)
402  return true;
404  return true;
405  return false;
406 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines class FitParameterHelper.
Defines FitParameterItems family of classes.
Defines class FitParameterProxyModel.
Defines class GUIHelpers functions.
Defines class JobModel.
Defines ModelPath namespace.
Defines namespace SessionItemUtils.
static void createFitParameter(FitParameterContainerItem *container, ParameterItem *parameterItem)
Creates fit parameter from given ParameterItem, sets starting value to the value of ParameterItem,...
static ParameterItem * getParameterItem(FitParameterContainerItem *container, const QString &link)
Returns ParameterItem corresponding to given link.
static void addToFitParameter(FitParameterContainerItem *container, ParameterItem *parameterItem, const QString &fitParName)
Adds given parameterItem to the existing fit parameter with display name fitParName.
static const QString P_MAX
static const QString T_LINK
static const QString P_TYPE
static const QString P_MIN
static const QString P_START_VALUE
static const QString P_LINK
QModelIndex index(int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE
QMimeData * mimeData(const QModelIndexList &indexes) const Q_DECL_OVERRIDE
void connectModel(QAbstractItemModel *sourceModel, bool isConnect=true)
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE
QMap< int, QString > m_columnNames
QMap< int, QString > m_columnToolTips
bool setData(const QModelIndex &index, const QVariant &value, int role) Q_DECL_OVERRIDE
SessionItem * itemForIndex(const QModelIndex &index) const
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const Q_DECL_OVERRIDE
QStringList mimeTypes() const Q_DECL_OVERRIDE
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE
SessionModel * sourceModel() const
QModelIndex indexOfItem(SessionItem *item) const
bool isValidSourceItem(SessionItem *item) const
Returns true if given item still exists in source model.
int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE
void onSourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
FitParameterProxyModel(FitParameterContainerItem *fitParContainer, QObject *parent=0)
QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE
void onSourceRowsRemoved(const QModelIndex &parent, int first, int last)
Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE
void addColumn(EColumn id, const QString &name, const QString &tooltip)
FitParameterContainerItem * m_root_item
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE
void unsubscribe(const void *caller)
Cancells all subscribtion of given caller.
Definition: ModelMapper.cpp:98
void setOnItemDestroy(std::function< void(SessionItem *)> f, const void *caller=0)
Definition: ModelMapper.cpp:87
The ParameterItem class represent a tuning value in a parameter tuning tree.
QVector< SessionItem * > getItems(const QString &tag="") const
Returns vector of all items of given tag.
int numberOfChildren() const
Returns total number of children.
Definition: SessionItem.cpp:94
QString displayName() const
Get display name of item, append index if ambigue.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
SessionItem * parent() const
Returns parent of this item.
Definition: SessionItem.cpp:73
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:66
SessionItem * childAt(int row) const
Returns the child at the given row.
QString modelType() const
Get model type.
QModelIndex index() const
Returns model index of this item.
Definition: SessionItem.cpp:80
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
SessionItem * itemForIndex(const QModelIndex &index) const
bool isValidItem(SessionModel *model, SessionItem *item, const QModelIndex &parent)
Iterates through all the model and returns true if item is found. This is to.
Definition: ModelPath.cpp:69
QString const & name(EShape k)
Definition: particles.cpp:21
QVariant ToolTipRole(const SessionItem &item, int ncol=0)
Returns tooltip for given item.
QVariant ForegroundRole(const SessionItem &item)
Returns text color for given item.
int ParentRow(const SessionItem &item)
Returns the index of the given item within its parent. Returns -1 when no parent is set.
const QString LinkMimeType
Definition: SessionXML.h:27