From 27117ef9d14d0aebd3f9b55b7e49908efd029ed3 Mon Sep 17 00:00:00 2001 From: blacksun Date: Sun, 12 Jul 2015 13:35:40 +0000 Subject: [PATCH] Add undo command for QetShapeItem geometry change git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4046 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- dev_doc/ID_of_QUndoCommand.txt | 1 + sources/qetgraphicsitem/qetshapeitem.cpp | 94 ++++++++++---- sources/qetgraphicsitem/qetshapeitem.h | 8 +- .../undocommand/qetshapegeometrycommand.cpp | 122 ++++++++++++++++++ sources/undocommand/qetshapegeometrycommand.h | 54 ++++++++ 5 files changed, 249 insertions(+), 30 deletions(-) create mode 100644 sources/undocommand/qetshapegeometrycommand.cpp create mode 100644 sources/undocommand/qetshapegeometrycommand.h diff --git a/dev_doc/ID_of_QUndoCommand.txt b/dev_doc/ID_of_QUndoCommand.txt index 572defc9f..8be57ee23 100755 --- a/dev_doc/ID_of_QUndoCommand.txt +++ b/dev_doc/ID_of_QUndoCommand.txt @@ -2,3 +2,4 @@ ChangeElementInformationCommand = 1 LinkElementCommand = 2 ItemResizerCommand = 3 ChangeShapeStyleCommand = 4 +QetShapeGeometryCommand = 5 diff --git a/sources/qetgraphicsitem/qetshapeitem.cpp b/sources/qetgraphicsitem/qetshapeitem.cpp index e3bfcfda6..3b3606fa4 100644 --- a/sources/qetgraphicsitem/qetshapeitem.cpp +++ b/sources/qetgraphicsitem/qetshapeitem.cpp @@ -22,6 +22,7 @@ #include "shapegraphicsitempropertieswidget.h" #include "PropertiesEditor/propertieseditordialog.h" #include "QetGraphicsItemModeler/qetgraphicshandlerutility.h" +#include "qetshapegeometrycommand.h" typedef QetGraphicsHandlerUtility QGHU; @@ -40,7 +41,8 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem m_P1 (Diagram::snapToGrid(p1)), m_P2 (Diagram::snapToGrid(p2)), m_hovered(false), - m_mouse_grab_handler(false) + m_mouse_grab_handler(false), + m_undo_command(nullptr) { if (type == Polyline) m_polygon << m_P1 << m_P2; @@ -49,7 +51,9 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem } QetShapeItem::~QetShapeItem() -{} +{ + if (m_undo_command) delete m_undo_command; +} /** * @brief QetShapeItem::setStyle @@ -70,21 +74,36 @@ void QetShapeItem::setStyle(Qt::PenStyle newStyle) * the last point of the polyline is replaced by P2. * @param P2 */ -void QetShapeItem::setP2(QPointF P2) { - P2 = Diagram::snapToGrid(P2); - - if (m_shapeType == Polyline) { +void QetShapeItem::setP2(const QPointF &P2) +{ + if (m_shapeType == Polyline && m_polygon.last() != P2) + { prepareGeometryChange(); m_polygon.replace(m_polygon.size()-1, P2); } - else { - if (P2 == m_P2) return; + else if (P2 != m_P2) + { prepareGeometryChange(); m_P2 = P2; } setTransformOriginPoint(boundingRect().center()); } +/** + * @brief QetShapeItem::setLine + * Set item geometry to line (only available for line shape) + * @param line + */ +void QetShapeItem::setLine(const QLineF &line) +{ + if (Q_LIKELY(m_shapeType == Line)) + { + prepareGeometryChange(); + m_P1 = line.p1(); + m_P2 = line.p2(); + } +} + /** * @brief QetShapeItem::setRect * Set this item geometry to rect (only available if shape is a rectangle or an ellipse) @@ -110,7 +129,7 @@ bool QetShapeItem::setRect(const QRectF &rect) * @param polygon : new polygon * @return true if item is polygon, else false */ -bool QetShapeItem::setPolygon(const QPolygon &polygon) +bool QetShapeItem::setPolygon(const QPolygonF &polygon) { if (Q_UNLIKELY(m_shapeType != Polyline)) return false; prepareGeometryChange(); @@ -173,26 +192,18 @@ QRectF QetShapeItem::boundingRect() const { * @brief QetShapeItem::shape * @return the shape of this item */ -QPainterPath QetShapeItem::shape() const { +QPainterPath QetShapeItem::shape() const +{ QPainterPath path; - switch (m_shapeType) { - case Line: - path.moveTo(m_P1); - path.lineTo(m_P2); - break; - case Rectangle: - path.addRect(QRectF(m_P1, m_P2)); - break; - case Ellipse: - path.addEllipse(QRectF(m_P1, m_P2)); - break; - case Polyline: - path.addPolygon(m_polygon); - break; - default: - Q_ASSERT(false); - break; + switch (m_shapeType) + { + case Line: path.moveTo(m_P1); + path.lineTo(m_P2); break; + case Rectangle: path.addRect(QRectF(m_P1, m_P2)); break; + case Ellipse: path.addEllipse(QRectF(m_P1, m_P2)); break; + case Polyline: path.addPolygon(m_polygon); break; + default: Q_ASSERT(false); break; } QPainterPathStroker pps; @@ -371,6 +382,14 @@ void QetShapeItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { //User click on an handler m_mouse_grab_handler = true; + + switch (m_shapeType) + { + case Line: m_undo_command = new QetShapeGeometryCommand(this, QLineF(m_P1, m_P2)); break; + case Rectangle: m_undo_command = new QetShapeGeometryCommand(this, QRectF(m_P1, m_P2)); break; + case Ellipse: m_undo_command = new QetShapeGeometryCommand(this, QRectF(m_P1, m_P2)); break; + case Polyline: m_undo_command = new QetShapeGeometryCommand(this, m_polygon); break; + } return; } } @@ -441,7 +460,26 @@ void QetShapeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) */ void QetShapeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - m_mouse_grab_handler = false; + if (m_mouse_grab_handler) + { + m_mouse_grab_handler = false; + switch(m_shapeType) + { + case Line: m_undo_command->setNewLine(QLineF(m_P1, m_P2)); break; + case Rectangle: m_undo_command->setNewRect(QRectF(m_P1, m_P2)); break; + case Ellipse: m_undo_command->setNewRect(QRectF(m_P1, m_P2)); break; + case Polyline : m_undo_command->setNewPolygon(m_polygon); break; + } + + if (diagram()) + { + diagram()->undoStack().push(m_undo_command); + m_undo_command = nullptr; + } + else + delete m_undo_command; + } + QetGraphicsItem::mouseReleaseEvent(event); } diff --git a/sources/qetgraphicsitem/qetshapeitem.h b/sources/qetgraphicsitem/qetshapeitem.h index af023b06d..f0d631935 100644 --- a/sources/qetgraphicsitem/qetshapeitem.h +++ b/sources/qetgraphicsitem/qetshapeitem.h @@ -22,6 +22,7 @@ class QDomElement; class QDomDocument; +class QetShapeGeometryCommand; /** * @brief The QetShapeItem class @@ -53,6 +54,7 @@ class QetShapeItem : public QetGraphicsItem ///METHODS void setStyle(Qt::PenStyle); Qt::PenStyle penStyle() const { return m_shapeStyle;} + ShapeType shapeType() const {return m_shapeType;} virtual bool fromXml (const QDomElement &); virtual QDomElement toXml (QDomDocument &document) const; @@ -61,9 +63,10 @@ class QetShapeItem : public QetGraphicsItem virtual void editProperty(); virtual QString name() const; - void setP2 (QPointF P2); + void setP2 (const QPointF &P2); + void setLine (const QLineF &line); bool setRect (const QRectF &rect); - bool setPolygon (const QPolygon &polygon); + bool setPolygon (const QPolygonF &polygon); //Methods available for polygon shape int pointsCount () const; @@ -93,5 +96,6 @@ class QetShapeItem : public QetGraphicsItem bool m_hovered, m_mouse_grab_handler; int m_vector_index; + QetShapeGeometryCommand *m_undo_command; }; #endif // QETSHAPEITEM_H diff --git a/sources/undocommand/qetshapegeometrycommand.cpp b/sources/undocommand/qetshapegeometrycommand.cpp new file mode 100644 index 000000000..076fdc8e4 --- /dev/null +++ b/sources/undocommand/qetshapegeometrycommand.cpp @@ -0,0 +1,122 @@ +/* + Copyright 2006-2015 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "qetshapegeometrycommand.h" +#include "qetshapeitem.h" +#include + +/** + * @brief QetShapeGeometryCommand::QetShapeGeometryCommand + * Constructor for a line shape + * @param item : item to change the geometry + * @param old_line : old line + * @param parent : parent undo command + */ +QetShapeGeometryCommand::QetShapeGeometryCommand(QetShapeItem *item, const QLineF &old_line, QUndoCommand *parent) : + QUndoCommand(parent), + m_shape_item(item), + m_old_line(old_line) +{ + setText(QObject::tr("Modifier la géometrie de : %1").arg(m_shape_item->name())); +} + +/** + * @brief QetShapeGeometryCommand::QetShapeGeometryCommand + * Constructor for a rectangle or ellipse shape + * @param item : item to change the geometry + * @param old_rect : old rectangle + * @param parent : parent undo command + */ +QetShapeGeometryCommand::QetShapeGeometryCommand(QetShapeItem *item, const QRectF &old_rect, QUndoCommand *parent): + QUndoCommand(parent), + m_shape_item(item), + m_old_rect(old_rect) +{ + setText(QObject::tr("Modifier la géometrie de : %1").arg(m_shape_item->name())); +} + +/** + * @brief QetShapeGeometryCommand::QetShapeGeometryCommand + * Constructor for polygon shape + * @param item : item to change the geometry + * @param old_polygon : old polygon + * @param parent : parent undo command + */ +QetShapeGeometryCommand::QetShapeGeometryCommand(QetShapeItem *item, const QPolygonF &old_polygon, QUndoCommand *parent): + QUndoCommand(parent), + m_shape_item(item), + m_old_polygon(old_polygon) +{ + setText(QObject::tr("Modifier la géometrie de : %1").arg(m_shape_item->name())); +} + +/** + * @brief QetShapeGeometryCommand::mergeWith + * Try to merge this undo command with @other + * @param other + * @return true if the two command was merged + */ +bool QetShapeGeometryCommand::mergeWith(const QUndoCommand *other) +{ + if (other->id() != id() || other->childCount()) return false; + const QetShapeGeometryCommand *other_undo = static_cast(other); + if (other_undo->m_shape_item != m_shape_item) return false; + + switch (m_shape_item->shapeType()) + { + case QetShapeItem::Line: m_new_line = other_undo->m_new_line; break; + case QetShapeItem::Rectangle: m_new_rect = other_undo->m_new_rect; break; + case QetShapeItem::Ellipse: m_new_rect = other_undo->m_new_rect; break; + case QetShapeItem::Polyline: m_new_polygon = other_undo->m_new_polygon; break; + } + + return true; +} + +/** + * @brief QetShapeGeometryCommand::redo + * Redo this command + */ +void QetShapeGeometryCommand::redo() +{ + switch (m_shape_item->shapeType()) + { + case QetShapeItem::Line: m_shape_item->setLine(m_new_line); break; + case QetShapeItem::Rectangle: m_shape_item->setRect(m_new_rect); break; + case QetShapeItem::Ellipse: m_shape_item->setRect(m_new_rect); break; + case QetShapeItem::Polyline: m_shape_item->setPolygon(m_new_polygon); break; + } + + QUndoCommand::redo(); +} + +/** + * @brief QetShapeGeometryCommand::undo + * Undo this command + */ +void QetShapeGeometryCommand::undo() +{ + switch (m_shape_item->shapeType()) + { + case QetShapeItem::Line: m_shape_item->setLine(m_old_line); break; + case QetShapeItem::Rectangle: m_shape_item->setRect(m_old_rect); break; + case QetShapeItem::Ellipse: m_shape_item->setRect(m_old_rect); break; + case QetShapeItem::Polyline: m_shape_item->setPolygon(m_old_polygon); break; + } + + QUndoCommand::undo(); +} diff --git a/sources/undocommand/qetshapegeometrycommand.h b/sources/undocommand/qetshapegeometrycommand.h new file mode 100644 index 000000000..8ffb07542 --- /dev/null +++ b/sources/undocommand/qetshapegeometrycommand.h @@ -0,0 +1,54 @@ +/* + Copyright 2006-2015 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef QETSHAPEGEOMETRYCOMMAND_H +#define QETSHAPEGEOMETRYCOMMAND_H + +#include +#include +#include +#include +class QetShapeItem; + +/** + * @brief The QetShapeGeometryCommand class + * This undo command class manage the geometry change of a QetShapeItem. + */ +class QetShapeGeometryCommand : public QUndoCommand +{ + public: + QetShapeGeometryCommand(QetShapeItem *item, const QLineF &old_line, QUndoCommand *parent = nullptr); + QetShapeGeometryCommand(QetShapeItem *item, const QRectF &old_rect, QUndoCommand *parent = nullptr); + QetShapeGeometryCommand(QetShapeItem *item, const QPolygonF &old_polygon, QUndoCommand *parent = nullptr); + + void setNewLine (const QLineF &new_line) {m_new_line = new_line;} + void setNewRect (const QRectF &new_rect) {m_new_rect = new_rect;} + void setNewPolygon (const QPolygonF &new_polygon) {m_new_polygon = new_polygon;} + + int id() const {return 5;} + bool mergeWith(const QUndoCommand *other); + void redo(); + void undo(); + + private: + QetShapeItem *m_shape_item; + QLineF m_old_line, m_new_line; + QPolygonF m_old_polygon, m_new_polygon; + QRectF m_old_rect, m_new_rect; +}; + +#endif // QETSHAPEGEOMETRYCOMMAND_H