Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • c.trageser/bornagain
  • mlz/bornagain
2 results
Show changes
Commits on Source (10)
Showing
with 166 additions and 261 deletions
......@@ -25,9 +25,9 @@
#include "GUI/View/Realspace/Particle3DContainer.h"
#include "GUI/View/Realspace/RealSpaceBuilderUtils.h"
#include "GUI/View/Realspace/RealSpaceCanvas.h"
#include "GUI/View/Realspace/RealSpaceModel.h"
#include "GUI/View/Realspace/RealSpacePositionBuilder.h"
#include "GUI/View/Realspace/TransformTo3D.h"
#include "GUI/ba3d/model/model.h"
#include "Sample/Aggregate/Interferences.h"
#include "Sample/Particle/Particle.h"
#include "Sample/Particle/ParticleCoreShell.h"
......@@ -52,7 +52,7 @@ RealSpaceBuilder::RealSpaceBuilder(QWidget* parent) : QWidget(parent) {}
RealSpaceBuilder::~RealSpaceBuilder() = default;
void RealSpaceBuilder::populate(RealSpaceModel* model, const SessionItem& item,
void RealSpaceBuilder::populate(GUI::RealSpace::Model* model, const SessionItem& item,
const SceneGeometry& sceneGeometry,
const GUI::RealSpace::Camera::Position& cameraPosition) const
{
......@@ -74,7 +74,8 @@ void RealSpaceBuilder::populate(RealSpaceModel* model, const SessionItem& item,
populateParticleFromParticleItem(model, item);
}
void RealSpaceBuilder::populateMultiLayer(RealSpaceModel* model, const MultiLayerItem& mlayerItem,
void RealSpaceBuilder::populateMultiLayer(GUI::RealSpace::Model* model,
const MultiLayerItem& mlayerItem,
const SceneGeometry& sceneGeometry,
const QVector3D&) const
{
......@@ -93,7 +94,7 @@ void RealSpaceBuilder::populateMultiLayer(RealSpaceModel* model, const MultiLaye
}
}
void RealSpaceBuilder::populateLayer(RealSpaceModel* model, const LayerItem& layerItem,
void RealSpaceBuilder::populateLayer(GUI::RealSpace::Model* model, const LayerItem& layerItem,
const SceneGeometry& sceneGeometry, const QVector3D& origin,
const bool isTopLayer) const
{
......@@ -105,7 +106,8 @@ void RealSpaceBuilder::populateLayer(RealSpaceModel* model, const LayerItem& lay
populateLayout(model, *layout, sceneGeometry, origin);
}
void RealSpaceBuilder::populateLayout(RealSpaceModel* model, const ParticleLayoutItem& layoutItem,
void RealSpaceBuilder::populateLayout(GUI::RealSpace::Model* model,
const ParticleLayoutItem& layoutItem,
const SceneGeometry& sceneGeometry,
const QVector3D& origin) const
{
......@@ -113,7 +115,7 @@ void RealSpaceBuilder::populateLayout(RealSpaceModel* model, const ParticleLayou
if (layoutItem.particles().empty())
return;
double layer_size = sceneGeometry.layer_size();
double layer_size = sceneGeometry.layerSize;
double total_density = layoutItem.totalDensity();
auto particle3DContainer_vector =
......@@ -129,7 +131,7 @@ void RealSpaceBuilder::populateLayout(RealSpaceModel* model, const ParticleLayou
lattice_positions, particle3DContainer_vector, model, sceneGeometry, this);
}
void RealSpaceBuilder::populateParticleFromParticleItem(RealSpaceModel* model,
void RealSpaceBuilder::populateParticleFromParticleItem(GUI::RealSpace::Model* model,
const SessionItem& particleItem) const
{
Particle3DContainer particle3DContainer;
......@@ -166,7 +168,7 @@ void RealSpaceBuilder::populateParticleFromParticleItem(RealSpaceModel* model,
}
void RealSpaceBuilder::populateParticleFromParticle3DContainer(
RealSpaceModel* model, const Particle3DContainer& particle3DContainer,
GUI::RealSpace::Model* model, const Particle3DContainer& particle3DContainer,
const QVector3D& lattice_position) const
{
if (particle3DContainer.containerSize()) {
......
......@@ -23,10 +23,13 @@ class SessionItem;
class LayerItem;
class MultiLayerItem;
class ParticleLayoutItem;
class RealSpaceModel;
class Shape3D;
class SceneGeometry;
struct SceneGeometry;
class Particle3DContainer;
namespace GUI::RealSpace {
class Model;
}
class RealSpaceBuilder : public QWidget {
Q_OBJECT
......@@ -37,26 +40,27 @@ public:
~RealSpaceBuilder();
void
populate(RealSpaceModel* model, const SessionItem& item, const SceneGeometry& sceneGeometry,
populate(GUI::RealSpace::Model* model, const SessionItem& item,
const SceneGeometry& sceneGeometry,
const GUI::RealSpace::Camera::Position& cameraPosition =
GUI::RealSpace::Camera::Position(GUI::RealSpace::Vector3D(0, -200, 120), // eye
GUI::RealSpace::Vector3D(0, 0, 0), // center
GUI::RealSpace::Vector3D::_z)) // up
const;
void populateMultiLayer(RealSpaceModel* model, const MultiLayerItem& mlayerItem,
void populateMultiLayer(GUI::RealSpace::Model* model, const MultiLayerItem& mlayerItem,
const SceneGeometry& sceneGeometry, const QVector3D& origin = {}) const;
void populateLayer(RealSpaceModel* model, const LayerItem& layerItem,
void populateLayer(GUI::RealSpace::Model* model, const LayerItem& layerItem,
const SceneGeometry& sceneGeometry, const QVector3D& origin = {},
const bool isTopLayer = false) const;
void populateLayout(RealSpaceModel* model, const ParticleLayoutItem& layoutItem,
void populateLayout(GUI::RealSpace::Model* model, const ParticleLayoutItem& layoutItem,
const SceneGeometry& sceneGeometry, const QVector3D& origin = {}) const;
void populateParticleFromParticleItem(RealSpaceModel* model,
void populateParticleFromParticleItem(GUI::RealSpace::Model* model,
const SessionItem& particleItem) const;
void populateParticleFromParticle3DContainer(RealSpaceModel* model,
void populateParticleFromParticle3DContainer(GUI::RealSpace::Model* model,
const Particle3DContainer& particle3DContainer,
const QVector3D& lattice_position = {}) const;
};
......
......@@ -72,12 +72,12 @@ GUI::RealSpace::BuilderUtils::computeCumulativeAbundances(const ParticleLayoutIt
void GUI::RealSpace::BuilderUtils::populateParticlesAtLatticePositions(
const std::vector<std::vector<double>>& lattice_positions,
const std::vector<Particle3DContainer>& particle3DContainer_vector, RealSpaceModel* model,
const SceneGeometry& sceneGeometry, const RealSpaceBuilder* builder3D)
const std::vector<Particle3DContainer>& particle3DContainer_vector,
GUI::RealSpace::Model* model, const SceneGeometry& sceneGeometry,
const RealSpaceBuilder* builder3D)
{
double layer_size = sceneGeometry.layer_size();
double layer_thickness =
std::max(sceneGeometry.layer_top_thickness(), sceneGeometry.layer_bottom_thickness());
double layer_size = sceneGeometry.layerSize;
double layer_thickness = sceneGeometry.topOrBottomLayerThickness;
for (std::vector<double> position : lattice_positions) {
// for random selection of particles based on their abundances
......
......@@ -20,9 +20,8 @@
#include <memory>
#include <utility>
class RealSpaceModel;
class SessionItem;
class SceneGeometry;
struct SceneGeometry;
class RealSpaceBuilder;
class IRotation;
class MesoCrystalItem;
......@@ -35,6 +34,7 @@ class Particle3DContainer;
class Interference2DParaCrystal;
namespace GUI::RealSpace {
struct Vector3D;
class Model;
namespace Particles {
class Particle;
}
......@@ -46,8 +46,9 @@ QVector<double> computeCumulativeAbundances(const ParticleLayoutItem& layoutItem
void populateParticlesAtLatticePositions(
const std::vector<std::vector<double>>& lattice_positions,
const std::vector<Particle3DContainer>& particle3DContainer_vector, RealSpaceModel* model,
const SceneGeometry& sceneGeometry, const RealSpaceBuilder* builder3D);
const std::vector<Particle3DContainer>& particle3DContainer_vector,
GUI::RealSpace::Model* model, const SceneGeometry& sceneGeometry,
const RealSpaceBuilder* builder3D);
// Implement Rotation of a 3D particle using parameters from IRotation Object
GUI::RealSpace::Vector3D implementParticleRotationfromIRotation(const IRotation*& rotation);
......
......@@ -20,21 +20,19 @@
#include "GUI/Model/State/SessionData.h"
#include "GUI/View/Info/CautionSign.h"
#include "GUI/View/Realspace/RealSpaceBuilder.h"
#include "GUI/View/Realspace/RealSpaceModel.h"
#include "GUI/ba3d/model/model.h"
#include "GUI/ba3d/widget.h"
#include <QApplication>
#include <QFileDialog>
#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 +41,24 @@ RealSpaceCanvas::RealSpaceCanvas(QWidget* parent)
setLayout(layout);
}
RealSpaceCanvas::~RealSpaceCanvas() = default;
void RealSpaceCanvas::setModel(SampleModel* sampleModel, QItemSelectionModel* selectionModel)
{
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()
void RealSpaceCanvas::setCurrentItem(SessionItem* item)
{
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();
defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0
}
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);
m_sceneGeometry.layerSize = m_sceneGeometry.layerSize * layerSizeChangeScale;
updateScene();
}
void RealSpaceCanvas::onSavePictureAction()
void RealSpaceCanvas::savePicture()
{
QPixmap pixmap(this->size());
render(&pixmap, QPoint(), childrenRegion());
......@@ -141,10 +70,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,26 +115,19 @@ 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;
m_realSpaceModel.reset(new GUI::RealSpace::Model);
RealSpaceBuilder builder3D;
try {
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,
m_view->cam().getPos());
// otherwise use default orientation of camera
else {
builder3D.populate(m_realSpaceModel.get(), *item, *m_sceneGeometry);
defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0
}
builder3D.populate(m_realSpaceModel.get(), *m_currentItem, m_sceneGeometry,
m_view->cam().getPos());
} catch (const std::exception& ex) {
m_cautionSign->setCautionMessage(ex.what());
} catch (...) {
......@@ -207,7 +142,7 @@ void RealSpaceCanvas::resetScene()
{
m_realSpaceModel.reset();
m_view->setModel(nullptr);
m_currentSelection = {};
m_currentItem = nullptr;
}
void RealSpaceCanvas::defaultView()
......@@ -242,16 +177,9 @@ 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 {
disconnect(model, &SampleModel::rowsInserted, this, &RealSpaceCanvas::updateScene);
disconnect(model, &SampleModel::rowsRemoved, this, &RealSpaceCanvas::updateScene);
connect(model, &SampleModel::rowsAboutToBeMoved, this,
&RealSpaceCanvas::onRowsAboutToBeRemoved);
disconnect(model, &SampleModel::nonPositionRelatedDataChanged, this,
&RealSpaceCanvas::updateScene);
disconnect(model, &SampleModel::modelReset, this, &RealSpaceCanvas::resetScene);
}
} else
model->disconnect(this);
}
......@@ -15,44 +15,22 @@
#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;
}
// Class for holding size and thickness information of layers
class SceneGeometry {
public:
SceneGeometry(double size = 100.0, double top_thickness = 25.0, double bottom_thickness = 25.0,
double min_thickness = 2.0)
{
l_size = size; // layer size
l_top_thickness = top_thickness; // top layer thickness
l_bottom_thickness = bottom_thickness; // bottom layer thickness
l_min_thickness = min_thickness; // minimum layer thickness
}
double layer_size() const { return l_size; }
double layer_top_thickness() const { return l_top_thickness; }
double layer_bottom_thickness() const { return l_top_thickness; }
double layer_min_thickness() const { return l_min_thickness; }
void set_layer_size(double size) { l_size = size; }
void set_layer_top_thickness(double top_thickness) { l_top_thickness = top_thickness; }
void set_layer_bottom_thickness(double bottom_thickness) { l_top_thickness = bottom_thickness; }
private:
double l_size;
double l_top_thickness;
double l_bottom_thickness;
double l_min_thickness;
class Model;
} // namespace GUI::RealSpace
//! Size and thickness information of layers
struct SceneGeometry {
double layerSize = 100.0;
double topOrBottomLayerThickness = 25.0;
double layerMinimumThickness = 2.0;
};
//! Provides 3D object generation for RealSpace presentation.
......@@ -60,44 +38,32 @@ 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);
private slots:
void updateScene();
void resetScene();
RealSpaceCanvas(SampleModel* sampleModel, QWidget* parent = nullptr);
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;
std::unique_ptr<GUI::RealSpace::Model> m_realSpaceModel;
SceneGeometry m_sceneGeometry;
CautionSign* m_cautionSign;
void savePicture(const QPixmap& pixmap);
SessionItem* m_currentItem;
};
#endif // BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACECANVAS_H
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/View/Realspace/RealSpaceModel.h
//! @brief Defines RealSpaceModel namespace
//!
//! @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)
//
// ************************************************************************************************
#ifndef BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACEMODEL_H
#define BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACEMODEL_H
#include "GUI/ba3d/model/model.h"
class RealSpaceModel : public GUI::RealSpace::Model {
};
#endif // BORNAGAIN_GUI_VIEW_REALSPACE_REALSPACEMODEL_H
......@@ -43,14 +43,12 @@ double GUI::View::TransformTo3D::visualLayerThickness(const LayerItem& layerItem
ASSERT(layerItem.hasModelType<LayerItem>());
double thickness(0.0);
if (isTopLayer(layerItem))
thickness = sceneGeometry.layer_top_thickness();
else if (isBottomLayer(layerItem))
thickness = sceneGeometry.layer_bottom_thickness();
if (isTopLayer(layerItem) || isBottomLayer(layerItem))
thickness = sceneGeometry.topOrBottomLayerThickness;
else
thickness = layerItem.thickness();
return thickness == 0.0 ? sceneGeometry.layer_min_thickness() : thickness;
return thickness == 0.0 ? sceneGeometry.layerMinimumThickness : thickness;
}
std::unique_ptr<GUI::RealSpace::Layer>
......@@ -59,7 +57,7 @@ GUI::View::TransformTo3D::createLayer(const LayerItem& layerItem,
{
double thickness = GUI::View::TransformTo3D::visualLayerThickness(layerItem, sceneGeometry);
double s2 = sceneGeometry.layer_size();
double s2 = sceneGeometry.layerSize;
double ztop = static_cast<double>(origin.z());
double zbottom = static_cast<double>(origin.z()) - thickness;
......
......@@ -23,7 +23,7 @@
class LayerItem;
class ParticleItem;
class SessionItem;
class SceneGeometry;
struct SceneGeometry;
class IFormFactor;
//! Collection of utility functions to build 3D objects from session items.
......
......@@ -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");
......@@ -31,33 +27,32 @@ RealSpacePanel::RealSpacePanel(SampleModel* sampleModel, QItemSelectionModel* se
const auto createAction = [&](const QString& text, const QString& tooltip) -> QAction* {
auto* action = new QAction(text, this);
action->setToolTip("Save 3D real space view as .png file");
action->setToolTip(tooltip);
toolbar->addAction(action);
toolbar->addSeparator();
return action;
};
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();
}
......@@ -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
......@@ -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);
......
......@@ -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;
};
......
......@@ -48,6 +48,9 @@ void WidgetMoverButton::mousePressEvent(QMouseEvent* event)
void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*)
{
qDeleteAll(m_animations.values());
m_animations.clear();
m_dragScrollTimer.stop();
m_started = false;
if (m_layoutToDeactivate != nullptr) {
......@@ -107,14 +110,22 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
QWidget* w = layoutItem->widget();
if (w == nullptr) {
layoutItem->setGeometry(r);
} else {
QPropertyAnimation* animation = new QPropertyAnimation(w, "geometry");
} else if (!m_animations.contains(w)) {
auto animation = new QPropertyAnimation(w, "geometry");
animation->setDuration(100);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setStartValue(w->geometry());
animation->setEndValue(r);
animation->start();
m_animations[w] = animation;
} else {
auto animation = m_animations[w];
if (animation->endValue() != r) {
animation->stop();
animation->setStartValue(w->geometry());
animation->setEndValue(r);
animation->start();
}
}
}
......
......@@ -15,10 +15,12 @@
#ifndef BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
#define BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
#include <QMap>
#include <QTimer>
#include <QToolButton>
class QScrollArea;
class QPropertyAnimation;
//! Button to move a widget vertically in a layout.
//!
......@@ -65,6 +67,7 @@ private:
QTimer m_dragScrollTimer;
QScrollArea* m_scrollArea;
QPoint m_hotSpot; //!< The mouse-down coordinates in the widget to move
QMap<QWidget*, QPropertyAnimation*> m_animations;
};
......
......@@ -6,8 +6,8 @@
#include "GUI/View/Realspace/Particle3DContainer.h"
#include "GUI/View/Realspace/RealSpaceBuilder.h"
#include "GUI/View/Realspace/RealSpaceBuilderUtils.h"
#include "GUI/View/Realspace/RealSpaceModel.h"
#include "GUI/View/Realspace/TransformTo3D.h"
#include "GUI/ba3d/model/model.h"
#include "Sample/Particle/Particle.h"
#include "Tests/GTestWrapper/google_test.h"
#include <QObject>
......@@ -17,7 +17,7 @@ class TestRealSpaceBuilderUtils : public ::testing::Test {
TEST_F(TestRealSpaceBuilderUtils, test_RealSpaceModelandParticle)
{
RealSpaceModel realSpaceModel;
GUI::RealSpace::Model realSpaceModel;
auto cylinder3D = std::make_unique<GUI::RealSpace::Particles::Cylinder>(5, 10);
QVector3D lattice_position1(0, 0, 0);
......@@ -72,11 +72,11 @@ TEST_F(TestRealSpaceBuilderUtils, test_Particle3DContainer)
EXPECT_EQ(p1.particleType(), "Particle");
EXPECT_FALSE(p1.particle3DBlend(0u));
RealSpaceModel realSpaceModel;
GUI::RealSpace::Model realSpaceModel;
// Test copy constructor
// If copy constructor (DEEP copy) is not implemented then p2/p3 is basically
// the same as p1 and cannot be added to the RealSpaceModel once p1 is added
// the same as p1 and cannot be added to the GUI::RealSpace::Model once p1 is added
Particle3DContainer p2(p1);
EXPECT_EQ(p2.containerSize(), 1u);
......@@ -93,7 +93,7 @@ TEST_F(TestRealSpaceBuilderUtils, test_Particle3DContainer)
// Test copy assignment operator
// If assignment operator (DEEP) is not implemented then p4 is basically
// the same as p1 and cannot be added to the RealSpaceModel once p1 is added
// the same as p1 and cannot be added to the GUI::RealSpace::Model once p1 is added
Particle3DContainer p4;
p4 = p1;
......@@ -102,7 +102,7 @@ TEST_F(TestRealSpaceBuilderUtils, test_Particle3DContainer)
EXPECT_EQ(p4.particleType(), "Particle");
EXPECT_FALSE(p4.particle3DBlend(0u));
// Add particle to RealSpaceModel by first creating a unique instance of it and then
// Add particle to GUI::RealSpace::Model by first creating a unique instance of it and then
// releasing (transfer ownership) to the model which deletes the new particle instance later on
auto p1_unique = p1.createParticle(0);
auto p2_unique = p2.createParticle(0);
......