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 + 1107
part text field + 1108 part text field + 1108
part rectangle + 1109 part rectangle + 1109
###QetGraphicsHandlerItem###
QetGraphicsHandlerItem = 1200

View File

@@ -1,5 +1,7 @@
HEADERS += \ HEADERS += \
$$PWD/qetgraphicshandlerutility.h $$PWD/qetgraphicshandlerutility.h \
$$PWD/qetgraphicshandleritem.h
SOURCES += \ 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/>. along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "qetgraphicshandlerutility.h" #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 * @brief QetGraphicsHandlerUtility::pointsForRect
@@ -169,7 +68,6 @@ QVector<QPointF> QetGraphicsHandlerUtility::pointsForLine(const QLineF &line) {
return (QVector<QPointF> {line.p1(), line.p2()}); return (QVector<QPointF> {line.p1(), line.p2()});
} }
#include <QDebug>
/** /**
* @brief QetGraphicsHandlerUtility::pointsForArc * @brief QetGraphicsHandlerUtility::pointsForArc
* Return the points for the given arc. * Return the points for the given arc.

View File

@@ -32,25 +32,6 @@ class QPainter;
*/ */
class QetGraphicsHandlerUtility 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: public:
static QVector <QPointF> pointsForRect (const QRectF &rect); static QVector <QPointF> pointsForRect (const QRectF &rect);
static QVector <QPointF> pointsForLine (const QLineF &line); static QVector <QPointF> pointsForLine (const QLineF &line);

View File

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

View File

@@ -24,23 +24,24 @@
#include <QGraphicsSceneHoverEvent> #include <QGraphicsSceneHoverEvent>
#include <QStyleOptionGraphicsItem> #include <QStyleOptionGraphicsItem>
#include <QGraphicsScene> #include <QGraphicsScene>
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/** /**
Constructor Constructor
@param parent Parent QGraphicsItem @param parent Parent QGraphicsItem
*/ */
ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent): ElementPrimitiveDecorator::ElementPrimitiveDecorator(QGraphicsItem *parent):
QGraphicsObject(parent), QGraphicsObject(parent)
m_handler(10)
{ {
init(); init();
m_handler.setOuterColor(Qt::darkGreen);
} }
/** /**
Destructor Destructor
*/ */
ElementPrimitiveDecorator::~ElementPrimitiveDecorator() { ElementPrimitiveDecorator::~ElementPrimitiveDecorator()
{
removeHandler();
} }
/** /**
@@ -68,12 +69,7 @@ QRectF ElementPrimitiveDecorator::internalBoundingRect() const {
*/ */
QRectF ElementPrimitiveDecorator::boundingRect() const QRectF ElementPrimitiveDecorator::boundingRect() const
{ {
QVector<QRectF> rect_vector = m_handler.handlerRect(getResizingsPoints()); return effective_bounding_rect_;
QRectF rect = effective_bounding_rect_;
rect |= rect_vector.first();
rect |= rect_vector.last();
return(rect);
} }
/** /**
@@ -97,9 +93,6 @@ void ElementPrimitiveDecorator::paint(QPainter *painter, const QStyleOptionGraph
painter -> setPen(pen); painter -> setPen(pen);
painter -> drawRect(modified_bounding_rect_); painter -> drawRect(modified_bounding_rect_);
//Draw the handlers
m_handler.drawHandler(painter, getResizingsPoints());
// uncomment to draw the real bouding rect (=adjusted internal bounding rect) // uncomment to draw the real bouding rect (=adjusted internal bounding rect)
// painter -> setBrush(QBrush(QColor(240, 0, 0, 127))); // painter -> setBrush(QBrush(QColor(240, 0, 0, 127)));
// painter -> drawRect(boundingRect()); // painter -> drawRect(boundingRect());
@@ -118,15 +111,19 @@ void ElementPrimitiveDecorator::setItems(const QList<CustomElementPart *> &items
if (focusItem() != this) { if (focusItem() != this) {
setFocus(); setFocus();
} }
adjusteHandlerPos();
} }
/** /**
@param items the new list of items this decorator is suposed to manipulate. @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; QList<CustomElementPart *> primitives;
foreach (QGraphicsItem *item, items) { for(QGraphicsItem *item : items)
if (CustomElementPart *part_item = dynamic_cast<CustomElementPart *>(item)) { {
if (CustomElementPart *part_item = dynamic_cast<CustomElementPart *>(item))
{
primitives << part_item; primitives << part_item;
} }
} }
@@ -157,72 +154,31 @@ QList<QGraphicsItem *> ElementPrimitiveDecorator::graphicsItems() const {
Adjust the visual decorator according to the currently assigned items. Adjust the visual decorator according to the currently assigned items.
It is notably called by setItems(). It is notably called by setItems().
*/ */
void ElementPrimitiveDecorator::adjust() { void ElementPrimitiveDecorator::adjust()
{
saveOriginalBoundingRect(); saveOriginalBoundingRect();
modified_bounding_rect_ = original_bounding_rect_; modified_bounding_rect_ = original_bounding_rect_;
adjustEffectiveBoundingRect(); 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. Handle event generated when mouse buttons are pressed.
@param event Object describing the mouse event @param event Object describing the mouse event
*/ */
void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event) void ElementPrimitiveDecorator::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
QPointF pos = event -> pos(); if (internalBoundingRect().contains(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))
{ {
current_operation_square_ = QET::MoveArea; 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(); first_pos_ = decorated_items_.at(0) -> toItem() -> scenePos();
latest_pos_ = event -> scenePos(); latest_pos_ = event -> scenePos();
mouse_offset_ = event -> scenePos() - first_pos_; mouse_offset_ = event -> scenePos() - first_pos_;
}
startMovement(); startMovement();
event -> accept(); event->accept();
} }
else else
event -> ignore(); event->ignore();
} }
/** /**
@@ -235,46 +191,12 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QPointF scene_pos = event -> scenePos(); QPointF scene_pos = event -> scenePos();
QPointF movement = scene_pos - latest_pos_; QPointF movement = scene_pos - latest_pos_;
if (current_operation_square_ > QET::NoOperation) { if (current_operation_square_ == QET::MoveArea)
// 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) {
// When moving the selection, consider the position of the first selected item // When moving the selection, consider the position of the first selected item
QPointF current_position = scene_pos - mouse_offset_; QPointF current_position = scene_pos - mouse_offset_;
QPointF rounded_current_position = snapConstPointToGrid(current_position); QPointF rounded_current_position = snapConstPointToGrid(current_position);
movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos(); movement = rounded_current_position - decorated_items_.at(0) -> toItem() -> scenePos();
}
QRectF bounding_rect = modified_bounding_rect_; QRectF bounding_rect = modified_bounding_rect_;
applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_); applyMovementToRect(current_operation_square_, movement, modified_bounding_rect_);
@@ -282,12 +204,12 @@ void ElementPrimitiveDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
adjustEffectiveBoundingRect(); adjustEffectiveBoundingRect();
} }
latest_pos_ = event -> scenePos(); latest_pos_ = event -> scenePos();
if (current_operation_square_ == QET::MoveArea) {
translateItems(movement); 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 @param event Object describing the mouse event
@see QGraphicsScene::mouseGrabberItem() @see QGraphicsScene::mouseGrabberItem()
*/ */
void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void ElementPrimitiveDecorator::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(event) Q_UNUSED(event)
ElementEditionCommand *command = 0; ElementEditionCommand *command = 0;
if (current_operation_square_ > QET::NoOperation) {
ScalePartsCommand *scale_command = new ScalePartsCommand(); if (current_operation_square_ == QET::MoveArea)
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) {
QPointF movement = mapToScene(modified_bounding_rect_.topLeft()) - mapToScene(original_bounding_rect_.topLeft()); 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()); MovePartsCommand *move_command = new MovePartsCommand(movement, 0, graphicsItems());
command = move_command; command = move_command;
} }
}
if (command) { if (command) {
emit(actionFinished(command)); emit(actionFinished(command));
} }
if (current_operation_square_ != QET::NoOperation) {
adjust(); adjust();
} }
@@ -376,7 +292,8 @@ void ElementPrimitiveDecorator::keyReleaseEvent(QKeyEvent *e) {
/** /**
Initialize an ElementPrimitiveDecorator Initialize an ElementPrimitiveDecorator
*/ */
void ElementPrimitiveDecorator::init() { void ElementPrimitiveDecorator::init()
{
setFlag(QGraphicsItem::ItemIsFocusable, true); setFlag(QGraphicsItem::ItemIsFocusable, true);
grid_step_x_ = grid_step_y_ = 1; grid_step_x_ = grid_step_y_ = 1;
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
@@ -397,6 +314,7 @@ void ElementPrimitiveDecorator::adjustEffectiveBoundingRect() {
prepareGeometryChange(); prepareGeometryChange();
effective_bounding_rect_ = modified_bounding_rect_ | effective_bounding_rect_; effective_bounding_rect_ = modified_bounding_rect_ | effective_bounding_rect_;
update(); update();
adjusteHandlerPos();
} }
/** /**
@@ -528,6 +446,152 @@ QVector<QPointF> ElementPrimitiveDecorator::getResizingsPoints() const
return vector; 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 Receive two rects, assuming they share a common corner and current is a \a
scaled version of \a original. scaled version of \a original.
@@ -597,3 +661,73 @@ QET::ScalingMethod ElementPrimitiveDecorator::scalingMethod(QGraphicsSceneMouseE
} }
return QET::RoundScaleRatios; 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 <QGraphicsObject>
#include "qet.h" #include "qet.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class ElementEditionCommand; class ElementEditionCommand;
class ElementScene; class ElementScene;
class CustomElementPart; class CustomElementPart;
class QetGraphicsHandlerItem;
/** /**
This class represents a decorator rendered above selected items so users This class represents a decorator rendered above selected items so users
@@ -64,7 +64,6 @@ class ElementPrimitiveDecorator : public QGraphicsObject
void actionFinished(ElementEditionCommand *); void actionFinished(ElementEditionCommand *);
protected: protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent *);
void mousePressEvent(QGraphicsSceneMouseEvent *); void mousePressEvent(QGraphicsSceneMouseEvent *);
void mouseMoveEvent(QGraphicsSceneMouseEvent *); void mouseMoveEvent(QGraphicsSceneMouseEvent *);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *); void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
@@ -75,6 +74,8 @@ class ElementPrimitiveDecorator : public QGraphicsObject
void snapPointToGrid(QPointF &) const; void snapPointToGrid(QPointF &) const;
bool mustSnapToGrid(QGraphicsSceneMouseEvent *); bool mustSnapToGrid(QGraphicsSceneMouseEvent *);
QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *); QET::ScalingMethod scalingMethod(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private: private:
void init(); void init();
@@ -88,8 +89,19 @@ class ElementPrimitiveDecorator : public QGraphicsObject
QRectF getSceneBoundingRect(QGraphicsItem *) const; QRectF getSceneBoundingRect(QGraphicsItem *) const;
QVector <QPointF> getResizingsPoints() const; QVector <QPointF> getResizingsPoints() const;
// attributes
private: 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_; QList<CustomElementPart *> decorated_items_;
QRectF effective_bounding_rect_; ///< actual, effective bounding rect -- never shrinks QRectF effective_bounding_rect_; ///< actual, effective bounding rect -- never shrinks
QRectF original_bounding_rect_; ///< original bounding rect 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 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 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 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 #endif

View File

@@ -32,8 +32,9 @@
#include "nameslist.h" #include "nameslist.h"
#include "ui/elementpropertieseditorwidget.h" #include "ui/elementpropertieseditorwidget.h"
#include "eseventinterface.h" #include "eseventinterface.h"
#include <algorithm> #include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include <algorithm>
#include <QKeyEvent> #include <QKeyEvent>
/** /**
@@ -524,27 +525,45 @@ QETElementEditor* ElementScene::editor() const {
} }
/** /**
Selectionne une liste de parties * @brief ElementScene::slot_select
@param content liste des parties a selectionner * Select the item in content, every others items in the scene are deselected
*/ * @param content
void ElementScene::slot_select(const ElementContent &content) { */
void ElementScene::slot_select(const ElementContent &content)
{
blockSignals(true); 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(); clearSelection();
foreach(QGraphicsItem *qgi, content) qgi -> setSelected(true);
foreach(QGraphicsItem *qgi, items_list)
qgi -> setSelected(true);
blockSignals(false); blockSignals(false);
emit(selectionChanged()); emit(selectionChanged());
} }
/** /**
Selectionne tout * @brief ElementScene::slot_selectAll
*/ * Select all items
*/
void ElementScene::slot_selectAll() { void ElementScene::slot_selectAll() {
slot_select(items()); slot_select(items());
} }
/** /**
Deselectionne tout * @brief ElementScene::slot_deselectAll
*/ * deselect all item
*/
void ElementScene::slot_deselectAll() { void ElementScene::slot_deselectAll() {
slot_select(ElementContent()); slot_select(ElementContent());
} }
@@ -811,7 +830,15 @@ void ElementScene::reset()
clearSelection(); clearSelection();
undoStack().clear(); 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); removeItem(qgi);
qgiManager().release(qgi); qgiManager().release(qgi);
@@ -1065,9 +1092,16 @@ void ElementScene::managePrimitivesGroups()
// should we hide the decorator? // should we hide the decorator?
QList<QGraphicsItem *> selected_items = zItems(ElementScene::Selected | ElementScene::IncludeTerminals); QList<QGraphicsItem *> selected_items = zItems(ElementScene::Selected | ElementScene::IncludeTerminals);
if (selected_items.size() <= 1) if (selected_items.size() <= 1)
{
m_decorator -> hide(); m_decorator -> hide();
}
else 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 -> setZValue(1000000);
m_decorator -> setPos(0, 0); m_decorator -> setPos(0, 0);
m_decorator -> setItems(selected_items); m_decorator -> setItems(selected_items);

View File

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

View File

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

View File

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

View File

@@ -18,6 +18,8 @@
#include "partarc.h" #include "partarc.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.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 * @brief PartArc::~PartArc
* Destructor * Destructor
*/ */
PartArc::~PartArc() { PartArc::~PartArc()
{
if(m_undo_command) delete m_undo_command; if(m_undo_command) delete m_undo_command;
removeHandler();
} }
/** /**
@@ -82,15 +86,7 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
drawShadowShape(painter); drawShadowShape(painter);
if (isSelected()) if (isSelected())
{
drawCross(m_rect.center(), painter); 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; 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 * @brief PartArc::shape
* @return the shape of this item * @return the shape of this item
@@ -153,10 +139,6 @@ QPainterPath PartArc::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape); shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape; return shape;
} }
@@ -172,68 +154,173 @@ QPainterPath PartArc::shadowShape() const
return (pps.createStroke(shape)); 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()) if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
{ switchResizeMode();
CustomElementGraphicPart::hoverMoveEvent(event);
return;
}
if (m_resize_mode == 1 || m_resize_mode == 2) { CustomElementGraphicPart::mouseReleaseEvent(event);
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);
} }
/** /**
* @brief PartArc::mousePressEvent * @brief PartArc::itemChange
* Handle mouse press event * @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 * @param event
*/ */
void PartArc::mousePressEvent(QGraphicsSceneMouseEvent *event) void PartArc::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) Q_UNUSED(qghi);
{ Q_UNUSED(event);
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));
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)); if (m_vector_index == 0)
m_undo_command->setText(tr("Modifier un arc")); {
m_undo_command->enableAnimation(); m_span_point = QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle /16, m_span_angle /16).at(1);
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);
m_undo_command = new QPropertyUndoCommand(this, "startAngle", QVariant(m_start_angle)); m_undo_command = new QPropertyUndoCommand(this, "startAngle", QVariant(m_start_angle));
m_undo_command->setText(tr("Modifier un arc")); 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 = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle), m_undo_command);
m_undo_command2->setText(tr("Modifier un arc")); m_undo_command2->setText(tr("Modifier un arc"));
m_undo_command2->enableAnimation(); 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 = new QPropertyUndoCommand(this, "spanAngle", QVariant(m_span_angle));
m_undo_command->setText(tr("Modifier un arc")); m_undo_command->setText(tr("Modifier un arc"));
m_undo_command->enableAnimation(); 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 * @brief PartArc::handlerMouseMoveEvent
* Handle mouse move event * @param qghi
* @param event * @param event
*/ */
void PartArc::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void PartArc::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (m_resize_mode == 1 || m_resize_mode == 2) { Q_UNUSED(qghi);
if (m_handler_index >= 0 && m_handler_index <= 7) {
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); QPointF new_pos = event->scenePos();
prepareGeometryChange(); if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
if (m_resize_mode == 1) 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 else
setRect(m_handler.mirrorRectForPosAtIndex(m_rect, pos_, m_handler_index)); {
QLineF line(m_rect.center(), mapFromItem(qghi, event->pos()));
return;
}
}
else if (m_resize_mode == 3) {
if (m_handler_index == 0 || m_handler_index == 1) {
QLineF line(m_rect.center(), event->pos());
prepareGeometryChange(); prepareGeometryChange();
if (m_handler_index == 0) { if (m_vector_index == 0) {
setStartAngle(line.angle()*16); setStartAngle(line.angle()*16);
setSpanAngle(line.angleTo(QLineF(m_rect.center(), m_span_point))*16); setSpanAngle(line.angleTo(QLineF(m_rect.center(), m_span_point))*16);
} }
else if (m_handler_index == 1) { else if (m_vector_index == 1) {
QLineF line2(m_rect.center(), m_handler.pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0)); QLineF line2(m_rect.center(), QetGraphicsHandlerUtility::pointsForArc(m_rect, m_start_angle/16, m_span_angle/16).at(0));
setSpanAngle (line2.angleTo(line)*16); setSpanAngle (line2.angleTo(line)*16);
} }
return;
} }
}
CustomElementGraphicPart::mouseMoveEvent(event);
} }
/** /**
* @brief PartArc::mouseReleaseEvent * @brief PartArc::handlerMouseReleaseEvent
* Handle mouse release event * @param qghi
* @param event * @param event
*/ */
void PartArc::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void PartArc::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { Q_UNUSED(qghi);
setCursor(Qt::OpenHandCursor); Q_UNUSED(event);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode();
}
if (m_resize_mode == 1 || m_resize_mode == 2) { if (m_resize_mode == 3)
if (m_handler_index >= 0 && m_handler_index <= 7) { {
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()) if (!m_rect.isValid())
m_rect = m_rect.normalized(); m_rect = m_rect.normalized();
m_undo_command->setNewValue(QVariant(m_rect)); m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command); elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr; m_undo_command = nullptr;
m_handler_index = -1; m_vector_index = -1;
return;
} }
}
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) { if (this->isSelected() && scene()->selectedItems().size() == 1)
m_resize_mode = 2; addHandler();
m_handler.setOuterColor(Qt::darkGreen); else
} removeHandler();
else if (m_resize_mode == 2 ) { }
m_resize_mode = 3;
m_handler.setOuterColor(Qt::magenta); /**
} * @brief PartArc::addHandler
else { * Add handlers for this item
m_resize_mode = 1; */
m_handler.setOuterColor(Qt::blue); void PartArc::addHandler()
} {
update(); 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 #define PART_ARC_H
#include "abstractpartellipse.h" #include "abstractpartellipse.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand; class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/** /**
* @brief The PartArc class * @brief The PartArc class
@@ -54,25 +54,34 @@ class PartArc : public AbstractPartEllipse
virtual const QDomElement toXml (QDomDocument &) const; virtual const QDomElement toXml (QDomDocument &) const;
virtual void fromXml (const QDomElement &); virtual void fromXml (const QDomElement &);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const; virtual QPainterPath shape() const;
virtual QPainterPath shadowShape() 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: protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private: private:
void switchResizeMode(); 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: private:
QetGraphicsHandlerUtility m_handler = 10;
int m_handler_index = -1;
QPropertyUndoCommand *m_undo_command = nullptr; QPropertyUndoCommand *m_undo_command = nullptr;
QPropertyUndoCommand *m_undo_command2 = nullptr; QPropertyUndoCommand *m_undo_command2 = nullptr;
int m_resize_mode = 1; int m_resize_mode = 1,
m_vector_index = -1;
QPointF m_span_point; QPointF m_span_point;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
}; };
#endif #endif

View File

@@ -18,6 +18,8 @@
#include "partellipse.h" #include "partellipse.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.h" #include "elementscene.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
/** /**
* @brief PartEllipse::PartEllipse * @brief PartEllipse::PartEllipse
@@ -27,8 +29,6 @@
*/ */
PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) : PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) :
AbstractPartEllipse(editor, parent), AbstractPartEllipse(editor, parent),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr) m_undo_command(nullptr)
{} {}
@@ -36,8 +36,10 @@ PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent) :
* @brief PartEllipse::~PartEllipse * @brief PartEllipse::~PartEllipse
* Destructor * Destructor
*/ */
PartEllipse::~PartEllipse() { PartEllipse::~PartEllipse()
{
if(m_undo_command) delete m_undo_command; if(m_undo_command) delete m_undo_command;
removeHandler();
} }
/** /**
@@ -65,11 +67,7 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
drawShadowShape(painter); drawShadowShape(painter);
if (isSelected()) if (isSelected())
{
drawCross(m_rect.center(), painter); 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)); 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 * @brief PartEllipse::shape
* @return the shape of this item * @return the shape of this item
@@ -148,10 +136,6 @@ QPainterPath PartEllipse::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape); shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape; return shape;
} }
@@ -166,77 +150,6 @@ QPainterPath PartEllipse::shadowShape() const
return (pps.createStroke(shape)); 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 * @brief PartEllipse::mouseReleaseEvent
* Handle mouse release event * Handle mouse release event
@@ -244,35 +157,225 @@ void PartEllipse::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/ */
void PartEllipse::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void PartEllipse::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
setCursor(Qt::OpenHandCursor);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode(); 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()) if (value.toBool() == true)
m_rect = m_rect.normalized(); {
//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)); if (scene()->selectedItems().size() == 1)
elementScene()->undoStack().push(m_undo_command); addHandler();
m_undo_command = nullptr;
m_handler_index = -1;
} }
else 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() void PartEllipse::switchResizeMode()
{ {
if (m_resize_mode == 1) { if (m_resize_mode == 1)
{
m_resize_mode = 2; 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_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 #define PART_ELLIPSE_H
#include "abstractpartellipse.h" #include "abstractpartellipse.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand; class QPropertyUndoCommand;
@@ -55,24 +54,29 @@ class PartEllipse : public AbstractPartEllipse
virtual QString xmlName() const { return(QString("ellipse")); } virtual QString xmlName() const { return(QString("ellipse")); }
virtual const QDomElement toXml (QDomDocument &) const; virtual const QDomElement toXml (QDomDocument &) const;
virtual void fromXml (const QDomElement &); virtual void fromXml (const QDomElement &);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const; virtual QPainterPath shape() const;
virtual QPainterPath shadowShape() const; virtual QPainterPath shadowShape() const;
virtual void setRect(const QRectF &rect) {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();}
protected: protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private: private:
void switchResizeMode(); 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: private:
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
QPropertyUndoCommand *m_undo_command; QPropertyUndoCommand *m_undo_command;
int m_resize_mode = 1; int m_resize_mode = 1,
m_vector_index = -1;
}; };
#endif #endif

View File

@@ -19,6 +19,7 @@
#include <cmath> #include <cmath>
#include "elementscene.h" #include "elementscene.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/** /**
@@ -33,14 +34,16 @@ PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent) :
first_length(1.5), first_length(1.5),
second_end(Qet::None), second_end(Qet::None),
second_length(1.5), second_length(1.5),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr) m_undo_command(nullptr)
{} {}
/// Destructeur /// Destructeur
PartLine::~PartLine() { PartLine::~PartLine()
if(m_undo_command) delete m_undo_command; {
if(m_undo_command)
delete m_undo_command;
removeHandler();
} }
/** /**
@@ -90,9 +93,6 @@ void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
if (m_hovered) if (m_hovered)
drawShadowShape(painter); drawShadowShape(painter);
if (isSelected() && scene()->selectedItems().size() == 1)
m_handler.drawHandler(painter, m_handler.pointsForLine(m_line));
painter->restore(); painter->restore();
} }
@@ -140,69 +140,206 @@ void PartLine::fromXml(const QDomElement &qde) {
} }
/** /**
* @brief PartLine::mousePressEvent * @brief PartLine::itemChange
* Handle mouse press event * @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 * @param event
*/ */
void PartLine::mousePressEvent(QGraphicsSceneMouseEvent *event) void PartLine::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if(event->button() == Qt::LeftButton) Q_UNUSED(qghi);
{ Q_UNUSED(event);
setCursor(Qt::ClosedHandCursor);
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 = new QPropertyUndoCommand(this, "line", QVariant(m_line));
m_undo_command->setText(tr("Modifier une ligne")); m_undo_command->setText(tr("Modifier une ligne"));
m_undo_command->enableAnimation(); m_undo_command->enableAnimation();
return; return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
} }
/** /**
* @brief PartLine::mouseMoveEvent * @brief PartLine::handlerMouseMoveEvent
* Handle pouse move event * @param qghi
* @param event * @param event
*/ */
void PartLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void PartLine::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if(m_handler_index >= 0 && m_handler_index <= 1) Q_UNUSED(qghi);
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
prepareGeometryChange(); prepareGeometryChange();
setLine(m_handler.lineForPosAtIndex(m_line, pos_, m_handler_index)); if (m_vector_index == 0)
} m_line.setP1(new_pos);
else else
CustomElementGraphicPart::mouseMoveEvent(event); m_line.setP2(new_pos);
adjusteHandlerPos();
} }
/** /**
* @brief PartLine::mouseReleaseEvent * @brief PartLine::handlerMouseReleaseEvent
* Handle mouse release event * @param qghi
* @param event * @param event
*/ */
void PartLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void PartLine::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) Q_UNUSED(qghi);
setCursor(Qt::OpenHandCursor); Q_UNUSED(event);
if (m_handler_index >= 0 && m_handler_index <= 1)
{
m_undo_command->setNewValue(QVariant(m_line)); m_undo_command->setNewValue(QVariant(m_line));
elementScene()->undoStack().push(m_undo_command); elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr; 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 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()); pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape); shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line)))
shape.addRect(rect);
return shape; return shape;
} }
@@ -402,9 +535,6 @@ QRectF PartLine::boundingRect() const
bound = bound.normalized(); bound = bound.normalized();
bound.adjust(-adjust, -adjust, adjust, adjust); bound.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForLine(m_line)))
bound |= rect;
return bound; return bound;
} }
@@ -496,6 +626,7 @@ void PartLine::setLine(const QLineF &line)
if (m_line == line) return; if (m_line == line) return;
prepareGeometryChange(); prepareGeometryChange();
m_line = line; m_line = line;
adjusteHandlerPos();
emit lineChanged(); emit lineChanged();
} }
@@ -533,20 +664,6 @@ void PartLine::setSecondEndLength(const qreal &l)
emit secondEndLengthChanged(); 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 * @brief PartLine::path
* @return this line has a QPainterPath. * @return this line has a QPainterPath.

View File

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

View File

@@ -18,6 +18,7 @@
#include "partpolygon.h" #include "partpolygon.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "elementscene.h" #include "elementscene.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
/** /**
@@ -29,16 +30,16 @@
PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent) : PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent) :
CustomElementGraphicPart(editor, parent), CustomElementGraphicPart(editor, parent),
m_closed(false), m_closed(false),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr) m_undo_command(nullptr)
{} {}
/** /**
* @brief PartPolygon::~PartPolygon * @brief PartPolygon::~PartPolygon
*/ */
PartPolygon::~PartPolygon() { PartPolygon::~PartPolygon()
{
if(m_undo_command) delete m_undo_command; if(m_undo_command) delete m_undo_command;
removeHandler();
} }
/** /**
@@ -64,9 +65,6 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
if (m_hovered) if (m_hovered)
drawShadowShape(painter); 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; if (m_polygon == polygon) return;
prepareGeometryChange(); prepareGeometryChange();
m_polygon = polygon; m_polygon = polygon;
adjusteHandlerPos();
emit polygonChanged(); emit polygonChanged();
} }
@@ -248,83 +247,195 @@ void PartPolygon::setClosed(bool close)
emit closedChange(); 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); if (value.toBool() == true)
return; {
//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) return QGraphicsItem::itemChange(change, value);
setCursor(Qt::SizeAllCursor);
else
CustomElementGraphicPart::hoverMoveEvent(event);
} }
/** /**
* @brief PartPolygon::mousePressEvent * @brief PartPolygon::sceneEventFilter
* Handle mouse press event * @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 * @param event
*/ */
void PartPolygon::mousePressEvent(QGraphicsSceneMouseEvent *event) void PartPolygon::handlerMousePressEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) Q_UNUSED(qghi);
{ Q_UNUSED(event);
setCursor(Qt::ClosedHandCursor);
if(isSelected())
{
m_handler_index = m_handler.pointIsHoverHandler(event->pos(), m_polygon);
if(m_handler_index >= 0) //User click on an handler
{
m_undo_command = new QPropertyUndoCommand(this, "polygon", QVariant(m_polygon)); m_undo_command = new QPropertyUndoCommand(this, "polygon", QVariant(m_polygon));
m_undo_command->setText(tr("Modifier un polygone")); m_undo_command->setText(tr("Modifier un polygone"));
return;
}
}
}
CustomElementGraphicPart::mousePressEvent(event);
} }
/** /**
* @brief PartPolygon::mouseMoveEvent * @brief PartPolygon::handlerMouseMoveEvent
* Handle mouse move event * @param qghi
* @param event * @param event
*/ */
void PartPolygon::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void PartPolygon::handlerMouseMoveEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if(m_handler_index >= 0) Q_UNUSED(qghi);
{
QPointF pos_ = event->modifiers() == Qt::ControlModifier ? event->pos() : mapFromScene(elementScene()->snapToGrid(event->scenePos())); QPointF new_pos = event->scenePos();
if (event->modifiers() != Qt::ControlModifier)
new_pos = elementScene()->snapToGrid(event->scenePos());
new_pos = mapFromScene(new_pos);
prepareGeometryChange(); prepareGeometryChange();
m_polygon.replace(m_handler_index, pos_); m_polygon.replace(m_vector_index, new_pos);
adjusteHandlerPos();
emit polygonChanged(); emit polygonChanged();
}
else
CustomElementGraphicPart::mouseMoveEvent(event);
} }
/** /**
* @brief PartPolygon::mouseReleaseEvent * @brief PartPolygon::handlerMouseReleaseEvent
* Handle mouse release event * @param qghi
* @param event * @param event
*/ */
void PartPolygon::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void PartPolygon::handlerMouseReleaseEvent(QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) Q_UNUSED(qghi);
setCursor(Qt::OpenHandCursor); Q_UNUSED(event);
if (m_handler_index >= 0)
{
m_undo_command->setNewValue(QVariant(m_polygon)); m_undo_command->setNewValue(QVariant(m_polygon));
elementScene()->undoStack().push(m_undo_command); elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr; 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 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()); pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape); shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_polygon))
shape.addRect(rect);
return shape; return shape;
} }
@@ -379,8 +486,5 @@ QRectF PartPolygon::boundingRect() const
r.adjust(-adjust, -adjust, adjust, adjust); r.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_polygon))
r |=rect;
return(r); return(r);
} }

View File

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

View File

@@ -18,6 +18,8 @@
#include "partrectangle.h" #include "partrectangle.h"
#include "elementscene.h" #include "elementscene.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
/** /**
* @brief PartRectangle::PartRectangle * @brief PartRectangle::PartRectangle
@@ -27,16 +29,16 @@
*/ */
PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent) : PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent) :
CustomElementGraphicPart(editor, parent), CustomElementGraphicPart(editor, parent),
m_handler(10),
m_handler_index(-1),
m_undo_command(nullptr) m_undo_command(nullptr)
{} {}
/** /**
* @brief PartRectangle::~PartRectangle * @brief PartRectangle::~PartRectangle
*/ */
PartRectangle::~PartRectangle() { PartRectangle::~PartRectangle()
{
if(m_undo_command) delete m_undo_command; if(m_undo_command) delete m_undo_command;
removeHandler();
} }
/** /**
@@ -69,11 +71,7 @@ void PartRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
drawShadowShape(painter); drawShadowShape(painter);
if (isSelected()) if (isSelected())
{
drawCross(m_rect.center(), painter); 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; if (rect == m_rect) return;
prepareGeometryChange(); prepareGeometryChange();
m_rect = rect; m_rect = rect;
adjusteHandlerPos();
emit rectChanged(); emit rectChanged();
} }
@@ -164,10 +163,6 @@ QPainterPath PartRectangle::shape() const
pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight()); pps.setWidth(m_hovered? penWeight()+SHADOWS_HEIGHT : penWeight());
shape = pps.createStroke(shape); shape = pps.createStroke(shape);
if (isSelected())
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
shape.addRect(rect);
return shape; return shape;
} }
@@ -196,9 +191,6 @@ QRectF PartRectangle::boundingRect() const
QRectF r = m_rect.normalized(); QRectF r = m_rect.normalized();
r.adjust(-adjust, -adjust, adjust, adjust); r.adjust(-adjust, -adjust, adjust, adjust);
foreach(QRectF rect, m_handler.handlerRect(m_handler.pointsForRect(m_rect)))
r |= rect;
return(r); 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)))); 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 * @brief PartRectangle::mouseReleaseEvent
* Handle mouse release event * Handle mouse release event
@@ -315,35 +236,223 @@ void PartRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/ */
void PartRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void PartRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton && event->buttonDownPos(Qt::LeftButton) == event->pos())
setCursor(Qt::OpenHandCursor);
if (event->buttonDownPos(Qt::LeftButton) == event->pos())
switchResizeMode(); 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()) QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
m_rect = m_rect.normalized();
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)); m_undo_command->setNewValue(QVariant(m_rect));
elementScene()->undoStack().push(m_undo_command); elementScene()->undoStack().push(m_undo_command);
m_undo_command = nullptr; m_undo_command = nullptr;
m_handler_index = -1; m_vector_index = -1;
}
else
CustomElementGraphicPart::mouseReleaseEvent(event);
} }
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) { if (this->isSelected() && scene()->selectedItems().size() == 1)
m_resize_mode = 2; addHandler();
m_handler.setOuterColor(Qt::darkGreen); else
} removeHandler();
else { }
m_resize_mode = 1;
m_handler.setOuterColor(Qt::blue); /**
} * @brief PartRectangle::addHandler
update(); * 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 #define PART_RECTANGLE_H
#include "customelementgraphicpart.h" #include "customelementgraphicpart.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
class QPropertyUndoCommand; class QPropertyUndoCommand;
class QetGraphicsHandlerItem;
/** /**
* This class represents a rectangle primitive which may be used to compose the * 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 &); virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected: protected:
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private: private:
void switchResizeMode(); 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: private:
QRectF m_rect; QRectF m_rect;
QList<QPointF> saved_points_; QList<QPointF> saved_points_;
QetGraphicsHandlerUtility m_handler;
int m_handler_index;
QPropertyUndoCommand *m_undo_command; QPropertyUndoCommand *m_undo_command;
int m_resize_mode = 1; int m_resize_mode = 1,
m_vector_index = -1;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
}; };
#endif #endif

View File

@@ -78,17 +78,16 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
terminal1(p1), terminal1(p1),
terminal2(p2), terminal2(p2),
m_mouse_over(false), m_mouse_over(false),
m_handler(10),
m_text_item(0), m_text_item(0),
segments(NULL), segments(NULL),
moving_segment(false), m_moving_segment(false),
modified_path(false), modified_path(false),
has_to_save_profile(false), has_to_save_profile(false),
must_highlight_(Conductor::None) must_highlight_(Conductor::None)
{ {
//set Zvalue at 11 to be upper than the DiagramImageItem and element //set Zvalue at 11 to be upper than the DiagramImageItem and element
setZValue(11); 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 //Add this conductor to the list of conductor of each of the two terminal
bool ajout_p1 = terminal1 -> addConductor(this); bool ajout_p1 = terminal1 -> addConductor(this);
@@ -117,7 +116,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
//Generate the path of this conductor. //Generate the path of this conductor.
generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation()); generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
setFlags(QGraphicsItem::ItemIsSelectable); setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsScenePositionChanges);
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
// Add the text field // Add the text field
@@ -137,6 +136,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) :
*/ */
Conductor::~Conductor() Conductor::~Conductor()
{ {
removeHandler();
terminal1->removeConductor(this); terminal1->removeConductor(this);
terminal2->removeConductor(this); terminal2->removeConductor(this);
deleteSegments(); deleteSegments();
@@ -171,30 +171,39 @@ void Conductor::updatePath(const QRectF &rect) {
} }
/** /**
Genere le QPainterPath a partir de la liste des points * @brief Conductor::segmentsToPath
*/ * Generate the QPainterPath from the list of points
void Conductor::segmentsToPath() { */
// chemin qui sera dessine void Conductor::segmentsToPath()
{
QPainterPath path; QPainterPath path;
// s'il n'y a pa des segments, on arrete la if (segments == NULL)
if (segments == NULL) setPath(path); setPath(path);
// demarre le chemin //Start the path
path.moveTo(segments -> firstPoint()); path.moveTo(segments -> firstPoint());
//Each segments
// parcourt les segments pour dessiner le chemin
ConductorSegment *segment = segments; ConductorSegment *segment = segments;
while(segment -> hasNextSegment()) { while(segment -> hasNextSegment()) {
path.lineTo(segment -> secondPoint()); path.lineTo(segment -> secondPoint());
segment = segment -> nextSegment(); segment = segment -> nextSegment();
} }
//Finish the path
// termine le chemin
path.lineTo(segment -> secondPoint()); path.lineTo(segment -> secondPoint());
// affecte le chemin au conducteur
setPath(path); 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 Dessine le conducteur sans antialiasing.
* Draw the conductor @param qp Le QPainter a utiliser pour dessiner le conducteur
* @param qp @param options Les options de style pour le conducteur
* @param options @param qw Le QWidget sur lequel on dessine
* @param qw */
*/
void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWidget *qw) void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWidget *qw)
{ {
Q_UNUSED(qw); Q_UNUSED(qw);
@@ -501,7 +509,7 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
final_conductor_pen.setCosmetic(true); final_conductor_pen.setCosmetic(true);
} }
qp->setPen(final_conductor_pen); qp -> setPen(final_conductor_pen);
//Draw the conductor //Draw the conductor
qp -> drawPath(path()); qp -> drawPath(path());
@@ -529,23 +537,18 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
if (isSelected()) qp -> setBrush(Qt::NoBrush); 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 //Draw the junctions
const QList<QPointF> junctions_list = junctions(); QList<QPointF> junctions_list = junctions();
if (!junctions_list.isEmpty()) if (!junctions_list.isEmpty()) {
{
final_conductor_pen.setStyle(Qt::SolidLine); final_conductor_pen.setStyle(Qt::SolidLine);
QBrush junction_brush(final_conductor_color, Qt::SolidPattern); QBrush junction_brush(final_conductor_color, Qt::SolidPattern);
qp -> setPen(final_conductor_pen); qp -> setPen(final_conductor_pen);
qp -> setBrush(junction_brush); qp -> setBrush(junction_brush);
qp -> setRenderHint(QPainter::Antialiasing, true); qp -> setRenderHint(QPainter::Antialiasing, true);
foreach(QPointF point, junctions_list) {
for(QPointF point : junctions_list)
qp -> drawEllipse(QRectF(point.x() - 1.5, point.y() - 1.5, 3.0, 3.0)); qp -> drawEllipse(QRectF(point.x() - 1.5, point.y() - 1.5, 3.0, 3.0));
} }
}
qp -> restore(); qp -> restore();
} }
@@ -603,70 +606,18 @@ void Conductor::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
*/ */
void Conductor::mousePressEvent(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); QGraphicsPathItem::mousePressEvent(event);
if (event -> modifiers() & Qt::ControlModifier) if (event->modifiers() & Qt::ControlModifier)
setSelected(!isSelected()); 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 * @brief Conductor::mouseReleaseEvent
* Manage the mouse release event
* @param event * @param event
*/ */
void Conductor::mouseReleaseEvent(QGraphicsSceneMouseEvent *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)) if (!(event -> modifiers() & Qt::ControlModifier))
QGraphicsPathItem::mouseReleaseEvent(event); QGraphicsPathItem::mouseReleaseEvent(event);
} }
@@ -694,56 +645,209 @@ void Conductor::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
} }
/** /**
* @brief Conductor::hoverMoveEvent conductor * @brief Conductor::itemChange
* @param e QGraphicsSceneHoverEvent describing the event * @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), if (value.toBool())
//we get the segment corresponding to the handler
int index = m_handler.pointIsHoverHandler(event->pos(), handlerPoints());
if (index > -1)
{ {
ConductorSegment *segment_ = segmentsList().at(index+1); m_previous_z_value = zValue();
if (m_handler.pointIsInHandler(event->pos(), segment_->secondPoint())) setZValue(qAbs(m_previous_z_value) + 10000);
setCursor(Qt::ForbiddenCursor); addHandler();
else if (m_handler.pointIsInHandler(event->pos(), segment_->middle()))
setCursor(segmentsList().at(index+1)->isVertical() ? Qt::SplitHCursor : Qt::SplitVCursor);
} }
else 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 * @brief Conductor::sceneEventFilter
Reimplemente ici pour : * @param watched
* positionner le conducteur en avant-plan lorsqu'il est selectionne * @param event
@param change Type de changement * @return
@param value Valeur relative au changement */
*/ bool Conductor::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value) { {
if (change == QGraphicsItem::ItemSelectedChange) { //Watched must be an handler
if (value.toBool()) { if(watched->type() == QetGraphicsHandlerItem::Type)
// le conducteur vient de se faire selectionner {
previous_z_value = zValue(); QetGraphicsHandlerItem *qghi = qgraphicsitem_cast<QetGraphicsHandlerItem *>(watched);
setZValue(qAbs(previous_z_value) + 10000);
} else { if(m_handler_vector.contains(qghi)) //Handler must be in m_vector_index, then we can start resize
// le conducteur vient de se faire deselectionner {
setZValue(previous_z_value); 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) { else if(event->type() == QEvent::GraphicsSceneMouseMove) //Move
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema {
calculateTextItemPosition(); handlerMouseMoveEvent(qghi, static_cast<QGraphicsSceneMouseEvent *>(event));
} else if (change == QGraphicsItem::ItemVisibleHasChanged) { return true;
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema }
calculateTextItemPosition(); 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())); 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_; return shape_;
} }

View File

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

View File

@@ -22,6 +22,7 @@
#include "shapegraphicsitempropertieswidget.h" #include "shapegraphicsitempropertieswidget.h"
#include "PropertiesEditor/propertieseditordialog.h" #include "PropertiesEditor/propertieseditordialog.h"
#include "QPropertyUndoCommand/qpropertyundocommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h"
#include "qetxml.h" #include "qetxml.h"
/** /**
@@ -37,18 +38,20 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem
m_shapeType(type), m_shapeType(type),
m_P1 (p1), m_P1 (p1),
m_P2 (p2), m_P2 (p2),
m_hovered(false), m_hovered(false)
m_mouse_grab_handler(false),
m_handler(10)
{ {
if (type == Polygon) m_polygon << m_P1 << m_P2; if (type == Polygon) m_polygon << m_P1 << m_P2;
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
m_pen.setStyle(Qt::DashLine); m_pen.setStyle(Qt::DashLine);
} }
QetShapeItem::~QetShapeItem() {} QetShapeItem::~QetShapeItem()
{
if(!m_handler_vector.isEmpty())
qDeleteAll(m_handler_vector);
}
/** /**
* @brief QetShapeItem::setPen * @brief QetShapeItem::setPen
@@ -109,6 +112,7 @@ bool QetShapeItem::setLine(const QLineF &line)
prepareGeometryChange(); prepareGeometryChange();
m_P1 = line.p1(); m_P1 = line.p1();
m_P2 = line.p2(); m_P2 = line.p2();
adjusteHandlerPos();
return true; return true;
} }
@@ -125,6 +129,7 @@ bool QetShapeItem::setRect(const QRectF &rect)
prepareGeometryChange(); prepareGeometryChange();
m_P1 = rect.topLeft(); m_P1 = rect.topLeft();
m_P2 = rect.bottomRight(); m_P2 = rect.bottomRight();
adjusteHandlerPos();
return true; return true;
} }
@@ -142,6 +147,7 @@ bool QetShapeItem::setPolygon(const QPolygonF &polygon)
if (Q_UNLIKELY(m_shapeType != Polygon)) return false; if (Q_UNLIKELY(m_shapeType != Polygon)) return false;
prepareGeometryChange(); prepareGeometryChange();
m_polygon = polygon; m_polygon = polygon;
adjusteHandlerPos();
return true; return true;
} }
@@ -246,23 +252,6 @@ QPainterPath QetShapeItem::shape() const
pps.setJoinStyle(Qt::RoundJoin); pps.setJoinStyle(Qt::RoundJoin);
path = pps.createStroke(path); 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); return (path);
} }
@@ -294,33 +283,14 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
painter -> restore (); painter -> restore ();
} }
//Draw the shape and handlers if is selected
switch (m_shapeType) switch (m_shapeType)
{ {
case Line: case Line: painter->drawLine(QLineF(m_P1, m_P2)); break;
painter->drawLine(QLineF(m_P1, m_P2)); case Rectangle: painter->drawRect(QRectF(m_P1, m_P2)); break;
if (isSelected()) case Ellipse: painter->drawEllipse(QRectF(m_P1, m_P2)); break;
m_handler.drawHandler(painter, QVector<QPointF>{m_P1, m_P2}); case Polygon: m_close ? painter->drawPolygon(m_polygon) : painter->drawPolyline(m_polygon); break;
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;
} }
painter->restore(); painter->restore();
} }
@@ -329,142 +299,23 @@ void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
* Handle hover enter event * Handle hover enter event
* @param event * @param event
*/ */
void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { void QetShapeItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = true; m_hovered = true;
QetGraphicsItem::hoverEnterEvent(event); 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 * @brief QetShapeItem::hoverLeaveEvent
* Handle hover leave event * Handle hover leave event
* @param event * @param event
*/ */
void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { void QetShapeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = false; m_hovered = false;
unsetCursor();
QetGraphicsItem::hoverLeaveEvent(event); 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 * @brief QetShapeItem::mouseReleaseEvent
* Handle mouse release event * Handle mouse release event
@@ -472,12 +323,228 @@ void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/ */
void QetShapeItem::mouseReleaseEvent(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(); 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()) if (diagram())
{ {
QPropertyUndoCommand *undo = nullptr; QPropertyUndoCommand *undo = nullptr;
@@ -501,23 +568,6 @@ void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
diagram()->undoStack().push(undo); 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 <QPen>
#include "qetgraphicsitem.h" #include "qetgraphicsitem.h"
#include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" #include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
class QDomElement; class QDomElement;
class QDomDocument; class QDomDocument;
class QetGraphicsHandlerItem;
/** /**
* @brief The QetShapeItem class * @brief The QetShapeItem class
@@ -96,14 +97,18 @@ class QetShapeItem : public QetGraphicsItem
protected: protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event); virtual void hoverEnterEvent (QGraphicsSceneHoverEvent *event);
virtual void hoverMoveEvent (QGraphicsSceneHoverEvent *event);
virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event); virtual void hoverLeaveEvent (QGraphicsSceneHoverEvent *event);
virtual void mousePressEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private: private:
void switchResizeMode(); void switchResizeMode();
void adjusteHandlerPos();
void handlerMousePressEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent (QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event);
///ATTRIBUTES ///ATTRIBUTES
private: private:
@@ -112,11 +117,10 @@ class QetShapeItem : public QetGraphicsItem
QBrush m_brush; QBrush m_brush;
QPointF m_P1, m_P2, m_old_P1, m_old_P2; QPointF m_P1, m_P2, m_old_P1, m_old_P2;
QPolygonF m_polygon, m_old_polygon; QPolygonF m_polygon, m_old_polygon;
bool m_hovered, bool m_hovered;
m_mouse_grab_handler;
int m_vector_index; int m_vector_index;
QetGraphicsHandlerUtility m_handler;
bool m_close = false; bool m_close = false;
int m_resize_mode = 1; int m_resize_mode = 1;
QVector<QetGraphicsHandlerItem *> m_handler_vector;
}; };
#endif // QETSHAPEITEM_H #endif // QETSHAPEITEM_H