diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp index a47452446..df06ce920 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp +++ b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.cpp @@ -16,8 +16,6 @@ along with QElectroTech. If not, see . */ #include "qetgraphicshandlerutility.h" -//#include -//#include #include @@ -241,3 +239,80 @@ QPolygonF QetGraphicsHandlerUtility::polygonForInsertPoint(const QPolygonF &old_ polygon.insert(index, pos); return polygon; } + +/** + * @brief QetGraphicsHandlerUtility::pointForRadiusRect + * @param rect the rectangle. + * @param xRadius : x radius + * @param yRadius : y radius + * @param mode : absolute or relative size: NOTE this argument is not used, this function always compute with relative size. + * @return the points of x and y radius of a rounded rect. + * The points are always based on the top right corner of the rect. + * the first point of vector is X the second Y + */ +#include +QVector QetGraphicsHandlerUtility::pointForRadiusRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode) +{ + Q_UNUSED(mode) + QVector v; + + qreal half_width = rect.width()/2; + qreal x_percent = std::min(xRadius, 100.00)/100; + QPointF X(rect.right() - half_width*x_percent, + rect.top()); + v << X; + + qreal half_height = rect.height()/2; + qreal y_percent = std::min(yRadius, 100.00)/100; + QPointF Y(rect.right(), + rect.top()+ half_height*y_percent); + v << Y; + + return v; +} + +/** + * @brief QetGraphicsHandlerUtility::radiusForPosAtIndex + * @param rect the rectangle + * @param pos : the pos of the new radius + * @param index : index of radius 0=X 1=Y + * @param mode + * @return + */ +qreal QetGraphicsHandlerUtility::radiusForPosAtIndex(const QRectF &rect, const QPointF &pos, int index, Qt::SizeMode mode) +{ + Q_UNUSED(mode) + + if(index == 0) //X + { + if (pos.x() < rect.center().x()) { + return 100; + } + else if (pos.x() > rect.right()) { + return 0; + } + else { + return (100 - percentageInRange(rect.center().x(), rect.right(), pos.x())); + } + } + else if (index == 1) //Y + { + if (pos.y() < rect.top()) { + return 0; + } + else if (pos.y() > rect.center().y()) { + return 100; + } + else { + return percentageInRange(rect.top(), rect.center().y(), pos.y()); + } + } + else { + return 0; + } +} + +qreal QetGraphicsHandlerUtility::percentageInRange(qreal min, qreal max, qreal value) { + return ((value - min) * 100) / (max - min); +} + diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h index 809435831..bcfddbcec 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h +++ b/sources/QetGraphicsItemModeler/qetgraphicshandlerutility.h @@ -41,6 +41,9 @@ class QetGraphicsHandlerUtility static QRectF mirrorRectForPosAtIndex (const QRectF &old_rect, const QPointF &pos, int index); static QLineF lineForPosAtIndex (const QLineF &old_line, const QPointF &pos, int index); static QPolygonF polygonForInsertPoint(const QPolygonF &old_polygon, bool closed, const QPointF &pos); + static QVector pointForRadiusRect (const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize); + static qreal radiusForPosAtIndex (const QRectF &rect, const QPointF &pos, int index, Qt::SizeMode mode = Qt::AbsoluteSize); + static qreal percentageInRange(qreal min, qreal max, qreal value); }; #endif // QETGRAPHICSHANDLERUTILITY_H diff --git a/sources/diagramevent/diagrameventaddshape.cpp b/sources/diagramevent/diagrameventaddshape.cpp index db9f1c19b..572dfb98f 100644 --- a/sources/diagramevent/diagrameventaddshape.cpp +++ b/sources/diagramevent/diagrameventaddshape.cpp @@ -82,6 +82,9 @@ bool DiagramEventAddShape::mousePressEvent(QGraphicsSceneMouseEvent *event) if (m_shape_type != QetShapeItem::Polygon) { m_shape_item->setP2 (pos); + if(m_shape_item->shapeType() == QetShapeItem::Rectangle || m_shape_item->shapeType() == QetShapeItem::Ellipse) { + m_shape_item->setRect(m_shape_item->rect().normalized()); + } m_diagram->undoStack().push (new AddItemCommand (m_shape_item, m_diagram)); m_shape_item = nullptr; //< set to nullptr for create new shape at next left clic } diff --git a/sources/qetgraphicsitem/qetshapeitem.cpp b/sources/qetgraphicsitem/qetshapeitem.cpp index f97c050c6..681f9a647 100644 --- a/sources/qetgraphicsitem/qetshapeitem.cpp +++ b/sources/qetgraphicsitem/qetshapeitem.cpp @@ -159,7 +159,9 @@ bool QetShapeItem::setRect(const QRectF &rect) */ bool QetShapeItem::setPolygon(const QPolygonF &polygon) { - if (Q_UNLIKELY(m_shapeType != Polygon)) return false; + if (Q_UNLIKELY(m_shapeType != Polygon)) { + return false; + } prepareGeometryChange(); m_polygon = polygon; adjusteHandlerPos(); @@ -181,6 +183,22 @@ void QetShapeItem::setClosed(bool close) } } +void QetShapeItem::setXRadius(qreal X) +{ + m_xRadius = X; + update(); + adjusteHandlerPos(); + emit XRadiusChanged(); +} + +void QetShapeItem::setYRadius(qreal Y) +{ + m_yRadius = Y; + update(); + adjusteHandlerPos(); + emit YRadiusChanged(); +} + /** * @brief QetShapeItem::pointCount * @return the number of point in the polygon @@ -246,7 +264,7 @@ QPainterPath QetShapeItem::shape() const path.lineTo(m_P2); break; case Rectangle: - path.addRect(QRectF(m_P1, m_P2)); + path.addRoundedRect(QRectF(m_P1, m_P2), m_xRadius, m_yRadius, Qt::RelativeSize); break; case Ellipse: path.addEllipse(QRectF(m_P1, m_P2)); @@ -301,7 +319,7 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti switch (m_shapeType) { case Line: painter->drawLine(QLineF(m_P1, m_P2)); break; - case Rectangle: painter->drawRect(QRectF(m_P1, m_P2)); break; + case Rectangle: painter->drawRoundedRect(QRectF(m_P1, m_P2), m_xRadius, m_yRadius, Qt::RelativeSize); break; case Ellipse: painter->drawEllipse(QRectF(m_P1, m_P2)); break; case Polygon: m_closed ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon); break; } @@ -331,17 +349,16 @@ void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) QetGraphicsItem::hoverLeaveEvent(event); } -/** - * @brief QetShapeItem::mouseReleaseEvent - * Handle mouse release event - * @param event - */ -void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (event->buttonDownPos(Qt::LeftButton) == event->pos()) + event->ignore(); + if (event->button() == Qt::LeftButton) { switchResizeMode(); - - QetGraphicsItem::mouseReleaseEvent(event); + event->accept(); + } + else { + QetGraphicsItem::mousePressEvent(event); + } } /** @@ -364,10 +381,10 @@ QVariant QetShapeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons qDeleteAll(m_handler_vector); m_handler_vector.clear(); } + m_resize_mode = 1; } } - else if (change == ItemPositionHasChanged) - { + else if (change == ItemPositionHasChanged) { adjusteHandlerPos(); } else if (change == ItemSceneHasChanged) @@ -485,7 +502,24 @@ void QetShapeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) */ void QetShapeItem::switchResizeMode() { - if (m_shapeType & (Rectangle | Ellipse)) + if (m_shapeType == Ellipse) + { + if (m_resize_mode == 1) + { + m_resize_mode = 2; + for (QetGraphicsHandlerItem *qghi : m_handler_vector) { + qghi->setColor(Qt::darkGreen); + } + } + else + { + m_resize_mode = 1; + for (QetGraphicsHandlerItem *qghi : m_handler_vector) { + qghi->setColor(Qt::blue); + } + } + } + else if (m_shapeType == Rectangle) { if (m_resize_mode == 1) { @@ -493,11 +527,26 @@ void QetShapeItem::switchResizeMode() for (QetGraphicsHandlerItem *qghi : m_handler_vector) qghi->setColor(Qt::darkGreen); } - else + else if (m_resize_mode == 2) + { + m_resize_mode = 3; + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + addHandler(); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) { + qghi->setColor(Qt::magenta); + } + } + else if (m_resize_mode == 3) { m_resize_mode = 1; - for (QetGraphicsHandlerItem *qghi : m_handler_vector) + qDeleteAll(m_handler_vector); + m_handler_vector.clear(); + addHandler(); + for (QetGraphicsHandlerItem *qghi : m_handler_vector) { qghi->setColor(Qt::blue); + } + } } } @@ -509,10 +558,23 @@ void QetShapeItem::addHandler() QVector points_vector; switch (m_shapeType) { - case Line: points_vector << m_P1 << m_P2; break; - case Rectangle: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; - case Ellipse: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; - case Polygon: points_vector = m_polygon; break; + case Line: + points_vector << m_P1 << m_P2; + break; + case Rectangle: + if (m_resize_mode == 3) { + points_vector = QetGraphicsHandlerUtility::pointForRadiusRect(QRectF(m_P1, m_P2), m_xRadius, m_yRadius); + } + else { + points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); + } + break; + case Ellipse: + points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); + break; + case Polygon: + points_vector = m_polygon; + break; } if(!points_vector.isEmpty() && scene()) @@ -536,13 +598,34 @@ void QetShapeItem::addHandler() */ void QetShapeItem::adjusteHandlerPos() { + if (m_handler_vector.isEmpty()) { + return; + } + QVector points_vector; switch (m_shapeType) { - case Line: points_vector << m_P1 << m_P2; break; - case Rectangle: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; - case Ellipse: points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); break; - case Polygon: points_vector = m_polygon; break; + case Line: { + points_vector << m_P1 << m_P2; + break; + } + case Rectangle: { + if (m_resize_mode != 3) { + points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); + } + else { + points_vector = QetGraphicsHandlerUtility::pointForRadiusRect(QRectF(m_P1, m_P2), m_xRadius, m_yRadius); + } + break; + } + case Ellipse: { + points_vector = QetGraphicsHandlerUtility::pointsForRect(QRectF(m_P1, m_P2)); + break; + } + case Polygon: { + points_vector = m_polygon; + break; + } } if (m_handler_vector.size() == points_vector.size()) @@ -621,6 +704,11 @@ void QetShapeItem::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphic m_old_P1 = m_P1; m_old_P2 = m_P2; m_old_polygon = m_polygon; + m_old_xRadius = m_xRadius; + m_old_yRadius = m_yRadius; + if(m_xRadius == 0 && m_yRadius == 0) { + m_modifie_radius_equaly = true; + } } /** @@ -650,10 +738,25 @@ void QetShapeItem::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphics setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); break; } - else { + else if (m_resize_mode == 2) { setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); break; } + else { + qreal radius = QetGraphicsHandlerUtility::radiusForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index); + if(m_modifie_radius_equaly) { + setXRadius(radius); + setYRadius(radius); + } + else if(m_vector_index == 0) { + setXRadius(radius); + } + else { + setYRadius(radius); + } + adjusteHandlerPos(); + break; + } case Ellipse: if (m_resize_mode == 1) { setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index)); @@ -682,19 +785,42 @@ void QetShapeItem::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraph Q_UNUSED(qghi); Q_UNUSED(event); + m_modifie_radius_equaly = false; + if (diagram()) { QPropertyUndoCommand *undo = nullptr; - if ((m_shapeType & (Line | Rectangle | Ellipse)) && (m_P1 != m_old_P1 || m_P2 != m_old_P2)) + if ((m_shapeType & (Line | Rectangle | Ellipse)) && ((m_P1 != m_old_P1 || m_P2 != m_old_P2) || + (m_old_xRadius != XRadius() || m_old_yRadius != m_yRadius)) + ) { switch(m_shapeType) { - case Line: undo = new QPropertyUndoCommand(this, "line",QLineF(m_old_P1, m_old_P2), QLineF(m_P1, m_P2)); break; - case Rectangle: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; - case Ellipse: undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2)); break; + case Line: { + undo = new QPropertyUndoCommand(this, "line",QLineF(m_old_P1, m_old_P2), QLineF(m_P1, m_P2)); + break; + } + case Rectangle: { + if (m_resize_mode == 1 || m_resize_mode == 2) { + undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2).normalized()); + } + else if (m_resize_mode == 3) + { + undo = new QPropertyUndoCommand(this, "xRadius", m_old_xRadius, m_xRadius); + QPropertyUndoCommand *undo_ = new QPropertyUndoCommand(this, "yRadius", m_old_yRadius, m_yRadius, undo); + undo_->setAnimated(); + } + break; + } + case Ellipse: { + undo = new QPropertyUndoCommand(this, "rect",QRectF(m_old_P1, m_old_P2), QRectF(m_P1, m_P2).normalized()); + break; + } case Polygon: break; } - if (undo) undo->enableAnimation(); + if (undo) { + undo->setAnimated(true, false); + } } else if (m_shapeType == Polygon && (m_polygon != m_old_polygon)) undo = new QPropertyUndoCommand(this, "polygon", m_old_polygon, m_polygon); diff --git a/sources/qetgraphicsitem/qetshapeitem.h b/sources/qetgraphicsitem/qetshapeitem.h index aa5a155cc..d771e87e3 100644 --- a/sources/qetgraphicsitem/qetshapeitem.h +++ b/sources/qetgraphicsitem/qetshapeitem.h @@ -36,18 +36,23 @@ class QetShapeItem : public QetGraphicsItem { Q_OBJECT - Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged) - Q_PROPERTY(QRectF rect READ rect WRITE setRect) - Q_PROPERTY(QLineF line READ line WRITE setLine) - Q_PROPERTY(QPolygonF polygon READ polygon WRITE setPolygon) - Q_PROPERTY(bool close READ isClosed WRITE setClosed NOTIFY closeChanged) + Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged) + Q_PROPERTY(QRectF rect READ rect WRITE setRect) + Q_PROPERTY(QLineF line READ line WRITE setLine) + Q_PROPERTY(QPolygonF polygon READ polygon WRITE setPolygon) + Q_PROPERTY(bool close READ isClosed WRITE setClosed NOTIFY closeChanged) + Q_PROPERTY(qreal xRadius READ XRadius WRITE setXRadius NOTIFY XRadiusChanged) + Q_PROPERTY(qreal yRadius READ YRadius WRITE setYRadius NOTIFY YRadiusChanged) signals: void penChanged(); void brushChanged(); void closeChanged(); - + void XRadiusChanged(); + void YRadiusChanged(); + + public: Q_ENUMS(ShapeType) enum ShapeType {Line =1, @@ -86,6 +91,10 @@ class QetShapeItem : public QetGraphicsItem bool setPolygon (const QPolygonF &polygon); bool isClosed() const {return m_closed;} void setClosed (bool close); + qreal XRadius() const {return m_xRadius;} + void setXRadius(qreal X); + qreal YRadius() const {return m_yRadius;} + void setYRadius(qreal Y); //Methods available for polygon shape int pointsCount () const; @@ -99,7 +108,7 @@ class QetShapeItem : public QetGraphicsItem void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void hoverEnterEvent (QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent (QGraphicsSceneHoverEvent *event) override; - void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override; + void mousePressEvent (QGraphicsSceneMouseEvent *event) override; QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; @@ -128,10 +137,15 @@ class QetShapeItem : public QetGraphicsItem QPolygonF m_polygon, m_old_polygon; bool m_hovered; int m_vector_index; - bool m_closed = false; + bool m_closed = false, + m_modifie_radius_equaly = false; int m_resize_mode = 1; QVector m_handler_vector; QAction *m_insert_point, *m_remove_point; + qreal m_xRadius = 0, + m_yRadius = 0, + m_old_xRadius, + m_old_yRadius; }; #endif // QETSHAPEITEM_H