BornAgain  1.19.79
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/View/Fit/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 
20 #include "GUI/Model/Job/JobItem.h"
30 #include <QAction>
31 #include <QMenu>
32 #include <QTreeView>
33 #include <QVBoxLayout>
34 
35 #include <boost/polymorphic_cast.hpp>
36 
37 using boost::polymorphic_downcast;
38 
40  : SessionItemWidget(parent)
41  , m_treeView(new QTreeView)
42  , m_tuningWidget(nullptr)
43  , m_createFitParAction(nullptr)
44  , m_removeFromFitParAction(nullptr)
45  , m_removeFitParAction(nullptr)
46  , m_fitParameterModel(nullptr)
47  , m_keyboardFilter(new DeleteEventFilter(this))
48  , m_infoLabel(new OverlayLabelController(this))
49 {
50  auto* layout = new QVBoxLayout(this);
51  layout->addWidget(m_treeView);
52  layout->setMargin(0);
53  layout->setSpacing(0);
54  init_actions();
55 
56  m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
57  m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
58  m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
59  m_treeView->setItemDelegate(new FitParameterDelegate(this));
60  m_treeView->setDragEnabled(true);
61  m_treeView->setDragDropMode(QAbstractItemView::DragDrop);
62  m_treeView->installEventFilter(m_keyboardFilter);
63  m_treeView->setAlternatingRowColors(true);
64  m_treeView->setStyleSheet("alternate-background-color: #EFF0F1;");
65 
66  connect(m_treeView, &QTreeView::customContextMenuRequested, this,
68 
70  m_infoLabel->setText("Drop parameter(s) to fit here");
71 }
72 
73 //! Sets ParameterTuningWidget to be able to provide it with context menu and steer
74 //! its behaviour in the course of fit settings or fit running
75 
77 {
78  if (tuningWidget == m_tuningWidget)
79  return;
80 
81  if (m_tuningWidget)
84 
85  m_tuningWidget = tuningWidget;
86  if (!m_tuningWidget)
87  return;
88 
90  &FitParameterWidget::onTuningWidgetContextMenu, Qt::UniqueConnection);
91  connect(m_tuningWidget, &QObject::destroyed, [this] { m_tuningWidget = nullptr; });
92 }
93 
94 //! Creates context menu for ParameterTuningWidget
95 
97 {
98  QMenu menu;
99 
100  if (jobItem()->getStatus() == JobStatus::Fitting) {
101  setActionsEnabled(false);
102  return;
103  }
104 
107 
108  menu.addAction(m_createFitParAction);
109  QMenu* addToFitParMenu = menu.addMenu("Add to existing fit parameter");
110  addToFitParMenu->setEnabled(true);
111 
112  const bool allow_one_fit_parameter_to_have_more_than_one_link = true;
113  if (allow_one_fit_parameter_to_have_more_than_one_link) {
114  QStringList fitParNames = jobItem()->fitParameterContainerItem()->fitParameterNames();
115  if (fitParNames.isEmpty() || !canCreateFitParameter())
116  addToFitParMenu->setEnabled(false);
117  for (int i = 0; i < fitParNames.count(); ++i) {
118  auto* action = new QAction(QString("to ").append(fitParNames.at(i)), addToFitParMenu);
119  connect(action, &QAction::triggered, [=] { onAddToFitParAction(i); });
120  addToFitParMenu->addAction(action);
121  }
122  }
123  menu.addSeparator();
124  menu.addAction(m_removeFromFitParAction);
125 
126  menu.exec(point);
127  setActionsEnabled(true);
128 }
129 
130 //! Creates context menu for the tree with fit parameters
131 
133 {
134  if (jobItem()->getStatus() == JobStatus::Fitting) {
135  setActionsEnabled(false);
136  return;
137  }
138  if (jobItem()->fitParameterContainerItem()->isEmpty())
139  return;
140 
141  QMenu menu;
142  menu.addAction(m_removeFitParAction);
143  menu.exec(m_treeView->viewport()->mapToGlobal(point));
144  setActionsEnabled(true);
145 }
146 
147 //! Propagates selection form the tree with fit parameters to the tuning widget
148 
149 void FitParameterWidget::onFitParametersSelectionChanged(const QItemSelection& selection)
150 {
151  if (selection.indexes().isEmpty())
152  return;
153 
154  for (auto index : selection.indexes()) {
155  m_tuningWidget->selectionModel()->clearSelection();
157  if (item->parentItem()->hasModelType<FitParameterLinkItem>()) {
158  QString link = polymorphic_downcast<FitParameterLinkItem*>(item->parentItem())->link();
160  jobItem()->parameterContainerItem()->findParameterItem(link));
161  }
162  }
163 }
164 
165 //! Creates fit parameters for all selected ParameterItem's in tuning widget
166 
168 {
169  for (auto* item : m_tuningWidget->getSelectedParameters())
170  if (!jobItem()->fitParameterContainerItem()->fitParameterItem(item))
172 }
173 
174 //! All ParameterItem's selected in tuning widget will be removed from link section of
175 //! corresponding fitParameterItem.
176 
178 {
179  for (auto* item : m_tuningWidget->getSelectedParameters())
181 }
182 
183 //! All selected FitParameterItem's of FitParameterItemLink's will be removed
184 
186 {
188 
189  // retrieve both, selected FitParameterItem and FitParameterItemLink
190  const auto linksToRemove = selectedFitParameterLinks();
191 
192  for (const auto& link : linksToRemove)
193  for (auto* fitParItem : container->fitParameterItems())
194  fitParItem->removeLink(link);
195 
196  QVector<FitParameterItem*> itemsToRemove = selectedFitParameters();
197  // By uncommenting line below, removing link from fit parameter will lead to fit parameter
198  // removal too (if it doesn't have other links)
199  // QVector<FitParameterItem *> itemsToRemove = selectedFitParameters()+emptyFitParameters();
200 
201  for (auto* item : itemsToRemove)
202  container->model()->removeRow(item->index().row(), item->index().parent());
203 }
204 
205 //! Add all selected parameters to fitParameter with given index
206 
208 {
209  const QString fitParName = jobItem()->fitParameterContainerItem()->fitParameterNames().at(ipar);
210  for (auto* item : m_tuningWidget->getSelectedParameters())
211  jobItem()->fitParameterContainerItem()->addToFitParameter(item, fitParName);
212 }
213 
215 {
216  spanParameters();
217  updateInfoLabel();
218 }
219 
221 {
222  init_fit_model();
223 }
224 
226 {
227  m_createFitParAction = new QAction("Create fit parameter", this);
228  connect(m_createFitParAction, &QAction::triggered, this,
230 
231  m_removeFromFitParAction = new QAction("Remove from fit parameters", this);
232  connect(m_removeFromFitParAction, &QAction::triggered, this,
234 
235  m_removeFitParAction = new QAction("Remove fit parameter", this);
236  connect(m_removeFitParAction, &QAction::triggered, this,
238 
241 }
242 
243 //! Initializes FitParameterModel and its tree.
244 
246 {
247  m_treeView->setModel(nullptr);
248 
249  delete m_fitParameterModel;
250  m_fitParameterModel = new FitParameterModel(jobItem()->fitParameterContainerItem(),
251  jobItem()->fitParameterContainerItem()->model());
252  m_treeView->setModel(m_fitParameterModel);
253 
254  connect(m_fitParameterModel, &FitParameterModel::dataChanged, this,
256  connect(m_fitParameterModel, &FitParameterModel::modelReset, this,
258 
261 }
262 
263 //! Returns true if tuning widget contains selected ParameterItem's which can be used to create
264 //! a fit parameter (i.e. it is not linked with some fit parameter already).
265 
267 {
268  QVector<ParameterItem*> selected = m_tuningWidget->getSelectedParameters();
269  for (auto* item : selected) {
270  if (jobItem()->fitParameterContainerItem()->fitParameterItem(item) == nullptr)
271  return true;
272  }
273  return false;
274 }
275 
276 //! Returns true if tuning widget contains selected ParameterItem's which can be removed from
277 //! fit parameters.
278 
280 {
281  QVector<ParameterItem*> selected = m_tuningWidget->getSelectedParameters();
282  for (auto* item : selected) {
283  if (jobItem()->fitParameterContainerItem()->fitParameterItem(item))
284  return true;
285  }
286  return false;
287 }
288 
289 //! Enables/disables all context menu actions.
290 
292 {
293  m_createFitParAction->setEnabled(value);
294  m_removeFromFitParAction->setEnabled(value);
295  m_removeFitParAction->setEnabled(value);
296 }
297 
298 //! Returns list of FitParameterItem's currently selected in FitParameterItem tree
299 
300 QVector<FitParameterItem*> FitParameterWidget::selectedFitParameters()
301 {
302  QVector<FitParameterItem*> result;
303  QModelIndexList indexes = m_treeView->selectionModel()->selectedIndexes();
304  for (auto index : indexes) {
305  if (SessionItem* item = m_fitParameterModel->itemForIndex(index)) {
306  if (item->hasModelType<FitParameterItem>()) {
307  auto* fitParItem = dynamic_cast<FitParameterItem*>(item);
308  ASSERT(fitParItem);
309  result.push_back(fitParItem);
310  }
311  }
312  }
313  return result;
314 }
315 
316 //! Returns list of FitParameterItem's which doesn't have any links attached.
317 
318 QVector<FitParameterItem*> FitParameterWidget::emptyFitParameters()
319 {
320  QVector<FitParameterItem*> result;
321  for (auto* fitParItem : jobItem()->fitParameterContainerItem()->fitParameterItems())
322  if (fitParItem->linkItems().empty())
323  result.push_back(fitParItem);
324 
325  return result;
326 }
327 
328 //! Returns links of FitParameterLink's item selected in FitParameterItem tree
329 
331 {
332  QStringList result;
333  QModelIndexList indexes = m_treeView->selectionModel()->selectedIndexes();
334  for (QModelIndex index : indexes) {
335  if (SessionItem* item = m_fitParameterModel->itemForIndex(index)) {
336  if (item->parentItem()->hasModelType<FitParameterLinkItem>()) {
337  auto* fitParItem = dynamic_cast<FitParameterLinkItem*>(item->parentItem());
338  ASSERT(fitParItem);
339  result.push_back(fitParItem->link());
340  }
341  }
342  }
343  return result;
344 }
345 
346 //! Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
347 
349 {
350  m_treeView->expandAll();
351  for (int i = 0; i < m_fitParameterModel->rowCount(QModelIndex()); i++) {
352  QModelIndex parameter = m_fitParameterModel->index(i, 0, QModelIndex());
353  if (!parameter.isValid())
354  break;
355  int childRowCount = m_fitParameterModel->rowCount(parameter);
356  if (childRowCount > 0) {
357  for (int j = 0; j < childRowCount; j++)
358  m_treeView->setFirstColumnSpanned(j, parameter, true);
359  }
360  }
361 }
362 
363 //! Places overlay label on top of tree view, if there is no fit parameters
365 {
366  if (!jobItem())
367  return;
368 
369  m_infoLabel->setShown(jobItem()->fitParameterContainerItem()->isEmpty());
370 }
371 
373 {
374  if (active) {
375  connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
377  } else {
378  disconnect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
380  }
381 }
382 
384 {
385  return dynamic_cast<JobItem*>(currentItem());
386 }
Defines classes releted to event filtering.
Defines class FitParameterContainerItem.
Defines class FitParameterDelegate.
Defines namespace FitParameterHelper.
Defines class FitParameterItem.
Defines class FitParameterLinkItem.
Defines class FitParameterModel.
Defines class FitParameterWidget.
Defines class FitSuiteItem.
Defines class JobItem.
Defines class JobModel.
@ Fitting
the job is busy fitting
Defines class OverlayLabelController.
Defines classes for ParameterTreeItems.
Defines class ParameterTuningWidget.
Lisens for press-del-key events.
The FitParameterContainerItem class is a collection of all defined fit parameters in JobItem.
QStringList fitParameterNames() const
Returns list of fit parameter display names.
void removeLink(const ParameterItem *parameterItem)
void createFitParameter(ParameterItem *parameterItem)
Creates fit parameter from given ParameterItem, sets starting value to the value of ParameterItem,...
QVector< FitParameterItem * > fitParameterItems() const
void addToFitParameter(ParameterItem *parameterItem, const QString &fitParName)
Adds given parameterItem to the existing fit parameter with display name fitParName....
The FitParameterDelegate class presents the content of SessionModel items in standard QTreeView....
FitParameterItems is a collection of items to define fit parameters in GUI.
The FitParameterLinkItem class holds a link to ParameterItem in tuning tree.
Model to show items from FitParameterContainer in 5 column tree view.
int rowCount(const QModelIndex &parent) const override
SessionItem * itemForIndex(const QModelIndex &index) const
QModelIndex index(int row, int column, const QModelIndex &parent) const override
ParameterTuningWidget * m_tuningWidget
void onAddToFitParAction(int ipar)
Add all selected parameters to fitParameter with given index.
FitParameterWidget(QWidget *parent=nullptr)
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 spanParameters()
Makes first column in FitParameterItem's tree related to ParameterItem link occupy whole space.
QAction * m_createFitParAction
void setParameterTuningWidget(ParameterTuningWidget *tuningWidget)
Sets ParameterTuningWidget to be able to provide it with context menu and steer its behaviour in the ...
void connectFitParametersSelection(bool active)
void subscribeToItem() override
FitParameterModel * m_fitParameterModel
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...
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
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.
QStringList selectedFitParameterLinks()
Returns links of FitParameterLink's item selected in FitParameterItem tree.
FitParameterContainerItem * fitParameterContainerItem()
Definition: JobItem.cpp:282
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. Contains a tree for parameter tuning and the model to pro...
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()
Base class for a GUI data item.
Definition: SessionItem.h:204
bool hasModelType() const
Definition: SessionItem.h:421
SessionModel * model() const
Returns model of this item.
Definition: SessionItem.cpp:60
SessionItem * parentItem() const
Returns parent of this item.
Definition: SessionItem.cpp:67
Defines namespace GUI::Constants.