2014-06-14 16:04:34 +00:00
|
|
|
/*
|
2017-01-20 10:55:49 +00:00
|
|
|
Copyright 2006-2017 The QElectroTech Team
|
2014-06-14 16:04:34 +00:00
|
|
|
This file is part of QElectroTech.
|
|
|
|
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2014-02-23 18:55:26 +00:00
|
|
|
#include "qetshapeitem.h"
|
2014-06-14 16:04:34 +00:00
|
|
|
#include "createdxf.h"
|
|
|
|
#include "diagram.h"
|
2014-06-17 09:08:41 +00:00
|
|
|
#include "qet.h"
|
2015-06-21 20:16:41 +00:00
|
|
|
#include "shapegraphicsitempropertieswidget.h"
|
2015-06-23 20:40:05 +00:00
|
|
|
#include "PropertiesEditor/propertieseditordialog.h"
|
2015-07-27 09:20:38 +00:00
|
|
|
#include "QPropertyUndoCommand/qpropertyundocommand.h"
|
2016-01-03 13:45:30 +00:00
|
|
|
#include "qetxml.h"
|
2014-06-14 16:04:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::QetShapeItem
|
|
|
|
* Constructor of shape item. point 1 and 2 must be in scene coordinate
|
|
|
|
* @param p1 first point
|
|
|
|
* @param p2 second point
|
|
|
|
* @param type type of item (line, rectangle, ellipse)
|
|
|
|
* @param parent parent item
|
|
|
|
*/
|
|
|
|
QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem *parent) :
|
2014-02-23 18:55:26 +00:00
|
|
|
QetGraphicsItem(parent),
|
2014-06-14 16:04:34 +00:00
|
|
|
m_shapeType(type),
|
2015-07-13 12:01:02 +00:00
|
|
|
m_P1 (p1),
|
|
|
|
m_P2 (p2),
|
2015-07-09 18:33:14 +00:00
|
|
|
m_hovered(false),
|
2015-07-12 13:35:40 +00:00
|
|
|
m_mouse_grab_handler(false),
|
2015-07-15 16:54:30 +00:00
|
|
|
m_handler(10)
|
2014-02-23 18:55:26 +00:00
|
|
|
{
|
2015-07-27 21:47:41 +00:00
|
|
|
if (type == Polygon) m_polygon << m_P1 << m_P2;
|
2014-06-14 16:04:34 +00:00
|
|
|
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
2014-11-24 17:36:02 +00:00
|
|
|
setAcceptHoverEvents(true);
|
2015-08-06 16:34:38 +00:00
|
|
|
m_pen.setStyle(Qt::DashLine);
|
2015-12-30 13:47:21 +00:00
|
|
|
|
2014-02-23 18:55:26 +00:00
|
|
|
}
|
|
|
|
|
2015-07-27 09:20:38 +00:00
|
|
|
QetShapeItem::~QetShapeItem() {}
|
2014-02-23 18:55:26 +00:00
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
2015-08-06 16:34:38 +00:00
|
|
|
* @brief QetShapeItem::setPen
|
|
|
|
* Set the pen to use for draw the shape
|
|
|
|
* @param pen
|
2014-06-14 16:04:34 +00:00
|
|
|
*/
|
2015-08-06 16:34:38 +00:00
|
|
|
void QetShapeItem::setPen(const QPen &pen)
|
2014-02-23 18:55:26 +00:00
|
|
|
{
|
2015-08-06 16:34:38 +00:00
|
|
|
if (m_pen == pen) return;
|
|
|
|
m_pen = pen;
|
2014-05-25 18:33:06 +00:00
|
|
|
update();
|
2015-08-06 16:34:38 +00:00
|
|
|
emit penChanged();
|
2014-05-25 18:33:06 +00:00
|
|
|
}
|
|
|
|
|
2016-01-12 14:02:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setBrush
|
|
|
|
* Set the brush to use for the fill the shape
|
|
|
|
* @param brush
|
|
|
|
*/
|
|
|
|
void QetShapeItem::setBrush(const QBrush &brush)
|
|
|
|
{
|
|
|
|
if (m_brush == brush) return;
|
|
|
|
m_brush = brush;
|
|
|
|
update();
|
|
|
|
emit brushChanged();
|
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setP2
|
2014-06-17 09:08:41 +00:00
|
|
|
* Set the second point of this item.
|
|
|
|
* If this item is a polyline,
|
|
|
|
* the last point of the polyline is replaced by P2.
|
2014-06-14 16:04:34 +00:00
|
|
|
* @param P2
|
|
|
|
*/
|
2015-07-12 13:35:40 +00:00
|
|
|
void QetShapeItem::setP2(const QPointF &P2)
|
|
|
|
{
|
2015-07-27 21:47:41 +00:00
|
|
|
if (m_shapeType == Polygon && m_polygon.last() != P2)
|
2015-07-12 13:35:40 +00:00
|
|
|
{
|
2014-06-17 09:08:41 +00:00
|
|
|
prepareGeometryChange();
|
|
|
|
m_polygon.replace(m_polygon.size()-1, P2);
|
|
|
|
}
|
2015-07-12 13:35:40 +00:00
|
|
|
else if (P2 != m_P2)
|
|
|
|
{
|
2014-06-17 09:08:41 +00:00
|
|
|
prepareGeometryChange();
|
|
|
|
m_P2 = P2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-12 13:35:40 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setLine
|
|
|
|
* Set item geometry to line (only available for line shape)
|
|
|
|
* @param line
|
2015-07-27 09:20:38 +00:00
|
|
|
* @return : true when shape is a Line, else false
|
2015-07-12 13:35:40 +00:00
|
|
|
*/
|
2015-07-27 09:20:38 +00:00
|
|
|
bool QetShapeItem::setLine(const QLineF &line)
|
2015-07-12 13:35:40 +00:00
|
|
|
{
|
2015-07-27 09:20:38 +00:00
|
|
|
if (Q_UNLIKELY(m_shapeType != Line)) return false;
|
|
|
|
prepareGeometryChange();
|
|
|
|
m_P1 = line.p1();
|
|
|
|
m_P2 = line.p2();
|
|
|
|
return true;
|
2015-07-12 13:35:40 +00:00
|
|
|
}
|
|
|
|
|
2015-07-09 18:33:14 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setRect
|
|
|
|
* Set this item geometry to rect (only available if shape is a rectangle or an ellipse)
|
|
|
|
* @param rect : new rect
|
|
|
|
* @return : true when shape is rectangle or ellipse, else false
|
|
|
|
*/
|
|
|
|
bool QetShapeItem::setRect(const QRectF &rect)
|
|
|
|
{
|
|
|
|
if (Q_LIKELY(m_shapeType == Rectangle || m_shapeType == Ellipse))
|
|
|
|
{
|
|
|
|
prepareGeometryChange();
|
|
|
|
m_P1 = rect.topLeft();
|
|
|
|
m_P2 = rect.bottomRight();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setPolygon
|
|
|
|
* Set this item geometry to polygon (only available if shape is a polyline)
|
|
|
|
* @param polygon : new polygon
|
|
|
|
* @return true if item is polygon, else false
|
|
|
|
*/
|
2015-07-12 13:35:40 +00:00
|
|
|
bool QetShapeItem::setPolygon(const QPolygonF &polygon)
|
2015-07-09 18:33:14 +00:00
|
|
|
{
|
2015-07-27 21:47:41 +00:00
|
|
|
if (Q_UNLIKELY(m_shapeType != Polygon)) return false;
|
2015-07-09 18:33:14 +00:00
|
|
|
prepareGeometryChange();
|
|
|
|
m_polygon = polygon;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-01-12 14:02:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setClosed
|
|
|
|
* Close this item, have effect only if this item is a polygon.
|
|
|
|
* @param close
|
|
|
|
*/
|
|
|
|
void QetShapeItem::setClosed(bool close)
|
|
|
|
{
|
|
|
|
if (m_shapeType == Polygon && close != m_close)
|
|
|
|
{
|
|
|
|
prepareGeometryChange();
|
|
|
|
m_close = close;
|
|
|
|
emit closeChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-29 23:18:00 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::pointCount
|
|
|
|
* @return the number of point in the polygon
|
|
|
|
*/
|
2015-07-27 09:20:38 +00:00
|
|
|
int QetShapeItem::pointsCount() const {
|
2014-12-29 23:18:00 +00:00
|
|
|
return m_polygon.size();
|
|
|
|
}
|
|
|
|
|
2014-06-17 09:08:41 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::setNextPoint
|
|
|
|
* Add a new point to the curent polygon
|
|
|
|
* @param P the new point.
|
|
|
|
*/
|
2015-07-27 09:20:38 +00:00
|
|
|
void QetShapeItem::setNextPoint(QPointF P)
|
|
|
|
{
|
2014-06-14 16:04:34 +00:00
|
|
|
prepareGeometryChange();
|
2014-06-17 09:08:41 +00:00
|
|
|
m_polygon.append(Diagram::snapToGrid(P));
|
2014-02-28 08:20:00 +00:00
|
|
|
}
|
|
|
|
|
2014-12-29 23:18:00 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::removePoints
|
|
|
|
* Number of point to remove on the polygon
|
|
|
|
* If @number is superior to number of polygon points-2,
|
|
|
|
* all points of polygon will be removed except the first two (minimum point for the polygon);
|
|
|
|
*/
|
|
|
|
void QetShapeItem::removePoints(int number)
|
|
|
|
{
|
|
|
|
if (pointsCount() == 2 || number < 1) return;
|
|
|
|
if ((pointsCount()-2) < number)
|
|
|
|
number = pointsCount() - 2;
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
prepareGeometryChange();
|
|
|
|
m_polygon.pop_back();
|
|
|
|
setTransformOriginPoint(boundingRect().center());
|
|
|
|
|
|
|
|
} while (i < number);
|
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::boundingRect
|
|
|
|
* @return the bounding rect of this item
|
|
|
|
*/
|
|
|
|
QRectF QetShapeItem::boundingRect() const {
|
2015-07-31 13:29:23 +00:00
|
|
|
return shape().boundingRect().adjusted(-6, -6, 6, 6);
|
2014-02-23 18:55:26 +00:00
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::shape
|
|
|
|
* @return the shape of this item
|
|
|
|
*/
|
2015-07-12 13:35:40 +00:00
|
|
|
QPainterPath QetShapeItem::shape() const
|
|
|
|
{
|
2014-02-27 09:55:54 +00:00
|
|
|
QPainterPath path;
|
|
|
|
|
2015-07-12 13:35:40 +00:00
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
2016-04-16 17:45:56 +00:00
|
|
|
case Line:
|
|
|
|
path.moveTo(m_P1);
|
|
|
|
path.lineTo(m_P2);
|
|
|
|
break;
|
|
|
|
case Rectangle:
|
|
|
|
path.addRect(QRectF(m_P1, m_P2));
|
|
|
|
break;
|
|
|
|
case Ellipse:
|
|
|
|
path.addEllipse(QRectF(m_P1, m_P2));
|
|
|
|
break;
|
|
|
|
case Polygon:
|
|
|
|
path.addPolygon(m_polygon);
|
|
|
|
if (m_close) {
|
|
|
|
path.closeSubpath();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Q_ASSERT(false);
|
|
|
|
break;
|
2014-02-27 09:55:54 +00:00
|
|
|
}
|
|
|
|
|
2014-11-24 17:36:02 +00:00
|
|
|
QPainterPathStroker pps;
|
2016-01-03 13:45:30 +00:00
|
|
|
pps.setWidth(m_hovered? m_pen.widthF()+10 : m_pen.widthF());
|
2014-11-24 17:36:02 +00:00
|
|
|
pps.setJoinStyle(Qt::RoundJoin);
|
2015-07-09 18:33:14 +00:00
|
|
|
path = pps.createStroke(path);
|
|
|
|
|
2016-10-20 18:57:22 +00:00
|
|
|
if (isSelected())
|
|
|
|
{
|
|
|
|
QVector <QPointF> vector;
|
2015-07-09 18:33:14 +00:00
|
|
|
|
2016-10-20 18:57:22 +00:00
|
|
|
if (m_shapeType == Line)
|
|
|
|
vector << m_P1 << m_P2;
|
|
|
|
else if (m_shapeType == Rectangle || m_shapeType == Ellipse) {
|
|
|
|
QRectF rect (m_P1, m_P2);
|
|
|
|
vector << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vector = m_polygon;
|
2014-11-24 17:36:02 +00:00
|
|
|
|
2016-10-20 18:57:22 +00:00
|
|
|
foreach(QRectF r, m_handler.handlerRect(vector))
|
|
|
|
path.addRect(r);
|
|
|
|
}
|
2016-10-20 19:01:15 +00:00
|
|
|
|
2015-07-09 18:33:14 +00:00
|
|
|
return (path);
|
2014-02-27 09:55:54 +00:00
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::paint
|
|
|
|
* Paint this item
|
|
|
|
* @param painter
|
|
|
|
* @param option
|
|
|
|
* @param widget
|
|
|
|
*/
|
|
|
|
void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
2014-03-07 12:34:47 +00:00
|
|
|
{
|
2014-06-14 16:04:34 +00:00
|
|
|
Q_UNUSED(option); Q_UNUSED(widget);
|
2014-03-07 12:34:47 +00:00
|
|
|
|
2015-08-06 16:34:38 +00:00
|
|
|
painter->save();
|
2016-01-03 13:45:30 +00:00
|
|
|
painter->setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter->setPen(m_pen);
|
2016-01-12 14:02:34 +00:00
|
|
|
painter->setBrush(m_brush);
|
2014-11-24 18:00:37 +00:00
|
|
|
|
2015-07-09 18:33:14 +00:00
|
|
|
//Draw hovered shadow
|
|
|
|
if (m_hovered)
|
|
|
|
{
|
2014-11-24 17:36:02 +00:00
|
|
|
painter->save();
|
|
|
|
QColor color(Qt::darkBlue);
|
|
|
|
color.setAlpha(25);
|
|
|
|
painter -> setBrush (QBrush (color));
|
|
|
|
painter -> setPen (Qt::NoPen);
|
|
|
|
painter -> drawPath (shape());
|
|
|
|
painter -> restore ();
|
|
|
|
}
|
2014-06-15 13:29:30 +00:00
|
|
|
|
2015-07-19 15:52:44 +00:00
|
|
|
//Draw the shape and handlers if is selected
|
2015-07-09 18:33:14 +00:00
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
2014-06-14 16:04:34 +00:00
|
|
|
case Line:
|
|
|
|
painter->drawLine(QLineF(m_P1, m_P2));
|
2015-07-09 18:33:14 +00:00
|
|
|
if (isSelected())
|
2015-07-19 15:52:44 +00:00
|
|
|
m_handler.drawHandler(painter, QVector<QPointF>{m_P1, m_P2});
|
2014-06-14 16:04:34 +00:00
|
|
|
break;
|
2015-07-09 18:33:14 +00:00
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
case Rectangle:
|
2014-11-24 17:36:02 +00:00
|
|
|
painter->drawRect(QRectF(m_P1, m_P2));
|
2015-07-09 18:33:14 +00:00
|
|
|
if (isSelected())
|
2015-07-19 15:52:44 +00:00
|
|
|
m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2)));
|
2014-06-14 16:04:34 +00:00
|
|
|
break;
|
2015-07-09 18:33:14 +00:00
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
case Ellipse:
|
2014-11-24 17:36:02 +00:00
|
|
|
painter->drawEllipse(QRectF(m_P1, m_P2));
|
2015-07-09 18:33:14 +00:00
|
|
|
if (isSelected())
|
2015-07-19 15:52:44 +00:00
|
|
|
m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2)));
|
2014-06-14 16:04:34 +00:00
|
|
|
break;
|
2015-07-09 18:33:14 +00:00
|
|
|
|
2015-07-27 21:47:41 +00:00
|
|
|
case Polygon:
|
2016-01-12 14:02:34 +00:00
|
|
|
m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon);
|
2015-07-19 15:52:44 +00:00
|
|
|
if (isSelected())
|
|
|
|
m_handler.drawHandler(painter, m_polygon);
|
2014-06-17 09:08:41 +00:00
|
|
|
break;
|
2014-02-28 14:30:59 +00:00
|
|
|
}
|
2015-08-06 16:34:38 +00:00
|
|
|
painter->restore();
|
2014-06-14 16:04:34 +00:00
|
|
|
}
|
2014-02-28 14:30:59 +00:00
|
|
|
|
2014-11-24 17:36:02 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::hoverEnterEvent
|
|
|
|
* Handle hover enter event
|
|
|
|
* @param event
|
|
|
|
*/
|
|
|
|
void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) {
|
|
|
|
m_hovered = true;
|
2015-07-27 09:20:38 +00:00
|
|
|
QetGraphicsItem::hoverEnterEvent(event);
|
2014-11-24 17:36:02 +00:00
|
|
|
}
|
|
|
|
|
2015-07-29 09:25:41 +00:00
|
|
|
void QetShapeItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
|
|
|
{
|
2015-07-31 13:29:23 +00:00
|
|
|
if (!isSelected()) return;
|
|
|
|
|
2015-07-29 09:25:41 +00:00
|
|
|
QVector <QPointF> vector;
|
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
|
|
|
case Line: vector << m_P1 << m_P2; break;
|
|
|
|
case Rectangle: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break;
|
|
|
|
case Ellipse: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break;
|
|
|
|
case Polygon: vector = m_polygon; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int handler = m_handler.pointIsHoverHandler(event->pos(), vector);
|
2015-07-31 13:29:23 +00:00
|
|
|
if (handler >= 0)
|
2015-07-29 09:25:41 +00:00
|
|
|
{
|
|
|
|
if (m_shapeType & (Line | Polygon)) {
|
|
|
|
setCursor(Qt::SizeAllCursor);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handler == 0 || handler == 2 || handler == 5 || handler == 7)
|
|
|
|
setCursor(Qt::SizeAllCursor);
|
|
|
|
else if (handler == 1 || handler == 6)
|
|
|
|
setCursor(Qt::SizeVerCursor);
|
|
|
|
else if (handler == 3 || handler == 4)
|
|
|
|
setCursor(Qt::SizeHorCursor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
setCursor(Qt::OpenHandCursor);
|
|
|
|
}
|
|
|
|
|
2014-11-24 17:36:02 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::hoverLeaveEvent
|
|
|
|
* Handle hover leave event
|
|
|
|
* @param event
|
|
|
|
*/
|
|
|
|
void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
|
|
|
|
m_hovered = false;
|
2015-07-31 13:29:23 +00:00
|
|
|
unsetCursor();
|
2015-07-27 09:20:38 +00:00
|
|
|
QetGraphicsItem::hoverLeaveEvent(event);
|
2014-11-24 17:36:02 +00:00
|
|
|
}
|
|
|
|
|
2015-07-09 18:33:14 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::mousePressEvent
|
|
|
|
* Handle mouse press event
|
|
|
|
* @param event
|
|
|
|
*/
|
|
|
|
void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
2015-07-31 13:29:23 +00:00
|
|
|
if (event->button() == Qt::LeftButton)
|
2015-07-09 18:33:14 +00:00
|
|
|
{
|
2015-07-31 13:29:23 +00:00
|
|
|
setCursor(Qt::ClosedHandCursor);
|
|
|
|
//Shape is selected, we see if user click in a handler
|
|
|
|
if (isSelected())
|
2015-07-09 18:33:14 +00:00
|
|
|
{
|
2015-07-31 13:29:23 +00:00
|
|
|
QVector <QPointF> vector;
|
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
|
|
|
case Line: vector << m_P1 << m_P2; break;
|
|
|
|
case Rectangle: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break;
|
|
|
|
case Ellipse: vector = m_handler.pointsForRect(QRectF(m_P1, m_P2)); break;
|
|
|
|
case Polygon: vector = m_polygon; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_vector_index = m_handler.pointIsHoverHandler(event->pos(), vector);
|
|
|
|
if (m_vector_index != -1)
|
|
|
|
{
|
|
|
|
//User click on an handler
|
|
|
|
m_mouse_grab_handler = true;
|
|
|
|
m_old_P1 = m_P1;
|
|
|
|
m_old_P2 = m_P2;
|
|
|
|
m_old_polygon = m_polygon;
|
|
|
|
return;
|
|
|
|
}
|
2015-07-09 18:33:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QetGraphicsItem::mousePressEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::mouseMoveEvent
|
|
|
|
* Handle move event
|
|
|
|
* @param event
|
|
|
|
*/
|
|
|
|
void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
if (m_mouse_grab_handler)
|
|
|
|
{
|
|
|
|
QPointF new_pos = event->pos();
|
|
|
|
if (event->modifiers() != Qt::ControlModifier)
|
|
|
|
new_pos = mapFromScene(Diagram::snapToGrid(event->scenePos()));
|
|
|
|
|
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
2015-07-27 09:20:38 +00:00
|
|
|
case Line:
|
2015-07-09 18:33:14 +00:00
|
|
|
prepareGeometryChange();
|
|
|
|
m_vector_index == 0 ? m_P1 = new_pos : m_P2 = new_pos;
|
|
|
|
break;
|
|
|
|
|
2016-07-19 17:12:30 +00:00
|
|
|
case Rectangle:
|
|
|
|
if (m_resize_mode == 1) {
|
|
|
|
setRect(m_handler.rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setRect(m_handler.mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Ellipse:
|
|
|
|
if (m_resize_mode == 1) {
|
|
|
|
setRect(m_handler.rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setRect(m_handler.mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
|
|
|
|
break;
|
|
|
|
}
|
2015-07-09 18:33:14 +00:00
|
|
|
|
2015-07-27 21:47:41 +00:00
|
|
|
case Polygon:
|
2015-07-09 18:33:14 +00:00
|
|
|
prepareGeometryChange();
|
|
|
|
m_polygon.replace(m_vector_index, new_pos);
|
|
|
|
break;
|
|
|
|
} //End switch
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QetGraphicsItem::mouseMoveEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::mouseReleaseEvent
|
|
|
|
* Handle mouse release event
|
|
|
|
* @param event
|
|
|
|
*/
|
|
|
|
void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
2016-07-19 17:12:30 +00:00
|
|
|
if ((m_shapeType & (Rectangle | Ellipse)) && event->buttonDownPos(Qt::LeftButton) == event->pos())
|
|
|
|
switchResizeMode();
|
|
|
|
|
2015-07-12 13:35:40 +00:00
|
|
|
if (m_mouse_grab_handler)
|
|
|
|
{
|
|
|
|
m_mouse_grab_handler = false;
|
|
|
|
if (diagram())
|
|
|
|
{
|
2015-07-27 09:20:38 +00:00
|
|
|
QPropertyUndoCommand *undo = nullptr;
|
|
|
|
if ((m_shapeType & (Line | Rectangle | Ellipse)) && (m_P1 != m_old_P1 || m_P2 != m_old_P2))
|
|
|
|
{
|
|
|
|
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;
|
2015-07-27 21:47:41 +00:00
|
|
|
case Polygon: break;
|
2015-07-27 09:20:38 +00:00
|
|
|
}
|
|
|
|
if (undo) undo->enableAnimation();
|
|
|
|
}
|
2015-07-27 21:47:41 +00:00
|
|
|
else if (m_shapeType == Polygon && (m_polygon != m_old_polygon))
|
2015-07-27 09:20:38 +00:00
|
|
|
undo = new QPropertyUndoCommand(this, "polygon", m_old_polygon, m_polygon);
|
|
|
|
|
|
|
|
if(undo)
|
|
|
|
{
|
|
|
|
undo->setText(tr("Modifier %1").arg(name()));
|
|
|
|
diagram()->undoStack().push(undo);
|
|
|
|
}
|
2015-07-12 13:35:40 +00:00
|
|
|
}
|
2015-07-29 09:25:41 +00:00
|
|
|
setCursor(Qt::OpenHandCursor);
|
2015-07-12 13:35:40 +00:00
|
|
|
}
|
|
|
|
|
2015-07-09 18:33:14 +00:00
|
|
|
QetGraphicsItem::mouseReleaseEvent(event);
|
|
|
|
}
|
|
|
|
|
2016-07-19 17:12:30 +00:00
|
|
|
void QetShapeItem::switchResizeMode()
|
|
|
|
{
|
|
|
|
if (m_resize_mode == 1) {
|
|
|
|
m_resize_mode = 2;
|
|
|
|
m_handler.setOuterColor(Qt::darkGreen);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_resize_mode = 1;
|
|
|
|
m_handler.setOuterColor(Qt::blue);
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::fromXml
|
|
|
|
* Build this item from the xml description
|
|
|
|
* @param e element where is stored this item
|
|
|
|
* @return true if load success
|
|
|
|
*/
|
2015-07-27 19:25:54 +00:00
|
|
|
bool QetShapeItem::fromXml(const QDomElement &e)
|
|
|
|
{
|
2014-06-14 16:04:34 +00:00
|
|
|
if (e.tagName() != "shape") return (false);
|
|
|
|
|
2014-11-13 11:21:06 +00:00
|
|
|
is_movable_ = (e.attribute("is_movable").toInt());
|
2016-01-12 14:02:34 +00:00
|
|
|
m_close = e.attribute("closed", "0").toInt();
|
2016-01-03 13:45:30 +00:00
|
|
|
m_pen = QETXML::penFromXml(e.firstChildElement("pen"));
|
2016-01-12 14:02:34 +00:00
|
|
|
m_brush = QETXML::brushFromXml(e.firstChildElement("brush"));
|
2014-06-17 09:08:41 +00:00
|
|
|
|
2015-07-27 19:25:54 +00:00
|
|
|
QString type = e.attribute("type");
|
2016-01-03 13:45:30 +00:00
|
|
|
//@TODO Compatibility for version older than N°4075, shape type was stored with an int
|
2015-07-27 19:25:54 +00:00
|
|
|
if (type.size() == 1)
|
|
|
|
{
|
|
|
|
switch(e.attribute("type","0").toInt())
|
|
|
|
{
|
|
|
|
case 0: m_shapeType = Line; break;
|
|
|
|
case 1: m_shapeType = Rectangle; break;
|
|
|
|
case 2: m_shapeType = Ellipse; break;
|
2015-07-27 21:47:41 +00:00
|
|
|
case 3: m_shapeType = Polygon; break;
|
2015-07-27 19:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//For version after N°4075, shape is stored with a string
|
|
|
|
else
|
|
|
|
{
|
2015-07-27 21:47:41 +00:00
|
|
|
QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("ShapeType"));
|
|
|
|
m_shapeType = QetShapeItem::ShapeType(me.keysToValue(type.toStdString().data()));
|
2015-07-27 19:25:54 +00:00
|
|
|
}
|
|
|
|
|
2015-07-27 21:47:41 +00:00
|
|
|
if (m_shapeType != Polygon)
|
2015-07-27 19:25:54 +00:00
|
|
|
{
|
2014-06-17 09:08:41 +00:00
|
|
|
m_P1.setX(e.attribute("x1", 0).toDouble());
|
|
|
|
m_P1.setY(e.attribute("y1", 0).toDouble());
|
|
|
|
m_P2.setX(e.attribute("x2", 0).toDouble());
|
|
|
|
m_P2.setY(e.attribute("y2", 0).toDouble());
|
|
|
|
}
|
2015-07-27 19:25:54 +00:00
|
|
|
else
|
|
|
|
foreach(QDomElement de, QET::findInDomElement(e, "points", "point"))
|
2014-06-17 09:08:41 +00:00
|
|
|
m_polygon << QPointF(de.attribute("x", 0).toDouble(), de.attribute("y", 0).toDouble());
|
2014-06-14 16:04:34 +00:00
|
|
|
|
2014-02-28 14:30:59 +00:00
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::toXml
|
|
|
|
* Save this item to xml element
|
|
|
|
* @param document parent document xml
|
|
|
|
* @return element xml where is write this item
|
|
|
|
*/
|
2015-07-13 12:01:02 +00:00
|
|
|
QDomElement QetShapeItem::toXml(QDomDocument &document) const
|
|
|
|
{
|
2014-02-28 14:30:59 +00:00
|
|
|
QDomElement result = document.createElement("shape");
|
|
|
|
|
2015-07-13 12:01:02 +00:00
|
|
|
//write some attribute
|
2015-07-27 21:47:41 +00:00
|
|
|
QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("ShapeType"));
|
|
|
|
result.setAttribute("type", me.valueToKey(m_shapeType));
|
2016-01-03 13:45:30 +00:00
|
|
|
result.appendChild(QETXML::penToXml(document, m_pen));
|
2016-01-12 14:02:34 +00:00
|
|
|
result.appendChild(QETXML::brushToXml(document, m_brush));
|
2014-11-13 11:04:34 +00:00
|
|
|
result.setAttribute("is_movable", bool(is_movable_));
|
2016-01-12 14:02:34 +00:00
|
|
|
result.setAttribute("closed", bool(m_close));
|
|
|
|
|
2015-07-27 21:47:41 +00:00
|
|
|
if (m_shapeType != Polygon)
|
2015-07-13 12:01:02 +00:00
|
|
|
{
|
|
|
|
result.setAttribute("x1", QString::number(mapToScene(m_P1).x()));
|
|
|
|
result.setAttribute("y1", QString::number(mapToScene(m_P1).y()));
|
|
|
|
result.setAttribute("x2", QString::number(mapToScene(m_P2).x()));
|
|
|
|
result.setAttribute("y2", QString::number(mapToScene(m_P2).y()));
|
2014-06-17 09:08:41 +00:00
|
|
|
}
|
2015-07-13 12:01:02 +00:00
|
|
|
else
|
|
|
|
{
|
2014-06-17 09:08:41 +00:00
|
|
|
QDomElement points = document.createElement("points");
|
2015-07-13 12:01:02 +00:00
|
|
|
foreach(QPointF p, m_polygon)
|
|
|
|
{
|
2014-06-17 09:08:41 +00:00
|
|
|
QDomElement point = document.createElement("point");
|
|
|
|
QPointF pf = mapToScene(p);
|
2016-10-17 19:41:44 +00:00
|
|
|
point.setAttribute("x", QString::number(pf.x()));
|
|
|
|
point.setAttribute("y", QString::number(pf.y()));
|
2014-06-17 09:08:41 +00:00
|
|
|
points.appendChild(point);
|
|
|
|
}
|
|
|
|
result.appendChild(points);
|
|
|
|
}
|
2014-02-28 14:30:59 +00:00
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
2014-03-07 08:05:25 +00:00
|
|
|
|
2014-06-14 16:04:34 +00:00
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::toDXF
|
|
|
|
* Draw this element to the dxf document
|
|
|
|
* @param filepath file path of the the dxf document
|
|
|
|
* @return true if draw success
|
|
|
|
*/
|
2015-07-27 09:20:38 +00:00
|
|
|
bool QetShapeItem::toDXF(const QString &filepath)
|
|
|
|
{
|
|
|
|
switch (m_shapeType)
|
|
|
|
{
|
|
|
|
case Line: Createdxf::drawLine (filepath, QLineF(mapToScene(m_P1), mapToScene(m_P2)), 0); return true;
|
|
|
|
case Rectangle: Createdxf::drawRectangle(filepath, QRectF(mapToScene(m_P1), mapToScene(m_P2)).normalized(), 0); return true;
|
|
|
|
case Ellipse: Createdxf::drawEllipse (filepath, QRectF(mapToScene(m_P1), mapToScene(m_P2)).normalized(), 0); return true;
|
|
|
|
default: return false;
|
2014-06-14 16:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::editProperty
|
|
|
|
* Edit the property of this item
|
|
|
|
*/
|
2014-03-07 08:05:25 +00:00
|
|
|
void QetShapeItem::editProperty()
|
|
|
|
{
|
|
|
|
if (diagram() -> isReadOnly()) return;
|
|
|
|
|
2015-06-23 20:40:05 +00:00
|
|
|
PropertiesEditorDialog ped(new ShapeGraphicsItemPropertiesWidget(this), diagram()->views().at(0));
|
|
|
|
ped.exec();
|
2014-03-07 08:05:25 +00:00
|
|
|
}
|
2014-10-11 17:45:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QetShapeItem::name
|
|
|
|
* @return the name of the curent shape.
|
|
|
|
*/
|
2015-07-27 09:20:38 +00:00
|
|
|
QString QetShapeItem::name() const {
|
|
|
|
switch (m_shapeType) {
|
|
|
|
case Line: return tr("une ligne");
|
|
|
|
case Rectangle: return tr("un rectangle");
|
|
|
|
case Ellipse: return tr("une éllipse");
|
2015-07-27 21:47:41 +00:00
|
|
|
case Polygon: return tr("une polyligne");
|
2015-07-27 09:20:38 +00:00
|
|
|
default: return tr("une shape");
|
2014-10-11 17:45:11 +00:00
|
|
|
}
|
|
|
|
}
|