Improve handling four ways grainlines.

This commit is contained in:
Roman Telezhynskyi 2023-05-02 17:38:02 +03:00
parent 894e2dffac
commit 1311c794c3
34 changed files with 2040 additions and 707 deletions

View File

@ -29,11 +29,13 @@
#include <QtMath>
#include "vpsheet.h"
#include "vplayout.h"
#include "../vlayout/vtextmanager.h"
#include "../vlayout/vlayoutpiecepath.h"
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vlayout/vlayoutpiecepath.h"
#include "../vlayout/vtextmanager.h"
#include "qline.h"
#include "vpiecegrainline.h"
#include "vplayout.h"
#include "vpsheet.h"
#include <QIcon>
#include <QLoggingCategory>
@ -154,12 +156,7 @@ void VPPiece::Update(const VPPiecePtr &piece)
SetInternalPaths(piece->GetInternalPaths());
SetPassmarks(piece->GetPassmarks());
SetPlaceLabels(piece->GetPlaceLabels());
SetGrainlineEnabled(piece->IsGrainlineEnabled());
SetGrainlineAngle(piece->GrainlineAngle());
SetGrainlineArrowType(piece->GrainlineArrowType());
SetGrainlinePoints(piece->GetGrainline());
SetGrainline(piece->GetGrainline());
SetPieceLabelRect(piece->GetPieceLabelRect());
SetPieceLabelData(piece->GetPieceLabelData());
SetPatternLabelRect(piece->GetPatternLabelRect());
@ -225,112 +222,62 @@ void VPPiece::RotateToGrainline(const VPTransformationOrigon &origin)
return;
}
const QVector<QPointF> grainlinePoints = GetMappedGrainline();
if (grainlinePoints.count() < 2)
const QLineF grainline = GetMappedGrainlineMainLine();
if (grainline.isNull())
{
return;
}
QLineF grainline(ConstFirst(grainlinePoints), ConstLast(grainlinePoints));
QLineF canonical(ConstFirst(grainlinePoints).x(), ConstFirst(grainlinePoints).y(),
ConstFirst(grainlinePoints).x()+100, ConstFirst(grainlinePoints).y());
GrainlineType grainlineType = sheet->GrainlineOrientation();
auto DegreesAtFront = [grainline, canonical, grainlineType]()
QLineF fabricGrainline(grainline.p1().x(), grainline.p1().y(), grainline.p1().x() + 100, grainline.p1().y());
if (sheet->GrainlineOrientation() == GrainlineType::Vertical)
{
QLineF atFront = canonical;
if (grainlineType == GrainlineType::Vertical)
{
atFront.setAngle(90);
}
fabricGrainline.setAngle(fabricGrainline.angle() - 90);
}
qreal angleTo = grainline.angleTo(atFront);
return angleTo;
};
QVector<qreal> angles;
angles.reserve(4);
auto DegreesAtRear = [grainline, canonical, grainlineType]()
const VPieceGrainline pieceGrainline = GetGrainline();
if (pieceGrainline.IsArrowUpEnabled())
{
QLineF atRear = canonical;
atRear.setAngle(grainlineType == GrainlineType::Vertical ? 270 : 180);
angles.append(grainline.angleTo(fabricGrainline));
}
qreal angleTo = grainline.angleTo(atRear);
return angleTo;
};
if (pieceGrainline.IsArrowDownEnabled())
{
QLineF arrow = grainline;
arrow.setAngle(arrow.angle() + 180);
angles.append(arrow.angleTo(fabricGrainline));
}
if (pieceGrainline.IsArrowLeftEnabled())
{
QLineF arrow = grainline;
arrow.setAngle(arrow.angle() + 90);
angles.append(arrow.angleTo(fabricGrainline));
}
if (pieceGrainline.IsArrowRightEnabled())
{
QLineF arrow = grainline;
arrow.setAngle(arrow.angle() - 90);
angles.append(arrow.angleTo(fabricGrainline));
}
GrainlineArrowDirection type = GrainlineArrowType();
qreal degrees = 0;
if (type == GrainlineArrowDirection::atFront)
if (not angles.isEmpty())
{
degrees = DegreesAtFront();
}
else if (type == GrainlineArrowDirection::atRear)
{
degrees = DegreesAtRear();
}
else if (type == GrainlineArrowDirection::atBoth)
{
const qreal atFront = DegreesAtFront();
if (atFront <= 90 || atFront >= 270)
{
degrees = atFront;
}
else
{
degrees = DegreesAtRear();
}
}
else
{
const qreal atFront = DegreesAtFront();
if (atFront <= 45)
{
degrees = atFront;
}
else if (atFront > 45 && atFront < 90)
{
degrees = atFront - 90;
}
else
{
degrees = atFront - 90 * qFloor(atFront / 90);
}
degrees = *std::min_element(angles.constBegin(), angles.constEnd());
}
if (origin.custom)
{
Rotate(MappedDetailBoundingRect().center(), degrees);
}
else
{
Rotate(origin.origin, degrees);
}
Rotate(origin.custom ? MappedDetailBoundingRect().center() : origin.origin, degrees);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineEnabled(bool enabled)
void VPPiece::SetGrainline(const VPieceGrainline &grainline)
{
VLayoutPiece::SetGrainlineEnabled(enabled);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineAngle(qreal angle)
{
VLayoutPiece::SetGrainlineAngle(angle);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineArrowType(GrainlineArrowDirection type)
{
VLayoutPiece::SetGrainlineArrowType(type);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlinePoints(const QVector<QPointF> &points)
{
VLayoutPiece::SetGrainlinePoints(points);
VLayoutPiece::SetGrainline(grainline);
}
//---------------------------------------------------------------------------------------------------------------------
@ -528,7 +475,7 @@ auto VPPiece::IsValid(QString &error) const -> bool
return false;
}
if (IsGrainlineEnabled() && GetGrainline().isEmpty())
if (IsGrainlineEnabled() && not GetGrainline().IsShapeValid())
{
error = tr("Grainline is empty");
return false;

View File

@ -35,6 +35,7 @@
#include "../vlayout/vlayoutpiece.h"
#include "../layout/layoutdef.h"
#include "vpiecegrainline.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
#include "../vmisc/defglobal.h"
@ -92,10 +93,7 @@ public:
auto Layout() const -> VPLayoutPtr;
void SetLayout(const VPLayoutPtr &layout);
void SetGrainlineEnabled(bool enabled);
void SetGrainlineAngle(qreal angle);
void SetGrainlineArrowType(GrainlineArrowDirection type);
void SetGrainlinePoints(const QVector<QPointF> &points);
void SetGrainline(const VPieceGrainline &grainline);
auto GetPieceLabelRect() const -> QVector<QPointF>;
void SetPieceLabelRect(const QVector<QPointF> &rect);

View File

@ -54,6 +54,7 @@
#include "undocommands/vpundopiecemove.h"
#include "undocommands/vpundomovepieceonsheet.h"
#include "vpiecegrainline.h"
#include <QLoggingCategory>
@ -465,19 +466,8 @@ void VPGraphicsPiece::InitGrainlineItem()
if(piece->IsGrainlineEnabled())
{
QPainterPath grainline;
QVector<QPointF> grainLinepoints = piece->GetMappedGrainline();
if(!grainLinepoints.isEmpty())
{
grainline.moveTo(ConstFirst(grainLinepoints));
for (int i = 1; i < grainLinepoints.size(); i++)
{
grainline.lineTo(grainLinepoints.at(i));
}
}
m_grainlineItem = new VGraphicsFillItem(this);
m_grainlineItem->setPath(grainline);
m_grainlineItem->setPath(VLayoutPiece::GrainlinePath(piece->GetMappedGrainlineShape()));
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
QPen pen(PieceColor(), settings->GetLayoutLineWidth(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);

View File

@ -30,6 +30,7 @@
#include <QFont>
#include <QXmlStreamAttributes>
#include <ciso646>
#include "vpiecegrainline.h"
#include "vplayoutfilereader.h"
#include "vplayoutliterals.h"
#include "../layout/vpsheet.h"
@ -109,29 +110,60 @@ auto StringToPath(const QString &path) -> QVector<QPointF>
//---------------------------------------------------------------------------------------------------------------------
auto StringToGrainlineArrowDirrection(const QString &dirrection) -> GrainlineArrowDirection
{
const QStringList arrows
{
ML::atFrontStr, // 0
ML::atRearStr, // 1
ML::atFourWayStr, // 2
ML::atBothStr // 3
const QStringList arrows{
ML::twoWaysUpDownStr, // 0
ML::oneWayUpStr, // 1
ML::oneWayDownStr, // 2
ML::fourWaysStr, // 3
ML::twoWaysUpLeftStr, // 4
ML::twoWaysUpRightStr, // 5
ML::twoWaysDownLeftStr, // 6
ML::twoWaysDownRightStr, // 7
ML::threeWaysUpDownLeftStr, // 8
ML::threeWaysUpDownRightStr, // 9
ML::threeWaysUpLeftRightStr, // 10
ML::threeWaysDownLeftRightStr, // 11
};
GrainlineArrowDirection arrowDirection = GrainlineArrowDirection::atBoth;
GrainlineArrowDirection arrowDirection = GrainlineArrowDirection::twoWaysUpDown;
switch (arrows.indexOf(dirrection))
{
case 0:// at front
arrowDirection = GrainlineArrowDirection::atFront;
case 1: // oneWayUp
arrowDirection = GrainlineArrowDirection::oneWayUp;
break;
case 1:// at rear
arrowDirection = GrainlineArrowDirection::atRear;
case 2: // oneWayDown
arrowDirection = GrainlineArrowDirection::oneWayDown;
break;
case 2:// at four way
arrowDirection = GrainlineArrowDirection::atFourWay;
case 3: // fourWays
arrowDirection = GrainlineArrowDirection::fourWays;
break;
case 3:// at both
case 4: // twoWaysUpLeft
arrowDirection = GrainlineArrowDirection::twoWaysUpLeft;
break;
case 5: // twoWaysUpRight
arrowDirection = GrainlineArrowDirection::twoWaysUpRight;
break;
case 6: // twoWaysDownLeft
arrowDirection = GrainlineArrowDirection::twoWaysDownLeft;
break;
case 7: // twoWaysDownRight
arrowDirection = GrainlineArrowDirection::twoWaysDownRight;
break;
case 8: // threeWaysUpDownLeft
arrowDirection = GrainlineArrowDirection::threeWaysUpDownLeft;
break;
case 9: // threeWaysUpDownRight
arrowDirection = GrainlineArrowDirection::threeWaysUpDownRight;
break;
case 10: // threeWaysUpLeftRight
arrowDirection = GrainlineArrowDirection::threeWaysUpLeftRight;
break;
case 11: // threeWaysDownLeftRight
arrowDirection = GrainlineArrowDirection::threeWaysDownLeftRight;
break;
case 0: // twoWaysUpDown
default:
arrowDirection = GrainlineArrowDirection::atBoth;
arrowDirection = GrainlineArrowDirection::twoWaysUpDown;
break;
}
return arrowDirection;
@ -600,23 +632,26 @@ void VPLayoutFileReader::ReadGrainline(const VPPiecePtr &piece)
{
AssertRootTag(ML::TagGrainline);
VPieceGrainline grainline;
QXmlStreamAttributes attribs = attributes();
bool enabled = ReadAttributeBool(attribs, ML::AttrEnabled, falseStr);
piece->SetGrainlineEnabled(enabled);
QVector<QPointF> path = StringToPath(readElementText());
grainline.SetEnabled(enabled);
QLineF mainLine = StringToLine(readElementText());
if (enabled)
{
piece->SetGrainlineAngle(ReadAttributeDouble(attribs, ML::AttrAngle, QChar('0')));
QString arrowDirection = ReadAttributeEmptyString(attribs, ML::AttrArrowDirection);
piece->SetGrainlineArrowType(StringToGrainlineArrowDirrection(arrowDirection));
grainline.SetArrowType(StringToGrainlineArrowDirrection(arrowDirection));
if (path.isEmpty())
if (mainLine.isNull())
{
throw VException(tr("Error in line %1. Grainline is empty.").arg(lineNumber()));
throw VException(tr("Error in line %1. Grainline main line is empty.").arg(lineNumber()));
}
piece->SetGrainlinePoints(path);
grainline.SetMainLine(mainLine);
}
piece->SetGrainline(grainline);
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -115,17 +115,33 @@ auto LinesToString(const QVector<QLineF> &lines) -> QString
//---------------------------------------------------------------------------------------------------------------------
auto GrainlineArrowDirrectionToString(GrainlineArrowDirection type) -> QString
{
switch(type)
switch (type)
{
case GrainlineArrowDirection::atFront:
return ML::atFrontStr;
case GrainlineArrowDirection::atRear:
return ML::atRearStr;
case GrainlineArrowDirection::atFourWay:
return ML::atFourWayStr;
case GrainlineArrowDirection::atBoth:
case GrainlineArrowDirection::oneWayUp:
return ML::oneWayUpStr;
case GrainlineArrowDirection::oneWayDown:
return ML::oneWayDownStr;
case GrainlineArrowDirection::fourWays:
return ML::fourWaysStr;
case GrainlineArrowDirection::twoWaysUpLeft:
return ML::twoWaysUpLeftStr;
case GrainlineArrowDirection::twoWaysUpRight:
return ML::twoWaysUpRightStr;
case GrainlineArrowDirection::twoWaysDownLeft:
return ML::twoWaysDownLeftStr;
case GrainlineArrowDirection::twoWaysDownRight:
return ML::twoWaysDownRightStr;
case GrainlineArrowDirection::threeWaysUpDownLeft:
return ML::threeWaysUpDownLeftStr;
case GrainlineArrowDirection::threeWaysUpDownRight:
return ML::threeWaysUpDownRightStr;
case GrainlineArrowDirection::threeWaysUpLeftRight:
return ML::threeWaysUpLeftRightStr;
case GrainlineArrowDirection::threeWaysDownLeftRight:
return ML::threeWaysDownLeftRightStr;
case GrainlineArrowDirection::twoWaysUpDown:
default:
return ML::atBothStr;
return ML::twoWaysUpDownStr;
}
}
} // namespace
@ -304,9 +320,8 @@ void VPLayoutFileWriter::WritePiece(const VPPiecePtr &piece)
[](bool enabled) noexcept {return not enabled;});
if (piece->IsGrainlineEnabled())
{
SetAttribute(ML::AttrAngle, piece->GrainlineAngle());
SetAttribute(ML::AttrArrowDirection, GrainlineArrowDirrectionToString(piece->GrainlineArrowType()));
writeCharacters(PathToString(piece->GetGrainline()));
SetAttribute(ML::AttrArrowDirection, GrainlineArrowDirrectionToString(piece->GetGrainline().GetArrowType()));
writeCharacters(LineToString(piece->GetGrainlineMainLine()));
}
writeEndElement();

View File

@ -51,6 +51,7 @@ class VLayoutPoint;
class VPLayoutFileWriter : public QXmlStreamWriter
{
Q_DECLARE_TR_FUNCTIONS(VPLayoutFileWriter) // NOLINT
public:
VPLayoutFileWriter()= default;
~VPLayoutFileWriter()= default;

View File

@ -85,7 +85,6 @@ const QString AttrTransform = QStringLiteral("transform"); // NOLINT(
const QString AttrShowSeamline = QStringLiteral("showSeamline"); // NOLINT(cert-err58-cpp)
const QString AttrEnabled = QStringLiteral("enabled"); // NOLINT(cert-err58-cpp)
const QString AttrBuiltIn = QStringLiteral("builtIn"); // NOLINT(cert-err58-cpp)
const QString AttrAngle = QStringLiteral("angle"); // NOLINT(cert-err58-cpp)
const QString AttrArrowDirection = QStringLiteral("arrowDirection"); // NOLINT(cert-err58-cpp)
const QString AttrType = QStringLiteral("type"); // NOLINT(cert-err58-cpp)
const QString AttrBaseLine = QStringLiteral("baseLine"); // NOLINT(cert-err58-cpp)
@ -115,12 +114,20 @@ const QString AttrY = QStringLiteral("y"); // NOLINT(cert-err
const QString AttrTurnPoint = QStringLiteral("turnPoint"); // NOLINT(cert-err58-cpp)
const QString AttrCurvePoint = QStringLiteral("curvePoint"); // NOLINT(cert-err58-cpp)
const QString atFrontStr = QStringLiteral("atFront"); // NOLINT(cert-err58-cpp)
const QString atRearStr = QStringLiteral("atRear"); // NOLINT(cert-err58-cpp)
const QString atFourWayStr = QStringLiteral("atFourWay"); // NOLINT(cert-err58-cpp)
const QString atBothStr = QStringLiteral("atBoth"); // NOLINT(cert-err58-cpp)
const QString oneWayUpStr = QStringLiteral("oneWayUp"); // NOLINT(cert-err58-cpp)
const QString oneWayDownStr = QStringLiteral("oneWayDown"); // NOLINT(cert-err58-cpp)
const QString fourWaysStr = QStringLiteral("fourWays"); // NOLINT(cert-err58-cpp)
const QString twoWaysUpDownStr = QStringLiteral("twoWaysUpDown"); // NOLINT(cert-err58-cpp)
const QString twoWaysUpLeftStr = QStringLiteral("twoWaysUpLeft"); // NOLINT(cert-err58-cpp)
const QString twoWaysUpRightStr = QStringLiteral("twoWaysUpRight"); // NOLINT(cert-err58-cpp)
const QString twoWaysDownLeftStr = QStringLiteral("twoWaysDownLeft"); // NOLINT(cert-err58-cpp)
const QString twoWaysDownRightStr = QStringLiteral("twoWaysDownRight"); // NOLINT(cert-err58-cpp)
const QString threeWaysUpDownLeftStr = QStringLiteral("threeWaysUpDownLeft"); // NOLINT(cert-err58-cpp)
const QString threeWaysUpDownRightStr = QStringLiteral("threeWaysUpDownRight"); // NOLINT(cert-err58-cpp)
const QString threeWaysUpLeftRightStr = QStringLiteral("threeWaysUpLeftRight"); // NOLINT(cert-err58-cpp)
const QString threeWaysDownLeftRightStr = QStringLiteral("threeWaysDownLeftRight"); // NOLINT(cert-err58-cpp)
const QChar groupSep = QLatin1Char(';');
const QChar groupSep = QLatin1Char(';');
const QChar coordintatesSep = QLatin1Char(',');
const QChar pointsSep = QLatin1Char(' ');
const QChar itemsSep = QLatin1Char('*');

View File

@ -90,7 +90,6 @@ extern const QString AttrTransform;
extern const QString AttrShowSeamline;
extern const QString AttrEnabled;
extern const QString AttrBuiltIn;
extern const QString AttrAngle;
extern const QString AttrArrowDirection;
extern const QString AttrType;
extern const QString AttrBaseLine;
@ -120,10 +119,18 @@ extern const QString AttrY;
extern const QString AttrTurnPoint;
extern const QString AttrCurvePoint;
extern const QString atFrontStr;
extern const QString atRearStr;
extern const QString atFourWayStr;
extern const QString atBothStr;
extern const QString oneWayUpStr;
extern const QString oneWayDownStr;
extern const QString fourWaysStr;
extern const QString twoWaysUpDownStr;
extern const QString twoWaysUpLeftStr;
extern const QString twoWaysUpRightStr;
extern const QString twoWaysDownLeftStr;
extern const QString twoWaysDownRightStr;
extern const QString threeWaysUpDownLeftStr;
extern const QString threeWaysUpDownRightStr;
extern const QString threeWaysUpLeftRightStr;
extern const QString threeWaysDownLeftRightStr;
extern const QChar groupSep;
extern const QChar coordintatesSep;

View File

@ -1138,23 +1138,23 @@ void MainWindowsNoGUI::ExportScene(const QList<QGraphicsScene *> &scenes,
exporter.SetFileName(name);
exporter.SetImageRect(paper->rect());
QPen defaultPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), Qt::SolidLine,
Qt::RoundCap, Qt::RoundJoin);
switch (m_dialogSaveLayout->Format())
{
case LayoutExportFormats::SVG:
paper->setVisible(false);
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToSVG(scene, details.at(i));
paper->setVisible(true);
break;
case LayoutExportFormats::PDF:
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToPDF(scene, details.at(i));
break;
case LayoutExportFormats::PNG:
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToPNG(scene, details.at(i));
break;
case LayoutExportFormats::OBJ:
@ -1163,13 +1163,11 @@ void MainWindowsNoGUI::ExportScene(const QList<QGraphicsScene *> &scenes,
paper->setVisible(true);
break;
case LayoutExportFormats::PS:
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToPS(scene, details.at(i));
break;
case LayoutExportFormats::EPS:
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToEPS(scene, details.at(i));
break;
case LayoutExportFormats::DXF_AC1006_Flat:
@ -1227,8 +1225,7 @@ void MainWindowsNoGUI::ExportScene(const QList<QGraphicsScene *> &scenes,
paper->setVisible(true);
break;
case LayoutExportFormats::TIF:
exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(),
Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
exporter.SetPen(defaultPen);
exporter.ExportToTIF(scene, details.at(i));
break;
default:

View File

@ -96,5 +96,6 @@
<file>schema/layout/v0.1.2.xsd</file>
<file>schema/layout/v0.1.3.xsd</file>
<file>schema/layout/v0.1.4.xsd</file>
<file>schema/layout/v0.1.5.xsd</file>
</qresource>
</RCC>

View File

@ -0,0 +1,579 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="layout">
<xs:complexType>
<xs:sequence>
<xs:element name="properties">
<xs:complexType>
<xs:sequence>
<xs:element type="units" name="unit"/>
<xs:element type="xs:string" name="title"/>
<xs:element type="xs:string" name="description"/>
<xs:element name="control">
<xs:complexType>
<xs:attribute type="xs:boolean" name="warningSuperposition"/>
<xs:attribute type="xs:boolean" name="warningOutOfBound"/>
<xs:attribute type="xs:boolean" name="stickyEdges"/>
<xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:float" name="piecesGap"/>
</xs:complexType>
</xs:element>
<xs:element name="tiles">
<xs:complexType>
<xs:sequence>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="visible"/>
<xs:attribute type="xs:string" name="matchingMarks"/>
<xs:attribute type="xs:boolean" name="printScheme"/>
<xs:attribute type="xs:boolean" name="tileNumber"/>
</xs:complexType>
</xs:element>
<xs:element name="scale">
<xs:complexType>
<xs:attribute type="LayoutScale" name="xScale"/>
<xs:attribute type="LayoutScale" name="yScale"/>
</xs:complexType>
</xs:element>
<xs:element name="watermark">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="showPreview" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="unplacedPieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sheets">
<xs:complexType>
<xs:sequence>
<xs:element name="sheet" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
<xs:element name="pieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
<xs:attribute type="xs:float" name="zValue"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="GrainlineType" name="grainlineType"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="formatVersion" name="version" use="required"/>
</xs:complexType>
</xs:element>
<!--Types-->
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="units">
<xs:restriction base="xs:string">
<xs:enumeration value="mm"/>
<xs:enumeration value="cm"/>
<xs:enumeration value="inch"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="uuid">
<xs:restriction base="xs:string">
<xs:pattern value="|\{[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}\}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ArrowDirection">
<xs:restriction base="xs:string">
<xs:enumeration value="oneWayUp"/>
<xs:enumeration value="oneWayDown"/>
<xs:enumeration value="twoWaysUpDown"/>
<xs:enumeration value="fourWays"/>
<xs:enumeration value="twoWaysUpLeft"/>
<xs:enumeration value="twoWaysUpRight"/>
<xs:enumeration value="twoWaysDownLeft"/>
<xs:enumeration value="twoWaysDownRight"/>
<xs:enumeration value="threeWaysUpDownLeft"/>
<xs:enumeration value="threeWaysUpDownRight"/>
<xs:enumeration value="threeWaysUpLeftRight"/>
<xs:enumeration value="threeWaysDownLeftRight"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NotchType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/>
<!--OneLine-->
<xs:enumeration value="1"/>
<!--TwoLines-->
<xs:enumeration value="2"/>
<!--ThreeLines-->
<xs:enumeration value="3"/>
<!--TMark-->
<xs:enumeration value="4"/>
<!--VMark-->
<xs:enumeration value="5"/>
<!--VMark2-->
<xs:enumeration value="6"/>
<!--UMark-->
<xs:enumeration value="7"/>
<!--BoxMark-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CurvePenStyle">
<xs:restriction base="xs:string">
<xs:enumeration value="hair"/>
<xs:enumeration value="dashLine"/>
<xs:enumeration value="dotLine"/>
<xs:enumeration value="dashDotLine"/>
<xs:enumeration value="dashDotDotLine"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="MarkerType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--Segment-->
<xs:enumeration value="1"/><!--Rectangle-->
<xs:enumeration value="2"/><!--Cross-->
<xs:enumeration value="3"/><!--Tshaped-->
<xs:enumeration value="4"/><!--Doubletree-->
<xs:enumeration value="5"/><!--Corner-->
<xs:enumeration value="6"/><!--Triangle-->
<xs:enumeration value="7"/><!--Hshaped-->
<xs:enumeration value="8"/><!--Button-->
<xs:enumeration value="9"/><!--Circle-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="AlignmentType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--default (no aligns)-->
<xs:enumeration value="1"/><!--aligns with the left edge-->
<xs:enumeration value="2"/><!--aligns with the right edge-->
<xs:enumeration value="4"/><!--Centers horizontally in the available space-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Transformation">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){8,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathNotEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinesPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\*){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PointPath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RectPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){3,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="GrainlineType">
<xs:restriction base="xs:string">
<xs:enumeration value="horizontal"/>
<xs:enumeration value="vertical"/>
<xs:enumeration value="notFixed"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LayoutScale">
<xs:restriction base="xs:float">
<xs:minInclusive value="0.01"/>
<xs:maxInclusive value="3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -946,15 +946,31 @@
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="arrowType">
<xs:restriction base="xs:unsignedInt">
<xs:restriction base="xs:integer">
<xs:enumeration value="0"/>
<!--Both-->
<!-- Represents a two-way arrow pointing up and down -->
<xs:enumeration value="1"/>
<!--Front-->
<!-- Represents a one-way arrow pointing up -->
<xs:enumeration value="2"/>
<!--Rear-->
<!-- Represents a one-way arrow pointing down -->
<xs:enumeration value="3"/>
<!--For way-->
<!-- Represents a four-way arrow pointing in all directions -->
<xs:enumeration value="4"/>
<!-- Represents a two-way arrow pointing up and left -->
<xs:enumeration value="5"/>
<!-- Represents a two-way arrow pointing up and right -->
<xs:enumeration value="6"/>
<!-- Represents a two-way arrow pointing down and left -->
<xs:enumeration value="7"/>
<!-- Represents a two-way arrow pointing down and right -->
<xs:enumeration value="8"/>
<!-- Represents a three-way arrow pointing up, down, and left -->
<xs:enumeration value="9"/>
<!-- Represents a three-way arrow pointing up, down, and right -->
<xs:enumeration value="10"/>
<!-- Represents a three-way arrow pointing up, left, and right -->
<xs:enumeration value="11"/>
<!-- Represents a three-way arrow pointing down, left, and right -->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="pieceVersion">

View File

@ -196,6 +196,14 @@ inline void VDomDocument::SetAttribute<QString>(QDomElement &domElement, const Q
domElement.setAttribute(name, value);
}
//---------------------------------------------------------------------------------------------------------------------
template <>
inline void VDomDocument::SetAttribute<QLatin1String>(QDomElement &domElement, const QString &name,
const QLatin1String &value) const
{
domElement.setAttribute(name, value);
}
//---------------------------------------------------------------------------------------------------------------------
template <>
inline void VDomDocument::SetAttribute<QChar>(QDomElement &domElement, const QString &name, const QChar &value) const

View File

@ -29,6 +29,8 @@
#include "../exception/vexception.h"
#include "../ifcdef.h"
#include "../vlayout/vlayoutpoint.h"
#include "compatibility.h"
#include "vpatterndb/floatItemData/floatitemdef.h"
/*
* Version rules:
@ -39,8 +41,8 @@
*/
const QString VLayoutConverter::LayoutMinVerStr = QStringLiteral("0.1.0");
const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.4");
const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.4.xsd");
const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.5");
const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.5.xsd");
//VLayoutConverter::LayoutMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
//VLayoutConverter::LayoutMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@ -55,14 +57,17 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, strInternalPathTag, (QLatin1String("int
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strMarkerTag, (QLatin1String("marker"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPointTag, (QLatin1String("point"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPieceTag, (QLatin1String("piece"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strGrainlineTag, (QLatin1String("grainline"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrX, (QLatin1String("x"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrY, (QLatin1String("y"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrTurnPoint, (QLatin1String("turnPoint"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrCurvePoint, (QLatin1String("curvePoint"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrId, (QLatin1String("id"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrUId, (QLatin1String("uid"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrAngle, (QLatin1String("angle"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strAttrArrowDirection, (QLatin1String("arrowDirection"))) // NOLINT
//const QChar groupSep = QLatin1Char(';');
const QChar groupSep = QLatin1Char(';');
const QChar coordintatesSep = QLatin1Char(',');
const QChar pointsSep = QLatin1Char(' ');
//const QChar itemsSep = QLatin1Char('*');
@ -92,6 +97,13 @@ auto StringV0_1_2ToPath(const QString &path) -> QVector<QPointF>
return p;
}
//---------------------------------------------------------------------------------------------------------------------
template <class T> auto NumberToString(T number) -> QString
{
const QLocale locale = QLocale::c();
return locale.toString(number, 'g', 12).remove(LocaleGroupSeparator(locale));
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
@ -120,13 +132,13 @@ auto VLayoutConverter::GetFormatVersionStr() const -> QString
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutConverter::XSDSchemas() -> QHash<unsigned int, QString>
{
static auto schemas = QHash <unsigned, QString>
{
static auto schemas = QHash<unsigned, QString>{
std::make_pair(FormatVersion(0, 1, 0), QStringLiteral("://schema/layout/v0.1.0.xsd")),
std::make_pair(FormatVersion(0, 1, 1), QStringLiteral("://schema/layout/v0.1.1.xsd")),
std::make_pair(FormatVersion(0, 1, 2), QStringLiteral("://schema/layout/v0.1.2.xsd")),
std::make_pair(FormatVersion(0, 1, 3), QStringLiteral("://schema/layout/v0.1.3.xsd")),
std::make_pair(FormatVersion(0, 1, 4), CurrentSchema),
std::make_pair(FormatVersion(0, 1, 4), QStringLiteral("://schema/layout/v0.1.4.xsd")),
std::make_pair(FormatVersion(0, 1, 5), CurrentSchema),
};
return schemas;
@ -159,10 +171,11 @@ void VLayoutConverter::ApplyPatches()
ToV0_1_3();
Q_FALLTHROUGH();
case (FormatVersion(0, 1, 3)):
ToV0_1_4();
case (FormatVersion(0, 1, 4)):
ToV0_1_5();
ValidateXML(CurrentSchema);
Q_FALLTHROUGH();
case (FormatVersion(0, 1, 4)):
case (FormatVersion(0, 1, 5)):
break;
default:
InvalidVersion(m_ver);
@ -264,6 +277,100 @@ void VLayoutConverter::ConvertPathToV0_1_3(QDomElement &node)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ConvertPiecesToV0_1_5()
{
// TODO. Delete if minimal supported version is 0.1.5
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 5), "Time to refactor the code.");
QDomNodeList grainlineTags = elementsByTagName(*strGrainlineTag);
for (int i = 0; i < grainlineTags.size(); ++i)
{
QDomElement node = grainlineTags.at(i).toElement();
if (node.isElement())
{
// remove angle attribute
if (node.hasAttribute(*strAttrAngle))
{
node.removeAttribute(*strAttrAngle);
}
// convert arrowDirection
if (node.hasAttribute(*strAttrArrowDirection))
{
QString arrowDirection = node.attribute(*strAttrArrowDirection);
const QStringList arrows{
"atFront", // 0
"atRear", // 1
"atFourWay", // 2
"atBoth" // 3
};
switch (arrows.indexOf(arrowDirection))
{
case 0: // at front
SetAttribute(node, *strAttrArrowDirection, QLatin1String("oneWayUp"));
break;
case 1: // at rear
SetAttribute(node, *strAttrArrowDirection, QLatin1String("oneWayDown"));
break;
case 2: // at four way
SetAttribute(node, *strAttrArrowDirection, QLatin1String("fourWays"));
break;
case 3: // at both
default:
SetAttribute(node, *strAttrArrowDirection, QLatin1String("twoWaysUpDown"));
break;
}
}
auto StringToPath = [](const QString &path) -> QVector<QPointF>
{
auto StringToPoint = [](const QString &point) -> QPointF
{
QStringList coordinates = point.split(coordintatesSep);
if (coordinates.count() == 2)
{
return {coordinates.at(0).toDouble(), coordinates.at(1).toDouble()};
}
return {};
};
QVector<QPointF> p;
if (path.isEmpty())
{
return p;
}
QStringList points = path.split(pointsSep);
p.reserve(points.size());
for (const auto &point : points)
{
p.append(StringToPoint(point));
}
return p;
};
const QVector<QPointF> path = StringToPath(node.text());
if (not path.isEmpty())
{
auto LineToString = [](const QLineF &line) -> QString
{
auto PointToString = [](const QPointF &p) -> QString
{ return NumberToString(p.x()) + coordintatesSep + NumberToString(p.y()); };
return PointToString(line.p1()) + groupSep + PointToString(line.p2());
};
node.firstChild().toText().setData(LineToString(QLineF(ConstFirst(path), ConstLast(path))));
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ToV0_1_3()
{
@ -277,11 +384,11 @@ void VLayoutConverter::ToV0_1_3()
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ToV0_1_4()
void VLayoutConverter::ToV0_1_5()
{
// TODO. Delete if minimal supported version is 0.1.4
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 4),
"Time to refactor the code.");
SetVersion(QStringLiteral("0.1.4"));
// TODO. Delete if minimal supported version is 0.1.5
Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 5), "Time to refactor the code.");
ConvertPiecesToV0_1_5();
SetVersion(QStringLiteral("0.1.5"));
Save();
}

View File

@ -46,7 +46,7 @@ public:
static const QString LayoutMaxVerStr;
static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const unsigned LayoutMinVer = FormatVersion(0, 1, 0);
static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 4);
static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 5);
static auto XSDSchemas() -> QHash <unsigned, QString>;
@ -69,8 +69,10 @@ protected:
void ConvertPiecesToV0_1_3();
void ConvertPathToV0_1_3(QDomElement &node);
void ConvertPiecesToV0_1_5();
void ToV0_1_3();
void ToV0_1_4();
void ToV0_1_5();
private:
Q_DISABLE_COPY_MOVE(VLayoutConverter) // NOLINT

View File

@ -27,8 +27,8 @@
*************************************************************************/
#include "vdxfengine.h"
#include <QLineF>
#include <QByteArray>
#include <QColor>
#include <QDateTime>
@ -866,10 +866,10 @@ void VDxfEngine::ExportAAMANotch(const QSharedPointer<dx_ifaceBlock> &detailBloc
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportAAMAGrainline(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
const QVector<QPointF> grainline = detail.GetMappedGrainline();
if (grainline.count() > 1)
const QLineF grainlineMainLine = detail.GetMappedGrainlineMainLine();
if (not grainlineMainLine.isNull())
{
if (DRW_Entity *e = AAMALine(QLineF(ConstFirst(grainline), ConstLast(grainline)), *layer7))
if (DRW_Entity *e = AAMALine(grainlineMainLine, *layer7))
{
detailBlock->ent.push_back(e);
}

View File

@ -27,6 +27,8 @@
*************************************************************************/
#include "vabstractpiece.h"
#include "qline.h"
#include "qmath.h"
#include "vabstractpiece_p.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vgeometry/vpointf.h"
@ -37,7 +39,7 @@
#include "../vpatterndb/floatItemData/vgrainlinedata.h"
#include "../vpatterndb/vcontainer.h"
#include "../vpatterndb/calculator.h"
#include "testpath.h"
#include "../vwidgets/vpiecegrainline.h"
#include "vrawsapoint.h"
#include <QLineF>
@ -1603,7 +1605,6 @@ auto VAbstractPiece::RollbackSeamAllowance(QVector<VRawSAPoint> points, const QL
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::IsItemContained(const QRectF &parentBoundingRect, const QVector<QPointF> &shape, qreal &dX,
qreal &dY) -> bool
@ -1749,81 +1750,48 @@ auto VAbstractPiece::FindGrainlineGeometry(const VGrainlineData& geom, const VCo
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractPiece::GrainlinePoints(const VGrainlineData &geom, const VContainer *pattern, const QRectF &boundingRect,
qreal &dAng) -> QVector<QPointF>
auto VAbstractPiece::GrainlineMainLine(const VGrainlineData &geom, const VContainer *pattern,
const QRectF &boundingRect) -> QLineF
{
SCASSERT(pattern != nullptr)
QPointF pt1;
qreal dLen = 0;
if ( not FindGrainlineGeometry(geom, pattern, dLen, dAng, pt1))
qreal dAng = 0;
if (not FindGrainlineGeometry(geom, pattern, dLen, dAng, pt1))
{
return {};
}
qreal rotation = dAng;
QPointF pt2(pt1.x() + dLen * qCos(dAng), pt1.y() - dLen * qSin(dAng));
QPointF pt2(pt1.x() + dLen * qCos(rotation), pt1.y() - dLen * qSin(rotation));
const qreal dArrowLen = ToPixel(0.5, *pattern->GetPatternUnit());
const qreal dArrowAng = M_PI/9;
VPieceGrainline grainline(QLineF(pt1, pt2), geom.GetArrowType());
QVector<QPointF> v;
v << pt1;
if (geom.GetArrowType() != GrainlineArrowDirection::atFront)
if (grainline.IsFourWays())
{
v << QPointF(pt1.x() + dArrowLen * qCos(rotation + dArrowAng),
pt1.y() - dArrowLen * qSin(rotation + dArrowAng));
v << QPointF(pt1.x() + dArrowLen * qCos(rotation - dArrowAng),
pt1.y() - dArrowLen * qSin(rotation - dArrowAng));
v << pt1;
if (geom.GetArrowType() == GrainlineArrowDirection::atFourWay)
{ // second double arrow
QLineF line(pt2, pt1);
line.setLength(line.length() - dArrowLen - dArrowLen*0.5);
v << line.p2();
v << QPointF(line.p2().x() + dArrowLen * qCos(rotation + dArrowAng),
line.p2().y() - dArrowLen * qSin(rotation + dArrowAng));
v << QPointF(line.p2().x() + dArrowLen * qCos(rotation - dArrowAng),
line.p2().y() - dArrowLen * qSin(rotation - dArrowAng));
v << line.p2();
}
QLineF mainLine = grainline.GetMainLine();
QLineF secondaryLine = grainline.SecondaryLine();
v = {mainLine.p1(), mainLine.p2(), secondaryLine.p1(), secondaryLine.p2()};
}
else
{
QLineF mainLine = grainline.GetMainLine();
v = {mainLine.p1(), mainLine.p2()};
}
if (geom.GetArrowType() != GrainlineArrowDirection::atFourWay)
qreal dX = 0;
qreal dY = 0;
if (not IsItemContained(boundingRect, v, dX, dY))
{
v << pt2;
pt1.rx() = + dX;
pt1.ry() = + dY;
pt2.rx() = + dX;
pt2.ry() = + dY;
}
if (geom.GetArrowType() != GrainlineArrowDirection::atRear)
{
rotation += M_PI;
if (geom.GetArrowType() == GrainlineArrowDirection::atFourWay)
{ // first double arrow
QLineF line(pt1, pt2);
line.setLength(line.length() - dArrowLen - dArrowLen*0.5);
v << line.p2();
v << QPointF(line.p2().x() + dArrowLen * qCos(rotation + dArrowAng),
line.p2().y() - dArrowLen * qSin(rotation + dArrowAng));
v << QPointF(line.p2().x() + dArrowLen * qCos(rotation - dArrowAng),
line.p2().y() - dArrowLen * qSin(rotation - dArrowAng));
v << line.p2();
v << pt2;
}
v << QPointF(pt2.x() + dArrowLen * qCos(rotation + dArrowAng),
pt2.y() - dArrowLen * qSin(rotation + dArrowAng));
v << QPointF(pt2.x() + dArrowLen * qCos(rotation - dArrowAng),
pt2.y() - dArrowLen * qSin(rotation - dArrowAng));
v << pt2;
}
return CorrectPosition(boundingRect, v);
return {pt1, pt2};
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -126,8 +126,8 @@ public:
static auto RollbackSeamAllowance(QVector<VRawSAPoint> points, const QLineF &cuttingEdge,
bool *success) -> QVector<VRawSAPoint>;
static auto GrainlinePoints(const VGrainlineData &geom, const VContainer *pattern,
const QRectF &boundingRect, qreal &dAng) -> QVector<QPointF>;
static auto GrainlineMainLine(const VGrainlineData &geom, const VContainer *pattern,
const QRectF &boundingRect) -> QLineF;
friend auto operator<< (QDataStream& dataStream, const VAbstractPiece& piece) -> QDataStream&;
friend auto operator>> (QDataStream& dataStream, VAbstractPiece& piece) -> QDataStream&;

View File

@ -33,6 +33,11 @@ VGraphicsFillItem::VGraphicsFillItem(QGraphicsItem *parent)
:QGraphicsPathItem(parent)
{}
//---------------------------------------------------------------------------------------------------------------------
VGraphicsFillItem::VGraphicsFillItem(const QPainterPath &path, QGraphicsItem *parent)
:QGraphicsPathItem(path, parent)
{}
//---------------------------------------------------------------------------------------------------------------------
VGraphicsFillItem::~VGraphicsFillItem()
{}
@ -54,6 +59,8 @@ void VGraphicsFillItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*
{
pen = painter->pen();
pen.setWidthF(width);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
}
painter->setPen(pen);

View File

@ -41,6 +41,8 @@ public:
* @brief VGraphicsFillItem Constructor
*/
explicit VGraphicsFillItem(QGraphicsItem *parent = nullptr);
VGraphicsFillItem(const QPainterPath &path, QGraphicsItem *parent = nullptr);
/**
* @brief ~VGraphicsFillItem Destructor
*/

View File

@ -46,23 +46,27 @@
#include <QUuid>
#include <QtMath>
#include "../vpatterndb/floatItemData/vpatternlabeldata.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/floatItemData/vgrainlinedata.h"
#include "../vpatterndb/variables/vmeasurement.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vgeometry/vlayoutplacelabel.h"
#include "../vgeometry/vplacelabelitem.h"
#include "../vgeometry/vpointf.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/literals.h"
#include "../vpatterndb/vcontainer.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/floatItemData/vgrainlinedata.h"
#include "../vpatterndb/floatItemData/vpatternlabeldata.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/variables/vmeasurement.h"
#include "../vpatterndb/vcontainer.h"
#include "../vpatterndb/vpassmark.h"
#include "../vpatterndb/vpiecenode.h"
#include "../vgeometry/vpointf.h"
#include "../vgeometry/vplacelabelitem.h"
#include "vlayoutpiece_p.h"
#include "vtextmanager.h"
#include "qline.h"
#include "qpainterpath.h"
#include "vgobject.h"
#include "vgraphicsfillitem.h"
#include "../vgeometry/vlayoutplacelabel.h"
#include "vlayoutpiece_p.h"
#include "vpiecegrainline.h"
#include "vtextmanager.h"
namespace
{
@ -751,6 +755,19 @@ auto VLayoutPiece::Map<VLayoutPoint>(QVector<VLayoutPoint> points) const -> QVec
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::Map(const GrainlineShape &shape) const -> GrainlineShape
{
GrainlineShape mappedShape;
mappedShape.reserve(shape.size());
for (auto subShape : shape)
{
mappedShape.append(Map(subShape));
}
return mappedShape;
}
//---------------------------------------------------------------------------------------------------------------------
// cppcheck-suppress unusedFunction
auto VLayoutPiece::GetMappedContourPoints() const -> QVector<VLayoutPoint>
@ -977,77 +994,59 @@ void VLayoutPiece::SetPatternLabelData(const VTextManager &data)
d->m_tmPattern = data;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainline(const VPieceGrainline &grainline)
{
d->m_grainline = grainline;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainline(const VGrainlineData& geom, const VContainer* pattern)
{
qreal dAng = 0;
QScopedPointer<QGraphicsItem> item(GetMainPathItem());
const QVector<QPointF> v = GrainlinePoints(geom, pattern, item->boundingRect(), dAng);
if (v.isEmpty())
QLineF mainLine = GrainlineMainLine(geom, pattern, item->boundingRect());
if (mainLine.isNull())
{
return;
}
d->m_grainlineEnabled = true;
d->m_grainlineArrowType = geom.GetArrowType();
d->m_grainlineAngle = qRadiansToDegrees(dAng);
d->m_grainlinePoints = v;
d->m_grainline = VPieceGrainline(mainLine, geom.GetArrowType());
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedGrainline() const -> QVector<QPointF>
auto VLayoutPiece::GetGrainline() const -> VPieceGrainline
{
return Map(d->m_grainlinePoints);
return d->m_grainline;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetGrainline() const -> QVector<QPointF>
auto VLayoutPiece::GetMappedGrainlineShape() const -> GrainlineShape
{
return d->m_grainlinePoints;
return Map(d->m_grainline.Shape());
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetGrainlineShape() const -> GrainlineShape
{
return d->m_grainline.Shape();
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetMappedGrainlineMainLine() const -> QLineF
{
return d->m_matrix.map(d->m_grainline.GetMainLine());
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GetGrainlineMainLine() const -> QLineF
{
return d->m_grainline.GetMainLine();
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::IsGrainlineEnabled() const -> bool
{
return d->m_grainlineEnabled;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainlineEnabled(bool enabled)
{
d->m_grainlineEnabled = enabled;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainlineAngle(qreal angle)
{
d->m_grainlineAngle = angle;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainlineArrowType(GrainlineArrowDirection type)
{
d->m_grainlineArrowType = type;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::SetGrainlinePoints(const QVector<QPointF> &points)
{
d->m_grainlinePoints = points;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GrainlineAngle() const -> qreal
{
return d->m_grainlineAngle;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GrainlineArrowType() const -> GrainlineArrowDirection
{
return d->m_grainlineArrowType;
return d->m_grainline.IsEnabled();
}
//---------------------------------------------------------------------------------------------------------------------
@ -1451,17 +1450,7 @@ void VLayoutPiece::DrawMiniature(QPainter &painter) const
painter.drawPath(LabelShapePath(label));
}
QVector<QPointF> gPoints = GetGrainline();
if (not gPoints.isEmpty())
{
QPainterPath path;
path.moveTo(gPoints.at(0));
for (auto p : qAsConst(gPoints))
{
path.lineTo(p);
}
painter.drawPath(path);
}
painter.drawPath(VLayoutPiece::GrainlinePath(GetGrainlineShape()));
}
//---------------------------------------------------------------------------------------------------------------------
@ -1547,6 +1536,23 @@ auto VLayoutPiece::BoundingRect(QVector<QPointF> points) -> QRectF
return QPolygonF(points).boundingRect();
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::GrainlinePath(const GrainlineShape &shape) -> QPainterPath
{
QPainterPath shapePath;
for (auto subShape : shape)
{
QPainterPath path;
path.moveTo(subShape.at(0));
for (auto p : qAsConst(subShape))
{
path.lineTo(p);
}
shapePath.addPath(path);
}
return shapePath;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutPiece::CreateLabelStrings(QGraphicsItem *parent, const QVector<QPointF> &labelShape,
const VTextManager &tm, bool textAsPaths) const
@ -1650,22 +1656,13 @@ void VLayoutPiece::CreateGrainlineItem(QGraphicsItem *parent) const
{
SCASSERT(parent != nullptr)
if (not d->m_grainlineEnabled || d->m_grainlinePoints.count() < 2)
if (not d->m_grainline.IsEnabled())
{
return;
}
auto* item = new VGraphicsFillItem(parent);
auto *item = new VGraphicsFillItem(VLayoutPiece::GrainlinePath(GetMappedGrainlineShape()), parent);
item->SetWidth(VAbstractApplication::VApp()->Settings()->WidthHairLine());
QPainterPath path;
QVector<QPointF> gPoints = GetMappedGrainline();
path.moveTo(gPoints.at(0));
for (auto p : qAsConst(gPoints))
{
path.lineTo(p);
}
item->setPath(path);
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -41,9 +41,11 @@
#include <QtGlobal>
#include <QCoreApplication>
#include "vabstractpiece.h"
#include "../vmisc/typedef.h"
#include "../vpatterndb/floatItemData/floatitemdef.h"
#include "../vwidgets/vpiecegrainline.h"
#include "qpainterpath.h"
#include "vabstractpiece.h"
#if __cplusplus >= 201703L // C++17
#include <optional>
@ -124,11 +126,12 @@ public:
const VContainer *pattern);
void SetGrainline(const VGrainlineData& geom, const VContainer *pattern);
auto GetMappedGrainline() const -> QVector<QPointF>;
auto GetGrainline() const -> QVector<QPointF>;
auto GetGrainline() const -> VPieceGrainline;
auto GetMappedGrainlineShape() const -> GrainlineShape;
auto GetGrainlineShape() const -> GrainlineShape;
auto GetMappedGrainlineMainLine() const -> QLineF;
auto GetGrainlineMainLine() const -> QLineF;
auto IsGrainlineEnabled() const -> bool;
auto GrainlineAngle() const -> qreal;
auto GrainlineArrowType() const -> GrainlineArrowDirection;
auto GetMatrix() const -> QTransform;
void SetMatrix(const QTransform &matrix);
@ -174,6 +177,8 @@ public:
static auto BoundingRect(QVector<QPointF> points) -> QRectF;
static auto GrainlinePath(const GrainlineShape &shape) -> QPainterPath;
auto isNull() const -> bool;
auto Square() const -> qint64;
@ -195,10 +200,7 @@ public:
auto MapPlaceLabelShape(PlaceLabelImg shape) const -> PlaceLabelImg;
protected:
void SetGrainlineEnabled(bool enabled);
void SetGrainlineAngle(qreal angle);
void SetGrainlineArrowType(GrainlineArrowDirection type);
void SetGrainlinePoints(const QVector<QPointF> &points);
void SetGrainline(const VPieceGrainline &grainline);
auto GetPieceLabelRect() const -> QVector<QPointF>;
void SetPieceLabelRect(const QVector<QPointF> &rect);
@ -226,6 +228,7 @@ private:
template <class T>
auto Map(QVector<T> points) const -> QVector<T>;
auto Map(const GrainlineShape &shape) const -> GrainlineShape;
auto Edge(const QVector<QPointF> &path, int i) const -> QLineF;
auto EdgeByPoint(const QVector<QPointF> &path, const QPointF &p1) const -> EdgeIndex;

View File

@ -35,6 +35,8 @@
#include <QTransform>
#include "../vpatterndb/floatItemData/floatitemdef.h"
#include "../vwidgets/vpiecegrainline.h"
#include "compatibility.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
#include "../vmisc/diagnostic.h"
#endif // QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
@ -92,12 +94,7 @@ public:
/** @brief patternInfo pattern info rectangle */
QVector<QPointF> m_patternInfo{}; // NOLINT(misc-non-private-member-variables-in-classes)
/** @brief grainlineInfo line */
QVector<QPointF> m_grainlinePoints{}; // NOLINT(misc-non-private-member-variables-in-classes)
GrainlineArrowDirection m_grainlineArrowType{GrainlineArrowDirection::atFront}; // NOLINT(misc-non-private-member-variables-in-classes)
qreal m_grainlineAngle{0}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_grainlineEnabled{false}; // NOLINT(misc-non-private-member-variables-in-classes)
VPieceGrainline m_grainline{}; // NOLINT(misc-non-private-member-variables-in-classes)
/** @brief m_tmDetail text manager for laying out detail info */
VTextManager m_tmDetail{}; // NOLINT(misc-non-private-member-variables-in-classes)
@ -124,7 +121,7 @@ private:
Q_DISABLE_ASSIGN_MOVE(VLayoutPieceData) // NOLINT
static constexpr quint32 streamHeader{0x80D7D009}; // CRC-32Q string "VLayoutPieceData"
static constexpr quint16 classVersion{4};
static constexpr quint16 classVersion{5};
};
QT_WARNING_POP
@ -141,7 +138,6 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
{
dataStream << VLayoutPieceData::streamHeader << VLayoutPieceData::classVersion;
// Added in classVersion = 1
dataStream << piece.m_contour;
dataStream << piece.m_seamAllowance;
dataStream << piece.m_layoutAllowance;
@ -152,23 +148,16 @@ inline auto operator<<(QDataStream &dataStream, const VLayoutPieceData &piece) -
dataStream << piece.m_mirror;
dataStream << piece.m_detailLabel;
dataStream << piece.m_patternInfo;
dataStream << piece.m_grainlinePoints;
dataStream << piece.m_grainlineArrowType;
dataStream << piece.m_grainlineAngle;
dataStream << piece.m_grainlineEnabled;
dataStream << piece.m_placeLabels;
dataStream << piece.m_square;
// Added in classVersion = 2
dataStream << piece.m_quantity;
dataStream << piece.m_id;
// Added in classVersion = 3
dataStream << piece.m_tmDetail;
dataStream << piece.m_tmPattern;
dataStream << piece.m_gradationId;
dataStream << piece.m_xScale;
dataStream << piece.m_yScale;
dataStream << piece.m_grainline;
return dataStream;
}
@ -181,7 +170,7 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
if (actualStreamHeader != VLayoutPieceData::streamHeader)
{
QString message = QCoreApplication::tr("VRawLayoutData prefix mismatch error: actualStreamHeader = 0x%1 and "
QString message = QCoreApplication::tr("VLayoutPieceData prefix mismatch error: actualStreamHeader = 0x%1 and "
"streamHeader = 0x%2")
.arg(actualStreamHeader, 8, 0x10, QChar('0'))
.arg(VLayoutPieceData::streamHeader, 8, 0x10, QChar('0'));
@ -193,7 +182,7 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
if (actualClassVersion > VLayoutPieceData::classVersion)
{
QString message = QCoreApplication::tr("VRawLayoutData compatibility error: actualClassVersion = %1 and "
QString message = QCoreApplication::tr("VLayoutPieceData compatibility error: actualClassVersion = %1 and "
"classVersion = %2")
.arg(actualClassVersion).arg(VLayoutPieceData::classVersion);
throw VException(message);
@ -218,6 +207,7 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
dataStream >> piece.m_contour;
dataStream >> piece.m_seamAllowance;
}
dataStream >> piece.m_layoutAllowance;
dataStream >> piece.m_passmarks;
dataStream >> piece.m_internalPaths;
@ -226,10 +216,23 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
dataStream >> piece.m_mirror;
dataStream >> piece.m_detailLabel;
dataStream >> piece.m_patternInfo;
dataStream >> piece.m_grainlinePoints;
dataStream >> piece.m_grainlineArrowType;
dataStream >> piece.m_grainlineAngle;
dataStream >> piece.m_grainlineEnabled;
QVector<QPointF> shape;
GrainlineArrowDirection arrowType = GrainlineArrowDirection::oneWayUp;
bool grainlineEnabled = false;
if (actualClassVersion < 5)
{
dataStream >> shape;
dataStream >> arrowType;
qreal grainlineAngle;
dataStream >> grainlineAngle;
dataStream >> grainlineEnabled;
}
dataStream >> piece.m_placeLabels;
dataStream >> piece.m_square;
@ -248,6 +251,25 @@ inline auto operator>>(QDataStream &dataStream, VLayoutPieceData &piece) -> QDat
dataStream >> piece.m_yScale;
}
if (actualClassVersion >= 5)
{
dataStream >> piece.m_grainline;
}
else
{
if (shape.size() >= 2)
{
piece.m_grainline = VPieceGrainline(QLineF(ConstFirst(shape), ConstLast(shape)), arrowType);
piece.m_grainline.SetEnabled(false);
}
else
{
piece.m_grainline = VPieceGrainline();
piece.m_grainline.SetArrowType(arrowType);
piece.m_grainline.SetEnabled(grainlineEnabled);
}
}
return dataStream;
}

View File

@ -47,10 +47,11 @@
#include <Qt>
#include <functional>
#include "../vmisc/def.h"
#include "../ifc/exception/vexception.h"
#include "../vpatterndb/floatItemData/floatitemdef.h"
#include "../vlayout/vlayoutpoint.h"
#include "../vmisc/def.h"
#include "../vpatterndb/floatItemData/floatitemdef.h"
#include "vpiecegrainline.h"
namespace
{
@ -557,8 +558,9 @@ void VPosition::FollowGrainline()
return;
}
VPieceGrainline pieceGrainline = m_data.detail.GetGrainline();
QLineF detailGrainline(10, 10, 100, 10);
detailGrainline.setAngle(m_data.detail.GrainlineAngle());
detailGrainline.setAngle(pieceGrainline.GetMainLine().angle());
if (m_data.detail.IsForceFlipping())
{
@ -574,8 +576,7 @@ void VPosition::FollowGrainline()
const qreal angle = detailGrainline.angleTo(FabricGrainline());
if (m_data.detail.GrainlineArrowType() == GrainlineArrowDirection::atBoth ||
m_data.detail.GrainlineArrowType() == GrainlineArrowDirection::atFront)
if (pieceGrainline.IsArrowUpEnabled())
{
RotateOnAngle(angle);
}
@ -585,8 +586,7 @@ void VPosition::FollowGrainline()
return;
}
if (m_data.detail.GrainlineArrowType() == GrainlineArrowDirection::atBoth ||
m_data.detail.GrainlineArrowType() == GrainlineArrowDirection::atRear)
if (pieceGrainline.IsArrowDownEnabled())
{
RotateOnAngle(angle + 180);
}
@ -596,15 +596,18 @@ void VPosition::FollowGrainline()
return;
}
if (m_data.detail.GrainlineArrowType() == GrainlineArrowDirection::atFourWay)
if (pieceGrainline.IsArrowLeftEnabled())
{
RotateOnAngle(angle + 90);
}
if (stop->load())
{
return;
}
if (stop->load())
{
return;
}
if (pieceGrainline.IsArrowRightEnabled())
{
RotateOnAngle(angle - 90);
}
}

View File

@ -29,16 +29,23 @@
#ifndef FLOATITEMDEF_H
#define FLOATITEMDEF_H
#include <QList>
#include <QString>
#include <QtTypes>
// denotes the type of arrow for the grainline
enum class GrainlineArrowDirection : qint8
{
atBoth,
atFront,
atRear,
atFourWay
twoWaysUpDown = 0,
oneWayUp = 1,
oneWayDown = 2,
fourWays = 3,
twoWaysUpLeft = 4,
twoWaysUpRight = 5,
twoWaysDownLeft = 6,
twoWaysDownRight = 7,
threeWaysUpDownLeft = 8,
threeWaysUpDownRight = 9,
threeWaysUpLeftRight = 10,
threeWaysDownLeftRight = 11
};
#endif // FLOATITEMDEF_H

View File

@ -379,7 +379,12 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
uiTabLabels->groupBoxDetailLabel->setEnabled(not m_templateLines.isEmpty());
uiTabGrainline->comboBoxArrow->setCurrentIndex(int(piece.GetGrainlineGeometry().GetArrowType()));
int index = uiTabGrainline->comboBoxArrow->findData(static_cast<int>(piece.GetGrainlineGeometry().GetArrowType()));
if (index == -1)
{
index = 0;
}
uiTabGrainline->comboBoxArrow->setCurrentIndex(index);
uiTabLabels->groupBoxDetailLabel->setChecked(ppData.IsVisible());
ChangeCurrentData(uiTabLabels->comboBoxDLCenterPin, ppData.CenterPin());
@ -2656,7 +2661,7 @@ VPiece DialogSeamAllowance::CreatePiece() const
piece.GetGrainlineGeometry().SetVisible(uiTabGrainline->groupBoxGrainline->isChecked());
piece.GetGrainlineGeometry().SetArrowType(
static_cast<GrainlineArrowDirection>(uiTabGrainline->comboBoxArrow->currentIndex()));
static_cast<GrainlineArrowDirection>(uiTabGrainline->comboBoxArrow->currentData().toInt()));
if (not flagGPin)
{
@ -3380,10 +3385,30 @@ void DialogSeamAllowance::InitGrainlineTab()
EnabledGrainline();
uiTabGrainline->comboBoxArrow->addItem(tr("Both"));
uiTabGrainline->comboBoxArrow->addItem(tr("Just front"));
uiTabGrainline->comboBoxArrow->addItem(tr("Just rear"));
uiTabGrainline->comboBoxArrow->addItem(tr("Four way"));
uiTabGrainline->comboBoxArrow->addItem(tr("Two ways (Up/Down)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::twoWaysUpDown));
uiTabGrainline->comboBoxArrow->addItem(tr("One way (Up)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::oneWayUp));
uiTabGrainline->comboBoxArrow->addItem(tr("One way (Down)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::oneWayDown));
uiTabGrainline->comboBoxArrow->addItem(tr("Four ways", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::fourWays));
uiTabGrainline->comboBoxArrow->addItem(tr("Two ways (Up/Left)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::twoWaysUpLeft));
uiTabGrainline->comboBoxArrow->addItem(tr("Two ways (Up/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::twoWaysUpRight));
uiTabGrainline->comboBoxArrow->addItem(tr("Two ways (Down/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::twoWaysDownLeft));
uiTabGrainline->comboBoxArrow->addItem(tr("Two ways (Down/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::twoWaysDownRight));
uiTabGrainline->comboBoxArrow->addItem(tr("Three ways (Up/Down/Left)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::threeWaysUpDownLeft));
uiTabGrainline->comboBoxArrow->addItem(tr("Three ways (Up/Down/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::threeWaysUpDownRight));
uiTabGrainline->comboBoxArrow->addItem(tr("Three ways (Up/Left/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::threeWaysUpLeftRight));
uiTabGrainline->comboBoxArrow->addItem(tr("Three ways (Down/Left/Right)", "grainline direction"),
static_cast<int>(GrainlineArrowDirection::threeWaysDownLeftRight));
m_iRotBaseHeight = uiTabGrainline->lineEditRotFormula->height();
m_iLenBaseHeight = uiTabGrainline->lineEditLenFormula->height();

View File

@ -27,31 +27,32 @@
*************************************************************************/
#include "vtoolseamallowance.h"
#include "../dialogs/tools/piece/dialogseamallowance.h"
#include "../dialogs/tools/piece/dialogduplicatedetail.h"
#include "../vpatterndb/vpiecenode.h"
#include "../vpatterndb/vpiecepath.h"
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/floatItemData/vpatternlabeldata.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/variables/vincrement.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vpointf.h"
#include "../vgeometry/vplacelabelitem.h"
#include "../vgeometry/vellipticalarc.h"
#include "../ifc/xml/vpatternconverter.h"
#include "../dialogs/tools/piece/dialogseamallowance.h"
#include "../ifc/exception/vexceptionwrongid.h"
#include "../ifc/xml/vlabeltemplateconverter.h"
#include "../ifc/xml/vpatternconverter.h"
#include "../qmuparser/qmutokenparser.h"
#include "../undocommands/addpiece.h"
#include "../undocommands/deletepiece.h"
#include "../undocommands/movepiece.h"
#include "../undocommands/savepieceoptions.h"
#include "../undocommands/togglepiecestate.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vellipticalarc.h"
#include "../vgeometry/vplacelabelitem.h"
#include "../vgeometry/vpointf.h"
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/floatItemData/vpatternlabeldata.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#include "../vpatterndb/variables/vincrement.h"
#include "../vpatterndb/vpiecenode.h"
#include "../vpatterndb/vpiecepath.h"
#include "../vwidgets/global.h"
#include "../vwidgets/vabstractmainwindow.h"
#include "../vwidgets/vmaingraphicsview.h"
#include "../vwidgets/vnobrushscalepathitem.h"
#include "../vwidgets/vabstractmainwindow.h"
#include "../vwidgets/global.h"
#include "../qmuparser/qmutokenparser.h"
#include "../vwidgets/vpiecegrainline.h"
#include "toolsdef.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
#include "../vmisc/backport/qoverload.h"
@ -2158,32 +2159,14 @@ auto VToolSeamAllowance::SelectedTools() const -> QList<VToolSeamAllowance *>
//---------------------------------------------------------------------------------------------------------------------
auto VToolSeamAllowance::IsGrainlinePositionValid() const -> bool
{
QVector<QLineF> grainLine = m_grainLine->Grainline();
VPieceGrainline grainLine = m_grainLine->Grainline();
const VPiece detail = VAbstractTool::data.GetPiece(m_id);
QVector<QPointF> contourPoints;
detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn()
? CastTo(detail.SeamAllowancePoints(getData()), contourPoints)
: CastTo(detail.MainPathPoints(getData()), contourPoints);
for (auto line : grainLine)
{
QVector<QPointF> points = VAbstractCurve::CurveIntersectLine(contourPoints, line);
for (auto &point : points)
{
if (not VFuzzyComparePoints(line.p1(), point) && not VFuzzyComparePoints(line.p2(), point))
{
return false;
}
}
}
QPainterPath grainLinePath;
for (auto line : grainLine)
{
grainLinePath.addPath(VGObject::PainterPath(QVector<QPointF>{line.p1(), line.p2()}));
}
const QPainterPath contourPath = VGObject::PainterPath(contourPoints);
return contourPath.contains(grainLinePath);
return grainLine.IsPositionValid(contourPoints);
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -26,7 +26,7 @@
**
*************************************************************************/
#include <math.h>
#include <cmath>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
@ -36,20 +36,17 @@
#include <QGraphicsView>
#include "../vmisc/def.h"
#include "../vmisc/vmath.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vmisc/vabstractapplication.h"
#include "../vmisc/literals.h"
#include "global.h"
#include "vpiecegrainline.h"
#include "vgrainlineitem.h"
#define ARROW_ANGLE M_PI/9
#define ARROW_LENGTH 15
#define RECT_WIDTH 30
#define RESIZE_RECT_SIZE 10
#define ROTATE_CIRC_R 7
#define ACTIVE_Z 10
#define LINE_PEN_WIDTH 3
constexpr int rectWidth = 30;
constexpr int resizeRectSize = 10;
constexpr int rotateCircR = 7;
constexpr int activeZ = 10;
//---------------------------------------------------------------------------------------------------------------------
/**
@ -58,19 +55,6 @@
*/
VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent)
: VPieceItem(pParent),
m_dRotation(0),
m_dStartRotation(0),
m_dLength(0),
m_polyBound(),
m_ptStartPos(),
m_ptStartMove(),
m_polyResize(),
m_dStartLength(0),
m_ptStart(),
m_ptFinish(),
m_ptCenter(),
m_dAngle(0),
m_eArrowType(GrainlineArrowDirection::atBoth),
m_penWidth(VAbstractApplication::VApp()->Settings()->WidthMainLine())
{
setAcceptHoverEvents(true);
@ -80,18 +64,16 @@ VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent)
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VGrainlineItem::shape() const
auto VGrainlineItem::shape() const -> QPainterPath
{
if (m_eMode == mNormal)
{
return MainShape();
}
else
{
QPainterPath path;
path.addPolygon(m_polyBound);
return path;
}
QPainterPath path;
path.addPolygon(m_polyBound);
return path;
}
//---------------------------------------------------------------------------------------------------------------------
@ -110,37 +92,39 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption
const qreal width = ScaleWidth(VAbstractApplication::VApp()->Settings()->WidthHairLine(), SceneScale(scene()));
pP->setPen(QPen(clr, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
pP->setRenderHints(QPainter::Antialiasing);
// line
const QLineF mainLine = MainLine();
VPieceGrainline grainline(QPointF(), m_dLength, m_dRotation, m_eArrowType);
// main line
const QLineF mainLine = grainline.GetMainLine();
pP->drawLine(mainLine.p1(), mainLine.p2());
pP->setBrush(clr);
qreal dArrLen = ARROW_LENGTH;
if (m_eArrowType != GrainlineArrowDirection::atRear)
if (grainline.IsArrowUpEnabled())
{
// first arrow
pP->drawPolygon(FirstArrow(MainLine().p2(), dArrLen));
if (m_eArrowType == GrainlineArrowDirection::atFourWay)
{ // first double arrow
QLineF line = MainLine();
line.setLength(line.length() - dArrLen - dArrLen*0.5);
pP->drawPolygon(FirstArrow(line.p2(), dArrLen));
}
pP->drawPolygon(grainline.ArrowUp());
}
if (m_eArrowType != GrainlineArrowDirection::atFront)
{
// second arrow
pP->drawPolygon(SecondArrow(MainLine().p1(), dArrLen));
if (m_eArrowType == GrainlineArrowDirection::atFourWay)
{ // second double arrow
QLineF line(MainLine().p2(), MainLine().p1());
line.setLength(line.length() - dArrLen - dArrLen*0.5);
pP->drawPolygon(SecondArrow(line.p2(), dArrLen));
if (grainline.IsArrowDownEnabled())
{
pP->drawPolygon(grainline.ArrowDown());
}
if (grainline.IsFourWays())
{
// secondary line
const QLineF secondaryLine = grainline.SecondaryLine();
pP->drawLine(secondaryLine.p1(), secondaryLine.p2());
if (grainline.IsArrowLeftEnabled())
{
pP->drawPolygon(grainline.ArrowLeft());
}
if (grainline.IsArrowRightEnabled())
{
pP->drawPolygon(grainline.ArrowRight());
}
}
@ -170,7 +154,7 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption
if (m_eMode == mRotate)
{
QPointF ptC = (m_polyBound.at(0) + m_polyBound.at(2))/2;
qreal dRad = ROTATE_CIRC_R;
qreal dRad = rotateCircR;
pP->setBrush(clr);
pP->drawEllipse(ptC, dRad, dRad);
@ -178,9 +162,9 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption
pP->save();
pP->translate(ptC);
pP->rotate(qRadiansToDegrees(-m_dRotation));
int iX = int(qRound(m_dLength/2 - 0.5*dRad));
int iY = int(qRound(RECT_WIDTH - 0.5*dRad));
int iR = int(qRound(dRad*3));
int iX = qRound(m_dLength/2 - 0.5*dRad);
int iY = grainline.IsFourWays() ? qRound((m_dLength/2) - 0.8*dRad) : qRound(rectWidth - 0.5*dRad);
int iR = qRound(dRad*3);
pP->drawArc(iX - iR, iY - iR, iR, iR, 0*16, -90*16);
pP->drawArc(-iX, iY - iR, iR, iR, 270*16, -90*16);
pP->drawArc(-iX, -iY, iR, iR, 180*16, -90*16);
@ -202,89 +186,27 @@ void VGrainlineItem::UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal
{
m_dRotation = qDegreesToRadians(dRotation);
m_dLength = dLength;
m_eArrowType = eAT;
VPieceGrainline grainline(ptPos, m_dLength, m_dRotation, m_eArrowType);
qreal dX;
qreal dY;
QPointF pt = ptPos;
if (not IsContained(pt, m_dRotation, dX, dY))
if (not grainline.IsContained(parentItem()->boundingRect(), dX, dY))
{
pt.setX(pt.x() + dX);
pt.setY(pt.y() + dY);
}
setPos(pt);
m_eArrowType = eAT;
UpdateRectangle();
Update();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VGrainlineItem::IsContained checks, if both ends of the grainline, starting at pt, are contained in
* parent widget.
* @param pt starting point of the grainline.
* @param dRot rotation of the grainline in [rad]
* @param dX horizontal translation needed to put the arrow inside parent item
* @param dY vertical translation needed to put the arrow inside parent item
* @return true, if both ends of the grainline, starting at pt, are contained in the parent widget and
* false otherwise.
*/
bool VGrainlineItem::IsContained(const QPointF& pt, qreal dRot, qreal &dX, qreal &dY) const
auto VGrainlineItem::Grainline() const -> VPieceGrainline
{
dX = 0;
dY = 0;
QPointF apt[2];
apt[0] = pt;
apt[1].setX(pt.x() + m_dLength * cos(dRot));
apt[1].setY(pt.y() - m_dLength * sin(dRot));
// single point differences
qreal dPtX;
qreal dPtY;
bool bInside = true;
QRectF rectParent = parentItem()->boundingRect();
for (int i = 0; i < 2; ++i)
{
dPtX = 0;
dPtY = 0;
if (rectParent.contains(apt[i]) == false)
{
if (apt[i].x() < rectParent.left())
{
dPtX = rectParent.left() - apt[i].x();
}
else if (apt[i].x() > rectParent.right())
{
dPtX = rectParent.right() - apt[i].x();
}
if (apt[i].y() < rectParent.top())
{
dPtY = rectParent.top() - apt[i].y();
}
else if (apt[i].y() > rectParent.bottom())
{
dPtY = rectParent.bottom() - apt[i].y();
}
if (fabs(dPtX) > fabs(dX))
{
dX = dPtX;
}
if (fabs(dPtY) > fabs(dY))
{
dY = dPtY;
}
bInside = false;
}
}
return bInside;
}
//---------------------------------------------------------------------------------------------------------------------
QLineF VGrainlineItem::Grainline() const
{
return {m_ptStart, m_ptFinish};
return {QLineF(m_ptStart, m_ptFinish), m_eArrowType};
}
//---------------------------------------------------------------------------------------------------------------------
@ -315,7 +237,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME)
if ((m_moveType & AllModifications ) == AllModifications)
{
AllUserModifications(pME->pos());
setZValue(ACTIVE_Z);
setZValue(activeZ);
Update();
}
else if (m_moveType & IsRotatable)
@ -333,7 +255,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME)
m_eMode = mRotate;
SetItemOverrideCursor(this, cursorArrowCloseHand, 1, 1);
}
setZValue(ACTIVE_Z);
setZValue(activeZ);
Update();
}
else if (m_moveType & IsResizable)
@ -346,7 +268,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME)
{
UserMoveAndResize(pME->pos());
}
setZValue(ACTIVE_Z);
setZValue(activeZ);
Update();
}
else if (m_moveType & IsMovable)
@ -365,7 +287,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME)
SetItemOverrideCursor(this, cursorArrowCloseHand, 1, 1);
}
setZValue(ACTIVE_Z);
setZValue(activeZ);
Update();
}
else
@ -388,7 +310,8 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
if (m_eMode == mMove && m_moveType & IsMovable)
{
QPointF pt = m_ptStartPos + ptDiff;
if (IsContained(pt, m_dRotation, dX, dY) == false)
VPieceGrainline grainline(pt, m_dLength, m_dRotation, m_eArrowType);
if (not grainline.IsContained(parentItem()->boundingRect(), dX, dY))
{
pt.setX(pt.x() + dX);
pt.setY(pt.y() + dY);
@ -440,7 +363,8 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
qreal dX;
qreal dY;
if (IsContained(pos, m_dRotation, dX, dY) == false)
VPieceGrainline grainline(pos, m_dLength, m_dRotation, m_eArrowType);
if (not grainline.IsContained(parentItem()->boundingRect(), dX, dY))
{
m_dLength = dPrevLen;
}
@ -469,7 +393,8 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
qreal dAng = GetAngle(mapToParent(pME->pos())) - m_dAngle;
QPointF ptNewPos = Rotate(m_ptStartPos, m_ptRotCenter, dAng);
if (IsContained(ptNewPos, m_dStartRotation + dAng, dX, dY) == true)
VPieceGrainline grainline(ptNewPos, m_dLength, m_dStartRotation + dAng, m_eArrowType);
if (grainline.IsContained(parentItem()->boundingRect(), dX, dY))
{
setPos(ptNewPos);
m_dRotation = m_dStartRotation + dAng;
@ -487,54 +412,57 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
*/
void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
{
if (pME->button() == Qt::LeftButton)
if (pME->button() != Qt::LeftButton)
{
if ((m_eMode == mMove || m_eMode == mRotate || m_eMode == mResize) && (flags() & QGraphicsItem::ItemIsMovable))
{
SetItemOverrideCursor(this, cursorArrowOpenHand, 1, 1);
}
VPieceItem::mouseReleaseEvent(pME);
return;
}
QPointF ptDiff = pME->scenePos() - m_ptStartMove;
qreal dLen = qSqrt(ptDiff.x()*ptDiff.x() + ptDiff.y()*ptDiff.y());
bool bShort = (dLen < 2);
if ((m_eMode == mMove || m_eMode == mRotate || m_eMode == mResize) && (flags() & QGraphicsItem::ItemIsMovable))
{
SetItemOverrideCursor(this, cursorArrowOpenHand, 1, 1);
}
if (m_eMode == mMove || m_eMode == mResize)
QPointF ptDiff = pME->scenePos() - m_ptStartMove;
qreal dLen = qSqrt(ptDiff.x()*ptDiff.x() + ptDiff.y()*ptDiff.y());
bool bShort = (dLen < 2);
if (m_eMode == mMove || m_eMode == mResize)
{
if (bShort)
{
if (bShort == true)
if (m_bReleased && m_moveType & IsRotatable)
{
if (m_bReleased == true && m_moveType & IsRotatable)
{
m_eMode = mRotate;
Update();
}
}
else
{
if (m_eMode == mMove && m_moveType & IsMovable)
{
emit SignalMoved(pos());
}
else if (m_moveType & IsResizable)
{
emit SignalResized(m_dLength);
}
m_eMode = mRotate;
Update();
}
}
else
{
if (bShort == true)
if (m_eMode == mMove && m_moveType & IsMovable)
{
m_eMode = mMove;
emit SignalMoved(pos());
}
else if (m_moveType & IsRotatable)
else if (m_moveType & IsResizable)
{
emit SignalRotated(m_dRotation, m_ptStart);
emit SignalResized(m_dLength);
}
Update();
}
m_bReleased = true;
}
else
{
if (bShort)
{
m_eMode = mMove;
}
else if (m_moveType & IsRotatable)
{
emit SignalRotated(m_dRotation, m_ptStart);
}
Update();
}
m_bReleased = true;
}
//---------------------------------------------------------------------------------------------------------------------
@ -574,22 +502,41 @@ void VGrainlineItem::Update()
*/
void VGrainlineItem::UpdateRectangle()
{
QPointF pt1(0, 0);
QPointF pt2(pt1.x() + m_dLength * cos(m_dRotation), pt1.y() - m_dLength * sin(m_dRotation));
VPieceGrainline grainline(QPointF(), m_dLength, m_dRotation, m_eArrowType);
const QLineF mainLine = grainline.GetMainLine();
m_ptStart = mapToParent(pt1);
m_ptFinish = mapToParent(pt2);
m_ptStart = mapToParent(mainLine.p1());
m_ptFinish = mapToParent(mainLine.p2());
m_ptCenter = (m_ptStart + m_ptFinish)/2;
m_polyBound.clear();
m_polyBound << QPointF(pt1.x() + RECT_WIDTH*cos(m_dRotation + M_PI/2),
pt1.y() - RECT_WIDTH*sin(m_dRotation + M_PI/2));
m_polyBound << QPointF(pt1.x() + RECT_WIDTH*cos(m_dRotation - M_PI/2),
pt1.y() - RECT_WIDTH*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(pt2.x() + RECT_WIDTH*cos(m_dRotation - M_PI/2),
pt2.y() - RECT_WIDTH*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(pt2.x() + RECT_WIDTH*cos(m_dRotation + M_PI/2),
pt2.y() - RECT_WIDTH*sin(m_dRotation + M_PI/2));
if (grainline.IsFourWays())
{
m_polyBound << QPointF(mainLine.p1().x() + (m_dLength/2)*cos(m_dRotation + M_PI/2),
mainLine.p1().y() - (m_dLength/2)*sin(m_dRotation + M_PI/2));
m_polyBound << QPointF(mainLine.p1().x() + (m_dLength/2)*cos(m_dRotation - M_PI/2),
mainLine.p1().y() - (m_dLength/2)*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(mainLine.p2().x() + (m_dLength/2)*cos(m_dRotation - M_PI/2),
mainLine.p2().y() - (m_dLength/2)*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(mainLine.p2().x() + (m_dLength/2)*cos(m_dRotation + M_PI/2),
mainLine.p2().y() - (m_dLength/2)*sin(m_dRotation + M_PI/2));
const QLineF secondaryLine = grainline.SecondaryLine();
m_ptSecondaryStart = mapToParent(secondaryLine.p1());
m_ptSecondaryFinish = mapToParent(secondaryLine.p2());
}
else
{
m_polyBound << QPointF(mainLine.p1().x() + rectWidth*cos(m_dRotation + M_PI/2),
mainLine.p1().y() - rectWidth*sin(m_dRotation + M_PI/2));
m_polyBound << QPointF(mainLine.p1().x() + rectWidth*cos(m_dRotation - M_PI/2),
mainLine.p1().y() - rectWidth*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(mainLine.p2().x() + rectWidth*cos(m_dRotation - M_PI/2),
mainLine.p2().y() - rectWidth*sin(m_dRotation - M_PI/2));
m_polyBound << QPointF(mainLine.p2().x() + rectWidth*cos(m_dRotation + M_PI/2),
mainLine.p2().y() - rectWidth*sin(m_dRotation + M_PI/2));
}
m_rectBoundingBox = m_polyBound.boundingRect().adjusted(-2, -2, 2, 2);
setTransformOriginPoint(m_rectBoundingBox.center());
@ -598,7 +545,7 @@ void VGrainlineItem::UpdateRectangle()
}
//---------------------------------------------------------------------------------------------------------------------
double VGrainlineItem::GetAngle(const QPointF &pt) const
auto VGrainlineItem::GetAngle(const QPointF &pt) const -> double
{
return -VPieceItem::GetAngle(pt);
}
@ -612,7 +559,7 @@ double VGrainlineItem::GetAngle(const QPointF &pt) const
* @param dAng angle of rotation
* @return point, which is a result of rotating pt around ptCenter by angle dAng
*/
QPointF VGrainlineItem::Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const
auto VGrainlineItem::Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) -> QPointF
{
QPointF ptRel = pt - ptCenter;
QPointF ptFinal;
@ -630,7 +577,7 @@ QPointF VGrainlineItem::Rotate(const QPointF& pt, const QPointF& ptCenter, qreal
* @param dDist distance
* @return resulting point
*/
QPointF VGrainlineItem::GetInsideCorner(int i, qreal dDist) const
auto VGrainlineItem::GetInsideCorner(int i, qreal dDist) const -> QPointF
{
QPointF pt1 = m_polyBound.at((i + 1) % m_polyBound.count()) - m_polyBound.at(i);
QPointF pt2 = m_polyBound.at((i + m_polyBound.count() - 1) % m_polyBound.count()) - m_polyBound.at(i);
@ -642,42 +589,10 @@ QPointF VGrainlineItem::GetInsideCorner(int i, qreal dDist) const
}
//---------------------------------------------------------------------------------------------------------------------
QLineF VGrainlineItem::MainLine() const
auto VGrainlineItem::MainShape() const -> QPainterPath
{
QPointF pt1;
QPointF pt2(pt1.x() + m_dLength * cos(m_dRotation), pt1.y() - m_dLength * sin(m_dRotation));
return QLineF(pt1, pt2);
}
//---------------------------------------------------------------------------------------------------------------------
QPolygonF VGrainlineItem::FirstArrow(const QPointF &pt, qreal dArrLen) const
{
QPolygonF poly;
poly << pt;
poly << QPointF(pt.x() + dArrLen*cos(M_PI + m_dRotation + ARROW_ANGLE),
pt.y() - dArrLen*sin(M_PI + m_dRotation + ARROW_ANGLE));
poly << QPointF(pt.x() + dArrLen*cos(M_PI + m_dRotation - ARROW_ANGLE),
pt.y() - dArrLen*sin(M_PI + m_dRotation - ARROW_ANGLE));
return poly;
}
//---------------------------------------------------------------------------------------------------------------------
QPolygonF VGrainlineItem::SecondArrow(const QPointF &pt, qreal dArrLen) const
{
QPolygonF poly;
poly << pt;
poly << QPointF(pt.x() + dArrLen*cos(m_dRotation + ARROW_ANGLE),
pt.y() - dArrLen*sin(m_dRotation + ARROW_ANGLE));
poly << QPointF(pt.x() + dArrLen*cos(m_dRotation - ARROW_ANGLE),
pt.y() - dArrLen*sin(m_dRotation - ARROW_ANGLE));
return poly;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VGrainlineItem::MainShape() const
{
QPainterPath path;
const QLineF mainLine = MainLine();
VPieceGrainline grainline(QPointF(), m_dLength, m_dRotation, m_eArrowType);
const QLineF mainLine = grainline.GetMainLine();
QPainterPath linePath;
linePath.moveTo(mainLine.p1());
linePath.lineTo(mainLine.p2());
@ -685,43 +600,57 @@ QPainterPath VGrainlineItem::MainShape() const
QPainterPathStroker stroker;
stroker.setWidth(m_penWidth);
QPainterPath path;
path.addPath((stroker.createStroke(linePath) + linePath).simplified());
path.closeSubpath();
const qreal dArrLen = ARROW_LENGTH;
if (m_eArrowType != GrainlineArrowDirection::atRear)
if (grainline.IsArrowUpEnabled())
{
// first arrow
QPainterPath polyPath;
polyPath.addPolygon(FirstArrow(MainLine().p2(), dArrLen));
if (m_eArrowType == GrainlineArrowDirection::atFourWay)
{ // first double arrow
QLineF line = MainLine();
line.setLength(line.length() - dArrLen - 0.5);
polyPath.addPolygon(FirstArrow(line.p2(), dArrLen));
}
polyPath.addPolygon(grainline.ArrowUp());
path.addPath((stroker.createStroke(polyPath) + polyPath).simplified());
path.closeSubpath();
}
if (m_eArrowType != GrainlineArrowDirection::atFront)
if (grainline.IsArrowDownEnabled())
{
// second arrow
QPainterPath polyPath;
polyPath.addPolygon(SecondArrow(MainLine().p1(), dArrLen));
if (m_eArrowType == GrainlineArrowDirection::atFourWay)
{ // second double arrow
QLineF line(MainLine().p2(), MainLine().p1());
line.setLength(line.length() - dArrLen - 0.5);
polyPath.addPolygon(SecondArrow(line.p2(), dArrLen));
}
polyPath.addPolygon(grainline.ArrowDown());
path.addPath((stroker.createStroke(polyPath) + polyPath).simplified());
path.closeSubpath();
}
if (grainline.IsFourWays())
{
const QLineF secondaryLine = grainline.SecondaryLine();
QPainterPath secondaryLinePath;
secondaryLinePath.moveTo(secondaryLine.p1());
secondaryLinePath.lineTo(secondaryLine.p2());
secondaryLinePath.closeSubpath();
path.addPath((stroker.createStroke(secondaryLinePath) + secondaryLinePath).simplified());
path.closeSubpath();
if (grainline.IsArrowLeftEnabled())
{
QPainterPath polyPath;
polyPath.addPolygon(grainline.ArrowLeft());
path.addPath((stroker.createStroke(polyPath) + polyPath).simplified());
path.closeSubpath();
}
if (grainline.IsArrowRightEnabled())
{
QPainterPath polyPath;
polyPath.addPolygon(grainline.ArrowRight());
path.addPath((stroker.createStroke(polyPath) + polyPath).simplified());
path.closeSubpath();
}
}
return path;
}
@ -751,7 +680,7 @@ void VGrainlineItem::UserRotateAndMove()
//---------------------------------------------------------------------------------------------------------------------
void VGrainlineItem::UserMoveAndResize(const QPointF &pos)
{
if (m_polyResize.containsPoint(pos, Qt::OddEvenFill) == true)
if (m_polyResize.containsPoint(pos, Qt::OddEvenFill))
{
m_eMode = mResize;
setCursor(Qt::SizeFDiagCursor);
@ -769,7 +698,7 @@ void VGrainlineItem::UpdatePolyResize()
m_polyResize.clear();
QPointF ptA = m_polyBound.at(1);
m_polyResize << ptA;
const double dSize = RESIZE_RECT_SIZE;
const double dSize = resizeRectSize;
ptA.setX(ptA.x() - dSize*cos(m_dRotation - M_PI/2));
ptA.setY(ptA.y() + dSize*sin(m_dRotation - M_PI/2));

View File

@ -30,68 +30,66 @@
#define VGRAINLINEITEM_H
#include "vpieceitem.h"
#include "../vpatterndb/floatItemData/vgrainlinedata.h"
#include "../vpatterndb/floatItemData/floatitemdef.h"
#include "../vmisc/def.h"
class VPieceGrainline;
class VGrainlineItem final : public VPieceItem
{
Q_OBJECT // NOLINT
public:
explicit VGrainlineItem(QGraphicsItem* pParent = nullptr);
virtual ~VGrainlineItem() = default;
~VGrainlineItem() override = default;
virtual QPainterPath shape() const override;
auto shape() const -> QPainterPath override;
virtual void paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget) override;
void UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength, GrainlineArrowDirection eAT);
void paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget) override;
void UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength, GrainlineArrowDirection eAT);
virtual int type() const override {return Type;}
auto type() const -> int override {return Type;}
enum { Type = UserType + static_cast<int>(Vis::GrainlineItem)};
bool IsContained(const QPointF &pt, qreal dRot, qreal &dX, qreal &dY) const;
QLineF Grainline() const;
auto Grainline() const -> VPieceGrainline;
signals:
void SignalResized(qreal dLength);
void SignalRotated(qreal dRot, const QPointF& ptNewPos);
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent* pME) override;
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* pME) override;
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) override;
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* pME) override;
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* pME) override;
virtual void Update() override;
void UpdateRectangle();
void mousePressEvent(QGraphicsSceneMouseEvent* pME) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* pME) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent* pME) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent* pME) override;
void Update() override;
void UpdateRectangle();
virtual double GetAngle(const QPointF &pt) const override;
auto GetAngle(const QPointF &pt) const -> double override;
QPointF Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const;
QPointF GetInsideCorner(int i, qreal dDist) const;
static auto Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) -> QPointF;
auto GetInsideCorner(int i, qreal dDist) const -> QPointF;
private:
Q_DISABLE_COPY_MOVE(VGrainlineItem) // NOLINT
qreal m_dRotation;
qreal m_dStartRotation;
qreal m_dLength;
QPolygonF m_polyBound;
QPointF m_ptStartPos;
QPointF m_ptStartMove;
QPolygonF m_polyResize;
qreal m_dStartLength;
QPointF m_ptStart;
QPointF m_ptFinish;
QPointF m_ptCenter;
qreal m_dAngle;
GrainlineArrowDirection m_eArrowType;
double m_penWidth{1};
qreal m_dRotation{0};
qreal m_dStartRotation{0};
qreal m_dLength{0};
QPolygonF m_polyBound{};
QPointF m_ptStartPos{};
QPointF m_ptStartMove{};
QPolygonF m_polyResize{};
qreal m_dStartLength{0};
QPointF m_ptStart{};
QPointF m_ptFinish{};
QPointF m_ptSecondaryStart{};
QPointF m_ptSecondaryFinish{};
QPointF m_ptCenter{};
qreal m_dAngle{0};
GrainlineArrowDirection m_eArrowType{GrainlineArrowDirection::twoWaysUpDown};
double m_penWidth{1};
QLineF MainLine() const;
QPolygonF FirstArrow(const QPointF &pt, qreal dArrLen) const;
QPolygonF SecondArrow(const QPointF &pt, qreal dArrLen) const;
QPainterPath MainShape() const;
auto MainShape() const -> QPainterPath;
void AllUserModifications(const QPointF &pos);
void UserRotateAndMove();

View File

@ -0,0 +1,449 @@
/************************************************************************
**
** @file vgrainline.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 27 4, 2023
**
** @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) 2023 Valentina project
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpiecegrainline.h"
#include "../vgeometry/vabstractcurve.h"
#include "qmath.h"
#include "vpiecegrainline_p.h"
#include <QTransform>
namespace
{
constexpr qreal arrowAngle = M_PI/9;
constexpr int arrowLength = 15;
}
// VPieceGrainlinePrivate
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainlinePrivate::MainLine(const QPointF &p1, qreal length, qreal angle) -> QLineF
{
QPointF pt2(p1.x() + length * cos(angle), p1.y() - length * sin(angle));
return {p1, pt2};
}
// VPieceGrainline
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::VPieceGrainline()
:d(new VPieceGrainlinePrivate)
{}
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::~VPieceGrainline() //NOLINT(modernize-use-equals-default)
{}
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::VPieceGrainline(const QLineF &mainLine, GrainlineArrowDirection arrowType)
:d (new VPieceGrainlinePrivate(mainLine, arrowType))
{}
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::VPieceGrainline(const QPointF &p1, qreal length, qreal angle, GrainlineArrowDirection arrowType)
:d (new VPieceGrainlinePrivate(VPieceGrainlinePrivate::MainLine(p1, length, angle), arrowType))
{}
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::VPieceGrainline(const VPieceGrainline &other) //NOLINT(modernize-use-equals-default)
:d (other.d)
{}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::operator=(const VPieceGrainline &grainline) -> VPieceGrainline &
{
if ( &grainline == this )
{
return *this;
}
d = grainline.d;
return *this;
}
#ifdef Q_COMPILER_RVALUE_REFS
//---------------------------------------------------------------------------------------------------------------------
VPieceGrainline::VPieceGrainline(VPieceGrainline &&grainline) Q_DECL_NOTHROW
: d(std::move(grainline.d))
{}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::operator=(VPieceGrainline &&grainline) Q_DECL_NOTHROW -> VPieceGrainline &
{
std::swap(d, grainline.d);
return *this;
}
#endif
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::GetMainLine() const -> QLineF
{
return d->m_mainLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceGrainline::SetMainLine(const QLineF &mainLine)
{
d->m_mainLine = mainLine;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::GetArrowType() const -> GrainlineArrowDirection
{
return d->m_arrowType;
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceGrainline::SetArrowType(GrainlineArrowDirection arrowType)
{
d->m_arrowType = arrowType;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsEnabled() const -> bool
{
return d->m_enabled;
}
//---------------------------------------------------------------------------------------------------------------------
void VPieceGrainline::SetEnabled(bool enabled)
{
d->m_enabled = enabled;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::SecondaryLine() const -> QLineF
{
QLineF mainLine = GetMainLine();
QLineF secondaryLine = mainLine;
QTransform t;
t.translate(mainLine.center().x(), mainLine.center().y());
t.rotate(90);
t.translate(-mainLine.center().x(), -mainLine.center().y());
secondaryLine = t.map(secondaryLine);
return secondaryLine;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsFourWays() const -> bool
{
return d->m_arrowType == GrainlineArrowDirection::fourWays ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpLeft ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpRight ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownLeft ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownLeft ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpLeftRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysDownLeftRight;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsArrowUpEnabled() const -> bool
{
return d->m_arrowType == GrainlineArrowDirection::oneWayUp ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpDown ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpLeft ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownLeft ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpLeftRight ||
d->m_arrowType == GrainlineArrowDirection::fourWays;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsArrowDownEnabled() const -> bool
{
return d->m_arrowType == GrainlineArrowDirection::oneWayDown ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpDown ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownLeft ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownLeft ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysDownLeftRight ||
d->m_arrowType == GrainlineArrowDirection::fourWays;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsArrowLeftEnabled() const -> bool
{
return d->m_arrowType == GrainlineArrowDirection::fourWays ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpLeft ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownLeft ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownLeft ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpLeftRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysDownLeftRight;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsArrowRightEnabled() const -> bool
{
return d->m_arrowType == GrainlineArrowDirection::fourWays ||
d->m_arrowType == GrainlineArrowDirection::twoWaysUpRight ||
d->m_arrowType == GrainlineArrowDirection::twoWaysDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpDownRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysUpLeftRight ||
d->m_arrowType == GrainlineArrowDirection::threeWaysDownLeftRight;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::ArrowUp() const -> QPolygonF
{
const QLineF mainLine = GetMainLine();
const qreal rotation = M_PI + qDegreesToRadians(mainLine.angle());
const QPointF pt = mainLine.p2();
return {
pt,
QPointF(pt.x() + arrowLength * cos(rotation + arrowAngle), pt.y() - arrowLength * sin(rotation + arrowAngle)),
QPointF(pt.x() + arrowLength * cos(rotation - arrowAngle), pt.y() - arrowLength * sin(rotation - arrowAngle)),
pt};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::ArrowDown() const -> QPolygonF
{
const QLineF mainLine = GetMainLine();
const qreal rotation = qDegreesToRadians(mainLine.angle());
const QPointF pt = mainLine.p1();
return {
pt,
QPointF(pt.x() + arrowLength * cos(rotation + arrowAngle), pt.y() - arrowLength * sin(rotation + arrowAngle)),
QPointF(pt.x() + arrowLength * cos(rotation - arrowAngle), pt.y() - arrowLength * sin(rotation - arrowAngle)),
pt};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::ArrowLeft() const -> QPolygonF
{
const qreal rotation = 3 * M_PI / 2 + qDegreesToRadians(GetMainLine().angle());
const QPointF pt = SecondaryLine().p1();
return {
pt,
QPointF(pt.x() + arrowLength * cos(rotation - arrowAngle), pt.y() - arrowLength * sin(rotation - arrowAngle)),
QPointF(pt.x() + arrowLength * cos(rotation + arrowAngle), pt.y() - arrowLength * sin(rotation + arrowAngle)),
pt};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::ArrowRight() const -> QPolygonF
{
const qreal rotation = M_PI / 2 + qDegreesToRadians(GetMainLine().angle());
const QPointF pt = SecondaryLine().p2();
return {
pt,
QPointF(pt.x() + arrowLength * cos(rotation + arrowAngle), pt.y() - arrowLength * sin(rotation + arrowAngle)),
QPointF(pt.x() + arrowLength * cos(rotation - arrowAngle), pt.y() - arrowLength * sin(rotation - arrowAngle)),
pt};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::Shape() const -> GrainlineShape
{
const QLineF mainLine = GetMainLine();
if (mainLine.isNull())
{
return {};
}
// main arrow
QVector<QPointF> arrow1;
if (IsArrowDownEnabled())
{
arrow1 << ArrowDown();
}
else
{
arrow1 << mainLine.p1();
}
if (IsArrowUpEnabled())
{
arrow1 << ArrowUp();
}
else
{
arrow1 << mainLine.p2();
}
if (IsFourWays())
{
// secondary arrow
QVector<QPointF> arrow2;
const QLineF secondaryLine = SecondaryLine();
if (IsArrowLeftEnabled())
{
arrow2 << ArrowLeft();
}
else
{
arrow2 << secondaryLine.p1();
}
if (IsArrowRightEnabled())
{
arrow2 << ArrowRight();
}
else
{
arrow2 << secondaryLine.p2();
}
return {arrow1, arrow2};
}
return {arrow1};
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VPieceGrainline::IsContained checks, if all ends of the grainline, starting at pt, are contained in
* parent widget.
* @param boundingRect bounding rect of piece
* @param dX horizontal translation needed to put the arrow inside parent item
* @param dY vertical translation needed to put the arrow inside parent item
* @return true, if all ends of the grainline, starting at pt, are contained in the bounding rect of piece and
* false otherwise.
*/
auto VPieceGrainline::IsContained(const QRectF &boundingRect, qreal &dX, qreal &dY) const -> bool
{
dX = 0;
dY = 0;
const QLineF mainLine = GetMainLine();
QVector<QPointF> apt = {mainLine.p1(), mainLine.p2()};
if (IsFourWays())
{
const QLineF secondaryLine = SecondaryLine();
apt.append(secondaryLine.p1());
apt.append(secondaryLine.p2());
}
// single point differences
qreal dPtX;
qreal dPtY;
bool bInside = true;
for (auto item : apt)
{
dPtX = 0;
dPtY = 0;
if (boundingRect.contains(item))
{
continue;
}
if (item.x() < boundingRect.left())
{
dPtX = boundingRect.left() - item.x();
}
else if (item.x() > boundingRect.right())
{
dPtX = boundingRect.right() - item.x();
}
if (item.y() < boundingRect.top())
{
dPtY = boundingRect.top() - item.y();
}
else if (item.y() > boundingRect.bottom())
{
dPtY = boundingRect.bottom() - item.y();
}
if (fabs(dPtX) > fabs(dX))
{
dX = dPtX;
}
if (fabs(dPtY) > fabs(dY))
{
dY = dPtY;
}
bInside = false;
}
return bInside;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsPositionValid(const QVector<QPointF> &contourPoints) const -> bool
{
QVector<QLineF> grainLine;
QLineF mainLine = GetMainLine();
if (IsFourWays ())
{
grainLine = {mainLine, SecondaryLine()};
}
grainLine = {mainLine};
for (auto line : grainLine)
{
QVector<QPointF> points = VAbstractCurve::CurveIntersectLine(contourPoints, line);
for (auto &point : points)
{
if (not VFuzzyComparePoints (line.p1 (), point) && not VFuzzyComparePoints (line.p2 (), point))
{
return false;
}
}
}
QPainterPath grainLinePath;
for (auto line : grainLine)
{
grainLinePath.addPath(VGObject::PainterPath(QVector<QPointF>{line.p1(), line.p2()}));
}
const QPainterPath contourPath = VGObject::PainterPath(contourPoints);
return contourPath.contains(grainLinePath);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPieceGrainline::IsShapeValid() const -> bool
{
GrainlineShape shape = Shape();
return std::ranges::all_of(shape, [](const auto& subShape)
{
return not subShape.isEmpty();
});
}
// Friend functions
//---------------------------------------------------------------------------------------------------------------------
auto operator<<(QDataStream &dataStream, const VPieceGrainline &grainline) -> QDataStream &
{
dataStream << *grainline.d;
return dataStream;
}
//---------------------------------------------------------------------------------------------------------------------
auto operator>>(QDataStream &dataStream, VPieceGrainline &grainline) -> QDataStream &
{
dataStream >> *grainline.d;
return dataStream;
}

View File

@ -0,0 +1,98 @@
/************************************************************************
**
** @file vpiecegrainline.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 27 4, 2023
**
** @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) 2023 Valentina project
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPIECEGRAINLINE_H
#define VPIECEGRAINLINE_H
#include <QSharedDataPointer>
#include <QMetaType>
#include "../vpatterndb/floatItemData/floatitemdef.h"
class QPointF;
class VPieceGrainlinePrivate;
class QLineF;
class QPolygonF;
class QRectF;
using GrainlineShape = QVector<QVector<QPointF>>;
class VPieceGrainline
{
public:
VPieceGrainline();
VPieceGrainline(const QLineF &mainLine, GrainlineArrowDirection arrowType);
VPieceGrainline(const QPointF &p1, qreal length, qreal angle, GrainlineArrowDirection arrowType);
VPieceGrainline(const VPieceGrainline &other);
~VPieceGrainline();
auto operator=(const VPieceGrainline &grainline) -> VPieceGrainline &;
#ifdef Q_COMPILER_RVALUE_REFS
VPieceGrainline(VPieceGrainline &&grainline) Q_DECL_NOTHROW;
auto operator=(VPieceGrainline &&grainline) Q_DECL_NOTHROW -> VPieceGrainline &;
#endif
auto GetMainLine() const -> QLineF;
void SetMainLine(const QLineF &mainLine);
auto GetArrowType() const -> GrainlineArrowDirection;
void SetArrowType(GrainlineArrowDirection arrowType);
auto IsEnabled() const -> bool;
void SetEnabled(bool enabled);
auto SecondaryLine() const -> QLineF;
auto IsFourWays() const -> bool;
auto IsArrowUpEnabled() const -> bool;
auto IsArrowDownEnabled() const -> bool;
auto IsArrowLeftEnabled() const -> bool;
auto IsArrowRightEnabled() const -> bool;
auto ArrowUp() const -> QPolygonF;
auto ArrowDown() const -> QPolygonF;
auto ArrowLeft() const -> QPolygonF;
auto ArrowRight() const -> QPolygonF;
auto Shape() const -> GrainlineShape;
auto IsContained(const QRectF &boundingRect, qreal &dX, qreal &dY) const -> bool;
auto IsPositionValid(const QVector<QPointF> &contourPoints) const -> bool;
auto IsShapeValid() const -> bool;
friend auto operator<< (QDataStream& dataStream, const VPieceGrainline& grainline) -> QDataStream&;
friend auto operator>> (QDataStream& dataStream, VPieceGrainline& grainline) -> QDataStream&;
private:
QSharedDataPointer<VPieceGrainlinePrivate> d;
};
Q_DECLARE_METATYPE(VPieceGrainline)
Q_DECLARE_TYPEINFO(VPieceGrainline, Q_MOVABLE_TYPE); // NOLINT
#endif // VPIECEGRAINLINE_H

View File

@ -0,0 +1,125 @@
/************************************************************************
**
** @file vpiecegrainline_p.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 27 4, 2023
**
** @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) 2023 Valentina project
** <https://gitlab.com/smart-pattern/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPIECEGRAINLINE_P_H
#define VPIECEGRAINLINE_P_H
#include <QLineF>
#include <QSharedData>
#include "../vmisc/defglobal.h"
#include "../ifc/exception/vexception.h"
#include "vpatterndb/floatItemData/floatitemdef.h"
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Weffc++")
QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor")
class VPieceGrainlinePrivate : public QSharedData
{
public:
VPieceGrainlinePrivate(){} // NOLINT(modernize-use-equals-default)
VPieceGrainlinePrivate(const QLineF &mainLine, GrainlineArrowDirection arrowType)
: m_mainLine(mainLine),
m_arrowType(arrowType),
m_enabled(true)
{}
VPieceGrainlinePrivate(const VPieceGrainlinePrivate &data) = default;
~VPieceGrainlinePrivate() = default;
static auto MainLine(const QPointF &p1, qreal length, qreal angle) -> QLineF;
friend auto operator<<(QDataStream& dataStream, const VPieceGrainlinePrivate& data) -> QDataStream&;
friend auto operator>>(QDataStream& dataStream, VPieceGrainlinePrivate& data) -> QDataStream&;
QLineF m_mainLine{}; // NOLINT(misc-non-private-member-variables-in-classes)
GrainlineArrowDirection m_arrowType{GrainlineArrowDirection::oneWayUp}; // NOLINT(misc-non-private-member-variables-in-classes)
bool m_enabled{false}; // NOLINT(misc-non-private-member-variables-in-classes)
private:
Q_DISABLE_ASSIGN_MOVE(VPieceGrainlinePrivate) // NOLINT
static constexpr quint32 streamHeader{0x5C5D5B3B}; // CRC-32Q string "VGrainlineData"
static constexpr quint16 classVersion{1};
};
QT_WARNING_POP
// See https://stackoverflow.com/a/46719572/3045403
#if __cplusplus < 201703L // C++17
constexpr quint32 VPieceGrainlinePrivate::streamHeader; // NOLINT(readability-redundant-declaration)
constexpr quint16 VPieceGrainlinePrivate::classVersion; // NOLINT(readability-redundant-declaration)
#endif
// Friend functions
//---------------------------------------------------------------------------------------------------------------------
inline auto operator<<(QDataStream &dataStream, const VPieceGrainlinePrivate &data) -> QDataStream &
{
dataStream << VPieceGrainlinePrivate::streamHeader << VPieceGrainlinePrivate::classVersion;
// Added in classVersion = 1
dataStream << data.m_enabled;
dataStream << data.m_arrowType;
dataStream << data.m_mainLine;
return dataStream;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto operator>>(QDataStream &dataStream, VPieceGrainlinePrivate &data) -> QDataStream &
{
quint32 actualStreamHeader = 0;
dataStream >> actualStreamHeader;
if (actualStreamHeader != VPieceGrainlinePrivate::streamHeader)
{
QString message = QCoreApplication::tr("VPieceGrainlinePrivate prefix mismatch error: actualStreamHeader = "
"0x%1 and streamHeader = 0x%2")
.arg(actualStreamHeader, 8, 0x10, QChar('0'))
.arg(VPieceGrainlinePrivate::streamHeader, 8, 0x10, QChar('0'));
throw VException(message);
}
quint16 actualClassVersion = 0;
dataStream >> actualClassVersion;
if (actualClassVersion > VPieceGrainlinePrivate::classVersion)
{
QString message = QCoreApplication::tr("VPieceGrainlinePrivate compatibility error: actualClassVersion = %1 "
"and classVersion = %2")
.arg(actualClassVersion).arg(VPieceGrainlinePrivate::classVersion);
throw VException(message);
}
dataStream >> data.m_enabled;
dataStream >> data.m_arrowType;
dataStream >> data.m_mainLine;
return dataStream;
}
#endif // VPIECEGRAINLINE_P_H

View File

@ -28,7 +28,8 @@ SOURCES += \
$$PWD/scalesceneitems.cpp \
$$PWD/vlineedit.cpp \
$$PWD/vplaintextedit.cpp \
$$PWD/vhighlighter.cpp
$$PWD/vhighlighter.cpp \
$$PWD/vpiecegrainline.cpp
*msvc*:SOURCES += $$PWD/stable.cpp
@ -60,4 +61,6 @@ HEADERS += \
$$PWD/scalesceneitems.h \
$$PWD/vlineedit.h \
$$PWD/vplaintextedit.h \
$$PWD/vhighlighter.h
$$PWD/vhighlighter.h \
$$PWD/vpiecegrainline.h \
$$PWD/vpiecegrainline_p.h

View File

@ -4,6 +4,7 @@ VLib {
Depends { name: "Qt"; submodules: ["core", "widgets"] }
Depends { name: "VMiscLib" }
Depends { name: "VPropertyExplorerLib" }
Depends { name: "VPatternDBLib" }
Depends {
name: "Qt.openglwidgets";
@ -65,7 +66,10 @@ VLib {
"scalesceneitems.h",
"vlineedit.h",
"vplaintextedit.h",
"vhighlighter.h"
"vhighlighter.h",
"vpiecegrainline.h",
"vpiecegrainline.cpp",
"vpiecegrainline_p.h"
]
Export {