/************************************************************************ ** ** @file vpundopiecezvaluemove.cpp ** @author Roman Telezhynskyi ** @date 18 2, 2022 ** ** @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) 2022 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 "vpundopiecezvaluemove.h" #include "../layout/vppiece.h" #include "../layout/vplayout.h" #include "../layout/vpsheet.h" #include "undocommands/vpundocommand.h" namespace { //--------------------------------------------------------------------------------------------------------------------- auto CorrectedZValues(const QList> &order) -> QHash { QHash correctedZValues; qreal step = 0; if (not order.isEmpty()) { step = 1.0/order.size(); } for (int i = 0; i < order.size(); ++i) { const QVector &level = order.at(i); for (const auto &pieceId : level) { correctedZValues.insert(pieceId, i*step); } } return correctedZValues; } } // namespace //--------------------------------------------------------------------------------------------------------------------- VPUndoPieceZValueMove::VPUndoPieceZValueMove(const VPPiecePtr &piece, ML::ZValueMove move, QUndoCommand *parent) : VPUndoCommand(parent), m_piece(piece), m_move(move) { setText(QObject::tr("z value move piece")); VPSheetPtr sheet = Sheet(); if (not sheet.isNull()) { const QList pieces = sheet->GetPieces(); for(const auto& p : pieces) { if (not p.isNull()) { m_oldValues.insert(p->GetUniqueID(), p->ZValue()); } } } } //--------------------------------------------------------------------------------------------------------------------- void VPUndoPieceZValueMove::undo() { VPPiecePtr piece = Piece(); if (piece.isNull()) { return; } VPLayoutPtr layout = piece->Layout(); if (layout.isNull()) { return; } VPSheetPtr sheet = Sheet(); if (sheet.isNull()) { return; } if (layout->GetFocusedSheet() != sheet) { layout->SetFocusedSheet(sheet); } const QList pieces = sheet->GetPieces(); for (const auto &p: pieces) { if (not p.isNull()) { if (m_oldValues.contains(p->GetUniqueID())) { p->SetZValue(m_oldValues.value(p->GetUniqueID())); emit layout->PieceZValueChanged(p); } } } } //--------------------------------------------------------------------------------------------------------------------- void VPUndoPieceZValueMove::redo() { VPPiecePtr piece = Piece(); if (piece.isNull()) { return; } VPLayoutPtr layout = piece->Layout(); if (layout.isNull()) { return; } VPSheetPtr sheet = Sheet(); if (sheet.isNull()) { return; } if (layout->GetFocusedSheet() != sheet) { layout->SetFocusedSheet(sheet); } const QList pieces = sheet->GetPieces(); QList> order; if (m_move == ML::ZValueMove::Top) { order = Levels(pieces, true); order.append({piece->GetUniqueID()}); } else if (m_move == ML::ZValueMove::Up) { const qreal step = LevelStep(pieces); for (const auto &p: pieces) { if (p->GetUniqueID() != piece->GetUniqueID()) { p->SetZValue(p->ZValue() - step); } } order = Levels(pieces, false); } else if (m_move == ML::ZValueMove::Down) { const qreal step = LevelStep(pieces); for (const auto &p: pieces) { if (p->GetUniqueID() != piece->GetUniqueID()) { p->SetZValue(p->ZValue() + step); } } order = Levels(pieces, false); } else if (m_move == ML::ZValueMove::Bottom) { order = Levels(pieces, true); order.prepend({piece->GetUniqueID()}); } QHash correctedZValues = CorrectedZValues(order); for (const auto &p: pieces) { if (not p.isNull()) { p->SetZValue(correctedZValues.value(p->GetUniqueID(), p->ZValue())); emit layout->PieceZValueChanged(p); } } emit layout->LayoutChanged(); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPieceZValueMove::id() const -> int { return static_cast(ML::UndoCommand::ZValueMovePiece); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPieceZValueMove::Piece() const -> VPPiecePtr { return m_piece; } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPieceZValueMove::Sheet() const -> VPSheetPtr { VPPiecePtr p = Piece(); if (not p.isNull()) { return p->Sheet(); } return {}; } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPieceZValueMove::Levels(const QList &pieces, bool skip) const -> QList > { VPPiecePtr piece = Piece(); if (piece.isNull()) { return {}; } QMap> levels; for (const auto &p: pieces) { if (p.isNull() || (skip && p->GetUniqueID() == piece->GetUniqueID())) { continue; } if (levels.contains(p->ZValue())) { QVector level_images = levels.value(p->ZValue()); level_images.append(p->GetUniqueID()); levels[p->ZValue()] = level_images; } else { levels[p->ZValue()] = {p->GetUniqueID()}; } } return levels.values(); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPieceZValueMove::LevelStep(const QList &pieces) const -> qreal { QList> levels = Levels(pieces, false); if (levels.isEmpty()) { return 0; } return 1.0/levels.size(); } //--------------------------------------------------------------------------------------------------------------------- // Z value pieces VPUndoPiecesZValueMove::VPUndoPiecesZValueMove(const QList &pieces, ML::ZValueMove move, QUndoCommand *parent) : VPUndoCommand(parent), m_move(move) { setText(QObject::tr("z value move pieces")); m_pieces.reserve(pieces.size()); for(const auto& p : pieces) { m_pieces.append(p); } VPSheetPtr sheet = Sheet(); if (not sheet.isNull()) { const QList pieces = sheet->GetPieces(); for(const auto& p : pieces) { if (not p.isNull()) { m_oldValues.insert(p->GetUniqueID(), p->ZValue()); } } } } //--------------------------------------------------------------------------------------------------------------------- void VPUndoPiecesZValueMove::undo() { if (m_pieces.isEmpty()) { return; } VPLayoutPtr layout = Layout(); if (layout.isNull()) { return; } VPSheetPtr sheet = Sheet(); if (sheet.isNull()) { return; } if (layout->GetFocusedSheet() != sheet) { layout->SetFocusedSheet(sheet); } const QList pieces = sheet->GetPieces(); for (const auto &p: pieces) { if (not p.isNull()) { if (m_oldValues.contains(p->GetUniqueID())) { p->SetZValue(m_oldValues.value(p->GetUniqueID())); emit layout->PieceZValueChanged(p); } } } } //--------------------------------------------------------------------------------------------------------------------- void VPUndoPiecesZValueMove::redo() { if (m_pieces.isEmpty()) { return; } VPLayoutPtr layout = Layout(); if (layout.isNull()) { return; } VPSheetPtr sheet = Sheet(); if (sheet.isNull()) { return; } if (layout->GetFocusedSheet() != sheet) { layout->SetFocusedSheet(sheet); } const QList allPieces = sheet->GetPieces(); QVector ids = PieceIds(); QList> order; if (m_move == ML::ZValueMove::Top) { order = Levels(allPieces, ids, true); order.append(ids); } else if (m_move == ML::ZValueMove::Up) { const qreal step = LevelStep(allPieces); for (const auto &p: allPieces) { if (not ids.contains(p->GetUniqueID())) { p->SetZValue(p->ZValue() - step); } } order = Levels(allPieces, ids, false); } else if (m_move == ML::ZValueMove::Down) { const qreal step = LevelStep(allPieces); for (const auto &p: allPieces) { if (not ids.contains(p->GetUniqueID())) { p->SetZValue(p->ZValue() + step); } } order = Levels(allPieces, ids, false); } else if (m_move == ML::ZValueMove::Bottom) { order = Levels(allPieces, ids, true); order.prepend(ids); } QHash correctedZValues = CorrectedZValues(order); for (const auto &p: allPieces) { if (not p.isNull()) { p->SetZValue(correctedZValues.value(p->GetUniqueID(), p->ZValue())); emit layout->PieceZValueChanged(p); } } emit layout->LayoutChanged(); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::id() const -> int { return static_cast(ML::UndoCommand::ZValueMovePieces); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::Layout() const -> VPLayoutPtr { for (const auto& piece : m_pieces) { VPPiecePtr p = piece.toStrongRef(); if (not p.isNull()) { return p->Layout(); } } return {}; } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::Sheet() const -> VPSheetPtr { for (const auto& piece : m_pieces) { VPPiecePtr p = piece.toStrongRef(); if (not p.isNull()) { return p->Sheet(); } } return {}; } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::PieceIds() const -> QVector { QVector ids; ids.reserve(m_pieces.size()); for (const auto& piece : m_pieces) { VPPiecePtr p = piece.toStrongRef(); if (not p.isNull()) { ids.append(p->GetUniqueID()); } } return ids; } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::Levels(const QList &allPieces, const QVector &skipPieces, bool skip) -> QList > { QMap> levels; for (const auto &p: allPieces) { if (p.isNull() || (skip && skipPieces.contains(p->GetUniqueID()))) { continue; } if (levels.contains(p->ZValue())) { QVector level_images = levels.value(p->ZValue()); level_images.append(p->GetUniqueID()); levels[p->ZValue()] = level_images; } else { levels[p->ZValue()] = {p->GetUniqueID()}; } } return levels.values(); } //--------------------------------------------------------------------------------------------------------------------- auto VPUndoPiecesZValueMove::LevelStep(const QList &pieces) const -> qreal { QList> levels = Levels(pieces, QVector(), false); if (levels.isEmpty()) { return 0; } return 1.0/levels.size(); }