diff --git a/GUI/View/Realspace/RealSpaceCanvas.cpp b/GUI/View/Realspace/RealSpaceCanvas.cpp index ef4cf7b318846154c8bf262ecba96d9991471d28..fc7bec467c989c7e9f93b408b9b2108e2e567e22 100644 --- a/GUI/View/Realspace/RealSpaceCanvas.cpp +++ b/GUI/View/Realspace/RealSpaceCanvas.cpp @@ -27,14 +27,14 @@ #include <QMessageBox> #include <QVBoxLayout> -RealSpaceCanvas::RealSpaceCanvas(QWidget* parent) +RealSpaceCanvas::RealSpaceCanvas(SampleModel* sampleModel, QWidget* parent) : QWidget(parent) - , m_sampleModel(nullptr) + , m_sampleModel(sampleModel) , m_view(new GUI::RealSpace::Widget3D) - , m_selectionModel(nullptr) , m_view_locked(false) , m_sceneGeometry(new SceneGeometry) , m_cautionSign(new CautionSign(this)) + , m_currentItem(nullptr) { auto layout = new QVBoxLayout; layout->setMargin(0); @@ -43,93 +43,23 @@ RealSpaceCanvas::RealSpaceCanvas(QWidget* parent) setLayout(layout); } -RealSpaceCanvas::~RealSpaceCanvas() = default; - -void RealSpaceCanvas::setModel(SampleModel* sampleModel, QItemSelectionModel* selectionModel) +void RealSpaceCanvas::setCurrentItem(SessionItem* item) { - if (sampleModel != m_sampleModel) { - - if (m_sampleModel) - setConnected(m_sampleModel, false); - - m_sampleModel = sampleModel; - - if (m_sampleModel) - setConnected(m_sampleModel, true); - } - - if (selectionModel != m_selectionModel) { - if (m_selectionModel) - disconnect(m_selectionModel, &QItemSelectionModel::selectionChanged, this, - &RealSpaceCanvas::onSelectionChanged); - - m_selectionModel = selectionModel; - - if (m_selectionModel) - connect(m_selectionModel, &QItemSelectionModel::selectionChanged, this, - &RealSpaceCanvas::onSelectionChanged); - } - - updateToSelection(); -} - -void RealSpaceCanvas::onSelectionChanged(const QItemSelection&, const QItemSelection&) -{ - updateToSelection(); -} - -void RealSpaceCanvas::updateToSelection() -{ - if (!m_selectionModel) - return; - - if (!m_view_locked) { - QModelIndexList indices = m_selectionModel->selection().indexes(); - - if (!indices.empty()) - m_currentSelection = FilterPropertyProxy::toSourceIndex(indices.back()); - else - m_currentSelection = {}; - // if no object is selected then display nothing on canvas - - updateScene(); - } -} - -void RealSpaceCanvas::onDefaultViewAction() -{ - defaultView(); -} - -void RealSpaceCanvas::onSideViewAction() -{ - sideView(); -} - -void RealSpaceCanvas::onTopViewAction() -{ - topView(); -} - -void RealSpaceCanvas::onLockViewAction(bool view_locked) -{ - if (m_view_locked != view_locked) { - m_view_locked = view_locked; - updateToSelection(); - } + m_currentItem = item; + updateScene(); } -void RealSpaceCanvas::onChangeLayerSizeAction(double layerSizeChangeScale) +void RealSpaceCanvas::changeLayerSize(double layerSizeChangeScale) { // when no object is selected --> take no action - if (m_currentSelection == QModelIndex()) + if (m_currentItem == nullptr) return; m_sceneGeometry->set_layer_size(m_sceneGeometry->layer_size() * layerSizeChangeScale); updateScene(); } -void RealSpaceCanvas::onSavePictureAction() +void RealSpaceCanvas::savePicture() { QPixmap pixmap(this->size()); render(&pixmap, QPoint(), childrenRegion()); @@ -141,10 +71,23 @@ void RealSpaceCanvas::onRowsAboutToBeRemoved(const QModelIndex& parent, int firs // clear scene if current selection will be removed if (!m_sampleModel) return; - if (m_currentSelection == m_sampleModel->index(first, 0, parent)) + const QModelIndex idx = m_sampleModel->index(first, 0, parent); + const auto* itemToBeRemoved = m_sampleModel->itemForIndex(idx); + if (m_currentItem == itemToBeRemoved) resetScene(); } +void RealSpaceCanvas::showEvent(QShowEvent*) +{ + setConnected(m_sampleModel, true); + updateScene(); +} + +void RealSpaceCanvas::hideEvent(QHideEvent*) +{ + setConnected(m_sampleModel, false); +} + void RealSpaceCanvas::savePicture(const QPixmap& pixmap) { QString dirname = gSessionData->projectDocument->userExportDir(); @@ -173,12 +116,12 @@ void RealSpaceCanvas::savePicture(const QPixmap& pixmap) void RealSpaceCanvas::updateScene() { + if (!m_currentItem) + return; + QApplication::setOverrideCursor(Qt::WaitCursor); m_realSpaceModel.reset(new RealSpaceModel); - auto item = m_sampleModel->itemForIndex(m_currentSelection); - if (!item) - return; RealSpaceBuilder builder3D; @@ -186,11 +129,11 @@ void RealSpaceCanvas::updateScene() m_cautionSign->clear(); // if the view is locked, keep the current orientation of the camera if (m_view_locked) - builder3D.populate(m_realSpaceModel.get(), *item, *m_sceneGeometry, + builder3D.populate(m_realSpaceModel.get(), *m_currentItem, *m_sceneGeometry, m_view->cam().getPos()); // otherwise use default orientation of camera else { - builder3D.populate(m_realSpaceModel.get(), *item, *m_sceneGeometry); + builder3D.populate(m_realSpaceModel.get(), *m_currentItem, *m_sceneGeometry); defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0 } } catch (const std::exception& ex) { @@ -207,7 +150,7 @@ void RealSpaceCanvas::resetScene() { m_realSpaceModel.reset(); m_view->setModel(nullptr); - m_currentSelection = {}; + m_currentItem = nullptr; } void RealSpaceCanvas::defaultView() @@ -242,7 +185,7 @@ void RealSpaceCanvas::setConnected(SampleModel* model, bool makeConnected) connect(model, &SampleModel::modelReset, this, &RealSpaceCanvas::resetScene, Qt::UniqueConnection); connect( - model, &SampleModel::modelAboutToBeReset, this, [&]() { m_currentSelection = {}; }, + model, &SampleModel::modelAboutToBeReset, this, [&]() { m_currentItem = nullptr; }, Qt::UniqueConnection); } else { diff --git a/GUI/View/Realspace/RealSpaceCanvas.h b/GUI/View/Realspace/RealSpaceCanvas.h index 750042cb50a184bf8d26cf80c32a040940a225ec..a27b1432fc65e524a522002f03aa2cc6da1f316a 100644 --- a/GUI/View/Realspace/RealSpaceCanvas.h +++ b/GUI/View/Realspace/RealSpaceCanvas.h @@ -15,14 +15,13 @@ #ifndef BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H #define BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H -#include <QItemSelectionModel> -#include <QModelIndex> #include <QWidget> #include <memory> class SampleModel; class RealSpaceModel; class CautionSign; +class SessionItem; namespace GUI::RealSpace { class Widget3D; } @@ -60,44 +59,35 @@ class RealSpaceCanvas : public QWidget { Q_OBJECT public: - RealSpaceCanvas(QWidget* parent = nullptr); - ~RealSpaceCanvas(); - - void setModel(SampleModel* sampleModel = nullptr, - QItemSelectionModel* selectionModel = nullptr); - -public slots: - void onSelectionChanged(const QItemSelection&, const QItemSelection&); - void updateToSelection(); - - void onDefaultViewAction(); - void onSideViewAction(); - void onTopViewAction(); - void onLockViewAction(bool view_locked); - void onChangeLayerSizeAction(double layer_size_scale); - void onSavePictureAction(); - void onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last); + RealSpaceCanvas(SampleModel* sampleModel, QWidget* parent = nullptr); -private slots: - void updateScene(); - void resetScene(); + void setCurrentItem(SessionItem* item); void defaultView(); void sideView(); void topView(); + void changeLayerSize(double layer_size_scale); + void savePicture(); + +protected: + virtual void showEvent(QShowEvent*) override; + virtual void hideEvent(QHideEvent*) override; + private: + void updateScene(); + void resetScene(); + void onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last); void setConnected(SampleModel* model, bool makeConnected); + void savePicture(const QPixmap& pixmap); SampleModel* m_sampleModel; - QModelIndex m_currentSelection; GUI::RealSpace::Widget3D* m_view; std::unique_ptr<RealSpaceModel> m_realSpaceModel; - QItemSelectionModel* m_selectionModel; bool m_view_locked; std::unique_ptr<SceneGeometry> m_sceneGeometry; CautionSign* m_cautionSign; - void savePicture(const QPixmap& pixmap); + SessionItem* m_currentItem; }; #endif // BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H diff --git a/GUI/View/SampleDesigner/RealSpacePanel.cpp b/GUI/View/SampleDesigner/RealSpacePanel.cpp index 2687b89957ba9e066d436f419abb160f9c0077d2..031f649e9f7a22227e6fd710c4ddaecdfb6db4ce 100644 --- a/GUI/View/SampleDesigner/RealSpacePanel.cpp +++ b/GUI/View/SampleDesigner/RealSpacePanel.cpp @@ -17,12 +17,8 @@ #include "GUI/View/Realspace/RealSpaceCanvas.h" #include <QVBoxLayout> -RealSpacePanel::RealSpacePanel(SampleModel* sampleModel, QItemSelectionModel* selectionModel, - QWidget* parent) - : QWidget(parent) - , m_canvas(new RealSpaceCanvas) - , m_sampleModel(sampleModel) - , m_selectionModel(selectionModel) +RealSpacePanel::RealSpacePanel(SampleModel* sampleModel, QWidget* parent) + : QWidget(parent), m_canvas(new RealSpaceCanvas(sampleModel)) { setWindowTitle("Real Space"); setObjectName("Sample3DPanel"); @@ -38,26 +34,25 @@ RealSpacePanel::RealSpacePanel(SampleModel* sampleModel, QItemSelectionModel* se }; auto* action = createAction("Save Picture", "Save 3D real space view as .png file"); - connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::onSavePictureAction); + connect(action, &QAction::triggered, m_canvas, QOverload<>::of(&RealSpaceCanvas::savePicture)); action = createAction("Default View", "Reset view and zoom level to default"); - connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::onDefaultViewAction); + connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::defaultView); action = createAction("Side View", "View sample from the side at current zoom level"); - connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::onSideViewAction); + connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::sideView); action = createAction("Top View", "View sample from the top at current zoom level"); - connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::onTopViewAction); + connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::topView); action = createAction("Enlarge", "Increase layer size"); - connect(action, &QAction::triggered, [this]() { m_canvas->onChangeLayerSizeAction(1.25); }); + connect(action, &QAction::triggered, [this]() { m_canvas->changeLayerSize(1.25); }); action = createAction("Reduce", "Decrease layer size"); - connect(action, &QAction::triggered, [this]() { m_canvas->onChangeLayerSizeAction(0.8); }); + connect(action, &QAction::triggered, [this]() { m_canvas->changeLayerSize(0.8); }); - action = createAction("Lock View", "Lock/unlock current sample selection"); - action->setCheckable(true); - connect(action, &QAction::triggered, m_canvas, &RealSpaceCanvas::onLockViewAction); + m_lockViewAction = createAction("Lock View", "Lock/unlock current sample selection"); + m_lockViewAction->setCheckable(true); auto* mainLayout = new QVBoxLayout(this); mainLayout->setMargin(0); @@ -72,12 +67,12 @@ QSize RealSpacePanel::sizeHint() const return QSize(300, 300); } -void RealSpacePanel::showEvent(QShowEvent*) +RealSpaceCanvas* RealSpacePanel::canvas() { - m_canvas->setModel(m_sampleModel, m_selectionModel); + return m_canvas; } -void RealSpacePanel::hideEvent(QHideEvent*) +bool RealSpacePanel::isViewLocked() const { - m_canvas->setModel(nullptr, nullptr); + return m_lockViewAction->isChecked(); } diff --git a/GUI/View/SampleDesigner/RealSpacePanel.h b/GUI/View/SampleDesigner/RealSpacePanel.h index 5d5b7d4e9809671dc5bc01b4e304308dba7237ee..ee3afb0df327e4b35f998916b2a58a5d56eb8472 100644 --- a/GUI/View/SampleDesigner/RealSpacePanel.h +++ b/GUI/View/SampleDesigner/RealSpacePanel.h @@ -28,18 +28,16 @@ class RealSpacePanel : public QWidget { Q_OBJECT public: - RealSpacePanel(SampleModel* sampleModel, QItemSelectionModel* selectionModel, QWidget* parent); + RealSpacePanel(SampleModel* sampleModel, QWidget* parent); QSize sizeHint() const override; + RealSpaceCanvas* canvas(); -protected: - void showEvent(QShowEvent*) override; - void hideEvent(QHideEvent*) override; + bool isViewLocked() const; private: RealSpaceCanvas* m_canvas; - SampleModel* m_sampleModel; - QItemSelectionModel* m_selectionModel; + QAction* m_lockViewAction; }; #endif // BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_REALSPACEPANEL_H diff --git a/GUI/View/SampleDesigner/SampleView.cpp b/GUI/View/SampleDesigner/SampleView.cpp index 201e7c0f98a7288249e12fde7919ed77bf7d0693..60c88ce44d9c5cef5a9d3be7d0a0254657b2fdfd 100644 --- a/GUI/View/SampleDesigner/SampleView.cpp +++ b/GUI/View/SampleDesigner/SampleView.cpp @@ -16,7 +16,9 @@ #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" @@ -61,14 +63,13 @@ void SampleView::initNetOrientedEditor() auto* treeWidget = new SampleTreeWidget(this, m_document->sampleModel()); auto* propertyWidget = new SamplePropertyWidget(treeWidget->treeView()->selectionModel(), this); auto* scriptPanel = new ScriptPanel(m_document->sampleModel(), this); - auto* realSpacePanel = new RealSpacePanel(m_document->sampleModel(), - treeWidget->treeView()->selectionModel(), 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, realSpacePanel, Qt::BottomDockWidgetArea); + m_docks->addWidget(REALSPACEPANEL, m_realSpacePanel, Qt::BottomDockWidgetArea); connect(scriptPanel, &ScriptPanel::widgetHeightRequest, m_docks, &DocksController::setDockHeightForWidget); @@ -92,6 +93,8 @@ void SampleView::initNetOrientedEditor() 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); @@ -131,12 +134,12 @@ void SampleView::initLayerOrientedEditor() QSizePolicy::MinimumExpanding); auto* scriptPanel = new ScriptPanel(m_document->sampleModel(), this); - auto* realSpacePanel = new RealSpacePanel(m_document->sampleModel(), nullptr, this); + m_realSpacePanel = new RealSpacePanel(m_document->sampleModel(), this); sampleSelectionPane->setWindowTitle("Samples"); m_docks->addWidget(SAMPLE_LIST, sampleSelectionPane, Qt::LeftDockWidgetArea); - m_docks->addWidget(REALSPACEPANEL, realSpacePanel, Qt::BottomDockWidgetArea); + m_docks->addWidget(REALSPACEPANEL, m_realSpacePanel, Qt::BottomDockWidgetArea); m_docks->addWidget(INFO, scriptPanel, Qt::BottomDockWidgetArea); connect(scriptPanel, &ScriptPanel::widgetHeightRequest, m_docks, @@ -181,6 +184,21 @@ void SampleView::updateFunctionalities() } } +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::toggleRealSpaceView() { m_docks->toggleDock(REALSPACEPANEL); diff --git a/GUI/View/SampleDesigner/SampleView.h b/GUI/View/SampleDesigner/SampleView.h index 28961e4dd405e5f67ed7c21cb505751482d59a5d..16e2f9851a2eef2f8a4f879ef66f3a7378154460 100644 --- a/GUI/View/SampleDesigner/SampleView.h +++ b/GUI/View/SampleDesigner/SampleView.h @@ -20,6 +20,8 @@ class DocksController; class ProjectDocument; class SampleToolBar; +class RealSpacePanel; +class QItemSelection; class SampleView : public QMainWindow { Q_OBJECT @@ -37,10 +39,12 @@ private: void initLayerOrientedEditor(); void deleteEditor(); void updateFunctionalities(); + void onSampleTreeViewSelectionChanged(const QItemSelection& selected, const QItemSelection&); DocksController* m_docks = nullptr; ProjectDocument* m_document = nullptr; SampleToolBar* m_toolBar = nullptr; + RealSpacePanel* m_realSpacePanel = nullptr; bool m_useLayerOrientedEditor = false; };