BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
RealSpaceCanvas.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/RealSpaceWidgets/RealSpaceCanvas.cpp
6 //! @brief Implements class RealSpaceScene
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
25 #include <QApplication>
26 #include <QFileDialog>
27 #include <QMessageBox>
28 #include <QVBoxLayout>
29 
31  : QWidget(parent)
32  , m_sampleModel(nullptr)
33  , m_view(new RealSpaceView)
34  , m_selectionModel(nullptr)
35  , m_view_locked(false)
36  , m_sceneGeometry(new SceneGeometry)
37  , m_warningSign(new WarningSign(this))
38 {
39  auto layout = new QVBoxLayout;
40  layout->setMargin(0);
41  layout->setSpacing(0);
42  layout->addWidget(m_view);
43  setLayout(layout);
44 }
45 
47 
48 void RealSpaceCanvas::setModel(SampleModel* sampleModel, QItemSelectionModel* selectionModel)
49 {
50  if (sampleModel != m_sampleModel) {
51 
52  if (m_sampleModel)
54 
55  m_sampleModel = sampleModel;
56 
57  if (m_sampleModel)
59  }
60 
61  if (selectionModel != m_selectionModel) {
62  if (m_selectionModel)
63  disconnect(m_selectionModel, &QItemSelectionModel::selectionChanged, this,
65 
66  m_selectionModel = selectionModel;
67 
68  if (m_selectionModel)
69  connect(m_selectionModel, &QItemSelectionModel::selectionChanged, this,
71  }
72 
74 }
75 
76 void RealSpaceCanvas::onSelectionChanged(const QItemSelection&, const QItemSelection&)
77 {
79 }
80 
82 {
83  if (!m_selectionModel)
84  return;
85 
86  if (!m_view_locked) {
87  QModelIndexList indices = m_selectionModel->selection().indexes();
88 
89  if (!indices.empty())
91  else
92  m_currentSelection = {};
93  // if no object is selected then display nothing on canvas
94 
95  updateScene();
96  }
97 }
98 
100 {
101  defaultView();
102 }
103 
105 {
106  sideView();
107 }
108 
110 {
111  topView();
112 }
113 
114 void RealSpaceCanvas::onLockViewAction(bool view_locked)
115 {
116  if (m_view_locked != view_locked) {
117  m_view_locked = view_locked;
119  }
120 }
121 
122 void RealSpaceCanvas::onChangeLayerSizeAction(double layerSizeChangeScale)
123 {
124  // when no object is selected --> take no action
125  if (m_currentSelection == QModelIndex())
126  return;
127 
128  m_sceneGeometry->set_layer_size(m_sceneGeometry->layer_size() * layerSizeChangeScale);
129  updateScene();
130 }
131 
133 {
134  QPixmap pixmap(this->size());
135  render(&pixmap, QPoint(), childrenRegion());
136  savePicture(pixmap);
137 }
138 
139 void RealSpaceCanvas::onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int)
140 {
141  // clear scene if current selection will be removed
142  if (m_currentSelection == m_sampleModel->index(first, 0, parent))
143  resetScene();
144 }
145 
146 void RealSpaceCanvas::savePicture(const QPixmap& pixmap)
147 {
148  QString dirname = AppSvc::projectManager()->userExportDir();
149  QString defaultExtension = ".png";
150  QString selectedFilter("*" + defaultExtension);
151  QString defaultName = dirname + "/untitled";
152  QString fileName = QFileDialog::getSaveFileName(nullptr, "Save 3D real space view", defaultName,
153  selectedFilter);
154  QString nameToSave =
155  fileName.endsWith(defaultExtension) ? fileName : fileName + defaultExtension;
156 
157  if (!nameToSave.isEmpty()) {
158  try {
159  pixmap.save(nameToSave);
160  } catch (const std::exception& ex) {
161  QString message = "Attempt to save file with the name '";
162  message.append(nameToSave);
163  message.append("' has failed with following error message\n\n");
164  message.append(QString::fromStdString(ex.what()));
165  QMessageBox::warning(nullptr, "Houston, we have a problem.", message);
166  }
167  }
168 }
169 
170 void RealSpaceCanvas::onDataChanged(const QModelIndex& index)
171 {
172  auto item = m_sampleModel->itemForIndex(index);
173  if (!item)
174  return;
175 
177  updateScene();
178 }
179 
181 {
182  QApplication::setOverrideCursor(Qt::WaitCursor);
183 
184  m_realSpaceModel.reset(new RealSpaceModel);
186  if (!item)
187  return;
188 
189  RealSpaceBuilder builder3D;
190 
191  try {
192  m_warningSign->clear();
193  // if the view is locked, keep the current orientation of the camera
194  if (m_view_locked)
195  builder3D.populate(m_realSpaceModel.get(), *item, *m_sceneGeometry,
196  m_view->getCamera().getPos());
197  // otherwise use default orientation of camera
198  else {
199  builder3D.populate(m_realSpaceModel.get(), *item, *m_sceneGeometry);
200  defaultView(); // Enforces default view and also sets the zoomLevel to default i.e. 0
201  }
202  } catch (const std::exception& ex) {
203  m_warningSign->setWarningMessage(ex.what());
204  } catch (...) {
205  // ignore other exceptions thrown
206  }
208 
209  QApplication::restoreOverrideCursor();
210 }
211 
213 {
214  m_realSpaceModel.reset();
215  m_view->setModel(nullptr);
216  m_currentSelection = {};
217 }
218 
220 {
221  m_view->defaultView();
222 }
223 
225 {
226  m_view->sideView();
227 }
228 
230 {
231  m_view->topView();
232 }
233 
234 void RealSpaceCanvas::setConnected(SampleModel* model, bool makeConnected)
235 {
236  if (!model)
237  return;
238 
239  if (makeConnected) {
240  connect(model, &SampleModel::rowsInserted, this, &RealSpaceCanvas::updateScene,
241  Qt::UniqueConnection);
242  connect(model, &SampleModel::rowsRemoved, this, &RealSpaceCanvas::updateScene,
243  Qt::UniqueConnection);
244  connect(model, &SampleModel::rowsAboutToBeRemoved, this,
245  &RealSpaceCanvas::onRowsAboutToBeRemoved, Qt::UniqueConnection);
246  connect(model, &SampleModel::dataChanged, this, &RealSpaceCanvas::onDataChanged,
247  Qt::UniqueConnection);
248  connect(model, &SampleModel::modelReset, this, &RealSpaceCanvas::resetScene,
249  Qt::UniqueConnection);
250  connect(
251  model, &SampleModel::modelAboutToBeReset, this, [&]() { m_currentSelection = {}; },
252  Qt::UniqueConnection);
253 
254  } else {
255  disconnect(model, &SampleModel::rowsInserted, this, &RealSpaceCanvas::updateScene);
256  disconnect(model, &SampleModel::rowsRemoved, this, &RealSpaceCanvas::updateScene);
257  connect(model, &SampleModel::rowsAboutToBeMoved, this,
259  disconnect(model, &SampleModel::dataChanged, this, &RealSpaceCanvas::onDataChanged);
260  disconnect(model, &SampleModel::modelReset, this, &RealSpaceCanvas::resetScene);
261  }
262 }
Defines class AppSvc.
Defines class FilterPropertyProxy.
Defines class ProjectManager.
Defines class RealSpaceBuilder.
Defines class RealSpaceCanvas.
Defines RealSpaceModel namespace.
Defines class RealSpaceView.
Defines class SampleModel.
Defines namespace SessionItemUtils.
Defines class WarningSign.
static ProjectManager * projectManager()
Definition: AppSvc.cpp:18
static QModelIndex toSourceIndex(QModelIndex index)
QString userExportDir() const
Returns directory name suitable for saving plots.
void populate(RealSpaceModel *model, const SessionItem &item, const SceneGeometry &sceneGeometry, const RealSpace::Camera::Position &cameraPosition=RealSpace::Camera::Position(RealSpace::Vector3D(0, -200, 120), RealSpace::Vector3D(0, 0, 0), RealSpace::Vector3D::_z))
QItemSelectionModel * m_selectionModel
void onSelectionChanged(const QItemSelection &, const QItemSelection &)
std::unique_ptr< RealSpaceModel > m_realSpaceModel
QModelIndex m_currentSelection
void setModel(SampleModel *sampleModel=nullptr, QItemSelectionModel *selectionModel=nullptr)
void onLockViewAction(bool view_locked)
WarningSign * m_warningSign
void onDataChanged(const QModelIndex &index)
std::unique_ptr< SceneGeometry > m_sceneGeometry
void onChangeLayerSizeAction(double layer_size_scale)
RealSpaceView * m_view
RealSpaceCanvas(QWidget *parent=nullptr)
void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
SampleModel * m_sampleModel
void savePicture(const QPixmap &pixmap)
void setConnected(SampleModel *model, bool makeConnected)
Contains 3D view.
Definition: RealSpaceView.h:29
RealSpace::Camera & getCamera()
void setModel(RealSpaceModel *model)
const Position & getPos() const
Definition: camera.h:51
Main model to hold sample items.
Definition: SampleModel.h:24
SessionItem * itemForIndex(const QModelIndex &index) const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
The WarningSign controls appearance of WarningSignWidget on top of parent widget.
Definition: WarningSign.h:25
void clear()
Clears warning message;.
Definition: WarningSign.cpp:40
void setWarningMessage(const QString &warningMessage)
Shows warning sign on the screen.
Definition: WarningSign.cpp:58
void warning(QWidget *parent, const QString &title, const QString &text, const QString &detailedText)
Definition: GUIHelpers.cpp:74
bool IsPositionRelated(const SessionItem &item)
Returns true if current item is related to the position on sample editor canvas.