From 18d9417c9671aae93ad26f13a50d937b4d7e7fa8 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 19 Aug 2021 12:36:39 +0300 Subject: [PATCH] Undo/Redo transformation origin move. --- src/app/puzzle/layout/layoutdef.h | 13 ++ src/app/puzzle/layout/vplayout.h | 1 + src/app/puzzle/layout/vpsheet.h | 12 -- src/app/puzzle/puzzle.pri | 2 + .../puzzle/scene/vpgraphicspiececontrols.cpp | 13 +- .../puzzle/scene/vpgraphicspiececontrols.h | 6 +- src/app/puzzle/scene/vpmaingraphicsview.cpp | 21 ++- src/app/puzzle/undocommands/vpundocommand.cpp | 5 +- src/app/puzzle/undocommands/vpundocommand.h | 15 ++- .../puzzle/undocommands/vpundooriginmove.cpp | 121 ++++++++++++++++++ .../puzzle/undocommands/vpundooriginmove.h | 73 +++++++++++ .../puzzle/undocommands/vpundopiecemove.cpp | 23 +--- src/app/puzzle/undocommands/vpundopiecemove.h | 16 --- .../puzzle/undocommands/vpundopiecerotate.cpp | 10 +- .../puzzle/undocommands/vpundopiecerotate.h | 16 --- 15 files changed, 270 insertions(+), 77 deletions(-) create mode 100644 src/app/puzzle/undocommands/vpundooriginmove.cpp create mode 100644 src/app/puzzle/undocommands/vpundooriginmove.h diff --git a/src/app/puzzle/layout/layoutdef.h b/src/app/puzzle/layout/layoutdef.h index e33db2838..fa3db8f46 100644 --- a/src/app/puzzle/layout/layoutdef.h +++ b/src/app/puzzle/layout/layoutdef.h @@ -28,6 +28,7 @@ #ifndef LAYOUTDEF_H #define LAYOUTDEF_H +#include #include class VPLayout; @@ -42,4 +43,16 @@ class VPSheet; using VPSheetPtr = QSharedPointer; using VPSheetWeakPtr = QWeakPointer; +enum class GrainlineType : qint8 +{ + Vertical, + Horizontal +}; + +struct VPTransformationOrigon +{ + QPointF origin{}; + bool custom{false}; +}; + #endif // LAYOUTDEF_H diff --git a/src/app/puzzle/layout/vplayout.h b/src/app/puzzle/layout/vplayout.h index 5f96b732c..03e75bd91 100644 --- a/src/app/puzzle/layout/vplayout.h +++ b/src/app/puzzle/layout/vplayout.h @@ -88,6 +88,7 @@ signals: void PieceSheetChanged(const VPPiecePtr &piece); void ActiveSheetChanged(const VPSheetPtr &focusedSheet); void PieceTransformationChanged(const VPPiecePtr &piece); + void TransformationOriginChanged(); protected: explicit VPLayout(QUndoStack *undoStack); diff --git a/src/app/puzzle/layout/vpsheet.h b/src/app/puzzle/layout/vpsheet.h index 8ba028997..4624c3ff8 100644 --- a/src/app/puzzle/layout/vpsheet.h +++ b/src/app/puzzle/layout/vpsheet.h @@ -40,18 +40,6 @@ class VPLayout; class VPPiece; -enum class GrainlineType : qint8 -{ - Vertical, - Horizontal -}; - -struct VPTransformationOrigon -{ - QPointF origin{}; - bool custom{false}; -}; - class VPSheet { public: diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index fffdb9748..d8f1e8850 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -8,6 +8,7 @@ SOURCES += \ $$PWD/dialogs/vpdialogabout.cpp \ $$PWD/main.cpp \ $$PWD/undocommands/vpundocommand.cpp \ + $$PWD/undocommands/vpundooriginmove.cpp \ $$PWD/undocommands/vpundopiecemove.cpp \ $$PWD/undocommands/vpundopiecerotate.cpp \ $$PWD/vpapplication.cpp \ @@ -45,6 +46,7 @@ HEADERS += \ $$PWD/scene/scenedef.h \ $$PWD/stable.h \ $$PWD/undocommands/vpundocommand.h \ + $$PWD/undocommands/vpundooriginmove.h \ $$PWD/undocommands/vpundopiecemove.h \ $$PWD/undocommands/vpundopiecerotate.h \ $$PWD/vpapplication.h \ diff --git a/src/app/puzzle/scene/vpgraphicspiececontrols.cpp b/src/app/puzzle/scene/vpgraphicspiececontrols.cpp index c4339b444..852ecaf25 100644 --- a/src/app/puzzle/scene/vpgraphicspiececontrols.cpp +++ b/src/app/puzzle/scene/vpgraphicspiececontrols.cpp @@ -38,6 +38,7 @@ #include "../vwidgets/global.h" #include "../layout/vplayout.h" #include "../undocommands/vpundopiecerotate.h" +#include "../undocommands/vpundooriginmove.h" #include "vpgraphicspiece.h" namespace @@ -93,12 +94,16 @@ VPGraphicsTransformationOrigin::VPGraphicsTransformationOrigin(const VPLayoutPtr setCursor(Qt::OpenHandCursor); setZValue(1); setAcceptHoverEvents(true); + + connect(layout.get(), &VPLayout::TransformationOriginChanged, this, + &VPGraphicsTransformationOrigin::SetTransformationOrigin); } //--------------------------------------------------------------------------------------------------------------------- void VPGraphicsTransformationOrigin::SetTransformationOrigin() { prepareGeometryChange(); + update(); } //--------------------------------------------------------------------------------------------------------------------- @@ -181,11 +186,14 @@ void VPGraphicsTransformationOrigin::mouseMoveEvent(QGraphicsSceneMouseEvent *ev VPTransformationOrigon origin = sheet->TransformationOrigin(); origin.origin = event->scenePos(); origin.custom = true; - sheet->SetTransformationOrigin(origin); + + auto *command = new VPUndoOriginMove(sheet, origin, m_allowChangeMerge); + layout->UndoStack()->push(command); } prepareGeometryChange(); } + m_allowChangeMerge = true; QGraphicsObject::mouseMoveEvent(event); } @@ -199,6 +207,7 @@ void VPGraphicsTransformationOrigin::mouseReleaseEvent(QGraphicsSceneMouseEvent if (event->button() == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); + m_allowChangeMerge = false; } } @@ -779,7 +788,7 @@ auto VPGraphicsPieceControls::SelectedPieces() const -> QVector &selectedPieces) const -> QRectF +auto VPGraphicsPieceControls::PiecesBoundingRect(const QVector &selectedPieces) -> QRectF { QRectF rect; for (auto *item : selectedPieces) diff --git a/src/app/puzzle/scene/vpgraphicspiececontrols.h b/src/app/puzzle/scene/vpgraphicspiececontrols.h index 1a2561b97..9c838cec8 100644 --- a/src/app/puzzle/scene/vpgraphicspiececontrols.h +++ b/src/app/puzzle/scene/vpgraphicspiececontrols.h @@ -69,6 +69,7 @@ private: bool m_originVisible{true}; VPLayoutWeakPtr m_layout{}; QColor m_color; + bool m_allowChangeMerge{false}; auto RotationCenter(QPainter *painter = nullptr) const -> QPainterPath; auto Center1() const -> QPainterPath; @@ -127,9 +128,10 @@ private: auto ArrowPath() const -> QPainterPath; - auto SelectedPieces() const -> QVector; - auto PiecesBoundingRect(const QVector &selectedPieces) const -> QRectF; auto HandleCorner(const QPointF &pos) const -> int; + + auto SelectedPieces() const -> QVector; + static auto PiecesBoundingRect(const QVector &selectedPieces) -> QRectF; }; #endif // VPGRAPHICSPIECECONTROLS_H diff --git a/src/app/puzzle/scene/vpmaingraphicsview.cpp b/src/app/puzzle/scene/vpmaingraphicsview.cpp index c1286bc93..13d5e0458 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.cpp +++ b/src/app/puzzle/scene/vpmaingraphicsview.cpp @@ -47,6 +47,7 @@ #include "vpgraphicspiececontrols.h" #include "../undocommands/vpundopiecemove.h" #include "../undocommands/vpundopiecerotate.h" +#include "../undocommands/vpundooriginmove.h" #include @@ -440,9 +441,23 @@ void VPMainGraphicsView::RestoreOrigin() const if (not sheet.isNull()) { VPTransformationOrigon origin = sheet->TransformationOrigin(); - origin.custom = false; - sheet->SetTransformationOrigin(origin); - m_rotationControls->on_UpdateControls(); + if (origin.custom) + { // ignore if not custom. Prevent double call + origin.custom = false; + + QRectF boundingRect; + for (auto *graphicsPiece : m_graphicsPieces) + { + if (graphicsPiece->isSelected()) + { + boundingRect = boundingRect.united(graphicsPiece->sceneBoundingRect()); + } + } + origin.origin = boundingRect.center(); + + auto *command = new VPUndoOriginMove(sheet, origin); + layout->UndoStack()->push(command); + } } } diff --git a/src/app/puzzle/undocommands/vpundocommand.cpp b/src/app/puzzle/undocommands/vpundocommand.cpp index e262d3e45..d3b18baee 100644 --- a/src/app/puzzle/undocommands/vpundocommand.cpp +++ b/src/app/puzzle/undocommands/vpundocommand.cpp @@ -30,6 +30,7 @@ Q_LOGGING_CATEGORY(vpUndo, "vp.undo") //--------------------------------------------------------------------------------------------------------------------- -VPUndoCommand::VPUndoCommand(QUndoCommand *parent) - : QUndoCommand(parent) +VPUndoCommand::VPUndoCommand(bool allowMerge, QUndoCommand *parent) + : QUndoCommand(parent), + m_allowMerge(allowMerge) {} diff --git a/src/app/puzzle/undocommands/vpundocommand.h b/src/app/puzzle/undocommands/vpundocommand.h index 23f8c8e22..3d81dcc57 100644 --- a/src/app/puzzle/undocommands/vpundocommand.h +++ b/src/app/puzzle/undocommands/vpundocommand.h @@ -40,6 +40,7 @@ enum class UndoCommand: qint8 MovePieces = 1, RotatePiece = 2, RotatePieces = 3, + MoveOrigin = 4, }; } @@ -49,11 +50,23 @@ class VPUndoCommand : public QObject, public QUndoCommand { Q_OBJECT public: - explicit VPUndoCommand(QUndoCommand *parent = nullptr); + explicit VPUndoCommand(bool allowMerge = false, QUndoCommand *parent = nullptr); virtual ~VPUndoCommand() =default; + auto AllowMerge() const -> bool; + +protected: + bool m_allowMerge; + private: Q_DISABLE_COPY(VPUndoCommand) }; + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoCommand::AllowMerge() const -> bool +{ + return m_allowMerge; +} + #endif // VPUNDOCOMMAND_H diff --git a/src/app/puzzle/undocommands/vpundooriginmove.cpp b/src/app/puzzle/undocommands/vpundooriginmove.cpp new file mode 100644 index 000000000..7bc6d3fe5 --- /dev/null +++ b/src/app/puzzle/undocommands/vpundooriginmove.cpp @@ -0,0 +1,121 @@ +/************************************************************************ + ** + ** @file vpundooriginmove.cpp + ** @author Roman Telezhynskyi + ** @date 19 8, 2021 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina 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 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina 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 Valentina. If not, see . + ** + *************************************************************************/ +#include "vpundooriginmove.h" +#include "../vmisc/def.h" +#include "../layout/vpsheet.h" +#include "../layout/vplayout.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPUndoOriginMove::VPUndoOriginMove(const VPSheetPtr &sheet, const VPTransformationOrigon &origin, bool allowMerge, + QUndoCommand *parent) + : VPUndoCommand(allowMerge, parent), + m_sheet(sheet), + m_origin(origin) +{ + SCASSERT(not sheet.isNull()) + + m_oldOrigin = sheet->TransformationOrigin(); + + setText(QObject::tr("move transformation origin")); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoOriginMove::undo() +{ + VPSheetPtr sheet = m_sheet.toStrongRef(); + if (sheet.isNull()) + { + return; + } + + VPLayoutPtr layout = sheet->GetLayout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(sheet); + + sheet->SetTransformationOrigin(m_oldOrigin); + layout->TransformationOriginChanged(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoOriginMove::redo() +{ + VPSheetPtr sheet = m_sheet.toStrongRef(); + if (sheet.isNull()) + { + return; + } + + VPLayoutPtr layout = sheet->GetLayout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(sheet); + + sheet->SetTransformationOrigin(m_origin); + layout->TransformationOriginChanged(); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoOriginMove::mergeWith(const QUndoCommand *command) -> bool +{ + if (command->id() != id()) // make sure other is also an VPUndoPieceMove command + { + return false; + } + + const auto *moveCommand = dynamic_cast(command); + SCASSERT(moveCommand != nullptr) + + VPSheetPtr sheet = Sheet(); + if (moveCommand->Sheet().isNull() || sheet.isNull() || not moveCommand->AllowMerge()) + { + return false; + } + + VPTransformationOrigon origin = moveCommand->Origin(); + + if (origin.custom != m_origin.custom) + { + return false; + } + + m_origin.origin += origin.origin; + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoOriginMove::id() const -> int +{ + return static_cast(ML::UndoCommand::MoveOrigin); +} diff --git a/src/app/puzzle/undocommands/vpundooriginmove.h b/src/app/puzzle/undocommands/vpundooriginmove.h new file mode 100644 index 000000000..ed80a8cfc --- /dev/null +++ b/src/app/puzzle/undocommands/vpundooriginmove.h @@ -0,0 +1,73 @@ +/************************************************************************ + ** + ** @file vpundooriginmove.h + ** @author Roman Telezhynskyi + ** @date 19 8, 2021 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentina project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina 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 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina 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 Valentina. If not, see . + ** + *************************************************************************/ +#ifndef VPUNDOORIGINMOVE_H +#define VPUNDOORIGINMOVE_H + +#include "vpundocommand.h" + +#include "../layout/layoutdef.h" + +class VPUndoOriginMove : public VPUndoCommand +{ + Q_OBJECT +public: + VPUndoOriginMove(const VPSheetPtr &sheet, const VPTransformationOrigon &origin, bool allowMerge = false, + QUndoCommand *parent = nullptr); + virtual ~VPUndoOriginMove()=default; + + virtual void undo() override; + virtual void redo() override; + // cppcheck-suppress unusedFunction + virtual auto mergeWith(const QUndoCommand *command) -> bool override; + virtual auto id() const -> int override ; + + auto Sheet() const -> VPSheetWeakPtr; + auto Origin() const -> const VPTransformationOrigon &; + +private: + Q_DISABLE_COPY(VPUndoOriginMove) + + VPSheetWeakPtr m_sheet; + VPTransformationOrigon m_oldOrigin{}; + VPTransformationOrigon m_origin{}; + +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoOriginMove::Sheet() const -> VPSheetWeakPtr +{ + return m_sheet; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoOriginMove::Origin() const ->const VPTransformationOrigon & +{ + return m_origin; +} + +#endif // VPUNDOORIGINMOVE_H diff --git a/src/app/puzzle/undocommands/vpundopiecemove.cpp b/src/app/puzzle/undocommands/vpundopiecemove.cpp index a6d842226..daee56760 100644 --- a/src/app/puzzle/undocommands/vpundopiecemove.cpp +++ b/src/app/puzzle/undocommands/vpundopiecemove.cpp @@ -32,11 +32,10 @@ //--------------------------------------------------------------------------------------------------------------------- VPUndoPieceMove::VPUndoPieceMove(const VPPiecePtr &piece, qreal dx, qreal dy, bool allowMerge, QUndoCommand *parent) - : VPUndoCommand(parent), + : VPUndoCommand(allowMerge, parent), m_piece(piece), m_dx(dx), - m_dy(dy), - m_allowMerge(allowMerge) + m_dy(dy) { SCASSERT(not piece.isNull()) @@ -99,17 +98,8 @@ auto VPUndoPieceMove::mergeWith(const QUndoCommand *command) -> bool SCASSERT(moveCommand != nullptr) VPPiecePtr piece = Piece(); - if (moveCommand->Piece().isNull() || piece.isNull()) - { - return false; - } - - if (moveCommand->Piece() != piece) - { - return false; - } - - if (not moveCommand->AllowMerge()) + if (moveCommand->Piece().isNull() || piece.isNull() || moveCommand->Piece() != piece || + not moveCommand->AllowMerge()) { return false; } @@ -129,10 +119,9 @@ auto VPUndoPieceMove::id() const -> int //--------------------------------------------------------------------------------------------------------------------- VPUndoPiecesMove::VPUndoPiecesMove(const QVector &pieces, qreal dx, qreal dy, bool allowMerge, QUndoCommand *parent) - : VPUndoCommand(parent), + : VPUndoCommand(allowMerge, parent), m_dx(dx), - m_dy(dy), - m_allowMerge(allowMerge) + m_dy(dy) { setText(QObject::tr("move pieces")); diff --git a/src/app/puzzle/undocommands/vpundopiecemove.h b/src/app/puzzle/undocommands/vpundopiecemove.h index 38e104bce..9c4bf09e3 100644 --- a/src/app/puzzle/undocommands/vpundopiecemove.h +++ b/src/app/puzzle/undocommands/vpundopiecemove.h @@ -51,7 +51,6 @@ public: auto Piece() const -> VPPiecePtr; auto Dx() const -> qreal; auto Dy() const -> qreal; - auto AllowMerge() const -> bool; private: Q_DISABLE_COPY(VPUndoPieceMove) @@ -60,7 +59,6 @@ private: QTransform m_oldTransform{}; qreal m_dx; qreal m_dy; - bool m_allowMerge; }; //--------------------------------------------------------------------------------------------------------------------- @@ -81,12 +79,6 @@ inline auto VPUndoPieceMove::Dy() const -> qreal return m_dy; } -//--------------------------------------------------------------------------------------------------------------------- -inline auto VPUndoPieceMove::AllowMerge() const -> bool -{ - return m_allowMerge; -} - // Move pieces class VPUndoPiecesMove : public VPUndoCommand { @@ -105,7 +97,6 @@ public: auto PieceIds() const -> QSet; auto Dx() const -> qreal; auto Dy() const -> qreal; - auto AllowMerge() const -> bool; private: Q_DISABLE_COPY(VPUndoPiecesMove) @@ -114,7 +105,6 @@ private: QMap m_oldTransforms{}; qreal m_dx; qreal m_dy; - bool m_allowMerge; auto Layout() const -> VPLayoutPtr; auto Sheet() const -> VPSheetPtr; @@ -132,10 +122,4 @@ inline auto VPUndoPiecesMove::Dy() const -> qreal return m_dy; } -//--------------------------------------------------------------------------------------------------------------------- -inline auto VPUndoPiecesMove::AllowMerge() const -> bool -{ - return m_allowMerge; -} - #endif // VPUNDOPIECEMOVE_H diff --git a/src/app/puzzle/undocommands/vpundopiecerotate.cpp b/src/app/puzzle/undocommands/vpundopiecerotate.cpp index 21afec0b6..a2ca91c54 100644 --- a/src/app/puzzle/undocommands/vpundopiecerotate.cpp +++ b/src/app/puzzle/undocommands/vpundopiecerotate.cpp @@ -32,11 +32,10 @@ //--------------------------------------------------------------------------------------------------------------------- VPUndoPieceRotate::VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge, QUndoCommand *parent) - : VPUndoCommand(parent), + : VPUndoCommand(allowMerge, parent), m_piece(piece), m_origin(origin), - m_angle(angle), - m_allowMerge(allowMerge) + m_angle(angle) { SCASSERT(not piece.isNull()) @@ -119,10 +118,9 @@ auto VPUndoPieceRotate::id() const -> int //--------------------------------------------------------------------------------------------------------------------- VPUndoPiecesRotate::VPUndoPiecesRotate(const QVector &pieces, const QPointF &origin, qreal angle, bool allowMerge, QUndoCommand *parent) - : VPUndoCommand(parent), + : VPUndoCommand(allowMerge, parent), m_origin(origin), - m_angle(angle), - m_allowMerge(allowMerge) + m_angle(angle) { setText(QObject::tr("rotate pieces")); diff --git a/src/app/puzzle/undocommands/vpundopiecerotate.h b/src/app/puzzle/undocommands/vpundopiecerotate.h index 1738bfa6e..96a480e36 100644 --- a/src/app/puzzle/undocommands/vpundopiecerotate.h +++ b/src/app/puzzle/undocommands/vpundopiecerotate.h @@ -52,7 +52,6 @@ public: auto Piece() const -> VPPiecePtr; auto Origin() const -> QPointF; auto Angle() const -> qreal; - auto AllowMerge() const -> bool; private: Q_DISABLE_COPY(VPUndoPieceRotate) @@ -61,7 +60,6 @@ private: QTransform m_oldTransform{}; QPointF m_origin; qreal m_angle; - bool m_allowMerge; }; //--------------------------------------------------------------------------------------------------------------------- @@ -82,12 +80,6 @@ inline auto VPUndoPieceRotate::Angle() const -> qreal return m_angle; } -//--------------------------------------------------------------------------------------------------------------------- -inline auto VPUndoPieceRotate::AllowMerge() const -> bool -{ - return m_allowMerge; -} - // Rotate pieces class VPUndoPiecesRotate : public VPUndoCommand { @@ -106,7 +98,6 @@ public: auto PieceIds() const -> QSet; auto Origin() const -> QPointF; auto Angle() const -> qreal; - auto AllowMerge() const -> bool; private: Q_DISABLE_COPY(VPUndoPiecesRotate) @@ -115,7 +106,6 @@ private: QMap m_oldTransforms{}; QPointF m_origin; qreal m_angle; - bool m_allowMerge; auto Layout() const -> VPLayoutPtr; auto Sheet() const -> VPSheetPtr; @@ -133,10 +123,4 @@ inline auto VPUndoPiecesRotate::Angle() const -> qreal return m_angle; } -//--------------------------------------------------------------------------------------------------------------------- -inline auto VPUndoPiecesRotate::AllowMerge() const -> bool -{ - return m_allowMerge; -} - #endif // VPUNDOPIECEROTATE_H