New warning "Piece gape position".

This commit is contained in:
Roman Telezhynskyi 2024-04-08 16:26:09 +03:00
parent 39d56e34aa
commit 9e3659830e
21 changed files with 282 additions and 62 deletions

View File

@ -66,6 +66,7 @@
- Updated Windows installer. - Updated Windows installer.
- Automatic crash reports. - Automatic crash reports.
- Improve compatibility with Richpeace CAD. - Improve compatibility with Richpeace CAD.
- New warning "Piece gape position".
# Valentina 0.7.52 September 12, 2022 # Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru. - Fix crash when default locale is ru.

View File

@ -128,6 +128,8 @@ PuzzlePreferencesLayoutPage::PuzzlePreferencesLayoutPage(QWidget *parent)
connect(ui->checkBoxWarningPiecesOutOfBound, &QCheckBox::stateChanged, this, connect(ui->checkBoxWarningPiecesOutOfBound, &QCheckBox::stateChanged, this,
[this]() { m_settingsChanged = true; }); [this]() { m_settingsChanged = true; });
connect(ui->checkBoxFollowGrainline, &QCheckBox::stateChanged, this, [this]() { m_settingsChanged = true; }); connect(ui->checkBoxFollowGrainline, &QCheckBox::stateChanged, this, [this]() { m_settingsChanged = true; });
connect(ui->checkBoxWarningPieceGapePosition, &QCheckBox::stateChanged, this,
[this]() { m_settingsChanged = true; });
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -166,6 +168,7 @@ auto PuzzlePreferencesLayoutPage::Apply() -> QStringList
settings->SetLayoutStickyEdges(ui->checkBoxStickyEdges->isChecked()); settings->SetLayoutStickyEdges(ui->checkBoxStickyEdges->isChecked());
settings->SetLayoutWarningPiecesOutOfBound(ui->checkBoxWarningPiecesOutOfBound->isChecked()); settings->SetLayoutWarningPiecesOutOfBound(ui->checkBoxWarningPiecesOutOfBound->isChecked());
settings->SetLayoutFollowGrainline(ui->checkBoxFollowGrainline->isChecked()); settings->SetLayoutFollowGrainline(ui->checkBoxFollowGrainline->isChecked());
settings->SetLayoutWarningPieceGapePosition(ui->checkBoxWarningPieceGapePosition->isChecked());
settings->SetLayoutLineWidth(ui->spinBoxLineWidth->value()); settings->SetLayoutLineWidth(ui->spinBoxLineWidth->value());
@ -661,6 +664,7 @@ void PuzzlePreferencesLayoutPage::ReadSettings()
ui->checkBoxStickyEdges->setChecked(settings->GetLayoutStickyEdges()); ui->checkBoxStickyEdges->setChecked(settings->GetLayoutStickyEdges());
ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound()); ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound());
ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline()); ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline());
ui->checkBoxWarningPieceGapePosition->setChecked(settings->GetLayoutWarningPieceGapePosition());
ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, LayoutUnit())); ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, LayoutUnit()));
SetPieceGap(settings->GetLayoutPieceGap()); SetPieceGap(settings->GetLayoutPieceGap());

View File

@ -87,7 +87,7 @@
<item> <item>
<widget class="QToolButton" name="toolButtonSheetPortraitOritation"> <widget class="QToolButton" name="toolButtonSheetPortraitOritation">
<property name="text"> <property name="text">
<string notr="true"></string> <string notr="true"/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc"> <iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
@ -107,7 +107,7 @@
<item> <item>
<widget class="QToolButton" name="toolButtonSheetLandscapeOrientation"> <widget class="QToolButton" name="toolButtonSheetLandscapeOrientation">
<property name="text"> <property name="text">
<string notr="true"></string> <string notr="true"/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc"> <iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
@ -309,6 +309,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxWarningPieceGapePosition">
<property name="text">
<string>Warning piece gape position</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="checkBoxStickyEdges"> <widget class="QCheckBox" name="checkBoxStickyEdges">
<property name="text"> <property name="text">
@ -475,7 +482,7 @@
<item> <item>
<widget class="QToolButton" name="toolButtonTilePortraitOrientation"> <widget class="QToolButton" name="toolButtonTilePortraitOrientation">
<property name="text"> <property name="text">
<string notr="true"></string> <string notr="true"/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc"> <iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
@ -495,7 +502,7 @@
<item> <item>
<widget class="QToolButton" name="toolButtonTileLandscapeOrientation"> <widget class="QToolButton" name="toolButtonTileLandscapeOrientation">
<property name="text"> <property name="text">
<string notr="true"></string> <string notr="true"/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc"> <iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">

View File

@ -90,6 +90,7 @@ auto VPLayout::CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr
layout->LayoutSettings().SetWarningSuperpositionOfPieces(settings->GetLayoutWarningPiecesSuperposition()); layout->LayoutSettings().SetWarningSuperpositionOfPieces(settings->GetLayoutWarningPiecesSuperposition());
layout->LayoutSettings().SetWarningPiecesOutOfBound(settings->GetLayoutWarningPiecesOutOfBound()); layout->LayoutSettings().SetWarningPiecesOutOfBound(settings->GetLayoutWarningPiecesOutOfBound());
layout->LayoutSettings().SetWarningPieceGapePosition(settings->GetLayoutWarningPieceGapePosition());
layout->LayoutSettings().SetFollowGrainline(settings->GetLayoutFollowGrainline()); layout->LayoutSettings().SetFollowGrainline(settings->GetLayoutFollowGrainline());
layout->LayoutSettings().SetStickyEdges(settings->GetLayoutStickyEdges()); layout->LayoutSettings().SetStickyEdges(settings->GetLayoutStickyEdges());
layout->LayoutSettings().SetPiecesGap(settings->GetLayoutPieceGap()); layout->LayoutSettings().SetPiecesGap(settings->GetLayoutPieceGap());

View File

@ -66,6 +66,18 @@ auto VPLayoutSettings::GetWarningPiecesOutOfBound() const -> bool
return m_warningPiecesOutOfBound; return m_warningPiecesOutOfBound;
} }
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetWarningPieceGapePosition(bool state)
{
m_warningPieceGapePosition = state;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetWarningPieceGapePosition() const -> bool
{
return m_warningPieceGapePosition;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTitle(const QString &title) void VPLayoutSettings::SetTitle(const QString &title)
{ {

View File

@ -91,6 +91,9 @@ public:
void SetWarningPiecesOutOfBound(bool state); void SetWarningPiecesOutOfBound(bool state);
auto GetWarningPiecesOutOfBound() const -> bool; auto GetWarningPiecesOutOfBound() const -> bool;
void SetWarningPieceGapePosition(bool state);
auto GetWarningPieceGapePosition() const -> bool;
/** /**
* @brief SetFollowGrainline Sets the type of grainline for the pieces to follow * @brief SetFollowGrainline Sets the type of grainline for the pieces to follow
* @param state the type of grainline * @param state the type of grainline
@ -330,6 +333,7 @@ private:
bool m_warningSuperpositionOfPieces{false}; bool m_warningSuperpositionOfPieces{false};
bool m_warningPiecesOutOfBound{false}; bool m_warningPiecesOutOfBound{false};
bool m_warningPieceGapePosition{false};
QString m_title{}; QString m_title{};
QString m_description{}; QString m_description{};

View File

@ -61,7 +61,7 @@ namespace
{ {
constexpr qreal minStickyDistance = MmToPixel(3.); constexpr qreal minStickyDistance = MmToPixel(3.);
constexpr qreal maxStickyDistance = MmToPixel(15.); constexpr qreal maxStickyDistance = MmToPixel(15.);
constexpr qreal stickyShift = MmToPixel(20.); constexpr qreal stickyShift = MmToPixel(1.);
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto CutEdge(const QLineF &edge) -> QVector<QPointF> auto CutEdge(const QLineF &edge) -> QVector<QPointF>
@ -95,58 +95,6 @@ auto CutEdge(const QLineF &edge) -> QVector<QPointF>
} }
return points; return points;
} }
//---------------------------------------------------------------------------------------------------------------------
auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
{
if (path.size() < 2)
{
return path;
}
QVector<QPointF> stickyPath;
for (int i = 0; i < path.size(); ++i)
{
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size() - 1 ? i + 1 : 0)));
}
return stickyPath;
}
//---------------------------------------------------------------------------------------------------------------------
auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
{
return QtConcurrent::blockingMappedReduced(
path1,
[path2](const QPointF &p1)
{
qreal minLocalDistance = std::numeric_limits<qreal>::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;
},
[](QLineF &result, const QLineF &next)
{
qreal const dist1 = result.length();
qreal const dist2 = next.length();
if (result.isNull() || dist2 < dist1)
{
result = next;
}
});
}
} // namespace } // namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -352,6 +300,18 @@ void VPPiece::FlipHorizontally()
SetHorizontallyFlipped(!IsHorizontallyFlipped()); SetHorizontallyFlipped(!IsHorizontallyFlipped());
} }
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::HasInvalidPieceGapPosition() const -> bool
{
return m_invalidPieceGapPosition;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetHasInvalidPieceGapPosition(bool status)
{
m_invalidPieceGapPosition = status;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
{ {
@ -436,6 +396,58 @@ auto VPPiece::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QP
return false; return false;
} }
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
{
if (path.size() < 2)
{
return path;
}
QVector<QPointF> stickyPath;
for (int i = 0; i < path.size(); ++i)
{
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size() - 1 ? i + 1 : 0)));
}
return stickyPath;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
{
return QtConcurrent::blockingMappedReduced(
path1,
[path2](const QPointF &p1)
{
qreal minLocalDistance = std::numeric_limits<qreal>::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;
},
[](QLineF &result, const QLineF &next)
{
qreal const dist1 = result.length();
qreal const dist2 = next.length();
if (result.isNull() || dist2 < dist1)
{
result = next;
}
});
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto VPPiece::IsValid(QString &error) const -> bool auto VPPiece::IsValid(QString &error) const -> bool
{ {

View File

@ -110,9 +110,14 @@ public:
auto HasSuperpositionWithPieces() const -> bool; auto HasSuperpositionWithPieces() const -> bool;
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces); void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
auto HasInvalidPieceGapPosition() const -> bool;
void SetHasInvalidPieceGapPosition(bool status);
auto StickyPosition(qreal &dx, qreal &dy) const -> bool; auto StickyPosition(qreal &dx, qreal &dy) const -> bool;
static auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool; static auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool;
static auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>;
static auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF;
static void CleanPosition(const VPPiecePtr &piece); static void CleanPosition(const VPPiecePtr &piece);
auto IsValid(QString &error) const -> bool; auto IsValid(QString &error) const -> bool;
@ -134,6 +139,7 @@ private:
bool m_isSelected{false}; bool m_isSelected{false};
bool m_outOfBound{false}; bool m_outOfBound{false};
bool m_hasSuperpositionWithPieces{false}; bool m_hasSuperpositionWithPieces{false};
bool m_invalidPieceGapPosition{false};
quint16 m_copyNumber{1}; quint16 m_copyNumber{1};

View File

@ -164,6 +164,9 @@ void VPSheetSceneData::PrepareForExport()
m_pieceSuperpositionTmp = layout->LayoutSettings().GetWarningSuperpositionOfPieces(); m_pieceSuperpositionTmp = layout->LayoutSettings().GetWarningSuperpositionOfPieces();
layout->LayoutSettings().SetWarningSuperpositionOfPieces(false); layout->LayoutSettings().SetWarningSuperpositionOfPieces(false);
m_pieceGapePositionTmp = layout->LayoutSettings().GetWarningPieceGapePosition();
layout->LayoutSettings().SetWarningPieceGapePosition(false);
} }
RefreshLayout(); RefreshLayout();
@ -197,6 +200,7 @@ void VPSheetSceneData::CleanAfterExport()
layout->LayoutSettings().SetWarningPiecesOutOfBound(m_outOfBoundTmp); layout->LayoutSettings().SetWarningPiecesOutOfBound(m_outOfBoundTmp);
layout->LayoutSettings().SetWarningSuperpositionOfPieces(m_pieceSuperpositionTmp); layout->LayoutSettings().SetWarningSuperpositionOfPieces(m_pieceSuperpositionTmp);
layout->LayoutSettings().SetWarningPieceGapePosition(m_pieceGapePositionTmp);
} }
RefreshLayout(); RefreshLayout();
@ -552,6 +556,70 @@ void VPSheet::ValidateSuperpositionOfPieces() const
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePieceGapePosition() const
{
VPLayoutPtr const layout = GetLayout();
if (layout.isNull())
{
return;
}
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
if (pieceGap <= 0)
{
return;
}
QList<VPPiecePtr> const pieces = GetPieces();
for (const auto &piece : pieces)
{
if (piece.isNull())
{
continue;
}
const bool oldInvalidPieceGapPosition = piece->HasInvalidPieceGapPosition();
QVector<QPointF> path1;
CastTo(piece->GetMappedExternalContourPoints(), path1);
path1 = VPPiece::PrepareStickyPath(path1);
bool hasInvalidPieceGapPosition = false;
for (const auto &p : pieces)
{
if (p.isNull() || piece == p)
{
continue;
}
QVector<QPointF> 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::ValidatePieceOutOfBound(const VPPiecePtr &piece) const void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
{ {
@ -699,6 +767,11 @@ void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
{ {
ValidateSuperpositionOfPieces(); ValidateSuperpositionOfPieces();
} }
if (layout->LayoutSettings().GetWarningPieceGapePosition())
{
ValidatePieceGapePosition();
}
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -128,6 +128,7 @@ private:
bool m_outOfBoundTmp{false}; bool m_outOfBoundTmp{false};
bool m_pieceSuperpositionTmp{false}; bool m_pieceSuperpositionTmp{false};
bool m_pieceGapePositionTmp{false};
void ConnectPiece(VPGraphicsPiece *piece) const; void ConnectPiece(VPGraphicsPiece *piece) const;
}; };
@ -183,6 +184,7 @@ public:
void SetTrashSheet(bool newTrashSheet); void SetTrashSheet(bool newTrashSheet);
void ValidateSuperpositionOfPieces() const; void ValidateSuperpositionOfPieces() const;
void ValidatePieceGapePosition() const;
void ValidatePieceOutOfBound(const VPPiecePtr &piece) const; void ValidatePieceOutOfBound(const VPPiecePtr &piece) const;
void ValidatePiecesOutOfBound() const; void ValidatePiecesOutOfBound() const;

View File

@ -1164,7 +1164,13 @@ auto VPGraphicsPiece::PieceColor() const -> QColor
superposition = piece->HasSuperpositionWithPieces(); superposition = piece->HasSuperpositionWithPieces();
} }
if (outOfBound || superposition) bool pieceGape = false;
if (layout->LayoutSettings().GetWarningPieceGapePosition())
{
pieceGape = piece->HasInvalidPieceGapPosition();
}
if (outOfBound || superposition || pieceGape)
{ {
return VSceneStylesheet::ManualLayoutStyle().PieceErrorColor(); return VSceneStylesheet::ManualLayoutStyle().PieceErrorColor();
} }

View File

@ -1250,6 +1250,8 @@ void VPMainWindow::InitPropertyTabLayout()
connect(ui->checkBoxLayoutWarningPiecesSuperposition, &QCheckBox::toggled, this, connect(ui->checkBoxLayoutWarningPiecesSuperposition, &QCheckBox::toggled, this,
&VPMainWindow::LayoutWarningPiecesSuperposition_toggled); &VPMainWindow::LayoutWarningPiecesSuperposition_toggled);
connect(ui->checkBoxLayoutWarningPieceGapePosition, &QCheckBox::toggled, this,
&VPMainWindow::LayoutWarningPieceGapePosition_toggled);
connect(ui->checkBoxLayoutWarningPiecesOutOfBound, &QCheckBox::toggled, this, connect(ui->checkBoxLayoutWarningPiecesOutOfBound, &QCheckBox::toggled, this,
&VPMainWindow::LayoutWarningPiecesOutOfBound_toggled); &VPMainWindow::LayoutWarningPiecesOutOfBound_toggled);
connect(ui->checkBoxCutOnFold, &QCheckBox::toggled, this, &VPMainWindow::LayoutCutOnFold_toggled); connect(ui->checkBoxCutOnFold, &QCheckBox::toggled, this, &VPMainWindow::LayoutCutOnFold_toggled);
@ -1611,6 +1613,8 @@ void VPMainWindow::SetPropertyTabLayoutData()
m_layout->LayoutSettings().GetWarningPiecesOutOfBound()); m_layout->LayoutSettings().GetWarningPiecesOutOfBound());
SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition,
m_layout->LayoutSettings().GetWarningSuperpositionOfPieces()); m_layout->LayoutSettings().GetWarningSuperpositionOfPieces());
SetCheckBoxValue(ui->checkBoxLayoutWarningPieceGapePosition,
m_layout->LayoutSettings().GetWarningPieceGapePosition());
SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().IsStickyEdges()); SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().IsStickyEdges());
SetCheckBoxValue(ui->checkBoxFollowGainline, m_layout->LayoutSettings().GetFollowGrainline()); SetCheckBoxValue(ui->checkBoxFollowGainline, m_layout->LayoutSettings().GetFollowGrainline());
SetCheckBoxValue(ui->checkBoxTogetherWithNotches, m_layout->LayoutSettings().IsBoundaryTogetherWithNotches()); SetCheckBoxValue(ui->checkBoxTogetherWithNotches, m_layout->LayoutSettings().IsBoundaryTogetherWithNotches());
@ -2935,7 +2939,8 @@ auto VPMainWindow::DrawTilesScheme(QPrinter *printer, QPainter *painter, const V
auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
{ {
if (not m_layout->LayoutSettings().GetWarningPiecesOutOfBound() && if (not m_layout->LayoutSettings().GetWarningPiecesOutOfBound() &&
not m_layout->LayoutSettings().GetWarningSuperpositionOfPieces()) not m_layout->LayoutSettings().GetWarningSuperpositionOfPieces() &&
not m_layout->LayoutSettings().GetWarningPieceGapePosition())
{ {
return true; return true;
} }
@ -2944,6 +2949,7 @@ auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
{ {
bool outOfBoundChecked = false; bool outOfBoundChecked = false;
bool pieceSuperpositionChecked = false; bool pieceSuperpositionChecked = false;
bool pieceGapePositionChecked = false;
QList<VPPiecePtr> const pieces = sheet->GetPieces(); QList<VPPiecePtr> const pieces = sheet->GetPieces();
for (const auto &piece : pieces) for (const auto &piece : pieces)
@ -2957,6 +2963,11 @@ auto VPMainWindow::AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool
{ {
return false; return false;
} }
if (not CheckPieceGapePosition(piece, pieceGapePositionChecked))
{
return false;
}
} }
} }
@ -3023,6 +3034,37 @@ auto VPMainWindow::CheckSuperpositionOfPieces(const VPPiecePtr &piece, bool &pie
return true; return true;
} }
//---------------------------------------------------------------------------------------------------------------------
auto VPMainWindow::CheckPieceGapePosition(const VPPiecePtr &piece, bool &pieceGapePositionChecked) -> bool
{
if (m_layout->LayoutSettings().GetWarningPieceGapePosition())
{
if (not pieceGapePositionChecked && not piece.isNull() && piece->HasInvalidPieceGapPosition())
{
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Question);
msgBox.setWindowTitle(tr("The layout is invalid."));
msgBox.setText(tr("The layout is invalid. One or several pieces are closer than minimally allowed. Do you "
"want to continue export?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
const int width = 500;
auto *horizontalSpacer = new QSpacerItem(width, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
auto *layout = qobject_cast<QGridLayout *>(msgBox.layout());
SCASSERT(layout != nullptr)
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
if (msgBox.exec() == QMessageBox::No)
{
return false;
}
pieceGapePositionChecked = true; // no need to ask more
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets) void VPMainWindow::PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets)
{ {
@ -4826,6 +4868,25 @@ void VPMainWindow::VerticalScaleChanged(double value)
VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView);
} }
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::LayoutWarningPieceGapePosition_toggled(bool checked)
{
if (not m_layout.isNull())
{
m_layout->LayoutSettings().SetWarningPieceGapePosition(checked);
LayoutWasSaved(false);
if (checked)
{
VPSheetPtr const sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePieceGapePosition();
}
}
m_graphicsView->RefreshPieces();
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked) void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked)
{ {

View File

@ -293,6 +293,7 @@ private slots:
void HorizontalScaleChanged(double value); void HorizontalScaleChanged(double value);
void VerticalScaleChanged(double value); void VerticalScaleChanged(double value);
void LayoutWarningPieceGapePosition_toggled(bool checked);
void LayoutWarningPiecesSuperposition_toggled(bool checked); void LayoutWarningPiecesSuperposition_toggled(bool checked);
void LayoutWarningPiecesOutOfBound_toggled(bool checked); void LayoutWarningPiecesOutOfBound_toggled(bool checked);
void LayoutCutOnFold_toggled(bool checked); void LayoutCutOnFold_toggled(bool checked);
@ -506,6 +507,7 @@ private:
auto AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool; auto AskLayoutIsInvalid(const QList<VPSheetPtr> &sheets) -> bool;
auto CheckPiecesOutOfBound(const VPPiecePtr &piece, bool &outOfBoundChecked) -> bool; auto CheckPiecesOutOfBound(const VPPiecePtr &piece, bool &outOfBoundChecked) -> bool;
auto CheckSuperpositionOfPieces(const VPPiecePtr &piece, bool &pieceSuperpositionChecked) -> bool; auto CheckSuperpositionOfPieces(const VPPiecePtr &piece, bool &pieceSuperpositionChecked) -> bool;
auto CheckPieceGapePosition(const VPPiecePtr &piece, bool &pieceGapePositionChecked) -> bool;
void PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets); void PrintLayoutSheets(QPrinter *printer, const QList<VPSheetPtr> &sheets);
static auto PrintLayoutSheetPage(QPrinter *printer, QPainter &painter, const VPSheetPtr &sheet) -> bool; static auto PrintLayoutSheetPage(QPrinter *printer, QPainter &painter, const VPSheetPtr &sheet) -> bool;

View File

@ -1645,8 +1645,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>392</width> <width>378</width>
<height>700</height> <height>710</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_27"> <layout class="QVBoxLayout" name="verticalLayout_27">
@ -1720,6 +1720,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxLayoutWarningPieceGapePosition">
<property name="text">
<string>Warning piece gape position</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="checkBoxSheetStickyEdges"> <widget class="QCheckBox" name="checkBoxSheetStickyEdges">
<property name="text"> <property name="text">
@ -2434,8 +2441,8 @@
</resources> </resources>
<connections/> <connections/>
<buttongroups> <buttongroups>
<buttongroup name="buttonGroupTileOrientation"/>
<buttongroup name="buttonGroupRotationDirection"/> <buttongroup name="buttonGroupRotationDirection"/>
<buttongroup name="buttonGroupSheetOrientation"/> <buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupTileOrientation"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -63,6 +63,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutTileShowWatermark, ("layou
// NOLINTNEXTLINE // NOLINTNEXTLINE
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesSuperposition, Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesSuperposition,
("layout/warningPiecesSuperposition"_L1)) ("layout/warningPiecesSuperposition"_L1))
// NOLINTNEXTLINE
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPieceGapePosition, ("layout/warningPieceGapePosition"_L1))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutStickyEdges, ("layout/stickyEdges"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutStickyEdges, ("layout/stickyEdges"_L1)) // NOLINT
// NOLINTNEXTLINE // NOLINTNEXTLINE
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesOutOfBound, ("layout/warningPiecesOutOfBound"_L1)) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesOutOfBound, ("layout/warningPiecesOutOfBound"_L1))
@ -292,6 +294,18 @@ auto VPSettings::GetLayoutWarningPiecesSuperposition() const -> bool
return value(*settingLayoutWarningPiecesSuperposition, true).toBool(); return value(*settingLayoutWarningPiecesSuperposition, true).toBool();
} }
//---------------------------------------------------------------------------------------------------------------------
void VPSettings::SetLayoutWarningPieceGapePosition(bool value)
{
setValue(*settingLayoutWarningPieceGapePosition, value);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSettings::GetLayoutWarningPieceGapePosition() const -> bool
{
return value(*settingLayoutWarningPieceGapePosition, true).toBool();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPSettings::SetLayoutStickyEdges(bool value) void VPSettings::SetLayoutStickyEdges(bool value)
{ {

View File

@ -89,6 +89,9 @@ public:
void SetLayoutWarningPiecesSuperposition(bool value); void SetLayoutWarningPiecesSuperposition(bool value);
auto GetLayoutWarningPiecesSuperposition() const -> bool; auto GetLayoutWarningPiecesSuperposition() const -> bool;
void SetLayoutWarningPieceGapePosition(bool value);
auto GetLayoutWarningPieceGapePosition() const -> bool;
void SetLayoutStickyEdges(bool value); void SetLayoutStickyEdges(bool value);
auto GetLayoutStickyEdges() const -> bool; auto GetLayoutStickyEdges() const -> bool;

View File

@ -333,6 +333,7 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
QXmlStreamAttributes const attribs = attributes(); QXmlStreamAttributes const attribs = attributes();
layout->LayoutSettings().SetWarningSuperpositionOfPieces( layout->LayoutSettings().SetWarningSuperpositionOfPieces(
ReadAttributeBool(attribs, ML::AttrWarningSuperposition, trueStr)); ReadAttributeBool(attribs, ML::AttrWarningSuperposition, trueStr));
layout->LayoutSettings().SetWarningPieceGapePosition(ReadAttributeBool(attribs, ML::AttrWarningPieceGape, trueStr));
layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr)); layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr));
layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr)); layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr));
layout->LayoutSettings().SetPiecesGap(qMax(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')), 0.0)); layout->LayoutSettings().SetPiecesGap(qMax(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')), 0.0));

View File

@ -172,6 +172,7 @@ void VPLayoutFileWriter::WriteLayoutProperties(const VPLayoutPtr &layout)
writeStartElement(ML::TagControl); writeStartElement(ML::TagControl);
SetAttribute(ML::AttrWarningSuperposition, layout->LayoutSettings().GetWarningSuperpositionOfPieces()); SetAttribute(ML::AttrWarningSuperposition, layout->LayoutSettings().GetWarningSuperpositionOfPieces());
SetAttribute(ML::AttrWarningOutOfBound, layout->LayoutSettings().GetWarningPiecesOutOfBound()); SetAttribute(ML::AttrWarningOutOfBound, layout->LayoutSettings().GetWarningPiecesOutOfBound());
SetAttribute(ML::AttrWarningPieceGape, layout->LayoutSettings().GetWarningPieceGapePosition());
SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().IsStickyEdges()); SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().IsStickyEdges());
SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap()); SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap());
SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline()); SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline());

View File

@ -71,6 +71,7 @@ const QString TagMirrorLine = QStringLiteral("mirrorLine"); // NOLINT(ce
const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp) const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp)
const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp) const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp)
const QString AttrWarningPieceGape = QStringLiteral("warningPieceGape"); // NOLINT(cert-err58-cpp)
const QString AttrStickyEdges = QStringLiteral("stickyEdges"); // NOLINT(cert-err58-cpp) const QString AttrStickyEdges = QStringLiteral("stickyEdges"); // NOLINT(cert-err58-cpp)
const QString AttrPiecesGap = QStringLiteral("piecesGap"); // NOLINT(cert-err58-cpp) const QString AttrPiecesGap = QStringLiteral("piecesGap"); // NOLINT(cert-err58-cpp)
const QString AttrVisible = QStringLiteral("visible"); // NOLINT(cert-err58-cpp) const QString AttrVisible = QStringLiteral("visible"); // NOLINT(cert-err58-cpp)

View File

@ -70,6 +70,7 @@ extern const QString TagMirrorLine;
extern const QString AttrWarningSuperposition; extern const QString AttrWarningSuperposition;
extern const QString AttrWarningOutOfBound; extern const QString AttrWarningOutOfBound;
extern const QString AttrWarningPieceGape;
extern const QString AttrStickyEdges; extern const QString AttrStickyEdges;
extern const QString AttrPiecesGap; extern const QString AttrPiecesGap;
extern const QString AttrVisible; extern const QString AttrVisible;

View File

@ -12,6 +12,7 @@
<xs:complexType> <xs:complexType>
<xs:attribute type="xs:boolean" name="warningSuperposition"/> <xs:attribute type="xs:boolean" name="warningSuperposition"/>
<xs:attribute type="xs:boolean" name="warningOutOfBound"/> <xs:attribute type="xs:boolean" name="warningOutOfBound"/>
<xs:attribute type="xs:boolean" name="warningPieceGape"/>
<xs:attribute type="xs:boolean" name="stickyEdges"/> <xs:attribute type="xs:boolean" name="stickyEdges"/>
<xs:attribute type="xs:boolean" name="followGrainline"/> <xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:boolean" name="boundaryTogetherWithNotches"/> <xs:attribute type="xs:boolean" name="boundaryTogetherWithNotches"/>