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.
- Backport fix vulnerability CVE-2021-21900.
- Improved main path validations.
- New path validation Invalid segment.
# Valentina 0.7.49 July 1, 2021
- Fix crash.

View File

@ -64,17 +64,12 @@ namespace
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)
&& 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> secondPoint;
@ -85,6 +80,13 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
}
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;
}
@ -92,6 +94,7 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
if (firstPoint->getIdObject() != NULL_ID && secondPoint->getIdObject() != NULL_ID &&
firstPoint->getIdObject() == secondPoint->getIdObject())
{
error = QObject::tr("Point '%1' repeats twice").arg(firstPoint->name());
return true;
}
@ -101,39 +104,52 @@ auto DoublePoint(const VPieceNode &firstNode, const VPieceNode &secondNode, cons
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;
}
//---------------------------------------------------------------------------------------------------------------------
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)
&& secondNode.GetTypeTool() != Tool::NodePoint && not (secondNode.GetId() == NULL_ID))
{
// don't ignore the same curve twice
if (firstNode.GetId() == secondNode.GetId())
{
return true;
}
QSharedPointer<VGObject> curve1;
QSharedPointer<VGObject> curve2;
try
{
// The same curve, but different modeling objects
const QSharedPointer<VGObject> curve1 = data->GetGObject(firstNode.GetId());
const QSharedPointer<VGObject> curve2 = data->GetGObject(secondNode.GetId());
if (curve1->getIdObject() == curve2->getIdObject())
{
return true;
}
curve1 = data->GetGObject(firstNode.GetId());
curve2 = data->GetGObject(secondNode.GetId());
}
catch (const VExceptionBadId &)
{
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;
@ -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);
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 bottomNode = RowNode(listWidget, FindNotExcludedNodeUp(listWidget, listWidget->count()-1));
return DoublePoint(topNode, bottomNode, data);
return DoublePoint(topNode, bottomNode, data, error);
}
return false;
}
//---------------------------------------------------------------------------------------------------------------------
bool DoublePoints(QListWidget *listWidget, const VContainer *data)
bool DoublePoints(QListWidget *listWidget, const VContainer *data, QString &error)
{
SCASSERT(listWidget != nullptr);
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 secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1));
if (DoublePoint(firstNode, secondNode, data))
if (DoublePoint(firstNode, secondNode, data, error))
{
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);
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 secondNode = RowNode(listWidget, FindNotExcludedNodeDown(listWidget, firstIndex+1));
if (DoubleCurve(firstNode, secondNode, data))
if (DoubleCurve(firstNode, secondNode, data, error))
{
return true;
}
@ -659,3 +675,160 @@ QString GetNodeName(const VContainer *data, const VPieceNode &node, bool showPas
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);
int FindNotExcludedNodeDown(QListWidget *listWidget, int candidate);
int FindNotExcludedNodeUp(QListWidget *listWidget, int candidate);
bool FirstPointEqualLast(QListWidget *listWidget, const VContainer *data);
bool DoublePoints(QListWidget *listWidget, const VContainer *data);
bool DoubleCurves(QListWidget *listWidget, const VContainer *data);
int FindNotExcludedPointDown(QListWidget *listWidget, int start);
int FindNotExcludedCurveDown(QListWidget *listWidget, int start);
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 InvalidSegment(QListWidget *listWidget, const VContainer *data, QString &error);
QString DialogWarningIcon();
QFont NodeFont(QFont font, bool nodeExcluded = false);
void CurrentCurveLength(vidtype curveId, VContainer *data);

View File

@ -1631,22 +1631,27 @@ auto DialogPiecePath::PathIsValid() const -> bool
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() +
tr("First point of <b>custom seam allowance</b> cannot be equal to the last point!"));
ui->helpLabel->setText(
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;
}
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;
}
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;
}
@ -1669,6 +1674,13 @@ auto DialogPiecePath::PathIsValid() const -> bool
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!"));
return true;
}

View File

@ -2698,21 +2698,28 @@ auto DialogSeamAllowance::MainPathIsValid() const -> bool
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;
}
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;
}
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;
}
@ -2722,6 +2729,14 @@ auto DialogSeamAllowance::MainPathIsValid() const -> bool
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;
}