diff --git a/src/app/puzzle/carousel/vpmimedatapiece.cpp b/src/app/puzzle/carousel/vpmimedatapiece.cpp index 8dbfc53db..227447e5e 100644 --- a/src/app/puzzle/carousel/vpmimedatapiece.cpp +++ b/src/app/puzzle/carousel/vpmimedatapiece.cpp @@ -42,13 +42,13 @@ auto VPMimeDataPiece::formats() const -> QStringList } //--------------------------------------------------------------------------------------------------------------------- -auto VPMimeDataPiece::GetPiecePtr() const -> VPPiece* +auto VPMimeDataPiece::GetPiecePtr() const -> VPPiecePtr { return m_piece; } //--------------------------------------------------------------------------------------------------------------------- -void VPMimeDataPiece::SetPiecePtr(VPPiece* piece) +void VPMimeDataPiece::SetPiecePtr(const VPPiecePtr &piece) { m_piece = piece; } diff --git a/src/app/puzzle/carousel/vpmimedatapiece.h b/src/app/puzzle/carousel/vpmimedatapiece.h index 235395f7b..9ad6e6338 100644 --- a/src/app/puzzle/carousel/vpmimedatapiece.h +++ b/src/app/puzzle/carousel/vpmimedatapiece.h @@ -31,7 +31,7 @@ #include -class VPPiece; +#include "../layout/layoutdef.h" class VPMimeDataPiece : public QMimeData { @@ -47,13 +47,13 @@ public: * @brief GetPiecePtr Returns the piece pointer of the mime data * @return piece pointer */ - auto GetPiecePtr() const -> VPPiece*; + auto GetPiecePtr() const -> VPPiecePtr; /** * @brief SetPiecePtr sets the piece pointer to the given value * @param piece the piece pointer */ - void SetPiecePtr(VPPiece* piece); + void SetPiecePtr(const VPPiecePtr &piece); static auto DragCursor(const QPixmap &piecePixmap) -> QPixmap; @@ -62,7 +62,7 @@ public: private: Q_DISABLE_COPY(VPMimeDataPiece) - VPPiece *m_piece{nullptr}; + VPPiecePtr m_piece{}; }; #endif // VPMIMEDATAPIECE_H diff --git a/src/app/puzzle/layout/vppiece.cpp b/src/app/puzzle/layout/vppiece.cpp index 57362e67d..2d925c461 100644 --- a/src/app/puzzle/layout/vppiece.cpp +++ b/src/app/puzzle/layout/vppiece.cpp @@ -78,7 +78,8 @@ auto VPPiece::GetPosition() -> QPointF //--------------------------------------------------------------------------------------------------------------------- void VPPiece::RotateToGrainline() { - if (not IsGrainlineEnabled() || m_sheet == nullptr) + VPSheetPtr sheet = Sheet(); + if (not IsGrainlineEnabled() || sheet.isNull()) { return; } @@ -94,7 +95,7 @@ void VPPiece::RotateToGrainline() QLineF canonical(grainlinePoints.first().x(), grainlinePoints.first().y(), grainlinePoints.first().x()+100, grainlinePoints.first().y()); - GrainlineType grainlineType = m_sheet->GrainlineType(); + GrainlineType grainlineType = sheet->GrainlineType(); auto DegreesAtFront = [grainline, canonical, grainlineType]() { @@ -147,25 +148,25 @@ auto VPPiece::IsSelected() const -> bool } //--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::Sheet() const -> VPSheet * +auto VPPiece::Sheet() const -> VPSheetPtr { return m_sheet; } //--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetSheet(VPSheet *newSheet) +void VPPiece::SetSheet(const VPSheetPtr &newSheet) { m_sheet = newSheet; } //--------------------------------------------------------------------------------------------------------------------- -auto VPPiece::Layout() const -> VPLayout * +auto VPPiece::Layout() const -> VPLayoutPtr { return m_layout; } //--------------------------------------------------------------------------------------------------------------------- -void VPPiece::SetLayout(VPLayout *layout) +void VPPiece::SetLayout(const VPLayoutPtr &layout) { SCASSERT(layout != nullptr) m_layout = layout; diff --git a/src/app/puzzle/layout/vppiece.h b/src/app/puzzle/layout/vppiece.h index 9cef09f26..58768e5a8 100644 --- a/src/app/puzzle/layout/vppiece.h +++ b/src/app/puzzle/layout/vppiece.h @@ -34,6 +34,7 @@ #include #include "../vlayout/vlayoutpiece.h" +#include "../layout/layoutdef.h" class VPLayout; class VPSheet; @@ -77,11 +78,11 @@ public: */ auto IsSelected() const -> bool; - auto Sheet() const -> VPSheet *; - void SetSheet(VPSheet *newSheet); + auto Sheet() const -> VPSheetPtr; + void SetSheet(const VPSheetPtr &newSheet); - auto Layout() const -> VPLayout *; - void SetLayout(VPLayout *layout); + auto Layout() const -> VPLayoutPtr; + void SetLayout(const VPLayoutPtr &layout); void SetGrainlineEnabled(bool enabled); void SetGrainlineAngle(qreal angle); @@ -103,11 +104,13 @@ public: private: Q_DISABLE_COPY(VPPiece) - VPLayout *m_layout{nullptr}; + VPLayoutWeakPtr m_layout{}; - VPSheet *m_sheet{nullptr}; + VPSheetWeakPtr m_sheet{}; bool m_isSelected{false}; }; +Q_DECLARE_METATYPE(VPPiecePtr) + #endif // VPPIECE_H diff --git a/src/app/puzzle/layout/vpsheet.cpp b/src/app/puzzle/layout/vpsheet.cpp index 3eb1fa41d..20b70b0b3 100644 --- a/src/app/puzzle/layout/vpsheet.cpp +++ b/src/app/puzzle/layout/vpsheet.cpp @@ -30,27 +30,27 @@ #include "vplayout.h" //--------------------------------------------------------------------------------------------------------------------- -VPSheet::VPSheet(VPLayout* layout) : - QObject(layout), +VPSheet::VPSheet(const VPLayoutPtr &layout) : m_layout(layout) { SCASSERT(layout != nullptr) } //--------------------------------------------------------------------------------------------------------------------- -auto VPSheet::GetLayout() -> VPLayout* +auto VPSheet::GetLayout() const -> VPLayoutPtr { return m_layout; } //--------------------------------------------------------------------------------------------------------------------- -auto VPSheet::GetPieces() const -> QList +auto VPSheet::GetPieces() const -> QList { - QList list; + QList list; - if (m_layout != nullptr) + VPLayoutPtr layout = GetLayout(); + if (not layout.isNull()) { - return m_layout->PiecesForSheet(this); + return layout->PiecesForSheet(m_uuid); } return {}; @@ -89,9 +89,10 @@ void VPSheet::SetVisible(bool visible) //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GrainlineType() const -> enum GrainlineType { - if (m_layout != nullptr) + VPLayoutPtr layout = GetLayout(); + if (not layout.isNull()) { - QSizeF size = m_layout->LayoutSettings().GetSheetSize(); + QSizeF size = layout->LayoutSettings().GetSheetSize(); if (size.height() < size.width()) { return GrainlineType::Horizontal; @@ -112,3 +113,11 @@ void VPSheet::SetTransformationOrigin(const VPTransformationOrigon &newTransform { m_transformationOrigin = newTransformationOrigin; } + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheet::Clear() +{ + m_name.clear(); + m_visible = true; + m_transformationOrigin = VPTransformationOrigon(); +} diff --git a/src/app/puzzle/layout/vpsheet.h b/src/app/puzzle/layout/vpsheet.h index 6c564529b..8ba028997 100644 --- a/src/app/puzzle/layout/vpsheet.h +++ b/src/app/puzzle/layout/vpsheet.h @@ -28,7 +28,6 @@ #ifndef VPSHEET_H #define VPSHEET_H -#include #include #include #include @@ -36,6 +35,7 @@ #include #include "def.h" +#include "layoutdef.h" class VPLayout; class VPPiece; @@ -52,11 +52,10 @@ struct VPTransformationOrigon bool custom{false}; }; -class VPSheet : public QObject +class VPSheet { - Q_OBJECT public: - explicit VPSheet(VPLayout* layout); + explicit VPSheet(const VPLayoutPtr &layout); virtual ~VPSheet() = default; @@ -64,9 +63,9 @@ public: * @brief GetLayout Returns the Layout of the sheet * @return Layout of the sheet */ - auto GetLayout() -> VPLayout*; + auto GetLayout() const -> VPLayoutPtr; - auto GetPieces() const -> QList; + auto GetPieces() const -> QList; /** * @brief GetName Returns the name of the sheet @@ -90,10 +89,12 @@ public: auto TransformationOrigin() const -> const VPTransformationOrigon &; void SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin); + void Clear(); + private: Q_DISABLE_COPY(VPSheet) - VPLayout *m_layout; + VPLayoutWeakPtr m_layout{}; QString m_name{}; @@ -104,4 +105,6 @@ private: VPTransformationOrigon m_transformationOrigin{}; }; +Q_DECLARE_METATYPE(VPSheetPtr) + #endif // VPSHEET_H diff --git a/src/app/puzzle/scene/vpmaingraphicsview.cpp b/src/app/puzzle/scene/vpmaingraphicsview.cpp index e63f08a25..bcc94bb8e 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.cpp +++ b/src/app/puzzle/scene/vpmaingraphicsview.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "../scene/vpgraphicssheet.h" #include "../scene/vpgraphicspiece.h" @@ -44,6 +45,7 @@ #include "../vwidgets/vmaingraphicsscene.h" #include "vptilefactory.h" #include "vpgraphicspiececontrols.h" +#include "../undocommands/vpundopiecemove.h" #include @@ -56,12 +58,12 @@ const QKeySequence restoreOriginShortcut = QKeySequence(Qt::ControlModifier + Qt //--------------------------------------------------------------------------------------------------------------------- -VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFactory, QWidget *parent) : +VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QWidget *parent) : VMainGraphicsView(parent), m_scene(new VMainGraphicsScene(this)), m_layout(layout) { - SCASSERT(m_layout != nullptr) + SCASSERT(not m_layout.isNull()) setScene(m_scene); m_graphicsSheet = new VPGraphicsSheet(m_layout); @@ -87,7 +89,7 @@ VPMainGraphicsView::VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFact m_rotationOrigin, &VPGraphicsTransformationOrigin::SetTransformationOrigin); // add the connections - connect(m_layout, &VPLayout::PieceSheetChanged, this, &VPMainGraphicsView::on_PieceSheetChanged); + connect(layout.get(), &VPLayout::PieceSheetChanged, this, &VPMainGraphicsView::on_PieceSheetChanged); auto *restoreOrigin = new QAction(this); restoreOrigin->setShortcut(restoreOriginShortcut); @@ -143,18 +145,25 @@ void VPMainGraphicsView::RefreshPieces() qDeleteAll(m_graphicsPieces); m_graphicsPieces.clear(); - VPSheet *sheet = m_layout->GetFocusedSheet(); - if (sheet != nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) { - QList pieces = sheet->GetPieces(); - m_graphicsPieces.reserve(pieces.size()); - - for (auto *piece : pieces) + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - auto *graphicsPiece = new VPGraphicsPiece(piece); - m_graphicsPieces.append(graphicsPiece); - scene()->addItem(graphicsPiece); - ConnectPiece(graphicsPiece); + QList pieces = sheet->GetPieces(); + m_graphicsPieces.reserve(pieces.size()); + + for (const auto &piece : pieces) + { + if (not piece.isNull()) + { + auto *graphicsPiece = new VPGraphicsPiece(piece); + m_graphicsPieces.append(graphicsPiece); + scene()->addItem(graphicsPiece); + ConnectPiece(graphicsPiece); + } + } } } } @@ -171,11 +180,15 @@ void VPMainGraphicsView::PrepareForExport() m_graphicsSheet->SetShowBorder(false); m_graphicsSheet->SetShowMargin(false); - m_showGridTmp = m_layout->GetFocusedSheet()->GetLayout()->LayoutSettings().GetShowGrid(); - m_layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(false); + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + m_showGridTmp = layout->GetFocusedSheet()->GetLayout()->LayoutSettings().GetShowGrid(); + layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(false); - m_showTilesTmp = m_layout->LayoutSettings().GetShowTiles(); - m_layout->LayoutSettings().SetShowTiles(false); + m_showTilesTmp = layout->LayoutSettings().GetShowTiles(); + layout->LayoutSettings().SetShowTiles(false); + } RefreshLayout(); } @@ -186,9 +199,13 @@ void VPMainGraphicsView::CleanAfterExport() m_graphicsSheet->SetShowBorder(true); m_graphicsSheet->SetShowMargin(true); - m_layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(m_showGridTmp); + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(m_showGridTmp); - m_layout->LayoutSettings().SetShowTiles(m_showTilesTmp); + layout->LayoutSettings().SetShowTiles(m_showTilesTmp); + } RefreshLayout(); } @@ -233,9 +250,15 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event) { const auto *mimePiece = qobject_cast (mime); - VPPiece *piece = mimePiece->GetPiecePtr(); - if(piece != nullptr) + VPPiecePtr piece = mimePiece->GetPiecePtr(); + if(not piece.isNull()) { + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + qCDebug(pMainGraphicsView(), "element dropped, %s", qUtf8Printable(piece->GetName())); event->acceptProposedAction(); @@ -243,7 +266,7 @@ void VPMainGraphicsView::dropEvent(QDropEvent *event) piece->SetPosition(mapToScene(event->pos())); // change the piecelist of the piece - piece->SetSheet(m_layout->GetFocusedSheet()); + piece->SetSheet(layout->GetFocusedSheet()); auto *graphicsPiece = new VPGraphicsPiece(piece); m_graphicsPieces.append(graphicsPiece); @@ -264,12 +287,12 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event) { for(auto *graphicsPiece : m_graphicsPieces) { - VPPiece *piece = graphicsPiece->GetPiece(); + VPPiecePtr piece = graphicsPiece->GetPiece(); - if(piece->IsSelected()) + if(not piece.isNull() && piece->IsSelected()) { piece->SetSelected(false); - piece->SetSheet(nullptr); + piece->SetSheet(VPSheetPtr()); m_graphicsPieces.removeAll(graphicsPiece); delete graphicsPiece; } @@ -321,6 +344,17 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event) } } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event) +{ + VMainGraphicsView::keyReleaseEvent(event); + if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right && event->key() != Qt::Key_Up && + event->key() != Qt::Key_Down) + { + m_allowChangeMerge = false; + } +} + //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event) { @@ -331,15 +365,22 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event) return; } + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + QMenu menu; - VPSheet *sheet = m_layout->GetFocusedSheet(); QAction *restoreOriginAction = menu.addAction(tr("Restore transformation origin")); restoreOriginAction->setShortcut(restoreOriginShortcut); - restoreOriginAction->setEnabled(sheet != nullptr && sheet->TransformationOrigin().custom); + restoreOriginAction->setEnabled(not sheet.isNull() && sheet->TransformationOrigin().custom); QAction *removeSheetAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Remove sheet")); - removeSheetAction->setEnabled(sheet != nullptr && m_layout->GetSheets().size() > 1); + removeSheetAction->setEnabled(not sheet.isNull() && layout->GetSheets().size() > 1); QAction *selectedAction = menu.exec(event->globalPos()); if (selectedAction == removeSheetAction) @@ -348,16 +389,18 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event) { sheet->SetVisible(false); - QList pieces = sheet->GetPieces(); - for (auto *piece : pieces) + QList pieces = sheet->GetPieces(); + for (const auto &piece : pieces) { - piece->SetSheet(nullptr); + if (not piece.isNull()) + { + piece->SetSheet(nullptr); + } } } - m_layout->SetFocusedSheet(nullptr); + layout->SetFocusedSheet(VPSheetPtr()); emit on_SheetRemoved(); - RefreshPieces(); } else if (selectedAction == restoreOriginAction) { @@ -369,8 +412,14 @@ void VPMainGraphicsView::contextMenuEvent(QContextMenuEvent *event) //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::RestoreOrigin() const { - VPSheet *sheet = m_layout->GetFocusedSheet(); - if (sheet != nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { VPTransformationOrigon origin = sheet->TransformationOrigin(); origin.custom = false; @@ -420,9 +469,13 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece) { SCASSERT(piece != nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); + + connect(layout.get(), &VPLayout::PieceTransformationChanged, piece, + &VPGraphicsPiece::on_RefreshPiece); connect(piece, &VPGraphicsPiece::PieceSelectionChanged, m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); - connect(piece, &VPGraphicsPiece::PiecePositionChanged, + connect(piece, &VPGraphicsPiece::PieceTransformationChanged, m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); connect(m_rotationControls, &VPGraphicsPieceControls::Rotate, piece, &VPGraphicsPiece::on_Rotate); connect(piece, &VPGraphicsPiece::HideTransformationHandles, @@ -434,8 +487,14 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece) //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) const { - VPSheet *sheet = m_layout->GetFocusedSheet(); - if (sheet == nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) { return; } @@ -453,20 +512,56 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) const } //--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) const +void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) { - for(auto *graphicsPiece : m_graphicsPieces) + if (m_graphicsPieces.isEmpty()) { - if (graphicsPiece->isSelected()) - { - graphicsPiece->TranslatePiece(dx, dy); - m_rotationControls->on_UpdateControls(); - } + return; } + + VPPiecePtr piece = m_graphicsPieces.first()->GetPiece(); + if (piece.isNull()) + { + return; + } + + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + auto PreparePieces = [this]() + { + QVector pieces; + for (auto *graphicsPiece : m_graphicsPieces) + { + if (graphicsPiece->isSelected()) + { + pieces.append(graphicsPiece->GetPiece()); + } + } + + return pieces; + }; + + QVector pieces = PreparePieces(); + if (pieces.size() == 1) + { + auto *command = new VPUndoPieceMove(pieces.first(), dx, dy, m_allowChangeMerge); + layout->UndoStack()->push(command); + } + else if (pieces.size() > 1) + { + auto *command = new VPUndoPiecesMove(pieces, dx, dy, m_allowChangeMerge); + layout->UndoStack()->push(command); + } + + m_allowChangeMerge = true; } //--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::on_PieceSheetChanged(VPPiece *piece) +void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece) { VPGraphicsPiece *_graphicsPiece = nullptr; for(auto *graphicPiece : m_graphicsPieces) @@ -477,8 +572,14 @@ void VPMainGraphicsView::on_PieceSheetChanged(VPPiece *piece) } } - if (piece->Sheet() == nullptr || piece->Sheet() == m_layout->GetTrashSheet() || - piece->Sheet() != m_layout->GetFocusedSheet()) // remove + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + if (piece->Sheet().isNull() || piece->Sheet() == layout->GetTrashSheet() || + piece->Sheet() != layout->GetFocusedSheet()) // remove { if (_graphicsPiece != nullptr) { diff --git a/src/app/puzzle/scene/vpmaingraphicsview.h b/src/app/puzzle/scene/vpmaingraphicsview.h index b29631052..e1e854d5f 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.h +++ b/src/app/puzzle/scene/vpmaingraphicsview.h @@ -30,6 +30,7 @@ #define VPMAINGRAPHICSVIEW_H #include "../vwidgets/vmaingraphicsview.h" +#include "../layout/layoutdef.h" class VMainGraphicsScene; class VPGraphicsPieceControls; @@ -45,7 +46,7 @@ class VPMainGraphicsView : public VMainGraphicsView { Q_OBJECT public: - VPMainGraphicsView(VPLayout *layout, VPTileFactory *tileFactory, QWidget *parent); + VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QWidget *parent); ~VPMainGraphicsView() = default; /** @@ -78,7 +79,7 @@ public slots: * the other given piece list * @param piece the piece that was moved */ - void on_PieceSheetChanged(VPPiece *piece); + void on_PieceSheetChanged(const VPPiecePtr &piece); void RefreshPieces(); @@ -89,6 +90,7 @@ protected: void dropEvent(QDropEvent *event) override; void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override; @@ -115,7 +117,7 @@ private: VPGraphicsPieceControls *m_rotationControls{nullptr}; VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr}; - VPLayout *m_layout; + VPLayoutWeakPtr m_layout; QList m_graphicsPieces{}; @@ -128,11 +130,12 @@ private: * variable to hold temporarly hte value of the show grid */ bool m_showGridTmp{false}; + bool m_allowChangeMerge{false}; void ConnectPiece(VPGraphicsPiece *piece); void RotatePiecesByAngle(qreal angle) const; - void TranslatePiecesOn(qreal dx, qreal dy) const; + void TranslatePiecesOn(qreal dx, qreal dy); }; diff --git a/src/app/puzzle/undocommands/vpundocommand.cpp b/src/app/puzzle/undocommands/vpundocommand.cpp new file mode 100644 index 000000000..e262d3e45 --- /dev/null +++ b/src/app/puzzle/undocommands/vpundocommand.cpp @@ -0,0 +1,35 @@ +/************************************************************************ + ** + ** @file vpundocommand.cpp + ** @author Roman Telezhynskyi + ** @date 16 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 "vpundocommand.h" + +Q_LOGGING_CATEGORY(vpUndo, "vp.undo") + +//--------------------------------------------------------------------------------------------------------------------- +VPUndoCommand::VPUndoCommand(QUndoCommand *parent) + : QUndoCommand(parent) +{} diff --git a/src/app/puzzle/undocommands/vpundocommand.h b/src/app/puzzle/undocommands/vpundocommand.h new file mode 100644 index 000000000..c2665264d --- /dev/null +++ b/src/app/puzzle/undocommands/vpundocommand.h @@ -0,0 +1,57 @@ +/************************************************************************ + ** + ** @file vpundocommand.h + ** @author Roman Telezhynskyi + ** @date 16 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 VPUNDOCOMMAND_H +#define VPUNDOCOMMAND_H + +#include +#include +#include + +namespace ML +{ +enum class UndoCommand: qint8 +{ + MovePiece = 0, + MovePieces = 1 +}; +} + +Q_DECLARE_LOGGING_CATEGORY(vpUndo) + +class VPUndoCommand : public QObject, public QUndoCommand +{ + Q_OBJECT +public: + explicit VPUndoCommand(QUndoCommand *parent = nullptr); + virtual ~VPUndoCommand() =default; + +private: + Q_DISABLE_COPY(VPUndoCommand) +}; + +#endif // VPUNDOCOMMAND_H diff --git a/src/app/puzzle/undocommands/vpundopiecemove.cpp b/src/app/puzzle/undocommands/vpundopiecemove.cpp new file mode 100644 index 000000000..a6d842226 --- /dev/null +++ b/src/app/puzzle/undocommands/vpundopiecemove.cpp @@ -0,0 +1,282 @@ +/************************************************************************ + ** + ** @file vpundopiecemove.cpp + ** @author Roman Telezhynskyi + ** @date 16 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 "vpundopiecemove.h" +#include "../vmisc/def.h" +#include "../layout/vppiece.h" +#include "../layout/vplayout.h" + +//--------------------------------------------------------------------------------------------------------------------- +VPUndoPieceMove::VPUndoPieceMove(const VPPiecePtr &piece, qreal dx, qreal dy, bool allowMerge, QUndoCommand *parent) + : VPUndoCommand(parent), + m_piece(piece), + m_dx(dx), + m_dy(dy), + m_allowMerge(allowMerge) +{ + SCASSERT(not piece.isNull()) + + m_oldTransform = piece->GetMatrix(); + + setText(QObject::tr("move piece")); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoPieceMove::undo() +{ + VPPiecePtr piece = Piece(); + if (piece.isNull()) + { + return; + } + + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(piece->Sheet()); + + piece->SetMatrix(m_oldTransform); + emit layout->PieceTransformationChanged(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoPieceMove::redo() +{ + VPPiecePtr piece = Piece(); + if (piece.isNull()) + { + return; + } + + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(piece->Sheet()); + + piece->Translate(m_dx, m_dy); + emit layout->PieceTransformationChanged(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPieceMove::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) + + VPPiecePtr piece = Piece(); + if (moveCommand->Piece().isNull() || piece.isNull()) + { + return false; + } + + if (moveCommand->Piece() != piece) + { + return false; + } + + if (not moveCommand->AllowMerge()) + { + return false; + } + + m_dx += moveCommand->Dx(); + m_dy += moveCommand->Dy(); + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPieceMove::id() const -> int +{ + return static_cast(ML::UndoCommand::MovePiece); +} + +// move pieces +//--------------------------------------------------------------------------------------------------------------------- +VPUndoPiecesMove::VPUndoPiecesMove(const QVector &pieces, qreal dx, qreal dy, bool allowMerge, + QUndoCommand *parent) + : VPUndoCommand(parent), + m_dx(dx), + m_dy(dy), + m_allowMerge(allowMerge) +{ + setText(QObject::tr("move pieces")); + + for (const auto& piece : pieces) + { + if (not piece.isNull()) + { + m_pieces.append(piece); + m_oldTransforms.insert(piece->GetUniqueID(), piece->GetMatrix()); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoPiecesMove::undo() +{ + if (m_pieces.isEmpty()) + { + return; + } + + VPLayoutPtr layout = Layout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(Sheet()); + + for (const auto& piece : m_pieces) + { + VPPiecePtr p = piece.toStrongRef(); + if (not p.isNull()) + { + if (m_oldTransforms.contains(p->GetUniqueID())) + { + p->SetMatrix(m_oldTransforms.value(p->GetUniqueID())); + emit layout->PieceTransformationChanged(p); + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPUndoPiecesMove::redo() +{ + if (m_pieces.isEmpty()) + { + return; + } + + VPLayoutPtr layout = Layout(); + if (layout.isNull()) + { + return; + } + + layout->SetFocusedSheet(Sheet()); + + for (const auto& piece : m_pieces) + { + VPPiecePtr p = piece.toStrongRef(); + if (not p.isNull()) + { + p->Translate(m_dx, m_dy); + emit layout->PieceTransformationChanged(p); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPiecesMove::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) + + if (moveCommand->PieceIds() != PieceIds()) + { + return false; + } + + if (not moveCommand->AllowMerge()) + { + return false; + } + + m_dx += moveCommand->Dx(); + m_dy += moveCommand->Dy(); + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPiecesMove::id() const -> int +{ + return static_cast(ML::UndoCommand::MovePieces); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPiecesMove::Layout() const -> VPLayoutPtr +{ + for (const auto& piece : m_pieces) + { + VPPiecePtr p = piece.toStrongRef(); + if (not p.isNull()) + { + return p->Layout(); + } + } + + return nullptr; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPUndoPiecesMove::Sheet() const -> VPSheetPtr +{ + for (const auto& piece : m_pieces) + { + VPPiecePtr p = piece.toStrongRef(); + if (not p.isNull()) + { + return p->Sheet(); + } + } + + return nullptr; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPiecesMove::PieceIds() const -> QSet +{ + QSet ids; + for (const auto& piece : m_pieces) + { + VPPiecePtr p = piece.toStrongRef(); + if (not p.isNull()) + { + ids.insert(p->GetUniqueID()); + } + }; + + return ids; +} diff --git a/src/app/puzzle/undocommands/vpundopiecemove.h b/src/app/puzzle/undocommands/vpundopiecemove.h new file mode 100644 index 000000000..38e104bce --- /dev/null +++ b/src/app/puzzle/undocommands/vpundopiecemove.h @@ -0,0 +1,141 @@ +/************************************************************************ + ** + ** @file vpundopiecemove.h + ** @author Roman Telezhynskyi + ** @date 16 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 VPUNDOPIECEMOVE_H +#define VPUNDOPIECEMOVE_H + +#include "vpundocommand.h" + +#include + +#include "../layout/layoutdef.h" + +class VPUndoPieceMove : public VPUndoCommand +{ + Q_OBJECT +public: + explicit VPUndoPieceMove(const VPPiecePtr &piece, qreal dx, qreal dy, bool allowMerge, + QUndoCommand *parent = nullptr); + virtual ~VPUndoPieceMove()=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 Piece() const -> VPPiecePtr; + auto Dx() const -> qreal; + auto Dy() const -> qreal; + auto AllowMerge() const -> bool; + +private: + Q_DISABLE_COPY(VPUndoPieceMove) + + VPPieceWeakPtr m_piece; + QTransform m_oldTransform{}; + qreal m_dx; + qreal m_dy; + bool m_allowMerge; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPieceMove::Piece() const -> VPPiecePtr +{ + return m_piece; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPieceMove::Dx() const -> qreal +{ + return m_dx; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPieceMove::Dy() const -> qreal +{ + return m_dy; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPieceMove::AllowMerge() const -> bool +{ + return m_allowMerge; +} + +// Move pieces +class VPUndoPiecesMove : public VPUndoCommand +{ + Q_OBJECT +public: + explicit VPUndoPiecesMove(const QVector &pieces, qreal dx, qreal dy, bool allowMerge, + QUndoCommand *parent = nullptr); + virtual ~VPUndoPiecesMove()=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 PieceIds() const -> QSet; + auto Dx() const -> qreal; + auto Dy() const -> qreal; + auto AllowMerge() const -> bool; + +private: + Q_DISABLE_COPY(VPUndoPiecesMove) + + QVector m_pieces{}; + QMap m_oldTransforms{}; + qreal m_dx; + qreal m_dy; + bool m_allowMerge; + + auto Layout() const -> VPLayoutPtr; + auto Sheet() const -> VPSheetPtr; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPUndoPiecesMove::Dx() const -> qreal +{ + return m_dx; +} + +//--------------------------------------------------------------------------------------------------------------------- +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/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 3a532ecd3..1212b936e 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "ui_vpmainwindow.h" #include "dialogs/vpdialogabout.h" @@ -69,10 +70,17 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : VAbstractMainWindow(parent), ui(new Ui::VPMainWindow), m_cmd(cmd), + m_undoStack(new QUndoStack(this)), + m_layout{VPLayout::CreateLayout(m_undoStack)}, m_statusLabel(new QLabel(this)), m_layoutWatcher(new QFileSystemWatcher(this)) { - // // ----- for test purposes, to be removed------------------ + ui->setupUi(this); + + // create a standard sheet + AddSheet(); + + // ----- for test purposes, to be removed------------------ m_layout->LayoutSettings().SetUnit(Unit::Cm); m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(true); m_layout->LayoutSettings().SetTitle(QString("My Test Layout")); @@ -85,11 +93,6 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : // -------------------------------------------------------- - ui->setupUi(this); - - // create a standard sheet - AddSheet(); - // init the tile factory m_tileFactory = new VPTileFactory(m_layout, VPApplication::VApp()->Settings()); m_tileFactory->refreshTileInfos(); @@ -196,9 +199,7 @@ auto VPMainWindow::LoadFile(QString path) -> bool file.open(QIODevice::ReadOnly); VPLayoutFileReader fileReader; - - delete m_layout; - m_layout = new VPLayout(); + m_layout->Clear(); fileReader.ReadFile(m_layout, &file); @@ -318,9 +319,9 @@ void VPMainWindow::ImportRawLayouts(const QStringList &rawLayouts) // TODO for feature "Update piece" : CreateOrUpdate() function indstead of CreatePiece() - VPPiece *piece = CreatePiece(rawPiece); + VPPiecePtr piece(CreatePiece(rawPiece)); piece->SetSheet(nullptr); // just in case - m_layout->AddPiece(piece); + VPLayout::AddPiece(m_layout, piece); } m_carrousel->Refresh(); @@ -378,9 +379,6 @@ void VPMainWindow::SetupMenu() connect(ui->actionExit, &QAction::triggered, this, &VPMainWindow::close); ui->actionExit->setShortcuts(QKeySequence::Quit); - // -------------------- connects the actions for the edit menu - // TODO : initialise the undo / redo - // -------------------- connects the actions for the windows menu // TODO : initialise the entries for the different windows @@ -388,6 +386,23 @@ void VPMainWindow::SetupMenu() QAction* actionDockWidgetToolOptions = ui->dockWidgetProperties->toggleViewAction(); ui->menuEdit->addAction(actionDockWidgetToolOptions); + auto *separatorAct = new QAction(this); + separatorAct->setSeparator(true); + ui->menuEdit->addAction(separatorAct); + + // Add Undo/Redo actions. + undoAction = m_layout->UndoStack()->createUndoAction(this, tr("&Undo")); + undoAction->setShortcuts(QKeySequence::Undo); + undoAction->setIcon(QIcon::fromTheme("edit-undo")); + ui->menuEdit->addAction(undoAction); + ui->toolBarUndoCommands->addAction(undoAction); + + redoAction = m_layout->UndoStack()->createRedoAction(this, tr("&Redo")); + redoAction->setShortcuts(QKeySequence::Redo); + redoAction->setIcon(QIcon::fromTheme("edit-redo")); + ui->menuEdit->addAction(redoAction); + ui->toolBarUndoCommands->addAction(redoAction); + // File m_recentFileActs.fill(nullptr); for (auto & recentFileAct : m_recentFileActs) @@ -570,7 +585,6 @@ void VPMainWindow::InitPropertyTabTiles() //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitPropertyTabLayout() { - // FIXME ---- For MVP we hide a few things. To be displayed when functions there ui->groupBoxLayoutControl->hide(); @@ -768,9 +782,8 @@ void VPMainWindow::InitMainGraphics() connect(m_graphicsView, &VPMainGraphicsView::ScaleChanged, this, &VPMainWindow::on_ScaleChanged); connect(m_graphicsView->GetScene(), &VMainGraphicsScene::mouseMove, this, &VPMainWindow::on_MouseMoved); - connect(m_carrousel, &VPCarrousel::on_ActiveSheetChanged, m_graphicsView, &VPMainGraphicsView::RefreshPieces); connect(m_graphicsView, &VPMainGraphicsView::on_SheetRemoved, m_carrousel, &VPCarrousel::Refresh); - connect(m_layout, &VPLayout::PieceSheetChanged, m_carrousel, &VPCarrousel::Refresh); + connect(m_layout.get(), &VPLayout::PieceSheetChanged, m_carrousel, &VPCarrousel::Refresh); } //--------------------------------------------------------------------------------------------------------------------- @@ -1109,7 +1122,7 @@ void VPMainWindow::CreateWindowMenu(QMenu *menu) //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::AddSheet() { - auto *sheet = new VPSheet(m_layout); + VPSheetPtr sheet(new VPSheet(m_layout)); sheet->SetName(QObject::tr("Sheet %1").arg(m_layout->GetSheets().size()+1)); m_layout->AddSheet(sheet); m_layout->SetFocusedSheet(sheet); @@ -1191,6 +1204,8 @@ void VPMainWindow::changeEvent(QEvent *event) { // retranslate designer form (single inheritance approach) ui->retranslateUi(this); + undoAction->setText(tr("&Undo")); + redoAction->setText(tr("&Redo")); WindowsLocale(); UpdateWindowTitle(); @@ -1726,7 +1741,7 @@ void VPMainWindow::on_pushButtonSheetExport_clicked() LayoutExportFormats format = static_cast(ui->comboBoxSheetExportFormat->currentData().toInt()); VPExporter exporter; - exporter.Export(m_layout, format, m_graphicsView); + exporter.Export(m_layout.get(), format, m_graphicsView); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index 3250c618e..b6c89f76b 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -417,7 +417,9 @@ private: VPCommandLinePtr m_cmd; - VPLayout *m_layout{new VPLayout(this)}; + QUndoStack *m_undoStack; + + VPLayoutPtr m_layout; QListm_selectedPieces{QList()}; VPTileFactory *m_tileFactory{nullptr}; @@ -442,6 +444,9 @@ private: QFileSystemWatcher *m_layoutWatcher; + QAction *undoAction{nullptr}; + QAction *redoAction{nullptr}; + /** * @brief CreatePiece creates a piece from the given VLayoutPiece data * @param rawPiece the raw piece data diff --git a/src/app/puzzle/vpmainwindow.ui b/src/app/puzzle/vpmainwindow.ui index 8e5544612..e0b469fc4 100644 --- a/src/app/puzzle/vpmainwindow.ui +++ b/src/app/puzzle/vpmainwindow.ui @@ -669,7 +669,7 @@ 0 - -170 + 0 342 870 @@ -1589,6 +1589,17 @@ false + + + Undo commands + + + TopToolBarArea + + + false + + diff --git a/src/app/puzzle/vptilefactory.cpp b/src/app/puzzle/vptilefactory.cpp index b789f5883..a0c321b3a 100644 --- a/src/app/puzzle/vptilefactory.cpp +++ b/src/app/puzzle/vptilefactory.cpp @@ -5,32 +5,26 @@ #include "../vwidgets/vmaingraphicsscene.h" #include "layout/vpsheet.h" #include "scene/vpmaingraphicsview.h" -#include "layout/vplayout.h" #include "../vmisc/def.h" #include "../vmisc/vcommonsettings.h" //--------------------------------------------------------------------------------------------------------------------- -VPTileFactory::VPTileFactory(VPLayout *layout, VCommonSettings *commonSettings): +VPTileFactory::VPTileFactory(const VPLayoutPtr &layout, VCommonSettings *commonSettings): m_layout(layout), m_commonSettings(commonSettings) { m_infoStripeWidth = UnitConvertor(1, Unit::Cm, Unit::Px); } -//--------------------------------------------------------------------------------------------------------------------- -VPTileFactory::~VPTileFactory() -{ - -} - //--------------------------------------------------------------------------------------------------------------------- void VPTileFactory::refreshTileInfos() { - if(m_layout != nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); + if(not layout.isNull()) { - PageOrientation tilesOrientation = m_layout->LayoutSettings().GetTilesOrientation(); - QSizeF tilesSize = m_layout->LayoutSettings().GetTilesSize(); - QMarginsF tilesMargins = m_layout->LayoutSettings().GetTilesMargins(); + PageOrientation tilesOrientation = layout->LayoutSettings().GetTilesOrientation(); + QSizeF tilesSize = layout->LayoutSettings().GetTilesSize(); + QMarginsF tilesMargins = layout->LayoutSettings().GetTilesMargins(); // sets the drawing height m_drawingAreaHeight = (tilesOrientation == PageOrientation::Portrait)? @@ -45,11 +39,11 @@ void VPTileFactory::refreshTileInfos() tilesMargins.left() + tilesMargins.right() + m_infoStripeWidth; - QSizeF sheetSize = m_layout->LayoutSettings().GetSheetSize(); + QSizeF sheetSize = layout->LayoutSettings().GetSheetSize(); qreal totalDrawingWidth = 0; qreal totaldrawingHeight = 0; - if(m_layout->LayoutSettings().GetOrientation() == PageOrientation::Portrait) + if(layout->LayoutSettings().GetOrientation() == PageOrientation::Portrait) { totalDrawingWidth = sheetSize.width(); totaldrawingHeight = sheetSize.height(); @@ -69,9 +63,17 @@ void VPTileFactory::refreshTileInfos() //--------------------------------------------------------------------------------------------------------------------- void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView, int row, int col) { - QMarginsF tilesMargins = m_layout->LayoutSettings().GetTilesMargins(); - QPen penTileInfos = QPen(QColor(180,180,180), m_commonSettings->WidthHairLine(), Qt::DashLine, Qt::RoundCap, Qt::RoundJoin); - QPen penTileDrawing = QPen(Qt::black, m_commonSettings->WidthMainLine(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + VPLayoutPtr layout = m_layout.toStrongRef(); + if(layout.isNull()) + { + return + ; + } + QMarginsF tilesMargins = layout->LayoutSettings().GetTilesMargins(); + QPen penTileInfos = QPen(QColor(180,180,180), m_commonSettings->WidthHairLine(), Qt::DashLine, Qt::RoundCap, + Qt::RoundJoin); + QPen penTileDrawing = QPen(Qt::black, m_commonSettings->WidthMainLine(), Qt::SolidLine, Qt::RoundCap, + Qt::RoundJoin); QSvgRenderer* svgRenderer = new QSvgRenderer(); @@ -280,7 +282,7 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView "%1 - %2" "" "") - .arg(page).arg(m_layout->GetFocusedSheet()->GetName())); + .arg(page).arg(layout->GetFocusedSheet()->GetName())); painter->save(); painter->rotate(-90); painter->translate(QPointF(-(m_drawingAreaHeight+tilesMargins.top()) + UnitConvertor(1, Unit::Cm, Unit::Px), diff --git a/src/app/puzzle/vptilefactory.h b/src/app/puzzle/vptilefactory.h index b89303d4d..050eff123 100644 --- a/src/app/puzzle/vptilefactory.h +++ b/src/app/puzzle/vptilefactory.h @@ -32,8 +32,9 @@ #include #include +#include "layout/vplayout.h" + class VPMainGraphicsView; -class VPLayout; class VCommonSettings; class QPainter; @@ -42,9 +43,9 @@ class VPTileFactory : QObject Q_OBJECT public: - VPTileFactory(VPLayout *layout, VCommonSettings *commonSettings); + VPTileFactory(const VPLayoutPtr &layout, VCommonSettings *commonSettings); - virtual ~VPTileFactory(); + virtual ~VPTileFactory() = default; /** * @brief drawTile draws the tile of given coordinate (row, col) from the @@ -87,7 +88,7 @@ public: private: Q_DISABLE_COPY(VPTileFactory) - VPLayout *m_layout{nullptr}; + VPLayoutWeakPtr m_layout; VCommonSettings *m_commonSettings{nullptr}; /** diff --git a/src/app/puzzle/xml/vplayoutfilereader.h b/src/app/puzzle/xml/vplayoutfilereader.h index 3261ca267..707a055c5 100644 --- a/src/app/puzzle/xml/vplayoutfilereader.h +++ b/src/app/puzzle/xml/vplayoutfilereader.h @@ -47,29 +47,29 @@ public: VPLayoutFileReader()=default; ~VPLayoutFileReader()=default; - auto ReadFile(VPLayout *layout, QFile *file) -> bool; + auto ReadFile(const VPLayoutPtr &layout, QFile *file) -> bool; private: Q_DISABLE_COPY(VPLayoutFileReader) - void ReadLayout(VPLayout *layout); - void ReadProperties(VPLayout *layout); - void ReadControl(VPLayout *layout); - void ReadTiles(VPLayout *layout); - void ReadUnplacedPieces(VPLayout *layout); - void ReadSheets(VPLayout *layout); - void ReadSheet(VPLayout *layout); - void ReadPieces(VPLayout *layout, VPSheet *sheet=nullptr); - void ReadPiece(VPPiece *piece); - void ReadSeamAllowance(VPPiece *piece); - void ReadGrainline(VPPiece *piece); - void ReadNotches(VPPiece *piece); + void ReadLayout(const VPLayoutPtr &layout); + void ReadProperties(const VPLayoutPtr &layout); + void ReadControl(const VPLayoutPtr &layout); + void ReadTiles(const VPLayoutPtr &layout); + void ReadUnplacedPieces(const VPLayoutPtr &layout); + void ReadSheets(const VPLayoutPtr &layout); + void ReadSheet(const VPLayoutPtr &layout); + void ReadPieces(const VPLayoutPtr &layout, const VPSheetPtr &sheet=VPSheetPtr()); + void ReadPiece(const VPPiecePtr &piece); + void ReadSeamAllowance(const VPPiecePtr &piece); + void ReadGrainline(const VPPiecePtr &piece); + void ReadNotches(const VPPiecePtr &piece); auto ReadNotch() -> VLayoutPassmark; - void ReadInternalPaths(VPPiece *piece); + void ReadInternalPaths(const VPPiecePtr &piece); auto ReadInternalPath() -> VLayoutPiecePath; - void ReadMarkers(VPPiece *piece); + void ReadMarkers(const VPPiecePtr &piece); auto ReadMarker() -> VLayoutPlaceLabel; - void ReadLabels(VPPiece *piece); + void ReadLabels(const VPPiecePtr &piece); auto ReadLabelLines() -> VTextManager; auto ReadLabelLine() -> TextLine; diff --git a/src/app/puzzle/xml/vplayoutfilewriter.cpp b/src/app/puzzle/xml/vplayoutfilewriter.cpp index a1e6faf22..e0f0d4c0d 100644 --- a/src/app/puzzle/xml/vplayoutfilewriter.cpp +++ b/src/app/puzzle/xml/vplayoutfilewriter.cpp @@ -137,7 +137,7 @@ auto GrainlineArrowDirrectionToString(GrainlineArrowDirection type) -> QString } // namespace //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteFile(VPLayout *layout, QIODevice *file) +void VPLayoutFileWriter::WriteFile(const VPLayoutPtr &layout, QIODevice *file) { setDevice(file); setAutoFormatting(true); @@ -152,7 +152,7 @@ void VPLayoutFileWriter::WriteFile(VPLayout *layout, QIODevice *file) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteLayout(VPLayout *layout) +void VPLayoutFileWriter::WriteLayout(const VPLayoutPtr &layout) { writeStartElement(ML::TagLayout); SetAttribute(ML::AttrVersion, VLayoutConverter::LayoutMaxVerStr); @@ -163,7 +163,7 @@ void VPLayoutFileWriter::WriteLayout(VPLayout *layout) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteProperties(VPLayout *layout) +void VPLayoutFileWriter::WriteProperties(const VPLayoutPtr &layout) { writeStartElement(ML::TagProperties); @@ -187,12 +187,12 @@ void VPLayoutFileWriter::WriteProperties(VPLayout *layout) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteSheets(VPLayout *layout) +void VPLayoutFileWriter::WriteSheets(const VPLayoutPtr &layout) { writeStartElement(ML::TagSheets); - QList sheets = layout->GetSheets(); - for (auto *sheet : sheets) + QList sheets = layout->GetSheets(); + for (const auto &sheet : sheets) { WriteSheet(sheet); } @@ -201,7 +201,7 @@ void VPLayoutFileWriter::WriteSheets(VPLayout *layout) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteSheet(VPSheet* sheet) +void VPLayoutFileWriter::WriteSheet(const VPSheetPtr &sheet) { writeStartElement(ML::TagSheet); @@ -213,7 +213,7 @@ void VPLayoutFileWriter::WriteSheet(VPSheet* sheet) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WriteTiles(VPLayout *layout) +void VPLayoutFileWriter::WriteTiles(const VPLayoutPtr &layout) { Q_UNUSED(layout); // to be removed @@ -228,10 +228,10 @@ void VPLayoutFileWriter::WriteTiles(VPLayout *layout) } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WritePieceList(const QList &list, const QString &tagName) +void VPLayoutFileWriter::WritePieceList(const QList &list, const QString &tagName) { writeStartElement(tagName); // piece list - for (auto *piece : list) + for (const auto &piece : list) { WritePiece(piece); } @@ -240,7 +240,7 @@ void VPLayoutFileWriter::WritePieceList(const QList &list, const QStr } //--------------------------------------------------------------------------------------------------------------------- -void VPLayoutFileWriter::WritePiece(VPPiece *piece) +void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece) { writeStartElement(ML::TagPiece); SetAttribute(ML::AttrID, piece->GetUUID().toString()); diff --git a/src/app/puzzle/xml/vplayoutfilewriter.h b/src/app/puzzle/xml/vplayoutfilewriter.h index defebc56d..415b0da7e 100644 --- a/src/app/puzzle/xml/vplayoutfilewriter.h +++ b/src/app/puzzle/xml/vplayoutfilewriter.h @@ -35,6 +35,7 @@ #include #include "../vmisc/literals.h" +#include "../layout/layoutdef.h" class VPLayout; class VPSheet; @@ -51,16 +52,16 @@ public: VPLayoutFileWriter()= default; ~VPLayoutFileWriter()= default; - void WriteFile(VPLayout *layout, QIODevice *file); + void WriteFile(const VPLayoutPtr &layout, QIODevice *file); private: - void WriteLayout(VPLayout *layout); - void WriteProperties(VPLayout *layout); - void WriteSheets(VPLayout *layout); - void WriteSheet(VPSheet* sheet); - void WriteTiles(VPLayout *layout); - void WritePieceList(const QList &list, const QString &tagName); - void WritePiece(VPPiece *piece); + void WriteLayout(const VPLayoutPtr &layout); + void WriteProperties(const VPLayoutPtr &layout); + void WriteSheets(const VPLayoutPtr &layout); + void WriteSheet(const VPSheetPtr &sheet); + void WriteTiles(const VPLayoutPtr &layout); + void WritePieceList(const QList &list, const QString &tagName); + void WritePiece(const VPPiecePtr &piece); void WriteLabel(const QVector &labelShape, const VTextManager &tm, const QString &tagName); void WriteLabelLines(const VTextManager &tm);