QetShapeItem : add handler for modified the geometry of shapes in the diagram

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4039 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2015-07-09 18:33:14 +00:00
parent 7424cb8c38
commit eaf3d22d25
5 changed files with 375 additions and 29 deletions

View File

@@ -0,0 +1,5 @@
HEADERS += \
$$PWD/qetgraphicshandlerutility.h
SOURCES += \
$$PWD/qetgraphicshandlerutility.cpp

View File

@@ -0,0 +1,108 @@
/*
Copyright 2006-2015 The QElectroTech Team
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/>.
*/
#include "qetgraphicshandlerutility.h"
#include <QPixmapCache>
#include <QPainter>
#define QetGraphicsHandlerSquareSize 10
/**
* @brief QetGraphicsHandlerUtility::pixmapHandler
* @return The pixmap of an handler
*/
QPixmap QetGraphicsHandlerUtility::pixmapHandler()
{
QPixmap handler(QetGraphicsHandlerSquareSize, QetGraphicsHandlerSquareSize);
if (!QPixmapCache::find("QetGraphicsHandler", handler))
{ //Pixmap isn't store in the QPixmapCache, we create it
QColor inner(0xFF, 0xFF, 0xFF);
QColor outer(0x00, 0x61, 0xFF);
QPainter painter_(&handler);
painter_.setBrush(QBrush(inner));
QPen square_pen(QBrush(outer), 2.0, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
square_pen.setCosmetic(true);
painter_.setPen(square_pen);
painter_.drawRect(0,0,10,10);
//Store the pixmap in the QPixmapCache
QPixmapCache::insert("QetGraphicsHandler", handler);
}
return handler;
}
/**
* @brief QetGraphicsHandlerUtility::posForHandler
* Returns a QPointF at the good coordinates
* for draw the handler pixmap centered on the point to modify
* @param point : the point to modify
* @return : point at the good coordinates to draw handler centered in @point
*/
QPointF QetGraphicsHandlerUtility::posForHandler(const QPointF &point)
{
QPointF snap_point = point;
snap_point.rx() -= QetGraphicsHandlerSquareSize/2;
snap_point.ry() -= QetGraphicsHandlerSquareSize/2;
return snap_point;
}
/**
* @brief QetGraphicsHandlerUtility::pointIsInHandler
* @param point : point to compare
* @param key_point : point at the center of handler (the point to modify, for exemple the corner of a rectangle)
* @return true if point is in a handler. else false
*/
bool QetGraphicsHandlerUtility::pointIsInHandler(const QPointF &point, const QPointF &key_point)
{
QRectF handler (posForHandler(key_point), QSize(QetGraphicsHandlerSquareSize, QetGraphicsHandlerSquareSize));
return handler.contains(point);
}
/**
* @brief QetGraphicsHandlerUtility::pointIsHoverHandler
* @param point : point to compare
* @param vector : vector of key_point (the point to modify, for exemple the corners of a rectangle)
* @return if point is hover an handler, return the index of the hovered key_point in the vector, else return -1
*/
int QetGraphicsHandlerUtility::pointIsHoverHandler(const QPointF &point, const QVector<QPointF> &vector)
{
foreach (QPointF key_point, vector)
if (pointIsInHandler(point, key_point))
return vector.indexOf(key_point);
return -1;
}
/**
* @brief QetGraphicsHandlerUtility::handlerRect
* Return the rect of pixmap handler for all key_point in vector (the point to modify, for exemple the corners of a rectangle)
* The order of rect in the returned vector is the same as the given vector.
* @param vector
* @return
*/
QVector<QRectF> QetGraphicsHandlerUtility::handlerRect(const QVector<QPointF> &vector)
{
QVector <QRectF> rect_vector;
QSize size(QetGraphicsHandlerSquareSize, QetGraphicsHandlerSquareSize);
foreach(QPointF point, vector)
rect_vector << QRectF(posForHandler(point), size);
return rect_vector;
}

View File

@@ -0,0 +1,38 @@
/*
Copyright 2006-2015 The QElectroTech Team
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/>.
*/
#ifndef QETGRAPHICSHANDLERUTILITY_H
#define QETGRAPHICSHANDLERUTILITY_H
#include <QPixmap>
/**
* @brief The QetGraphicsHandlerUtility class
* This class provide some static methods to create and use handler for
* modify graphics shape like line rectangle etc...
*/
class QetGraphicsHandlerUtility
{
public:
static QPixmap pixmapHandler();
static QPointF posForHandler(const QPointF &point);
static bool pointIsInHandler (const QPointF &point, const QPointF &key_point);
static int pointIsHoverHandler (const QPointF &point, const QVector<QPointF> &vector);
static QVector<QRectF> handlerRect (const QVector<QPointF> &vector);
};
#endif // QETGRAPHICSHANDLERUTILITY_H

View File

@@ -21,7 +21,9 @@
#include "qet.h" #include "qet.h"
#include "shapegraphicsitempropertieswidget.h" #include "shapegraphicsitempropertieswidget.h"
#include "PropertiesEditor/propertieseditordialog.h" #include "PropertiesEditor/propertieseditordialog.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
typedef QetGraphicsHandlerUtility QGHU;
/** /**
* @brief QetShapeItem::QetShapeItem * @brief QetShapeItem::QetShapeItem
@@ -37,7 +39,8 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem
m_shapeStyle(Qt::DashLine), m_shapeStyle(Qt::DashLine),
m_P1 (Diagram::snapToGrid(p1)), m_P1 (Diagram::snapToGrid(p1)),
m_P2 (Diagram::snapToGrid(p2)), m_P2 (Diagram::snapToGrid(p2)),
m_hovered(false) m_hovered(false),
m_mouse_grab_handler(false)
{ {
if (type == Polyline) m_polygon << m_P1 << m_P2; if (type == Polyline) m_polygon << m_P1 << m_P2;
@@ -95,6 +98,39 @@ void QetShapeItem::setP2(QPointF P2) {
setTransformOriginPoint(boundingRect().center()); setTransformOriginPoint(boundingRect().center());
} }
/**
* @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
*/
bool QetShapeItem::setPolygon(const QPolygon &polygon)
{
if (Q_UNLIKELY(m_shapeType != Polyline)) return false;
prepareGeometryChange();
m_polygon = polygon;
return true;
}
/** /**
* @brief QetShapeItem::pointCount * @brief QetShapeItem::pointCount
* @return the number of point in the polygon * @return the number of point in the polygon
@@ -175,8 +211,26 @@ QPainterPath QetShapeItem::shape() const {
QPainterPathStroker pps; QPainterPathStroker pps;
pps.setWidth(10); pps.setWidth(10);
pps.setJoinStyle(Qt::RoundJoin); pps.setJoinStyle(Qt::RoundJoin);
path = pps.createStroke(path);
return (pps.createStroke(path)); if (isSelected())
{
QVector <QPointF> vector;
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;
foreach(QRectF r, QGHU::handlerRect(vector))
path.addRect(r);
}
return (path);
} }
/** /**
@@ -206,8 +260,9 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
painter -> setRenderHint(QPainter::Antialiasing, false); painter -> setRenderHint(QPainter::Antialiasing, false);
pen.setWidthF(1); pen.setWidthF(1);
//Draw hovered shadow
if (m_hovered) { if (m_hovered)
{
painter->save(); painter->save();
QColor color(Qt::darkBlue); QColor color(Qt::darkBlue);
color.setAlpha(25); color.setAlpha(25);
@@ -216,26 +271,54 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
painter -> drawPath (shape()); painter -> drawPath (shape());
painter -> restore (); painter -> restore ();
} }
else if (isSelected()) { //Draw red if selected
if (isSelected())
pen.setColor(Qt::red); pen.setColor(Qt::red);
}
painter -> setPen(pen); painter -> setPen(pen);
switch (m_shapeType) { //vector use to draw handler if needed
QVector <QPointF> point_vector;
//Draw the shape
switch (m_shapeType)
{
case Line: case Line:
painter->drawLine(QLineF(m_P1, m_P2)); painter->drawLine(QLineF(m_P1, m_P2));
if (isSelected())
point_vector << m_P1 << m_P2;
break; break;
case Rectangle: case Rectangle:
painter->drawRect(QRectF(m_P1, m_P2)); painter->drawRect(QRectF(m_P1, m_P2));
if (isSelected())
{
QRectF rect (m_P1, m_P2);
point_vector << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
}
break; break;
case Ellipse: case Ellipse:
painter->drawEllipse(QRectF(m_P1, m_P2)); painter->drawEllipse(QRectF(m_P1, m_P2));
if (isSelected())
{
QRectF rect (m_P1, m_P2);
point_vector << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
}
break; break;
case Polyline: case Polyline:
{
painter->drawPolyline(m_polygon); painter->drawPolyline(m_polygon);
point_vector = m_polygon;
}
break; break;
} }
//Draw handler if shape is selected
if (isSelected())
foreach(QPointF point, point_vector)
painter->drawPixmap(QGHU::posForHandler(point), QGHU::pixmapHandler());
} }
/** /**
@@ -262,6 +345,119 @@ void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
update(); update();
} }
/**
* @brief QetShapeItem::mousePressEvent
* Handle mouse press event
* @param event
*/
void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//Shape is selected, we see if user click in a handler
if (isSelected())
{
QVector <QPointF> vector;
switch (m_shapeType)
{
case Line:
vector << m_P1 << m_P2;
break;
case Rectangle: {
QRectF rect (m_P1, m_P2);
vector << rect.topLeft() << rect.topRight() << rect.bottomLeft() << rect.bottomRight();
}
break;
case Ellipse: {
QRectF rect (m_P1, m_P2);
vector << rect.topLeft() << rect.topRight() << rect.bottomLeft() << rect.bottomRight();
}
break;
case Polyline:
vector = m_polygon;
break;
}
m_vector_index = QGHU::pointIsHoverHandler(event->pos(), vector);
if (m_vector_index != -1)
{
//User click on an handler
m_mouse_grab_handler = true;
return;
}
}
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)
{
case Line: {
prepareGeometryChange();
m_vector_index == 0 ? m_P1 = new_pos : m_P2 = new_pos;
}
break;
case Rectangle: {
QRectF rect(m_P1, m_P2);
if (m_vector_index == 0) rect.setTopLeft(new_pos);
else if (m_vector_index == 1) rect.setTopRight(new_pos);
else if (m_vector_index == 2) rect.setBottomLeft(new_pos);
else if (m_vector_index == 3) rect.setBottomRight(new_pos);
setRect(rect);
}
break;
case Ellipse: {
QRectF rect(m_P1, m_P2);
if (m_vector_index == 0) rect.setTopLeft(new_pos);
else if (m_vector_index == 1) rect.setTopRight(new_pos);
else if (m_vector_index == 2) rect.setBottomLeft(new_pos);
else if (m_vector_index == 3) rect.setBottomRight(new_pos);
setRect(rect);
}
break;
case Polyline: {
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)
{
m_mouse_grab_handler = false;
QetGraphicsItem::mouseReleaseEvent(event);
}
/** /**
* @brief QetShapeItem::fromXml * @brief QetShapeItem::fromXml
* Build this item from the xml description * Build this item from the xml description
@@ -368,22 +564,14 @@ void QetShapeItem::editProperty()
* @brief QetShapeItem::name * @brief QetShapeItem::name
* @return the name of the curent shape. * @return the name of the curent shape.
*/ */
QString QetShapeItem::name() const { QString QetShapeItem::name() const
switch (m_shapeType) { {
case Line: switch (m_shapeType)
return tr("une ligne"); {
break; case Line: return tr("une ligne"); break;
case Rectangle: case Rectangle: return tr("un rectangle"); break;
return tr("un rectangle"); case Ellipse: return tr("une éllipse"); break;
break; case Polyline: return tr("une polyligne"); break;
case Ellipse: default: return tr("une shape"); break;
return tr("une éllipse");
break;
case Polyline:
return tr("une polyligne");
break;
default:
return tr("une shape");
break;
} }
} }

View File

@@ -62,6 +62,8 @@ class QetShapeItem : public QetGraphicsItem
virtual QString name() const; virtual QString name() const;
void setP2 (QPointF P2); void setP2 (QPointF P2);
bool setRect (const QRectF &rect);
bool setPolygon (const QPolygon &polygon);
//Methods available for polygon shape //Methods available for polygon shape
int pointsCount () const; int pointsCount () const;
@@ -75,6 +77,9 @@ class QetShapeItem : public QetGraphicsItem
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event); virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event);
virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
private: private:
void changeGraphicsItem (const ShapeType &newtype); void changeGraphicsItem (const ShapeType &newtype);
@@ -88,6 +93,8 @@ class QetShapeItem : public QetGraphicsItem
Qt::PenStyle m_shapeStyle; Qt::PenStyle m_shapeStyle;
QPointF m_P1, m_P2; QPointF m_P1, m_P2;
QPolygonF m_polygon; QPolygonF m_polygon;
bool m_hovered; bool m_hovered,
m_mouse_grab_handler;
int m_vector_index;
}; };
#endif // QETSHAPEITEM_H #endif // QETSHAPEITEM_H