Toatly revamp of the handlers use to modify primitves, shapes and conductors.

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5001 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
blacksun
2017-08-02 15:26:14 +00:00
parent 86cb13f74d
commit 618683d962
27 changed files with 2255 additions and 1307 deletions

View File

@@ -21,6 +21,3 @@ part terminal + 1106
part text + 1107
part text field + 1108
part rectangle + 1109
###QetGraphicsHandlerItem###
QetGraphicsHandlerItem = 1200

View File

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

View File

@@ -0,0 +1,99 @@
/*
Copyright 2006-2017 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 "qetgraphicshandleritem.h"
#include <QPainter>
#include <QDebug>
/**
* @brief QetGraphicsHandlerItem::QetGraphicsHandlerItem
* @param size, the size of the handler
*/
QetGraphicsHandlerItem::QetGraphicsHandlerItem(qreal size) :
m_size(size)
{}
/**
* @brief QetGraphicsHandlerItem::boundingRect
* @return
*/
QRectF QetGraphicsHandlerItem::boundingRect() const
{
qreal rect_size = m_size * m_previous_zoom_factor;
QRectF rect(0-rect_size/2, 0-rect_size/2, rect_size, rect_size);
rect.adjust(-2, -2, 2, 2);
return rect;
}
/**
* @brief QetGraphicsHandlerItem::setColor
* @param color, set the color of the handler
*/
void QetGraphicsHandlerItem::setColor(QColor color)
{
m_color = color;
update();
}
/**
* @brief QetGraphicsHandlerItem::paint
* @param painter
* @param option
* @param widget
*/
void QetGraphicsHandlerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
qreal zoom_factor = 1.0/painter->transform().m11();
if(zoom_factor != m_previous_zoom_factor)
{
prepareGeometryChange();
m_previous_zoom_factor = zoom_factor;
}
qreal rect_size = m_size * m_previous_zoom_factor;
QRectF rect(0-rect_size/2, 0-rect_size/2, rect_size, rect_size);
painter->save();
painter->setBrush(QBrush(m_color));
QPen pen(QBrush(m_color), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
pen.setCosmetic(true);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->drawEllipse(rect);
painter->restore();
}
/**
* @brief QetGraphicsHandlerItem::handlerForPoint
* @param points
* @return A list of handler with pos at point
*/
QVector<QetGraphicsHandlerItem *> QetGraphicsHandlerItem::handlerForPoint(const QVector<QPointF> &points, int size)
{
QVector <QetGraphicsHandlerItem *> list_;
for (QPointF point : points)
{
QetGraphicsHandlerItem *qghi = new QetGraphicsHandlerItem(size);
qghi->setPos(point);
list_ << qghi;
}
return list_;
}

View File

@@ -0,0 +1,53 @@
/*
Copyright 2006-2017 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 QETGRAPHICSHANDLERITEM_H
#define QETGRAPHICSHANDLERITEM_H
#include <QGraphicsItem>
/**
* @brief The QetGraphicsHandlerItem class
* This graphics item represents a point, destined to be used as an handler,
* for modifie the geometrie of a another graphics item (like shapes).
* The graphics item to be modified, must call "installSceneEventFilter" of this item with itself for argument,.
* The ghraphics item to be modified, need to reimplement "sceneEventFilter" for create the modification behavior.
*/
class QetGraphicsHandlerItem : public QGraphicsItem
{
public:
QetGraphicsHandlerItem(qreal size = 15);
virtual QRectF boundingRect() const;
enum { Type = UserType + 1200};
virtual int type() const {return Type;}
void setColor(QColor color);
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
qreal m_size,
m_previous_zoom_factor = 1;
QColor m_color;
public:
static QVector<QetGraphicsHandlerItem *> handlerForPoint(const QVector<QPointF> &points, int size = 15);
};
#endif // QETGRAPHICSHANDLERITEM_H

View File

@@ -16,111 +16,10 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qetgraphicshandlerutility.h"
#include <QPainter>
//#include <QVector>
//#include <QPointF>
#include <QPainterPath>
/**
* @brief QetGraphicsHandlerUtility::QetGraphicsHandlerUtility
* Constructor
* @param size : the size of the handler
*/
QetGraphicsHandlerUtility::QetGraphicsHandlerUtility(qreal size) :
m_size (size)
{}
/**
* @brief QetGraphicsHandlerUtility::drawHandler
* Draw the handler at pos @point, using the QPainter @painter.
* @param painter : painter to use for drawing the handler
* @param point : point to draw the handler
*/
void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QPointF &point)
{
//Setup the zoom factor to draw the handler in the same size at screen,
//no matter the zoom of the QPainter
m_zoom_factor = 1.0/painter->transform().m11();
painter->save();
painter->setBrush(QBrush(m_inner_color));
QPen square_pen(QBrush(m_outer_color), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
square_pen.setCosmetic(true);
painter->setPen(square_pen);
painter->drawRect(getRect(point));
painter->restore();
}
/**
* @brief QetGraphicsHandlerUtility::drawHandler
* Conveniance method for void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QPointF &point)
* @param painter
* @param points
* @param color2
*/
void QetGraphicsHandlerUtility::drawHandler(QPainter *painter, const QVector<QPointF> &points) {
foreach(QPointF point, points)
drawHandler(painter, 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) const {
return (getRect(key_point).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) const
{
foreach (QPointF key_point, vector)
if (pointIsInHandler(point, key_point))
return vector.indexOf(key_point);
return -1;
}
/**
* @brief QetGraphicsHandlerUtility::handlerRect
* Return the rect of the 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) const
{
QVector <QRectF> rect_vector;
foreach(QPointF point, vector)
rect_vector << getRect(point);
return rect_vector;
}
void QetGraphicsHandlerUtility::setInnerColor(QColor color) {
m_inner_color = color;
}
void QetGraphicsHandlerUtility::setOuterColor(QColor color) {
m_outer_color = color;
}
/**
* @brief QetGraphicsHandlerUtility::getRect
* @param point
* @return
*/
QRectF QetGraphicsHandlerUtility::getRect(const QPointF &point) const
{
qreal rect_size = m_size * m_zoom_factor;
QRectF rect(point.x() - rect_size/2, point.y() - rect_size/2, rect_size, rect_size);
return rect;
}
/**
* @brief QetGraphicsHandlerUtility::pointsForRect
@@ -169,7 +68,6 @@ QVector<QPointF> QetGraphicsHandlerUtility::pointsForLine(const QLineF &line) {
return (QVector<QPointF> {line.p1(), line.p2()});
}
#include <QDebug>
/**
* @brief QetGraphicsHandlerUtility::pointsForArc
* Return the points for the given arc.

View File

@@ -32,25 +32,6 @@ class QPainter;
*/
class QetGraphicsHandlerUtility
{
public:
QetGraphicsHandlerUtility (qreal size = 1);
void setSize(qreal size) {m_size = size;}
void drawHandler (QPainter *painter, const QPointF & point);
void drawHandler(QPainter *painter, const QVector<QPointF> &points);
QPointF posForHandler(const QPointF &point) const;
bool pointIsInHandler (const QPointF &point, const QPointF &key_point) const;
int pointIsHoverHandler (const QPointF &point, const QVector<QPointF> &vector) const;
QVector<QRectF> handlerRect (const QVector<QPointF> &vector) const;
void setInnerColor (QColor color);
void setOuterColor (QColor color);
private:
QRectF getRect (const QPointF &point) const;
qreal m_size;
qreal m_zoom_factor = 1;
QColor m_inner_color = Qt::white,
m_outer_color = Qt::blue;
public:
static QVector <QPointF> pointsForRect (const QRectF &rect);
static QVector <QPointF> pointsForLine (const QLineF &line);

View File

@@ -91,10 +91,7 @@ Diagram::Diagram(QETProject *project) :
* @brief Diagram::~Diagram
* Destructor
*/
Diagram::~Diagram()
{
//First clear every selection to close an hypothetical editor
clearSelection();
Diagram::~Diagram() {
// clear undo stack to prevent errors, because contains pointers to this diagram and is elements.
undoStack().clear();
//delete of QGIManager, every elements he knows are removed
@@ -106,15 +103,19 @@ Diagram::~Diagram()
delete elements_mover_;
delete element_texts_mover_;
if (m_event_interface)
delete m_event_interface;
if (m_event_interface) delete m_event_interface;
// list removable items
QList<QGraphicsItem *> deletable_items;
for(QGraphicsItem *qgi : items())
{
if (qgi -> parentItem()) continue;
if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
if (qgi->parentItem())
continue;
if (qgi->type() == Conductor::Type)
continue;
if (qgi->type() == QetGraphicsHandlerItem::Type)
continue;
deletable_items << qgi;
}
@@ -377,6 +378,8 @@ void Diagram::keyReleaseEvent(QKeyEvent *e)
* Diagram become the ownership of event_interface
* If there is a previous interface, they will be delete before
* and call init() to the new interface.
* The derivated class of DiagramEventInterface need to emit the signal "finish" when the job is done,
* diagram use this signal to delete the interface. If the signal isn't send, the interface will never be deleted.
* @param event_interface
*/
void Diagram::setEventInterface(DiagramEventInterface *event_interface)

View File

@@ -24,23 +24,24 @@
#include <QGraphicsSceneHoverEvent>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsScene>
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/**
Constructor
@param parent Parent QGraphicsItem
*/
ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent):
QGraphicsObject(parent),
m_handler(10)
QGraphicsObject(parent)
{
init();
m_handler.setOuterColor(Qt::darkGreen);
}
/**
Destructor
*/
ElementPrimitiveDecorator::~ElementPrimitiveDecorator() {
ElementPrimitiveDecorator::~ElementPrimitiveDecorator()
{
removeHandler();
}
/**
@@ -68,12 +69,7 @@ QRectF ElementPrimitiveDecorator::internalBoundingRect() const {
*/
QRectF ElementPrimitiveDecorator::boundingRect() const
{
QVector<QRectF> rect_vector = m_handler.handlerRect(getResizingsPoints());
QRectF rect = effective_bounding_rect_;
rect |= rect_vector.first();
rect |= rect_vector.last();
return(rect);
return effective_bounding_rect_;
}
/**
@@ -97,9 +93,6 @@ void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraph
painter -> setPen(pen);
painter -> drawRect(modified_bounding_rect_);
//Draw the handlers
m_handler.drawHandler(painter, getResizingsPoints());
// uncomment to draw the real bouding rect (=adjusted internal bounding rect)
// painter -> setBrush(QBrush(QColor(240, 0, 0, 127)));
// painter -> drawRect(boundingRect());
@@ -118,15 +111,19 @@ void ElementPrimitiveDecorator::setItems(const QList<CustomElementPart *> &items
if (focusItem() != this) {
setFocus();
}
adjusteHandlerPos();
}
/**
@param items the new list of items this decorator is suposed to manipulate.
*/
void ElementPrimitiveDecorator::setItems(const QList<QGraphicsItem *> &items) {
void ElementPrimitiveDecorator::setItems(const QList<QGraphicsItem *> &items)
{
QList<CustomElementPart *> primitives;
foreach (QGraphicsItem *item, items) {
if (CustomElementPart *part_item = dynamic_cast<CustomElementPart *>(item)) {
for(QGraphicsItem *item : items)
{
if (CustomElementPart *part_item = dynamic_cast<CustomElementPart *>(item))
{
primitives << part_item;
}
}
@@ -157,72 +154,31 @@ QList<QGraphicsItem *> ElementPrimitiveDecorator::graphicsItems() const {
Adjust the visual decorator according to the currently assigned items.
It is notably called by setItems().
*/
void ElementPrimitiveDecorator::adjust() {
void ElementPrimitiveDecorator::adjust()
{
saveOriginalBoundingRect();
modified_bounding_rect_ = original_bounding_rect_;
adjustEffectiveBoundingRect();
}
/**
Handle events generated when the mouse hovers over the decorator.
@param event Object describing the hover event.
*/
void ElementPrimitiveDecorator::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
int p = m_handler.pointIsHoverHandler(event->pos(), getResizingsPoints());
if (p == 0 || p == 7)
setCursor(Qt::SizeFDiagCursor);
else if (p == 2 || p == 5)
setCursor(Qt::SizeBDiagCursor);
else if (p == 1 || p ==6)
setCursor(Qt::SizeVerCursor);
else if (p == 3 || p == 4)
setCursor(Qt::SizeHorCursor);
else if (p == -1 && modified_bounding_rect_.normalized().contains(event->pos()))
setCursor(Qt::SizeAllCursor);
else
setCursor(Qt::ArrowCursor);
}
/**
Handle event generated when mouse buttons are pressed.
@param event Object describing the mouse event
*/
void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QPointF pos = event -> pos();
QVector <QPointF> points = getResizingsPoints();
current_operation_square_ = m_handler.pointIsHoverHandler(pos, points);
bool accept = false;
if (current_operation_square_ != QET::NoOperation)
accept = true;
else
{
if (internalBoundingRect().contains(pos))
if (internalBoundingRect().contains(event->pos()))
{
current_operation_square_ = QET::MoveArea;
accept = true;
}
}
if (accept)
{
if (current_operation_square_ > QET::NoOperation)
first_pos_ = latest_pos_ = mapToScene(points.at(current_operation_square_));
else
{
first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos();
latest_pos_ = event -> scenePos();
mouse_offset_ = event -> scenePos() - first_pos_;
}
startMovement();
event -> accept();
event->accept();
}
else
event -> ignore();
event->ignore();
}
/**
@@ -235,46 +191,12 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QPointF scene_pos = event -> scenePos();
QPointF movement = scene_pos - latest_pos_;
if (current_operation_square_ > QET::NoOperation) {
// This is a scaling operation.
// For convenience purposes, we may need to adjust mouse movements.
QET::ScalingMethod scaling_method = scalingMethod(event);
if (scaling_method > QET::FreeScaling) {
// real, non-rounded movement from the mouse press event
QPointF global_movement = scene_pos - first_pos_;
QPointF rounded_global_movement;
if (scaling_method == QET::SnapScalingPointToGrid) {
// real, rounded movement from the mouse press event
rounded_global_movement = snapConstPointToGrid(global_movement);
}
else {
QRectF new_bounding_rect = original_bounding_rect_;
applyMovementToRect(current_operation_square_, global_movement, new_bounding_rect);
const qreal scale_epsilon = 20.0; // rounds to 0.05
QPointF delta = deltaForRoundScaling(original_bounding_rect_, new_bounding_rect, scale_epsilon);
// real, rounded movement from the mouse press event
rounded_global_movement = global_movement + delta;
}
// rounded position of the current mouse move event
QPointF rounded_scene_pos = first_pos_ + rounded_global_movement;
// when scaling the selection, consider the center of the currently dragged resizing rectangle
QPointF current_position = mapToScene(getResizingsPoints().at(current_operation_square_));
// determine the final, effective movement
movement = rounded_scene_pos - current_position;
}
}
else if (current_operation_square_ == QET::MoveArea) {
if (current_operation_square_ == QET::MoveArea)
{
// When moving the selection, consider the position of the first selected item
QPointF current_position = scene_pos - mouse_offset_;
QPointF rounded_current_position = snapConstPointToGrid(current_position);
movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos();
}
QRectF bounding_rect = modified_bounding_rect_;
applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_);
@@ -282,12 +204,12 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
adjustEffectiveBoundingRect();
}
latest_pos_ = event -> scenePos();
if (current_operation_square_ == QET::MoveArea) {
translateItems(movement);
} else {
scaleItems(original_bounding_rect_, modified_bounding_rect_);
}
}
/**
@@ -296,31 +218,25 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
@param event Object describing the mouse event
@see QGraphicsScene::mouseGrabberItem()
*/
void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event)
ElementEditionCommand *command = 0;
if (current_operation_square_ > QET::NoOperation) {
ScalePartsCommand *scale_command = new ScalePartsCommand();
scale_command -> setScaledPrimitives(items());
scale_command -> setTransformation(
mapToScene(original_bounding_rect_).boundingRect(),
mapToScene(modified_bounding_rect_).boundingRect()
);
command = scale_command;
} else if (current_operation_square_ == QET::MoveArea) {
if (current_operation_square_ == QET::MoveArea)
{
QPointF movement = mapToScene(modified_bounding_rect_.topLeft()) - mapToScene(original_bounding_rect_.topLeft());
if (!movement.isNull()) {
if (!movement.isNull())
{
MovePartsCommand *move_command = new MovePartsCommand(movement, 0, graphicsItems());
command = move_command;
}
}
if (command) {
emit(actionFinished(command));
}
if (current_operation_square_ != QET::NoOperation) {
adjust();
}
@@ -376,7 +292,8 @@ void ElementPrimitiveDecorator::keyReleaseEvent(QKeyEvent *e) {
/**
Initialize an ElementPrimitiveDecorator
*/
void ElementPrimitiveDecorator::init() {
void ElementPrimitiveDecorator::init()
{
setFlag(QGraphicsItem::ItemIsFocusable, true);
grid_step_x_ = grid_step_y_ = 1;
setAcceptHoverEvents(true);
@@ -397,6 +314,7 @@ void ElementPrimitiveDecorator::adjustEffectiveBoundingRect() {
prepareGeometryChange();
effective_bounding_rect_ = modified_bounding_rect_ | effective_bounding_rect_;
update();
adjusteHandlerPos();
}
/**
@@ -528,6 +446,152 @@ QVector<QPointF> ElementPrimitiveDecorator::getResizingsPoints() const
return vector;
}
/**
* @brief ElementPrimitiveDecorator::adjusteHandlerPos
*/
void ElementPrimitiveDecorator::adjusteHandlerPos()
{
QVector <QPointF> points_vector = mapToScene(getResizingsPoints());
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
/**
* @brief ElementPrimitiveDecorator::handlerMousePressEvent
* @param qghi
* @param event
*/
void ElementPrimitiveDecorator::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event);
QVector <QPointF> points = getResizingsPoints();
current_operation_square_ = m_handler_vector.indexOf(qghi);
first_pos_ = latest_pos_ = mapToScene(points.at(current_operation_square_));
startMovement();
}
/**
* @brief ElementPrimitiveDecorator::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void ElementPrimitiveDecorator::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
QPointF scene_pos = event -> scenePos();
QPointF movement = scene_pos - latest_pos_;
// For convenience purposes, we may need to adjust mouse movements.
QET::ScalingMethod scaling_method = scalingMethod(event);
if (scaling_method > QET::FreeScaling)
{
// real, non-rounded movement from the mouse press event
QPointF global_movement = scene_pos - first_pos_;
QPointF rounded_global_movement;
if (scaling_method == QET::SnapScalingPointToGrid)
{
// real, rounded movement from the mouse press event
rounded_global_movement = snapConstPointToGrid(global_movement);
}
else
{
QRectF new_bounding_rect = original_bounding_rect_;
applyMovementToRect(current_operation_square_, global_movement, new_bounding_rect);
const qreal scale_epsilon = 20.0; // rounds to 0.05
QPointF delta = deltaForRoundScaling(original_bounding_rect_, new_bounding_rect, scale_epsilon);
// real, rounded movement from the mouse press event
rounded_global_movement = global_movement + delta;
}
// rounded position of the current mouse move event
QPointF rounded_scene_pos = first_pos_ + rounded_global_movement;
// when scaling the selection, consider the center of the currently dragged resizing rectangle
QPointF current_position = mapToScene(getResizingsPoints().at(current_operation_square_));
// determine the final, effective movement
movement = rounded_scene_pos - current_position;
}
QRectF bounding_rect = modified_bounding_rect_;
applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_);
if (modified_bounding_rect_ != bounding_rect) {
adjustEffectiveBoundingRect();
}
latest_pos_ = event -> scenePos();
scaleItems(original_bounding_rect_, modified_bounding_rect_);
}
/**
* @brief ElementPrimitiveDecorator::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void ElementPrimitiveDecorator::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
ElementEditionCommand *command = 0;
if (current_operation_square_ > QET::NoOperation)
{
ScalePartsCommand *scale_command = new ScalePartsCommand();
scale_command -> setScaledPrimitives(items());
scale_command -> setTransformation(
mapToScene(original_bounding_rect_).boundingRect(),
mapToScene(modified_bounding_rect_).boundingRect()
);
command = scale_command;
}
if (command) {
emit(actionFinished(command));
}
adjust();
current_operation_square_ = QET::NoOperation;
}
/**
* @brief ElementPrimitiveDecorator::addHandler
* Add handlers for this item
*/
void ElementPrimitiveDecorator::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapFromScene(getResizingsPoints()));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
scene()->addItem(handler);
handler->setColor(Qt::darkGreen);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief ElementPrimitiveDecorator::removeHandler
* Remove the handlers of this item
*/
void ElementPrimitiveDecorator::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}
/**
Receive two rects, assuming they share a common corner and current is a \a
scaled version of \a original.
@@ -597,3 +661,73 @@ QET::ScalingMethod ElementPrimitiveDecorator::scalingMethod(QGraphicsSceneMouseE
}
return QET::RoundScaleRatios;
}
/**
* @brief ElementPrimitiveDecorator::itemChange
* @param change
* @param value
* @return
*/
QVariant ElementPrimitiveDecorator::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSceneHasChanged)
{
if(scene()) //Item is added to scene, we also add handlers
addHandler();
else //Item is removed from scene, we also remove the handlers
removeHandler();
}
else if (change == ItemVisibleHasChanged)
{
bool visible = value.toBool();
for(QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setVisible(visible);
}
else if (change == ItemZValueHasChanged && !m_handler_vector.isEmpty())
{
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setZValue(this->zValue()+1);
}
return QGraphicsObject::itemChange(change, value);
}
/**
* @brief ElementPrimitiveDecorator::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool ElementPrimitiveDecorator::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}

View File

@@ -20,11 +20,11 @@
#include <QGraphicsObject>
#include "qet.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class ElementEditionCommand;
class ElementScene;
class CustomElementPart;
class QetGraphicsHandlerItem;
/**
This class represents a decorator rendered above selected items so users
@@ -64,7 +64,6 @@ class ElementPrimitiveDecorator : public QGraphicsObject
void actionFinished(ElementEditionCommand *);
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent *);
void mousePressEvent(QGraphicsSceneMouseEvent *);
void mouseMoveEvent(QGraphicsSceneMouseEvent *);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
@@ -75,6 +74,8 @@ class ElementPrimitiveDecorator : public QGraphicsObject
void snapPointToGrid(QPointF &) const;
bool mustSnapToGrid(QGraphicsSceneMouseEvent *);
QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void init();
@@ -88,8 +89,19 @@ class ElementPrimitiveDecorator : public QGraphicsObject
QRectF getSceneBoundingRect(QGraphicsItem *) const;
QVector <QPointF> getResizingsPoints() const;
// attributes
private:
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void addHandler();
void removeHandler();
QList<CustomElementPart *> decorated_items_;
QRectF effective_bounding_rect_; ///< actual, effective bounding rect -- never shrinks
QRectF original_bounding_rect_; ///< original bounding rect
@@ -107,7 +119,8 @@ class ElementPrimitiveDecorator : public QGraphicsObject
QPointF mouse_offset_; ///< Offset between the mouse position and the point to be snapped to grid when moving selection
bool moving_by_keys_; ///< Whether we are currently moving our decorated items using the arrow keys
QPointF keys_movement_; ///< Movement applied to our decorated items using the arrow keys
QetGraphicsHandlerUtility m_handler;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
int m_vector_index = -1;
};
#endif

View File

@@ -32,8 +32,9 @@
#include "nameslist.h"
#include "ui/elementpropertieseditorwidget.h"
#include "eseventinterface.h"
#include <algorithm>
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include <algorithm>
#include <QKeyEvent>
/**
@@ -524,27 +525,45 @@ QETElementEditor* ElementScene::editor() const {
}
/**
Selectionne une liste de parties
@param content liste des parties a selectionner
*/
void ElementScene::slot_select(const ElementContent &content) {
* @brief ElementScene::slot_select
* Select the item in content, every others items in the scene are deselected
* @param content
*/
void ElementScene::slot_select(const ElementContent &content)
{
blockSignals(true);
//Befor clear selection, we must to remove the handlers items in @content,
//because if in @content there are a selected item, but also its handlers items,
//When item is deselected, the item delete its handlers items,
//then handlers in content doesn't exist anymore and cause segfault
QList<QGraphicsItem*> items_list;
for (QGraphicsItem *qgi : content)
{
if(qgi->type() != QetGraphicsHandlerItem::Type)
items_list << qgi;
}
clearSelection();
foreach(QGraphicsItem *qgi, content) qgi -> setSelected(true);
foreach(QGraphicsItem *qgi, items_list)
qgi -> setSelected(true);
blockSignals(false);
emit(selectionChanged());
}
/**
Selectionne tout
*/
* @brief ElementScene::slot_selectAll
* Select all items
*/
void ElementScene::slot_selectAll() {
slot_select(items());
}
/**
Deselectionne tout
*/
* @brief ElementScene::slot_deselectAll
* deselect all item
*/
void ElementScene::slot_deselectAll() {
slot_select(ElementContent());
}
@@ -811,7 +830,15 @@ void ElementScene::reset()
clearSelection();
undoStack().clear();
foreach (QGraphicsItem *qgi, items())
//We don't add handlers, because it's the role of the primitive or decorator to remove it.
QList<QGraphicsItem*> items_list;
for (QGraphicsItem *qgi : items())
{
if(qgi->type() != QetGraphicsHandlerItem::Type)
items_list << qgi;
}
for (QGraphicsItem *qgi : items_list)
{
removeItem(qgi);
qgiManager().release(qgi);
@@ -1065,9 +1092,16 @@ void ElementScene::managePrimitivesGroups()
// should we hide the decorator?
QList<QGraphicsItem *> selected_items = zItems(ElementScene::Selected | ElementScene::IncludeTerminals);
if (selected_items.size() <= 1)
{
m_decorator -> hide();
}
else
{
for(QGraphicsItem *qgi : selected_items)
{
//We recall set selected, then every primitive will remove there handler because there are several item selected
qgi->setSelected(true);
}
m_decorator -> setZValue(1000000);
m_decorator -> setPos(0, 0);
m_decorator -> setItems(selected_items);

View File

@@ -82,7 +82,7 @@ class ElementScene : public QGraphicsScene
QETElementEditor *m_element_editor = nullptr;
/// Variables to manage the paste area on the scene
QGraphicsRectItem *m_paste_area = nullptr;
QGraphicsRectItem *m_paste_area;
QRectF m_defined_paste_area;
/// Variables to handle copy/paste with offset

View File

@@ -118,6 +118,7 @@ void AbstractPartEllipse::setRect(const QRectF &rect)
if (rect == m_rect) return;
prepareGeometryChange();
m_rect = rect;
emit rectChanged();
}

View File

@@ -20,6 +20,8 @@
#include "customelementgraphicpart.h"
class QetGraphicsHandlerItem;
/**
* @brief The AbstractPartEllipse class
* This is the base class for all ellipse based item like ellipse, circle, arc.
@@ -61,20 +63,21 @@ class AbstractPartEllipse : public CustomElementGraphicPart
virtual QPointF sceneTopLeft() const;
QRectF rect() const;
void setRect (const QRectF &rect);
virtual void setRect (const QRectF &rect);
virtual bool isUseless() const;
int startAngle() const {return m_start_angle;}
void setStartAngle (const int &start_angle);
virtual void setStartAngle (const int &start_angle);
int spanAngle () const {return m_span_angle;}
void setSpanAngle (const int &span_angle);
virtual void setSpanAngle (const int &span_angle);
protected:
QList<QPointF> saved_points_;
QRectF m_rect;
qreal m_start_angle;
qreal m_span_angle;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif // ABSTRACTPARTELLIPSE_H

View File

@@ -18,6 +18,8 @@
#include "partarc.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
/**
@@ -37,8 +39,10 @@ PartArc::PartArc(QETElementEditor *editor, QGraphicsItem *parent) :
* @brief PartArc::~PartArc
* Destructor
*/
PartArc::~PartArc() {
PartArc::~PartArc()
{
if(m_undo_command) delete m_undo_command;
removeHandler();
}
/**
@@ -82,15 +86,7 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
drawShadowShape(painter);
if (isSelected())
{
drawCross(m_rect.center(), painter);
if (scene()->selectedItems().size() == 1) {
if (m_resize_mode == 3)
m_handler.drawHandler(painter, m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16));
else
m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect));
}
}
}
/**
@@ -129,16 +125,6 @@ void PartArc::fromXml(const QDomElement &qde) {
m_span_angle = qde.attribute("angle", "-1440").toDouble() * 16;
}
QRectF PartArc::boundingRect() const
{
QRectF r = AbstractPartEllipse::boundingRect();
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
r |= rect;
return r;
}
/**
* @brief PartArc::shape
* @return the shape of this item
@@ -153,10 +139,6 @@ QPainterPath PartArc::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape;
}
@@ -172,68 +154,173 @@ QPainterPath PartArc::shadowShape() const
return (pps.createStroke(shape));
}
void PartArc::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
/**
* @brief PartArc::mouseReleaseEvent
* Handle mouse release event
* @param event
*/
void PartArc::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (!isSelected())
{
CustomElementGraphicPart::hoverMoveEvent(event);
return;
}
if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
if (m_resize_mode == 1 || m_resize_mode == 2) {
int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
if (handler >= 0)
{
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);
return;
}
}
else if (m_resize_mode == 3) {
if (m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16)) >= 0) {
setCursor(Qt::SizeAllCursor);
return;
}
}
CustomElementGraphicPart::hoverMoveEvent(event);
CustomElementGraphicPart::mouseReleaseEvent(event);
}
/**
* @brief PartArc::mousePressEvent
* Handle mouse press event
* @brief PartArc::itemChange
* @param change
* @param value
* @return
*/
QVariant PartArc::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged && scene())
{
if (value.toBool() == true)
{
//When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler,
//according to the number of selected items.
connect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged);
if (scene()->selectedItems().size() == 1)
addHandler();
}
else
{
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged);
removeHandler();
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneChange)
{
if(scene())
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartArc::sceneSelectionChanged);
setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed.
}
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief PartArc::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool PartArc::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief PartArc::switchResizeMode
*/
void PartArc::switchResizeMode()
{
if (m_resize_mode == 1)
{
m_resize_mode = 2;
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setColor(Qt::darkGreen);
}
else if (m_resize_mode == 2)
{
m_resize_mode = 3;
//From rect mode to angle mode, then numbers of handlers change
removeHandler();
addHandler();
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setColor(Qt::magenta);
}
else
{
m_resize_mode = 1;
//From angle mode to rect mode, then numbers of handlers change
removeHandler();
addHandler();
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setColor(Qt::blue);
}
}
/**
* @brief PartArc::adjusteHandlerPos
*/
void PartArc::adjusteHandlerPos()
{
if (m_handler_vector.isEmpty())
return;
QVector <QPointF> points_vector;
if(m_resize_mode == 3)
points_vector = QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16);
else
points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect);
if (m_handler_vector.size() == points_vector.size())
{
points_vector = mapToScene(points_vector);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief PartArc::handlerMousePressEvent
* @param qghi
* @param event
*/
void PartArc::mousePressEvent(QGraphicsSceneMouseEvent *event)
void PartArc::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
if (isSelected())
{
//resize rect
if (m_resize_mode == 1 || m_resize_mode == 2) {
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
Q_UNUSED(qghi);
Q_UNUSED(event);
if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler
if (m_resize_mode == 3) //Resize angle
{
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier un arc"));
m_undo_command->enableAnimation();
return;
}
}
//resize angle
if (m_resize_mode == 3) {
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16));
if (m_handler_index == 0) {
m_span_point = m_handler.pointsForArc(m_rect, m_start_angle /16, m_span_angle /16).at(1);
if (m_vector_index == 0)
{
m_span_point = QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle /16, m_span_angle /16).at(1);
m_undo_command = new QPropertyUndoCommand(this, "startAngle", QVariant(m_start_angle));
m_undo_command->setText(tr("Modifier un arc"));
@@ -242,125 +329,149 @@ void PartArc::mousePressEvent(QGraphicsSceneMouseEvent *event)
m_undo_command2 = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle), m_undo_command);
m_undo_command2->setText(tr("Modifier un arc"));
m_undo_command2->enableAnimation();
return;
}
else if (m_handler_index == 1) {
else if (m_vector_index == 1)
{
m_undo_command = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle));
m_undo_command->setText(tr("Modifier un arc"));
m_undo_command->enableAnimation();
return;
}
}
else //resize rect
{
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier un arc"));
m_undo_command->enableAnimation();
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
/**
* @brief PartArc::mouseMoveEvent
* Handle mouse move event
* @brief PartArc::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void PartArc::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void PartArc::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (m_resize_mode == 1 || m_resize_mode == 2) {
if (m_handler_index >= 0 && m_handler_index <= 7) {
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos()));
prepareGeometryChange();
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
if (m_resize_mode == 1)
setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index));
setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index));
else if (m_resize_mode == 2)
setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index));
else
setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index));
return;
}
}
else if (m_resize_mode == 3) {
if (m_handler_index == 0 || m_handler_index == 1) {
QLineF line(m_rect.center(), event->pos());
{
QLineF line(m_rect.center(), mapFromItem(qghi, event->pos()));
prepareGeometryChange();
if (m_handler_index == 0) {
if (m_vector_index == 0) {
setStartAngle(line.angle()*16);
setSpanAngle(line.angleTo(QLineF(m_rect.center(), m_span_point))*16);
}
else if (m_handler_index == 1) {
QLineF line2(m_rect.center(), m_handler.pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0));
else if (m_vector_index == 1) {
QLineF line2(m_rect.center(), QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0));
setSpanAngle (line2.angleTo(line)*16);
}
return;
}
}
CustomElementGraphicPart::mouseMoveEvent(event);
}
/**
* @brief PartArc::mouseReleaseEvent
* Handle mouse release event
* @brief PartArc::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void PartArc::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void PartArc::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
setCursor(Qt::OpenHandCursor);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
}
Q_UNUSED(qghi);
Q_UNUSED(event);
if (m_resize_mode == 1 || m_resize_mode == 2) {
if (m_handler_index >= 0 && m_handler_index <= 7) {
if (m_resize_mode == 3)
{
if (m_vector_index == 0)
{
m_undo_command->setNewValue(QVariant(m_start_angle));
m_undo_command2->setNewValue(QVariant(m_span_angle));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_undo_command2 = nullptr;
m_vector_index = -1;
}
else if (m_vector_index == 1)
{
m_undo_command->setNewValue(QVariant(m_span_angle));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_vector_index = -1;
}
}
else
{
if (!m_rect.isValid())
m_rect = m_rect.normalized();
m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
return;
m_vector_index = -1;
}
}
else if (m_resize_mode == 3) {
if (m_handler_index == 0) {
m_undo_command->setNewValue(QVariant(m_start_angle));
m_undo_command2->setNewValue(QVariant(m_span_angle));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_undo_command2 = nullptr;
m_handler_index = -1;
return;
}
else if (m_handler_index == 1) {
m_undo_command->setNewValue(QVariant(m_span_angle));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
return;
}
}
CustomElementGraphicPart::mouseReleaseEvent(event);
}
void PartArc::switchResizeMode()
/**
* @brief PartArc::sceneSelectionChanged
* When the scene selection change, if there are several primitive selected, we remove the handler of this item
*/
void PartArc::sceneSelectionChanged()
{
if (m_resize_mode == 1) {
m_resize_mode = 2;
m_handler.setOuterColor(Qt::darkGreen);
}
else if (m_resize_mode == 2 ) {
m_resize_mode = 3;
m_handler.setOuterColor(Qt::magenta);
}
else {
m_resize_mode = 1;
m_handler.setOuterColor(Qt::blue);
}
update();
if (this->isSelected() && scene()->selectedItems().size() == 1)
addHandler();
else
removeHandler();
}
/**
* @brief PartArc::addHandler
* Add handlers for this item
*/
void PartArc::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
if(m_resize_mode == 3)
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16)));
}
else
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect)));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
QColor color = Qt::blue;
if (m_resize_mode == 2)
color = Qt::darkGreen;
else if (m_resize_mode == 3)
color = Qt::magenta;
handler->setColor(color);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief PartArc::removeHandler
* Remove the handlers of this item
*/
void PartArc::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}

View File

@@ -19,9 +19,9 @@
#define PART_ARC_H
#include "abstractpartellipse.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/**
* @brief The PartArc class
@@ -54,25 +54,34 @@ class PartArc : public AbstractPartEllipse
virtual const QDomElement toXml (QDomDocument &) const;
virtual void fromXml (const QDomElement &);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual QPainterPath shadowShape() const;
virtual void setRect(const QRectF &rect) {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();}
virtual void setStartAngle(const int &start_angle) {AbstractPartEllipse::setStartAngle(start_angle); adjusteHandlerPos();}
virtual void setSpanAngle(const int &span_angle) {AbstractPartEllipse::setSpanAngle(span_angle); adjusteHandlerPos();}
protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void switchResizeMode();
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void sceneSelectionChanged ();
void addHandler();
void removeHandler();
private:
QetGraphicsHandlerUtility m_handler = 10;
int m_handler_index = -1;
QPropertyUndoCommand *m_undo_command = nullptr;
QPropertyUndoCommand *m_undo_command2 = nullptr;
int m_resize_mode = 1;
int m_resize_mode = 1,
m_vector_index = -1;
QPointF m_span_point;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif

View File

@@ -18,6 +18,8 @@
#include "partellipse.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
/**
* @brief PartEllipse::PartEllipse
@@ -27,8 +29,6 @@
*/
PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) :
AbstractPartEllipse(editor, parent),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr)
{}
@@ -36,8 +36,10 @@ PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) :
* @brief PartEllipse::~PartEllipse
* Destructor
*/
PartEllipse::~PartEllipse() {
PartEllipse::~PartEllipse()
{
if(m_undo_command) delete m_undo_command;
removeHandler();
}
/**
@@ -65,11 +67,7 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
drawShadowShape(painter);
if (isSelected())
{
drawCross(m_rect.center(), painter);
if (scene()->selectedItems().size() == 1)
m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect));
}
}
/**
@@ -125,16 +123,6 @@ void PartEllipse::fromXml(const QDomElement &qde)
QSizeF(width, height));
}
QRectF PartEllipse::boundingRect() const
{
QRectF r = AbstractPartEllipse::boundingRect();
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
r |= rect;
return r;
}
/**
* @brief PartEllipse::shape
* @return the shape of this item
@@ -148,10 +136,6 @@ QPainterPath PartEllipse::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape;
}
@@ -166,77 +150,6 @@ QPainterPath PartEllipse::shadowShape() const
return (pps.createStroke(shape));
}
void PartEllipse::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if (!isSelected())
{
CustomElementGraphicPart::hoverMoveEvent(event);
return;
}
int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
if (handler >= 0)
{
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
CustomElementGraphicPart::hoverMoveEvent(event);
}
/**
* @brief PartEllipse::mousePressEvent
* Handle mouse press event
* @param event
*/
void PartEllipse::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
if (isSelected())
{
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler
{
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier une ellipse"));
m_undo_command->enableAnimation();
return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
/**
* @brief PartEllipse::mouseMoveEvent
* Handle mouse move event
* @param event
*/
void PartEllipse::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(m_handler_index >= 0 && m_handler_index <= 7)
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos()));
prepareGeometryChange();
if (m_resize_mode == 1)
setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index));
else
setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index));
}
else
CustomElementGraphicPart::mouseMoveEvent(event);
}
/**
* @brief PartEllipse::mouseReleaseEvent
* Handle mouse release event
@@ -244,35 +157,225 @@ void PartEllipse::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/
void PartEllipse::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
setCursor(Qt::OpenHandCursor);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
}
if (m_handler_index >= 0 && m_handler_index <= 7)
CustomElementGraphicPart::mouseReleaseEvent(event);
}
/**
* @brief PartEllipse::itemChange
* @param change
* @param value
* @return
*/
QVariant PartEllipse::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged && scene())
{
if (!m_rect.isValid())
m_rect = m_rect.normalized();
if (value.toBool() == true)
{
//When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler,
//according to the number of selected items.
connect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged);
m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
if (scene()->selectedItems().size() == 1)
addHandler();
}
else
CustomElementGraphicPart::mouseReleaseEvent(event);
{
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged);
removeHandler();
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneChange)
{
if(scene())
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartEllipse::sceneSelectionChanged);
setSelected(false); //This item is removed from scene, then we deselect this, and so, the handlers is also removed.
}
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief PartEllipse::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool PartEllipse::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
void PartEllipse::switchResizeMode()
{
if (m_resize_mode == 1) {
if (m_resize_mode == 1)
{
m_resize_mode = 2;
m_handler.setOuterColor(Qt::darkGreen);
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setColor(Qt::darkGreen);
}
else {
else
{
m_resize_mode = 1;
m_handler.setOuterColor(Qt::blue);
for (QetGraphicsHandlerItem *qghi : m_handler_vector)
qghi->setColor(Qt::blue);
}
}
/**
* @brief PartEllipse::adjusteHandlerPos
*/
void PartEllipse::adjusteHandlerPos()
{
if (m_handler_vector.isEmpty())
return;
QVector <QPointF> points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect);
if (m_handler_vector.size() == points_vector.size())
{
points_vector = mapToScene(points_vector);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief PartEllipse::handlerMousePressEvent
* @param qghi
* @param event
*/
void PartEllipse::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier un rectangle"));
m_undo_command->enableAnimation();
return;
}
/**
* @brief PartEllipse::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void PartEllipse::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
if (m_resize_mode == 1)
setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index));
else
setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index));
adjusteHandlerPos();
}
/**
* @brief PartEllipse::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void PartEllipse::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_vector_index = -1;
}
/**
* @brief PartEllipse::sceneSelectionChanged
* When the scene selection change, if there are several primitive selected, we remove the handler of this item
*/
void PartEllipse::sceneSelectionChanged()
{
if (this->isSelected() && scene()->selectedItems().size() == 1)
addHandler();
else
removeHandler();
}
/**
* @brief PartEllipse::addHandler
* Add handlers for this item
*/
void PartEllipse::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect)));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
QColor color = Qt::blue;
if (m_resize_mode == 2)
color = Qt::darkGreen;
handler->setColor(color);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief PartEllipse::removeHandler
* Remove the handlers of this item
*/
void PartEllipse::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
update();
}

View File

@@ -19,7 +19,6 @@
#define PART_ELLIPSE_H
#include "abstractpartellipse.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand;
@@ -55,24 +54,29 @@ class PartEllipse : public AbstractPartEllipse
virtual QString xmlName() const { return(QString("ellipse")); }
virtual const QDomElement toXml (QDomDocument &) const;
virtual void fromXml (const QDomElement &);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual QPainterPath shadowShape() const;
virtual void setRect(const QRectF &rect) {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();}
protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void switchResizeMode();
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void sceneSelectionChanged ();
void addHandler();
void removeHandler();
private:
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
QPropertyUndoCommand *m_undo_command;
int m_resize_mode = 1;
int m_resize_mode = 1,
m_vector_index = -1;
};
#endif

View File

@@ -19,6 +19,7 @@
#include <cmath>
#include "elementscene.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/**
@@ -33,14 +34,16 @@ PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent) :
first_length(1.5),
second_end(Qet::None),
second_length(1.5),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr)
{}
/// Destructeur
PartLine::~PartLine() {
if(m_undo_command) delete m_undo_command;
PartLine::~PartLine()
{
if(m_undo_command)
delete m_undo_command;
removeHandler();
}
/**
@@ -90,9 +93,6 @@ void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
if (m_hovered)
drawShadowShape(painter);
if (isSelected() && scene()->selectedItems().size() == 1)
m_handler.drawHandler(painter, m_handler.pointsForLine(m_line));
painter->restore();
}
@@ -140,69 +140,206 @@ void PartLine::fromXml(const QDomElement &qde) {
}
/**
* @brief PartLine::mousePressEvent
* Handle mouse press event
* @brief PartLine::itemChange
* @param change
* @param value
* @return
*/
QVariant PartLine::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged && scene())
{
if (value.toBool() == true)
{
//When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler,
//according to the number of selected items.
connect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged);
if (scene()->selectedItems().size() == 1)
addHandler();
}
else
{
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged);
removeHandler();
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneChange)
{
if(scene())
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartLine::sceneSelectionChanged);
setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed.
}
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief PartLine::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool PartLine::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief PartLine::adjusteHandlerPos
* Adjust the position of the handler item
*/
void PartLine::adjusteHandlerPos()
{
if(m_handler_vector.isEmpty())
return;
QVector<QPointF> points_vector;
points_vector << m_line.p1() << m_line.p2();
if (m_handler_vector.size() == points_vector.size())
{
points_vector = mapToScene(points_vector);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief PartLine::handlerMousePressEvent
* @param qghi
* @param event
*/
void PartLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
void PartLine::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
Q_UNUSED(qghi);
Q_UNUSED(event);
if (isSelected())
{
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForLine(m_line));
if(m_handler_index >= 0 && m_handler_index <= 1) //User click on an handler
{
m_undo_command = new QPropertyUndoCommand(this, "line", QVariant(m_line));
m_undo_command->setText(tr("Modifier une ligne"));
m_undo_command->enableAnimation();
return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
/**
* @brief PartLine::mouseMoveEvent
* Handle pouse move event
* @brief PartLine::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void PartLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void PartLine::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if(m_handler_index >= 0 && m_handler_index <= 1)
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos()));
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
prepareGeometryChange();
setLine(m_handler.lineForPosAtIndex(m_line, pos_, m_handler_index));
}
if (m_vector_index == 0)
m_line.setP1(new_pos);
else
CustomElementGraphicPart::mouseMoveEvent(event);
m_line.setP2(new_pos);
adjusteHandlerPos();
}
/**
* @brief PartLine::mouseReleaseEvent
* Handle mouse release event
* @brief PartLine::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void PartLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void PartLine::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
setCursor(Qt::OpenHandCursor);
Q_UNUSED(qghi);
Q_UNUSED(event);
if (m_handler_index >= 0 && m_handler_index <= 1)
{
m_undo_command->setNewValue(QVariant(m_line));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
}
m_vector_index = -1;
}
/**
* @brief PartLine::sceneSelectionChanged
* When the scene selection change, if there are several primitive selected, we remove the handler of this item
*/
void PartLine::sceneSelectionChanged()
{
if (this->isSelected() && scene()->selectedItems().size() == 1)
addHandler();
else
CustomElementGraphicPart::mouseReleaseEvent(event);
removeHandler();
}
/**
* @brief PartLine::addHandler
* Add handlers for this item
*/
void PartLine::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
QVector<QPointF> points_vector;
points_vector << m_line.p1() << m_line.p2();
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(points_vector));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
handler->setColor(Qt::blue);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief PartLine::removeHandler
* Remove the handlers of this item
*/
void PartLine::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}
/**
@@ -243,10 +380,6 @@ QPainterPath PartLine::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line)))
shape.addRect(rect);
return shape;
}
@@ -402,9 +535,6 @@ QRectF PartLine::boundingRect() const
bound = bound.normalized();
bound.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line)))
bound |= rect;
return bound;
}
@@ -496,6 +626,7 @@ void PartLine::setLine(const QLineF &line)
if (m_line == line) return;
prepareGeometryChange();
m_line = line;
adjusteHandlerPos();
emit lineChanged();
}
@@ -533,20 +664,6 @@ void PartLine::setSecondEndLength(const qreal &l)
emit secondEndLengthChanged();
}
void PartLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if (!isSelected())
{
CustomElementGraphicPart::hoverMoveEvent(event);
return;
}
if (m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForLine(m_line)) >= 0)
setCursor(Qt::SizeAllCursor);
else
CustomElementGraphicPart::hoverMoveEvent(event);
}
/**
* @brief PartLine::path
* @return this line has a QPainterPath.

View File

@@ -20,9 +20,9 @@
#include "customelementgraphicpart.h"
#include "qet.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/**
This class represents a line primitive which may be used to compose the
@@ -96,19 +96,26 @@ class PartLine : public CustomElementGraphicPart
void setSecondEndLength(const qreal &l);
protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
QPainterPath path() const;
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void sceneSelectionChanged ();
void addHandler();
void removeHandler();
QPainterPath path() const;
QList<QPointF> fourShapePoints() const;
QRectF firstEndCircleRect() const;
QRectF secondEndCircleRect() const;
void debugPaint(QPainter *);
/*****************/
Qet::EndType first_end;
qreal first_length;
@@ -116,8 +123,8 @@ class PartLine : public CustomElementGraphicPart
qreal second_length;
QList<QPointF> saved_points_;
QLineF m_line;
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
int m_vector_index = -1;
QPropertyUndoCommand *m_undo_command;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif

View File

@@ -18,6 +18,7 @@
#include "partpolygon.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/**
@@ -29,16 +30,16 @@
PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent) :
CustomElementGraphicPart(editor, parent),
m_closed(false),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr)
{}
/**
* @brief PartPolygon::~PartPolygon
*/
PartPolygon::~PartPolygon() {
PartPolygon::~PartPolygon()
{
if(m_undo_command) delete m_undo_command;
removeHandler();
}
/**
@@ -64,9 +65,6 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
if (m_hovered)
drawShadowShape(painter);
if (isSelected() && scene()->selectedItems().size() == 1)
m_handler.drawHandler(painter, m_polygon);
}
/**
@@ -199,6 +197,7 @@ void PartPolygon::setPolygon(const QPolygonF &polygon)
if (m_polygon == polygon) return;
prepareGeometryChange();
m_polygon = polygon;
adjusteHandlerPos();
emit polygonChanged();
}
@@ -248,83 +247,195 @@ void PartPolygon::setClosed(bool close)
emit closedChange();
}
void PartPolygon::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
/**
* @brief PartPolygon::itemChange
* @param change
* @param value
* @return
*/
QVariant PartPolygon::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (!isSelected())
if (change == ItemSelectedHasChanged && scene())
{
CustomElementGraphicPart::hoverMoveEvent(event);
return;
if (value.toBool() == true)
{
//When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler,
//according to the number of selected items.
connect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged);
if (scene()->selectedItems().size() == 1)
addHandler();
}
else
{
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged);
removeHandler();
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneChange)
{
if(scene())
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartPolygon::sceneSelectionChanged);
setSelected(false); //This is item removed from scene, then we deselect this, and so, the handlers is also removed.
}
if (m_handler.pointIsHoverHandler(event->pos(), m_polygon) >= 0)
setCursor(Qt::SizeAllCursor);
else
CustomElementGraphicPart::hoverMoveEvent(event);
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief PartPolygon::mousePressEvent
* Handle mouse press event
* @brief PartPolygon::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool PartPolygon::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief PartPolygon::adjusteHandlerPos
*/
void PartPolygon::adjusteHandlerPos()
{
if(m_handler_vector.isEmpty())
return;
if (m_handler_vector.size() == m_polygon.size())
{
QVector <QPointF> points_vector = mapToScene(m_polygon);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief PartPolygon::handlerMousePressEvent
* @param qghi
* @param event
*/
void PartPolygon::mousePressEvent(QGraphicsSceneMouseEvent *event)
void PartPolygon::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
if(isSelected())
{
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_polygon);
Q_UNUSED(qghi);
Q_UNUSED(event);
if(m_handler_index >= 0) //User click on an handler
{
m_undo_command = new QPropertyUndoCommand(this, "polygon", QVariant(m_polygon));
m_undo_command->setText(tr("Modifier un polygone"));
return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
/**
* @brief PartPolygon::mouseMoveEvent
* Handle mouse move event
* @brief PartPolygon::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void PartPolygon::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void PartPolygon::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if(m_handler_index >= 0)
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos()));
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
prepareGeometryChange();
m_polygon.replace(m_handler_index, pos_);
m_polygon.replace(m_vector_index, new_pos);
adjusteHandlerPos();
emit polygonChanged();
}
else
CustomElementGraphicPart::mouseMoveEvent(event);
}
/**
* @brief PartPolygon::mouseReleaseEvent
* Handle mouse release event
* @brief PartPolygon::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void PartPolygon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void PartPolygon::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
setCursor(Qt::OpenHandCursor);
Q_UNUSED(qghi);
Q_UNUSED(event);
if (m_handler_index >= 0)
{
m_undo_command->setNewValue(QVariant(m_polygon));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
}
m_vector_index = -1;
}
/**
* @brief PartPolygon::sceneSelectionChanged
* When the scene selection change, if there are several primitive selected, we remove the handler of this item
*/
void PartPolygon::sceneSelectionChanged()
{
if (this->isSelected() && scene()->selectedItems().size() == 1)
addHandler();
else
CustomElementGraphicPart::mouseReleaseEvent(event);
removeHandler();
}
/**
* @brief PartPolygon::addHandler
* Add handlers for this item
*/
void PartPolygon::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(m_polygon));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
handler->setColor(Qt::blue);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief PartPolygon::removeHandler
* Remove the handlers of this item
*/
void PartPolygon::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}
/**
@@ -343,10 +454,6 @@ QPainterPath PartPolygon::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_polygon))
shape.addRect(rect);
return shape;
}
@@ -379,8 +486,5 @@ QRectF PartPolygon::boundingRect() const
r.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_polygon))
r |=rect;
return(r);
}

View File

@@ -20,10 +20,9 @@
#include <QPolygonF>
#include "customelementgraphicpart.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/**
* @brief The PartPolygon class
@@ -85,17 +84,25 @@ class PartPolygon : public CustomElementGraphicPart
void setClosed (bool close);
protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void sceneSelectionChanged ();
void addHandler();
void removeHandler();
bool m_closed;
QList<QPointF> saved_points_;
QPolygonF m_polygon;
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
QPropertyUndoCommand *m_undo_command;
int m_vector_index = -1;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif

View File

@@ -18,6 +18,8 @@
#include "partrectangle.h"
#include "elementscene.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
/**
* @brief PartRectangle::PartRectangle
@@ -27,16 +29,16 @@
*/
PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent) :
CustomElementGraphicPart(editor, parent),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr)
{}
/**
* @brief PartRectangle::~PartRectangle
*/
PartRectangle::~PartRectangle() {
PartRectangle::~PartRectangle()
{
if(m_undo_command) delete m_undo_command;
removeHandler();
}
/**
@@ -69,11 +71,7 @@ void PartRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
drawShadowShape(painter);
if (isSelected())
{
drawCross(m_rect.center(), painter);
if (scene()->selectedItems().size() == 1)
m_handler.drawHandler(painter, m_handler.pointsForRect(m_rect));
}
}
/**
@@ -129,6 +127,7 @@ void PartRectangle::setRect(const QRectF &rect)
if (rect == m_rect) return;
prepareGeometryChange();
m_rect = rect;
adjusteHandlerPos();
emit rectChanged();
}
@@ -164,10 +163,6 @@ QPainterPath PartRectangle::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape;
}
@@ -196,9 +191,6 @@ QRectF PartRectangle::boundingRect() const
QRectF r = m_rect.normalized();
r.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
r |= rect;
return(r);
}
@@ -237,77 +229,6 @@ void PartRectangle::handleUserTransformation(const QRectF &initial_selection_rec
setRect(QRectF(mapFromScene(mapped_points.at(0)), mapFromScene(mapped_points.at(1))));
}
void PartRectangle::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if (!isSelected())
{
CustomElementGraphicPart::hoverMoveEvent(event);
return;
}
int handler = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
if (handler >= 0)
{
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
CustomElementGraphicPart::hoverMoveEvent(event);
}
/**
* @brief PartRectangle::mousePressEvent
* Handle mouse press event
* @param event
*/
void PartRectangle::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
if(isSelected())
{
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_handler.pointsForRect(m_rect));
if(m_handler_index >= 0 && m_handler_index <= 7) //User click on an handler
{
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier un rectangle"));
m_undo_command->enableAnimation();
return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
}
/**
* @brief PartRectangle::mouseMoveEvent
* Handle mouse press event
* @param event
*/
void PartRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(m_handler_index >= 0 && m_handler_index <= 7)
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos()));
prepareGeometryChange();
if (m_resize_mode == 1)
setRect(m_handler.rectForPosAtIndex(m_rect, pos_, m_handler_index));
else
setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index));
}
else
CustomElementGraphicPart::mouseMoveEvent(event);
}
/**
* @brief PartRectangle::mouseReleaseEvent
* Handle mouse release event
@@ -315,35 +236,223 @@ void PartRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/
void PartRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
setCursor(Qt::OpenHandCursor);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
CustomElementGraphicPart::mouseReleaseEvent(event);
}
/**
* @brief PartRectangle::itemChange
* @param change
* @param value
* @return
*/
QVariant PartRectangle::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged && scene())
{
if (value.toBool() == true)
{
//When item is selected, he must to be up to date whene the selection in the scene change, for display or not the handler,
//according to the number of selected items.
connect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged);
if (scene()->selectedItems().size() == 1)
addHandler();
}
else
{
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged);
removeHandler();
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneChange)
{
if(scene())
disconnect(scene(), &QGraphicsScene::selectionChanged, this, &PartRectangle::sceneSelectionChanged);
setSelected(false); //This item is removed from scene, then we deselect this, and so, the handlers is also removed.
}
if (m_handler_index >= 0 && m_handler_index <= 7)
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief PartRectangle::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool PartRectangle::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
if (!m_rect.isValid())
m_rect = m_rect.normalized();
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief PartRectangle::switchResizeMode
*/
void PartRectangle::switchResizeMode()
{
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);
}
}
/**
* @brief PartRectangle::adjusteHandlerPos
*/
void PartRectangle::adjusteHandlerPos()
{
if (m_handler_vector.isEmpty())
return;
QVector <QPointF> points_vector = QetGraphicsHandlerUtility::pointsForRect(m_rect);
if (m_handler_vector.size() == points_vector.size())
{
points_vector = mapToScene(points_vector);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief PartRectangle::handlerMousePressEvent
* @param qghi
* @param event
*/
void PartRectangle::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
m_undo_command = new QPropertyUndoCommand(this, "rect", QVariant(m_rect));
m_undo_command->setText(tr("Modifier un rectangle"));
m_undo_command->enableAnimation();
return;
}
/**
* @brief PartRectangle::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void PartRectangle::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
if (m_resize_mode == 1)
setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(m_rect, new_pos, m_vector_index));
else
setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(m_rect, new_pos, m_vector_index));
adjusteHandlerPos();
}
void PartRectangle::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr;
m_handler_index = -1;
}
else
CustomElementGraphicPart::mouseReleaseEvent(event);
m_vector_index = -1;
}
void PartRectangle::switchResizeMode()
/**
* @brief PartRectangle::sceneSelectionChanged
* When the scene selection change, if there are several primitive selected, we remove the handler of this item
*/
void PartRectangle::sceneSelectionChanged()
{
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();
if (this->isSelected() && scene()->selectedItems().size() == 1)
addHandler();
else
removeHandler();
}
/**
* @brief PartRectangle::addHandler
* Add handlers for this item
*/
void PartRectangle::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(QetGraphicsHandlerUtility::pointsForRect(m_rect)));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
QColor color = Qt::blue;
if (m_resize_mode == 2)
color = Qt::darkGreen;
handler->setColor(color);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief PartRectangle::removeHandler
* Remove the handlers of this item
*/
void PartRectangle::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}

View File

@@ -19,9 +19,9 @@
#define PART_RECTANGLE_H
#include "customelementgraphicpart.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/**
* This class represents a rectangle primitive which may be used to compose the
@@ -75,20 +75,27 @@ class PartRectangle : public CustomElementGraphicPart
virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void switchResizeMode();
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void sceneSelectionChanged ();
void addHandler();
void removeHandler();
private:
QRectF m_rect;
QList<QPointF> saved_points_;
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
QPropertyUndoCommand *m_undo_command;
int m_resize_mode = 1;
int m_resize_mode = 1,
m_vector_index = -1;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif

View File

@@ -78,17 +78,16 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
terminal1(p1),
terminal2(p2),
m_mouse_over(false),
m_handler(10),
m_text_item(0),
segments(NULL),
moving_segment(false),
m_moving_segment(false),
modified_path(false),
has_to_save_profile(false),
must_highlight_(Conductor::None)
{
//set Zvalue at 11 to be upper than the DiagramImageItem and element
setZValue(11);
previous_z_value = zValue();
m_previous_z_value = zValue();
//Add this conductor to the list of conductor of each of the two terminal
bool ajout_p1 = terminal1 -> addConductor(this);
@@ -117,7 +116,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
//Generate the path of this conductor.
generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
setFlags(QGraphicsItem::ItemIsSelectable);
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsScenePositionChanges);
setAcceptHoverEvents(true);
// Add the text field
@@ -137,6 +136,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
*/
Conductor::~Conductor()
{
removeHandler();
terminal1->removeConductor(this);
terminal2->removeConductor(this);
deleteSegments();
@@ -171,30 +171,39 @@ void Conductor::updatePath(const QRectF &rect) {
}
/**
Genere le QPainterPath a partir de la liste des points
*/
void Conductor::segmentsToPath() {
// chemin qui sera dessine
* @brief Conductor::segmentsToPath
* Generate the QPainterPath from the list of points
*/
void Conductor::segmentsToPath()
{
QPainterPath path;
// s'il n'y a pa des segments, on arrete la
if (segments == NULL) setPath(path);
if (segments == NULL)
setPath(path);
// demarre le chemin
//Start the path
path.moveTo(segments -> firstPoint());
// parcourt les segments pour dessiner le chemin
//Each segments
ConductorSegment *segment = segments;
while(segment -> hasNextSegment()) {
path.lineTo(segment -> secondPoint());
segment = segment -> nextSegment();
}
// termine le chemin
//Finish the path
path.lineTo(segment -> secondPoint());
// affecte le chemin au conducteur
setPath(path);
//If conductor is selected and he's not being modified
//we update the position of the handlers
if (isSelected() && !m_moving_segment)
{
if(handlerPoints().size() == m_handler_vector.size())
adjusteHandlerPos();
else
removeHandler();
addHandler();
}
}
/**
@@ -456,12 +465,11 @@ QPointF Conductor::extendTerminal(const QPointF &terminal, Qet::Orientation term
}
/**
* @brief Conductor::paint
* Draw the conductor
* @param qp
* @param options
* @param qw
*/
Dessine le conducteur sans antialiasing.
@param qp Le QPainter a utiliser pour dessiner le conducteur
@param options Les options de style pour le conducteur
@param qw Le QWidget sur lequel on dessine
*/
void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWidget *qw)
{
Q_UNUSED(qw);
@@ -501,7 +509,7 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
final_conductor_pen.setCosmetic(true);
}
qp->setPen(final_conductor_pen);
qp -> setPen(final_conductor_pen);
//Draw the conductor
qp -> drawPath(path());
@@ -529,23 +537,18 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
if (isSelected()) qp -> setBrush(Qt::NoBrush);
}
//Draw the squares used to modify the path of conductor when he is selected
if (isSelected())
m_handler.drawHandler(qp, handlerPoints());
//Draw the junctions
const QList<QPointF> junctions_list = junctions();
if (!junctions_list.isEmpty())
{
QList<QPointF> junctions_list = junctions();
if (!junctions_list.isEmpty()) {
final_conductor_pen.setStyle(Qt::SolidLine);
QBrush junction_brush(final_conductor_color, Qt::SolidPattern);
qp -> setPen(final_conductor_pen);
qp -> setBrush(junction_brush);
qp -> setRenderHint(QPainter::Antialiasing, true);
for(QPointF point : junctions_list)
foreach(QPointF point, junctions_list) {
qp -> drawEllipse(QRectF(point.x() - 1.5, point.y() - 1.5, 3.0, 3.0));
}
}
qp -> restore();
}
@@ -603,70 +606,18 @@ void Conductor::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
*/
void Conductor::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//Left clic
if (event->buttons() & Qt::LeftButton)
{
//If user click on a handler (square used to modify the path of conductor),
//we get the segment corresponding to the handler
int index = m_handler.pointIsHoverHandler(event->pos(), handlerPoints());
if (index > -1)
{
moving_segment = true;
moved_segment = segmentsList().at(index+1);
before_mov_text_pos_ = m_text_item -> pos();
}
}
QGraphicsPathItem::mousePressEvent(event);
if (event -> modifiers() & Qt::ControlModifier)
if (event->modifiers() & Qt::ControlModifier)
setSelected(!isSelected());
}
/**
* @brief Conductor::mouseMoveEvent
* Manage the mouse move event
* @param event
*/
void Conductor::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
//Left clic
if ((event->buttons() & Qt::LeftButton) && moving_segment)
{
//Snap the mouse pos to grid
QPointF pos_ = Diagram::snapToGrid(event->pos());
//Position of the last point
QPointF p = moved_segment -> middle();
//Calcul the movement
moved_segment -> moveX(pos_.x() - p.x());
moved_segment -> moveY(pos_.y() - p.y());
//Apply the movement
modified_path = true;
has_to_save_profile = true;
segmentsToPath();
calculateTextItemPosition();
}
QGraphicsPathItem::mouseMoveEvent(event);
}
/**
* @brief Conductor::mouseReleaseEvent
* Manage the mouse release event
* @param event
*/
void Conductor::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
moving_segment = false;
if (has_to_save_profile)
{
saveProfile();
has_to_save_profile = false;
}
if (!(event -> modifiers() & Qt::ControlModifier))
QGraphicsPathItem::mouseReleaseEvent(event);
}
@@ -694,56 +645,209 @@ void Conductor::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
}
/**
* @brief Conductor::hoverMoveEvent conductor
* @param e QGraphicsSceneHoverEvent describing the event
* @brief Conductor::itemChange
* @param change
* @param value
* @return
*/
void Conductor::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (isSelected())
if (change == QGraphicsItem::ItemSelectedChange)
{
//If user hover an handler (square used to modify the path of conductor),
//we get the segment corresponding to the handler
int index = m_handler.pointIsHoverHandler(event->pos(), handlerPoints());
if (index > -1)
if (value.toBool())
{
ConductorSegment *segment_ = segmentsList().at(index+1);
if (m_handler.pointIsInHandler(event->pos(), segment_->secondPoint()))
setCursor(Qt::ForbiddenCursor);
else if (m_handler.pointIsInHandler(event->pos(), segment_->middle()))
setCursor(segmentsList().at(index+1)->isVertical() ? Qt::SplitHCursor : Qt::SplitVCursor);
m_previous_z_value = zValue();
setZValue(qAbs(m_previous_z_value) + 10000);
addHandler();
}
else
setCursor(Qt::ArrowCursor);
{
setZValue(m_previous_z_value);
removeHandler();
}
}
else if (change == QGraphicsItem::ItemSceneHasChanged)
{
calculateTextItemPosition();
if(!scene())
removeHandler();
else if (scene() && isSelected())
addHandler();
}
else if (change == QGraphicsItem::ItemVisibleHasChanged) {
calculateTextItemPosition();
}
else if (change == QGraphicsItem::ItemPositionHasChanged && isSelected()) {
adjusteHandlerPos();
}
QGraphicsPathItem::hoverMoveEvent(event);
return(QGraphicsPathItem::itemChange(change, value));
}
/**
Gere les changements relatifs au conducteur
Reimplemente ici pour :
* positionner le conducteur en avant-plan lorsqu'il est selectionne
@param change Type de changement
@param value Valeur relative au changement
*/
QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == QGraphicsItem::ItemSelectedChange) {
if (value.toBool()) {
// le conducteur vient de se faire selectionner
previous_z_value = zValue();
setZValue(qAbs(previous_z_value) + 10000);
} else {
// le conducteur vient de se faire deselectionner
setZValue(previous_z_value);
* @brief Conductor::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool Conductor::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
} else if (change == QGraphicsItem::ItemSceneHasChanged) {
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema
calculateTextItemPosition();
} else if (change == QGraphicsItem::ItemVisibleHasChanged) {
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema
calculateTextItemPosition();
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief Conductor::adjusteHandlerPos
* Adjust the position of the handler item
*/
void Conductor::adjusteHandlerPos()
{
if (m_handler_vector.isEmpty())
return;
if (m_handler_vector.size() == handlerPoints().size())
{
QVector <QPointF> points_vector = mapToScene(handlerPoints());
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief Conductor::handlerMousePressEvent
* @param qghi
* @param event
*/
void Conductor::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event);
//we get the segment corresponding to the handler
if (m_vector_index > -1)
{
qghi->setColor(Qt::cyan);
m_moving_segment = true;
m_moved_segment = segmentsList().at(m_vector_index+1);
before_mov_text_pos_ = m_text_item -> pos();
for(QetGraphicsHandlerItem *handler : m_handler_vector)
if(handler != qghi)
handler->hide();
}
}
/**
* @brief Conductor::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void Conductor::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
if (m_moving_segment)
{
//Snap the mouse pos to grid
QPointF pos_ = Diagram::snapToGrid(mapFromItem(qghi, event->pos()));
//Position of the last point
QPointF p = m_moved_segment -> middle();
//Calcul the movement
m_moved_segment -> moveX(pos_.x() - p.x());
m_moved_segment -> moveY(pos_.y() - p.y());
//Apply the movement
modified_path = true;
has_to_save_profile = true;
segmentsToPath();
calculateTextItemPosition();
qghi->setPos(mapToScene(m_moved_segment->middle()));
}
}
/**
* @brief Conductor::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void Conductor::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(qghi);
m_vector_index = -1;
m_moving_segment = false;
if (has_to_save_profile)
{
saveProfile();
has_to_save_profile = false;
}
//When handler is released, the conductor can have more segment than befor the handler was moved
//then we remove all handles and new ones are added
removeHandler();
addHandler();
}
/**
* @brief Conductor::addHandler
* Add handlers for this item
*/
void Conductor::addHandler()
{
if (m_handler_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(handlerPoints()));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
handler->setColor(Qt::blue);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
handler->setZValue(this->zValue()+1);
}
}
}
/**
* @brief Conductor::removeHandler
* Remove the handlers of this item
*/
void Conductor::removeHandler()
{
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
return(QGraphicsPathItem::itemChange(change, value));
}
/**
@@ -769,22 +873,6 @@ QPainterPath Conductor::shape() const
QPainterPath shape_(pps.createStroke(path()));
/**
Add handle rect to path, occur a weird bug.
when the conductor is removed from the scene he continue to be painted in the scene and make artefact.
If we save (exactly when we clear the undo stack of project when saving), Qet crash,
Don't add the handle rect to the path seem to work well.
More information here :
https://qelectrotech.org/bugtracker/view.php?id=107
https://qelectrotech.org/forum/viewtopic.php?pid=5619#p5619
https://qelectrotech.org/forum/viewtopic.php?pid=5067#p5067
**/
// if (isSelected()) {
// foreach (QRectF rect, m_handler.handlerRect(handlerPoints())) {
// shape_.addRect(rect);
// }
// }
return shape_;
}

View File

@@ -20,7 +20,6 @@
#include "conductorproperties.h"
#include <QGraphicsPathItem>
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
#include "assignvariables.h"
class ConductorProfile;
@@ -32,6 +31,8 @@ class ConductorTextItem;
class Element;
class QETDiagramEditor;
class NumerotationContext;
class QetGraphicsHandlerItem;
typedef QPair<QPointF, Qt::Corner> ConductorBend;
typedef QHash<Qt::Corner, ConductorProfile> ConductorProfilesGroup;
/**
@@ -133,16 +134,25 @@ class Conductor : public QObject, public QGraphicsPathItem
protected:
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void addHandler();
void removeHandler();
QVector<QetGraphicsHandlerItem *> m_handler_vector;
int m_vector_index = -1;
bool m_mouse_over;
QetGraphicsHandlerUtility m_handler;
/// Functional properties
ConductorProperties m_properties;
/// Text input for non simple, non-singleline conductors
@@ -150,10 +160,10 @@ class Conductor : public QObject, public QGraphicsPathItem
/// Segments composing the conductor
ConductorSegment *segments;
/// Attributs related to mouse interaction
bool moving_segment;
bool m_moving_segment;
int moved_point;
qreal previous_z_value;
ConductorSegment *moved_segment;
qreal m_previous_z_value;
ConductorSegment *m_moved_segment;
QPointF before_mov_text_pos_;
/// Whether the conductor was manually modified by users
bool modified_path;

View File

@@ -22,6 +22,7 @@
#include "shapegraphicsitempropertieswidget.h"
#include "PropertiesEditor/propertieseditordialog.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
#include "qetxml.h"
/**
@@ -37,18 +38,20 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem
m_shapeType(type),
m_P1 (p1),
m_P2 (p2),
m_hovered(false),
m_mouse_grab_handler(false),
m_handler(10)
m_hovered(false)
{
if (type == Polygon) m_polygon << m_P1 << m_P2;
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
setAcceptHoverEvents(true);
m_pen.setStyle(Qt::DashLine);
}
QetShapeItem::~QetShapeItem() {}
QetShapeItem::~QetShapeItem()
{
if(!m_handler_vector.isEmpty())
qDeleteAll(m_handler_vector);
}
/**
* @brief QetShapeItem::setPen
@@ -109,6 +112,7 @@ bool QetShapeItem::setLine(const QLineF &line)
prepareGeometryChange();
m_P1 = line.p1();
m_P2 = line.p2();
adjusteHandlerPos();
return true;
}
@@ -125,6 +129,7 @@ bool QetShapeItem::setRect(const QRectF &rect)
prepareGeometryChange();
m_P1 = rect.topLeft();
m_P2 = rect.bottomRight();
adjusteHandlerPos();
return true;
}
@@ -142,6 +147,7 @@ bool QetShapeItem::setPolygon(const QPolygonF &polygon)
if (Q_UNLIKELY(m_shapeType != Polygon)) return false;
prepareGeometryChange();
m_polygon = polygon;
adjusteHandlerPos();
return true;
}
@@ -246,23 +252,6 @@ QPainterPath QetShapeItem::shape() const
pps.setJoinStyle(Qt::RoundJoin);
path = 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, m_handler.handlerRect(vector))
path.addRect(r);
}
return (path);
}
@@ -294,33 +283,14 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
painter -> restore ();
}
//Draw the shape and handlers if is selected
switch (m_shapeType)
{
case Line:
painter->drawLine(QLineF(m_P1, m_P2));
if (isSelected())
m_handler.drawHandler(painter, QVector<QPointF>{m_P1, m_P2});
break;
case Rectangle:
painter->drawRect(QRectF(m_P1, m_P2));
if (isSelected())
m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2)));
break;
case Ellipse:
painter->drawEllipse(QRectF(m_P1, m_P2));
if (isSelected())
m_handler.drawHandler(painter, m_handler.pointsForRect(QRectF(m_P1, m_P2)));
break;
case Polygon:
m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon);
if (isSelected())
m_handler.drawHandler(painter, m_polygon);
break;
case Line: painter->drawLine(QLineF(m_P1, m_P2)); break;
case Rectangle: painter->drawRect(QRectF(m_P1, m_P2)); break;
case Ellipse: painter->drawEllipse(QRectF(m_P1, m_P2)); break;
case Polygon: m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon); break;
}
painter->restore();
}
@@ -329,142 +299,23 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
* Handle hover enter event
* @param event
*/
void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) {
void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = true;
QetGraphicsItem::hoverEnterEvent(event);
}
void QetShapeItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if (!isSelected()) return;
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);
if (handler >= 0)
{
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);
}
/**
* @brief QetShapeItem::hoverLeaveEvent
* Handle hover leave event
* @param event
*/
void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = false;
unsetCursor();
QetGraphicsItem::hoverLeaveEvent(event);
}
/**
* @brief QetShapeItem::mousePressEvent
* Handle mouse press event
* @param event
*/
void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::ClosedHandCursor);
//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: 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;
}
}
}
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:
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;
}
case Polygon:
prepareGeometryChange();
m_polygon.replace(m_vector_index, new_pos);
break;
} //End switch
return;
}
QetGraphicsItem::mouseMoveEvent(event);
}
/**
* @brief QetShapeItem::mouseReleaseEvent
* Handle mouse release event
@@ -472,12 +323,228 @@ void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/
void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if ((m_shapeType & (Rectangle | Ellipse)) && event->buttonDownPos(Qt::LeftButton) == event->pos())
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
if (m_mouse_grab_handler)
QetGraphicsItem::mouseReleaseEvent(event);
}
/**
* @brief QetShapeItem::itemChange
* @param change
* @param value
* @return
*/
QVariant QetShapeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged)
{
m_mouse_grab_handler = false;
if (value.toBool() == true) //If this is selected, wa add handlers.
{
QVector <QPointF> 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;
}
if(!points_vector.isEmpty() && scene())
{
m_handler_vector = QetGraphicsHandlerItem::handlerForPoint(mapToScene(points_vector));
for(QetGraphicsHandlerItem *handler : m_handler_vector)
{
handler->setColor(Qt::blue);
scene()->addItem(handler);
handler->installSceneEventFilter(this);
}
}
}
else //Else this is deselected, we remove handlers
{
if(!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
m_handler_vector.clear();
}
}
}
else if (change == ItemPositionHasChanged)
{
adjusteHandlerPos();
}
else if (change == ItemSceneHasChanged)
{
if (!scene()) //This is removed from scene, then we deselect this, and so, the handlers is also removed.
{
setSelected(false);
}
}
return QGraphicsItem::itemChange(change, value);
}
/**
* @brief QetShapeItem::sceneEventFilter
* @param watched
* @param event
* @return
*/
bool QetShapeItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
//Watched must be an handler
if(watched->type() == QetGraphicsHandlerItem::Type)
{
QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
{
m_vector_index = m_handler_vector.indexOf(qghi);
if (m_vector_index != -1)
{
if(event->type() == QEvent::GraphicsSceneMousePress) //Click
{
handlerMousePressEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
{
handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
else if (event->type() == QEvent::GraphicsSceneMouseRelease) //Release
{
handlerMouseReleaseEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
}
}
}
return false;
}
/**
* @brief QetShapeItem::switchResizeMode
*/
void QetShapeItem::switchResizeMode()
{
if (m_shapeType & (Rectangle | 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);
}
}
}
/**
* @brief QetShapeItem::adjusteHandlerPos
* Adjust the position of the handler item
*/
void QetShapeItem::adjusteHandlerPos()
{
QVector <QPointF> 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;
}
if (m_handler_vector.size() == points_vector.size())
{
points_vector = mapToScene(points_vector);
for (int i = 0 ; i < points_vector.size() ; ++i)
m_handler_vector.at(i)->setPos(points_vector.at(i));
}
}
/**
* @brief QetShapeItem::handlerMousePressEvent
* @param qghi
* @param event
*/
void QetShapeItem::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
m_old_P1 = m_P1;
m_old_P2 = m_P2;
m_old_polygon = m_polygon;
}
/**
* @brief QetShapeItem::handlerMouseMoveEvent
* @param qghi
* @param event
*/
void QetShapeItem::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = Diagram::snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
switch (m_shapeType)
{
case Line:
prepareGeometryChange();
m_vector_index == 0 ? m_P1 = new_pos : m_P2 = new_pos;
adjusteHandlerPos();
break;
case Rectangle:
if (m_resize_mode == 1) {
setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
break;
}
else {
setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
break;
}
case Ellipse:
if (m_resize_mode == 1) {
setRect(QetGraphicsHandlerUtility::rectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
break;
}
else {
setRect(QetGraphicsHandlerUtility::mirrorRectForPosAtIndex(QRectF(m_P1, m_P2), new_pos, m_vector_index));
break;
}
case Polygon:
prepareGeometryChange();
m_polygon.replace(m_vector_index, new_pos);
adjusteHandlerPos();
break;
} //End switch
}
/**
* @brief QetShapeItem::handlerMouseReleaseEvent
* @param qghi
* @param event
*/
void QetShapeItem::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(qghi);
Q_UNUSED(event);
if (diagram())
{
QPropertyUndoCommand *undo = nullptr;
@@ -501,23 +568,6 @@ void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
diagram()->undoStack().push(undo);
}
}
setCursor(Qt::OpenHandCursor);
}
QetGraphicsItem::mouseReleaseEvent(event);
}
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();
}
/**

View File

@@ -20,10 +20,11 @@
#include <QPen>
#include "qetgraphicsitem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
class QDomElement;
class QDomDocument;
class QetGraphicsHandlerItem;
/**
* @brief The QetShapeItem class
@@ -96,14 +97,18 @@ class QetShapeItem : public QetGraphicsItem
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event);
virtual void hoverMoveEvent (QGraphicsSceneHoverEvent *event);
virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
void switchResizeMode();
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
///ATTRIBUTES
private:
@@ -112,11 +117,10 @@ class QetShapeItem : public QetGraphicsItem
QBrush m_brush;
QPointF m_P1, m_P2, m_old_P1, m_old_P2;
QPolygonF m_polygon, m_old_polygon;
bool m_hovered,
m_mouse_grab_handler;
bool m_hovered;
int m_vector_index;
QetGraphicsHandlerUtility m_handler;
bool m_close = false;
int m_resize_mode = 1;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
};
#endif // QETSHAPEITEM_H