-
Wuttke, Joachim authoredWuttke, Joachim authored
ParameterTuningWidget.cpp 7.54 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/View/FitObjective/ParameterTuningWidget.cpp
//! @brief Implements class ParameterTuningWidget
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "GUI/View/FitObjective/ParameterTuningWidget.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Data/IntensityDataItem.h"
#include "GUI/Model/Job/ParameterTreeItems.h"
#include "GUI/Model/Model/ParameterTuningModel.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/View/FitObjective/ParameterTuningDelegate.h"
#include "GUI/View/FitObjective/SliderSettingsWidget.h"
#include "GUI/View/Info/CautionSign.h"
#include "GUI/View/Widget/StyledToolbar.h"
#include <QAction>
#include <QTreeView>
#include <QVBoxLayout>
ParameterTuningWidget::ParameterTuningWidget(QWidget* parent)
: DataAccessWidget(parent)
, m_jobModel(nullptr)
, m_parameterTuningModel(nullptr)
, m_sliderSettingsWidget(new SliderSettingsWidget(this))
, m_treeView(new QTreeView)
, m_delegate(new ParameterTuningDelegate(this))
, m_cautionSign(new CautionSign(m_treeView))
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_treeView->setItemDelegate(m_delegate);
m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
m_treeView->setDragDropMode(QAbstractItemView::NoDragDrop);
m_treeView->setAttribute(Qt::WA_MacShowFocusRect, false);
auto* resetValuesAction = new QAction(QIcon(":/images/undo-variant.svg"), "Reset values", this);
resetValuesAction->setToolTip("Reset parameter tree to initial values");
connect(resetValuesAction, &QAction::triggered, this,
&ParameterTuningWidget::restoreModelsOfCurrentJobItem);
auto* toolbar = new StyledToolbar(this);
toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolbar->addAction(resetValuesAction);
auto* mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
mainLayout->addWidget(toolbar);
mainLayout->addWidget(m_sliderSettingsWidget);
mainLayout->addWidget(m_treeView);
setLayout(mainLayout);
connect(m_sliderSettingsWidget, &SliderSettingsWidget::sliderRangeFactorChanged, this,
&ParameterTuningWidget::onSliderRangeChanged);
connect(m_sliderSettingsWidget, &SliderSettingsWidget::lockzChanged, this,
&ParameterTuningWidget::onLockZValueChanged);
connect(m_delegate, &ParameterTuningDelegate::currentLinkChanged, this,
&ParameterTuningWidget::onCurrentLinkChanged);
connect(m_treeView, &QTreeView::customContextMenuRequested, this,
&ParameterTuningWidget::onCustomContextMenuRequested);
}
void ParameterTuningWidget::setJobOrRealItem(QObject* job_item)
{
DataAccessWidget::setJobOrRealItem(job_item);
m_sliderSettingsWidget->setJobOrRealItem(job_item);
updateParameterModel();
updateDragAndDropSettings();
connect(jobItem(), &JobItem::jobStatusChanged, this,
[this](const JobStatus) { updateJobStatus(); });
updateJobStatus();
}
void ParameterTuningWidget::setModel(QObject* jobModel)
{
m_jobModel = dynamic_cast<JobModel*>(jobModel);
ASSERT(m_jobModel);
}
QItemSelectionModel* ParameterTuningWidget::selectionModel()
{
ASSERT(m_treeView);
return m_treeView->selectionModel();
}
//! Returns list of ParameterItem's currently selected in parameter tree
QVector<ParameterItem*> ParameterTuningWidget::selectedParameterItems()
{
QVector<ParameterItem*> result;
for (auto index : selectionModel()->selectedIndexes())
if (ParameterItem* parItem = m_parameterTuningModel->getParameterItem(index))
result.push_back(parItem);
return result;
}
void ParameterTuningWidget::onCurrentLinkChanged(ParameterItem* item)
{
ASSERT(jobItem());
if (jobItem()->isRunning())
return;
if (item)
m_jobModel->runJob(jobItem());
}
void ParameterTuningWidget::onSliderRangeChanged(int value)
{
m_delegate->setSliderRangeFactor(value);
}
void ParameterTuningWidget::onLockZValueChanged(bool value)
{
if (!jobItem())
return;
if (IntensityDataItem* intensityDataItem = jobItem()->intensityDataItem())
intensityDataItem->setZaxisLocked(value);
}
void ParameterTuningWidget::updateParameterModel()
{
ASSERT(m_jobModel);
if (!jobItem())
return;
if (!jobItem()->sampleItem() || !jobItem()->instrumentItem())
throw std::runtime_error("JobItem is missing sample or instrument model");
delete m_parameterTuningModel;
m_parameterTuningModel =
new ParameterTuningModel(jobItem()->parameterContainerItem()->parameterTreeRoot(), this);
m_treeView->setModel(m_parameterTuningModel);
if (m_treeView->columnWidth(0) < 170)
m_treeView->setColumnWidth(0, 170);
m_treeView->expandAll();
}
void ParameterTuningWidget::onCustomContextMenuRequested(const QPoint& point)
{
emit itemContextMenuRequest(m_treeView->mapToGlobal(point + QPoint(2, 22)));
}
void ParameterTuningWidget::restoreModelsOfCurrentJobItem()
{
ASSERT(m_jobModel);
ASSERT(jobItem());
if (jobItem()->isRunning())
return;
closeActiveEditors();
m_jobModel->restore(jobItem());
m_jobModel->runJob(jobItem());
gProjectDocument.value()->setModified();
}
void ParameterTuningWidget::makeSelected(ParameterItem* item)
{
QModelIndex index = m_parameterTuningModel->indexForItem(item);
if (index.isValid())
selectionModel()->select(index, QItemSelectionModel::Select);
}
void ParameterTuningWidget::contextMenuEvent(QContextMenuEvent*)
{
// reimplemented to suppress context menu from QMainWindow
}
//! Disable drag-and-drop abilities, if job is in fit running state.
void ParameterTuningWidget::updateDragAndDropSettings()
{
ASSERT(jobItem());
if (jobItem()->status() == JobStatus::Fitting) {
setTuningDelegateEnabled(false);
m_treeView->setDragDropMode(QAbstractItemView::NoDragDrop);
} else {
setTuningDelegateEnabled(true);
if (jobItem()->isValidForFitting())
m_treeView->setDragDropMode(QAbstractItemView::DragOnly);
}
}
//! Sets delegate to enabled/disabled state.
//! In 'disabled' state the delegate is in ReadOnlyMode, if it was containing already some
//! editing widget, it will be forced to close.
void ParameterTuningWidget::setTuningDelegateEnabled(bool enabled)
{
if (enabled)
m_delegate->setReadOnly(false);
else {
m_delegate->setReadOnly(true);
closeActiveEditors();
}
}
void ParameterTuningWidget::closeActiveEditors()
{
QModelIndex index = m_treeView->currentIndex();
QWidget* editor = m_treeView->indexWidget(index);
if (editor) {
// m_delegate->commitData(editor);
m_delegate->closeEditor(editor, QAbstractItemDelegate::NoHint);
}
m_treeView->selectionModel()->clearSelection();
}
void ParameterTuningWidget::updateJobStatus()
{
m_cautionSign->clear();
if (jobItem()->isFailed()) {
QString message;
message.append("Current parameter values cause simulation failure.\n\n");
message.append(jobItem()->comments());
m_cautionSign->setCautionMessage(message);
}
updateDragAndDropSettings();
}