From 537efbeaa838049272136138d559b774c05b9521 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Sat, 20 Apr 2024 17:00:51 +0300 Subject: [PATCH] Move piece position validation to separate thread. --- src/app/puzzle/layout/vplayout.cpp | 29 +- src/app/puzzle/layout/vplayout.h | 1 - src/app/puzzle/layout/vppiece.cpp | 51 ++- src/app/puzzle/layout/vpsheet.cpp | 464 ++++++++++++-------- src/app/puzzle/layout/vpsheet.h | 22 +- src/app/puzzle/scene/vpmaingraphicsview.cpp | 4 +- src/app/puzzle/vpmainwindow.cpp | 30 +- 7 files changed, 357 insertions(+), 244 deletions(-) diff --git a/src/app/puzzle/layout/vplayout.cpp b/src/app/puzzle/layout/vplayout.cpp index 31e8d1c92..ea1d5964a 100644 --- a/src/app/puzzle/layout/vplayout.cpp +++ b/src/app/puzzle/layout/vplayout.cpp @@ -276,7 +276,7 @@ auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull()) { m_sheets.append(sheet); - connect(this, &VPLayout::PieceTransformationChanged, sheet.data(), &VPSheet::CheckPiecePositionValidity); + connect(this, &VPLayout::PieceTransformationChanged, sheet.data(), &VPSheet::CheckPiecesPositionValidity); } return sheet; } @@ -328,7 +328,7 @@ void VPLayout::SetFocusedSheet(const VPSheetPtr &focusedSheet) m_focusedSheet = focusedSheet.isNull() ? m_sheets.constFirst() : focusedSheet; } - CheckPiecesPositionValidity(m_focusedSheet); + m_focusedSheet->CheckPiecesPositionValidity(); emit ActiveSheetChanged(m_focusedSheet); } @@ -427,30 +427,9 @@ void VPLayout::CheckPiecesPositionValidity() const { for (const auto &sheet : m_sheets) { - CheckPiecesPositionValidity(sheet); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPLayout::CheckPiecesPositionValidity(const VPSheetPtr &sheet) const -{ - if (not sheet.isNull()) - { - const VPLayoutSettings &settings = LayoutSettings(); - - if (settings.GetWarningPiecesOutOfBound()) + if (not sheet.isNull()) { - sheet->ValidatePiecesOutOfBound(); - } - - if (settings.GetWarningSuperpositionOfPieces()) - { - sheet->ValidateSuperpositionOfPieces(); - } - - if (settings.GetWarningPieceGapePosition()) - { - sheet->ValidatePieceGapePosition(); + sheet->CheckPiecesPositionValidity(); } } } diff --git a/src/app/puzzle/layout/vplayout.h b/src/app/puzzle/layout/vplayout.h index 2478a121f..e2a810d19 100644 --- a/src/app/puzzle/layout/vplayout.h +++ b/src/app/puzzle/layout/vplayout.h @@ -91,7 +91,6 @@ public: void Clear(); void CheckPiecesPositionValidity() const; - void CheckPiecesPositionValidity(const VPSheetPtr &sheet) const; auto TileFactory() const -> QSharedPointer; void SetTileFactory(const QSharedPointer &newTileFactory); diff --git a/src/app/puzzle/layout/vppiece.cpp b/src/app/puzzle/layout/vppiece.cpp index 11c5b8af1..1d417a3c6 100644 --- a/src/app/puzzle/layout/vppiece.cpp +++ b/src/app/puzzle/layout/vppiece.cpp @@ -62,7 +62,7 @@ namespace { constexpr qreal minStickyDistance = MmToPixel(3.); constexpr qreal maxStickyDistance = MmToPixel(15.); -constexpr qreal stickyShift = MmToPixel(1.); +constexpr qreal stickyShift = MmToPixel(5.); //--------------------------------------------------------------------------------------------------------------------- auto CutEdge(const QLineF &edge) -> QVector @@ -440,24 +440,15 @@ auto VPPiece::PrepareStickyPath(const QVector &path) -> QVector &path1, const QVector &path2) -> QLineF { - std::function const DistanceFunc = [path2](const QPointF &p1) + const int maxThreads = QThread::idealThreadCount(); + + QVector> path1Chunks; + path1Chunks.reserve(maxThreads); + const vsizetype chunkSize = (path1.size() + maxThreads - 1) / maxThreads; // Round up + for (vsizetype i = 0; i < path1.size(); i += chunkSize) { - qreal minLocalDistance = std::numeric_limits::max(); - QLineF localClosestDistance; - - for (const auto &p2 : path2) - { - QLineF const d(p1, p2); - qreal const length = d.length(); - if (length < minLocalDistance) - { - minLocalDistance = length; - localClosestDistance = d; - } - } - - return localClosestDistance; - }; + path1Chunks.append(path1.mid(i, chunkSize)); + } std::function const ReduceFunc = [](QLineF &result, const QLineF &next) { @@ -469,7 +460,29 @@ auto VPPiece::ClosestDistance(const QVector &path1, const QVector(path1, DistanceFunc, ReduceFunc); + auto CalculateClosestDistanceForChunk = [&](const QVector &chunk) -> QLineF + { + qreal minLocalDistance = std::numeric_limits::max(); + QLineF localClosestDistance; + + for (const auto &c : chunk) + { + for (const auto &p2 : path2) + { + QLineF const d(c, p2); + qreal const length = d.length(); + if (length < minLocalDistance) + { + minLocalDistance = length; + localClosestDistance = d; + } + } + } + + return localClosestDistance; + }; + + return QtConcurrent::blockingMappedReduced(path1Chunks, CalculateClosestDistanceForChunk, ReduceFunc); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/puzzle/layout/vpsheet.cpp b/src/app/puzzle/layout/vpsheet.cpp index 5e0728ca3..57d25c45f 100644 --- a/src/app/puzzle/layout/vpsheet.cpp +++ b/src/app/puzzle/layout/vpsheet.cpp @@ -38,6 +38,205 @@ #include "vplayout.h" #include "vppiece.h" +#include + +namespace +{ +struct VSheetPiece +{ + QString m_id{}; + bool m_showFullPiece{false}; + QLineF m_seamMirrorLine{}; + QLineF m_seamAllowanceMirrorLine{}; + QVector m_externalContourPoints{}; +}; + +struct VPiecesValidationData +{ + bool m_warnPiecesOutOfBound{false}; + bool m_warnSuperpositionOfPieces{false}; + bool m_warnPieceGapePosition{false}; + bool m_cutOnFold{false}; + QRectF m_sheetRect{}; + qreal m_pieceGap{0}; + QVector m_pieces{}; +}; + +//--------------------------------------------------------------------------------------------------------------------- +void ValidatePiecesOutOfBound(const VPiecesValidationData &data, QHash &validations) +{ + + for (const auto &piece : data.m_pieces) + { + VPiecePositionValidity validation = validations.value(piece.m_id); + + if (data.m_cutOnFold && not piece.m_showFullPiece && !piece.m_seamMirrorLine.isNull()) + { + QLineF const foldLine = data.m_sheetRect.width() >= data.m_sheetRect.height() + ? QLineF(data.m_sheetRect.topLeft(), data.m_sheetRect.topRight()) + : QLineF(data.m_sheetRect.topRight(), data.m_sheetRect.bottomRight()); + + validation.m_outOfBound = + not VGObject::IsLineSegmentOnLineSegment(foldLine, piece.m_seamAllowanceMirrorLine, MmToPixel(0.5)); + } + else + { + QRectF const pieceRect = VLayoutPiece::BoundingRect(piece.m_externalContourPoints); + validation.m_outOfBound = not data.m_sheetRect.contains(pieceRect); + } + + validations.insert(piece.m_id, validation); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void ValidateSuperpositionOfPieces(const VPiecesValidationData &data, + QHash &validations) +{ + QSet invalidPieces; + invalidPieces.reserve(data.m_pieces.size()); + + for (const auto &piece : data.m_pieces) + { + if (invalidPieces.contains(piece.m_id)) + { + continue; + } + + bool hasSuperposition = false; + VSheetPiece invalidPiece; + + for (const auto &p : data.m_pieces) + { + if (piece.m_id == p.m_id) + { + continue; + } + + if (VPPiece::PathsSuperposition(piece.m_externalContourPoints, p.m_externalContourPoints)) + { + hasSuperposition = true; + invalidPiece = p; + break; + } + } + + auto UpdateValidity = [&validations, hasSuperposition, &invalidPieces](const QString &id) + { + VPiecePositionValidity validation = validations.value(id); + validation.m_superposition = hasSuperposition; + validations.insert(id, validation); + if (hasSuperposition) + { + invalidPieces.insert(id); + } + }; + + UpdateValidity(piece.m_id); + + if (!invalidPiece.m_id.isEmpty()) + { + UpdateValidity(invalidPiece.m_id); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void ValidatePiecesGapePosition(const VPiecesValidationData &data, QHash &validations) +{ + if (data.m_pieceGap <= 0) + { + return; + } + + QSet invalidPieces; + invalidPieces.reserve(data.m_pieces.size()); + + for (const auto &piece : data.m_pieces) + { + if (invalidPieces.contains(piece.m_id)) + { + continue; + } + + QRectF const path1Rect = VLayoutPiece::BoundingRect(piece.m_externalContourPoints) + .adjusted(-data.m_pieceGap, -data.m_pieceGap, data.m_pieceGap, data.m_pieceGap); + QVector const path1 = VPPiece::PrepareStickyPath(piece.m_externalContourPoints); + bool hasInvalidPieceGapPosition = false; + VSheetPiece invalidPiece; + + for (const auto &p : data.m_pieces) + { + if (piece.m_id == p.m_id) + { + continue; + } + + QRectF const path2Rect = + VLayoutPiece::BoundingRect(p.m_externalContourPoints) + .adjusted(-data.m_pieceGap, -data.m_pieceGap, data.m_pieceGap, data.m_pieceGap); + + if (!path1Rect.intersects(path2Rect) && !path1Rect.contains(path2Rect) && !path2Rect.contains(path1Rect)) + { + continue; + } + + QVector const path2 = VPPiece::PrepareStickyPath(p.m_externalContourPoints); + + QLineF const distance = VPPiece::ClosestDistance(path1, path2); + + if (distance.length() < data.m_pieceGap - accuracyPointOnLine) + { + hasInvalidPieceGapPosition = true; + invalidPiece = p; + break; + } + } + + auto UpdateValidity = [&validations, hasInvalidPieceGapPosition, &invalidPieces](const QString &id) + { + VPiecePositionValidity validation = validations.value(id); + validation.m_gap = hasInvalidPieceGapPosition; + validations.insert(id, validation); + if (hasInvalidPieceGapPosition) + { + invalidPieces.insert(id); + } + }; + + UpdateValidity(piece.m_id); + + if (!invalidPiece.m_id.isEmpty()) + { + UpdateValidity(invalidPiece.m_id); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto ValidatePiecesPositions(const VPiecesValidationData &data) -> QHash +{ + QHash validations; + + if (data.m_warnPiecesOutOfBound) + { + ValidatePiecesOutOfBound(data, validations); + } + + if (data.m_warnSuperpositionOfPieces) + { + ValidateSuperpositionOfPieces(data, validations); + } + + if (data.m_warnPieceGapePosition) + { + ValidatePiecesGapePosition(data, validations); + } + + return validations; +} +} // namespace + // VPSheetSceneData //--------------------------------------------------------------------------------------------------------------------- VPSheetSceneData::VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid) @@ -339,7 +538,8 @@ void VPSheetSceneData::ConnectPiece(VPGraphicsPiece *piece) const VPSheet::VPSheet(const VPLayoutPtr &layout, QObject *parent) : QObject(parent), m_layout(layout), - m_sceneData(QSharedPointer::create(layout, Uuid())) + m_sceneData(QSharedPointer::create(layout, Uuid())), + m_validityWatcher(new QFutureWatcher>(this)) { SCASSERT(not layout.isNull()) @@ -347,10 +547,16 @@ VPSheet::VPSheet(const VPLayoutPtr &layout, QObject *parent) SetIgnoreMargins(settings->GetLayoutSheetIgnoreMargins()); SetSheetMargins(settings->GetLayoutSheetMargins()); SetSheetSize(QSizeF(settings->GetLayoutSheetPaperWidth(), settings->GetLayoutSheetPaperHeight())); + + connect(m_validityWatcher, &QFutureWatcher>::finished, this, + &VPSheet::UpdatePiecesValidity); } //--------------------------------------------------------------------------------------------------------------------- -VPSheet::~VPSheet() = default; +VPSheet::~VPSheet() +{ + m_validityWatcher->cancel(); +} //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GetLayout() const -> VPLayoutPtr @@ -508,171 +714,6 @@ void VPSheet::SetTrashSheet(bool newTrashSheet) m_trashSheet = newTrashSheet; } -//--------------------------------------------------------------------------------------------------------------------- -void VPSheet::ValidateSuperpositionOfPieces() const -{ - QList const pieces = GetPieces(); - - for (const auto &piece : pieces) - { - if (piece.isNull() || piece->OutOfBound()) - { - continue; - } - - const bool oldSuperpositionOfPieces = piece->HasSuperpositionWithPieces(); - QVector path1; - CastTo(piece->GetMappedExternalContourPoints(), path1); - bool hasSuperposition = false; - - for (const auto &p : pieces) - { - if (p.isNull() || piece == p) - { - continue; - } - - QVector path2; - CastTo(p->GetMappedExternalContourPoints(), path2); - - bool const superposition = VPPiece::PathsSuperposition(path1, path2); - if (superposition) - { - hasSuperposition = superposition; - break; - } - } - - piece->SetHasSuperpositionWithPieces(hasSuperposition); - - if (oldSuperpositionOfPieces != piece->HasSuperpositionWithPieces()) - { - VPLayoutPtr const layout = GetLayout(); - if (not layout.isNull()) - { - emit layout->PiecePositionValidityChanged(piece); - } - } - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPSheet::ValidatePieceGapePosition(const VPPiecePtr &piece) const -{ - VPLayoutPtr const layout = GetLayout(); - if (layout.isNull()) - { - return; - } - - const qreal pieceGap = layout->LayoutSettings().GetPiecesGap(); - if (pieceGap <= 0) - { - return; - } - - if (piece.isNull() || piece->HasSuperpositionWithPieces() || piece->OutOfBound()) - { - return; - } - - const bool oldInvalidPieceGapPosition = piece->HasInvalidPieceGapPosition(); - - QVector path1; - CastTo(piece->GetMappedExternalContourPoints(), path1); - path1 = VPPiece::PrepareStickyPath(path1); - bool hasInvalidPieceGapPosition = false; - - QList const pieces = GetPieces(); - - for (const auto &p : pieces) - { - if (p.isNull() || piece == p) - { - continue; - } - - QVector path2; - CastTo(p->GetMappedExternalContourPoints(), path2); - path2 = VPPiece::PrepareStickyPath(path2); - - QLineF const distance = VPPiece::ClosestDistance(path1, path2); - - if (distance.length() < pieceGap - accuracyPointOnLine) - { - hasInvalidPieceGapPosition = true; - break; - } - } - - piece->SetHasInvalidPieceGapPosition(hasInvalidPieceGapPosition); - - if (oldInvalidPieceGapPosition != piece->HasInvalidPieceGapPosition()) - { - VPLayoutPtr const layout = GetLayout(); - if (not layout.isNull()) - { - emit layout->PiecePositionValidityChanged(piece); - } - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPSheet::ValidatePieceGapePosition() const -{ - QList const pieces = GetPieces(); - for (const auto &piece : pieces) - { - ValidatePieceGapePosition(piece); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const -{ - if (piece.isNull()) - { - return; - } - - const bool oldOutOfBound = piece->OutOfBound(); - QRectF const sheetRect = GetMarginsRect(); - - VPLayoutPtr const layout = GetLayout(); - if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold() && not piece->IsShowFullPiece() && - !piece->GetSeamMirrorLine().isNull()) - { - QLineF const foldLine = sheetRect.width() >= sheetRect.height() - ? QLineF(sheetRect.topLeft(), sheetRect.topRight()) - : QLineF(sheetRect.topRight(), sheetRect.bottomRight()); - piece->SetOutOfBound(not VGObject::IsLineSegmentOnLineSegment( - foldLine, piece->GetMappedSeamAllowanceMirrorLine(), MmToPixel(0.5))); - } - else - { - QRectF const pieceRect = piece->MappedDetailBoundingRect(); - piece->SetOutOfBound(not sheetRect.contains(pieceRect)); - } - - if (oldOutOfBound != piece->OutOfBound()) - { - if (not layout.isNull()) - { - emit layout->PiecePositionValidityChanged(piece); - } - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPSheet::ValidatePiecesOutOfBound() const -{ - QList const pieces = GetPieces(); - for (const auto &piece : pieces) - { - ValidatePieceOutOfBound(piece); - } -} - //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GetSheetRect() const -> QRectF { @@ -752,32 +793,91 @@ void VPSheet::RemoveUnusedLength() } //--------------------------------------------------------------------------------------------------------------------- -void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const +void VPSheet::CheckPiecesPositionValidity() const { + if (m_validityWatcher->isFinished()) + { + VPLayoutPtr const layout = GetLayout(); + if (layout.isNull()) + { + return; + } + + VPiecesValidationData data; + data.m_warnPiecesOutOfBound = layout->LayoutSettings().GetWarningPiecesOutOfBound(); + data.m_warnSuperpositionOfPieces = layout->LayoutSettings().GetWarningSuperpositionOfPieces(); + data.m_warnPieceGapePosition = layout->LayoutSettings().GetWarningPieceGapePosition(); + data.m_cutOnFold = layout->LayoutSettings().IsCutOnFold(); + data.m_sheetRect = GetMarginsRect(); + data.m_pieceGap = layout->LayoutSettings().GetPiecesGap(); + + QList const pieces = GetPieces(); + QVector sheetPieces; + sheetPieces.reserve(pieces.size()); + + for (const auto &piece : pieces) + { + VSheetPiece data; + data.m_showFullPiece = piece->IsShowFullPiece(); + data.m_id = piece->GetUniqueID(); + data.m_seamMirrorLine = piece->GetMappedSeamMirrorLine(); + data.m_seamAllowanceMirrorLine = piece->GetMappedSeamAllowanceMirrorLine(); + + QVector points; + CastTo(piece->GetMappedExternalContourPoints(), points); + data.m_externalContourPoints = points; + + sheetPieces.append(data); + } + + data.m_pieces = sheetPieces; + + m_validationStale = false; + m_validityWatcher->setFuture(QtConcurrent::run([data]() { return ValidatePiecesPositions(data); })); + } + else + { + m_validationStale = true; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheet::UpdatePiecesValidity() +{ + QHash const newValidations = m_validityWatcher->future().result(); + + QList const pieces = GetPieces(); + QHash sortedPieces; + sortedPieces.reserve(pieces.size()); + + for (const auto &piece : pieces) + { + sortedPieces.insert(piece->GetUniqueID(), piece); + } + VPLayoutPtr const layout = GetLayout(); if (layout.isNull()) { return; } - if (QList const pieces = GetPieces(); piece.isNull() || not pieces.contains(piece)) + for (auto i = newValidations.cbegin(), end = newValidations.cend(); i != end; ++i) { - return; + if (sortedPieces.contains(i.key())) + { + VPPiecePtr const piece = sortedPieces.value(i.key()); + piece->SetOutOfBound(i.value().m_outOfBound); + piece->SetHasSuperpositionWithPieces(i.value().m_superposition); + piece->SetHasInvalidPieceGapPosition(i.value().m_gap); + + emit layout->PiecePositionValidityChanged(piece); + } } - if (layout->LayoutSettings().GetWarningPiecesOutOfBound()) + if (m_validationStale) { - ValidatePieceOutOfBound(piece); - } - - if (layout->LayoutSettings().GetWarningSuperpositionOfPieces()) - { - ValidateSuperpositionOfPieces(); - } - - if (layout->LayoutSettings().GetWarningPieceGapePosition()) - { - ValidatePieceGapePosition(piece); + m_validationStale = false; + CheckPiecesPositionValidity(); } } diff --git a/src/app/puzzle/layout/vpsheet.h b/src/app/puzzle/layout/vpsheet.h index 401a79af6..b43d5417d 100644 --- a/src/app/puzzle/layout/vpsheet.h +++ b/src/app/puzzle/layout/vpsheet.h @@ -29,6 +29,7 @@ #define VPSHEET_H #include +#include #include #include #include @@ -50,6 +51,13 @@ class VPGraphicsSheet; class VLayoutPiece; class QGraphicsItem; +struct VPiecePositionValidity +{ + bool m_outOfBound{false}; + bool m_superposition{false}; + bool m_gap{false}; +}; + class VPSheetSceneData { public: @@ -183,12 +191,6 @@ public: auto TrashSheet() const -> bool; void SetTrashSheet(bool newTrashSheet); - void ValidateSuperpositionOfPieces() const; - void ValidatePieceGapePosition(const VPPiecePtr &piece) const; - void ValidatePieceGapePosition() const; - void ValidatePieceOutOfBound(const VPPiecePtr &piece) const; - void ValidatePiecesOutOfBound() const; - auto GetSheetRect() const -> QRectF; auto GetMarginsRect() const -> QRectF; @@ -283,7 +285,10 @@ public: auto GetSheetOrientation() const -> QPageLayout::Orientation; public slots: - void CheckPiecePositionValidity(const VPPiecePtr &piece) const; + void CheckPiecesPositionValidity() const; + +private slots: + void UpdatePiecesValidity(); private: Q_DISABLE_COPY_MOVE(VPSheet) // NOLINT @@ -316,6 +321,9 @@ private: QSharedPointer m_sceneData{nullptr}; + QFutureWatcher> *m_validityWatcher; + mutable bool m_validationStale{false}; + auto SheetUnits() const -> Unit; }; diff --git a/src/app/puzzle/scene/vpmaingraphicsview.cpp b/src/app/puzzle/scene/vpmaingraphicsview.cpp index 80209bcd5..644805502 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.cpp +++ b/src/app/puzzle/scene/vpmaingraphicsview.cpp @@ -650,9 +650,7 @@ void VPMainGraphicsView::RemovePiece() const if (not layout.isNull()) { emit layout->PieceSelectionChanged(piece); - - auto *command = new VPUndoMovePieceOnSheet(VPSheetPtr(), piece); - layout->UndoStack()->push(command); + layout->UndoStack()->push(new VPUndoMovePieceOnSheet(VPSheetPtr(), piece)); } } } diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 03afe4d91..2cb6b7777 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -1119,7 +1119,7 @@ void VPMainWindow::InitMarginsData(const QString &suffix) LayoutWasSaved(false); m_layout->TileFactory()->RefreshTileInfos(); m_graphicsView->RefreshLayout(); - m_layout->CheckPiecesPositionValidity(sheet); + sheet->CheckPiecesPositionValidity(); } } }); @@ -2140,7 +2140,10 @@ void VPMainWindow::SheetPaperSizeChanged() } else { - m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet()); + if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull()) + { + sheet->CheckPiecesPositionValidity(); + } } } @@ -3908,7 +3911,7 @@ void VPMainWindow::on_SheetMarginChanged() LayoutWasSaved(false); - m_layout->CheckPiecesPositionValidity(sheet); + sheet->CheckPiecesPositionValidity(); } m_graphicsView->RefreshLayout(); @@ -4910,7 +4913,10 @@ void VPMainWindow::LayoutWarningPieceGapePosition_toggled(bool checked) LayoutWasSaved(false); if (checked) { - m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet()); + if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull()) + { + sheet->CheckPiecesPositionValidity(); + } } m_graphicsView->RefreshPieces(); } @@ -4925,7 +4931,11 @@ void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked) LayoutWasSaved(false); if (checked) { - m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet()); + + if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull()) + { + sheet->CheckPiecesPositionValidity(); + } } m_graphicsView->RefreshPieces(); } @@ -4941,7 +4951,10 @@ void VPMainWindow::LayoutWarningPiecesOutOfBound_toggled(bool checked) if (checked) { - m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet()); + if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull()) + { + sheet->CheckPiecesPositionValidity(); + } } m_graphicsView->RefreshPieces(); } @@ -4954,7 +4967,10 @@ void VPMainWindow::LayoutCutOnFold_toggled(bool checked) { m_layout->LayoutSettings().SetCutOnFold(checked); LayoutWasSaved(false); - m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet()); + if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull()) + { + sheet->CheckPiecesPositionValidity(); + } m_graphicsView->RefreshLayout(); } }