BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
MaskGraphicsScene.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Mask/MaskGraphicsScene.cpp
6 //! @brief Implements class MaskGraphicsScene
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 
21 #include "GUI/Util/Error.h"
26 #include <QGraphicsItem>
27 #include <QGraphicsSceneMoveEvent>
28 #include <QItemSelection>
29 #include <QLineF>
30 #include <QPainter>
31 
32 #include <boost/polymorphic_cast.hpp>
33 
34 using boost::polymorphic_downcast;
35 
36 namespace {
37 
38 const QRectF default_scene_rect(0, 0, 800, 600);
39 const qreal min_distance_to_create_rect = 10;
40 
41 } // namespace
42 
44  : QGraphicsScene(parent)
45  , m_maskModel(nullptr)
46  , m_selectionModel(nullptr)
47  , m_proxy(nullptr)
48  , m_block_selection(false)
49  , m_intensityItem(nullptr)
50  , m_currentItem(nullptr)
51 {
52  setSceneRect(default_scene_rect);
53  connect(this, &MaskGraphicsScene::selectionChanged, this,
55 }
56 
58 {
59  // Fix within #1792
60  if (m_proxy)
61  m_proxy->setSceneAdaptor(nullptr);
62 }
63 
64 void MaskGraphicsScene::setMaskContext(SessionModel* model, const QModelIndex& maskContainerIndex,
65  IntensityDataItem* intensityItem)
66 {
67  m_intensityItem = intensityItem;
68 
69  if (model != m_maskModel || m_maskContainerIndex != maskContainerIndex) {
70  if (m_maskModel) {
71  disconnect(m_maskModel, &SessionModel::modelAboutToBeReset, this,
73  disconnect(m_maskModel, &SessionModel::rowsInserted, this,
75  disconnect(m_maskModel, &SessionModel::rowsAboutToBeRemoved, this,
77  disconnect(m_maskModel, &SessionModel::rowsRemoved, this,
79  disconnect(m_maskModel, &SessionModel::modelReset, this,
81  }
82 
83  m_maskModel = model;
84 
85  QString containerType = m_maskModel->itemForIndex(maskContainerIndex)->modelType();
86  if (containerType != MaskContainerItem::M_TYPE
87  && containerType != ProjectionContainerItem::M_TYPE)
88  throw Error("MaskGraphicsScene::setMaskContext() -> Error. Not a container");
89 
90  m_maskContainerIndex = maskContainerIndex;
91 
92  if (m_maskModel) {
93  connect(m_maskModel, &SessionModel::modelAboutToBeReset, this,
95  connect(m_maskModel, &SessionModel::rowsInserted, this,
97  connect(m_maskModel, &SessionModel::rowsAboutToBeRemoved, this,
99  connect(m_maskModel, &SessionModel::rowsRemoved, this,
101  connect(m_maskModel, &SessionModel::modelReset, this, &MaskGraphicsScene::updateScene);
102  }
103 
104  resetScene();
105  updateScene();
106  }
107 }
108 
110 {
111  m_intensityItem = nullptr;
112  if (m_maskModel) {
113  disconnect(m_maskModel, &SessionModel::modelAboutToBeReset, this,
115  disconnect(m_maskModel, &SessionModel::rowsInserted, this,
117  disconnect(m_maskModel, &SessionModel::rowsAboutToBeRemoved, this,
119  disconnect(m_maskModel, &SessionModel::rowsRemoved, this,
121  disconnect(m_maskModel, &SessionModel::modelReset, this, &MaskGraphicsScene::updateScene);
122  }
123  m_maskModel = nullptr;
125  resetScene();
126 }
127 
128 void MaskGraphicsScene::setSelectionModel(QItemSelectionModel* model)
129 {
130  ASSERT(model);
131  m_selectionModel = model;
132  connect(m_selectionModel, &QItemSelectionModel::selectionChanged, this,
133  &MaskGraphicsScene::onSessionSelectionChanged, Qt::UniqueConnection);
134 }
135 
137 {
138  ASSERT(m_proxy);
139  return m_proxy->colorMap();
140 }
141 
142 void MaskGraphicsScene::onActivityModeChanged(MaskEditorFlags::Activity value)
143 {
144  if (!m_proxy)
145  return;
146 
149 
150  m_context.setActivityType(value);
152 
153  updateCursors();
154 }
155 
156 void MaskGraphicsScene::onMaskValueChanged(MaskEditorFlags::MaskValue value)
157 {
158  m_context.setMaskValue(value);
159 }
160 
161 void MaskGraphicsScene::onRowsInserted(const QModelIndex&, int, int)
162 {
163  updateScene();
164 }
165 
166 void MaskGraphicsScene::onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last)
167 {
168  m_block_selection = true;
169  for (int irow = first; irow <= last; ++irow) {
170  QModelIndex itemIndex = m_maskModel->index(irow, 0, parent);
171  deleteViews(itemIndex); // deleting all child items
172  }
173  m_block_selection = false;
174 }
175 
176 void MaskGraphicsScene::onRowsRemoved(const QModelIndex&, int, int)
177 {
178  updateScene();
179 }
180 
182 {
183  if (isDrawingInProgress()) {
184  ASSERT(m_currentItem);
185  QModelIndex index = m_maskModel->indexOfItem(m_currentItem);
186  m_maskModel->removeRows(index.row(), 1, index.parent());
187  setDrawingInProgress(false);
188  }
189 }
190 
192 {
193  ASSERT(m_selectionModel);
194  m_block_selection = true;
195  m_selectionModel->clearSelection();
196  clearSelection();
197 
198  clear();
199  m_ItemToView.clear();
200  m_proxy = nullptr;
201  m_adaptor.reset(new ColorMapSceneAdaptor);
202 
203  m_block_selection = false;
204 }
205 
206 //! Main method to update scene on various changes in the model.
207 
209 {
210  if (!m_maskModel)
211  return;
212 
216  setZValues();
217 }
218 
219 //! Propagates selection from model to scene.
220 
221 void MaskGraphicsScene::onSessionSelectionChanged(const QItemSelection&, const QItemSelection&)
222 {
223  if (m_block_selection)
224  return;
225 
226  m_block_selection = true;
227 
228  for (auto it = m_ItemToView.begin(); it != m_ItemToView.end(); ++it) {
229  QModelIndex index = m_maskModel->indexOfItem(it.key());
230  if (index.isValid())
231  it.value()->setSelected(m_selectionModel->isSelected(index));
232  }
233  m_block_selection = false;
234 }
235 
236 //! Propagates selection from scene to model.
237 
239 {
240  if (m_block_selection)
241  return;
242 
243  m_block_selection = true;
244 
245  m_selectionModel->clearSelection();
246 
247  for (QGraphicsItem* graphicsItem : selectedItems()) {
248  if (auto* view = dynamic_cast<IShape2DView*>(graphicsItem)) {
249  QModelIndex itemIndex = m_maskModel->indexOfItem(view->parameterizedItem());
250  ASSERT(itemIndex.isValid());
251  if (!m_selectionModel->isSelected(itemIndex))
252  m_selectionModel->select(itemIndex, QItemSelectionModel::Select);
253  }
254  }
255  m_block_selection = false;
256 }
257 
258 void MaskGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
259 {
260  if (event->buttons() & Qt::RightButton) {
261  if (isDrawingInProgress())
263  else
265  return;
266  }
267  if (isValidForPolygonDrawing(event)) {
268  processPolygonItem(event);
269  return;
270  }
271  if (isValidForLineDrawing(event)) {
272  processLineItem(event);
273  return;
274  }
275  if (isValidForMaskAllDrawing(event)) {
276  processMaskAllItem(event);
277  return;
278  }
279  if (isValidForRectangleShapeDrawing(event)) {
281  return;
282  }
283  QGraphicsScene::mousePressEvent(event);
284 }
285 
286 void MaskGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
287 {
290  return;
291  }
292  QGraphicsScene::mouseMoveEvent(event);
293 
295  m_currentMousePosition = event->scenePos();
296  invalidate();
297  }
298 }
299 
300 //! Finalizes item drawing or pass events to other items.
301 
302 void MaskGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
303 {
304  if (isDrawingInProgress()) {
306  clearSelection();
307  if (m_currentItem) {
308  // drawing ended up with item drawn, let's make it selected
310  view->setSelected(true);
311  } else {
312  // drawing ended without item to be draw (too short mouse move)
313  // making item beneath of mouse release position to be selected
315  }
316  setDrawingInProgress(false);
317  }
318  } else {
319  QGraphicsScene::mouseReleaseEvent(event);
320  }
321 }
322 
323 //! Draws dashed line to the current mouse position in the case of ungoing
324 //! line or polygon drawing.
325 
326 void MaskGraphicsScene::drawForeground(QPainter* painter, const QRectF&)
327 {
328  // if(!isDrawingInProgress())
329  // return;
330 
331  if (m_currentMousePosition == QPointF())
332  return;
333 
334  if (PolygonView* polygon = currentPolygon()) {
335  painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
336  painter->drawLine(QLineF(polygon->lastAddedPoint(), m_currentMousePosition));
337  } else {
338  if (m_context.isLineMode()) {
339  const QRectF& plot_scene_rectangle = m_adaptor->viewportRectangle();
340  if (!plot_scene_rectangle.contains(m_currentMousePosition))
341  return;
342 
343  painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
345  QPointF p1(m_currentMousePosition.x(), plot_scene_rectangle.bottom());
346  QPointF p2(m_currentMousePosition.x(), plot_scene_rectangle.top());
347  painter->drawLine(QLineF(p1, p2));
348  }
350  QPointF p1(plot_scene_rectangle.left(), m_currentMousePosition.y());
351  QPointF p2(plot_scene_rectangle.right(), m_currentMousePosition.y());
352  painter->drawLine(QLineF(p1, p2));
353  }
354  }
355  }
356 }
357 
358 //! Creates item context menu if there is IMaskView beneath the mouse right click.
359 
360 void MaskGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
361 {
362  if (isDrawingInProgress())
363  return;
364 
365  if (dynamic_cast<IShape2DView*>(itemAt(event->scenePos(), QTransform())))
366  emit itemContextMenuRequest(event->screenPos());
367 }
368 
369 //! Updates proxy widget for intensity data item.
370 
372 {
373  ASSERT(m_intensityItem);
374  if (!m_proxy) {
378  addItem(m_proxy);
379  }
380 }
381 
382 //! Recutsively runs through the model and creates corresponding views.
383 
384 void MaskGraphicsScene::updateViews(const QModelIndex& parentIndex, IShape2DView* parentView)
385 {
386  ASSERT(m_maskModel);
387  IShape2DView* childView(nullptr);
388  for (int i_row = 0; i_row < m_maskModel->rowCount(parentIndex); ++i_row) {
389  QModelIndex itemIndex = m_maskModel->index(i_row, 0, parentIndex);
390  if (SessionItem* item = m_maskModel->itemForIndex(itemIndex)) {
391  if (item->hasModelType<GroupItem>() || item->hasModelType<PropertyItem>())
392  continue;
393 
394  childView = addViewForItem(item);
395  if (childView) {
396  if (parentView)
397  parentView->addView(childView, i_row);
398  }
399  }
400  updateViews(itemIndex, childView);
401  }
402 }
403 
404 //! Creates a view for given item.
405 
407 {
408  ASSERT(item);
409  IShape2DView* view = m_ItemToView[item];
410  if (!view) {
411  view = MaskViewFactory::createMaskView(item, m_adaptor.data());
412  if (view) {
413  m_ItemToView[item] = view;
414  addItem(view);
415  return view;
416  }
417  }
418  return view;
419 }
420 
421 //! Recursive delete of all views corresponding to given index.
422 
423 void MaskGraphicsScene::deleteViews(const QModelIndex& parentIndex)
424 {
425  for (int i_row = 0; i_row < m_maskModel->rowCount(parentIndex); ++i_row) {
426  QModelIndex itemIndex = m_maskModel->index(i_row, 0, parentIndex);
427 
428  if (SessionItem* item = m_maskModel->itemForIndex(itemIndex))
430 
431  deleteViews(itemIndex);
432  }
433  removeItemViewFromScene(m_maskModel->itemForIndex(parentIndex)); // deleting parent item
434 }
435 
436 //! Removes single view from scene.
437 
439 {
440  for (auto it = m_ItemToView.begin(); it != m_ItemToView.end(); ++it) {
441  if (it.key() == item) {
442  IShape2DView* view = it.value();
443  view->setSelected(false);
444  m_ItemToView.erase(it);
445  delete view;
446  break;
447  }
448  }
449 }
450 
451 //! Returns true if left mouse bottom click was inside ColorMap viewport rectangle.
452 
453 bool MaskGraphicsScene::isValidMouseClick(QGraphicsSceneMouseEvent* event)
454 {
455  if (!m_adaptor)
456  return false;
457  if (!(event->buttons() & Qt::LeftButton))
458  return false;
459  if (!m_adaptor->viewportRectangle().contains(event->scenePos()))
460  return false;
461  return true;
462 }
463 
464 //! Returns true if mouse click is valid for rectangular/elliptic/ROI shapes.
465 
466 bool MaskGraphicsScene::isValidForRectangleShapeDrawing(QGraphicsSceneMouseEvent* event)
467 {
468  if (isDrawingInProgress())
469  return false;
470  if (!isValidMouseClick(event))
471  return false;
473  return false;
475  return false;
476  if (m_context.isROIMode()) {
477  // only one ROI is allowed
478  for (SessionItem* item : m_ItemToView.keys())
479  if (item->modelType() == RegionOfInterestItem::M_TYPE)
480  return false;
481  }
482  return true;
483 }
484 
485 //! Returns true if mouse click is in context suitable for polygon drawing.
486 
487 bool MaskGraphicsScene::isValidForPolygonDrawing(QGraphicsSceneMouseEvent* event)
488 {
489  if (!isValidMouseClick(event))
490  return false;
491  if (!m_context.isPolygonMode())
492  return false;
493  if (!isDrawingInProgress()) {
495  return false;
496  }
497  return true;
498 }
499 
500 //! Returns true if mouse click is in context suitable for line drawing.
501 
502 bool MaskGraphicsScene::isValidForLineDrawing(QGraphicsSceneMouseEvent* event)
503 {
504  if (!isValidMouseClick(event))
505  return false;
506  if (isDrawingInProgress())
507  return false;
508  if (!m_context.isLineMode())
509  return false;
510  if (QGraphicsItem* graphicsItem = itemAt(event->scenePos(), QTransform())) {
511  if (graphicsItem->type() == MaskEditorHelper::VERTICALLINE
512  || graphicsItem->type() == MaskEditorHelper::HORIZONTALLINE)
513  return false;
514  }
515  return true;
516 }
517 
518 //! Returns true if MaskAllItem can be drawn. Only one item of such type is allowed.
519 
520 bool MaskGraphicsScene::isValidForMaskAllDrawing(QGraphicsSceneMouseEvent* event)
521 {
522  if (!isValidMouseClick(event))
523  return false;
524  if (isDrawingInProgress())
525  return false;
526  if (!m_context.isMaskAllMode())
527  return false;
528  for (SessionItem* item : m_ItemToView.keys())
529  if (item->modelType() == MaskAllItem::M_TYPE)
530  return false;
531  return true;
532 }
533 
534 //! Return true if area beneath the mouse contains views of given type.
535 
536 bool MaskGraphicsScene::isAreaContains(QGraphicsSceneMouseEvent* event,
538 {
539  for (QGraphicsItem* graphicsItem : this->items(event->scenePos()))
540  if (graphicsItem->type() == viewType)
541  return true;
542  return false;
543 }
544 
546 {
548 }
549 
551 {
553  if (!value)
554  m_currentItem = nullptr;
555 }
556 
557 //! Sets the state of all views in pan&zoom mode.
558 //! In pan&zoom mode, the selection is removed, all items can't receive mouse clicks, and all
559 //! events are propagated down to ColorMap plot.
560 
562 {
563  if (value)
564  m_selectionModel->clearSelection();
565 
566  Qt::MouseButtons acceptedButton = (value ? Qt::NoButton : Qt::LeftButton);
567  for (IShape2DView* view : m_ItemToView.values())
568  view->setAcceptedMouseButtons(acceptedButton);
569 
570  m_proxy->setInZoomMode(value);
571 }
572 
573 //! Change cursor to stress that hovered item is movable (when not in PanZoom mode)
574 
576 {
577  for (auto it = m_ItemToView.begin(); it != m_ItemToView.end(); ++it) {
578  if (it.key()->modelType() == VerticalLineItem::M_TYPE)
579  it.value()->setCursor(m_context.isInZoomMode() ? Qt::ArrowCursor : Qt::SizeHorCursor);
580  else if (it.key()->modelType() == HorizontalLineItem::M_TYPE)
581  it.value()->setCursor(m_context.isInZoomMode() ? Qt::ArrowCursor : Qt::SizeVerCursor);
582  }
583 }
584 
585 void MaskGraphicsScene::makeViewAtMousePosSelected(QGraphicsSceneMouseEvent* event)
586 {
587  if (QGraphicsItem* graphicsItem = itemAt(event->scenePos(), QTransform()))
588  graphicsItem->setSelected(true);
589 }
590 
591 //! Processes RectangleItem and EllipseItem drawing
592 //! If the mouse move distance with left button down is larger than certain threshold,
593 //! new item will be created. Further, this function will update size and position
594 //! of current rectangle if mouse keep moving.
595 
596 void MaskGraphicsScene::processRectangleShapeItem(QGraphicsSceneMouseEvent* event)
597 {
598  if (!isDrawingInProgress())
599  setDrawingInProgress(true);
600 
601  QPointF click_pos = event->buttonDownScenePos(Qt::LeftButton);
602  QPointF mouse_pos = event->scenePos();
603  QLineF line(mouse_pos, click_pos);
604 
605  if (!m_currentItem && line.length() > min_distance_to_create_rect) {
608  if (!m_context.isROIMode())
609  dynamic_cast<MaskItem*>(m_currentItem)->setMaskValue(m_context.getMaskValue());
611  }
612  if (!m_currentItem)
613  return;
614 
615  qreal xmin = std::min(click_pos.x(), mouse_pos.x());
616  qreal xmax = std::max(click_pos.x(), mouse_pos.x());
617  qreal ymin = std::min(click_pos.y(), mouse_pos.y());
618  qreal ymax = std::max(click_pos.y(), mouse_pos.y());
619 
622  auto* rectItem = polymorphic_downcast<RectangleItem*>(m_currentItem);
623  rectItem->setXLow(m_adaptor->fromSceneX(xmin));
624  rectItem->setYLow(m_adaptor->fromSceneY(ymax));
625  rectItem->setXUp(m_adaptor->fromSceneX(xmax));
626  rectItem->setYUp(m_adaptor->fromSceneY(ymin));
627  } else if (m_currentItem->modelType() == EllipseItem::M_TYPE) {
628  auto* ellItem = polymorphic_downcast<EllipseItem*>(m_currentItem);
629  ellItem->setXCenter(m_adaptor->fromSceneX(xmin + (xmax - xmin) / 2.));
630  ellItem->setYCenter(m_adaptor->fromSceneY(ymin + (ymax - ymin) / 2.));
631  ellItem->setXRadius((m_adaptor->fromSceneX(xmax) - m_adaptor->fromSceneX(xmin)) / 2.);
632  ellItem->setYRadius((m_adaptor->fromSceneY(ymin) - m_adaptor->fromSceneY(ymax)) / 2.);
633  }
634 }
635 
636 void MaskGraphicsScene::processPolygonItem(QGraphicsSceneMouseEvent* event)
637 {
638  ASSERT(m_context.isPolygonMode());
639 
640  if (!m_currentItem) {
641  setDrawingInProgress(true);
643  new_poly->setMaskValue(m_context.getMaskValue());
644  m_currentItem = new_poly;
645  m_selectionModel->clearSelection();
647  QItemSelectionModel::Select);
649  }
651 
652  if (PolygonView* polygon = currentPolygon()) {
653  if (polygon->closePolygonIfNecessary()) {
654  setDrawingInProgress(false);
656  return;
657  }
658  }
660  QPointF click_pos = event->buttonDownScenePos(Qt::LeftButton);
661 
662  point->setPosX(m_adaptor->fromSceneX(click_pos.x()));
663  point->setPosY(m_adaptor->fromSceneY(click_pos.y()));
664 }
665 
666 void MaskGraphicsScene::processLineItem(QGraphicsSceneMouseEvent* event)
667 {
668  setDrawingInProgress(true);
669  QPointF click_pos = event->buttonDownScenePos(Qt::LeftButton);
670 
672  processVerticalLineItem(click_pos);
673 
675  processHorizontalLineItem(click_pos);
676 
677  m_selectionModel->clearSelection();
678  m_selectionModel->select(m_maskModel->indexOfItem(m_currentItem), QItemSelectionModel::Select);
680  dynamic_cast<MaskItem*>(m_currentItem)->setMaskValue(m_context.getMaskValue());
681 
682  setDrawingInProgress(false);
683 }
684 
686 {
688  m_currentItem = item;
689  item->setPosX(m_adaptor->fromSceneX(pos.x()));
690 }
691 
693 {
695  m_currentItem = item;
696  item->setPosY(m_adaptor->fromSceneY(pos.y()));
697 }
698 
699 void MaskGraphicsScene::processMaskAllItem(QGraphicsSceneMouseEvent* event)
700 {
701  Q_UNUSED(event);
702  setDrawingInProgress(true);
704  m_selectionModel->clearSelection();
705  setDrawingInProgress(false);
706 }
707 
708 //! Update Z-values of all IMaskView to reflect stacking order in SessionModel.
709 //! Item with irow=0 is the top most on graphics scene (and so is having largest z-values).
710 
712 {
713  ASSERT(m_maskContainerIndex.isValid());
714  for (int i = 0; i < m_maskModel->rowCount(m_maskContainerIndex); i++) {
715  QModelIndex itemIndex = m_maskModel->index(i, 0, m_maskContainerIndex);
716  SessionItem* item = m_maskModel->itemForIndex(itemIndex);
717  if (IShape2DView* view = m_ItemToView[item])
718  view->setZValue(m_maskModel->rowCount(m_maskContainerIndex) - itemIndex.row() + 1);
719  }
720 }
721 
722 //! Returns polygon which is currently under the drawing.
723 
725 {
726  PolygonView* result(nullptr);
728  if (m_currentItem)
729  result = dynamic_cast<PolygonView*>(m_ItemToView[m_currentItem]);
730  }
731  return result;
732 }
733 
734 //! Sets item name depending on alreay existent items.
735 //! If there is already "Rectangle1", the new name will be "Rectangle2"
736 
738 {
739  if (itemToChange->modelType() == RegionOfInterestItem::M_TYPE)
740  return;
741 
742  int glob_index(0);
743  for (int i_row = 0; i_row < m_maskModel->rowCount(m_maskContainerIndex); ++i_row) {
744  QModelIndex itemIndex = m_maskModel->index(i_row, 0, m_maskContainerIndex);
745  if (SessionItem* currentItem = m_maskModel->itemForIndex(itemIndex)) {
746  if (currentItem->modelType() == itemToChange->modelType()) {
747  QString itemName = currentItem->itemName();
748  if (itemName.startsWith(itemToChange->itemName())) {
749  int item_index = itemName.remove(0, itemToChange->itemName().size()).toInt();
750  if (item_index > glob_index)
751  glob_index = item_index;
752  }
753  }
754  }
755  }
756  itemToChange->setItemName(itemToChange->itemName() + QString::number(++glob_index));
757 }
Defines class ColorMapSceneAdaptor.
Defines error class.
Defines class GroupItem.
Defines class MaskGraphicsProxy.
Defines class MaskGraphicsScene.
Defines MaskItems classes.
Defines class MaskViewFactory.
Defines PolygonView class.
Defines items related to projections over color map.
Defines class PropertyItem.
Defines class SessionModel.
Performs conversion of MaskItems coordinates between ColorMap and GraphicsScene.
The ColorMap class presents 2D intensity data from IntensityDataItem as color map.
Definition: ColorMap.h:36
static constexpr auto M_TYPE
Definition: MaskItems.h:167
static constexpr auto M_TYPE
Definition: MaskItems.h:147
Main interface class for views representing MaskItems, Projections on graphics scene.
Definition: IShape2DView.h:27
virtual void addView(IShape2DView *childView, int row=0)
static constexpr auto M_TYPE
Definition: MaskItems.h:192
static constexpr auto M_TYPE
Definition: MaskItems.h:204
QString activityToModelType() const
Returns model type corresponding to current activity.
int activityToRow() const
Returns model row corresponding to given activity. All shapes, except ROI, will be added on top of ea...
void setDrawingInProgress(bool value)
void setActivityType(MaskEditorFlags::Activity value)
bool isActivityRequiresDrawingCancel(MaskEditorFlags::Activity proposed_new_activity) const
Returns true, if proposed activity requires the cancel of drawing i.e. there is an ungoing polygon dr...
bool isVerticalLineMode() const
bool isRectangleShapeMode() const
bool isHorizontalLineMode() const
bool isDrawingInProgress() const
void setMaskValue(MaskEditorFlags::MaskValue value)
Graphics proxy to place QWidget inside QGraphicsScene, used by MaskEditorCanvas.
void setIntensityItem(IntensityDataItem *item)
void setInZoomMode(bool value)
Sets widget to zoom mode, when signals (zoom wheel, mouse clicks) are send down to ColorMap plot....
void setSceneAdaptor(ISceneAdaptor *sceneAdaptor)
PolygonView * currentPolygon() const
Returns polygon which is currently under the drawing.
bool isAreaContains(QGraphicsSceneMouseEvent *event, MaskEditorHelper::EViewTypes viewType)
Return true if area beneath the mouse contains views of given type.
bool isValidMouseClick(QGraphicsSceneMouseEvent *event)
Returns true if left mouse bottom click was inside ColorMap viewport rectangle.
void setSelectionModel(QItemSelectionModel *model)
void updateScene()
Main method to update scene on various changes in the model.
void processLineItem(QGraphicsSceneMouseEvent *event)
void processVerticalLineItem(const QPointF &pos)
SessionModel * m_maskModel
void setZValues()
Update Z-values of all IMaskView to reflect stacking order in SessionModel. Item with irow=0 is the t...
void setDrawingInProgress(bool value)
void processPolygonItem(QGraphicsSceneMouseEvent *event)
void processMaskAllItem(QGraphicsSceneMouseEvent *event)
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
void setInPanAndZoomMode(bool value)
Sets the state of all views in pan&zoom mode. In pan&zoom mode, the selection is removed,...
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
Finalizes item drawing or pass events to other items.
QItemSelectionModel * m_selectionModel
void processHorizontalLineItem(const QPointF &pos)
void onMaskValueChanged(MaskEditorFlags::MaskValue value)
IntensityDataItem * m_intensityItem
void processRectangleShapeItem(QGraphicsSceneMouseEvent *event)
Processes RectangleItem and EllipseItem drawing If the mouse move distance with left button down is l...
bool isDrawingInProgress() const
void removeItemViewFromScene(SessionItem *item)
Removes single view from scene.
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
void itemContextMenuRequest(const QPoint &point)
MaskGraphicsProxy * m_proxy
void setMaskContext(SessionModel *model, const QModelIndex &maskContainerIndex, IntensityDataItem *intensityItem)
void onSceneSelectionChanged()
Propagates selection from scene to model.
IShape2DView * addViewForItem(SessionItem *item)
Creates a view for given item.
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
Creates item context menu if there is IMaskView beneath the mouse right click.
void deleteViews(const QModelIndex &parentIndex)
Recursive delete of all views corresponding to given index.
bool isValidForMaskAllDrawing(QGraphicsSceneMouseEvent *event)
Returns true if MaskAllItem can be drawn. Only one item of such type is allowed.
void updateViews(const QModelIndex &parentIndex={}, IShape2DView *parentView=nullptr)
Recutsively runs through the model and creates corresponding views.
bool isValidForRectangleShapeDrawing(QGraphicsSceneMouseEvent *event)
Returns true if mouse click is valid for rectangular/elliptic/ROI shapes.
void onRowsInserted(const QModelIndex &, int, int)
bool isValidForPolygonDrawing(QGraphicsSceneMouseEvent *event)
Returns true if mouse click is in context suitable for polygon drawing.
void setItemName(SessionItem *itemToChange)
Sets item name depending on alreay existent items. If there is already "Rectangle1",...
MaskDrawingContext m_context
QModelIndex m_maskContainerIndex
bool isValidForLineDrawing(QGraphicsSceneMouseEvent *event)
Returns true if mouse click is in context suitable for line drawing.
QMap< SessionItem *, IShape2DView * > m_ItemToView
void onRowsRemoved(const QModelIndex &, int, int)
void drawForeground(QPainter *painter, const QRectF &rect) override
Draws dashed line to the current mouse position in the case of ungoing line or polygon drawing.
void makeViewAtMousePosSelected(QGraphicsSceneMouseEvent *event)
MaskGraphicsScene(QObject *parent=nullptr)
void updateProxyWidget()
Updates proxy widget for intensity data item.
void onSessionSelectionChanged(const QItemSelection &, const QItemSelection &)
Propagates selection from model to scene.
~MaskGraphicsScene() override
void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
void updateCursors()
Change cursor to stress that hovered item is movable (when not in PanZoom mode)
SessionItem * m_currentItem
QSharedPointer< ISceneAdaptor > m_adaptor
void onActivityModeChanged(MaskEditorFlags::Activity value)
A base class for all mask items.
Definition: MaskItems.h:27
void setMaskValue(bool mask_value)
Definition: MaskItems.cpp:85
static IShape2DView * createMaskView(SessionItem *item, ISceneAdaptor *adaptor=nullptr)
static constexpr auto M_TYPE
Definition: MaskItems.h:112
void setPosX(double pos_x)
Definition: MaskItems.cpp:229
This is a View of polygon mask (represented by PolygonItem) on GraphicsScene.
Definition: PolygonView.h:26
static constexpr auto M_TYPE
static constexpr auto M_TYPE
Definition: MaskItems.h:61
static constexpr auto M_TYPE
Definition: MaskItems.h:83
Base class for a GUI data item.
Definition: SessionItem.h:204
QString itemName() const
Get item name, return display name if no name is set.
void setItemName(const QString &name)
Set item name, add property if necessary.
bool hasModelType() const
Definition: SessionItem.h:421
QString modelType() const
Get model type.
Base class for a GUI data collection. A collection is e.g. all real data (RealDataModel)....
Definition: SessionModel.h:42
SessionItem * itemForIndex(const QModelIndex &index) const
T * insertItem(SessionItem *parent=nullptr, int row=-1, QString tag="")
Definition: SessionModel.h:137
QModelIndex index(int row, int column, const QModelIndex &parent) const override
SessionItem * insertNewItem(QString model_type, SessionItem *parent_item=nullptr, int row=-1, QString tag="")
bool removeRows(int row, int count, const QModelIndex &parent) override
int rowCount(const QModelIndex &parent) const override
QModelIndex indexOfItem(SessionItem *item) const
static constexpr auto M_TYPE
Definition: MaskItems.h:131