// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/View/SampleDesigner/SampleView.cpp //! @brief Implements class SampleView //! //! @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/SampleDesigner/SampleView.h" #include "GUI/Model/Group/FilterPropertyProxy.h" #include "GUI/Model/Project/ProjectDocument.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Sample/SampleModel.h" #include "GUI/View/Common/DocksController.h" #include "GUI/View/Realspace/RealSpaceCanvas.h" #include "GUI/View/SampleDesigner/DesignerScene.h" #include "GUI/View/SampleDesigner/DesignerView.h" #include "GUI/View/SampleDesigner/LayerOrientedSampleEditor.h" #include "GUI/View/SampleDesigner/RealSpacePanel.h" #include "GUI/View/SampleDesigner/SampleListView.h" #include "GUI/View/SampleDesigner/SamplePropertyWidget.h" #include "GUI/View/SampleDesigner/SampleToolBar.h" #include "GUI/View/SampleDesigner/SampleToolBox.h" #include "GUI/View/SampleDesigner/SampleTreeWidget.h" #include "GUI/View/SampleDesigner/ScriptPanel.h" #include <QBoxLayout> #include <QDockWidget> #include <QMenu> #include <QToolButton> SampleView::SampleView(QWidget* parent, ProjectDocument* document, bool initAsLayerOrientedEditor) : QMainWindow(parent), m_document(document) { setObjectName("SampleView"); connect(m_document, &ProjectDocument::modified, this, &SampleView::updateFunctionalities); if (initAsLayerOrientedEditor) initLayerOrientedEditor(); else initNetOrientedEditor(); } void SampleView::initNetOrientedEditor() { const bool wasVisible = isVisible(); hide(); // important; otherwise the dockwidget layout is messed up deleteEditor(); m_docks = new DocksController(this); auto* designerScene = new DesignerScene(this, m_document); auto* designerView = new DesignerView(designerScene, this); auto* toolBox = new SampleToolBox(this); auto* treeWidget = new SampleTreeWidget(this, m_document->sampleModel()); auto* propertyWidget = new SamplePropertyWidget(treeWidget->treeView()->selectionModel(), this); auto* scriptPanel = new ScriptPanel(m_document->sampleModel(), this); m_realSpacePanel = new RealSpacePanel(m_document->sampleModel(), this); m_docks->addWidget(TOOLBOX, toolBox, Qt::LeftDockWidgetArea); m_docks->addWidget(SAMPLE_TREE, treeWidget, Qt::RightDockWidgetArea); m_docks->addWidget(PROPERTY_EDITOR, propertyWidget, Qt::RightDockWidgetArea); m_docks->addWidget(INFO, scriptPanel, Qt::BottomDockWidgetArea); m_docks->addWidget(REALSPACEPANEL, m_realSpacePanel, Qt::BottomDockWidgetArea); connect(scriptPanel, &ScriptPanel::widgetHeightRequest, m_docks, &DocksController::setDockHeightForWidget); designerScene->setSelectionModel( treeWidget->treeView()->selectionModel(), dynamic_cast<FilterPropertyProxy*>( const_cast<QAbstractItemModel*>(treeWidget->treeView()->model()))); setCentralWidget(designerView); resetLayout(); // m_toolBar should be initialized after MaterialBrowser m_toolBar = new SampleToolBar(this); connect(m_toolBar, &SampleToolBar::deleteItems, designerView, &DesignerView::deleteSelectedItems); connect(m_toolBar, &SampleToolBar::selectionMode, designerView, &DesignerView::onSelectionMode); connect(designerView, &DesignerView::selectionModeChanged, m_toolBar, &SampleToolBar::onViewSelectionMode); connect(m_toolBar, &SampleToolBar::centerView, designerView, &DesignerView::onCenterView); connect(m_toolBar, &SampleToolBar::changeScale, designerView, &DesignerView::onChangeScale); connect(designerScene, &DesignerScene::selectionModeChangeRequest, designerView, &DesignerView::onSelectionMode); connect(treeWidget->treeView()->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SampleView::onSampleTreeViewSelectionChanged); addToolBar(m_toolBar); m_useLayerOrientedEditor = false; if (wasVisible) show(); } void SampleView::initLayerOrientedEditor() { const bool wasVisible = isVisible(); hide(); // important; otherwise the dockwidget layout is messed up deleteEditor(); m_docks = new DocksController(this); auto* editor = new LayerOrientedSampleEditor(this); auto* sampleSelectionPane = new QWidget(this); auto* sampleSelectionLayout = new QVBoxLayout(sampleSelectionPane); sampleSelectionLayout->setContentsMargins(0, 0, 0, 0); sampleSelectionLayout->setSpacing(0); auto* sampleSelectionToolbar = new StyledToolBar(sampleSelectionPane); auto* sampleSelectionView = new SampleListView(this, m_document->sampleModel()); sampleSelectionToolbar->addAction(sampleSelectionView->newSampleAction()); sampleSelectionToolbar->addAction(sampleSelectionView->chooseFromLibraryAction()); if (auto* btn = dynamic_cast<QToolButton*>(sampleSelectionToolbar->widgetForAction( sampleSelectionView->chooseFromLibraryAction()))) btn->setPopupMode(QToolButton::InstantPopup); sampleSelectionToolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); sampleSelectionLayout->addWidget(sampleSelectionToolbar); sampleSelectionLayout->addWidget(sampleSelectionView); sampleSelectionView->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); auto* scriptPanel = new ScriptPanel(m_document->sampleModel(), this); m_realSpacePanel = new RealSpacePanel(m_document->sampleModel(), this); m_realSpacePanel->setLockViewActionVisible(false); // lock not used in layer oriented editor sampleSelectionPane->setWindowTitle("Samples"); m_docks->addWidget(SAMPLE_LIST, sampleSelectionPane, Qt::LeftDockWidgetArea); m_docks->addWidget(REALSPACEPANEL, m_realSpacePanel, Qt::BottomDockWidgetArea); m_docks->addWidget(INFO, scriptPanel, Qt::BottomDockWidgetArea); connect(scriptPanel, &ScriptPanel::widgetHeightRequest, m_docks, &DocksController::setDockHeightForWidget); connect(sampleSelectionView, &SampleListView::currentSampleChanged, this, &SampleView::onCurrentSampleChanged); connect(sampleSelectionView, &SampleListView::currentSampleChanged, editor, &LayerOrientedSampleEditor::setCurrentSample); connect(editor, &LayerOrientedSampleEditor::requestViewInRealSpace, this, &SampleView::onRequestViewInRealSpace); setCentralWidget(editor); resetLayout(); m_useLayerOrientedEditor = true; if (wasVisible) show(); } void SampleView::deleteEditor() { delete m_toolBar; m_toolBar = nullptr; if (m_docks != nullptr) { auto dockWidgets = m_docks->dockWidgets(); delete m_docks; m_docks = nullptr; qDeleteAll(dockWidgets); } if (auto* w = dynamic_cast<DesignerView*>(centralWidget())) delete w->scene(); delete centralWidget(); } void SampleView::updateFunctionalities() { if (auto* d = m_docks->findDock(SAMPLE_LIST)) { if (m_document->singleSampleMode()) d->hide(); else d->show(); } } void SampleView::onSampleTreeViewSelectionChanged(const QItemSelection& selected, const QItemSelection&) { if (m_realSpacePanel->isViewLocked()) return; if (selected.indexes().empty()) return; const QModelIndex currentIndex = FilterPropertyProxy::toSourceIndex(selected.indexes().back()); auto* item = m_document->sampleModel()->itemForIndex(currentIndex); if (item) m_realSpacePanel->canvas()->setCurrentItem(item); } void SampleView::onCurrentSampleChanged(MultiLayerItem* current) { if (m_layerOrientedSampleEditor) m_layerOrientedSampleEditor->setCurrentSample(current); m_realSpacePanel->canvas()->setCurrentItem(current); } void SampleView::onRequestViewInRealSpace(SessionItem* itemToView) { if (!itemToView) return; m_docks->setDockVisible(REALSPACEPANEL); m_realSpacePanel->canvas()->setCurrentItem(itemToView); } void SampleView::toggleRealSpaceView() { m_docks->toggleDock(REALSPACEPANEL); } void SampleView::fillViewMenu(QMenu* menu) { auto* editorSelectionActions = new QActionGroup(this); auto* action = menu->addAction("Layer oriented sample editor"); action->setCheckable(true); action->setChecked(m_useLayerOrientedEditor); connect(action, &QAction::triggered, this, &SampleView::initLayerOrientedEditor, Qt::QueuedConnection); editorSelectionActions->addAction(action); action = menu->addAction("Net oriented sample editor"); action->setCheckable(true); action->setChecked(!m_useLayerOrientedEditor); connect(action, &QAction::triggered, this, &SampleView::initNetOrientedEditor, Qt::QueuedConnection); editorSelectionActions->addAction(action); menu->addSeparator(); m_docks->addDockActionsToMenu(menu); menu->addSeparator(); action = new QAction(menu); action->setText("Reset to default layout"); connect(action, &QAction::triggered, this, &SampleView::resetLayout); menu->addAction(action); } void SampleView::resetLayout() { m_docks->resetLayout(); tabifyDockWidget(m_docks->findDock(REALSPACEPANEL), m_docks->findDock(INFO)); m_docks->findDock(REALSPACEPANEL)->raise(); // makes first tab active m_docks->findDock(REALSPACEPANEL)->hide(); m_docks->findDock(INFO)->hide(); if (auto* d = m_docks->findDock(SAMPLE_LIST)) { if (m_document->singleSampleMode()) d->hide(); else d->show(); } }