From 3ce2b6d6abd7cad0285b65a49a9723a29fe15bd4 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Tue, 9 Nov 2021 08:07:49 +0100 Subject: [PATCH] simplify RealSpace (3D) view - refactoring, mv selection handling out of presentation class --- GUI/View/Realspace/RealSpaceCanvas.cpp | 117 ++++++--------------- GUI/View/Realspace/RealSpaceCanvas.h | 40 +++---- GUI/View/SampleDesigner/RealSpacePanel.cpp | 33 +++--- GUI/View/SampleDesigner/RealSpacePanel.h | 10 +- GUI/View/SampleDesigner/SampleView.cpp | 28 ++++- GUI/View/SampleDesigner/SampleView.h | 4 + 6 files changed, 90 insertions(+), 142 deletions(-) diff --git a/GUI/View/Realspace/RealSpaceCanvas.cpp b/GUI/View/Realspace/RealSpaceCanvas.cpp index ef4cf7b3188..fc7bec467c9 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 750042cb50a..a27b1432fc6 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 2687b89957b..031f649e9f7 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 5d5b7d4e980..ee3afb0df32 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 201e7c0f98a..60c88ce44d9 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 28961e4dd40..16e2f9851a2 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; }; -- GitLab