New path validation Invalid segment.

This commit is contained in:
Roman Telezhynskyi 2021-11-24 14:15:21 +02:00
parent cd23cec411
commit cb036e8d43
5 changed files with 248 additions and 44 deletions

View file

@ -26,6 +26,7 @@
- Improve for a search bar. - Improve for a search bar.
- Backport fix vulnerability CVE-2021-21900. - Backport fix vulnerability CVE-2021-21900.
- Improved main path validations. - Improved main path validations.
- New path validation Invalid segment.
# Valentina 0.7.49 July 1, 2021 # Valentina 0.7.49 July 1, 2021
- Fix crash. - Fix crash.

View file

@ -64,17 +64,12 @@ namespace
const int dialogMaxFormulaHeight = 80; const int dialogMaxFormulaHeight = 80;
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, const VContainer *data) -> bool auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, const VContainer *data,
QString &error) -> bool
{ {
if (firstNode.GetTypeTool() == Tool::NodePoint && not (firstNode.GetId() == NULL_ID) if (firstNode.GetTypeTool() == Tool::NodePoint && not (firstNode.GetId() == NULL_ID)
&& secondNode.GetTypeTool() == Tool::NodePoint && not (secondNode.GetId() == NULL_ID)) && secondNode.GetTypeTool() == Tool::NodePoint && not (secondNode.GetId() == NULL_ID))
{ {
// don't ignore the same point twice
if (firstNode.GetId() == secondNode.GetId())
{
return true;
}
QSharedPointer<VPointF> firstPoint; QSharedPointer<VPointF> firstPoint;
QSharedPointer<VPointF> secondPoint; QSharedPointer<VPointF> secondPoint;
@ -85,6 +80,13 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
} }
catch(const VExceptionBadId &) catch(const VExceptionBadId &)
{ {
return false;
}
// don't ignore the same point twice
if (firstNode.GetId() == secondNode.GetId())
{
error = QObject::tr("Point '%1' repeats twice").arg(firstPoint->name());
return true; return true;
} }
@ -92,6 +94,7 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
if (firstPoint->getIdObject() != NULL_ID && secondPoint->getIdObject() != NULL_ID && if (firstPoint->getIdObject() != NULL_ID && secondPoint->getIdObject() != NULL_ID &&
firstPoint->getIdObject() == secondPoint->getIdObject()) firstPoint->getIdObject() == secondPoint->getIdObject())
{ {
error = QObject::tr("Point '%1' repeats twice").arg(firstPoint->name());
return true; return true;
} }
@ -101,39 +104,52 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
return false; return false;
} }
return firstPoint->toQPointF() == secondPoint->toQPointF(); bool sameCoordinates = VFuzzyComparePoints(firstPoint->toQPointF(), secondPoint->toQPointF());
if (sameCoordinates)
{
error = QObject::tr("Points '%1' and '%2' have the same coordinates.")
.arg(firstPoint->name(), secondPoint->name());
}
return sameCoordinates;
} }
return false; return false;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto DoubleCurve(const VPieceNode &firstNode, const VPieceNode &secondNode, const VContainer *data) -> bool auto DoubleCurve(const VPieceNode &firstNode, const VPieceNode &secondNode, const VContainer *data,
QString &error) -> bool
{ {
if (firstNode.GetTypeTool() != Tool::NodePoint && not (firstNode.GetId() == NULL_ID) if (firstNode.GetTypeTool() != Tool::NodePoint && not (firstNode.GetId() == NULL_ID)
&& secondNode.GetTypeTool() != Tool::NodePoint && not (secondNode.GetId() == NULL_ID)) && secondNode.GetTypeTool() != Tool::NodePoint && not (secondNode.GetId() == NULL_ID))
{ {
// don't ignore the same curve twice QSharedPointer<VGObject> curve1;
if (firstNode.GetId() == secondNode.GetId()) QSharedPointer<VGObject> curve2;
{
return true;
}
try try
{ {
// The same curve, but different modeling objects curve1 = data->GetGObject(firstNode.GetId());
const QSharedPointer<VGObject> curve1 = data->GetGObject(firstNode.GetId()); curve2 = data->GetGObject(secondNode.GetId());
const QSharedPointer<VGObject> curve2 = data->GetGObject(secondNode.GetId());
if (curve1->getIdObject() == curve2->getIdObject())
{
return true;
}
} }
catch (const VExceptionBadId &) catch (const VExceptionBadId &)
{ {
return false; return false;
} }
// don't ignore the same curve twice
if (firstNode.GetId() == secondNode.GetId())
{
error = QObject::tr("Leave only one copy of curve '%1'").arg(curve1->name());
return true;
}
// The same curve, but different modeling objects
if (curve1->getIdObject() == curve2->getIdObject())
{
error = QObject::tr("Leave only one copy of curve '%1'").arg(curve1->name());
return true;
}
} }
return false; return false;
@ -422,7 +438,7 @@ int FindNotExcludedNodeUp(QListWidget *listWidget, int candidate)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data) bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data, QString &error)
{ {
SCASSERT(listWidget != nullptr); SCASSERT(listWidget != nullptr);
if (listWidget->count() > 1) if (listWidget->count() > 1)
@ -430,13 +446,13 @@ bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data)
const VPieceNode topNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, 0)); const VPieceNode topNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, 0));
const VPieceNode bottomNode = RowNode(listWidget, FindNotExcludedNodeUp(listWidget, listWidget->count()-1)); const VPieceNode bottomNode = RowNode(listWidget, FindNotExcludedNodeUp(listWidget, listWidget->count()-1));
return DoublePoint(topNode, bottomNode, data); return DoublePoint(topNode, bottomNode, data, error);
} }
return false; return false;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool DoublePoints(QListWidget *listWidget, const VContainer *data) bool DoublePoints(QListWidget *listWidget, const VContainer *data, QString &error)
{ {
SCASSERT(listWidget != nullptr); SCASSERT(listWidget != nullptr);
for (int i=0, sz = listWidget->count()-1; i<sz; ++i) for (int i=0, sz = listWidget->count()-1; i<sz; ++i)
@ -445,7 +461,7 @@ bool DoublePoints(QListWidget *listWidget, const VContainer *data)
const VPieceNode firstNode = RowNode(listWidget, firstIndex); const VPieceNode firstNode = RowNode(listWidget, firstIndex);
const VPieceNode secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1)); const VPieceNode secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1));
if (DoublePoint(firstNode, secondNode, data)) if (DoublePoint(firstNode, secondNode, data, error))
{ {
return true; return true;
} }
@ -454,7 +470,7 @@ bool DoublePoints(QListWidget *listWidget, const VContainer *data)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto DoubleCurves(QListWidget *listWidget, const VContainer *data) -> bool auto DoubleCurves(QListWidget *listWidget, const VContainer *data, QString &error) -> bool
{ {
SCASSERT(listWidget != nullptr); SCASSERT(listWidget != nullptr);
for (int i=0, sz = listWidget->count()-1; i<sz; ++i) for (int i=0, sz = listWidget->count()-1; i<sz; ++i)
@ -463,7 +479,7 @@ auto DoubleCurves(QListWidget *listWidget, const VContainer *data) -> bool
const VPieceNode firstNode = RowNode(listWidget, firstIndex); const VPieceNode firstNode = RowNode(listWidget, firstIndex);
const VPieceNode secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1)); const VPieceNode secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1));
if (DoubleCurve(firstNode, secondNode, data)) if (DoubleCurve(firstNode, secondNode, data, error))
{ {
return true; return true;
} }
@ -659,3 +675,160 @@ QString GetNodeName(const VContainer *data, const VPieceNode &node, bool showPas
return name; return name;
} }
//---------------------------------------------------------------------------------------------------------------------
auto FindNotExcludedPointDown(QListWidget *listWidget, int start) -> int
{
SCASSERT(listWidget != nullptr);
int index = -1;
if (start < 0 || start >= listWidget->count())
{
return index;
}
int i = start;
int count = 0;
do
{
const QListWidgetItem *rowItem = listWidget->item(i);
SCASSERT(rowItem != nullptr);
auto rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
if (not rowNode.IsExcluded() && rowNode.GetTypeTool() == Tool::NodePoint && rowNode.GetId() != NULL_ID)
{
index = i;
break;
}
++i;
if (i >= listWidget->count())
{
i = 0;
}
++count;
}
while (count < listWidget->count());
return index;
}
//---------------------------------------------------------------------------------------------------------------------
auto FindNotExcludedCurveDown(QListWidget *listWidget, int start) -> int
{
SCASSERT(listWidget != nullptr);
int index = -1;
if (start < 0 || start >= listWidget->count())
{
return index;
}
int i = start;
int count = 0;
do
{
const QListWidgetItem *rowItem = listWidget->item(i);
SCASSERT(rowItem != nullptr);
auto rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
if (not rowNode.IsExcluded() && rowNode.GetTypeTool() != Tool::NodePoint && rowNode.GetId() != NULL_ID)
{
index = i;
break;
}
++i;
if (i >= listWidget->count())
{
i = 0;
}
++count;
}
while (count < listWidget->count());
return index;
}
//---------------------------------------------------------------------------------------------------------------------
auto InvalidSegment(QListWidget *listWidget, const VContainer *data, QString &error) -> bool
{
SCASSERT(listWidget != nullptr);
for (int index=0; index < listWidget->count(); ++index)
{
int firstCurveIndex = -1;
int pointIndex = -1;
int secondCurveIndex = -1;
auto FindPair = [listWidget, &firstCurveIndex, &pointIndex, &secondCurveIndex]( int start)
{
for (int i=start; i < listWidget->count(); ++i)
{
firstCurveIndex = FindNotExcludedCurveDown(listWidget, i);
if (firstCurveIndex == -1)
{
continue;
}
pointIndex = FindNotExcludedPointDown(listWidget, firstCurveIndex+1);
if (pointIndex == -1)
{
continue;
}
secondCurveIndex = FindNotExcludedCurveDown(listWidget, pointIndex+1);
if (secondCurveIndex == -1 || firstCurveIndex == secondCurveIndex)
{
continue;
}
return true;
}
return false;
};
if (not FindPair(index))
{
continue;
}
const VPieceNode firstCurveNode = RowNode(listWidget, firstCurveIndex);
const VPieceNode secondCurveNode = RowNode(listWidget, secondCurveIndex);
QString errorDoubleCurve;
if (not DoubleCurve(firstCurveNode, secondCurveNode, data, errorDoubleCurve))
{
continue;
}
const VPieceNode pointNode = RowNode(listWidget, pointIndex);
if (pointNode.GetId() == NULL_ID)
{
continue;
}
try
{
const QSharedPointer<VAbstractCurve> curve1 = data->GeometricObject<VAbstractCurve>(firstCurveNode.GetId());
const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(pointNode.GetId());
error = QObject::tr("Point '%1' does not lie on a curve '%2'").arg(point->name(), curve1->name());
bool validSegment = curve1->IsPointOnCurve(point->toQPointF());
if (not validSegment)
{
return true;
}
}
catch (const VExceptionBadId &)
{
continue;
}
}
return false;
}

View file

@ -80,10 +80,13 @@ void CheckPointLabel(QDialog *dialog, QLineEdit* edit, QLabel *labelEditNamePo
const VContainer *data, bool &flag); const VContainer *data, bool &flag);
int FindNotExcludedNodeDown(QListWidget *listWidget, int candidate); int FindNotExcludedNodeDown(QListWidget *listWidget, int candidate);
int FindNotExcludedNodeUp(QListWidget *listWidget, int candidate); int FindNotExcludedNodeUp(QListWidget *listWidget, int candidate);
bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data); int FindNotExcludedPointDown(QListWidget *listWidget, int start);
bool DoublePoints(QListWidget *listWidget, const VContainer *data); int FindNotExcludedCurveDown(QListWidget *listWidget, int start);
bool DoubleCurves(QListWidget *listWidget, const VContainer *data); bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data, QString &error);
bool DoublePoints(QListWidget *listWidget, const VContainer *data, QString &error);
bool DoubleCurves(QListWidget *listWidget, const VContainer *data, QString &error);
bool EachPointLabelIsUnique(QListWidget *listWidget); bool EachPointLabelIsUnique(QListWidget *listWidget);
bool InvalidSegment(QListWidget *listWidget, const VContainer *data, QString &error);
QString DialogWarningIcon(); QString DialogWarningIcon();
QFont NodeFont(QFont font, bool nodeExcluded = false); QFont NodeFont(QFont font, bool nodeExcluded = false);
void CurrentCurveLength(vidtype curveId, VContainer *data); void CurrentCurveLength(vidtype curveId, VContainer *data);

View file

@ -1631,22 +1631,27 @@ auto DialogPiecePath::PathIsValid() const -> bool
return false; return false;
} }
if (GetType() == PiecePathType::CustomSeamAllowance && FirstPointEqualLast(ui->listWidget, data)) QString error;
if (GetType() == PiecePathType::CustomSeamAllowance && FirstPointEqualLast(ui->listWidget, data, error))
{ {
ui->helpLabel->setText(DialogWarningIcon() + ui->helpLabel->setText(
tr("First point of <b>custom seam allowance</b> cannot be equal to the last point!")); QString("%1%2 %3")
.arg(DialogWarningIcon(),
tr("First point of <b>custom seam allowance</b> cannot be equal to the last point!"), error));
return false; return false;
} }
if (DoublePoints(ui->listWidget, data)) error.clear();
if (DoublePoints(ui->listWidget, data, error))
{ {
ui->helpLabel->setText(DialogWarningIcon() + tr("You have double points!")); ui->helpLabel->setText(QString("%1%2 %3").arg(DialogWarningIcon(), tr("You have double points!"), error));
return false; return false;
} }
if (DoubleCurves(ui->listWidget, data)) error.clear();
if (DoubleCurves(ui->listWidget, data, error))
{ {
ui->helpLabel->setText(DialogWarningIcon() + tr("The same curve repeats twice!")); ui->helpLabel->setText(QString("%1%2 %3").arg(DialogWarningIcon(), tr("The same curve repeats twice!"), error));
return false; return false;
} }
@ -1669,6 +1674,13 @@ auto DialogPiecePath::PathIsValid() const -> bool
return false; return false;
} }
error.clear();
if (InvalidSegment(ui->listWidget, data, error))
{
ui->helpLabel->setText(QString("%1%2 %3").arg(DialogWarningIcon(), tr("Invalid segment!"), error));
return false;
}
ui->helpLabel->setText(tr("Ready!")); ui->helpLabel->setText(tr("Ready!"));
return true; return true;
} }

View file

@ -2698,21 +2698,28 @@ auto DialogSeamAllowance::MainPathIsValid() const -> bool
return false; return false;
} }
if (FirstPointEqualLast(uiTabPaths->listWidgetMainPath, data)) QString error;
if (FirstPointEqualLast(uiTabPaths->listWidgetMainPath, data, error))
{ {
uiTabPaths->helpLabel->setText(DialogWarningIcon() + tr("First point cannot be equal to the last point!")); uiTabPaths->helpLabel->setText(
QString("%1%2 %3").arg(DialogWarningIcon(),
tr("First point cannot be equal to the last point!"), error));
return false; return false;
} }
if (DoublePoints(uiTabPaths->listWidgetMainPath, data)) error.clear();
if (DoublePoints(uiTabPaths->listWidgetMainPath, data, error))
{ {
uiTabPaths->helpLabel->setText(DialogWarningIcon() + tr("You have double points!")); uiTabPaths->helpLabel->setText(QString("%1%2 %3")
.arg(DialogWarningIcon(), tr("You have double points!"), error));
return false; return false;
} }
if (DoubleCurves(uiTabPaths->listWidgetMainPath, data)) error.clear();
if (DoubleCurves(uiTabPaths->listWidgetMainPath, data, error))
{ {
uiTabPaths->helpLabel->setText(DialogWarningIcon() + tr("The same curve repeats twice!")); uiTabPaths->helpLabel->setText(QString("%1%2 %3")
.arg(DialogWarningIcon(), tr("The same curve repeats twice!"), error));
return false; return false;
} }
@ -2722,6 +2729,14 @@ auto DialogSeamAllowance::MainPathIsValid() const -> bool
return false; return false;
} }
error.clear();
if (InvalidSegment(uiTabPaths->listWidgetMainPath, data, error))
{
uiTabPaths->helpLabel->setText(QString("%1%2 %3")
.arg(DialogWarningIcon(), tr("Invalid segment!"), error));
return false;
}
return true; return true;
} }