diff --git a/GUI/Views/MaskWidgets/EllipseView.cpp b/GUI/Views/MaskWidgets/EllipseView.cpp index 897ed4f0ab476d7c76b02d9c3c2abfc4afc904d5..d822d56c1b6cd71a4b071c0104fc93551b02fab3 100644 --- a/GUI/Views/MaskWidgets/EllipseView.cpp +++ b/GUI/Views/MaskWidgets/EllipseView.cpp @@ -46,15 +46,6 @@ void EllipseView::onPropertyChange(const QString& propertyName) } } -void EllipseView::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) -{ - painter->setRenderHints(QPainter::Antialiasing); - bool mask_value = m_item->getItemValue(MaskItem::P_MASK_VALUE).toBool(); - painter->setBrush(MaskEditorHelper::getMaskBrush(mask_value)); - painter->setPen(MaskEditorHelper::getMaskPen(mask_value)); - painter->drawEllipse(m_mask_rect); -} - void EllipseView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (m_activeHandleElement) { @@ -105,6 +96,13 @@ void EllipseView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) } } +QPainterPath EllipseView::shape() const +{ + QPainterPath path; + path.addEllipse(m_mask_rect); + return path; +} + //! updates position of view using item properties void EllipseView::update_position() diff --git a/GUI/Views/MaskWidgets/EllipseView.h b/GUI/Views/MaskWidgets/EllipseView.h index 0493f4e378e8eefe6223a08268e2862959ae53b2..977a108e1105f8f41d338c832bbaa356513941d8 100644 --- a/GUI/Views/MaskWidgets/EllipseView.h +++ b/GUI/Views/MaskWidgets/EllipseView.h @@ -29,13 +29,13 @@ public: EllipseView(); protected slots: - virtual void onChangedX(); - virtual void onChangedY(); - virtual void onPropertyChange(const QString& propertyName); + virtual void onChangedX() override; + virtual void onChangedY() override; + virtual void onPropertyChange(const QString& propertyName) override; protected: - void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*); - void mouseMoveEvent(QGraphicsSceneMouseEvent* event); + virtual QPainterPath shape() const override; + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; private: void update_position(); diff --git a/GUI/Views/MaskWidgets/IShape2DView.cpp b/GUI/Views/MaskWidgets/IShape2DView.cpp index 9770155beba0018610b82547e4eb27fdd070c2e5..936eb0faee8a58be62986ab598c5394fa39f76c1 100644 --- a/GUI/Views/MaskWidgets/IShape2DView.cpp +++ b/GUI/Views/MaskWidgets/IShape2DView.cpp @@ -16,6 +16,7 @@ #include "GUI/Models/MaskItems.h" #include "GUI/Views/MaskWidgets/ISceneAdaptor.h" #include <QAction> +#include <QGraphicsScene> #include <QGraphicsSceneContextMenuEvent> #include <QMenu> #include <QPainter> @@ -78,6 +79,46 @@ void IShape2DView::setSceneAdaptor(const ISceneAdaptor* adaptor) } } +void IShape2DView::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) +{ + const bool isMasked = m_item->getItemValue(MaskItem::P_MASK_VALUE).toBool(); + painter->setBrush(MaskEditorHelper::getMaskBrush(isMasked)); + painter->setPen(MaskEditorHelper::getMaskPen(isMasked)); + painter->setRenderHints(QPainter::Antialiasing); + painter->drawPath(maskedShape()); +} + +QPainterPath IShape2DView::maskedShape() const +{ + static const QSet<MaskEditorHelper::EViewTypes> relevantMaskTypes = { + MaskEditorHelper::RECTANGLE, MaskEditorHelper::POLYGON, MaskEditorHelper::VERTICALLINE, + MaskEditorHelper::HORIZONTALLINE, MaskEditorHelper::ELLIPSE}; + + QPainterPath resultingShape = mapToScene(shape()); + for (auto item : scene()->items()) { + const auto maskItem = dynamic_cast<IShape2DView*>(item); + if (!maskItem + || !relevantMaskTypes.contains((MaskEditorHelper::EViewTypes)maskItem->type())) + continue; + + const bool isMaskingItem = + maskItem->parameterizedItem()->getItemValue(MaskItem::P_MASK_VALUE).toBool(); + const bool isOnTop = maskItem->zValue() > zValue(); + if (isMaskingItem || !isOnTop) + continue; + + const auto maskItemShape = maskItem->mapToScene(maskItem->shape()); + if (!maskItemShape.intersects(resultingShape)) + continue; + + // Item lays on top and is non-masking -> subtract the + // path of the item + resultingShape = resultingShape.subtracted(maskItemShape); + } + + return mapFromScene(resultingShape); +} + double IShape2DView::par(const QString& property_name) const { return m_item->getItemValue(property_name).toReal(); diff --git a/GUI/Views/MaskWidgets/IShape2DView.h b/GUI/Views/MaskWidgets/IShape2DView.h index 7194a752bd92916fe23c84bc6c86f243973ef1de..c22e01eb898df957a077fd3409dee35fd8c7b89d 100644 --- a/GUI/Views/MaskWidgets/IShape2DView.h +++ b/GUI/Views/MaskWidgets/IShape2DView.h @@ -50,6 +50,11 @@ protected slots: virtual void onPropertyChange(const QString&) {} protected: + virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) override; + + //! Returns the shape with all masking already applied. + QPainterPath maskedShape() const; + double par(const QString& property_name) const; qreal toSceneX(const QString& property_name) const; qreal toSceneX(qreal value) const; diff --git a/GUI/Views/MaskWidgets/LineViews.cpp b/GUI/Views/MaskWidgets/LineViews.cpp index 4a13c3c0dadbfa15f5c536e0477144bef58c607d..3e2ed63cae39ded909333344b95b2d9e84c33677 100644 --- a/GUI/Views/MaskWidgets/LineViews.cpp +++ b/GUI/Views/MaskWidgets/LineViews.cpp @@ -32,6 +32,13 @@ VerticalLineView::VerticalLineView() setCursor(Qt::SizeHorCursor); } +QPainterPath VerticalLineView::shape() const +{ + QPainterPath p; + p.addRect(QRectF(-mask_visible_width / 2., 0.0, mask_visible_width, m_bounding_rect.height())); + return p; +} + void VerticalLineView::onChangedX() { setBlockOnProperty(true); @@ -96,6 +103,14 @@ HorizontalLineView::HorizontalLineView() setCursor(Qt::SizeVerCursor); } +QPainterPath HorizontalLineView::shape() const +{ + QPainterPath path; + path.addRect( + QRectF(0.0, -mask_visible_width / 2., m_bounding_rect.width(), mask_visible_width)); + return path; +} + void HorizontalLineView::onChangedY() { setBlockOnProperty(true); diff --git a/GUI/Views/MaskWidgets/LineViews.h b/GUI/Views/MaskWidgets/LineViews.h index f3010c3a5a4e93eff1a386fd67881943b9b68e05..ee73fedd31b545441baa8fbbbb0a032edb8d6dc5 100644 --- a/GUI/Views/MaskWidgets/LineViews.h +++ b/GUI/Views/MaskWidgets/LineViews.h @@ -26,6 +26,7 @@ public: int type() const { return MaskEditorHelper::VERTICALLINE; } VerticalLineView(); + virtual QPainterPath shape() const override; protected slots: virtual void update_view(); @@ -46,6 +47,7 @@ public: int type() const { return MaskEditorHelper::HORIZONTALLINE; } HorizontalLineView(); + virtual QPainterPath shape() const override; protected slots: virtual void update_view(); diff --git a/GUI/Views/MaskWidgets/MaskEditorHelper.cpp b/GUI/Views/MaskWidgets/MaskEditorHelper.cpp index 015ca96e266946cfb7b1716f392770dc90835f9a..4c56893ea8b0e0de976b59f67dac692d5f5c0cda 100644 --- a/GUI/Views/MaskWidgets/MaskEditorHelper.cpp +++ b/GUI/Views/MaskWidgets/MaskEditorHelper.cpp @@ -33,14 +33,10 @@ QPen MaskEditorHelper::getSelectionMarkerPen() QBrush MaskEditorHelper::getMaskBrush(bool mask_value) { - QBrush result; - result.setStyle(Qt::SolidPattern); - if (mask_value) { - result.setColor(QColor(209, 109, 97)); // deep red - } else { - result.setColor(QColor(0, 213, 106)); // deep green - } - return result; + if (!mask_value) + return Qt::NoBrush; + + return QBrush(QColor(0, 0, 80)); // deep blue } QPen MaskEditorHelper::getMaskPen(bool mask_value) diff --git a/GUI/Views/MaskWidgets/PolygonView.cpp b/GUI/Views/MaskWidgets/PolygonView.cpp index 47c961d71f9ff27908bd7ad4db75869cf530defb..304973e357f717bf50bd387fd0b3eaa0f564d918 100644 --- a/GUI/Views/MaskWidgets/PolygonView.cpp +++ b/GUI/Views/MaskWidgets/PolygonView.cpp @@ -59,6 +59,14 @@ QPointF PolygonView::lastAddedPoint() const return childItems().size() ? childItems().back()->scenePos() : QPointF(); } +QPainterPath PolygonView::shape() const +{ + QPainterPath path; + path.addPolygon(m_polygon); + path.closeSubpath(); + return path; +} + //! Returns true if there was a request to close polygon (emitted by its start point), //! and then closes a polygon. Returns true if polygon was closed. bool PolygonView::closePolygonIfNecessary() @@ -86,21 +94,17 @@ bool PolygonView::isClosedPolygon() return m_item->getItemValue(PolygonItem::P_ISCLOSED).toBool(); } -void PolygonView::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) +void PolygonView::paint(QPainter* painter, const QStyleOptionGraphicsItem* o, QWidget* w) { - ASSERT(m_item); - painter->setRenderHints(QPainter::Antialiasing); - - bool mask_value = m_item->getItemValue(MaskItem::P_MASK_VALUE).toBool(); - painter->setBrush(MaskEditorHelper::getMaskBrush(mask_value)); - painter->setPen(MaskEditorHelper::getMaskPen(mask_value)); - - // painter->drawRect(m_bounding_rect); - - painter->drawPolyline(m_polygon.toPolygon()); - if (isClosedPolygon()) - painter->drawPolygon(m_polygon.toPolygon()); + IShape2DView::paint(painter, o, w); + else { + ASSERT(m_item); + const bool mask_value = m_item->getItemValue(MaskItem::P_MASK_VALUE).toBool(); + painter->setRenderHints(QPainter::Antialiasing); + painter->setPen(MaskEditorHelper::getMaskPen(mask_value)); + painter->drawPolyline(m_polygon.toPolygon()); + } } QVariant PolygonView::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value) diff --git a/GUI/Views/MaskWidgets/PolygonView.h b/GUI/Views/MaskWidgets/PolygonView.h index 4d50e0471d21f6205db33656e644016da6c01272..1e3accbb8cb12ac5c85f89408a15169826a98859 100644 --- a/GUI/Views/MaskWidgets/PolygonView.h +++ b/GUI/Views/MaskWidgets/PolygonView.h @@ -31,6 +31,7 @@ public: void addView(IShape2DView* childView, int row); bool isClosedPolygon(); QPointF lastAddedPoint() const; + virtual QPainterPath shape() const override; public slots: bool closePolygonIfNecessary(); @@ -40,7 +41,7 @@ protected slots: void update_view(); protected: - void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*); + virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) override; QVariant itemChange(GraphicsItemChange change, const QVariant& value); void mouseMoveEvent(QGraphicsSceneMouseEvent* event); diff --git a/GUI/Views/MaskWidgets/RectangleBaseView.cpp b/GUI/Views/MaskWidgets/RectangleBaseView.cpp index b9ef738b4c29fb123cd5e769189d0d28ac33fc6f..180a1f4eedf34081d7b01c7db3fd902fa90ef4ef 100644 --- a/GUI/Views/MaskWidgets/RectangleBaseView.cpp +++ b/GUI/Views/MaskWidgets/RectangleBaseView.cpp @@ -75,8 +75,9 @@ void RectangleBaseView::update_bounding_rect() { if (m_item) { m_mask_rect = mask_rectangle(); - m_bounding_rect = m_mask_rect.marginsAdded( - QMarginsF(bbox_margins, bbox_margins, bbox_margins, bbox_margins)); + if (type() != MaskEditorHelper::REGIONOFINTEREST) + m_bounding_rect = m_mask_rect.marginsAdded( + QMarginsF(bbox_margins, bbox_margins, bbox_margins, bbox_margins)); } for (QMap<SizeHandleElement::EHandleLocation, SizeHandleElement*>::iterator it = m_resize_handles.begin(); diff --git a/GUI/Views/MaskWidgets/RectangleView.cpp b/GUI/Views/MaskWidgets/RectangleView.cpp index a2eabfaf82002f7bcc1b46eaa37988d437485078..65b37acf9e6d28f5563b405dd96b8786e74d1ba7 100644 --- a/GUI/Views/MaskWidgets/RectangleView.cpp +++ b/GUI/Views/MaskWidgets/RectangleView.cpp @@ -19,6 +19,13 @@ RectangleView::RectangleView() = default; +QPainterPath RectangleView::shape() const +{ + QPainterPath path; + path.addRect(m_mask_rect); + return path; +} + void RectangleView::onChangedX() { setBlockOnProperty(true); @@ -41,14 +48,6 @@ void RectangleView::onPropertyChange(const QString& propertyName) update_view(); } -void RectangleView::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) -{ - bool mask_value = m_item->getItemValue(MaskItem::P_MASK_VALUE).toBool(); - painter->setBrush(MaskEditorHelper::getMaskBrush(mask_value)); - painter->setPen(MaskEditorHelper::getMaskPen(mask_value)); - painter->drawRect(m_mask_rect); -} - void RectangleView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (m_activeHandleElement) { diff --git a/GUI/Views/MaskWidgets/RectangleView.h b/GUI/Views/MaskWidgets/RectangleView.h index e79e7e6f1e8b49ff1c66b27e7ebc4502c28d8a98..3c02b581c2179682bc00bfadb0e248dad0502858 100644 --- a/GUI/Views/MaskWidgets/RectangleView.h +++ b/GUI/Views/MaskWidgets/RectangleView.h @@ -27,14 +27,13 @@ public: int type() const { return MaskEditorHelper::RECTANGLE; } RectangleView(); - + virtual QPainterPath shape() const override; protected slots: virtual void onChangedX(); virtual void onChangedY(); virtual void onPropertyChange(const QString& propertyName); protected: - void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*); void mouseMoveEvent(QGraphicsSceneMouseEvent* event); protected: diff --git a/GUI/Views/MaskWidgets/RegionOfInterestView.cpp b/GUI/Views/MaskWidgets/RegionOfInterestView.cpp index a1870589dc931b4cc722f7d324c37bd4a1f9cd53..1ff3d241bd6e8d9b56c4ca31fad4339f3a63c33c 100644 --- a/GUI/Views/MaskWidgets/RegionOfInterestView.cpp +++ b/GUI/Views/MaskWidgets/RegionOfInterestView.cpp @@ -13,16 +13,29 @@ // ************************************************************************************************ #include "GUI/Views/MaskWidgets/RegionOfInterestView.h" +#include "GUI/Views/MaskWidgets/ISceneAdaptor.h" #include <QPainter> -//! Paints two-color tiny frame without filling. +QRectF RegionOfInterestView::boundingRect() const +{ + return mapFromScene(m_adaptor->viewportRectangle()).boundingRect(); +} + +void RegionOfInterestView::update_view() +{ + RectangleView::update_view(); + m_bounding_rect = m_adaptor->viewportRectangle(); + update(); +} void RegionOfInterestView::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) { - painter->setPen(QPen(QColor(34, 67, 255))); - painter->drawRect(m_mask_rect); + QPainterPath outerRect; + outerRect.addRect(boundingRect()); + + QPainterPath innerRect; + innerRect.addRect(m_mask_rect); - QRectF secondRect = m_mask_rect.marginsAdded(QMarginsF(1, 1, 1, 1)); - painter->setPen(QPen(QColor(255, 255, 245))); - painter->drawRect(secondRect); + painter->setBrush(MaskEditorHelper::getMaskBrush(true)); + painter->drawPath(outerRect.subtracted(innerRect)); } diff --git a/GUI/Views/MaskWidgets/RegionOfInterestView.h b/GUI/Views/MaskWidgets/RegionOfInterestView.h index 6c39fe3c69d2d69a0e93c04ad3bfa1076b4022ad..86090ad81d1e2e6cdd7ae74fa5c25bed913846b2 100644 --- a/GUI/Views/MaskWidgets/RegionOfInterestView.h +++ b/GUI/Views/MaskWidgets/RegionOfInterestView.h @@ -24,6 +24,10 @@ class RegionOfInterestView : public RectangleView { public: int type() const { return MaskEditorHelper::REGIONOFINTEREST; } + virtual QRectF boundingRect() const; + +protected slots: + void update_view(); protected: void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*);