diff --git a/sources/editor/editorcommands.cpp b/sources/editor/editorcommands.cpp index 0be416769..ece66c7ca 100644 --- a/sources/editor/editorcommands.cpp +++ b/sources/editor/editorcommands.cpp @@ -609,3 +609,67 @@ void changeElementDataCommand::redo() { m_scene->setElementData(m_new); QUndoCommand::redo(); } + +RotateElementsCommand::RotateElementsCommand(ElementScene *scene, QUndoCommand *parent) : +ElementEditionCommand(QObject::tr("Pivoter la selection", "undo caption"), scene, nullptr, parent) +{ + m_items = scene->selectedItems(); +} + +/** + @brief RotateElementsCommand::undo +*/ +void RotateElementsCommand::undo() +{ + for (QGraphicsItem *item : m_items) + { + if (item->type() == PartTerminal::Type) { + PartTerminal* term = qgraphicsitem_cast(item); + term->setRotation(term->rotation()-90); + } + else if (item->type() == PartRectangle::Type) { + PartRectangle* rect = qgraphicsitem_cast(item); + rect->setRotation(rect->rotation()-90); + } + else if (item->type() == PartLine::Type) { + PartLine* line = qgraphicsitem_cast(item); + line->setRotation(line->rotation()-90); + } + else if (item->type() == PartPolygon::Type) { + PartPolygon* poly = qgraphicsitem_cast(item); + poly->setRotation(poly->rotation()-90); + } + else { + item->setRotation(item->rotation()-90); + } + } +} +/** + @brief RotateElementsCommand::redo +*/ +void RotateElementsCommand::redo() +{ + for (QGraphicsItem *item : m_items) + { + if (item->type() == PartTerminal::Type) { + PartTerminal* term = qgraphicsitem_cast(item); + term->setRotation(term->rotation()+90); + } + else if (item->type() == PartRectangle::Type) { + PartRectangle* rect = qgraphicsitem_cast(item); + rect->setRotation(rect->rotation()+90); + } + else if (item->type() == PartLine::Type) { + PartLine* line = qgraphicsitem_cast(item); + line->setRotation(line->rotation()+90); + } + else if (item->type() == PartPolygon::Type) { + PartPolygon* poly = qgraphicsitem_cast(item); + poly->setRotation(poly->rotation()+90); + } + else { + item->setRotation(item->rotation()+90); + } + } + +} diff --git a/sources/editor/editorcommands.h b/sources/editor/editorcommands.h index 414cf17bb..6e803b3c9 100644 --- a/sources/editor/editorcommands.h +++ b/sources/editor/editorcommands.h @@ -22,6 +22,19 @@ #include "elementcontent.h" #include "elementscene.h" #include "elementview.h" +#include "graphicspart/abstractpartellipse.h" +#include "graphicspart/customelementgraphicpart.h" +#include "graphicspart/customelementpart.h" +#include "graphicspart/partarc.h" +#include "graphicspart/partdynamictextfield.h" +#include "graphicspart/partellipse.h" +#include "graphicspart/partline.h" +#include "graphicspart/partpolygon.h" +#include "graphicspart/partrectangle.h" +#include "graphicspart/partterminal.h" +#include "graphicspart/parttext.h" +#include "../QPropertyUndoCommand/qpropertyundocommand.h" + /** @brief The ElementEditionCommand class @@ -279,4 +292,24 @@ class changeElementDataCommand : public ElementEditionCommand m_new; }; +/** + @brief The RotateSelectionInESCommand class + Rotate the selected items in the element editor +*/ + +class RotateElementsCommand : public ElementEditionCommand +{ + +public: + RotateElementsCommand(ElementScene *scene, QUndoCommand *parent=nullptr); + void undo() override; + void redo() override; + +private: + ElementScene *m_scene =nullptr; + QList m_items; + +}; + + #endif diff --git a/sources/editor/graphicspart/partline.cpp b/sources/editor/graphicspart/partline.cpp index bc7006e0f..06174badc 100644 --- a/sources/editor/graphicspart/partline.cpp +++ b/sources/editor/graphicspart/partline.cpp @@ -603,6 +603,19 @@ void PartLine::setSecondEndLength(const qreal &l) emit secondEndLengthChanged(); } +void PartLine::setRotation(qreal angle) { + + QTransform rotation = QTransform().translate(m_line.p1().x(),m_line.p1().y()).rotate(angle-m_rot).translate(-m_line.p1().x(),-m_line.p1().y()); + m_rot=angle; + + setLine(rotation.map(m_line)); +} + +qreal PartLine::rotation() const { + return m_rot; +} + + /** @brief PartLine::path @return this line has a QPainterPath. diff --git a/sources/editor/graphicspart/partline.h b/sources/editor/graphicspart/partline.h index a2fc0ef81..647df4c60 100644 --- a/sources/editor/graphicspart/partline.h +++ b/sources/editor/graphicspart/partline.h @@ -94,6 +94,8 @@ class PartLine : public CustomElementGraphicPart void setFirstEndLength(const qreal &l); qreal secondEndLength() const {return second_length;} void setSecondEndLength(const qreal &l); + void setRotation(qreal angle); + qreal rotation() const; protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; @@ -124,5 +126,6 @@ class PartLine : public CustomElementGraphicPart int m_vector_index = -1; QPropertyUndoCommand *m_undo_command; QVector m_handler_vector; + qreal m_rot; }; #endif diff --git a/sources/editor/graphicspart/partpolygon.cpp b/sources/editor/graphicspart/partpolygon.cpp index 5e142b374..0b7be6ee5 100644 --- a/sources/editor/graphicspart/partpolygon.cpp +++ b/sources/editor/graphicspart/partpolygon.cpp @@ -293,6 +293,21 @@ void PartPolygon::resetAllHandlerColor() } } + +void PartPolygon::setRotation(qreal angle) { + + QTransform rotation = QTransform().translate(m_polygon.first().x(),m_polygon.first().y()).rotate(angle-m_rot).translate(-m_polygon.first().x(),-m_polygon.first().y()); + m_rot=angle; + + setPolygon(rotation.map(m_polygon)); +} + +qreal PartPolygon::rotation() const { + return m_rot; +} + + + /** @brief PartPolygon::itemChange @param change diff --git a/sources/editor/graphicspart/partpolygon.h b/sources/editor/graphicspart/partpolygon.h index 282f4f126..2bfc72176 100644 --- a/sources/editor/graphicspart/partpolygon.h +++ b/sources/editor/graphicspart/partpolygon.h @@ -87,6 +87,9 @@ class PartPolygon : public CustomElementGraphicPart void setHandlerColor(QPointF pos, const QColor &color) final; void resetAllHandlerColor() final; + void setRotation (qreal angle); + qreal rotation () const; + protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override; @@ -114,5 +117,6 @@ class PartPolygon : public CustomElementGraphicPart QAction *m_insert_point, *m_remove_point; QPointF m_context_menu_pos; + qreal m_rot; }; #endif diff --git a/sources/editor/graphicspart/partrectangle.cpp b/sources/editor/graphicspart/partrectangle.cpp index b9d2c2110..73e6020d3 100644 --- a/sources/editor/graphicspart/partrectangle.cpp +++ b/sources/editor/graphicspart/partrectangle.cpp @@ -30,7 +30,9 @@ */ PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent) : CustomElementGraphicPart(editor, parent) -{} +{ + m_rot=0; +} /** @brief PartRectangle::~PartRectangle @@ -169,6 +171,18 @@ void PartRectangle::setYRadius(qreal Y) emit YRadiusChanged(); } +void PartRectangle::setRotation(qreal angle) { + + QTransform rotation = QTransform().rotate(angle-m_rot); + m_rot=angle; + + setRect(rotation.mapRect(m_rect)); +} + +qreal PartRectangle::rotation() const { + return m_rot; +} + /** @brief PartRectangle::sceneGeometricRect @return the minimum, margin-less rectangle this part can fit into, in scene @@ -187,7 +201,7 @@ QRectF PartRectangle::sceneGeometricRect() const */ QPointF PartRectangle::sceneTopLeft() const { - return(mapToScene(rect().topLeft())); + return(mapToScene(rect().topLeft())); } /** diff --git a/sources/editor/graphicspart/partrectangle.h b/sources/editor/graphicspart/partrectangle.h index e8bbc3946..64b743a56 100644 --- a/sources/editor/graphicspart/partrectangle.h +++ b/sources/editor/graphicspart/partrectangle.h @@ -34,6 +34,7 @@ class PartRectangle : public CustomElementGraphicPart Q_PROPERTY(QRectF rect READ rect WRITE setRect) Q_PROPERTY(qreal xRadius READ XRadius WRITE setXRadius NOTIFY XRadiusChanged) Q_PROPERTY(qreal yRadius READ YRadius WRITE setYRadius NOTIFY YRadiusChanged) + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) // constructors, destructor public: @@ -47,6 +48,7 @@ class PartRectangle : public CustomElementGraphicPart void rectChanged(); void XRadiusChanged(); void YRadiusChanged(); + void rotationChanged(); // methods public: @@ -69,6 +71,8 @@ class PartRectangle : public CustomElementGraphicPart void setXRadius(qreal X); qreal YRadius() const {return m_yRadius;} void setYRadius(qreal Y); + void setRotation(qreal angle); + qreal rotation() const; QRectF sceneGeometricRect() const override; virtual QPointF sceneTopLeft() const; @@ -109,5 +113,6 @@ class PartRectangle : public CustomElementGraphicPart m_old_xRadius, m_old_yRadius; bool m_modifie_radius_equaly = false; + qreal m_rot; }; #endif diff --git a/sources/editor/graphicspart/partterminal.cpp b/sources/editor/graphicspart/partterminal.cpp index 3c5539f1a..6a1c2d461 100644 --- a/sources/editor/graphicspart/partterminal.cpp +++ b/sources/editor/graphicspart/partterminal.cpp @@ -140,6 +140,7 @@ QRectF PartTerminal::boundingRect() const return(br); } + /** Definit l'orientation de la borne @param ori la nouvelle orientation de la borne @@ -151,6 +152,32 @@ void PartTerminal::setOrientation(Qet::Orientation ori) { updateSecondPoint(); emit orientationChanged(); } + +/** + Redéfinit la fonction de rotation pour la traduire en orientation de la borne + @param angle +*/ +void PartTerminal::setRotation(qreal angle) { + qreal angle_mod = std::fmod(angle,360); + Qet::Orientation new_ori = Qet::North; + + if (0 <= angle_mod && angle_mod < 90 ) new_ori = Qet::North; + else if (90 <= angle_mod && angle_mod < 180) new_ori = Qet::East; + else if (180 <= angle_mod && angle_mod < 270) new_ori = Qet::South; + else new_ori = Qet::West; + + setOrientation(new_ori); +} + +qreal PartTerminal::rotation() const { + switch (d->m_orientation) { + case Qet::North : return 0; + case Qet::East : return 90; + case Qet::South : return 180; + case Qet::West : return 270; + } +} + /** @brief PartTerminal::setName @param name diff --git a/sources/editor/graphicspart/partterminal.h b/sources/editor/graphicspart/partterminal.h index ad023f0b6..5a1577c4f 100644 --- a/sources/editor/graphicspart/partterminal.h +++ b/sources/editor/graphicspart/partterminal.h @@ -72,7 +72,11 @@ class PartTerminal : public CustomElementGraphicPart void handleUserTransformation(const QRectF &, const QRectF &) override; Qet::Orientation orientation() const {return d -> m_orientation;} - void setOrientation(Qet::Orientation ori); + void setOrientation(Qet::Orientation ori); + + qreal rotation() const; + void setRotation(qreal angle); + QString name() const override { return d -> m_name; } void setName(QString& name); diff --git a/sources/editor/ui/qetelementeditor.cpp b/sources/editor/ui/qetelementeditor.cpp index 661d19843..0374e4b63 100644 --- a/sources/editor/ui/qetelementeditor.cpp +++ b/sources/editor/ui/qetelementeditor.cpp @@ -109,6 +109,7 @@ void QETElementEditor::contextMenu(QPoint p, QList actions) menu.addAction(ui->m_delete_action); menu.addAction(ui->m_cut_action); menu.addAction(ui->m_copy_action); + menu.addAction((ui->m_rotate_action)); menu.addSeparator(); menu.addAction(ui->m_paste_action); menu.addAction(ui->m_paste_in_area_action); @@ -1018,7 +1019,10 @@ void QETElementEditor::setupActions() depth_toolbar -> addActions(m_depth_action_group -> actions()); addToolBar(Qt::TopToolBarArea, depth_toolbar); - //Zoom action + //Rotate action + connect(ui->m_rotate_action, &QAction::triggered, [this]() {this -> elementScene() -> undoStack().push(new RotateElementsCommand(this->elementScene()));}); + + //Zoom action ui->m_zoom_in_action -> setShortcut(QKeySequence::ZoomIn); ui->m_zoom_out_action -> setShortcut(QKeySequence::ZoomOut); ui->m_zoom_fit_best_action -> setShortcut(QKeySequence(tr("Ctrl+9"))); diff --git a/sources/editor/ui/qetelementeditor.ui b/sources/editor/ui/qetelementeditor.ui index d63959565..bbdc88564 100644 --- a/sources/editor/ui/qetelementeditor.ui +++ b/sources/editor/ui/qetelementeditor.ui @@ -25,7 +25,7 @@ 0 0 800 - 21 + 20 @@ -75,6 +75,7 @@ + @@ -488,6 +489,18 @@ Affiche des informations sur la bibliothèque Qt + + + + :/ico/16x16/orientations.png:/ico/16x16/orientations.png + + + Rotation + + + Space + +