BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FitParameterWidget.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/FitWidgets/FitParameterWidget.cpp
6 //! @brief Implements class FitParameterWidget
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 
29 #include <QAction>
30 #include <QMenu>
31 #include <QTreeView>
32 #include <QVBoxLayout>
33 
35  : SessionItemWidget(parent)
36  , m_treeView(new QTreeView)
37  , m_tuningWidget(0)
38  , m_createFitParAction(0)
39  , m_removeFromFitParAction(0)
40  , m_removeFitParAction(0)
41  , m_fitParameterModel(0)
42  , m_delegate(new SessionModelDelegate(this))
43  , m_keyboardFilter(new DeleteEventFilter(this))
44  , m_infoLabel(new OverlayLabelController(this))
45 {
46  QVBoxLayout* layout = new QVBoxLayout;
47  layout->addWidget(m_treeView);
48  layout->setMargin(0);
49  layout->setSpacing(0);
50  setLayout(layout);
51  init_actions();
52 
53  m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
54  m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
55  m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
56  m_treeView->setItemDelegate(m_delegate);
57  m_treeView->setDragEnabled(true);
58  m_treeView->setDragDropMode(QAbstractItemView::DragDrop);
59  m_treeView->installEventFilter(m_keyboardFilter);
60  m_treeView->setAlternatingRowColors(true);
61  m_treeView->setStyleSheet("alternate-background-color: #EFF0F1;");
62 
63  connect(m_treeView, &QTreeView::customContextMenuRequested, this,
65 
67  m_infoLabel->setText("Drop parameter(s) to fit here");
68 }
69 
70 //! Sets ParameterTuningWidget to be able to provide it with context menu and steer
71 //! it behaviour in the course of fit settings or fit runnig
72 
74 {
75  if (tuningWidget == m_tuningWidget) {
76  return;
77 
78  } else {
79  if (m_tuningWidget)
82 
83  m_tuningWidget = tuningWidget;
84  if (!m_tuningWidget)
85  return;
86 
88  &FitParameterWidget::onTuningWidgetContextMenu, Qt::UniqueConnection);
89  connect(m_tuningWidget, &QObject::destroyed, [this] { m_tuningWidget = nullptr; });
90  }
91 }
92 
93 // QSize FitParameterWidget::sizeHint() const
94 //{
95 // return QSize(Constants::REALTIME_WIDGET_WIDTH_HINT, Constants::FIT_PARAMETER_WIDGET_HEIGHT);
96 //}
97 
98 // QSize FitParameterWidget::minimumSizeHint() const
99 //{
100 // return QSize(25, 25);
101 //}
102 
103 //! Creates context menu for ParameterTuningWidget
104 
106 {
107  QMenu menu;
109  menu.exec(point);
110  setActionsEnabled(true);
111 }
112 
113 //! Creates context menu for the tree with fit parameters
114 
116 {
117  QMenu menu;
119  menu.exec(m_treeView->mapToGlobal(point + QPoint(2, 22)));
120  setActionsEnabled(true);
121 }
122 
123 void FitParameterWidget::onTuningWidgetSelectionChanged(const QItemSelection& selection)
124 {
125  Q_UNUSED(selection);
126 }
127 
128 //! Propagates selection form the tree with fit parameters to the tuning widget
129 
130 void FitParameterWidget::onFitParametersSelectionChanged(const QItemSelection& selection)
131 {
132  if (selection.indexes().isEmpty())
133  return;
134 
135  for (auto index : selection.indexes()) {
136  m_tuningWidget->selectionModel()->clearSelection();
138  if (item->parent()->modelType() == "FitParameterLink") {
139  QString link = item->parent()->getItemValue(FitParameterLinkItem::P_LINK).toString();
141  FitParameterHelper::getParameterItem(jobItem()->fitParameterContainerItem(), link));
142  }
143  }
144 }
145 
146 //! Creates fit parameters for all selected ParameterItem's in tuning widget
147 
149 {
150  for (auto item : m_tuningWidget->getSelectedParameters()) {
151  if (!FitParameterHelper::getFitParameterItem(jobItem()->fitParameterContainerItem(),
152  item)) {
153  FitParameterHelper::createFitParameter(jobItem()->fitParameterContainerItem(), item);
154  }
155  }
156 }
157 
158 //! All ParameterItem's selected in tuning widget will be removed from link section of
159 //! corresponding fitParameterItem.
160 
162 {
163  for (auto item : m_tuningWidget->getSelectedParameters()) {
164  if (FitParameterHelper::getFitParameterItem(jobItem()->fitParameterContainerItem(), item)) {
165  FitParameterHelper::removeFromFitParameters(jobItem()->fitParameterContainerItem(),
166  item);
167  }
168  }
169 }
170 
171 //! All selected FitParameterItem's of FitParameterItemLink's will be removed
172 
174 {
176 
177  // retrieve both, selected FitParameterItem and FitParameterItemLink
178  QVector<FitParameterLinkItem*> linksToRemove = selectedFitParameterLinks();
179 
180  for (auto item : linksToRemove) {
181  container->model()->removeRow(item->index().row(), item->index().parent());
182  }
183 
184  QVector<FitParameterItem*> itemsToRemove = selectedFitParameters();
185  // By uncommenting line below, removing link from fit parameter will lead to fit parameter
186  // removal too (if it doesn't have other links)
187  // QVector<FitParameterItem *> itemsToRemove = selectedFitParameters()+emptyFitParameters();
188 
189  for (auto item : itemsToRemove) {
190  container->model()->removeRow(item->index().row(), item->index().parent());
191  }
192 }
193 
194 //! Add all selected parameters to fitParameter with given index
195 
197 {
198  QStringList fitParNames =
199  FitParameterHelper::getFitParameterNames(jobItem()->fitParameterContainerItem());
200  for (auto item : m_tuningWidget->getSelectedParameters()) {
201  FitParameterHelper::addToFitParameter(jobItem()->fitParameterContainerItem(), item,
202  fitParNames.at(ipar));
203  }
204 }
205 
207 {
208  spanParameters();
209  updateInfoLabel();
210 }
211 
212 //! Context menu reimplemented to suppress the default one
213 
214 void FitParameterWidget::contextMenuEvent(QContextMenuEvent* event)
215 {
216  Q_UNUSED(event);
217 }
218 
220 {
221  init_fit_model();
222 }
223 
225 {
226  m_createFitParAction = new QAction("Create fit parameter", this);
227  connect(m_createFitParAction, &QAction::triggered, this,
229 
230  m_removeFromFitParAction = new QAction("Remove from fit parameters", this);
231  connect(m_removeFromFitParAction, &QAction::triggered, this,
233 
234  m_removeFitParAction = new QAction("Remove fit parameter", this);
235  connect(m_removeFitParAction, &QAction::triggered, this,
237 
240 }
241 
242 //! Fills context menu for ParameterTuningWidget with content.
243 
245 {
246  if (jobItem()->getStatus() == "Fitting") {
247  setActionsEnabled(false);
248  return;
249  }
250 
253 
254  menu.addAction(m_createFitParAction);
255  QMenu* addToFitParMenu = menu.addMenu("Add to existing fit parameter");
256  addToFitParMenu->setEnabled(true);
257 
258  const bool allow_one_fit_parameter_to_have_more_than_one_link = true;
259  if (allow_one_fit_parameter_to_have_more_than_one_link) {
260  QStringList fitParNames =
261  FitParameterHelper::getFitParameterNames(jobItem()->fitParameterContainerItem());
262  if (fitParNames.isEmpty() || canCreateFitParameter() == false) {
263  addToFitParMenu->setEnabled(false);
264  }
265  for (int i = 0; i < fitParNames.count(); ++i) {
266  QAction* action =
267  new QAction(QString("to ").append(fitParNames.at(i)), addToFitParMenu);
268  connect(action, &QAction::triggered, [=] { onAddToFitParAction(i); });
269  addToFitParMenu->addAction(action);
270  }
271  }
272  menu.addSeparator();
273  menu.addAction(m_removeFromFitParAction);
274 }
275 
276 //! Fills context menu for FitParameterTree with content.
277 
279 {
280  if (jobItem()->getStatus() == "Fitting") {
281  setActionsEnabled(false);
282  return;
283  }
284  menu.addAction(m_removeFitParAction);
285 }
286 
287 //! Initializes FitParameterModel and its tree.
288 
290 {
291  m_treeView->setModel(0);
292 
293  delete m_fitParameterModel;
295  jobItem()->fitParameterContainerItem(), jobItem()->fitParameterContainerItem()->model());
296  m_treeView->setModel(m_fitParameterModel);
297 
298  connect(m_fitParameterModel, &FitParameterProxyModel::dataChanged, this,
300  connect(m_fitParameterModel, &FitParameterProxyModel::modelReset, this,
302 
305 }
306 
307 //! Returns true if tuning widget contains selected ParameterItem's which can be used to create
308 //! a fit parameter (i.e. it is not linked with some fit parameter already).
309 
311 {
312  QVector<ParameterItem*> selected = m_tuningWidget->getSelectedParameters();
313  for (auto item : selected) {
314  if (FitParameterHelper::getFitParameterItem(jobItem()->fitParameterContainerItem(), item)
315  == nullptr)
316  return true;
317  }
318  return false;
319 }
320 
321 //! Returns true if tuning widget contains selected ParameterItem's which can be removed from
322 //! fit parameters.
323 
325 {
326  QVector<ParameterItem*> selected = m_tuningWidget->getSelectedParameters();
327  for (auto item : selected) {
328  if (FitParameterHelper::getFitParameterItem(jobItem()->fitParameterContainerItem(), item))
329  return true;
330  }
331  return false;
332 }
333 
334 //! Enables/disables all context menu actions.
335 
337 {
338  m_createFitParAction->setEnabled(value);
339  m_removeFromFitParAction->setEnabled(value);
340  m_removeFitParAction->setEnabled(value);
341 }
342 
343 //! Returns list of FitParameterItem's currently selected in FitParameterItem tree
344 
345 QVector<FitParameterItem*> FitParameterWidget::selectedFitParameters()
346 {
347  QVector<FitParameterItem*> result;
348  QModelIndexList indexes = m_treeView->selectionModel()->selectedIndexes();
349  for (auto index : indexes) {
350  if (SessionItem* item = m_fitParameterModel->itemForIndex(index)) {
351  if (item->modelType() == "FitParameter") {
352  FitParameterItem* fitParItem = dynamic_cast<FitParameterItem*>(item);
353  ASSERT(fitParItem);
354  result.push_back(fitParItem);
355  }
356  }
357  }
358  return result;
359 }
360 
361 //! Returns list of FitParameterItem's which doesn't have any links attached.
362 
363 QVector<FitParameterItem*> FitParameterWidget::emptyFitParameters()
364 {
365  QVector<FitParameterItem*> result;
366  for (auto fitParItem : jobItem()->fitParameterContainerItem()->fitParameterItems())
367  if (fitParItem->getItems(FitParameterItem::T_LINK).empty())
368  result.push_back(fitParItem);
369 
370  return result;
371 }
372 
373 //! Returns links of FitParameterLink's item selected in FitParameterItem tree
374 
375 QVector<FitParameterLinkItem*> FitParameterWidget::selectedFitParameterLinks()
376 {
377  QVector<FitParameterLinkItem*> result;
378  QModelIndexList indexes = m_treeView->selectionModel()->selectedIndexes();
379  for (QModelIndex index : indexes) {
380  if (SessionItem* item = m_fitParameterModel->itemForIndex(index)) {
381  if (item->parent()->modelType() == "FitParameterLink") {
382  FitParameterLinkItem* fitParItem =
383  dynamic_cast<FitParameterLinkItem*>(item->parent());
384  ASSERT(fitParItem);
385  result.push_back(fitParItem);
386  }
387  }
388  }
389  return result;
390 }
391 
392 //! Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
393 
395 {
396  m_treeView->expandAll();
397  for (int i = 0; i < m_fitParameterModel->rowCount(QModelIndex()); i++) {
398  QModelIndex parameter = m_fitParameterModel->index(i, 0, QModelIndex());
399  if (!parameter.isValid())
400  break;
401  int childRowCount = m_fitParameterModel->rowCount(parameter);
402  if (childRowCount > 0) {
403  for (int j = 0; j < childRowCount; j++) {
404  m_treeView->setFirstColumnSpanned(j, parameter, true);
405  }
406  }
407  }
408 }
409 
410 //! Places overlay label on top of tree view, if there is no fit parameters
412 {
413  if (!jobItem())
414  return;
415 
416  bool is_to_show_label = jobItem()->fitParameterContainerItem()->isEmpty();
417  m_infoLabel->setShown(is_to_show_label);
418 }
419 
421 {
423 
424  if (active) {
425  connect(m_tuningWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this,
427  } else {
428  disconnect(m_tuningWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this,
430  }
431 }
432 
434 {
435  if (active) {
436  connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
438  } else {
439  disconnect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
441  }
442 }
443 
445 {
446  return dynamic_cast<JobItem*>(currentItem());
447 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines classes releted to event filtering.
Defines class FilterPropertyProxy.
Defines class FitParameterHelper.
Defines FitParameterItems family of classes.
Defines class FitParameterProxyModel.
Defines class FitParameterWidget.
Defines class FitSuiteItem.
Defines class JobItem.
Defines class JobModel.
Defines class OverlayLabelController.
Defines classes for ParameterTreeItems.
Defines class ParameterTuningWidget.
Defines class SessionModelDelegate.
Lisens for press-del-key events.
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 QStringList getFitParameterNames(FitParameterContainerItem *container)
Returns list of fit parameter display names.
static FitParameterItem * getFitParameterItem(FitParameterContainerItem *container, ParameterItem *parameterItem)
Returns fFitParameterItem corresponding to given ParameterItem.
static void removeFromFitParameters(FitParameterContainerItem *container, ParameterItem *parameterItem)
Removes link to given parameterItem from fit parameters.
static void addToFitParameter(FitParameterContainerItem *container, ParameterItem *parameterItem, const QString &fitParName)
Adds given parameterItem to the existing fit parameter with display name fitParName.
The FitParameterItem class represents a fit parameter in GUI.
static const QString T_LINK
FitParameterItems is a collection of items to define fit parameters in GUI.
static const QString P_LINK
The FitParameterProxyModel adapts the original JobModel to show items from FitParameterContainer in 5...
QModelIndex index(int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE
SessionItem * itemForIndex(const QModelIndex &index) const
int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE
ParameterTuningWidget * m_tuningWidget
void onAddToFitParAction(int ipar)
Add all selected parameters to fitParameter with given index.
void connectTuningWidgetSelection(bool active)
void onCreateFitParAction()
Creates fit parameters for all selected ParameterItem's in tuning widget.
QVector< FitParameterItem * > emptyFitParameters()
Returns list of FitParameterItem's which doesn't have any links attached.
QVector< FitParameterItem * > selectedFitParameters()
Returns list of FitParameterItem's currently selected in FitParameterItem tree.
void onFitParameterTreeContextMenu(const QPoint &point)
Creates context menu for the tree with fit parameters.
void contextMenuEvent(QContextMenuEvent *event)
Context menu reimplemented to suppress the default one.
void spanParameters()
Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
void initTuningWidgetContextMenu(QMenu &menu)
Fills context menu for ParameterTuningWidget with content.
FitParameterProxyModel * m_fitParameterModel
QAction * m_createFitParAction
void setParameterTuningWidget(ParameterTuningWidget *tuningWidget)
Sets ParameterTuningWidget to be able to provide it with context menu and steer it behaviour in the c...
void connectFitParametersSelection(bool active)
QAction * m_removeFitParAction
void updateInfoLabel()
Places overlay label on top of tree view, if there is no fit parameters.
void setActionsEnabled(bool value)
Enables/disables all context menu actions.
void onRemoveFromFitParAction()
All ParameterItem's selected in tuning widget will be removed from link section of corresponding fitP...
FitParameterWidget(QWidget *parent=0)
void initFitParameterTreeContextMenu(QMenu &menu)
Fills context menu for FitParameterTree with content.
void onTuningWidgetSelectionChanged(const QItemSelection &selection)
bool canRemoveFromFitParameters()
Returns true if tuning widget contains selected ParameterItem's which can be removed from fit paramet...
void onTuningWidgetContextMenu(const QPoint &point)
Creates context menu for ParameterTuningWidget.
OverlayLabelController * m_infoLabel
SessionModelDelegate * m_delegate
DeleteEventFilter * m_keyboardFilter
void init_fit_model()
Initializes FitParameterModel and its tree.
void onFitParametersSelectionChanged(const QItemSelection &selection)
Propagates selection form the tree with fit parameters to the tuning widget.
bool canCreateFitParameter()
Returns true if tuning widget contains selected ParameterItem's which can be used to create a fit par...
QAction * m_removeFromFitParAction
void onRemoveFitParAction()
All selected FitParameterItem's of FitParameterItemLink's will be removed.
QVector< FitParameterLinkItem * > selectedFitParameterLinks()
Returns links of FitParameterLink's item selected in FitParameterItem tree.
FitParameterContainerItem * fitParameterContainerItem()
Definition: JobItem.cpp:251
The OverlayLabelController class controlls appearance of InfoLabelWidget (position,...
void setArea(QAbstractScrollArea *area)
void setText(const QString &text)
void setShown(bool shown)
Shows/removes a label from the controlled widget.
Main widget for real time parameter tuning.
void makeSelected(ParameterItem *item)
QVector< ParameterItem * > getSelectedParameters()
Returns list of ParameterItem's currently selected in parameter tree.
void itemContextMenuRequest(const QPoint &point)
QItemSelectionModel * selectionModel()
The SessionItemWidget class is a base for all widgets representing the content of SessionItem.
SessionItem * currentItem()
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
SessionItem * parent() const
Returns parent of this item.
Definition: SessionItem.cpp:73
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:66
QString modelType() const
Get model type.
The SessionModelDelegate class presents the content of SessionModel items in standard QTreeView.
Defines namespace Constants.