From 27d61986571f70bc80f44f444fd532d32cf4c55e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 3 Nov 2016 17:59:53 +0200
Subject: [PATCH 001/208] Redesing VDetail class. Meet new classes VPiece and
 VPieceNode.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpatterndb.pri |  10 ++-
 src/libs/vpatterndb/vpiece.cpp     | 132 +++++++++++++++++++++++++++++
 src/libs/vpatterndb/vpiece.h       |  62 ++++++++++++++
 src/libs/vpatterndb/vpiece_p.h     |  68 +++++++++++++++
 src/libs/vpatterndb/vpiecenode.cpp |  96 +++++++++++++++++++++
 src/libs/vpatterndb/vpiecenode.h   |  64 ++++++++++++++
 src/libs/vpatterndb/vpiecenode_p.h |  82 ++++++++++++++++++
 7 files changed, 512 insertions(+), 2 deletions(-)
 create mode 100644 src/libs/vpatterndb/vpiece.cpp
 create mode 100644 src/libs/vpatterndb/vpiece.h
 create mode 100644 src/libs/vpatterndb/vpiece_p.h
 create mode 100644 src/libs/vpatterndb/vpiecenode.cpp
 create mode 100644 src/libs/vpatterndb/vpiecenode.h
 create mode 100644 src/libs/vpatterndb/vpiecenode_p.h

diff --git a/src/libs/vpatterndb/vpatterndb.pri b/src/libs/vpatterndb/vpatterndb.pri
index c1ae5168a..49256369c 100644
--- a/src/libs/vpatterndb/vpatterndb.pri
+++ b/src/libs/vpatterndb/vpatterndb.pri
@@ -21,7 +21,9 @@ SOURCES += \
     $$PWD/vpatternpiecedata.cpp \
     $$PWD/vpatterninfogeometry.cpp \
     $$PWD/vgrainlinegeometry.cpp \
-    $$PWD/variables/vcurveclength.cpp
+    $$PWD/variables/vcurveclength.cpp \
+    $$PWD/vpiece.cpp \
+    $$PWD/vpiecenode.cpp
 
 win32-msvc*:SOURCES += $$PWD/stable.cpp
 
@@ -57,4 +59,8 @@ HEADERS += \
     $$PWD/vpatternpiecedata.h \
     $$PWD/vpatterninfogeometry.h \
     $$PWD/vgrainlinegeometry.h \
-    $$PWD/variables/vcurveclength.h
+    $$PWD/variables/vcurveclength.h \
+    $$PWD/vpiece.h \
+    $$PWD/vpiece_p.h \
+    $$PWD/vpiecenode.h \
+    $$PWD/vpiecenode_p.h
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
new file mode 100644
index 000000000..372231fc0
--- /dev/null
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -0,0 +1,132 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vpiece.h"
+#include "vpiece_p.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece::VPiece()
+    : d(new VPieceData)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece::VPiece(const VPiece &piece)
+    : d (piece.d)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece &VPiece::operator=(const VPiece &piece)
+{
+    if ( &piece == this )
+    {
+        return *this;
+    }
+    d = piece.d;
+    return *this;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece::~VPiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief append append in the end of list node.
+ * @param node new node.
+ */
+void VPiece::Append(const VPieceNode &node)
+{
+    d->nodes.append(node);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/** @brief Clear detail full clear. */
+void VPiece::Clear()
+{
+    ClearNodes();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/** @brief ClearNodes clear list of nodes. */
+void VPiece::ClearNodes()
+{
+    d->nodes.clear();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief CountNode return count nodes.
+ * @return count.
+ */
+qint32 VPiece::CountNode() const
+{
+    return d->nodes.size();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief operator [] find node by index in list.
+ * @param indx index node in list.
+ * @return node
+ */
+VPieceNode &VPiece::operator [](int indx)
+{
+    return d->nodes[indx];
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief at find node by index in list.
+ * @param indx index node in list.
+ * @return const node.
+ */
+const VPieceNode &VPiece::at(int indx) const
+{
+    return d->nodes.at(indx);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief getNodes return list of nodes.
+ * @return list of nodes.
+ */
+QVector<VPieceNode> VPiece::GetNodes() const
+{
+    return d->nodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief setNodes set list of nodes
+ * @param value list of nodes
+ */
+// cppcheck-suppress unusedFunction
+void VPiece::SetNodes(const QVector<VPieceNode> &nodes)
+{
+    d->nodes = nodes;
+}
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
new file mode 100644
index 000000000..90dc2ddc4
--- /dev/null
+++ b/src/libs/vpatterndb/vpiece.h
@@ -0,0 +1,62 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECE_H
+#define VPIECE_H
+
+#include <QtGlobal>
+#include <QSharedDataPointer>
+
+class VPieceData;
+class VPieceNode;
+
+class VPiece
+{
+public:
+    VPiece();
+    VPiece(const VPiece &piece);
+    VPiece &operator=(const VPiece &piece);
+    virtual ~VPiece();
+
+    void   Append(const VPieceNode &node);
+    void   Clear();
+    void   ClearNodes();
+    qint32 CountNode() const;
+
+    VPieceNode & operator[](int indx);
+    const VPieceNode & at ( int indx ) const;
+
+    QVector<VPieceNode> GetNodes() const;
+    void                SetNodes(const QVector<VPieceNode> &nodes);
+private:
+    QSharedDataPointer<VPieceData> d;
+};
+
+Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);
+
+#endif // VPIECE_H
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
new file mode 100644
index 000000000..f673dc340
--- /dev/null
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -0,0 +1,68 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECE_P_H
+#define VPIECE_P_H
+
+#include <QSharedData>
+#include <QVector>
+
+#include "../vmisc/diagnostic.h"
+#include "vpiecenode.h"
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+
+class VPieceData : public QSharedData
+{
+public:
+    VPieceData()
+        : nodes()
+    {}
+
+    VPieceData(const VPieceData &detail)
+        : QSharedData(detail),
+          nodes(detail.nodes)
+    {}
+
+    ~VPieceData();
+
+    /** @brief nodes list detail nodes. */
+    QVector<VPieceNode> nodes;
+
+private:
+    VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
+};
+
+VPieceData::~VPieceData()
+{}
+
+QT_WARNING_POP
+
+#endif // VPIECE_P_H
+
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
new file mode 100644
index 000000000..1b0d4c523
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -0,0 +1,96 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vpiecenode.h"
+#include "vpiecenode_p.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode::VPieceNode()
+    : d(new VPieceNodeData)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode::VPieceNode(quint32 id, Tool typeTool, bool reverse)
+    : d(new VPieceNodeData(id, typeTool, reverse))
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode::VPieceNode(const VPieceNode &node)
+    : d (node.d)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode &VPieceNode::operator=(const VPieceNode &node)
+{
+    if ( &node == this )
+    {
+        return *this;
+    }
+    d = node.d;
+    return *this;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode::~VPieceNode()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 VPieceNode::GetId() const
+{
+    return d->id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetId(quint32 id)
+{
+    d->id = id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+Tool VPieceNode::GetTypeTool() const
+{
+    return d->typeTool;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetTypeTool(Tool value)
+{
+    d->typeTool = value;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VPieceNode::GetReverse() const
+{
+    return d->reverse;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetReverse(bool reverse)
+{
+    d->reverse = reverse;
+}
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
new file mode 100644
index 000000000..385d9bf6b
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -0,0 +1,64 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECENODE_H
+#define VPIECENODE_H
+
+#include <QtGlobal>
+#include <QSharedDataPointer>
+#include <QMetaType>
+
+#include "../vmisc/def.h"
+
+class VPieceNodeData;
+
+class VPieceNode
+{
+public:
+    VPieceNode();
+    VPieceNode(quint32 id, Tool typeTool, bool reverse = false);
+    VPieceNode(const VPieceNode &node);
+    VPieceNode &operator=(const VPieceNode &node);
+    ~VPieceNode();
+
+    quint32 GetId() const;
+    void    SetId(quint32 id);
+
+    Tool GetTypeTool() const;
+    void SetTypeTool(Tool value);
+
+    bool GetReverse() const;
+    void SetReverse(bool reverse);
+private:
+    QSharedDataPointer<VPieceNodeData> d;
+};
+
+Q_DECLARE_METATYPE(VPieceNode)
+Q_DECLARE_TYPEINFO(VPieceNode, Q_MOVABLE_TYPE);
+
+#endif // VPIECENODE_H
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
new file mode 100644
index 000000000..59c0f4ae2
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -0,0 +1,82 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECENODE_P_H
+#define VPIECENODE_P_H
+
+#include <QSharedData>
+#include "../ifc/ifcdef.h"
+#include "../vmisc/diagnostic.h"
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+
+class VPieceNodeData : public QSharedData
+{
+public:
+  VPieceNodeData()
+    : id(NULL_ID),
+      typeTool(Tool::NodePoint),
+      reverse(false)
+  {}
+
+  VPieceNodeData(quint32 id, Tool typeTool, bool reverse)
+      : id(id),
+        typeTool(typeTool),
+        reverse(reverse)
+  {}
+
+  VPieceNodeData (const VPieceNodeData& node)
+      : QSharedData(node),
+        id(node.id),
+        typeTool(node.typeTool),
+        reverse(node.reverse)
+  {}
+
+  ~VPieceNodeData();
+
+  /** @brief id object id. */
+  quint32 id;
+
+  /** @brief typeTool type of tool */
+  Tool typeTool;
+
+  /** @brief reverse true if need reverse points list for node. */
+  bool reverse;
+
+private:
+    VPieceNodeData &operator=(const VPieceNodeData &) Q_DECL_EQ_DELETE;
+};
+
+VPieceNodeData::~VPieceNodeData()
+{}
+
+QT_WARNING_POP
+
+#endif // VPIECENODE_P_H
+

From 22f9fb1e260f26c49e123d37e50e0795d1befc7e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 3 Nov 2016 20:15:53 +0200
Subject: [PATCH 002/208] Added class VAbstractPiece.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 301 ++++++++++++++++++++++++++++
 src/libs/vlayout/vabstractpiece.h   |  53 +++++
 src/libs/vlayout/vlayout.pri        |  10 +-
 src/libs/vpatterndb/vpiece.cpp      | 121 ++++++++++-
 src/libs/vpatterndb/vpiece.h        |  13 +-
 5 files changed, 491 insertions(+), 7 deletions(-)
 create mode 100644 src/libs/vlayout/vabstractpiece.cpp
 create mode 100644 src/libs/vlayout/vabstractpiece.h

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
new file mode 100644
index 000000000..0309df112
--- /dev/null
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -0,0 +1,301 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vabstractpiece.h"
+
+#include <QLineF>
+#include <QSet>
+#include <QVector>
+#include <QDebug>
+
+#include "../vgeometry/vgobject.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VAbstractPiece::VAbstractPiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VAbstractPiece::VAbstractPiece(const VAbstractPiece &piece)
+{
+    Q_UNUSED(piece)
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VAbstractPiece &VAbstractPiece::operator=(const VAbstractPiece &piece)
+{
+    if ( &piece == this )
+    {
+        return *this;
+    }
+    return *this;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VAbstractPiece::~VAbstractPiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
+{
+    // Calculation a polygon area through the sum of the areas of trapezoids
+    qreal s, res = 0;
+    const int n = points.size();
+
+    if(n > 2)
+    {
+        for (int i = 0; i < n; ++i)
+        {
+            if (i == 0)
+            {
+                //if i == 0, then y[i-1] replace on y[n-1]
+                s = points.at(i).x()*(points.at(n-1).y() - points.at(i+1).y());
+                res += s;
+            }
+            else
+            {
+                if (i == n-1)
+                {
+                    // if i == n-1, then y[i+1] replace on y[0]
+                    s = points.at(i).x()*(points.at(i-1).y() - points.at(0).y());
+                    res += s;
+                }
+                else
+                {
+                    s = points.at(i).x()*(points.at(i-1).y() - points.at(i+1).y());
+                    res += s;
+                }
+            }
+        }
+    }
+    return res;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief CheckLoops seek and delete loops in equidistant.
+ * @param points vector of points of equidistant.
+ * @return vector of points of equidistant.
+ */
+QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
+{
+    const int count = points.size();
+    /*If we got less than 4 points no need seek loops.*/
+    if (count < 4)
+    {
+        qDebug()<<"Less then 4 points. Doesn't need check for loops.";
+        return points;
+    }
+
+    const bool pathClosed = (points.first() == points.last());
+
+    QVector<QPointF> ekvPoints;
+
+    qint32 i, j, jNext = 0;
+    for (i = 0; i < count; ++i)
+    {
+        /*Last three points no need check.*/
+        /*Triangle has not contain loops*/
+        if (i > count-3)
+        {
+            ekvPoints.append(points.at(i));
+            continue;
+        }
+
+        enum LoopIntersectType { NoIntersection, BoundedIntersection, ParallelIntersection };
+
+        QPointF crosPoint;
+        LoopIntersectType status = NoIntersection;
+        const QLineF line1(points.at(i), points.at(i+1));
+        // Because a path can contains several loops we will seek the last and only then remove the loop(s)
+        // That's why we parse from the end
+        for (j = count-1; j >= i+2; --j)
+        {
+
+            j == count-1 ? jNext = 0 : jNext = j+1;
+            QLineF line2(points.at(j), points.at(jNext));
+
+            if(qFuzzyIsNull(line2.length()))
+            {//If a path is closed the edge (count-1;0) length will be 0
+                continue;
+            }
+
+            QSet<qint32> uniqueVertices;
+            uniqueVertices << i << i+1 << j;
+
+            // For closed path last point is equal to first. Using index of the first.
+            pathClosed && jNext == count-1 ? uniqueVertices << 0 : uniqueVertices << jNext;
+
+            const QLineF::IntersectType intersect = line1.intersect(line2, &crosPoint);
+            if (intersect == QLineF::NoIntersection)
+            { // According to the documentation QLineF::NoIntersection indicates that the lines do not intersect;
+              // i.e. they are parallel. But parallel also mean they can be on the same line.
+              // Method IsPointOnLineviaPDP will check it.
+                if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1))
+                    // Lines are not neighbors
+                    && uniqueVertices.size() == 4
+                    && line1.p2() != line2.p2()
+                    && line1.p1() != line2.p1()
+                    && line1.p2() != line2.p1()
+                    && line1.p1() != line2.p2())
+                {
+                    // Left to catch case where segments are on the same line, but do not have real intersections.
+                    QLineF tmpLine1 = line1;
+                    QLineF tmpLine2 = line2;
+
+                    tmpLine1.setAngle(tmpLine1.angle()+90);
+
+                    QPointF tmpCrosPoint;
+                    const QLineF::IntersectType tmpIntrs1 = tmpLine1.intersect(tmpLine2, &tmpCrosPoint);
+
+                    tmpLine1 = line1;
+                    tmpLine2.setAngle(tmpLine2.angle()+90);
+
+                    const QLineF::IntersectType tmpIntrs2 = tmpLine1.intersect(tmpLine2, &tmpCrosPoint);
+
+                    if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection)
+                    { // Now we really sure that lines are on the same lines and have real intersections.
+                        status = ParallelIntersection;
+                        break;
+                    }
+                }
+            }
+            else if (intersect == QLineF::BoundedIntersection)
+            {
+                if (uniqueVertices.size() == 4
+                    && line1.p1() != crosPoint
+                    && line1.p2() != crosPoint
+                    && line2.p1() != crosPoint
+                    && line2.p2() != crosPoint)
+                { // Break, but not if lines are neighbors
+                    status = BoundedIntersection;
+                    break;
+                }
+            }
+            status = NoIntersection;
+        }
+
+        switch (status)
+        {
+            case ParallelIntersection:
+                /*We have found a loop.*/
+                // Theoretically there is no big difference which point j or jNext to select.
+                // In the end we will draw a line in any case.
+                ekvPoints.append(points.at(i));
+                ekvPoints.append(points.at(jNext));
+                i = j;
+                break;
+            case BoundedIntersection:
+                /*We have found a loop.*/
+                ekvPoints.append(points.at(i));
+                ekvPoints.append(crosPoint);
+                i = j;
+                break;
+            case NoIntersection:
+                /*We have not found loop.*/
+                ekvPoints.append(points.at(i));
+                break;
+            default:
+                break;
+        }
+    }
+    return ekvPoints;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
+ * @param points list of points equdistant.
+ * @return corrected list.
+ */
+QVector<QPointF> VAbstractPiece::CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast)
+{
+    if (points.size()<4)//Better don't check if only three points. We can destroy equidistant.
+    {
+        qDebug()<<"Only three points.";
+        return points;
+    }
+
+    //Clear equivalent points
+    QVector<QPointF> correctPoints = RemoveDublicates(points, removeFirstAndLast);
+
+    if (correctPoints.size()<3)
+    {
+        return correctPoints;
+    }
+
+    //Remove point on line
+    for (qint32 i = 1; i <correctPoints.size()-1; ++i)
+    {// In this case we alwayse will have bounded intersection, so all is need is to check if point i is on line.
+     // Unfortunatelly QLineF::intersect can't be used in this case because of the floating-point accuraccy problem.
+        if (VGObject::IsPointOnLineviaPDP(correctPoints.at(i), correctPoints.at(i-1), correctPoints.at(i+1)))
+        {
+            correctPoints.remove(i);
+        }
+    }
+
+    return correctPoints;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast)
+{
+    QVector<QPointF> p = points;
+
+    if (removeFirstAndLast)
+    {
+        if (not p.isEmpty() && p.size() > 1)
+        {
+            // Path can't be closed
+            if (p.first() == p.last())
+            {
+            #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+                p.remove(p.size() - 1);
+            #else
+                p.removeLast();
+            #endif
+            }
+        }
+    }
+
+    for (int i = 0; i < p.size()-1; ++i)
+    {
+        if (p.at(i) == p.at(i+1))
+        {
+            if (not removeFirstAndLast && (i == p.size()-1))
+            {
+                continue;
+            }
+
+            p.erase(p.begin() + i + 1);
+            --i;
+            continue;
+        }
+    }
+
+    return p;
+}
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
new file mode 100644
index 000000000..78caab9bd
--- /dev/null
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -0,0 +1,53 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VABSTRACTPIECE_H
+#define VABSTRACTPIECE_H
+
+#include <QtGlobal>
+
+template <class T> class QVector;
+class QPointF;
+
+class VAbstractPiece
+{
+public:
+    VAbstractPiece();
+    VAbstractPiece(const VAbstractPiece &piece);
+    VAbstractPiece &operator=(const VAbstractPiece &piece);
+    virtual ~VAbstractPiece();
+
+    static qreal            SumTrapezoids(const QVector<QPointF> &points);
+    static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
+    static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
+
+protected:
+    static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast = true);
+};
+
+#endif // VABSTRACTPIECE_H
diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri
index 6d82d469f..434680020 100644
--- a/src/libs/vlayout/vlayout.pri
+++ b/src/libs/vlayout/vlayout.pri
@@ -17,8 +17,9 @@ HEADERS += \
     $$PWD/vbestsquare.h \
     $$PWD/vposition.h \
     $$PWD/vtextmanager.h \
-    vposter.h \
-    vgraphicsfillitem.h
+    $$PWD/vposter.h \
+    $$PWD/vgraphicsfillitem.h \
+    $$PWD/vabstractpiece.h
 
 SOURCES += \
     $$PWD/vlayoutgenerator.cpp \
@@ -30,7 +31,8 @@ SOURCES += \
     $$PWD/vbestsquare.cpp \
     $$PWD/vposition.cpp \
     $$PWD/vtextmanager.cpp \
-    vposter.cpp \
-    vgraphicsfillitem.cpp
+    $$PWD/vposter.cpp \
+    $$PWD/vgraphicsfillitem.cpp \
+    $$PWD/vabstractpiece.cpp
 
 win32-msvc*:SOURCES += $$PWD/stable.cpp
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 372231fc0..ef57752f0 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -28,15 +28,21 @@
 
 #include "vpiece.h"
 #include "vpiece_p.h"
+#include "../vgeometry/vpointf.h"
+#include "../vgeometry/vabstractcurve.h"
+#include "vcontainer.h"
+
+#include <QSharedPointer>
+#include <QDebug>
 
 //---------------------------------------------------------------------------------------------------------------------
 VPiece::VPiece()
-    : d(new VPieceData)
+    : VAbstractPiece(), d(new VPieceData)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
 VPiece::VPiece(const VPiece &piece)
-    : d (piece.d)
+    : VAbstractPiece(piece), d (piece.d)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -46,6 +52,7 @@ VPiece &VPiece::operator=(const VPiece &piece)
     {
         return *this;
     }
+    VAbstractPiece::operator=(piece);
     d = piece.d;
     return *this;
 }
@@ -130,3 +137,113 @@ void VPiece::SetNodes(const QVector<VPieceNode> &nodes)
 {
     d->nodes = nodes;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
+{
+    QVector<QPointF> points;
+    for (int i = 0; i < CountNode(); ++i)
+    {
+        switch (at(i).GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
+                points.append(*point);
+            }
+            break;
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+                const QPointF begin = StartSegment(data, i, at(i).GetReverse());
+                const QPointF end = EndSegment(data, i, at(i).GetReverse());
+
+                points << curve->GetSegmentPoints(begin, end, at(i).GetReverse());
+            }
+            break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).GetTypeTool());
+                break;
+        }
+    }
+
+    points = CheckLoops(CorrectEquidistantPoints(points));//A path can contains loops
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
+{
+    if (i < 0 && i > CountNode()-1)
+    {
+        return QPointF();
+    }
+
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+    QVector<QPointF> points = curve->GetPoints();
+    if (reverse)
+    {
+        points = VGObject::GetReversePoints(points);
+    }
+
+    QPointF begin = points.first();
+    if (CountNode() > 1)
+    {
+        if (i == 0)
+        {
+            if (at(CountNode()-1).GetTypeTool() == Tool::NodePoint)
+            {
+                begin = *data->GeometricObject<VPointF>(at(CountNode()-1).GetId());
+            }
+        }
+        else
+        {
+            if (at(i-1).GetTypeTool() == Tool::NodePoint)
+            {
+                begin = *data->GeometricObject<VPointF>(at(i-1).GetId());
+            }
+        }
+    }
+    return begin;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) const
+{
+    if (i < 0 && i > CountNode()-1)
+    {
+        return QPointF();
+    }
+
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+    QVector<QPointF> points = curve->GetPoints();
+    if (reverse)
+    {
+        points = VGObject::GetReversePoints(points);
+    }
+
+    QPointF end = points.last();
+    if (CountNode() > 2)
+    {
+        if (i == CountNode() - 1)
+        {
+            if (at(0).GetTypeTool() == Tool::NodePoint)
+            {
+                end = *data->GeometricObject<VPointF>(at(0).GetId());
+            }
+        }
+        else
+        {
+            if (at(i+1).GetTypeTool() == Tool::NodePoint)
+            {
+                end = *data->GeometricObject<VPointF>(at(i+1).GetId());
+            }
+        }
+    }
+    return end;
+}
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 90dc2ddc4..18c093f6a 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -32,10 +32,15 @@
 #include <QtGlobal>
 #include <QSharedDataPointer>
 
+#include "../vlayout/vabstractpiece.h"
+
 class VPieceData;
 class VPieceNode;
+class QPointF;
+class VContainer;
+template <class T> class QVector;
 
-class VPiece
+class VPiece : public VAbstractPiece
 {
 public:
     VPiece();
@@ -53,8 +58,14 @@ public:
 
     QVector<VPieceNode> GetNodes() const;
     void                SetNodes(const QVector<VPieceNode> &nodes);
+
+    QVector<QPointF> MainPathPoints(const VContainer *data) const;
+
 private:
     QSharedDataPointer<VPieceData> d;
+
+    QPointF StartSegment(const VContainer *data, const int &i, bool reverse) const;
+    QPointF EndSegment(const VContainer *data, const int &i, bool reverse) const;
 };
 
 Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);

From 1dd86e66fb66bf386046761b54212a6c95e8f59c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 16:16:11 +0200
Subject: [PATCH 003/208] New dialog connected to tool button.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp              |  12 +-
 src/libs/vtools/dialogs/dialogs.pri           |  10 +-
 src/libs/vtools/dialogs/tooldialogs.h         |   1 +
 src/libs/vtools/dialogs/tools/dialogdetail.ui |  30 +-
 .../dialogs/tools/dialogseamallowance.cpp     | 290 ++++++++++++++++++
 .../dialogs/tools/dialogseamallowance.h       |  75 +++++
 .../dialogs/tools/dialogseamallowance.ui      | 130 ++++++++
 7 files changed, 520 insertions(+), 28 deletions(-)
 create mode 100644 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
 create mode 100644 src/libs/vtools/dialogs/tools/dialogseamallowance.h
 create mode 100644 src/libs/vtools/dialogs/tools/dialogseamallowance.ui

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 2f678b024..b7053c149 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -935,7 +935,7 @@ void MainWindow::ToolPointOfContact(bool checked)
 void MainWindow::ToolDetail(bool checked)
 {
     ToolSelectAllDrawObjects();
-    SetToolButton<DialogDetail>(checked, Tool::Detail, "://cursor/new_detail_cursor.png",
+    SetToolButton<DialogSeamAllowance>(checked, Tool::Detail, "://cursor/new_detail_cursor.png",
                                 tr("Select points, arcs, curves clockwise."), &MainWindow::ClosedDialogDetail);
 }
 
@@ -946,12 +946,12 @@ void MainWindow::ToolDetail(bool checked)
  */
 void MainWindow::ClosedDialogDetail(int result)
 {
-    if (result == QDialog::Accepted)
-    {
-        VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
-    }
+//    if (result == QDialog::Accepted)
+//    {
+//        VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
+//    }
     ArrowTool();
-    doc->LiteParseTree(Document::LiteParse);
+//    doc->LiteParseTree(Document::LiteParse);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/dialogs/dialogs.pri b/src/libs/vtools/dialogs/dialogs.pri
index 343b5a64c..3c1543155 100644
--- a/src/libs/vtools/dialogs/dialogs.pri
+++ b/src/libs/vtools/dialogs/dialogs.pri
@@ -41,8 +41,8 @@ HEADERS += \
     $$PWD/tools/dialogrotation.h \
     $$PWD/tools/dialogflippingbyline.h \
     $$PWD/tools/dialogflippingbyaxis.h \
-    $$PWD/tools/dialogmove.h
-
+    $$PWD/tools/dialogmove.h \
+    $$PWD/tools/dialogseamallowance.h
 
 SOURCES += \
     $$PWD/tools/dialogalongline.cpp \
@@ -83,7 +83,8 @@ SOURCES += \
     $$PWD/tools/dialogrotation.cpp \
     $$PWD/tools/dialogflippingbyline.cpp \
     $$PWD/tools/dialogflippingbyaxis.cpp \
-    $$PWD/tools/dialogmove.cpp
+    $$PWD/tools/dialogmove.cpp \
+    $$PWD/tools/dialogseamallowance.cpp
 
 FORMS += \
     $$PWD/tools/dialogalongline.ui \
@@ -123,4 +124,5 @@ FORMS += \
     $$PWD/tools/dialogrotation.ui \
     $$PWD/tools/dialogflippingbyline.ui \
     $$PWD/tools/dialogflippingbyaxis.ui \
-    $$PWD/tools/dialogmove.ui
+    $$PWD/tools/dialogmove.ui \
+    $$PWD/tools/dialogseamallowance.ui
diff --git a/src/libs/vtools/dialogs/tooldialogs.h b/src/libs/vtools/dialogs/tooldialogs.h
index 23f99447c..d7f859cc1 100644
--- a/src/libs/vtools/dialogs/tooldialogs.h
+++ b/src/libs/vtools/dialogs/tooldialogs.h
@@ -34,6 +34,7 @@
 #include "tools/dialogarcwithlength.h"
 #include "tools/dialogbisector.h"
 #include "tools/dialogdetail.h"
+#include "tools/dialogseamallowance.h"
 #include "tools/dialogendline.h"
 #include "tools/dialogline.h"
 #include "tools/dialoglineintersect.h"
diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.ui b/src/libs/vtools/dialogs/tools/dialogdetail.ui
index 7198fcea0..699792160 100644
--- a/src/libs/vtools/dialogs/tools/dialogdetail.ui
+++ b/src/libs/vtools/dialogs/tools/dialogdetail.ui
@@ -14,7 +14,7 @@
    <string>Seam allowance tool</string>
   </property>
   <property name="windowIcon">
-   <iconset resource="../../../vmisc/share/resources/icon.qrc">
+   <iconset>
     <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
   </property>
   <property name="locale">
@@ -24,7 +24,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>2</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tab">
       <attribute name="title">
@@ -45,7 +45,7 @@
             <string/>
            </property>
            <property name="pixmap">
-            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/32x32/clockwise.png</pixmap>
+            <pixmap>:/icon/32x32/clockwise.png</pixmap>
            </property>
           </widget>
          </item>
@@ -318,8 +318,7 @@
                   </property>
                   <property name="icon">
                    <iconset theme="go-down">
-                    <normaloff/>
-                   </iconset>
+                    <normaloff>.</normaloff>.</iconset>
                   </property>
                  </widget>
                 </item>
@@ -333,8 +332,7 @@
                   </property>
                   <property name="icon">
                    <iconset theme="go-up">
-                    <normaloff/>
-                   </iconset>
+                    <normaloff>.</normaloff>.</iconset>
                   </property>
                  </widget>
                 </item>
@@ -636,7 +634,7 @@
            <string notr="true">...</string>
           </property>
           <property name="icon">
-           <iconset resource="../../../vmisc/share/resources/icon.qrc">
+           <iconset>
             <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
           </property>
           <property name="iconSize">
@@ -653,7 +651,7 @@
            <string/>
           </property>
           <property name="pixmap">
-           <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+           <pixmap>:/icon/24x24/equal.png</pixmap>
           </property>
          </widget>
         </item>
@@ -744,8 +742,7 @@
           </property>
           <property name="icon">
            <iconset theme="go-down">
-            <normaloff/>
-           </iconset>
+            <normaloff>.</normaloff>.</iconset>
           </property>
           <property name="iconSize">
            <size>
@@ -842,7 +839,7 @@
            <string notr="true">...</string>
           </property>
           <property name="icon">
-           <iconset resource="../../../vmisc/share/resources/icon.qrc">
+           <iconset>
             <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
           </property>
           <property name="iconSize">
@@ -859,7 +856,7 @@
            <string/>
           </property>
           <property name="pixmap">
-           <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+           <pixmap>:/icon/24x24/equal.png</pixmap>
           </property>
          </widget>
         </item>
@@ -950,8 +947,7 @@
           </property>
           <property name="icon">
            <iconset theme="go-down">
-            <normaloff/>
-           </iconset>
+            <normaloff>.</normaloff>.</iconset>
           </property>
           <property name="iconSize">
            <size>
@@ -1082,9 +1078,7 @@
   <tabstop>checkBoxPattern</tabstop>
   <tabstop>lineEditLetter</tabstop>
  </tabstops>
- <resources>
-  <include location="../../../vmisc/share/resources/icon.qrc"/>
- </resources>
+ <resources/>
  <connections>
   <connection>
    <sender>buttonBox</sender>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
new file mode 100644
index 000000000..d4f083ec0
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -0,0 +1,290 @@
+/************************************************************************
+ **
+ **  @file   dialogseamallowance.cpp
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "dialogseamallowance.h"
+#include "ui_dialogseamallowance.h"
+#include "../vpatterndb/vpiecenode.h"
+
+#include <QBuffer>
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent)
+    : DialogTool(data, toolId, parent),
+      ui(new Ui::DialogSeamAllowance),
+      m_piece()
+{
+    ui->setupUi(this);
+
+    InitOkCancelApply(ui);
+
+    flagName = true;//We have default name of piece.
+    flagError = MainPathIsValid();
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogSeamAllowance::~DialogSeamAllowance()
+{
+    delete ui;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece DialogSeamAllowance::GetPiece() const
+{
+    return m_piece;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetPiece(const VPiece &piece)
+{
+    m_piece = piece;
+    ui->listWidget->clear();
+    for (int i = 0; i < m_piece.CountNode(); ++i)
+    {
+        NewItem(m_piece.at(i));
+    }
+
+    ValidObjects(MainPathIsValid());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief ChoosedObject gets id and type of selected object. Save right data and ignore wrong.
+ * @param id id of objects (points, arcs, splines, spline paths)
+ * @param type type of object
+ */
+void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
+{
+    bool reverse = false;
+    switch (type)
+    {
+        case SceneObject::Arc:
+            NewItem(VPieceNode(id, Tool::NodeArc, reverse));
+            break;
+        case SceneObject::Point:
+            NewItem(VPieceNode(id, Tool::NodePoint, reverse));
+            break;
+        case SceneObject::Spline:
+            NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
+            break;
+        case SceneObject::SplinePath:
+            NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+            break;
+        case (SceneObject::Line):
+        case (SceneObject::Detail):
+        case (SceneObject::Unknown):
+        default:
+            qDebug() << "Got wrong scene object. Ignore.";
+            break;
+    }
+
+    ValidObjects(MainPathIsValid());
+    show();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SaveData()
+{
+    m_piece.Clear();
+    m_piece = CreatePiece();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::CheckState()
+{
+    SCASSERT(bOk != nullptr);
+    bOk->setEnabled(flagName && flagError);
+    // In case dialog hasn't apply button
+    if ( bApply != nullptr)
+    {
+        bApply->setEnabled(bOk->isEnabled());
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiece DialogSeamAllowance::CreatePiece() const
+{
+    VPiece piece;
+    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidget->item(i);
+        piece.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
+    }
+
+    return piece;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::NewItem(const VPieceNode &node)
+{
+    SCASSERT(node.GetId() > NULL_ID);
+    QString name;
+    switch (node.GetTypeTool())
+    {
+        case (Tool::NodePoint):
+        case (Tool::NodeArc):
+        case (Tool::NodeSpline):
+        case (Tool::NodeSplinePath):
+        {
+            const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(node.GetId());
+            name = obj->name();
+            break;
+        }
+        default:
+            qDebug()<<"Got wrong tools. Ignore.";
+            return;
+    }
+
+    if (node.GetReverse())
+    {
+        name = QLatin1String("- ") + name;
+    }
+
+    bool canAddNewPoint = false;
+
+    if(ui->listWidget->count() == 0)
+    {
+        canAddNewPoint = true;
+    }
+    else
+    {
+        if(RowId(ui->listWidget->count()-1) != node.GetId())
+        {
+            canAddNewPoint = true;
+        }
+    }
+
+    if(canAddNewPoint)
+    {
+        QListWidgetItem *item = new QListWidgetItem(name);
+        item->setFont(QFont("Times", 12, QFont::Bold));
+        item->setData(Qt::UserRole, QVariant::fromValue(node));
+        ui->listWidget->addItem(item);
+        ui->listWidget->setCurrentRow(ui->listWidget->count()-1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 DialogSeamAllowance::RowId(int i) const
+{
+    const QListWidgetItem *rowItem = ui->listWidget->item(i);
+    SCASSERT(rowItem != nullptr);
+    const VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+    return rowNode.GetId();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogSeamAllowance::MainPathIsValid() const
+{
+    const QIcon icon = QIcon::fromTheme("dialog-warning",
+                                  QIcon(":/icons/win.icon.theme/16x16/status/dialog-warning.png"));
+
+    const QPixmap pixmap = icon.pixmap(QSize(16, 16));
+    QByteArray byteArray;
+    QBuffer buffer(&byteArray);
+    pixmap.save(&buffer, "PNG");
+    QString url = QString("<img src=\"data:image/png;base64,") + byteArray.toBase64() + QLatin1String("\"/> ");
+
+    if(CreatePiece().MainPathPoints(data).count() < 3)
+    {
+        url += tr("You need more points!");
+        ui->helpLabel->setText(url);
+        return false;
+    }
+    else
+    {
+        if(not MainPathIsClockwise())
+        {
+            url += tr("You have to choose points in a clockwise direction!");
+            ui->helpLabel->setText(url);
+            return false;
+        }
+        if (FirstPointEqualLast())
+        {
+            url += tr("First point cannot be equal to the last point!");
+            ui->helpLabel->setText(url);
+            return false;
+        }
+        else
+        {
+            for (int i=0, sz = ui->listWidget->count()-1; i<sz; ++i)
+            {
+                if (RowId(i) == RowId(i+1))
+                {
+                    url += tr("You have double points!");
+                    ui->helpLabel->setText(url);
+                    return false;
+                }
+            }
+        }
+    }
+    ui->helpLabel->setText(tr("Ready!"));
+    return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ValidObjects(bool value)
+{
+    flagError = value;
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogSeamAllowance::FirstPointEqualLast() const
+{
+    if (ui->listWidget->count() > 1)
+    {
+        if (RowId(0) == RowId(ui->listWidget->count()-1))
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogSeamAllowance::MainPathIsClockwise() const
+{
+    const QVector<QPointF> points = CreatePiece().MainPathPoints(data);
+
+    if(points.count() < 3)
+    {
+        return false;
+    }
+
+    const qreal res = VPiece::SumTrapezoids(points);
+    if (res < 0)
+    {
+        return true;
+    }
+    return false;
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
new file mode 100644
index 000000000..478d98548
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -0,0 +1,75 @@
+/************************************************************************
+ **
+ **  @file   dialogseamallowance.h
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   3 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 DIALOGSEAMALLOWANCE_H
+#define DIALOGSEAMALLOWANCE_H
+
+#include "dialogtool.h"
+#include "../vpatterndb/vpiece.h"
+
+namespace Ui
+{
+    class DialogSeamAllowance;
+}
+
+class DialogSeamAllowance : public DialogTool
+{
+    Q_OBJECT
+
+public:
+    DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent = nullptr);
+    virtual ~DialogSeamAllowance();
+
+    VPiece GetPiece() const;
+    void   SetPiece(const VPiece &m_piece);
+
+public slots:
+    virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
+
+protected:
+    /** @brief SaveData Put dialog data in local variables */
+    virtual void SaveData() Q_DECL_OVERRIDE;
+    virtual void CheckState() Q_DECL_OVERRIDE;
+
+private:
+    Q_DISABLE_COPY(DialogSeamAllowance)
+
+    Ui::DialogSeamAllowance *ui;
+    VPiece m_piece;
+
+    VPiece CreatePiece() const;
+
+    void    NewItem(const VPieceNode &node);
+    quint32 RowId(int i) const;
+    bool    MainPathIsValid() const;
+    void    ValidObjects(bool value);
+    bool    FirstPointEqualLast() const;
+    bool    MainPathIsClockwise() const;
+};
+
+#endif // DIALOGSEAMALLOWANCE_H
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
new file mode 100644
index 000000000..810e28537
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogSeamAllowance</class>
+ <widget class="QDialog" name="DialogSeamAllowance">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>559</width>
+    <height>423</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../../../vmisc/share/resources/icon.qrc">
+    <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tabMainPath">
+      <attribute name="title">
+       <string>Main path</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_8">
+         <item>
+          <widget class="QLabel" name="label_3">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+           <property name="pixmap">
+            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/32x32/clockwise.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="label_4">
+           <property name="text">
+            <string>All objects in path should follow in clockwise direction.</string>
+           </property>
+           <property name="wordWrap">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QListWidget" name="listWidget"/>
+       </item>
+       <item>
+        <widget class="QLabel" name="helpLabel">
+         <property name="text">
+          <string>Ready!</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::RichText</enum>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../../vmisc/share/resources/icon.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>DialogSeamAllowance</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>DialogSeamAllowance</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

From a378922bf61c49539475737e7b36436403c2fe62 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 16:25:01 +0200
Subject: [PATCH 004/208] Piece Node point can't be reversed.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode.cpp | 5 ++++-
 src/libs/vpatterndb/vpiecenode_p.h | 7 ++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index 1b0d4c523..26e5b414a 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -92,5 +92,8 @@ bool VPieceNode::GetReverse() const
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetReverse(bool reverse)
 {
-    d->reverse = reverse;
+    if (d->typeTool != Tool::NodePoint)
+    {
+        d->reverse = reverse;
+    }
 }
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index 59c0f4ae2..5417aa138 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -49,7 +49,12 @@ public:
       : id(id),
         typeTool(typeTool),
         reverse(reverse)
-  {}
+  {
+      if (typeTool == Tool::NodePoint)
+      {
+          reverse = false;
+      }
+  }
 
   VPieceNodeData (const VPieceNodeData& node)
       : QSharedData(node),

From e261d02f89e06d6439d3823b9edd9df095850a90 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 16:25:57 +0200
Subject: [PATCH 005/208] Check keyboard modificator and add object reversed if
 pressed Shift.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index d4f083ec0..0871d2646 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -81,13 +81,17 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
 void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
 {
     bool reverse = false;
+    if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier)
+    {
+        reverse = true;
+    }
     switch (type)
     {
         case SceneObject::Arc:
             NewItem(VPieceNode(id, Tool::NodeArc, reverse));
             break;
         case SceneObject::Point:
-            NewItem(VPieceNode(id, Tool::NodePoint, reverse));
+            NewItem(VPieceNode(id, Tool::NodePoint));
             break;
         case SceneObject::Spline:
             NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
@@ -160,7 +164,7 @@ void DialogSeamAllowance::NewItem(const VPieceNode &node)
             return;
     }
 
-    if (node.GetReverse())
+    if (node.GetTypeTool() != Tool::NodePoint && node.GetReverse())
     {
         name = QLatin1String("- ") + name;
     }

From 721d447af120ac3fbd02a8d58d93a104e64351cd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 16:28:10 +0200
Subject: [PATCH 006/208] Refactor member names VPieceNode class.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode.cpp | 14 +++++++-------
 src/libs/vpatterndb/vpiecenode_p.h | 28 ++++++++++++++--------------
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index 26e5b414a..b2e5bbba3 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -62,38 +62,38 @@ VPieceNode::~VPieceNode()
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VPieceNode::GetId() const
 {
-    return d->id;
+    return d->m_id;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetId(quint32 id)
 {
-    d->id = id;
+    d->m_id = id;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 Tool VPieceNode::GetTypeTool() const
 {
-    return d->typeTool;
+    return d->m_typeTool;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetTypeTool(Tool value)
 {
-    d->typeTool = value;
+    d->m_typeTool = value;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 bool VPieceNode::GetReverse() const
 {
-    return d->reverse;
+    return d->m_reverse;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetReverse(bool reverse)
 {
-    if (d->typeTool != Tool::NodePoint)
+    if (d->m_typeTool != Tool::NodePoint)
     {
-        d->reverse = reverse;
+        d->m_reverse = reverse;
     }
 }
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index 5417aa138..bdc54abb8 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -40,39 +40,39 @@ class VPieceNodeData : public QSharedData
 {
 public:
   VPieceNodeData()
-    : id(NULL_ID),
-      typeTool(Tool::NodePoint),
-      reverse(false)
+    : m_id(NULL_ID),
+      m_typeTool(Tool::NodePoint),
+      m_reverse(false)
   {}
 
   VPieceNodeData(quint32 id, Tool typeTool, bool reverse)
-      : id(id),
-        typeTool(typeTool),
-        reverse(reverse)
+      : m_id(id),
+        m_typeTool(typeTool),
+        m_reverse(reverse)
   {
-      if (typeTool == Tool::NodePoint)
+      if (m_typeTool == Tool::NodePoint)
       {
-          reverse = false;
+          m_reverse = false;
       }
   }
 
   VPieceNodeData (const VPieceNodeData& node)
       : QSharedData(node),
-        id(node.id),
-        typeTool(node.typeTool),
-        reverse(node.reverse)
+        m_id(node.m_id),
+        m_typeTool(node.m_typeTool),
+        m_reverse(node.m_reverse)
   {}
 
   ~VPieceNodeData();
 
   /** @brief id object id. */
-  quint32 id;
+  quint32 m_id;
 
   /** @brief typeTool type of tool */
-  Tool typeTool;
+  Tool m_typeTool;
 
   /** @brief reverse true if need reverse points list for node. */
-  bool reverse;
+  bool m_reverse;
 
 private:
     VPieceNodeData &operator=(const VPieceNodeData &) Q_DECL_EQ_DELETE;

From eb84ae7526a10ab2f1bf8a6d9a63e5cd9e293a8c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 17:04:18 +0200
Subject: [PATCH 007/208] Added list context menu with options Delete and
 Reverse (except for point).

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 65 +++++++++++++++++--
 .../dialogs/tools/dialogseamallowance.h       |  4 ++
 2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 0871d2646..fa1ef109f 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -31,6 +31,7 @@
 #include "../vpatterndb/vpiecenode.h"
 
 #include <QBuffer>
+#include <QMenu>
 
 //---------------------------------------------------------------------------------------------------------------------
 DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent)
@@ -45,6 +46,9 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     flagName = true;//We have default name of piece.
     flagError = MainPathIsValid();
     CheckState();
+
+    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -130,6 +134,45 @@ void DialogSeamAllowance::CheckState()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
+{
+    const int row = ui->listWidget->currentRow();
+    if (ui->listWidget->count() == 0 || row == -1 || row >= ui->listWidget->count())
+    {
+        return;
+    }
+
+    QMenu *menu = new QMenu(this);
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+
+    QListWidgetItem *rowItem = ui->listWidget->item(row);
+    SCASSERT(rowItem != nullptr);
+    VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+
+    QAction *actionReverse = nullptr;
+    if (rowNode.GetTypeTool() != Tool::NodePoint)
+    {
+        actionReverse = menu->addAction(tr("Reverse"));
+        actionReverse->setCheckable(true);
+        actionReverse->setChecked(rowNode.GetReverse());
+    }
+
+    QAction *selectedAction = menu->exec(ui->listWidget->viewport()->mapToGlobal(pos));
+    if (selectedAction == actionDelete)
+    {
+        delete ui->listWidget->item(row);
+        ValidObjects(MainPathIsValid());
+    }
+    else if (selectedAction == actionReverse)
+    {
+        rowNode.SetReverse(not rowNode.GetReverse());
+        rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+        rowItem->setText(GetNodeName(rowNode));
+        ValidObjects(MainPathIsValid());
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::CreatePiece() const
 {
@@ -155,8 +198,7 @@ void DialogSeamAllowance::NewItem(const VPieceNode &node)
         case (Tool::NodeSpline):
         case (Tool::NodeSplinePath):
         {
-            const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(node.GetId());
-            name = obj->name();
+            name = GetNodeName(node);
             break;
         }
         default:
@@ -164,10 +206,7 @@ void DialogSeamAllowance::NewItem(const VPieceNode &node)
             return;
     }
 
-    if (node.GetTypeTool() != Tool::NodePoint && node.GetReverse())
-    {
-        name = QLatin1String("- ") + name;
-    }
+
 
     bool canAddNewPoint = false;
 
@@ -292,3 +331,17 @@ bool DialogSeamAllowance::MainPathIsClockwise() const
     }
     return false;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetNodeName(const VPieceNode &node) const
+{
+    const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(node.GetId());
+    QString name = obj->name();
+
+    if (node.GetTypeTool() != Tool::NodePoint && node.GetReverse())
+    {
+        name = QLatin1String("- ") + name;
+    }
+
+    return name;
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 478d98548..ff1095a72 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -56,6 +56,9 @@ protected:
     virtual void SaveData() Q_DECL_OVERRIDE;
     virtual void CheckState() Q_DECL_OVERRIDE;
 
+private slots:
+    void ShowContextMenu(const QPoint &pos);
+
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
 
@@ -70,6 +73,7 @@ private:
     void    ValidObjects(bool value);
     bool    FirstPointEqualLast() const;
     bool    MainPathIsClockwise() const;
+    QString GetNodeName(const VPieceNode &node) const;
 };
 
 #endif // DIALOGSEAMALLOWANCE_H

From f40bf977c820147a78886c523455274227caa82d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 17:34:15 +0200
Subject: [PATCH 008/208] Enable internal move in the list. Helps user quickly
 make reorder.

--HG--
branch : feature
---
 src/app/valentina/main.cpp                    |  3 +++
 src/libs/vpatterndb/vpiecenode.cpp            | 21 +++++++++++++++++++
 src/libs/vpatterndb/vpiecenode.h              |  3 +++
 .../dialogs/tools/dialogseamallowance.ui      |  6 +++++-
 4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/app/valentina/main.cpp b/src/app/valentina/main.cpp
index 60348d25f..8016abe6b 100644
--- a/src/app/valentina/main.cpp
+++ b/src/app/valentina/main.cpp
@@ -29,6 +29,7 @@
 #include "mainwindow.h"
 #include "core/vapplication.h"
 #include "../fervor/fvupdater.h"
+#include "../vpatterndb/vpiecenode.h"
 
 #include <QMessageBox> // For QT_REQUIRE_VERSION
 #include <QTimer>
@@ -53,6 +54,8 @@ int main(int argc, char *argv[])
 
     qt_qhash_seed.store(0); // Lock producing random attribute order in XML
 
+    qRegisterMetaTypeStreamOperators<VPieceNode>("VPieceNode");
+
 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
     QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
 #endif
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index b2e5bbba3..f238e2f65 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -97,3 +97,24 @@ void VPieceNode::SetReverse(bool reverse)
         d->m_reverse = reverse;
     }
 }
+
+// Friend functions
+//---------------------------------------------------------------------------------------------------------------------
+QDataStream& operator<<(QDataStream& out, const VPieceNode& p)
+{
+    out << p.d->m_id << static_cast<int>(p.d->m_typeTool) << p.d->m_reverse;
+    return out;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDataStream& operator>>(QDataStream& in, VPieceNode& p)
+{
+    in >> p.d->m_id;
+
+    int type = 0;
+    in >> type;
+    p.d->m_typeTool = static_cast<Tool>(type);
+
+    in >> p.d->m_reverse;
+    return in;
+}
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 385d9bf6b..62e3ad3fd 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -46,6 +46,9 @@ public:
     VPieceNode &operator=(const VPieceNode &node);
     ~VPieceNode();
 
+    friend QDataStream& operator<<(QDataStream& out, const VPieceNode& p);
+    friend QDataStream& operator>>(QDataStream& in, VPieceNode& p);
+
     quint32 GetId() const;
     void    SetId(quint32 id);
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 810e28537..78d9d7889 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -59,7 +59,11 @@
         </layout>
        </item>
        <item>
-        <widget class="QListWidget" name="listWidget"/>
+        <widget class="QListWidget" name="listWidget">
+         <property name="dragDropMode">
+          <enum>QAbstractItemView::InternalMove</enum>
+         </property>
+        </widget>
        </item>
        <item>
         <widget class="QLabel" name="helpLabel">

From f8ee078ef7950a897763fb991d9d1ca263831ad0 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 4 Nov 2016 19:36:36 +0200
Subject: [PATCH 009/208] When user creates new piece button Apply should be
 disabled.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogseamallowance.cpp   | 14 ++++++++++++--
 .../vtools/dialogs/tools/dialogseamallowance.h     |  3 +++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index fa1ef109f..b2c93467c 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -37,11 +37,13 @@
 DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
       ui(new Ui::DialogSeamAllowance),
-      m_piece()
+      m_piece(),
+      applyAllowed(false)// By default disabled
 {
     ui->setupUi(this);
 
     InitOkCancelApply(ui);
+    EnableApply(applyAllowed);
 
     flagName = true;//We have default name of piece.
     flagError = MainPathIsValid();
@@ -57,6 +59,14 @@ DialogSeamAllowance::~DialogSeamAllowance()
     delete ui;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EnableApply(bool enable)
+{
+    SCASSERT(bApply != nullptr);
+    bApply->setEnabled(enable);
+    applyAllowed = enable;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::GetPiece() const
 {
@@ -128,7 +138,7 @@ void DialogSeamAllowance::CheckState()
     SCASSERT(bOk != nullptr);
     bOk->setEnabled(flagName && flagError);
     // In case dialog hasn't apply button
-    if ( bApply != nullptr)
+    if ( bApply != nullptr && applyAllowed)
     {
         bApply->setEnabled(bOk->isEnabled());
     }
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index ff1095a72..beb4c2477 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -45,6 +45,8 @@ public:
     DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent = nullptr);
     virtual ~DialogSeamAllowance();
 
+    void EnableApply(bool enable);
+
     VPiece GetPiece() const;
     void   SetPiece(const VPiece &m_piece);
 
@@ -64,6 +66,7 @@ private:
 
     Ui::DialogSeamAllowance *ui;
     VPiece m_piece;
+    bool   applyAllowed;
 
     VPiece CreatePiece() const;
 

From 65a38141dede61e00b090bab0a1e67367d3ef755 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 5 Nov 2016 10:56:44 +0200
Subject: [PATCH 010/208] Added class VisToolPiece.

Show visualization creating piece main path.

--HG--
branch : feature
---
 src/libs/vmisc/def.h                          |  3 +-
 src/libs/vpatterndb/vpiece.cpp                | 46 ++++++++++++
 src/libs/vpatterndb/vpiece.h                  |  4 ++
 .../line/operation/visoperation.cpp           | 12 +---
 .../visualization/path/vistoolpiece.cpp       | 72 +++++++++++++++++++
 .../vtools/visualization/path/vistoolpiece.h  | 57 +++++++++++++++
 .../vtools/visualization/visualization.cpp    | 46 +++++++++---
 src/libs/vtools/visualization/visualization.h |  9 ++-
 .../vtools/visualization/visualization.pri    |  6 +-
 9 files changed, 229 insertions(+), 26 deletions(-)
 create mode 100644 src/libs/vtools/visualization/path/vistoolpiece.cpp
 create mode 100644 src/libs/vtools/visualization/path/vistoolpiece.h

diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index e2f3a8ae1..debc5166b 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -158,7 +158,8 @@ enum class Vis : ToolVisHolderType
     ToolRotation,
     ToolFlippingByLine,
     ToolFlippingByAxis,
-    ToolMove
+    ToolMove,
+    ToolPiece
 };
 
 enum class VarType : char { Measurement, Increment, LineLength, CurveLength, CurveCLength, LineAngle, CurveAngle,
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index ef57752f0..6c7c31709 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -34,6 +34,7 @@
 
 #include <QSharedPointer>
 #include <QDebug>
+#include <QPainterPath>
 
 //---------------------------------------------------------------------------------------------------------------------
 VPiece::VPiece()
@@ -174,6 +175,51 @@ QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
     return points;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VPiece::MainPathNodePoints(const VContainer *data) const
+{
+    QVector<QPointF> points;
+    for (int i = 0; i < CountNode(); ++i)
+    {
+        switch (at(i).GetTypeTool())
+        {
+            case Tool::NodePoint:
+            {
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
+                points.append(*point);
+            }
+            break;
+            case Tool::NodeArc:
+            case Tool::NodeSpline:
+            case Tool::NodeSplinePath:
+            default:
+                break;
+        }
+    }
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPainterPath VPiece::MainPathPath(const VContainer *data) const
+{
+    const QVector<QPointF> points = MainPathPoints(data);
+    QPainterPath path;
+
+    if (not points.isEmpty())
+    {
+        path.moveTo(points[0]);
+        for (qint32 i = 1; i < points.count(); ++i)
+        {
+            path.lineTo(points.at(i));
+        }
+        path.lineTo(points.at(0));
+        path.setFillRule(Qt::WindingFill);
+    }
+
+    return path;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 18c093f6a..13541f829 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -34,6 +34,7 @@
 
 #include "../vlayout/vabstractpiece.h"
 
+class QPainterPath;
 class VPieceData;
 class VPieceNode;
 class QPointF;
@@ -60,6 +61,9 @@ public:
     void                SetNodes(const QVector<VPieceNode> &nodes);
 
     QVector<QPointF> MainPathPoints(const VContainer *data) const;
+    QVector<QPointF> MainPathNodePoints(const VContainer *data) const;
+
+    QPainterPath MainPathPath(const VContainer *data) const;
 
 private:
     QSharedDataPointer<VPieceData> d;
diff --git a/src/libs/vtools/visualization/line/operation/visoperation.cpp b/src/libs/vtools/visualization/line/operation/visoperation.cpp
index c581fc91e..b80f78d34 100644
--- a/src/libs/vtools/visualization/line/operation/visoperation.cpp
+++ b/src/libs/vtools/visualization/line/operation/visoperation.cpp
@@ -78,17 +78,7 @@ void VisOperation::VisualMode(const quint32 &pointId)
 //---------------------------------------------------------------------------------------------------------------------
 QGraphicsEllipseItem *VisOperation::GetPoint(quint32 i, const QColor &color)
 {
-    if (not points.isEmpty() && static_cast<quint32>(points.size() - 1) >= i)
-    {
-        return points.at(static_cast<int>(i));
-    }
-    else
-    {
-        auto point = InitPoint(color, this);
-        points.append(point);
-        return point;
-    }
-    return nullptr;
+    return GetPointItem(Visualization::data, factor, points, i, color, this);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
new file mode 100644
index 000000000..8507dd41a
--- /dev/null
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -0,0 +1,72 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   5 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vistoolpiece.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VisToolPiece::VisToolPiece(const VContainer *data, QGraphicsItem *parent)
+    : VisPath(data, parent),
+      m_points(),
+      m_piece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VisToolPiece::~VisToolPiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiece::RefreshGeometry()
+{
+    if (m_piece.CountNode() > 0)
+    {
+        DrawPath(this, m_piece.MainPathPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
+
+        const QVector<QPointF> nodes = m_piece.MainPathNodePoints(Visualization::data);
+
+        for (int i = 0; i < nodes.size(); ++i)
+        {
+            QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
+            DrawPoint(point, nodes.at(i), supportColor);
+        }
+
+        Visualization::toolTip = tr("Select main path objects, <b>Shift</b> - reverse direction curves, "
+                                    "<b>Enter</b> - finish creation");
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiece::SetPiece(const VPiece &piece)
+{
+    m_piece = piece;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QGraphicsEllipseItem *VisToolPiece::GetPoint(quint32 i, const QColor &color)
+{
+    return GetPointItem(Visualization::data, factor, m_points, i, color, this);
+}
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.h b/src/libs/vtools/visualization/path/vistoolpiece.h
new file mode 100644
index 000000000..da9e23919
--- /dev/null
+++ b/src/libs/vtools/visualization/path/vistoolpiece.h
@@ -0,0 +1,57 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   5 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VISTOOLPIECE_H
+#define VISTOOLPIECE_H
+
+#include <QtCore/QObject>
+#include <QtGlobal>
+
+#include "vispath.h"
+#include "../vpatterndb/vpiece.h"
+
+class VisToolPiece : public VisPath
+{
+    Q_OBJECT
+public:
+    VisToolPiece(const VContainer *data, QGraphicsItem *parent = nullptr);
+    virtual ~VisToolPiece();
+
+    virtual void RefreshGeometry() Q_DECL_OVERRIDE;
+    void         SetPiece(const VPiece &piece);
+    virtual int  type() const Q_DECL_OVERRIDE {return Type;}
+    enum { Type = UserType + static_cast<int>(Vis::ToolPiece)};
+private:
+    Q_DISABLE_COPY(VisToolPiece)
+    QVector<QGraphicsEllipseItem *> m_points;
+    VPiece m_piece;
+
+    QGraphicsEllipseItem* GetPoint(quint32 i, const QColor &color);
+};
+
+#endif // VISTOOLPIECE_H
diff --git a/src/libs/vtools/visualization/visualization.cpp b/src/libs/vtools/visualization/visualization.cpp
index fabfca5f5..e77ca4089 100644
--- a/src/libs/vtools/visualization/visualization.cpp
+++ b/src/libs/vtools/visualization/visualization.cpp
@@ -141,20 +141,11 @@ void Visualization::MousePos(const QPointF &scenePos)
 //---------------------------------------------------------------------------------------------------------------------
 QGraphicsEllipseItem *Visualization::InitPoint(const QColor &color, QGraphicsItem *parent, qreal z) const
 {
-    QGraphicsEllipseItem *point = new QGraphicsEllipseItem(parent);
-    point->setZValue(1);
-    point->setBrush(QBrush(Qt::NoBrush));
-    point->setPen(QPen(color, qApp->toPixel(WidthMainLine(*Visualization::data->GetPatternUnit()))/factor));
-    point->setRect(PointRect(ToPixel(DefPointRadius/*mm*/, Unit::Mm)));
-    point->setPos(QPointF());
-    point->setFlags(QGraphicsItem::ItemStacksBehindParent);
-    point->setZValue(z);
-    point->setVisible(false);
-    return point;
+    return InitPointItem(Visualization::data, factor, color, parent, z);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QRectF Visualization::PointRect(const qreal &radius) const
+QRectF Visualization::PointRect(qreal radius)
 {
     QRectF rec = QRectF(0, 0, radius*2, radius*2);
     rec.translate(-rec.center().x(), -rec.center().y());
@@ -236,6 +227,39 @@ void Visualization::DrawPath(QGraphicsPathItem *pathItem, const QPainterPath &pa
     pathItem->setVisible(true);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QGraphicsEllipseItem *Visualization::GetPointItem(const VContainer *data, qreal factor,
+                                                  QVector<QGraphicsEllipseItem *> &points, quint32 i,
+                                                  const QColor &color, QGraphicsItem *parent)
+{
+    if (not points.isEmpty() && static_cast<quint32>(points.size() - 1) >= i)
+    {
+        return points.at(static_cast<int>(i));
+    }
+    else
+    {
+        auto point = InitPointItem(data, factor, color, parent);
+        points.append(point);
+        return point;
+    }
+    return nullptr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QGraphicsEllipseItem *Visualization::InitPointItem(const VContainer *data, qreal factor, const QColor &color,
+                                                   QGraphicsItem *parent, qreal z)
+{
+    QGraphicsEllipseItem *point = new QGraphicsEllipseItem(parent);
+    point->setZValue(1);
+    point->setBrush(QBrush(Qt::NoBrush));
+    point->setPen(QPen(color, qApp->toPixel(WidthMainLine(*data->GetPatternUnit()))/factor));
+    point->setRect(PointRect(ToPixel(DefPointRadius/*mm*/, Unit::Mm)));
+    point->setPos(QPointF());
+    point->setFlags(QGraphicsItem::ItemStacksBehindParent);
+    point->setZValue(z);
+    point->setVisible(false);
+    return point;
+}
 
 //---------------------------------------------------------------------------------------------------------------------
 Mode Visualization::GetMode() const
diff --git a/src/libs/vtools/visualization/visualization.h b/src/libs/vtools/visualization/visualization.h
index d2e08ccd0..5a18d1a4b 100644
--- a/src/libs/vtools/visualization/visualization.h
+++ b/src/libs/vtools/visualization/visualization.h
@@ -84,7 +84,6 @@ protected:
     virtual void AddOnScene()=0;
 
     QGraphicsEllipseItem *InitPoint(const QColor &color, QGraphicsItem *parent, qreal z = 0) const;
-    QRectF       PointRect(const qreal &radius) const;
     void         DrawPoint(QGraphicsEllipseItem *point, const QPointF &pos, const QColor &color,
                            Qt::PenStyle style = Qt::SolidLine);
     virtual void DrawLine(QGraphicsLineItem *lineItem, const QLineF &line, const QColor &color,
@@ -97,8 +96,16 @@ protected:
 
     template <class Item>
     Item         *InitItem(const QColor &color, QGraphicsItem *parent);
+
+    static QRectF                PointRect(qreal radius);
+    static QGraphicsEllipseItem* GetPointItem(const VContainer *data, qreal factor,
+                                              QVector<QGraphicsEllipseItem *> &points, quint32 i, const QColor &color,
+                                              QGraphicsItem *parent);
 private:
     Q_DISABLE_COPY(Visualization)
+
+    static QGraphicsEllipseItem* InitPointItem(const VContainer *data, qreal factor, const QColor &color,
+                                               QGraphicsItem *parent, qreal z = 0);
 };
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/visualization/visualization.pri b/src/libs/vtools/visualization/visualization.pri
index 7eee605f6..7f16b5713 100644
--- a/src/libs/vtools/visualization/visualization.pri
+++ b/src/libs/vtools/visualization/visualization.pri
@@ -37,7 +37,8 @@ HEADERS += \
     $$PWD/path/vistoolcubicbezierpath.h \
     $$PWD/line/operation/visoperation.h \
     $$PWD/line/operation/vistoolflippingbyaxis.h \
-    $$PWD/line/operation/vistoolmove.h
+    $$PWD/line/operation/vistoolmove.h \
+    $$PWD/path/vistoolpiece.h
 
 SOURCES += \
     $$PWD/visualization.cpp \
@@ -75,4 +76,5 @@ SOURCES += \
     $$PWD/path/vistoolcubicbezierpath.cpp \
     $$PWD/line/operation/visoperation.cpp \
     $$PWD/line/operation/vistoolflippingbyaxis.cpp \
-    $$PWD/line/operation/vistoolmove.cpp
+    $$PWD/line/operation/vistoolmove.cpp \
+    $$PWD/path/vistoolpiece.cpp

From bf306f6101addd9db6ef763033034e15846ade55 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 5 Nov 2016 12:49:20 +0200
Subject: [PATCH 011/208] The visualization connected to tool dialog.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp              |  2 +-
 .../dialogs/tools/dialogseamallowance.cpp     | 32 ++++++++++++++++++-
 .../dialogs/tools/dialogseamallowance.h       |  1 +
 .../visualization/path/vistoolpiece.cpp       |  3 --
 4 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 65c9e5186..83f54631d 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -936,7 +936,7 @@ void MainWindow::ToolDetail(bool checked)
 {
     ToolSelectAllDrawObjects();
     SetToolButton<DialogSeamAllowance>(checked, Tool::Detail, "://cursor/new_detail_cursor.png",
-                                tr("Select points, arcs, curves clockwise."), &MainWindow::ClosedDialogDetail);
+                                tr("Select main path objects clockwise."), &MainWindow::ClosedDialogDetail);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index b2c93467c..52f02e3c3 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -29,6 +29,7 @@
 #include "dialogseamallowance.h"
 #include "ui_dialogseamallowance.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "visualization/path/vistoolpiece.h"
 
 #include <QBuffer>
 #include <QMenu>
@@ -51,6 +52,8 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
 
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
+
+    vis = new VisToolPiece(data);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -122,7 +125,34 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
     }
 
     ValidObjects(MainPathIsValid());
-    show();
+
+    auto visPath = qobject_cast<VisToolPiece *>(vis);
+    SCASSERT(visPath != nullptr);
+    const VPiece p = CreatePiece();
+    visPath->SetPiece(p);
+
+    if (p.CountNode() == 1)
+    {
+        emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
+                        "<b>Enter</b> - finish creation"));
+
+        visPath->VisualMode(NULL_ID);
+    }
+    else
+    {
+        visPath->RefreshGeometry();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ShowDialog(bool click)
+{
+    if (click == false)
+    {
+        emit ToolTip("");
+        setModal(true);
+        show();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index beb4c2477..c9134338a 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -52,6 +52,7 @@ public:
 
 public slots:
     virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
+    virtual void ShowDialog(bool click) Q_DECL_OVERRIDE;
 
 protected:
     /** @brief SaveData Put dialog data in local variables */
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index 8507dd41a..98cbea37d 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -53,9 +53,6 @@ void VisToolPiece::RefreshGeometry()
             QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
             DrawPoint(point, nodes.at(i), supportColor);
         }
-
-        Visualization::toolTip = tr("Select main path objects, <b>Shift</b> - reverse direction curves, "
-                                    "<b>Enter</b> - finish creation");
     }
 }
 

From b7def444ef1f15492364c20eb2f66623aa387417 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 5 Nov 2016 14:08:26 +0200
Subject: [PATCH 012/208] Visialization. Highlight first and last point of main
 path.

--HG--
branch : feature
---
 .../vtools/visualization/path/vistoolpiece.cpp    | 15 ++++++++++++++-
 src/libs/vtools/visualization/path/vistoolpiece.h |  3 +++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index 98cbea37d..3ae7e9b14 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -32,8 +32,13 @@
 VisToolPiece::VisToolPiece(const VContainer *data, QGraphicsItem *parent)
     : VisPath(data, parent),
       m_points(),
+      m_line1(nullptr),
+      m_line2(nullptr),
       m_piece()
-{}
+{
+    m_line1 = InitItem<QGraphicsLineItem>(supportColor, this);
+    m_line2 = InitItem<QGraphicsLineItem>(supportColor, this);
+}
 
 //---------------------------------------------------------------------------------------------------------------------
 VisToolPiece::~VisToolPiece()
@@ -53,6 +58,14 @@ void VisToolPiece::RefreshGeometry()
             QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
             DrawPoint(point, nodes.at(i), supportColor);
         }
+
+        const QVector<QPointF> points = m_piece.MainPathPoints(Visualization::data);
+        DrawLine(m_line1, QLineF(points.first(), Visualization::scenePos), supportColor, Qt::DashLine);
+
+        if (points.size() > 1)
+        {
+            DrawLine(m_line2, QLineF(points.last(), Visualization::scenePos), supportColor, Qt::DashLine);
+        }
     }
 }
 
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.h b/src/libs/vtools/visualization/path/vistoolpiece.h
index da9e23919..f647924a2 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.h
+++ b/src/libs/vtools/visualization/path/vistoolpiece.h
@@ -49,6 +49,9 @@ public:
 private:
     Q_DISABLE_COPY(VisToolPiece)
     QVector<QGraphicsEllipseItem *> m_points;
+
+    QGraphicsLineItem *m_line1;
+    QGraphicsLineItem *m_line2;
     VPiece m_piece;
 
     QGraphicsEllipseItem* GetPoint(quint32 i, const QColor &color);

From bff5462ef3b423b812ffcce6a3ca9782b68c6fa0 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 5 Nov 2016 15:27:19 +0200
Subject: [PATCH 013/208] Changes in dialog: reverse and internal move update
 the visualization automatically.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 103 +++++++++++-------
 .../dialogs/tools/dialogseamallowance.h       |   1 +
 .../visualization/path/vistoolpiece.cpp       |  38 ++++++-
 .../vtools/visualization/path/vistoolpiece.h  |   2 +
 4 files changed, 99 insertions(+), 45 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 52f02e3c3..34156dce2 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -52,6 +52,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
 
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
+    connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
 
     vis = new VisToolPiece(data);
 }
@@ -97,50 +98,53 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
  */
 void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
 {
-    bool reverse = false;
-    if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier)
+    if (not prepare)
     {
-        reverse = true;
-    }
-    switch (type)
-    {
-        case SceneObject::Arc:
-            NewItem(VPieceNode(id, Tool::NodeArc, reverse));
-            break;
-        case SceneObject::Point:
-            NewItem(VPieceNode(id, Tool::NodePoint));
-            break;
-        case SceneObject::Spline:
-            NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
-            break;
-        case SceneObject::SplinePath:
-            NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
-            break;
-        case (SceneObject::Line):
-        case (SceneObject::Detail):
-        case (SceneObject::Unknown):
-        default:
-            qDebug() << "Got wrong scene object. Ignore.";
-            break;
-    }
+        bool reverse = false;
+        if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier)
+        {
+            reverse = true;
+        }
+        switch (type)
+        {
+            case SceneObject::Arc:
+                NewItem(VPieceNode(id, Tool::NodeArc, reverse));
+                break;
+            case SceneObject::Point:
+                NewItem(VPieceNode(id, Tool::NodePoint));
+                break;
+            case SceneObject::Spline:
+                NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
+                break;
+            case SceneObject::SplinePath:
+                NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+                break;
+            case (SceneObject::Line):
+            case (SceneObject::Detail):
+            case (SceneObject::Unknown):
+            default:
+                qDebug() << "Got wrong scene object. Ignore.";
+                break;
+        }
 
-    ValidObjects(MainPathIsValid());
+        ValidObjects(MainPathIsValid());
 
-    auto visPath = qobject_cast<VisToolPiece *>(vis);
-    SCASSERT(visPath != nullptr);
-    const VPiece p = CreatePiece();
-    visPath->SetPiece(p);
+        auto visPath = qobject_cast<VisToolPiece *>(vis);
+        SCASSERT(visPath != nullptr);
+        const VPiece p = CreatePiece();
+        visPath->SetPiece(p);
 
-    if (p.CountNode() == 1)
-    {
-        emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
-                        "<b>Enter</b> - finish creation"));
+        if (p.CountNode() == 1)
+        {
+            emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
+                            "<b>Enter</b> - finish creation"));
 
-        visPath->VisualMode(NULL_ID);
-    }
-    else
-    {
-        visPath->RefreshGeometry();
+            visPath->VisualMode(NULL_ID);
+        }
+        else
+        {
+            visPath->RefreshGeometry();
+        }
     }
 }
 
@@ -150,7 +154,15 @@ void DialogSeamAllowance::ShowDialog(bool click)
     if (click == false)
     {
         emit ToolTip("");
-        setModal(true);
+        prepare = true;
+
+        auto visPath = qobject_cast<VisToolPiece *>(vis);
+        SCASSERT(visPath != nullptr);
+        visPath->SetMode(Mode::Show);
+        visPath->RefreshGeometry();
+
+        // Fix issue #526. Dialog Detail is not on top after selection second object on Mac.
+        setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
         show();
     }
 }
@@ -211,6 +223,17 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
         rowItem->setText(GetNodeName(rowNode));
         ValidObjects(MainPathIsValid());
     }
+
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ListChanged()
+{
+    auto visPath = qobject_cast<VisToolPiece *>(vis);
+    SCASSERT(visPath != nullptr);
+    visPath->SetPiece(CreatePiece());
+    visPath->RefreshGeometry();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index c9134338a..5657147a5 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -61,6 +61,7 @@ protected:
 
 private slots:
     void ShowContextMenu(const QPoint &pos);
+    void ListChanged();
 
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index 3ae7e9b14..f085d8e59 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -47,6 +47,8 @@ VisToolPiece::~VisToolPiece()
 //---------------------------------------------------------------------------------------------------------------------
 void VisToolPiece::RefreshGeometry()
 {
+    HideAllItems();
+
     if (m_piece.CountNode() > 0)
     {
         DrawPath(this, m_piece.MainPathPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
@@ -59,12 +61,15 @@ void VisToolPiece::RefreshGeometry()
             DrawPoint(point, nodes.at(i), supportColor);
         }
 
-        const QVector<QPointF> points = m_piece.MainPathPoints(Visualization::data);
-        DrawLine(m_line1, QLineF(points.first(), Visualization::scenePos), supportColor, Qt::DashLine);
-
-        if (points.size() > 1)
+        if (mode == Mode::Creation)
         {
-            DrawLine(m_line2, QLineF(points.last(), Visualization::scenePos), supportColor, Qt::DashLine);
+            const QVector<QPointF> points = m_piece.MainPathPoints(Visualization::data);
+            DrawLine(m_line1, QLineF(points.first(), Visualization::scenePos), supportColor, Qt::DashLine);
+
+            if (points.size() > 1)
+            {
+                DrawLine(m_line2, QLineF(points.last(), Visualization::scenePos), supportColor, Qt::DashLine);
+            }
         }
     }
 }
@@ -80,3 +85,26 @@ QGraphicsEllipseItem *VisToolPiece::GetPoint(quint32 i, const QColor &color)
 {
     return GetPointItem(Visualization::data, factor, m_points, i, color, this);
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiece::HideAllItems()
+{
+    if (m_line1)
+    {
+        m_line1->setVisible(false);
+    }
+
+    if (m_line2)
+    {
+        m_line2->setVisible(false);
+    }
+
+    QVector<QGraphicsEllipseItem *> m_points;
+    for (int i=0; i < m_points.size(); ++i)
+    {
+        if (QGraphicsEllipseItem *item = m_points.at(i))
+        {
+            item->setVisible(false);
+        }
+    }
+}
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.h b/src/libs/vtools/visualization/path/vistoolpiece.h
index f647924a2..a9071d5e4 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.h
+++ b/src/libs/vtools/visualization/path/vistoolpiece.h
@@ -55,6 +55,8 @@ private:
     VPiece m_piece;
 
     QGraphicsEllipseItem* GetPoint(quint32 i, const QColor &color);
+
+    void HideAllItems();
 };
 
 #endif // VISTOOLPIECE_H

From 2ed35461b6ba9cd56c8592821e63f6d09b5c023f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 5 Nov 2016 15:31:20 +0200
Subject: [PATCH 014/208] Forbid delete objects if user is creating a piece.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 34156dce2..d3cf319e6 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -197,6 +197,7 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
 
     QMenu *menu = new QMenu(this);
     QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+    actionDelete->setEnabled(applyAllowed);//Because we can't undo this operation when creating a piece.
 
     QListWidgetItem *rowItem = ui->listWidget->item(row);
     SCASSERT(rowItem != nullptr);

From 977b52b787eb9d5caab18d149ec9016d41eceb48 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 12:52:07 +0200
Subject: [PATCH 015/208] VContainer supports working with VPiece class.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.cpp | 35 ++++++++++++++++++++++++++++++
 src/libs/vpatterndb/vcontainer.h   |  7 ++++++
 2 files changed, 42 insertions(+)

diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index 5661de0c3..93f74e225 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -166,6 +166,19 @@ const VDetail VContainer::GetDetail(quint32 id) const
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VPiece VContainer::GetPiece(quint32 id) const
+{
+    if (d->pieces->contains(id))
+    {
+        return d->pieces->value(id);
+    }
+    else
+    {
+        throw VExceptionBadId(tr("Can't find object"), id);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief AddGObject add new GObject to container
@@ -193,6 +206,14 @@ quint32 VContainer::AddDetail(const VDetail &detail)
     return id;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 VContainer::AddPiece(const VPiece &detail)
+{
+    const quint32 id = getNextId();
+    d->pieces->insert(id, detail);
+    return id;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VContainer::getId()
 {
@@ -500,6 +521,14 @@ void VContainer::UpdateDetail(quint32 id, const VDetail &detail)
     UpdateId(id);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VContainer::UpdatePiece(quint32 id, const VPiece &detail)
+{
+    Q_ASSERT_X(id != NULL_ID, Q_FUNC_INFO, "id == 0"); //-V654 //-V712
+    d->pieces->insert(id, detail);
+    UpdateId(id);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VContainer::GetTableValue(const QString &name, MeasurementsType patternType) const
 {
@@ -734,6 +763,12 @@ const QHash<quint32, VDetail> *VContainer::DataDetails() const
     return d->details.data();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+const QHash<quint32, VPiece> *VContainer::DataPieces() const
+{
+    return d->pieces.data();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 const QHash<QString, QSharedPointer<VInternalVariable> > *VContainer::DataVariables() const
 {
diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index 028d763ce..1ffe87e33 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -54,6 +54,7 @@
 #include "variables.h"
 #include "variables/vinternalvariable.h"
 #include "vdetail.h"
+#include "vpiece.h"
 #include "vtranslatevars.h"
 
 class VAbstractCubicBezierPath;
@@ -81,6 +82,7 @@ public:
         : gObjects(QHash<quint32, QSharedPointer<VGObject> >()),
           variables(QHash<QString, QSharedPointer<VInternalVariable> > ()),
           details(QSharedPointer<QHash<quint32, VDetail>>(new QHash<quint32, VDetail>())),
+          pieces(QSharedPointer<QHash<quint32, VPiece>>(new QHash<quint32, VPiece>())),
           trVars(trVars), patternUnit(patternUnit)
     {}
 
@@ -108,6 +110,7 @@ public:
      * @brief details container of details
      */
     QSharedPointer<QHash<quint32, VDetail>> details;
+    QSharedPointer<QHash<quint32, VPiece>> pieces;
 
     const VTranslateVars *trVars;
     const Unit *patternUnit;
@@ -135,6 +138,7 @@ public:
     const QSharedPointer<VGObject> GetGObject(quint32 id) const;
     static const QSharedPointer<VGObject> GetFakeGObject(quint32 id);
     const VDetail      GetDetail(quint32 id) const;
+    VPiece             GetPiece(quint32 id) const;
     qreal              GetTableValue(const QString& name, MeasurementsType patternType) const;
     template <typename T>
     QSharedPointer<T>  GetVariable(QString name) const;
@@ -144,6 +148,7 @@ public:
 
     quint32            AddGObject(VGObject *obj);
     quint32            AddDetail(const VDetail &detail);
+    quint32            AddPiece(const VPiece &detail);
     void               AddLine(const quint32 &firstPointId, const quint32 &secondPointId);
     void               AddArc(const QSharedPointer<VArc> &arc, const quint32 &arcId, const quint32 &parentId = NULL_ID);
     void               AddSpline(const QSharedPointer<VAbstractBezier> &curve, quint32 id, quint32 parentId = NULL_ID);
@@ -156,6 +161,7 @@ public:
 
     void               UpdateGObject(quint32 id, VGObject* obj);
     void               UpdateDetail(quint32 id, const VDetail &detail);
+    void               UpdatePiece(quint32 id, const VPiece &detail);
 
     void               Clear();
     void               ClearForFullParse();
@@ -178,6 +184,7 @@ public:
 
     const QHash<quint32, QSharedPointer<VGObject> >         *DataGObjects() const;
     const QHash<quint32, VDetail>                           *DataDetails() const;
+    const QHash<quint32, VPiece>                            *DataPieces() const;
     const QHash<QString, QSharedPointer<VInternalVariable>> *DataVariables() const;
 
     const QMap<QString, QSharedPointer<VMeasurement> >  DataMeasurements() const;

From 37173fb0e4f9b838e5c8b71009728d8f68bf6cee Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 12:53:14 +0200
Subject: [PATCH 016/208] VPiece class. Added members for storing a piece
 position.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 58 ++++++++++++++++++++++++----------
 src/libs/vpatterndb/vpiece.h   |  8 ++++-
 src/libs/vpatterndb/vpiece_p.h | 13 ++++++--
 3 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 6c7c31709..5a44c47ae 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -69,7 +69,7 @@ VPiece::~VPiece()
  */
 void VPiece::Append(const VPieceNode &node)
 {
-    d->nodes.append(node);
+    d->m_nodes.append(node);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -83,7 +83,7 @@ void VPiece::Clear()
 /** @brief ClearNodes clear list of nodes. */
 void VPiece::ClearNodes()
 {
-    d->nodes.clear();
+    d->m_nodes.clear();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -91,9 +91,9 @@ void VPiece::ClearNodes()
  * @brief CountNode return count nodes.
  * @return count.
  */
-qint32 VPiece::CountNode() const
+qint32 VPiece::CountNodes() const
 {
-    return d->nodes.size();
+    return d->m_nodes.size();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -104,7 +104,7 @@ qint32 VPiece::CountNode() const
  */
 VPieceNode &VPiece::operator [](int indx)
 {
-    return d->nodes[indx];
+    return d->m_nodes[indx];
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -115,7 +115,7 @@ VPieceNode &VPiece::operator [](int indx)
  */
 const VPieceNode &VPiece::at(int indx) const
 {
-    return d->nodes.at(indx);
+    return d->m_nodes.at(indx);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -125,7 +125,7 @@ const VPieceNode &VPiece::at(int indx) const
  */
 QVector<VPieceNode> VPiece::GetNodes() const
 {
-    return d->nodes;
+    return d->m_nodes;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -136,14 +136,14 @@ QVector<VPieceNode> VPiece::GetNodes() const
 // cppcheck-suppress unusedFunction
 void VPiece::SetNodes(const QVector<VPieceNode> &nodes)
 {
-    d->nodes = nodes;
+    d->m_nodes = nodes;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
 {
     QVector<QPointF> points;
-    for (int i = 0; i < CountNode(); ++i)
+    for (int i = 0; i < CountNodes(); ++i)
     {
         switch (at(i).GetTypeTool())
         {
@@ -179,7 +179,7 @@ QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
 QVector<QPointF> VPiece::MainPathNodePoints(const VContainer *data) const
 {
     QVector<QPointF> points;
-    for (int i = 0; i < CountNode(); ++i)
+    for (int i = 0; i < CountNodes(); ++i)
     {
         switch (at(i).GetTypeTool())
         {
@@ -220,10 +220,34 @@ QPainterPath VPiece::MainPathPath(const VContainer *data) const
     return path;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPiece::GetMx() const
+{
+    return d->m_mx;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetMx(qreal value)
+{
+    d->m_mx = value;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPiece::GetMy() const
+{
+    return d->m_my;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetMy(qreal value)
+{
+    d->m_my = value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
 {
-    if (i < 0 && i > CountNode()-1)
+    if (i < 0 && i > CountNodes()-1)
     {
         return QPointF();
     }
@@ -237,13 +261,13 @@ QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse)
     }
 
     QPointF begin = points.first();
-    if (CountNode() > 1)
+    if (CountNodes() > 1)
     {
         if (i == 0)
         {
-            if (at(CountNode()-1).GetTypeTool() == Tool::NodePoint)
+            if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
             {
-                begin = *data->GeometricObject<VPointF>(at(CountNode()-1).GetId());
+                begin = *data->GeometricObject<VPointF>(at(CountNodes()-1).GetId());
             }
         }
         else
@@ -260,7 +284,7 @@ QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse)
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) const
 {
-    if (i < 0 && i > CountNode()-1)
+    if (i < 0 && i > CountNodes()-1)
     {
         return QPointF();
     }
@@ -274,9 +298,9 @@ QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) c
     }
 
     QPointF end = points.last();
-    if (CountNode() > 2)
+    if (CountNodes() > 2)
     {
-        if (i == CountNode() - 1)
+        if (i == CountNodes() - 1)
         {
             if (at(0).GetTypeTool() == Tool::NodePoint)
             {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 13541f829..4ae3a267a 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -52,7 +52,7 @@ public:
     void   Append(const VPieceNode &node);
     void   Clear();
     void   ClearNodes();
-    qint32 CountNode() const;
+    qint32 CountNodes() const;
 
     VPieceNode & operator[](int indx);
     const VPieceNode & at ( int indx ) const;
@@ -65,6 +65,12 @@ public:
 
     QPainterPath MainPathPath(const VContainer *data) const;
 
+    qreal GetMx() const;
+    void  SetMx(qreal value);
+
+    qreal GetMy() const;
+    void  SetMy(qreal value);
+
 private:
     QSharedDataPointer<VPieceData> d;
 
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index f673dc340..79001e36a 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -42,18 +42,25 @@ class VPieceData : public QSharedData
 {
 public:
     VPieceData()
-        : nodes()
+        : m_nodes(),
+          m_mx(0),
+          m_my(0)
     {}
 
     VPieceData(const VPieceData &detail)
         : QSharedData(detail),
-          nodes(detail.nodes)
+          m_nodes(detail.m_nodes),
+          m_mx(detail.m_mx),
+          m_my(detail.m_my)
     {}
 
     ~VPieceData();
 
     /** @brief nodes list detail nodes. */
-    QVector<VPieceNode> nodes;
+    QVector<VPieceNode> m_nodes;
+
+    qreal m_mx;
+    qreal m_my;
 
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;

From 2b75519d666de0377995127ec5be8cca0d2b1944 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 12:54:33 +0200
Subject: [PATCH 017/208] Undocommand "add piece".

--HG--
branch : feature
---
 src/libs/vtools/undocommands/addpiece.cpp     | 111 ++++++++++++++++++
 src/libs/vtools/undocommands/addpiece.h       |  69 +++++++++++
 src/libs/vtools/undocommands/undocommands.pri |   6 +-
 src/libs/vtools/undocommands/vundocommand.cpp |  10 ++
 src/libs/vtools/undocommands/vundocommand.h   |   2 +
 5 files changed, 196 insertions(+), 2 deletions(-)
 create mode 100644 src/libs/vtools/undocommands/addpiece.cpp
 create mode 100644 src/libs/vtools/undocommands/addpiece.h

diff --git a/src/libs/vtools/undocommands/addpiece.cpp b/src/libs/vtools/undocommands/addpiece.cpp
new file mode 100644
index 000000000..e9d96e56c
--- /dev/null
+++ b/src/libs/vtools/undocommands/addpiece.cpp
@@ -0,0 +1,111 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   6 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "addpiece.h"
+#include "../vpatterndb/vpiecenode.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+AddPiece::AddPiece(const QDomElement &xml, VAbstractPattern *doc, const VPiece &detail, const QString &drawName,
+                   QUndoCommand *parent)
+    : VUndoCommand(xml, doc, parent),
+      m_detail(detail),
+      m_drawName(drawName)
+{
+    setText(tr("add detail"));
+    nodeId = doc->GetParametrId(xml);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+AddPiece::~AddPiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void AddPiece::undo()
+{
+    qCDebug(vUndo, "Undo.");
+
+    QDomElement details = GetDetailsSection();
+    if (not details.isNull())
+    {
+        QDomElement domElement = doc->elementById(nodeId);
+        if (domElement.isElement())
+        {
+            if (details.removeChild(domElement).isNull())
+            {
+                qCDebug(vUndo, "Can't delete node");
+                return;
+            }
+
+            DecrementReferences(m_detail.GetNodes());
+        }
+        else
+        {
+            qCDebug(vUndo, "Can't get node by id = %u.", nodeId);
+            return;
+        }
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagDetails));
+        return;
+    }
+    emit NeedFullParsing();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void AddPiece::redo()
+{
+    qCDebug(vUndo, "Redo.");
+
+    QDomElement details = GetDetailsSection();
+    if (not details.isNull())
+    {
+        details.appendChild(xml);
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagDetails));
+        return;
+    }
+    RedoFullParsing();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement AddPiece::GetDetailsSection() const
+{
+    QDomElement details;
+    if (m_drawName.isEmpty())
+    {
+        doc->GetActivNodeElement(VAbstractPattern::TagDetails, details);
+    }
+    else
+    {
+        details = doc->GetDraw(m_drawName).firstChildElement(VAbstractPattern::TagDetails);
+    }
+    return details;
+}
diff --git a/src/libs/vtools/undocommands/addpiece.h b/src/libs/vtools/undocommands/addpiece.h
new file mode 100644
index 000000000..f04c6c7a6
--- /dev/null
+++ b/src/libs/vtools/undocommands/addpiece.h
@@ -0,0 +1,69 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   6 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 ADDPIECE_H
+#define ADDPIECE_H
+
+#include <qcompilerdetection.h>
+#include <QDomElement>
+#include <QMetaObject>
+#include <QObject>
+#include <QString>
+#include <QtGlobal>
+
+#include "../tools/vtoolseamallowance.h"
+#include "vpiece.h"
+#include "vundocommand.h"
+
+class QDomElement;
+class QUndoCommand;
+class VAbstractPattern;
+
+
+class AddPiece : public VUndoCommand
+{
+    Q_OBJECT
+public:
+    AddPiece(const QDomElement &xml, VAbstractPattern *doc, const VPiece &detail, const QString &drawName = QString(),
+             QUndoCommand *parent = nullptr);
+    virtual ~AddPiece();
+
+    // cppcheck-suppress unusedFunction
+    virtual void undo() Q_DECL_OVERRIDE;
+    // cppcheck-suppress unusedFunction
+    virtual void redo() Q_DECL_OVERRIDE;
+private:
+    Q_DISABLE_COPY(AddPiece)
+
+    VPiece m_detail;
+    QString m_drawName;
+
+    QDomElement GetDetailsSection() const;
+};
+
+#endif // ADDPIECE_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index 216944bb2..fe6ec5f59 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -23,7 +23,8 @@ HEADERS += \
     $$PWD/delgroup.h \
     $$PWD/label/moveabstractlabel.h \
     $$PWD/toggledetailinlayout.h \
-    $$PWD/label/operationmovelabel.h
+    $$PWD/label/operationmovelabel.h \
+    $$PWD/addpiece.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -47,4 +48,5 @@ SOURCES += \
     $$PWD/delgroup.cpp \
     $$PWD/label/moveabstractlabel.cpp \
     $$PWD/toggledetailinlayout.cpp \
-    $$PWD/label/operationmovelabel.cpp
+    $$PWD/label/operationmovelabel.cpp \
+    $$PWD/addpiece.cpp
diff --git a/src/libs/vtools/undocommands/vundocommand.cpp b/src/libs/vtools/undocommands/vundocommand.cpp
index a9b56b076..51a3ccd4c 100644
--- a/src/libs/vtools/undocommands/vundocommand.cpp
+++ b/src/libs/vtools/undocommands/vundocommand.cpp
@@ -33,6 +33,7 @@
 #include "../ifc/ifcdef.h"
 #include "../vmisc/def.h"
 #include "../vpatterndb/vnodedetail.h"
+#include "../vpatterndb/vpiecenode.h"
 
 class QDomElement;
 class QDomNode;
@@ -92,3 +93,12 @@ void VUndoCommand::DecrementReferences(const QVector<VNodeDetail> &nodes) const
         doc->DecrementReferens(nodes.at(i).getId());
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::DecrementReferences(const QVector<VPieceNode> &nodes) const
+{
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        doc->DecrementReferens(nodes.at(i).GetId());
+    }
+}
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index 31cd57570..9d92a1f0e 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -65,6 +65,7 @@ enum class UndoCommand: char { AddPatternPiece,
                              };
 
 class VNodeDetail;
+class VPieceNode;
 class VPattern;
 
 class VUndoCommand : public QObject, public QUndoCommand
@@ -87,6 +88,7 @@ protected:
 
     void         IncrementReferences(const QVector<VNodeDetail> &nodes) const;
     void         DecrementReferences(const QVector<VNodeDetail> &nodes) const;
+    void         DecrementReferences(const QVector<VPieceNode> &nodes) const;
 private:
     Q_DISABLE_COPY(VUndoCommand)
 };

From 721b9b638b2578858fde450bcaa6a75295d44ed9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 12:55:57 +0200
Subject: [PATCH 018/208] Fixed VPiece class method name. CountNode ->
 CountNodes.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 4 ++--
 src/libs/vtools/visualization/path/vistoolpiece.cpp   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index d3cf319e6..d37e136ea 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -82,7 +82,7 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
 {
     m_piece = piece;
     ui->listWidget->clear();
-    for (int i = 0; i < m_piece.CountNode(); ++i)
+    for (int i = 0; i < m_piece.CountNodes(); ++i)
     {
         NewItem(m_piece.at(i));
     }
@@ -134,7 +134,7 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
         const VPiece p = CreatePiece();
         visPath->SetPiece(p);
 
-        if (p.CountNode() == 1)
+        if (p.CountNodes() == 1)
         {
             emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
                             "<b>Enter</b> - finish creation"));
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index f085d8e59..695c9cb9a 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -49,7 +49,7 @@ void VisToolPiece::RefreshGeometry()
 {
     HideAllItems();
 
-    if (m_piece.CountNode() > 0)
+    if (m_piece.CountNodes() > 0)
     {
         DrawPath(this, m_piece.MainPathPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
 

From 4a41840ae79155f1fb79515ca94d8ebb0f03cd6e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 12:57:01 +0200
Subject: [PATCH 019/208] New class VToolSeamAllowance.

--HG--
branch : feature
---
 .../core/vtooloptionspropertybrowser.cpp      |   6 +-
 src/app/valentina/dialogs/dialoghistory.cpp   |   3 +-
 src/app/valentina/mainwindow.cpp              |  30 +-
 src/app/valentina/xml/vpattern.cpp            | 267 ++++-----
 src/libs/ifc/xml/vabstractpattern.cpp         |   8 +-
 src/libs/vmisc/def.h                          |   1 +
 src/libs/vtools/tools/tools.pri               |   6 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  | 559 ++++++++++++++++++
 src/libs/vtools/tools/vtoolseamallowance.h    | 123 ++++
 9 files changed, 850 insertions(+), 153 deletions(-)
 create mode 100644 src/libs/vtools/tools/vtoolseamallowance.cpp
 create mode 100644 src/libs/vtools/tools/vtoolseamallowance.h

diff --git a/src/app/valentina/core/vtooloptionspropertybrowser.cpp b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
index 40183cc34..99434e6d5 100644
--- a/src/app/valentina/core/vtooloptionspropertybrowser.cpp
+++ b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
@@ -77,7 +77,7 @@ void VToolOptionsPropertyBrowser::ClearPropertyBrowser()
 void VToolOptionsPropertyBrowser::ShowItemOptions(QGraphicsItem *item)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
 
     switch (item->type())
     {
@@ -210,7 +210,7 @@ void VToolOptionsPropertyBrowser::UpdateOptions()
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
 
     switch (currentItem->type())
     {
@@ -354,7 +354,7 @@ void VToolOptionsPropertyBrowser::userChangedData(VProperty *property)
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
 
     switch (currentItem->type())
     {
diff --git a/src/app/valentina/dialogs/dialoghistory.cpp b/src/app/valentina/dialogs/dialoghistory.cpp
index bd177bdea..8b57fdadf 100644
--- a/src/app/valentina/dialogs/dialoghistory.cpp
+++ b/src/app/valentina/dialogs/dialoghistory.cpp
@@ -208,7 +208,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QString DialogHistory::Record(const VToolRecord &tool)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was used in history.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in history.");
 
     const QDomElement domElem = doc->elementById(tool.getId());
     if (domElem.isElement() == false)
@@ -381,6 +381,7 @@ QString DialogHistory::Record(const VToolRecord &tool)
             //Because "history" not only show history of pattern, but help restore current data for each pattern's
             //piece, we need add record about details and nodes, but don't show them.
             case Tool::Detail:
+            case Tool::Piece:
             case Tool::UnionDetails:
             case Tool::NodeArc:
             case Tool::NodePoint:
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 83f54631d..74c7fdc71 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -52,6 +52,7 @@
 #include "tools/drawTools/drawtools.h"
 #include "../vtools/dialogs/tooldialogs.h"
 #include "tools/vtooldetail.h"
+#include "tools/vtoolseamallowance.h"
 #include "tools/vtooluniondetails.h"
 #include "dialogs/dialogs.h"
 #include "dialogs/vwidgetgroups.h"
@@ -935,8 +936,10 @@ void MainWindow::ToolPointOfContact(bool checked)
 void MainWindow::ToolDetail(bool checked)
 {
     ToolSelectAllDrawObjects();
-    SetToolButton<DialogSeamAllowance>(checked, Tool::Detail, "://cursor/new_detail_cursor.png",
-                                tr("Select main path objects clockwise."), &MainWindow::ClosedDialogDetail);
+    SetToolButtonWithApply<DialogSeamAllowance>(checked, Tool::Piece, "://cursor/new_detail_cursor.png",
+                                                tr("Select main path objects clockwise."),
+                                                &MainWindow::ClosedDialogWithApply<VToolSeamAllowance>,
+                                                &MainWindow::ApplyDialog<VToolSeamAllowance>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -946,12 +949,12 @@ void MainWindow::ToolDetail(bool checked)
  */
 void MainWindow::ClosedDialogDetail(int result)
 {
-//    if (result == QDialog::Accepted)
-//    {
-//        VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
-//    }
+    if (result == QDialog::Accepted)
+    {
+        VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
+    }
     ArrowTool();
-//    doc->LiteParseTree(Document::LiteParse);
+    doc->LiteParseTree(Document::LiteParse);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1773,7 +1776,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::CancelTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was handled.");
 
     qCDebug(vMainWindow, "Canceling tool.");
     delete dialogTool;
@@ -1859,6 +1862,9 @@ void MainWindow::CancelTool()
         case Tool::Detail:
             ui->toolButtonNewDetail->setChecked(false);
             break;
+        case Tool::Piece:
+            ui->toolButtonNewDetail->setChecked(false);
+            break;
         case Tool::Height:
             ui->toolButtonHeight->setChecked(false);
             break;
@@ -2971,7 +2977,7 @@ void MainWindow::SetEnableTool(bool enable)
     }
 
     // This check helps to find missed tools
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools were handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools were handled.");
 
     //Drawing Tools
     ui->toolButtonEndLine->setEnabled(drawTools);
@@ -3291,7 +3297,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::LastUsedTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was handled.");
 
     if (currentTool == lastUsedTool)
     {
@@ -3381,6 +3387,10 @@ void MainWindow::LastUsedTool()
             ui->toolButtonNewDetail->setChecked(true);
             ToolDetail(true);
             break;
+        case Tool::Piece:
+            ui->toolButtonNewDetail->setChecked(true);
+            ToolDetail(true);
+            break;
         case Tool::Height:
             ui->toolButtonHeight->setChecked(true);
             ToolHeight(true);
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 624f5ff2e..d50dcf7fb 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -608,142 +608,142 @@ void VPattern::ParseDrawMode(const QDomNode &node, const Document &parse, const
  */
 void VPattern::ParseDetailElement(const QDomElement &domElement, const Document &parse)
 {
-    Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
-    try
-    {
-        VDetail detail;
-        const quint32 id = GetParametrId(domElement);
-        detail.setName(GetParametrString(domElement, AttrName, ""));
-        detail.setMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
-        detail.setMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
-        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
-        detail.setWidth(GetParametrDouble(domElement, VToolDetail::AttrWidth, "10.0"));
-        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
-        detail.setForbidFlipping(GetParametrUInt(domElement, VToolDetail::AttrForbidFlipping,
-                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
-        detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
+//    Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
+//    try
+//    {
+//        VDetail detail;
+//        const quint32 id = GetParametrId(domElement);
+//        detail.setName(GetParametrString(domElement, AttrName, ""));
+//        detail.setMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
+//        detail.setMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
+//        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
+//        detail.setWidth(GetParametrDouble(domElement, VToolDetail::AttrWidth, "10.0"));
+//        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
+//        detail.setForbidFlipping(GetParametrUInt(domElement, VToolDetail::AttrForbidFlipping,
+//                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
+//        detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
 
-        QStringList types = QStringList() << VToolDetail::NodePoint << VToolDetail::NodeArc << VToolDetail::NodeSpline
-                                          << VToolDetail::NodeSplinePath;
-        const QDomNodeList nodeList = domElement.childNodes();
-        const qint32 num = nodeList.size();
-        for (qint32 i = 0; i < num; ++i)
-        {
-            const QDomElement element = nodeList.at(i).toElement();
-            if (element.isNull() == false)
-            {
-                if (element.tagName() == VToolDetail::TagNode)
-                {
-                    const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-                    const qreal mx = qApp->toPixel(GetParametrDouble(element, AttrMx, "0.0"));
-                    const qreal my = qApp->toPixel(GetParametrDouble(element, AttrMy, "0.0"));
-                    const bool reverse = GetParametrUInt(element, VToolDetail::AttrReverse, "0");
-                    const NodeDetail nodeType = NodeDetail::Contour;
+//        QStringList types = QStringList() << VToolDetail::NodePoint << VToolDetail::NodeArc << VToolDetail::NodeSpline
+//                                          << VToolDetail::NodeSplinePath;
+//        const QDomNodeList nodeList = domElement.childNodes();
+//        const qint32 num = nodeList.size();
+//        for (qint32 i = 0; i < num; ++i)
+//        {
+//            const QDomElement element = nodeList.at(i).toElement();
+//            if (element.isNull() == false)
+//            {
+//                if (element.tagName() == VToolDetail::TagNode)
+//                {
+//                    const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
+//                    const qreal mx = qApp->toPixel(GetParametrDouble(element, AttrMx, "0.0"));
+//                    const qreal my = qApp->toPixel(GetParametrDouble(element, AttrMy, "0.0"));
+//                    const bool reverse = GetParametrUInt(element, VToolDetail::AttrReverse, "0");
+//                    const NodeDetail nodeType = NodeDetail::Contour;
 
-                    const QString t = GetParametrString(element, AttrType, "NodePoint");
-                    Tool tool;
+//                    const QString t = GetParametrString(element, AttrType, "NodePoint");
+//                    Tool tool;
 
-                    switch (types.indexOf(t))
-                    {
-                        case 0: // VToolDetail::NodePoint
-                            tool = Tool::NodePoint;
-                            break;
-                        case 1: // VToolDetail::NodeArc
-                            tool = Tool::NodeArc;
-                            break;
-                        case 2: // VToolDetail::NodeSpline
-                            tool = Tool::NodeSpline;
-                            break;
-                        case 3: // VToolDetail::NodeSplinePath
-                            tool = Tool::NodeSplinePath;
-                            break;
-                        default:
-                            VException e(tr("Wrong tag name '%1'.").arg(t));
-                            throw e;
-                    }
-                    detail.append(VNodeDetail(id, tool, nodeType, mx, my, reverse));
-                }
-                else if (element.tagName() == TagData)
-                {
-                    bool bVisible = GetParametrBool(element, AttrVisible, trueStr);
-                    detail.GetPatternPieceData().SetVisible(bVisible);
-                    try
-                    {
-                        QString qsLetter = GetParametrString(element, AttrLetter, "");
-                        detail.GetPatternPieceData().SetLetter(qsLetter);
-                    } catch(...)
-                    {
-                        detail.GetPatternPieceData().SetLetter("");
-                    }
-                    QPointF ptPos;
-                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-                    detail.GetPatternPieceData().SetPos(ptPos);
-                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
-                    detail.GetPatternPieceData().SetLabelWidth(dLW);
-                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
-                    detail.GetPatternPieceData().SetLabelHeight(dLH);
-                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
-                    detail.GetPatternPieceData().SetFontSize(iFS);
-                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
-                    detail.GetPatternPieceData().SetRotation(dRot);
+//                    switch (types.indexOf(t))
+//                    {
+//                        case 0: // VToolDetail::NodePoint
+//                            tool = Tool::NodePoint;
+//                            break;
+//                        case 1: // VToolDetail::NodeArc
+//                            tool = Tool::NodeArc;
+//                            break;
+//                        case 2: // VToolDetail::NodeSpline
+//                            tool = Tool::NodeSpline;
+//                            break;
+//                        case 3: // VToolDetail::NodeSplinePath
+//                            tool = Tool::NodeSplinePath;
+//                            break;
+//                        default:
+//                            VException e(tr("Wrong tag name '%1'.").arg(t));
+//                            throw e;
+//                    }
+//                    detail.append(VNodeDetail(id, tool, nodeType, mx, my, reverse));
+//                }
+//                else if (element.tagName() == TagData)
+//                {
+//                    bool bVisible = GetParametrBool(element, AttrVisible, trueStr);
+//                    detail.GetPatternPieceData().SetVisible(bVisible);
+//                    try
+//                    {
+//                        QString qsLetter = GetParametrString(element, AttrLetter, "");
+//                        detail.GetPatternPieceData().SetLetter(qsLetter);
+//                    } catch(...)
+//                    {
+//                        detail.GetPatternPieceData().SetLetter("");
+//                    }
+//                    QPointF ptPos;
+//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
+//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
+//                    detail.GetPatternPieceData().SetPos(ptPos);
+//                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
+//                    detail.GetPatternPieceData().SetLabelWidth(dLW);
+//                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
+//                    detail.GetPatternPieceData().SetLabelHeight(dLH);
+//                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
+//                    detail.GetPatternPieceData().SetFontSize(iFS);
+//                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
+//                    detail.GetPatternPieceData().SetRotation(dRot);
 
-                    QDomNodeList nodeListMCP = element.childNodes();
-                    for (int iMCP = 0; iMCP < nodeListMCP.count(); ++iMCP)
-                    {
-                        MaterialCutPlacement mcp;
-                        QDomElement domMCP = nodeListMCP.at(iMCP).toElement();
-                        mcp.m_eMaterial = MaterialType(GetParametrUInt(domMCP, AttrMaterial, 0));
-                        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-                        {
-                            mcp.m_qsMaterialUserDef = GetParametrString(domMCP, AttrUserDefined, "");
-                        }
-                        mcp.m_iCutNumber = static_cast<int>(GetParametrUInt(domMCP, AttrCutNumber, 0));
-                        mcp.m_ePlacement = PlacementType(GetParametrUInt(domMCP, AttrPlacement, 0));
-                        detail.GetPatternPieceData().Append(mcp);
-                    }
-                }
-                else if (element.tagName() == TagPatternInfo)
-                {
-                    detail.GetPatternInfo().SetVisible(GetParametrBool(element, AttrVisible, trueStr));
-                    QPointF ptPos;
-                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-                    detail.GetPatternInfo().SetPos(ptPos);
-                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
-                    detail.GetPatternInfo().SetLabelWidth(dLW);
-                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
-                    detail.GetPatternInfo().SetLabelHeight(dLH);
-                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
-                    detail.GetPatternInfo().SetFontSize(iFS);
-                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
-                    detail.GetPatternInfo().SetRotation(dRot);
-                }
-                else if (element.tagName() == TagGrainline)
-                {
-                    detail.GetGrainlineGeometry().SetVisible(GetParametrBool(element, AttrVisible, falseStr));
-                    QPointF ptPos;
-                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-                    detail.GetGrainlineGeometry().SetPos(ptPos);
-                    QString qsLength = GetParametrString(element, AttrLength, "0");
-                    detail.GetGrainlineGeometry().SetLength(qsLength);
-                    QString qsRot = GetParametrString(element, VToolDetail::AttrRotation, "90");
-                    detail.GetGrainlineGeometry().SetRotation(qsRot);
-                    VGrainlineGeometry::ArrowType eAT =
-                            VGrainlineGeometry::ArrowType(GetParametrUInt(element, AttrArrows, "0"));
-                    detail.GetGrainlineGeometry().SetArrowType(eAT);
-                }
-            }
-        }
-        VToolDetail::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
-    }
-    catch (const VExceptionBadId &e)
-    {
-        VExceptionObjectError excep(tr("Error creating or updating detail"), domElement);
-        excep.AddMoreInformation(e.ErrorMessage());
-        throw excep;
-    }
+//                    QDomNodeList nodeListMCP = element.childNodes();
+//                    for (int iMCP = 0; iMCP < nodeListMCP.count(); ++iMCP)
+//                    {
+//                        MaterialCutPlacement mcp;
+//                        QDomElement domMCP = nodeListMCP.at(iMCP).toElement();
+//                        mcp.m_eMaterial = MaterialType(GetParametrUInt(domMCP, AttrMaterial, 0));
+//                        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
+//                        {
+//                            mcp.m_qsMaterialUserDef = GetParametrString(domMCP, AttrUserDefined, "");
+//                        }
+//                        mcp.m_iCutNumber = static_cast<int>(GetParametrUInt(domMCP, AttrCutNumber, 0));
+//                        mcp.m_ePlacement = PlacementType(GetParametrUInt(domMCP, AttrPlacement, 0));
+//                        detail.GetPatternPieceData().Append(mcp);
+//                    }
+//                }
+//                else if (element.tagName() == TagPatternInfo)
+//                {
+//                    detail.GetPatternInfo().SetVisible(GetParametrBool(element, AttrVisible, trueStr));
+//                    QPointF ptPos;
+//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
+//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
+//                    detail.GetPatternInfo().SetPos(ptPos);
+//                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
+//                    detail.GetPatternInfo().SetLabelWidth(dLW);
+//                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
+//                    detail.GetPatternInfo().SetLabelHeight(dLH);
+//                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
+//                    detail.GetPatternInfo().SetFontSize(iFS);
+//                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
+//                    detail.GetPatternInfo().SetRotation(dRot);
+//                }
+//                else if (element.tagName() == TagGrainline)
+//                {
+//                    detail.GetGrainlineGeometry().SetVisible(GetParametrBool(element, AttrVisible, falseStr));
+//                    QPointF ptPos;
+//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
+//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
+//                    detail.GetGrainlineGeometry().SetPos(ptPos);
+//                    QString qsLength = GetParametrString(element, AttrLength, "0");
+//                    detail.GetGrainlineGeometry().SetLength(qsLength);
+//                    QString qsRot = GetParametrString(element, VToolDetail::AttrRotation, "90");
+//                    detail.GetGrainlineGeometry().SetRotation(qsRot);
+//                    VGrainlineGeometry::ArrowType eAT =
+//                            VGrainlineGeometry::ArrowType(GetParametrUInt(element, AttrArrows, "0"));
+//                    detail.GetGrainlineGeometry().SetArrowType(eAT);
+//                }
+//            }
+//        }
+//        VToolDetail::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
+//    }
+//    catch (const VExceptionBadId &e)
+//    {
+//        VExceptionObjectError excep(tr("Error creating or updating detail"), domElement);
+//        excep.AddMoreInformation(e.ErrorMessage());
+//        throw excep;
+//    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -3442,7 +3442,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QRectF VPattern::ActiveDrawBoundingRect() const
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48, "Not all tools was used.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used.");
 
     QRectF rec;
 
@@ -3565,6 +3565,7 @@ QRectF VPattern::ActiveDrawBoundingRect() const
                     break;
                 //These tools are not accesseble in Draw mode, but still 'history' contains them.
                 case Tool::Detail:
+                case Tool::Piece:
                 case Tool::UnionDetails:
                 case Tool::NodeArc:
                 case Tool::NodePoint:
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index c7ed109f2..05076bd9f 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -1422,7 +1422,7 @@ QStringList VAbstractPattern::ListPointExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagPoint);
@@ -1493,7 +1493,7 @@ QStringList VAbstractPattern::ListArcExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagArc);
@@ -1554,7 +1554,7 @@ QStringList VAbstractPattern::ListPathPointExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(AttrPathPoint);
@@ -1620,7 +1620,7 @@ QStringList VAbstractPattern::ListOperationExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 48);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagOperation);
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index debc5166b..a5c420e90 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -92,6 +92,7 @@ enum class Tool : ToolVisHolderType
     CutSplinePath,
     PointOfContact,
     Detail,
+    Piece,
     NodePoint,
     NodeArc,
     NodeSpline,
diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri
index 4f4536aae..563ab6573 100644
--- a/src/libs/vtools/tools/tools.pri
+++ b/src/libs/vtools/tools/tools.pri
@@ -57,7 +57,8 @@ HEADERS += \
     $$PWD/drawTools/operation/vabstractoperation.h \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.h \
     $$PWD/drawTools/operation/flipping/vabstractflipping.h \
-    $$PWD/drawTools/operation/vtoolmove.h
+    $$PWD/drawTools/operation/vtoolmove.h \
+    $$PWD/vtoolseamallowance.h
 
 SOURCES += \
     $$PWD/vtooldetail.cpp \
@@ -112,4 +113,5 @@ SOURCES += \
     $$PWD/drawTools/operation/vabstractoperation.cpp \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.cpp \
     $$PWD/drawTools/operation/flipping/vabstractflipping.cpp \
-    $$PWD/drawTools/operation/vtoolmove.cpp
+    $$PWD/drawTools/operation/vtoolmove.cpp \
+    $$PWD/vtoolseamallowance.cpp
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
new file mode 100644
index 000000000..62b260af5
--- /dev/null
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -0,0 +1,559 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   6 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vtoolseamallowance.h"
+#include "../dialogs/tools/dialogseamallowance.h"
+#include "../vpatterndb/vpiecenode.h"
+#include "nodeDetails/vnodearc.h"
+#include "nodeDetails/vnodepoint.h"
+#include "nodeDetails/vnodespline.h"
+#include "nodeDetails/vnodesplinepath.h"
+#include "../vgeometry/varc.h"
+#include "../vgeometry/vcubicbezier.h"
+#include "../vgeometry/vcubicbezierpath.h"
+#include "../vgeometry/vpointf.h"
+#include "../vgeometry/vspline.h"
+#include "../vgeometry/vsplinepath.h"
+#include "../ifc/xml/vpatternconverter.h"
+#include "../undocommands/addpiece.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QMenu>
+
+// Current version of seam allowance tag nned for backward compatibility
+const quint8 VToolSeamAllowance::pieceVersion = 2;
+
+const QString VToolSeamAllowance::TagNodes    = QStringLiteral("nodes");
+const QString VToolSeamAllowance::TagNode     = QStringLiteral("node");
+
+const QString VToolSeamAllowance::AttrVersion     = QStringLiteral("version");
+const QString VToolSeamAllowance::AttrNodeReverse = QStringLiteral("reverse");
+
+const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
+const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
+const QString VToolSeamAllowance::NodeSpline     = QStringLiteral("NodeSpline");
+const QString VToolSeamAllowance::NodeSplinePath = QStringLiteral("NodeSplinePath");
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolSeamAllowance::~VToolSeamAllowance()
+{
+    delete m_dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                               VContainer *data)
+{
+    SCASSERT(dialog != nullptr);
+    DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(dialog);
+    SCASSERT(dialogTool != nullptr);
+    VPiece detail = dialogTool->GetPiece();
+    QVector<VPieceNode> nodes;
+    qApp->getUndoStack()->beginMacro("add detail");
+    for (int i = 0; i< detail.CountNodes(); ++i)
+    {
+        quint32 id = 0;
+        VPieceNode nodeD = detail.at(i);
+        switch (nodeD.GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                id = CreateNode<VPointF>(data, nodeD.GetId());
+                VNodePoint::Create(doc, data, scene, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+            }
+            break;
+            case (Tool::NodeArc):
+            {
+                id = CreateNode<VArc>(data, nodeD.GetId());
+                VNodeArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+            }
+            break;
+            case (Tool::NodeSpline):
+            {
+                const auto obj = data->GetGObject(nodeD.GetId());
+                if (obj->getType() == GOType::Spline)
+                {
+                    id = CreateNode<VSpline>(data, nodeD.GetId());
+                }
+                else
+                {
+                    id = CreateNode<VCubicBezier>(data, nodeD.GetId());
+                }
+                VNodeSpline::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+            }
+            break;
+            case (Tool::NodeSplinePath):
+            {
+                const auto obj = data->GetGObject(nodeD.GetId());
+                if (obj->getType() == GOType::SplinePath)
+                {
+                    id = CreateNode<VSplinePath>(data, nodeD.GetId());
+                }
+                else
+                {
+                    id = CreateNode<VCubicBezierPath>(data, nodeD.GetId());
+                }
+                VNodeSplinePath::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+            }
+            break;
+            default:
+                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+                break;
+        }
+        nodeD.SetId(id);
+        nodes.append(nodeD);
+    }
+
+    detail.SetNodes(nodes);
+    VToolSeamAllowance *piece = Create(0, detail, scene, doc, data, Document::FullParse, Source::FromGui);
+
+    if (piece != nullptr)
+    {
+        piece->m_dialog = dialogTool;
+    }
+    return piece;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, const VPiece &newPiece, VMainGraphicsScene *scene,
+                                               VAbstractPattern *doc, VContainer *data, const Document &parse,
+                                               const Source &typeCreation, const QString &drawName)
+{
+    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
+    {
+        id = data->AddPiece(newPiece);
+    }
+    else
+    {
+        data->UpdatePiece(id, newPiece);
+        if (parse != Document::FullParse)
+        {
+            doc->UpdateToolData(id, data);
+        }
+    }
+    VAbstractTool::AddRecord(id, Tool::Piece, doc);
+    if (parse == Document::FullParse)
+    {
+        VToolSeamAllowance *piece = new VToolSeamAllowance(doc, data, id, typeCreation, scene, drawName);
+        scene->addItem(piece);
+        connect(piece, &VToolSeamAllowance::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
+        connect(scene, &VMainGraphicsScene::EnableDetailItemHover, piece, &VToolSeamAllowance::AllowHover);
+        connect(scene, &VMainGraphicsScene::EnableDetailItemSelection, piece, &VToolSeamAllowance::AllowSelecting);
+        connect(scene, &VMainGraphicsScene::HighlightDetail, piece, &VToolSeamAllowance::Highlight);
+        doc->AddTool(id, piece);
+    }
+    return nullptr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
+{
+    QDomElement nod = doc->createElement(TagNode);
+
+    doc->SetAttribute(nod, AttrIdObject, node.GetId());
+
+    if (node.GetTypeTool() != Tool::NodePoint)
+    {
+        doc->SetAttribute(nod, AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
+    }
+
+    switch (node.GetTypeTool())
+    {
+        case (Tool::NodeArc):
+            doc->SetAttribute(nod, AttrType, NodeArc);
+            break;
+        case (Tool::NodePoint):
+            doc->SetAttribute(nod, AttrType, NodePoint);
+            break;
+        case (Tool::NodeSpline):
+            doc->SetAttribute(nod, AttrType, NodeSpline);
+            break;
+        case (Tool::NodeSplinePath):
+            doc->SetAttribute(nod, AttrType, NodeSplinePath);
+            break;
+        default:
+            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+            break;
+    }
+    domElement.appendChild(nod);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
+{
+    if (piece.CountNodes() > 0)
+    {
+        QDomElement nodesElement = doc->createElement(TagNodes);
+        for (int i = 0; i < piece.CountNodes(); ++i)
+        {
+            AddNode(doc, nodesElement, piece.at(i));
+        }
+        domElement.appendChild(nodesElement);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VToolSeamAllowance::getTagName() const
+{
+    return VAbstractPattern::TagDetail;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::ShowVisualization(bool show)
+{
+    Q_UNUSED(show)
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::GroupVisibility(quint32 object, bool visible)
+{
+    Q_UNUSED(object);
+    Q_UNUSED(visible);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::FullUpdateFromFile()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::FullUpdateFromGuiOk(int result)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::EnableToolMove(bool move)
+{
+    setFlag(QGraphicsItem::ItemIsMovable, move);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AllowHover(bool enabled)
+{
+    setAcceptHoverEvents(enabled);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AllowSelecting(bool enabled)
+{
+    setFlag(QGraphicsItem::ItemIsSelectable, enabled);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::Highlight(quint32 id)
+{
+    setSelected(this->id == id);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddToFile()
+{
+    const VPiece piece = VAbstractTool::data.GetPiece(id);
+
+    QDomElement domElement = doc->createElement(getTagName());
+
+    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+    doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
+    doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
+    doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
+
+    // nodes
+    AddNodes(doc, domElement, piece);
+
+    AddPiece *addDet = new AddPiece(domElement, doc, piece, m_drawName);
+    connect(addDet, &AddPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
+    qApp->getUndoStack()->push(addDet);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::RefreshDataInFile()
+{
+    QDomElement domElement = doc->elementById(id);
+    if (domElement.isElement())
+    {
+        // Refresh only parts that we possibly need to update
+        {
+            // TODO. Delete if minimal supported version is 0.5.0
+            Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 5, 0),
+                              "Time to refactor the code.");
+            doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVariant VToolSeamAllowance::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+    return VNoBrushScalePathItem::itemChange(change, value);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    // Special for not selectable item first need to call standard mousePressEvent then accept event
+    VNoBrushScalePathItem::mousePressEvent(event);
+
+    // Somehow clicking on notselectable object do not clean previous selections.
+    if (not (flags() & ItemIsSelectable) && scene())
+    {
+        scene()->clearSelection();
+    }
+
+    if (flags() & QGraphicsItem::ItemIsMovable)
+    {
+        if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
+        {
+            SetOverrideCursor(cursorArrowCloseHand, 1, 1);
+        }
+    }
+
+    if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
+    {
+        doc->SelectedDetail(id);
+        emit ChoosedTool(id, SceneObject::Detail);
+    }
+
+    event->accept();// Special for not selectable item first need to call standard mousePressEvent then accept event
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    if (event->button() == Qt::LeftButton)
+    {
+        //Disable cursor-arrow-closehand
+        RestoreOverrideCursor(cursorArrowCloseHand);
+    }
+    VNoBrushScalePathItem::mouseReleaseEvent(event);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+    if (flags() & QGraphicsItem::ItemIsMovable)
+    {
+        SetOverrideCursor(cursorArrowOpenHand, 1, 1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+    if (flags() & QGraphicsItem::ItemIsMovable)
+    {
+        SetOverrideCursor(cursorArrowOpenHand, 1, 1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+    //Disable cursor-arrow-openhand
+    if (flags() & QGraphicsItem::ItemIsMovable)
+    {
+        RestoreOverrideCursor(cursorArrowOpenHand);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+    QMenu menu;
+    QAction *actionOption = menu.addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
+
+//    QAction *inLayoutOption = menu.addAction(tr("In layout"));
+//    inLayoutOption->setCheckable(true);
+//    const VDetail detail = VAbstractTool::data.GetDetail(id);
+//    inLayoutOption->setChecked(detail.IsInLayout());
+
+//    QAction *actionRemove = menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+//    _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
+
+    QAction *selectedAction = menu.exec(event->screenPos());
+    if (selectedAction == actionOption)
+    {
+        m_dialog = new DialogSeamAllowance(getData(), id, qApp->getMainWindow());
+        m_dialog->setModal(true);
+        connect(m_dialog, &DialogTool::DialogClosed, this, &VToolSeamAllowance::FullUpdateFromGuiOk);
+        SetDialog();
+        m_dialog->show();
+    }
+//    else if (selectedAction == inLayoutOption)
+//    {
+//        ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, selectedAction->isChecked(),
+//                                                                     &(VAbstractTool::data), doc);
+//        connect(togglePrint, &ToggleDetailInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
+//        qApp->getUndoStack()->push(togglePrint);
+//    }
+//    else if (selectedAction == actionRemove)
+//    {
+//        try
+//        {
+//            DeleteTool();
+//        }
+//        catch(const VExceptionToolWasDeleted &e)
+//        {
+//            Q_UNUSED(e);
+//            return;//Leave this method immediately!!!
+//        }
+//        return; //Leave this method immediately after call!!!
+    //    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::keyReleaseEvent(QKeyEvent *event)
+{
+    VNoBrushScalePathItem::keyReleaseEvent ( event );
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SetDialog()
+{
+    SCASSERT(m_dialog != nullptr);
+    DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(m_dialog);
+    SCASSERT(dialogTool != nullptr);
+    dialogTool->SetPiece(VAbstractTool::data.GetPiece(id));
+    dialogTool->EnableApply(true);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data, const quint32 &id,
+                                       const Source &typeCreation, VMainGraphicsScene *scene,
+                                       const QString &drawName, QGraphicsItem *parent)
+    : VAbstractTool(doc, data, id),
+      VNoBrushScalePathItem(parent),
+      m_dialog(nullptr),
+      m_sceneDetails(scene),
+      m_drawName(drawName)
+{
+    VPiece detail = data->GetPiece(id);
+    for (int i = 0; i< detail.CountNodes(); ++i)
+    {
+        switch (detail.at(i).GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.at(i));
+                connect(tool, &VNodePoint::ShowContextMenu, this, &VToolSeamAllowance::contextMenuEvent);
+                break;
+            }
+            case (Tool::NodeArc):
+                doc->IncrementReferens(detail.at(i).GetId());
+                break;
+            case (Tool::NodeSpline):
+                doc->IncrementReferens(detail.at(i).GetId());
+                break;
+            case (Tool::NodeSplinePath):
+                doc->IncrementReferens(detail.at(i).GetId());
+                break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore.";
+                break;
+        }
+    }
+    this->setFlag(QGraphicsItem::ItemIsMovable, true);
+    this->setFlag(QGraphicsItem::ItemIsSelectable, true);
+    RefreshGeometry();
+
+    this->setBrush(QBrush(Qt::Dense7Pattern));
+
+    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+    this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
+
+    connect(scene, &VMainGraphicsScene::EnableToolMove, this, &VToolSeamAllowance::EnableToolMove);
+    //connect(scene, &VMainGraphicsScene::ItemClicked, this, &VToolSeamAllowance::ResetChildren);
+    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
+    {
+        AddToFile();
+        if (typeCreation != Source::FromTool)
+        {
+            qApp->getUndoStack()->endMacro();
+        }
+    }
+    else
+    {
+        RefreshDataInFile();
+    }
+    setAcceptHoverEvents(true);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::RefreshGeometry()
+{
+    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
+
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
+    QPainterPath mainPath = detail.MainPathPath(this->getData());
+    this->setPath(mainPath);
+    this->setPos(detail.GetMx(), detail.GetMy());
+
+    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::DeleteTool(bool ask)
+{
+
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template<typename T>
+/**
+ * @brief CreateNode create new node for detail.
+ * @param data container.
+ * @param id id parent object.
+ * @return id for new object.
+ */
+quint32 VToolSeamAllowance::CreateNode(VContainer *data, const quint32 &id)
+{
+    //We can't use exist object. Need create new.
+    T *node = new T(*data->GeometricObject<T>(id).data());
+    node->setMode(Draw::Modeling);
+    return data->AddGObject(node);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template <typename Tool>
+/**
+ * @brief InitTool initial node item on scene
+ * @param scene pointer to scene.
+ * @param node node of detail.
+ */
+Tool *VToolSeamAllowance::InitTool(VMainGraphicsScene *scene, const VPieceNode &node)
+{
+    QHash<quint32, VDataTool*>* tools = doc->getTools();
+    SCASSERT(tools != nullptr);
+    Tool *tool = qobject_cast<Tool*>(tools->value(node.GetId()));
+    SCASSERT(tool != nullptr);
+    connect(tool, &Tool::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
+    tool->setParentItem(this);
+    tool->SetParentType(ParentType::Item);
+    doc->IncrementReferens(node.GetId());
+    return tool;
+}
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
new file mode 100644
index 000000000..836849aa9
--- /dev/null
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -0,0 +1,123 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   6 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VTOOLSEAMALLOWANCE_H
+#define VTOOLSEAMALLOWANCE_H
+
+#include <QtGlobal>
+#include <qcompilerdetection.h>
+#include <QObject>
+
+#include "../vwidgets/vnobrushscalepathitem.h"
+#include "vabstracttool.h"
+
+class VMainGraphicsScene;
+class DialogTool;
+class VPiece;
+
+class VToolSeamAllowance : public VAbstractTool, public VNoBrushScalePathItem
+{
+    Q_OBJECT
+public:
+    virtual ~VToolSeamAllowance();
+
+    static VToolSeamAllowance* Create(DialogTool *m_dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                      VContainer *data);
+    static VToolSeamAllowance* Create(quint32 id, const VPiece &newPiece, VMainGraphicsScene *scene,
+                                      VAbstractPattern *doc, VContainer *data, const Document &parse,
+                                      const Source &typeCreation, const QString &m_drawName = QString());
+
+    static const quint8 pieceVersion;
+
+    static const QString TagNodes;
+    static const QString TagNode;
+
+    static const QString AttrVersion;
+    static const QString AttrNodeReverse;
+
+    static const QString NodeArc;
+    static const QString NodePoint;
+    static const QString NodeSpline;
+    static const QString NodeSplinePath;
+
+    static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
+    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
+
+    virtual int        type() const Q_DECL_OVERRIDE {return Type;}
+    enum { Type = UserType + static_cast<int>(Tool::Piece)};
+
+    virtual QString    getTagName() const Q_DECL_OVERRIDE;
+    virtual void       ShowVisualization(bool show) Q_DECL_OVERRIDE;
+    virtual void       GroupVisibility(quint32 object, bool visible) Q_DECL_OVERRIDE;
+public slots:
+    virtual void       FullUpdateFromFile () Q_DECL_OVERRIDE;
+    virtual void       FullUpdateFromGuiOk(int result);
+    void               EnableToolMove(bool move);
+    virtual void       AllowHover(bool enabled) Q_DECL_OVERRIDE;
+    virtual void       AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
+    void               Highlight(quint32 id);
+protected:
+    virtual void       AddToFile () Q_DECL_OVERRIDE;
+    virtual void       RefreshDataInFile() Q_DECL_OVERRIDE;
+    virtual QVariant   itemChange ( GraphicsItemChange change, const QVariant &value ) Q_DECL_OVERRIDE;
+    virtual void       mousePressEvent( QGraphicsSceneMouseEvent * event) Q_DECL_OVERRIDE;
+    virtual void       mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE;
+    virtual void       hoverMoveEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
+    virtual void       hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
+    virtual void       hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
+    virtual void       contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE;
+    virtual void       keyReleaseEvent(QKeyEvent * event) Q_DECL_OVERRIDE;
+    virtual void       SetVisualization() Q_DECL_OVERRIDE {}
+
+private:
+    Q_DISABLE_COPY(VToolSeamAllowance)
+
+    /** @brief dialog dialog options. */
+    DialogTool         *m_dialog;
+
+    /** @brief sceneDetails pointer to the scene. */
+    VMainGraphicsScene *m_sceneDetails;
+    QString             m_drawName;
+
+    void SetDialog();
+
+    template<typename T>
+    static quint32 CreateNode(VContainer *data, const quint32 &id);
+
+    VToolSeamAllowance(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation,
+                       VMainGraphicsScene *scene, const QString &m_drawName, QGraphicsItem * parent = nullptr);
+
+    void               RefreshGeometry ();
+
+    template <typename Tool>
+    Tool*              InitTool(VMainGraphicsScene *scene, const VPieceNode &node);
+
+    virtual void       DeleteTool(bool ask = true) Q_DECL_OVERRIDE;
+};
+
+#endif // VTOOLSEAMALLOWANCE_H

From a32be533ec5a735b333368132d4a3bce048ba59d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 13:07:29 +0200
Subject: [PATCH 020/208] Fix crash.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index 1ffe87e33..726b6bbf9 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -91,6 +91,7 @@ public:
           gObjects(data.gObjects),
           variables(data.variables),
           details(data.details),
+          pieces(data.pieces),
           trVars(data.trVars),
           patternUnit(data.patternUnit)
     {}

From c5e8a6a529732d2e87469067ad221bd89f4edb69 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 13:39:27 +0200
Subject: [PATCH 021/208] Refactor templates SetToolButton and
 SetToolButtonWithApply.

These templates do almost the same. Uniting them looks like a good idea.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 54 +++++++++++---------------------
 1 file changed, 19 insertions(+), 35 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 74c7fdc71..d8f4ac82c 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -541,13 +541,28 @@ void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, cons
         CancelTool();
         emit EnableItemMove(false);
         currentTool = lastUsedTool = t;
-        QPixmap pixmap(cursor);
+        auto cursorResource = cursor;
+        if (qApp->devicePixelRatio() >= 2)
+        {
+            // Try to load HiDPI versions of the cursors if availible
+            auto cursorHidpiResource = QString(cursor).replace(".png", "@2x.png");
+            if (QFileInfo(cursorResource).exists())
+            {
+                cursorResource = cursorHidpiResource;
+            }
+        }
+        QPixmap pixmap(cursorResource);
         QCursor cur(pixmap, 2, 3);
         ui->view->setCursor(cur);
         helpLabel->setText(toolTip);
         ui->view->setShowToolOptions(false);
         dialogTool = new Dialog(pattern, 0, this);
 
+        if (t == Tool::Midpoint)
+        {
+            dialogTool->Build(t);
+        }
+
         VMainGraphicsScene *scene = qobject_cast<VMainGraphicsScene *>(currentScene);
         SCASSERT(scene != nullptr);
 
@@ -555,6 +570,7 @@ void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, cons
         connect(scene, &VMainGraphicsScene::SelectedObject, dialogTool.data(), &DialogTool::SelectedObject);
         connect(dialogTool.data(), &DialogTool::DialogClosed, this, closeDialogSlot);
         connect(dialogTool.data(), &DialogTool::ToolTip, this, &MainWindow::ShowToolTip);
+        connect(ui->view, &VMainGraphicsView::MouseRelease, [this](){EndVisualization(true);});
         ui->view->itemClicked(nullptr);
     }
     else
@@ -578,45 +594,13 @@ template <typename Dialog, typename Func, typename Func2>
  * @param applyDialogSlot function to handle apply in dialog.
  */
 void MainWindow::SetToolButtonWithApply(bool checked, Tool t, const QString &cursor, const QString &toolTip,
-                               Func closeDialogSlot, Func2 applyDialogSlot)
+                                        Func closeDialogSlot, Func2 applyDialogSlot)
 {
     if (checked)
     {
-        CancelTool();
-        emit EnableItemMove(false);
-        currentTool = lastUsedTool = t;
-        auto cursorResource = cursor;
-        if (qApp->devicePixelRatio() >= 2)
-        {
-            // Try to load HiDPI versions of the cursors if availible
-            auto cursorHidpiResource = QString(cursor).replace(".png", "@2x.png");
-            if (QFileInfo(cursorResource).exists())
-            {
-                cursorResource = cursorHidpiResource;
-            }
-        }
-        QPixmap pixmap(cursorResource);
-        QCursor cur(pixmap, 2, 3);
-        ui->view->setCursor(cur);
-        ui->view->setShowToolOptions(false);
-        helpLabel->setText(toolTip);
-        dialogTool = new Dialog(pattern, NULL_ID, this);
+        SetToolButton<Dialog>(checked, t, cursor, toolTip, closeDialogSlot);
 
-        if (t == Tool::Midpoint)
-        {
-            dialogTool->Build(t);
-        }
-
-        VMainGraphicsScene *scene = qobject_cast<VMainGraphicsScene *>(currentScene);
-        SCASSERT(scene != nullptr);
-
-        connect(scene, &VMainGraphicsScene::ChoosedObject, dialogTool.data(), &DialogTool::ChosenObject);
-        connect(scene, &VMainGraphicsScene::SelectedObject, dialogTool.data(), &DialogTool::SelectedObject);
-        connect(dialogTool.data(), &DialogTool::DialogClosed, this, closeDialogSlot);
         connect(dialogTool.data(), &DialogTool::DialogApplied, this, applyDialogSlot);
-        connect(dialogTool.data(), &DialogTool::ToolTip, this, &MainWindow::ShowToolTip);
-        connect(ui->view, &VMainGraphicsView::MouseRelease, [this](){EndVisualization(true);});
-        ui->view->itemClicked(nullptr);
     }
     else
     {

From bf847bac7bd19b90ba4e155f3b8e9371e9fc0694 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 14:04:23 +0200
Subject: [PATCH 022/208] Dialog Detail need pointer to scene Details.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 174 ++++++++++++++++++-------------
 src/app/valentina/mainwindow.h   |  14 ++-
 2 files changed, 112 insertions(+), 76 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index d8f4ac82c..8c6eae650 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -636,7 +636,7 @@ void MainWindow::ClosedDialog(int result)
  * @param result result working dialog.
  */
 template <typename DrawTool>
-void MainWindow::ClosedDialogWithApply(int result)
+void MainWindow::ClosedDialogWithApply(int result, VMainGraphicsScene *scene)
 {
     SCASSERT(not dialogTool.isNull());
     if (result == QDialog::Accepted)
@@ -644,7 +644,6 @@ void MainWindow::ClosedDialogWithApply(int result)
         // Only create tool if not already created with apply
         if (dialogTool->GetAssociatedTool() == nullptr)
         {
-            VMainGraphicsScene *scene = qobject_cast<VMainGraphicsScene *>(currentScene);
             SCASSERT(scene != nullptr);
 
             dialogTool->SetAssociatedTool(
@@ -682,14 +681,13 @@ void MainWindow::ClosedDialogWithApply(int result)
  * @brief ApplyDialog handle apply in dialog
  */
 template <typename DrawTool>
-void MainWindow::ApplyDialog()
+void MainWindow::ApplyDialog(VMainGraphicsScene *scene)
 {
     SCASSERT(not dialogTool.isNull());
 
     // Only create tool if not already created with apply
     if (dialogTool->GetAssociatedTool() == nullptr)
     {
-        VMainGraphicsScene *scene = qobject_cast<VMainGraphicsScene *>(currentScene);
         SCASSERT(scene != nullptr);
 
         dialogTool->SetAssociatedTool(
@@ -703,6 +701,34 @@ void MainWindow::ApplyDialog()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+template <typename DrawTool>
+void MainWindow::ClosedDrawDialogWithApply(int result)
+{
+    ClosedDialogWithApply<DrawTool>(result, sceneDraw);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template <typename DrawTool>
+void MainWindow::ApplyDrawDialog()
+{
+    ApplyDialog<DrawTool>(sceneDraw);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template <typename DrawTool>
+void MainWindow::ClosedDetailsDialogWithApply(int result)
+{
+    ClosedDialogWithApply<DrawTool>(result, sceneDetails);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template <typename DrawTool>
+void MainWindow::ApplyDetailsDialog()
+{
+    ApplyDialog<DrawTool>(sceneDetails);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ToolEndLine handler tool endLine.
@@ -712,8 +738,8 @@ void MainWindow::ToolEndLine(bool checked)
 {
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogEndLine>(checked, Tool::EndLine, ":/cursor/endline_cursor.png", tr("Select point"),
-                                          &MainWindow::ClosedDialogWithApply<VToolEndLine>,
-                                          &MainWindow::ApplyDialog<VToolEndLine>);
+                                          &MainWindow::ClosedDrawDialogWithApply<VToolEndLine>,
+                                          &MainWindow::ApplyDrawDialog<VToolEndLine>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -725,8 +751,8 @@ void MainWindow::ToolLine(bool checked)
 {
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogLine>(checked, Tool::Line, ":/cursor/line_cursor.png", tr("Select first point"),
-                                       &MainWindow::ClosedDialogWithApply<VToolLine>,
-                                       &MainWindow::ApplyDialog<VToolLine>);
+                                       &MainWindow::ClosedDrawDialogWithApply<VToolLine>,
+                                       &MainWindow::ApplyDrawDialog<VToolLine>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -738,8 +764,8 @@ void MainWindow::ToolAlongLine(bool checked)
 {
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogAlongLine>(checked, Tool::AlongLine, ":/cursor/alongline_cursor.png",
-                                            tr("Select point"), &MainWindow::ClosedDialogWithApply<VToolAlongLine>,
-                                            &MainWindow::ApplyDialog<VToolAlongLine>);
+                                            tr("Select point"), &MainWindow::ClosedDrawDialogWithApply<VToolAlongLine>,
+                                            &MainWindow::ApplyDrawDialog<VToolAlongLine>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -748,8 +774,8 @@ void MainWindow::ToolMidpoint(bool checked)
     ToolSelectPointByRelease();
     // Reuse DialogAlongLine and VToolAlongLine but with different cursor
     SetToolButtonWithApply<DialogAlongLine>(checked, Tool::Midpoint, ":/cursor/midpoint_cursor.png",
-                                            tr("Select point"), &MainWindow::ClosedDialogWithApply<VToolAlongLine>,
-                                            &MainWindow::ApplyDialog<VToolAlongLine>);
+                                            tr("Select point"), &MainWindow::ClosedDrawDialogWithApply<VToolAlongLine>,
+                                            &MainWindow::ApplyDrawDialog<VToolAlongLine>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -762,8 +788,8 @@ void MainWindow::ToolShoulderPoint(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogShoulderPoint>(checked, Tool::ShoulderPoint, ":/cursor/shoulder_cursor.png",
                                                 tr("Select point"),
-                                                &MainWindow::ClosedDialogWithApply<VToolShoulderPoint>,
-                                                &MainWindow::ApplyDialog<VToolShoulderPoint>);
+                                                &MainWindow::ClosedDrawDialogWithApply<VToolShoulderPoint>,
+                                                &MainWindow::ApplyDrawDialog<VToolShoulderPoint>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -776,8 +802,8 @@ void MainWindow::ToolNormal(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogNormal>(checked, Tool::Normal, ":/cursor/normal_cursor.png",
                                          tr("Select first point of line"),
-                                         &MainWindow::ClosedDialogWithApply<VToolNormal>,
-                                         &MainWindow::ApplyDialog<VToolNormal>);
+                                         &MainWindow::ClosedDrawDialogWithApply<VToolNormal>,
+                                         &MainWindow::ApplyDrawDialog<VToolNormal>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -790,8 +816,8 @@ void MainWindow::ToolBisector(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogBisector>(checked, Tool::Bisector, ":/cursor/bisector_cursor.png",
                                            tr("Select first point of angle"),
-                                           &MainWindow::ClosedDialogWithApply<VToolBisector>,
-                                           &MainWindow::ApplyDialog<VToolBisector>);
+                                           &MainWindow::ClosedDrawDialogWithApply<VToolBisector>,
+                                           &MainWindow::ApplyDrawDialog<VToolBisector>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -804,8 +830,8 @@ void MainWindow::ToolLineIntersect(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogLineIntersect>(checked, Tool::LineIntersect, ":/cursor/intersect_cursor.png",
                                                 tr("Select first point of first line"),
-                                                &MainWindow::ClosedDialogWithApply<VToolLineIntersect>,
-                                                &MainWindow::ApplyDialog<VToolLineIntersect>);
+                                                &MainWindow::ClosedDrawDialogWithApply<VToolLineIntersect>,
+                                                &MainWindow::ApplyDrawDialog<VToolLineIntersect>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -818,8 +844,8 @@ void MainWindow::ToolSpline(bool checked)
     ToolSelectPointByPress();
     SetToolButtonWithApply<DialogSpline>(checked, Tool::Spline, ":/cursor/spline_cursor.png",
                                          tr("Select first point curve"),
-                                         &MainWindow::ClosedDialogWithApply<VToolSpline>,
-                                         &MainWindow::ApplyDialog<VToolSpline>);
+                                         &MainWindow::ClosedDrawDialogWithApply<VToolSpline>,
+                                         &MainWindow::ApplyDrawDialog<VToolSpline>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -828,8 +854,8 @@ void MainWindow::ToolCubicBezier(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogCubicBezier>(checked, Tool::CubicBezier, ":/cursor/cubic_bezier_cursor.png",
                                               tr("Select first curve point"),
-                                              &MainWindow::ClosedDialogWithApply<VToolCubicBezier>,
-                                              &MainWindow::ApplyDialog<VToolCubicBezier>);
+                                              &MainWindow::ClosedDrawDialogWithApply<VToolCubicBezier>,
+                                              &MainWindow::ApplyDrawDialog<VToolCubicBezier>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -842,8 +868,8 @@ void MainWindow::ToolCutSpline(bool checked)
     ToolSelectSpline();
     SetToolButtonWithApply<DialogCutSpline>(checked, Tool::CutSpline, ":/cursor/spline_cut_point_cursor.png",
                                             tr("Select simple curve"),
-                                            &MainWindow::ClosedDialogWithApply<VToolCutSpline>,
-                                            &MainWindow::ApplyDialog<VToolCutSpline>);
+                                            &MainWindow::ClosedDrawDialogWithApply<VToolCutSpline>,
+                                            &MainWindow::ApplyDrawDialog<VToolCutSpline>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -855,8 +881,8 @@ void MainWindow::ToolArc(bool checked)
 {
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogArc>(checked, Tool::Arc, ":/cursor/arc_cursor.png",
-                                      tr("Select point of center of arc"), &MainWindow::ClosedDialogWithApply<VToolArc>,
-                                      &MainWindow::ApplyDialog<VToolArc>);
+                                      tr("Select point of center of arc"), &MainWindow::ClosedDrawDialogWithApply<VToolArc>,
+                                      &MainWindow::ApplyDrawDialog<VToolArc>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -869,8 +895,8 @@ void MainWindow::ToolSplinePath(bool checked)
     ToolSelectPointByPress();
     SetToolButtonWithApply<DialogSplinePath>(checked, Tool::SplinePath, ":/cursor/splinepath_cursor.png",
                                              tr("Select point of curve path"),
-                                             &MainWindow::ClosedDialogWithApply<VToolSplinePath>,
-                                             &MainWindow::ApplyDialog<VToolSplinePath>);
+                                             &MainWindow::ClosedDrawDialogWithApply<VToolSplinePath>,
+                                             &MainWindow::ApplyDrawDialog<VToolSplinePath>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -880,8 +906,8 @@ void MainWindow::ToolCubicBezierPath(bool checked)
     SetToolButtonWithApply<DialogCubicBezierPath>(checked, Tool::CubicBezierPath,
                                                   ":/cursor/cubic_bezier_path_cursor.png",
                                                   tr("Select point of cubic bezier path"),
-                                                  &MainWindow::ClosedDialogWithApply<VToolCubicBezierPath>,
-                                                  &MainWindow::ApplyDialog<VToolCubicBezierPath>);
+                                                  &MainWindow::ClosedDrawDialogWithApply<VToolCubicBezierPath>,
+                                                  &MainWindow::ApplyDrawDialog<VToolCubicBezierPath>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -894,8 +920,8 @@ void MainWindow::ToolCutSplinePath(bool checked)
     ToolSelectSplinePath();
     SetToolButtonWithApply<DialogCutSplinePath>(checked, Tool::CutSplinePath,
                                                 ":/cursor/splinepath_cut_point_cursor.png", tr("Select curve path"),
-                                                &MainWindow::ClosedDialogWithApply<VToolCutSplinePath>,
-                                                &MainWindow::ApplyDialog<VToolCutSplinePath>);
+                                                &MainWindow::ClosedDrawDialogWithApply<VToolCutSplinePath>,
+                                                &MainWindow::ApplyDrawDialog<VToolCutSplinePath>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -908,8 +934,8 @@ void MainWindow::ToolPointOfContact(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogPointOfContact>(checked, Tool::PointOfContact, ":/cursor/pointcontact_cursor.png",
                                                  tr("Select first point of line"),
-                                                 &MainWindow::ClosedDialogWithApply<VToolPointOfContact>,
-                                                 &MainWindow::ApplyDialog<VToolPointOfContact>);
+                                                 &MainWindow::ClosedDrawDialogWithApply<VToolPointOfContact>,
+                                                 &MainWindow::ApplyDrawDialog<VToolPointOfContact>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -922,8 +948,8 @@ void MainWindow::ToolDetail(bool checked)
     ToolSelectAllDrawObjects();
     SetToolButtonWithApply<DialogSeamAllowance>(checked, Tool::Piece, "://cursor/new_detail_cursor.png",
                                                 tr("Select main path objects clockwise."),
-                                                &MainWindow::ClosedDialogWithApply<VToolSeamAllowance>,
-                                                &MainWindow::ApplyDialog<VToolSeamAllowance>);
+                                                &MainWindow::ClosedDetailsDialogWithApply<VToolSeamAllowance>,
+                                                &MainWindow::ApplyDetailsDialog<VToolSeamAllowance>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -950,8 +976,8 @@ void MainWindow::ToolHeight(bool checked)
 {
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogHeight>(checked, Tool::Height, ":/cursor/height_cursor.png", tr("Select base point"),
-                                         &MainWindow::ClosedDialogWithApply<VToolHeight>,
-                                         &MainWindow::ApplyDialog<VToolHeight>);
+                                         &MainWindow::ClosedDrawDialogWithApply<VToolHeight>,
+                                         &MainWindow::ApplyDrawDialog<VToolHeight>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -964,8 +990,8 @@ void MainWindow::ToolTriangle(bool checked)
     ToolSelectPointByRelease();
     SetToolButtonWithApply<DialogTriangle>(checked, Tool::Triangle, ":/cursor/triangle_cursor.png",
                                            tr("Select first point of axis"),
-                                           &MainWindow::ClosedDialogWithApply<VToolTriangle>,
-                                           &MainWindow::ApplyDialog<VToolTriangle>);
+                                           &MainWindow::ClosedDrawDialogWithApply<VToolTriangle>,
+                                           &MainWindow::ApplyDrawDialog<VToolTriangle>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -979,8 +1005,8 @@ void MainWindow::ToolPointOfIntersection(bool checked)
     SetToolButtonWithApply<DialogPointOfIntersection>(checked, Tool::PointOfIntersection,
                                                       ":/cursor/pointofintersect_cursor.png",
                                                       tr("Select point for X value (vertical)"),
-                                                      &MainWindow::ClosedDialogWithApply<VToolPointOfIntersection>,
-                                                      &MainWindow::ApplyDialog<VToolPointOfIntersection>);
+                                                      &MainWindow::ClosedDrawDialogWithApply<VToolPointOfIntersection>,
+                                                      &MainWindow::ApplyDrawDialog<VToolPointOfIntersection>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1022,8 +1048,8 @@ void MainWindow::ToolRotation(bool checked)
     SetToolButtonWithApply<DialogRotation>(checked, Tool::Rotation,
                                            ":/cursor/rotation_cursor.png",
                                            tr("Select one or more objects, <b>Enter</b> - confirm selection"),
-                                           &MainWindow::ClosedDialogWithApply<VToolRotation>,
-                                           &MainWindow::ApplyDialog<VToolRotation>);
+                                           &MainWindow::ClosedDrawDialogWithApply<VToolRotation>,
+                                           &MainWindow::ApplyDrawDialog<VToolRotation>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1033,8 +1059,8 @@ void MainWindow::ToolFlippingByLine(bool checked)
     SetToolButtonWithApply<DialogFlippingByLine>(checked, Tool::FlippingByLine,
                                            ":/cursor/flipping_line_cursor.png",
                                            tr("Select one or more objects, <b>Enter</b> - confirm selection"),
-                                           &MainWindow::ClosedDialogWithApply<VToolFlippingByLine>,
-                                           &MainWindow::ApplyDialog<VToolFlippingByLine>);
+                                           &MainWindow::ClosedDrawDialogWithApply<VToolFlippingByLine>,
+                                           &MainWindow::ApplyDrawDialog<VToolFlippingByLine>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1044,8 +1070,8 @@ void MainWindow::ToolFlippingByAxis(bool checked)
     SetToolButtonWithApply<DialogFlippingByAxis>(checked, Tool::FlippingByAxis,
                                            ":/cursor/flipping_axis_cursor.png",
                                            tr("Select one or more objects, <b>Enter</b> - confirm selection"),
-                                           &MainWindow::ClosedDialogWithApply<VToolFlippingByAxis>,
-                                                 &MainWindow::ApplyDialog<VToolFlippingByAxis>);
+                                           &MainWindow::ClosedDrawDialogWithApply<VToolFlippingByAxis>,
+                                                 &MainWindow::ApplyDrawDialog<VToolFlippingByAxis>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1055,8 +1081,8 @@ void MainWindow::ToolMove(bool checked)
     SetToolButtonWithApply<DialogMove>(checked, Tool::Move,
                                          ":/cursor/move_cursor.png",
                                          tr("Select one or more objects, <b>Enter</b> - confirm selection"),
-                                         &MainWindow::ClosedDialogWithApply<VToolMove>,
-                                         &MainWindow::ApplyDialog<VToolMove>);
+                                         &MainWindow::ClosedDrawDialogWithApply<VToolMove>,
+                                         &MainWindow::ApplyDrawDialog<VToolMove>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1087,8 +1113,8 @@ void MainWindow::ToolCutArc(bool checked)
 {
     ToolSelectArc();
     SetToolButtonWithApply<DialogCutArc>(checked, Tool::CutArc, ":/cursor/arc_cut_cursor.png",
-                                         tr("Select arc"), &MainWindow::ClosedDialogWithApply<VToolCutArc>,
-                                         &MainWindow::ApplyDialog<VToolCutArc>);
+                                         tr("Select arc"), &MainWindow::ClosedDrawDialogWithApply<VToolCutArc>,
+                                         &MainWindow::ApplyDrawDialog<VToolCutArc>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1098,8 +1124,8 @@ void MainWindow::ToolLineIntersectAxis(bool checked)
     SetToolButtonWithApply<DialogLineIntersectAxis>(checked, Tool::LineIntersectAxis,
                                                     ":/cursor/line_intersect_axis_cursor.png",
                                                     tr("Select first point of line"),
-                                                    &MainWindow::ClosedDialogWithApply<VToolLineIntersectAxis>,
-                                                    &MainWindow::ApplyDialog<VToolLineIntersectAxis>);
+                                                    &MainWindow::ClosedDrawDialogWithApply<VToolLineIntersectAxis>,
+                                                    &MainWindow::ApplyDrawDialog<VToolLineIntersectAxis>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1109,8 +1135,8 @@ void MainWindow::ToolCurveIntersectAxis(bool checked)
     SetToolButtonWithApply<DialogCurveIntersectAxis>(checked, Tool::CurveIntersectAxis,
                                                      ":/cursor/curve_intersect_axis_cursor.png",
                                                      tr("Select curve"),
-                                                     &MainWindow::ClosedDialogWithApply<VToolCurveIntersectAxis>,
-                                                     &MainWindow::ApplyDialog<VToolCurveIntersectAxis>);
+                                                     &MainWindow::ClosedDrawDialogWithApply<VToolCurveIntersectAxis>,
+                                                     &MainWindow::ApplyDrawDialog<VToolCurveIntersectAxis>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1121,8 +1147,8 @@ void MainWindow::ToolArcIntersectAxis(bool checked)
     SetToolButtonWithApply<DialogCurveIntersectAxis>(checked, Tool::ArcIntersectAxis,
                                                      ":/cursor/arc_intersect_axis_cursor.png",
                                                      tr("Select arc"),
-                                                     &MainWindow::ClosedDialogWithApply<VToolCurveIntersectAxis>,
-                                                     &MainWindow::ApplyDialog<VToolCurveIntersectAxis>);
+                                                     &MainWindow::ClosedDrawDialogWithApply<VToolCurveIntersectAxis>,
+                                                     &MainWindow::ApplyDrawDialog<VToolCurveIntersectAxis>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1132,8 +1158,8 @@ void MainWindow::ToolPointOfIntersectionArcs(bool checked)
     SetToolButtonWithApply<DialogPointOfIntersectionArcs>(checked, Tool::PointOfIntersectionArcs,
                                                           "://cursor/point_of_intersection_arcs.png",
                                                           tr("Select first an arc"),
-                                                       &MainWindow::ClosedDialogWithApply<VToolPointOfIntersectionArcs>,
-                                                          &MainWindow::ApplyDialog<VToolPointOfIntersectionArcs>);
+                                                       &MainWindow::ClosedDrawDialogWithApply<VToolPointOfIntersectionArcs>,
+                                                          &MainWindow::ApplyDrawDialog<VToolPointOfIntersectionArcs>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1143,8 +1169,8 @@ void MainWindow::ToolPointOfIntersectionCircles(bool checked)
     SetToolButtonWithApply<DialogPointOfIntersectionCircles>(checked, Tool::PointOfIntersectionCircles,
                                                              "://cursor/point_of_intersection_circles.png",
                                                              tr("Select first circle center"),
-                                                    &MainWindow::ClosedDialogWithApply<VToolPointOfIntersectionCircles>,
-                                                             &MainWindow::ApplyDialog<VToolPointOfIntersectionCircles>);
+                                                    &MainWindow::ClosedDrawDialogWithApply<VToolPointOfIntersectionCircles>,
+                                                             &MainWindow::ApplyDrawDialog<VToolPointOfIntersectionCircles>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1154,8 +1180,8 @@ void MainWindow::ToolPointOfIntersectionCurves(bool checked)
     SetToolButtonWithApply<DialogPointOfIntersectionCurves>(checked, Tool::PointOfIntersectionCurves,
                                                              "://cursor/intersection_curves_cursor.png",
                                                              tr("Select first curve"),
-                                                    &MainWindow::ClosedDialogWithApply<VToolPointOfIntersectionCurves>,
-                                                             &MainWindow::ApplyDialog<VToolPointOfIntersectionCurves>);
+                                                    &MainWindow::ClosedDrawDialogWithApply<VToolPointOfIntersectionCurves>,
+                                                             &MainWindow::ApplyDrawDialog<VToolPointOfIntersectionCurves>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1165,8 +1191,8 @@ void MainWindow::ToolPointFromCircleAndTangent(bool checked)
     SetToolButtonWithApply<DialogPointFromCircleAndTangent>(checked, Tool::PointFromCircleAndTangent,
                                                             "://cursor/point_from_circle_and_tangent_cursor.png",
                                                             tr("Select point on tangent"),
-                                                    &MainWindow::ClosedDialogWithApply<VToolPointFromCircleAndTangent>,
-                                                            &MainWindow::ApplyDialog<VToolPointFromCircleAndTangent>);
+                                                    &MainWindow::ClosedDrawDialogWithApply<VToolPointFromCircleAndTangent>,
+                                                            &MainWindow::ApplyDrawDialog<VToolPointFromCircleAndTangent>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1176,8 +1202,8 @@ void MainWindow::ToolPointFromArcAndTangent(bool checked)
     SetToolButtonWithApply<DialogPointFromArcAndTangent>(checked, Tool::PointFromArcAndTangent,
                                                          "://cursor/point_from_arc_and_tangent_cursor.png",
                                                          tr("Select point on tangent"),
-                                                        &MainWindow::ClosedDialogWithApply<VToolPointFromArcAndTangent>,
-                                                         &MainWindow::ApplyDialog<VToolPointFromArcAndTangent>);
+                                                        &MainWindow::ClosedDrawDialogWithApply<VToolPointFromArcAndTangent>,
+                                                         &MainWindow::ApplyDrawDialog<VToolPointFromArcAndTangent>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1187,8 +1213,8 @@ void MainWindow::ToolArcWithLength(bool checked)
     SetToolButtonWithApply<DialogArcWithLength>(checked, Tool::ArcWithLength,
                                                 "://cursor/arc_with_length_cursor.png",
                                                 tr("Select point of the center of the arc"),
-                                                &MainWindow::ClosedDialogWithApply<VToolArcWithLength>,
-                                                &MainWindow::ApplyDialog<VToolArcWithLength>);
+                                                &MainWindow::ClosedDrawDialogWithApply<VToolArcWithLength>,
+                                                &MainWindow::ApplyDrawDialog<VToolArcWithLength>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1198,8 +1224,8 @@ void MainWindow::ToolTrueDarts(bool checked)
     SetToolButtonWithApply<DialogTrueDarts>(checked, Tool::TrueDarts,
                                                 "://cursor/true_darts_cursor.png",
                                                 tr("Select the first base line point"),
-                                                &MainWindow::ClosedDialogWithApply<VToolTrueDarts>,
-                                            &MainWindow::ApplyDialog<VToolTrueDarts>);
+                                                &MainWindow::ClosedDrawDialogWithApply<VToolTrueDarts>,
+                                            &MainWindow::ApplyDrawDialog<VToolTrueDarts>);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h
index 8bc530b0c..34851eaf5 100644
--- a/src/app/valentina/mainwindow.h
+++ b/src/app/valentina/mainwindow.h
@@ -282,10 +282,20 @@ private:
                                               Func closeDialogSlot, Func2 applyDialogSlot);
     template <typename DrawTool>
     void               ClosedDialog(int result);
+
     template <typename DrawTool>
-    void               ClosedDialogWithApply(int result);
+    void ClosedDialogWithApply(int result, VMainGraphicsScene *scene);
     template <typename DrawTool>
-    void               ApplyDialog();
+    void ApplyDialog(VMainGraphicsScene *scene);
+    template <typename DrawTool>
+    void ClosedDrawDialogWithApply(int result);
+    template <typename DrawTool>
+    void ApplyDrawDialog();
+    template <typename DrawTool>
+    void ClosedDetailsDialogWithApply(int result);
+    template <typename DrawTool>
+    void ApplyDetailsDialog();
+
     bool               SavePattern(const QString &curFile, QString &error);
     void               AutoSavePattern();
     void               setCurrentFile(const QString &fileName);

From 4cfcf5ad8dfcae95ac8759753ff8334a63e696fd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 16:32:18 +0200
Subject: [PATCH 023/208] New pattern format version 0.4.0.

Convert tag detail to new version.

--HG--
branch : feature
---
 src/libs/ifc/schema.qrc                |   1 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd | 634 +++++++++++++++++++++++++
 src/libs/ifc/xml/vpatternconverter.cpp | 110 ++++-
 src/libs/ifc/xml/vpatternconverter.h   |   7 +-
 4 files changed, 748 insertions(+), 4 deletions(-)
 create mode 100644 src/libs/ifc/schema/pattern/v0.4.0.xsd

diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc
index 33ca3fdf5..3e40a2a66 100644
--- a/src/libs/ifc/schema.qrc
+++ b/src/libs/ifc/schema.qrc
@@ -22,6 +22,7 @@
         <file>schema/pattern/v0.3.6.xsd</file>
         <file>schema/pattern/v0.3.7.xsd</file>
         <file>schema/pattern/v0.3.8.xsd</file>
+        <file>schema/pattern/v0.4.0.xsd</file>
         <file>schema/standard_measurements/v0.3.0.xsd</file>
         <file>schema/standard_measurements/v0.4.0.xsd</file>
         <file>schema/standard_measurements/v0.4.1.xsd</file>
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
new file mode 100644
index 000000000..eb822a1c5
--- /dev/null
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -0,0 +1,634 @@
+<?xml version="1.0" encoding="UTF-8"?>
+   <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+         <!-- XML Schema Generated from XML Document-->
+         <xs:element name="pattern">
+               <xs:complexType>
+                     <xs:sequence minOccurs="1" maxOccurs="unbounded">
+                            <xs:element name="version" type="formatVersion"></xs:element>
+                            <xs:element name="unit" type="units"></xs:element>
+                            <xs:element name="image" minOccurs="0" maxOccurs="1">
+                                <xs:complexType>
+                                 <xs:simpleContent>
+                                    <xs:extension base="xs:string">
+                                       <xs:attribute name="extension" type="imageExtension"></xs:attribute>
+                                    </xs:extension>
+                                 </xs:simpleContent>
+                                </xs:complexType>
+                            </xs:element>
+                            <xs:element name="author" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="gradation" minOccurs="0" maxOccurs="1">
+                                <xs:complexType>
+                                       <xs:sequence>
+                                             <xs:element name="heights">
+                                                   <xs:complexType>
+                                                         <xs:attribute name="all" type="xs:boolean" use="required"></xs:attribute>
+                                                         <xs:attribute name="h50" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h56" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h62" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h68" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h74" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h80" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h86" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h92" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h98" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h104" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h110" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h116" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h122" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h128" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h134" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h140" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h146" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h152" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h158" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h164" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h170" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h176" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h182" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h188" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="h194" type="xs:boolean"></xs:attribute>       
+                                                   </xs:complexType>
+                                             </xs:element>
+                                             <xs:element name="sizes">
+                                                   <xs:complexType>
+                                                         <xs:attribute name="all" type="xs:boolean" use="required"></xs:attribute>
+                                                         <xs:attribute name="s22" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s24" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s26" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s28" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s30" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s32" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s34" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s36" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s38" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s40" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s42" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s44" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s46" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s48" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s50" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s52" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s54" type="xs:boolean"></xs:attribute>
+                                                         <xs:attribute name="s56" type="xs:boolean"></xs:attribute>    
+                                                   </xs:complexType>
+                                             </xs:element>
+                                       </xs:sequence>
+                                       <xs:attribute name="custom" type="xs:boolean"></xs:attribute>
+                                       <xs:attribute name="defHeight" type="baseHeight"></xs:attribute>
+                                       <xs:attribute name="defSize" type="baseSize"></xs:attribute>
+                                 </xs:complexType>
+                            </xs:element>
+                            <xs:element name="patternName" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="patternNumber" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="company" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="customer" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="size" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="showDate" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
+                            <xs:element name="showMeasurements" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
+                           <xs:element name="measurements" type="xs:string"></xs:element>
+                           <xs:element name="increments" minOccurs="0" maxOccurs="1">
+                                 <xs:complexType>
+                                       <xs:sequence minOccurs="0" maxOccurs="unbounded">
+                                             <xs:element name="increment" minOccurs="0" maxOccurs="unbounded">
+                                                   <xs:complexType>
+                                                         <xs:attribute name="description" type="xs:string" use="required"></xs:attribute>
+                                                         <xs:attribute name="name" type="shortName" use="required"></xs:attribute>
+                                                         <xs:attribute name="formula" type="xs:string" use="required"></xs:attribute>      
+                                                   </xs:complexType>
+                                             </xs:element>
+                                       </xs:sequence>
+                                 </xs:complexType>
+                                 <xs:unique name="incrementName">
+                                    <xs:selector xpath="increment"/>
+                                    <xs:field xpath="@name"/>
+                                 </xs:unique>
+                           </xs:element>
+                           <xs:element name="draw" minOccurs="1" maxOccurs="unbounded">
+                                 <xs:complexType>
+                                       <xs:sequence>
+                                             <xs:element name="calculation" minOccurs="1" maxOccurs="unbounded">
+                                                   <xs:complexType>
+                                                         <xs:sequence>
+                                                               <xs:choice minOccurs="0" maxOccurs="unbounded">   
+                                                                     <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="x" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="y" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="name" type="shortName"></xs:attribute>
+                                                                                 <xs:attribute name="firstPoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="secondPoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="thirdPoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="basePoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="pShoulder" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p1Line" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p2Line" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="angle" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="splinePath" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="spline" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p1Line1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p1Line2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p2Line1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p2Line2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="radius" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="axisP1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="axisP2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="arc" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="curve" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="curve1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="curve2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="lineColor" type="colors"></xs:attribute>
+                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
+                                                                                 <xs:attribute name="firstArc" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="secondArc" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="crossPoint" type="crossType"></xs:attribute>
+                                                                                 <xs:attribute name="vCrossPoint" type="crossType"></xs:attribute>
+                                                                                 <xs:attribute name="hCrossPoint" type="crossType"></xs:attribute>
+                                                                                 <xs:attribute name="c1Center" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="c2Center" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="c1Radius" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="c2Radius" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="cRadius" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="tangent" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="cCenter" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="name1" type="shortName"></xs:attribute>
+                                                                                 <xs:attribute name="mx1" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="my1" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="name2" type="shortName"></xs:attribute>
+                                                                                 <xs:attribute name="mx2" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="my2" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="point1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="point2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="dartP1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="dartP2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="dartP3" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="baseLineP1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="baseLineP2" type="xs:unsignedInt"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>                                                              
+                                                                     <xs:element name="line" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="firstPoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="secondPoint" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="lineColor" type="colors"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element> 
+                                                                     <xs:element name="operation" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+																			     <xs:sequence>
+                                                                                       <xs:element name="source" minOccurs="1" maxOccurs="1">
+                                                                                             <xs:complexType>
+																								   <xs:sequence>
+																									   <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
+																											 <xs:complexType>
+																												<xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
+																											 </xs:complexType>
+																									   </xs:element>
+																								   </xs:sequence>	   
+                                                                                             </xs:complexType>
+                                                                                       </xs:element>
+                                                                                       <xs:element name="destination" minOccurs="1" maxOccurs="1">
+                                                                                             <xs:complexType>
+																								   <xs:sequence>
+																									   <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
+																											 <xs:complexType>
+																												<xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                                                <xs:attribute name="mx" type="xs:double"></xs:attribute>
+																								                <xs:attribute name="my" type="xs:double"></xs:attribute>
+																											 </xs:complexType>
+																									   </xs:element>
+																								   </xs:sequence>
+                                                                                             </xs:complexType>
+                                                                                       </xs:element>
+                                                                                 </xs:sequence>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="angle" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="suffix" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="p1Line" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="p2Line" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="axisType" type="axisType"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element> 
+                                                                     <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="angle1" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="angle2" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="radius" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
+                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
+                                                                     <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:sequence>
+                                                                                       <xs:element name="pathPoint" minOccurs="0" maxOccurs="unbounded">
+                                                                                             <xs:complexType>
+                                                                                                   <xs:attribute name="kAsm2" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="pSpline" type="xs:unsignedInt"></xs:attribute>
+                                                                                                   <xs:attribute name="angle" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="angle1" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="angle2" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="length1" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="length2" type="xs:string"></xs:attribute>
+                                                                                                   <xs:attribute name="kAsm1" type="xs:string"></xs:attribute>
+                                                                                             </xs:complexType>
+                                                                                       </xs:element>
+                                                                                 </xs:sequence>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="kCurve" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="kAsm1" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="kAsm2" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="angle1" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="angle2" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="length1" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="length2" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="point1" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="point2" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="point3" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="point4" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
+                                                                                 <xs:attribute name="duplicate" type="xs:unsignedInt"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
+                                                               </xs:choice>
+                                                         </xs:sequence>
+                                                   </xs:complexType>
+                                             </xs:element>
+                                             <xs:element name="modeling" minOccurs="1" maxOccurs="unbounded">
+                                                   <xs:complexType>
+                                                         <xs:sequence>
+                                                               <xs:choice minOccurs="0" maxOccurs="unbounded">
+                                                                     <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
+                                                                     <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
+                                                                     <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
+                                                                     <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">
+                                                                       <xs:complexType>
+                                                                             <xs:sequence>
+                                                                                   <xs:element name="det" minOccurs="2" maxOccurs="2">
+                                                                                         <xs:complexType>
+                                                                                               <xs:sequence>
+                                                                                                     <xs:element name="node" maxOccurs="unbounded">
+                                                                                                           <xs:complexType>
+                                                                                                                 <xs:attribute name="nodeType" type="xs:string"></xs:attribute>
+                                                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+                                                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                                                                 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+                                                                                                           </xs:complexType>
+                                                                                                     </xs:element>
+                                                                                               </xs:sequence>
+                                                                                         </xs:complexType>
+                                                                                   </xs:element>
+                                                                                   <xs:element name="children" minOccurs="0" maxOccurs="1">
+                                                                                         <xs:complexType>
+                                                                                               <xs:sequence>
+                                                                                                     <xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
+                                                                                               </xs:sequence>
+                                                                                         </xs:complexType>
+                                                                                   </xs:element>
+                                                                             </xs:sequence>
+                                                                             <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                             <xs:attribute name="type" type="xs:string"></xs:attribute>
+                                                                             <xs:attribute name="indexD1" type="xs:unsignedInt"></xs:attribute>
+                                                                             <xs:attribute name="indexD2" type="xs:unsignedInt"></xs:attribute>
+                                                                             <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                       </xs:complexType>
+                                                                    </xs:element>
+                                                               </xs:choice>           
+                                                         </xs:sequence>
+                                                   </xs:complexType>
+                                             </xs:element>
+                                             <xs:element name="details" minOccurs="1" maxOccurs="unbounded">
+                                                   <xs:complexType>
+                                                         <xs:sequence>
+                                                               <xs:element name="detail" minOccurs="0" maxOccurs="unbounded">
+                                                                     <xs:complexType>
+                                                                           <xs:sequence>
+                                                                               <xs:element name="data" minOccurs="0" maxOccurs="1">
+                                                                                   <xs:complexType>
+                                                                                       <xs:sequence>
+                                                                                           <xs:element name="mcp" minOccurs="0" maxOccurs="unbounded">
+                                                                                               <xs:complexType>
+                                                                                                   <xs:attribute name="cutNumber" type="xs:unsignedInt"/>
+                                                                                                   <xs:attribute name="userDef" type="xs:string"/>
+                                                                                                   <xs:attribute name="material" type="materialType"/>
+                                                                                                   <xs:attribute name="placement" type="placementType"/>
+                                                                                               </xs:complexType>
+                                                                                           </xs:element>
+                                                                                       </xs:sequence>
+                                                                                       <xs:attribute name="letter" type="xs:string"></xs:attribute>
+                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
+                                                                                       <xs:attribute name="fontSize" type="xs:unsignedInt"></xs:attribute>
+                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="width" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="height" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="rotation" type="xs:double"></xs:attribute>
+                                                                                   </xs:complexType>
+                                                                               </xs:element>
+                                                                               <xs:element name="patternInfo" minOccurs="0" maxOccurs="1">
+                                                                                   <xs:complexType>
+                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
+                                                                                       <xs:attribute name="fontSize" type="xs:unsignedInt"></xs:attribute>
+                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="width" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="height" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="rotation" type="xs:double"></xs:attribute>
+                                                                                   </xs:complexType>
+                                                                               </xs:element>
+                                                                               <xs:element name="grainline" minOccurs="0" maxOccurs="1">
+                                                                                   <xs:complexType>
+                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
+                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                                       <xs:attribute name="length" type="xs:string"></xs:attribute>
+                                                                                       <xs:attribute name="rotation" type="xs:string"></xs:attribute>
+										       <xs:attribute name="arrows" type="arrowType"></xs:attribute>
+                                                                                    </xs:complexType>
+                                                                               </xs:element>
+                                                                               <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+																					<xs:complexType>
+																						<xs:sequence>
+																						   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+																								   <xs:complexType>
+																										 <xs:attribute name="type" type="xs:string"></xs:attribute>
+																										 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+																								   </xs:complexType>
+																							 </xs:element>
+																						 </xs:sequence>
+																					 </xs:complexType>
+																				</xs:element>
+                                                                           </xs:sequence>
+                                                                           <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                           <xs:attribute name="version" type="pieceVersion"></xs:attribute>
+                                                                           <xs:attribute name="mx" type="xs:double"></xs:attribute>
+                                                                           <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                     </xs:complexType>
+                                                               </xs:element>
+                                                         </xs:sequence>
+                                                   </xs:complexType>
+                                             </xs:element>
+                                             <xs:element name="groups" minOccurs="0" maxOccurs="1">
+                                                   <xs:complexType>
+                                                         <xs:sequence>
+                                                               <xs:element name="group" minOccurs="0" maxOccurs="unbounded">
+                                                                     <xs:complexType>
+                                                                           <xs:sequence>
+                                                                                 <xs:element name="item" maxOccurs="unbounded">
+                                                                                       <xs:complexType>
+                                                                                             <xs:attribute name="object" type="xs:unsignedInt"></xs:attribute>
+                                                                                             <xs:attribute name="tool" type="xs:unsignedInt"></xs:attribute>
+                                                                                       </xs:complexType>
+                                                                                 </xs:element>
+                                                                           </xs:sequence>
+                                                                           <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                           <xs:attribute name="name" type="xs:string"></xs:attribute>
+                                                                           <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
+                                                                     </xs:complexType>
+                                                               </xs:element>
+                                                         </xs:sequence>
+                                                   </xs:complexType>
+                                             </xs:element>
+                                       </xs:sequence>
+                                       <xs:attribute name="name" type="xs:string"></xs:attribute>
+                                 </xs:complexType>
+                           </xs:element>
+                     </xs:sequence>
+					 <xs:attribute name="readOnly" type="xs:boolean"></xs:attribute>
+               </xs:complexType>
+         </xs:element>
+    <xs:simpleType name="shortName">
+        <xs:restriction base="xs:string">   
+            <xs:pattern value="^([^0-9*/^+\-=\s()?%:;!.,`'\&quot;]){1,1}([^*/^+\-=\s()?%:;!.,`'\&quot;]){0,}$"/>
+        </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="measurementsTypes">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="standard"/>
+            <xs:enumeration value="individual"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="formatVersion">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
+        </xs:restriction>
+    </xs:simpleType>
+     <xs:simpleType name="imageExtension">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="PNG"/>
+            <xs:enumeration value="JPG"/>
+            <xs:enumeration value="BMP"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="colors">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="black"/>
+            <xs:enumeration value="green"/>
+            <xs:enumeration value="blue"/>
+            <xs:enumeration value="darkRed"/>
+            <xs:enumeration value="darkGreen"/>
+            <xs:enumeration value="darkBlue"/>
+            <xs:enumeration value="yellow"/>
+            <xs:enumeration value="lightsalmon"/>
+            <xs:enumeration value="goldenrod"/>
+            <xs:enumeration value="orange"/>
+            <xs:enumeration value="deeppink"/>
+            <xs:enumeration value="violet"/>
+            <xs:enumeration value="darkviolet"/>
+            <xs:enumeration value="mediumseagreen"/>
+            <xs:enumeration value="lime"/>
+            <xs:enumeration value="deepskyblue"/>
+            <xs:enumeration value="cornflowerblue"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="baseHeight">
+        <xs:restriction base="xs:unsignedInt">
+            <xs:enumeration value="50"/>
+            <xs:enumeration value="56"/>
+            <xs:enumeration value="62"/>
+            <xs:enumeration value="68"/>
+            <xs:enumeration value="74"/>
+            <xs:enumeration value="80"/>
+            <xs:enumeration value="86"/>
+            <xs:enumeration value="92"/>
+            <xs:enumeration value="98"/>
+            <xs:enumeration value="104"/>
+            <xs:enumeration value="110"/>
+            <xs:enumeration value="116"/>
+            <xs:enumeration value="122"/>
+            <xs:enumeration value="128"/>
+            <xs:enumeration value="134"/>
+            <xs:enumeration value="140"/>
+            <xs:enumeration value="146"/>
+            <xs:enumeration value="152"/>
+            <xs:enumeration value="158"/>
+            <xs:enumeration value="164"/>
+            <xs:enumeration value="170"/>
+            <xs:enumeration value="176"/>
+            <xs:enumeration value="182"/>
+            <xs:enumeration value="188"/>
+            <xs:enumeration value="194"/>
+            <xs:enumeration value="500"/>
+            <xs:enumeration value="560"/>
+            <xs:enumeration value="620"/>
+            <xs:enumeration value="680"/>
+            <xs:enumeration value="740"/>
+            <xs:enumeration value="800"/>
+            <xs:enumeration value="860"/>
+            <xs:enumeration value="920"/>
+            <xs:enumeration value="980"/>
+            <xs:enumeration value="1040"/>
+            <xs:enumeration value="1100"/>
+            <xs:enumeration value="1160"/>
+            <xs:enumeration value="1220"/>
+            <xs:enumeration value="1280"/>
+            <xs:enumeration value="1340"/>
+            <xs:enumeration value="1400"/>
+            <xs:enumeration value="1460"/>
+            <xs:enumeration value="1520"/>
+            <xs:enumeration value="1580"/>
+            <xs:enumeration value="1640"/>
+            <xs:enumeration value="1700"/>
+            <xs:enumeration value="1760"/>
+            <xs:enumeration value="1820"/>
+            <xs:enumeration value="1880"/>
+            <xs:enumeration value="1940"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="baseSize">
+        <xs:restriction base="xs:unsignedInt">
+            <xs:enumeration value="22"/>
+            <xs:enumeration value="24"/>
+            <xs:enumeration value="26"/>
+            <xs:enumeration value="28"/>
+            <xs:enumeration value="30"/>
+            <xs:enumeration value="32"/>
+            <xs:enumeration value="34"/>
+            <xs:enumeration value="36"/>
+            <xs:enumeration value="38"/>
+            <xs:enumeration value="40"/>
+            <xs:enumeration value="42"/>
+            <xs:enumeration value="44"/>
+            <xs:enumeration value="46"/>
+            <xs:enumeration value="48"/>
+            <xs:enumeration value="50"/>
+            <xs:enumeration value="52"/>
+            <xs:enumeration value="54"/>
+            <xs:enumeration value="56"/>
+            <xs:enumeration value="220"/>
+            <xs:enumeration value="240"/>
+            <xs:enumeration value="260"/>
+            <xs:enumeration value="280"/>
+            <xs:enumeration value="300"/>
+            <xs:enumeration value="320"/>
+            <xs:enumeration value="340"/>
+            <xs:enumeration value="360"/>
+            <xs:enumeration value="380"/>
+            <xs:enumeration value="400"/>
+            <xs:enumeration value="420"/>
+            <xs:enumeration value="440"/>
+            <xs:enumeration value="460"/>
+            <xs:enumeration value="480"/>
+            <xs:enumeration value="500"/>
+            <xs:enumeration value="520"/>
+            <xs:enumeration value="540"/>
+            <xs:enumeration value="560"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="crossType">
+        <xs:restriction base="xs:unsignedInt">
+            <xs:enumeration value="1"/>
+            <xs:enumeration value="2"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="axisType">
+        <xs:restriction base="xs:unsignedInt">
+            <xs:enumeration value="1"/>
+            <xs:enumeration value="2"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="materialType">
+       <xs:restriction base="xs:unsignedInt">
+            <xs:enumeration value="0"/><!--Fabric-->
+            <xs:enumeration value="1"/><!--Lining-->
+            <xs:enumeration value="2"/><!--Interfacing-->
+            <xs:enumeration value="3"/><!--Interlining-->
+            <xs:enumeration value="4"/><!--UserDefined-->
+       </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType name="placementType">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="0"/><!--No placement-->
+       <xs:enumeration value="1"/><!--Cut on Fold-->
+     </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType name="arrowType">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="0"/><!--Both-->
+       <xs:enumeration value="1"/><!--Front-->
+       <xs:enumeration value="2"/><!--Rear-->
+     </xs:restriction>
+   </xs:simpleType>
+   <xs:simpleType name="pieceVersion">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="1"/><!--Old version-->
+       <xs:enumeration value="2"/><!--New version-->
+     </xs:restriction>
+   </xs:simpleType>
+   </xs:schema>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index deff9a092..cf12435a9 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -58,8 +58,8 @@ class QDomElement;
  */
 
 const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.0");
-const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.3.8");
-const QString VPatternConverter::CurrentSchema    = QStringLiteral("://schema/pattern/v0.3.8.xsd");
+const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.4.0");
+const QString VPatternConverter::CurrentSchema    = QStringLiteral("://schema/pattern/v0.4.0.xsd");
 
 //VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
 //VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@@ -115,6 +115,20 @@ const QString strPointFromArcAndTangent    = QStringLiteral("pointFromArcAndTang
 const QString strPointOfIntersectionArcs   = QStringLiteral("pointOfIntersectionArcs");
 const QString strFirstArc                  = QStringLiteral("firstArc");
 const QString strSecondArc                 = QStringLiteral("secondArc");
+const QString strDetail                    = QStringLiteral("detail");
+const QString strSupplement                = QStringLiteral("supplement");
+const QString strClosed                    = QStringLiteral("closed");
+const QString strWidth                     = QStringLiteral("width");
+const QString strNode                      = QStringLiteral("node");
+const QString strNodes                     = QStringLiteral("nodes");
+const QString strData                      = QStringLiteral("data");
+const QString strPatternInfo               = QStringLiteral("patternInfo");
+const QString strGrainline                 = QStringLiteral("grainline");
+const QString strReverse                   = QStringLiteral("reverse");
+const QString strMx                        = QStringLiteral("mx");
+const QString strMy                        = QStringLiteral("my");
+const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
+const QString strInLayout                  = QStringLiteral("inLayout");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)
@@ -175,6 +189,8 @@ QString VPatternConverter::XSDSchema(int ver) const
         case (0x000307):
             return QStringLiteral("://schema/pattern/v0.3.7.xsd");
         case (0x000308):
+            return QStringLiteral("://schema/pattern/v0.3.8.xsd");
+        case (0x000400):
             return CurrentSchema;
         default:
             InvalidVersion(ver);
@@ -274,6 +290,10 @@ void VPatternConverter::ApplyPatches()
                 ValidateXML(XSDSchema(0x000308), fileName);
                 V_FALLTHROUGH
             case (0x000308):
+                ToV0_4_0();
+                ValidateXML(XSDSchema(0x000400), fileName);
+                V_FALLTHROUGH
+            case (0x000400):
                 break;
             default:
                 break;
@@ -462,6 +482,14 @@ void VPatternConverter::ToV0_3_8()
     Save();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternConverter::ToV0_4_0()
+{
+    SetVersion(QStringLiteral("0.4.0"));
+    TagDetailToV0_4_0();
+    Save();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagUnitToV0_2_0()
 {
@@ -1467,3 +1495,81 @@ void VPatternConverter::FixSubPaths(int i, quint32 id, quint32 baseCurve)
         }
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternConverter::TagDetailToV0_4_0()
+{
+    const QDomNodeList list = elementsByTagName(strDetail);
+    for (int i=0; i < list.size(); ++i)
+    {
+        QDomElement dom = list.at(i).toElement();
+
+        if (not dom.isNull())
+        {
+            dom.removeAttribute(strName);
+            dom.removeAttribute(strSupplement);
+            dom.removeAttribute(strClosed);
+            dom.removeAttribute(strWidth);
+            dom.removeAttribute(strMx);
+            dom.removeAttribute(strMy);
+            dom.removeAttribute(strForbidFlipping);
+            dom.removeAttribute(strInLayout);
+
+            dom.setAttribute(strVersion, "1");
+
+            const QStringList tags = QStringList() << strNode << strData << strPatternInfo << strGrainline;
+
+            QDomElement tagData;
+            QDomElement tagPatternInfo;
+            QDomElement tagGrainline;
+            QDomElement tagNodes = createElement(strNodes);
+
+            const QDomNodeList childList = dom.childNodes();
+            for (qint32 i = 0; i < childList.size(); ++i)
+            {
+                const QDomElement element = childList.at(i).toElement();
+                if (not element.isNull())
+                {
+                    switch (tags.indexOf(element.tagName()))
+                    {
+                        case 0://strNode
+                        {
+                            QDomElement tagNode = createElement(strNode);
+
+                            tagNode.setAttribute(strIdObject, element.attribute(strIdObject, NULL_ID_STR));
+
+                            if (element.hasAttribute(strReverse))
+                            {
+                                tagNode.setAttribute(strReverse, element.attribute(strReverse, "0"));
+                            }
+
+                            tagNode.setAttribute(strType, element.attribute(strType, ""));
+
+                            tagNodes.appendChild(tagNode);
+
+                            break;
+                        }
+                        case 1://strData
+                            tagData = element.cloneNode().toElement();
+                            break;
+                        case 2://strPatternInfo
+                            tagPatternInfo = element.cloneNode().toElement();
+                            break;
+                        case 3://strGrainline
+                            tagGrainline = element.cloneNode().toElement();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            RemoveAllChildren(dom);
+
+            dom.appendChild(tagData);
+            dom.appendChild(tagPatternInfo);
+            dom.appendChild(tagGrainline);
+            dom.appendChild(tagNodes);
+        }
+    }
+}
diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h
index 267bbbfd5..483d8782b 100644
--- a/src/libs/ifc/xml/vpatternconverter.h
+++ b/src/libs/ifc/xml/vpatternconverter.h
@@ -55,10 +55,10 @@ public:
 // GCC 4.6 doesn't allow constexpr and const together
 #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) <= 406
     static Q_DECL_CONSTEXPR int PatternMinVer = CONVERTER_VERSION_CHECK(0, 1, 0);
-    static Q_DECL_CONSTEXPR int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 3, 8);
+    static Q_DECL_CONSTEXPR int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 4, 0);
 #else
     static Q_DECL_CONSTEXPR const int PatternMinVer = CONVERTER_VERSION_CHECK(0, 1, 0);
-    static Q_DECL_CONSTEXPR const int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 3, 8);
+    static Q_DECL_CONSTEXPR const int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 4, 0);
 #endif
 
 protected:
@@ -97,6 +97,7 @@ private:
     void ToV0_3_6();
     void ToV0_3_7();
     void ToV0_3_8();
+    void ToV0_4_0();
 
     void          TagUnitToV0_2_0();
     void          TagIncrementToV0_2_0();
@@ -132,6 +133,8 @@ private:
 
     void FixCutPoint();
     void FixSubPaths(int i, quint32 id, quint32 baseCurve);
+
+    void TagDetailToV0_4_0();
 };
 
 //---------------------------------------------------------------------------------------------------------------------

From b5061038babdfdb49b3e8b3cda0a247170b460b3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 16:34:44 +0200
Subject: [PATCH 024/208] Fix mistake. The next pattern format will be 0.4.0.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 62b260af5..6a856519f 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -296,8 +296,8 @@ void VToolSeamAllowance::RefreshDataInFile()
     {
         // Refresh only parts that we possibly need to update
         {
-            // TODO. Delete if minimal supported version is 0.5.0
-            Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 5, 0),
+            // TODO. Delete if minimal supported version is 0.4.0
+            Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
                               "Time to refactor the code.");
             doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
         }

From 5f6b39493472a84d1e32992d3a0072f1855e91b7 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 17:07:16 +0200
Subject: [PATCH 025/208] Added more static asserts to check minimally
 supported file format versions.

--HG--
branch : feature
---
 src/libs/ifc/xml/vpatternconverter.cpp | 188 +++++++++++++++++++++++++
 src/libs/ifc/xml/vvitconverter.cpp     |  44 ++++++
 src/libs/ifc/xml/vvstconverter.cpp     |  40 ++++++
 3 files changed, 272 insertions(+)

diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index cf12435a9..e4bbe71d7 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -328,6 +328,10 @@ void VPatternConverter::DowngradeToCurrentMaxVersion()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_1_1()
 {
+    // TODO. Delete if minimal supported version is 0.1.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 1),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.1.1"));
     Save();
 }
@@ -335,6 +339,10 @@ void VPatternConverter::ToV0_1_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_1_2()
 {
+    // TODO. Delete if minimal supported version is 0.1.2
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 2),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.1.2"));
     Save();
 }
@@ -342,6 +350,10 @@ void VPatternConverter::ToV0_1_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_1_3()
 {
+    // TODO. Delete if minimal supported version is 0.1.3
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 3),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.1.3"));
     Save();
 }
@@ -349,6 +361,10 @@ void VPatternConverter::ToV0_1_3()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_1_4()
 {
+    // TODO. Delete if minimal supported version is 0.1.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 4),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.1.4"));
     Save();
 }
@@ -356,6 +372,10 @@ void VPatternConverter::ToV0_1_4()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.0"));
     TagUnitToV0_2_0();
     TagIncrementToV0_2_0();
@@ -367,6 +387,10 @@ void VPatternConverter::ToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_1()
 {
+    // TODO. Delete if minimal supported version is 0.2.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 1),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.1"));
     ConvertMeasurementsToV0_2_1();
     Save();
@@ -375,6 +399,10 @@ void VPatternConverter::ToV0_2_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_2()
 {
+    // TODO. Delete if minimal supported version is 0.2.2
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 2),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.2"));
     Save();
 }
@@ -382,6 +410,10 @@ void VPatternConverter::ToV0_2_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_3()
 {
+    // TODO. Delete if minimal supported version is 0.2.3
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 3),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.3"));
     Save();
 }
@@ -389,6 +421,10 @@ void VPatternConverter::ToV0_2_3()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_4()
 {
+    // TODO. Delete if minimal supported version is 0.2.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 4),
+                      "Time to refactor the code.");
+
     FixToolUnionToV0_2_4();
     SetVersion(QStringLiteral("0.2.4"));
     Save();
@@ -397,6 +433,10 @@ void VPatternConverter::ToV0_2_4()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_5()
 {
+    // TODO. Delete if minimal supported version is 0.2.5
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 5),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.5"));
     Save();
 }
@@ -404,6 +444,10 @@ void VPatternConverter::ToV0_2_5()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_6()
 {
+    // TODO. Delete if minimal supported version is 0.2.6
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 6),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.6"));
     Save();
 }
@@ -411,6 +455,10 @@ void VPatternConverter::ToV0_2_6()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_2_7()
 {
+    // TODO. Delete if minimal supported version is 0.2.7
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 7),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.2.7"));
     Save();
 }
@@ -418,6 +466,10 @@ void VPatternConverter::ToV0_2_7()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_0()
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     //Cutting path do not create anymore subpaths
     FixCutPoint();
     FixCutPoint();
@@ -428,6 +480,10 @@ void VPatternConverter::ToV0_3_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_1()
 {
+    // TODO. Delete if minimal supported version is 0.3.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.1"));
     RemoveColorToolCutV0_3_1();
     Save();
@@ -436,6 +492,10 @@ void VPatternConverter::ToV0_3_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_2()
 {
+    // TODO. Delete if minimal supported version is 0.3.2
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.2"));
     Save();
 }
@@ -443,6 +503,10 @@ void VPatternConverter::ToV0_3_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_3()
 {
+    // TODO. Delete if minimal supported version is 0.3.3
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 3),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.3"));
     Save();
 }
@@ -450,6 +514,10 @@ void VPatternConverter::ToV0_3_3()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_4()
 {
+    // TODO. Delete if minimal supported version is 0.3.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 4),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.4"));
     Save();
 }
@@ -457,6 +525,10 @@ void VPatternConverter::ToV0_3_4()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_5()
 {
+    // TODO. Delete if minimal supported version is 0.3.5
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 5),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.5"));
     Save();
 }
@@ -464,6 +536,10 @@ void VPatternConverter::ToV0_3_5()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_6()
 {
+    // TODO. Delete if minimal supported version is 0.3.6
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 6),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.6"));
     Save();
 }
@@ -471,6 +547,10 @@ void VPatternConverter::ToV0_3_6()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_7()
 {
+    // TODO. Delete if minimal supported version is 0.3.7
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 7),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.7"));
     Save();
 }
@@ -478,6 +558,10 @@ void VPatternConverter::ToV0_3_7()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_3_8()
 {
+    // TODO. Delete if minimal supported version is 0.3.8
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 8),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.8"));
     Save();
 }
@@ -485,6 +569,10 @@ void VPatternConverter::ToV0_3_8()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ToV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.4.0"));
     TagDetailToV0_4_0();
     Save();
@@ -493,6 +581,10 @@ void VPatternConverter::ToV0_4_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagUnitToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QDomElement unit = createElement(strUnit);
     QDomText newNodeText = createTextNode(MUnitV0_1_4());
     unit.appendChild(newNodeText);
@@ -504,6 +596,10 @@ void VPatternConverter::TagUnitToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagIncrementToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     const QSet<QString> names = FixIncrementsToV0_2_0();
 
     FixPointExpressionsToV0_2_0(names);
@@ -514,6 +610,10 @@ void VPatternConverter::TagIncrementToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ConvertMeasurementsToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     const QMap<QString, QString> names = OldNamesToNewNames_InV0_2_0();
     ConvertPointExpressionsToV0_2_0(names);
     ConvertArcExpressionsToV0_2_0(names);
@@ -523,6 +623,10 @@ void VPatternConverter::ConvertMeasurementsToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 QSet<QString> VPatternConverter::FixIncrementsToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QSet<QString> names;
     const QDomElement incr = TagIncrementsV0_1_4();
     QDomNode domNode = incr.firstChild();
@@ -565,6 +669,10 @@ QSet<QString> VPatternConverter::FixIncrementsToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::FixPointExpressionsToV0_2_0(const QSet<QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strPoint);
     for (int i=0; i < list.size(); ++i)
@@ -625,6 +733,10 @@ void VPatternConverter::FixPointExpressionsToV0_2_0(const QSet<QString> &names)
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::FixArcExpressionsToV0_2_0(const QSet<QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strArc);
     for (int i=0; i < list.size(); ++i)
@@ -676,6 +788,10 @@ void VPatternConverter::FixArcExpressionsToV0_2_0(const QSet<QString> &names)
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::FixPathPointExpressionsToV0_2_0(const QSet<QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strPathPoint);
     for (int i=0; i < list.size(); ++i)
@@ -717,6 +833,10 @@ void VPatternConverter::FixPathPointExpressionsToV0_2_0(const QSet<QString> &nam
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ConvertPointExpressionsToV0_2_0(const QMap<QString, QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strPoint);
     for (int i=0; i < list.size(); ++i)
@@ -777,6 +897,10 @@ void VPatternConverter::ConvertPointExpressionsToV0_2_0(const QMap<QString, QStr
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ConvertArcExpressionsToV0_2_0(const QMap<QString, QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strArc);
     for (int i=0; i < list.size(); ++i)
@@ -828,6 +952,10 @@ void VPatternConverter::ConvertArcExpressionsToV0_2_0(const QMap<QString, QStrin
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ConvertPathPointExpressionsToV0_2_0(const QMap<QString, QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QString formula;
     const QDomNodeList list = elementsByTagName(strPathPoint);
     for (int i=0; i < list.size(); ++i)
@@ -869,6 +997,10 @@ void VPatternConverter::ConvertPathPointExpressionsToV0_2_0(const QMap<QString,
 //---------------------------------------------------------------------------------------------------------------------
 QString VPatternConverter::FixMeasurementInFormulaToV0_2_0(const QString &formula, const QMap<QString, QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     qmu::QmuTokenParser *cal = new qmu::QmuTokenParser(formula, false, false);// Eval formula
     QMap<int, QString> tokens = cal->GetTokens();// Tokens (variables, measurements)
     delete cal;
@@ -899,6 +1031,10 @@ QString VPatternConverter::FixMeasurementInFormulaToV0_2_0(const QString &formul
 //---------------------------------------------------------------------------------------------------------------------
 QString VPatternConverter::FixIncrementInFormulaToV0_2_0(const QString &formula, const QSet<QString> &names)
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     qmu::QmuTokenParser *cal = new qmu::QmuTokenParser(formula, false, false);// Eval formula
     QMap<int, QString> tokens = cal->GetTokens();// Tokens (variables, measurements)
     delete cal;
@@ -929,6 +1065,10 @@ QString VPatternConverter::FixIncrementInFormulaToV0_2_0(const QString &formula,
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagMeasurementsToV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     QDomElement ms = TagMeasurementsV0_1_4();
     const QString path = GetParametrString(ms, strPath);
 
@@ -943,6 +1083,10 @@ void VPatternConverter::TagMeasurementsToV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ConvertMeasurementsToV0_2_1()
 {
+    // TODO. Delete if minimal supported version is 0.2.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 1),
+                      "Time to refactor the code.");
+
     const QMap<QString, QString> names = OldNamesToNewNames_InV0_2_1();
 
     // Structure did not change. We can use the same code.
@@ -954,6 +1098,10 @@ void VPatternConverter::ConvertMeasurementsToV0_2_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::RemoveColorToolCutV0_3_1()
 {
+    // TODO. Delete if minimal supported version is 0.3.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
+                      "Time to refactor the code.");
+
     const QDomNodeList list = elementsByTagName(strPoint);
     for (int i=0; i < list.size(); ++i)
     {
@@ -972,6 +1120,10 @@ void VPatternConverter::RemoveColorToolCutV0_3_1()
 //---------------------------------------------------------------------------------------------------------------------
 QString VPatternConverter::MUnitV0_1_4() const
 {
+    // TODO. Delete if minimal supported version is 0.1.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 4),
+                      "Time to refactor the code.");
+
     const QDomElement element = TagMeasurementsV0_1_4();
     try
     {
@@ -988,6 +1140,10 @@ QString VPatternConverter::MUnitV0_1_4() const
 //---------------------------------------------------------------------------------------------------------------------
 QDomElement VPatternConverter::TagMeasurementsV0_1_4() const
 {
+    // TODO. Delete if minimal supported version is 0.1.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 4),
+                      "Time to refactor the code.");
+
     const QDomNodeList list = elementsByTagName(strMeasurements);
     const QDomElement element = list.at(0).toElement();
     if (not element.isElement())
@@ -1001,6 +1157,10 @@ QDomElement VPatternConverter::TagMeasurementsV0_1_4() const
 //---------------------------------------------------------------------------------------------------------------------
 QDomElement VPatternConverter::TagIncrementsV0_1_4() const
 {
+    // TODO. Delete if minimal supported version is 0.1.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 4),
+                      "Time to refactor the code.");
+
     const QDomNodeList list = elementsByTagName(strIncrements);
     const QDomElement element = list.at(0).toElement();
     if (not element.isElement())
@@ -1014,6 +1174,10 @@ QDomElement VPatternConverter::TagIncrementsV0_1_4() const
 //---------------------------------------------------------------------------------------------------------------------
 QStringList VPatternConverter::ListPathPointExpressionsV0_1_4() const
 {
+    // TODO. Delete if minimal supported version is 0.1.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 1, 4),
+                      "Time to refactor the code.");
+
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(strPathPoint);
     for (int i=0; i < list.size(); ++i)
@@ -1054,6 +1218,10 @@ QStringList VPatternConverter::ListPathPointExpressionsV0_1_4() const
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::FixToolUnionToV0_2_4()
 {
+    // TODO. Delete if minimal supported version is 0.2.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 4),
+                      "Time to refactor the code.");
+
     QDomElement root = documentElement();
     const QDomNodeList modelings = root.elementsByTagName(strModeling);
     for (int i=0; i<modelings.size(); ++i)
@@ -1065,6 +1233,10 @@ void VPatternConverter::FixToolUnionToV0_2_4()
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::ParseModelingToV0_2_4(const QDomElement &modeling)
 {
+    // TODO. Delete if minimal supported version is 0.2.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 4),
+                      "Time to refactor the code.");
+
     QDomElement node = modeling.firstChild().toElement();
     while (not node.isNull())
     {
@@ -1100,6 +1272,10 @@ void VPatternConverter::ParseModelingToV0_2_4(const QDomElement &modeling)
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::SaveChildrenToolUnionToV0_2_4(quint32 id, const QVector<quint32> &children)
 {
+    // TODO. Delete if minimal supported version is 0.2.4
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 4),
+                      "Time to refactor the code.");
+
     QDomElement toolUnion = elementById(id);
     if (toolUnion.isNull())
     {
@@ -1121,6 +1297,10 @@ void VPatternConverter::SaveChildrenToolUnionToV0_2_4(quint32 id, const QVector<
 //---------------------------------------------------------------------------------------------------------------------
 QMap<QString, QString> VPatternConverter::OldNamesToNewNames_InV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.2.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 0),
+                      "Time to refactor the code.");
+
     // old name, new name
     QMap<QString, QString> names;
 
@@ -1297,6 +1477,10 @@ QMap<QString, QString> VPatternConverter::OldNamesToNewNames_InV0_2_0()
 //---------------------------------------------------------------------------------------------------------------------
 QMap<QString, QString> VPatternConverter::OldNamesToNewNames_InV0_2_1()
 {
+    // TODO. Delete if minimal supported version is 0.2.1
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 2, 1),
+                      "Time to refactor the code.");
+
     // old name, new name
     QMap<QString, QString> names;
 
@@ -1499,6 +1683,10 @@ void VPatternConverter::FixSubPaths(int i, quint32 id, quint32 baseCurve)
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagDetailToV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     const QDomNodeList list = elementsByTagName(strDetail);
     for (int i=0; i < list.size(); ++i)
     {
diff --git a/src/libs/ifc/xml/vvitconverter.cpp b/src/libs/ifc/xml/vvitconverter.cpp
index bb5c857c9..49c7a397d 100644
--- a/src/libs/ifc/xml/vvitconverter.cpp
+++ b/src/libs/ifc/xml/vvitconverter.cpp
@@ -150,6 +150,10 @@ void VVITConverter::DowngradeToCurrentMaxVersion()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::AddNewTagsForV0_3_0()
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     QDomElement rootElement = this->documentElement();
     QDomNode refChild = rootElement.firstChildElement("version");
 
@@ -168,12 +172,20 @@ void VVITConverter::AddNewTagsForV0_3_0()
 //---------------------------------------------------------------------------------------------------------------------
 QString VVITConverter::MUnitV0_2_0()
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     return UniqueTagText(QStringLiteral("unit"), QStringLiteral("cm"));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ConvertMeasurementsToV0_3_0()
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     const QString tagBM = QStringLiteral("body-measurements");
 
     QDomElement bm = createElement(tagBM);
@@ -213,6 +225,10 @@ void VVITConverter::ConvertMeasurementsToV0_3_0()
 //---------------------------------------------------------------------------------------------------------------------
 QDomElement VVITConverter::AddMV0_3_0(const QString &name, qreal value)
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     QDomElement element = createElement(QStringLiteral("m"));
 
     SetAttribute(element, QStringLiteral("name"), name);
@@ -226,6 +242,10 @@ QDomElement VVITConverter::AddMV0_3_0(const QString &name, qreal value)
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::GenderV0_3_1()
 {
+    // TODO. Delete if minimal supported version is 0.3.1
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
+                      "Time to refactor the code.");
+
     const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("sex"));
     QDomElement sex = nodeList.at(0).toElement();
 
@@ -239,6 +259,10 @@ void VVITConverter::GenderV0_3_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::PM_SystemV0_3_2()
 {
+    // TODO. Delete if minimal supported version is 0.3.2
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
+                      "Time to refactor the code.");
+
     QDomElement pm_system = createElement(QStringLiteral("pm_system"));
     pm_system.appendChild(createTextNode(QStringLiteral("998")));
 
@@ -252,6 +276,10 @@ void VVITConverter::PM_SystemV0_3_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ConvertMeasurementsToV0_3_3()
 {
+    // TODO. Delete if minimal supported version is 0.3.3
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 3),
+                      "Time to refactor the code.");
+
     const QMap<QString, QString> names = OldNamesToNewNames_InV0_3_3();
     auto i = names.constBegin();
     while (i != names.constEnd())
@@ -281,6 +309,10 @@ void VVITConverter::ConvertMeasurementsToV0_3_3()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ToV0_3_0()
 {
+    // TODO. Delete if minimal supported version is 0.3.0
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
+                      "Time to refactor the code.");
+
     AddRootComment();
     SetVersion(QStringLiteral("0.3.0"));
     AddNewTagsForV0_3_0();
@@ -291,6 +323,10 @@ void VVITConverter::ToV0_3_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ToV0_3_1()
 {
+    // TODO. Delete if minimal supported version is 0.3.1
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.1"));
     GenderV0_3_1();
     Save();
@@ -299,6 +335,10 @@ void VVITConverter::ToV0_3_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ToV0_3_2()
 {
+    // TODO. Delete if minimal supported version is 0.3.2
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.2"));
     PM_SystemV0_3_2();
     Save();
@@ -307,6 +347,10 @@ void VVITConverter::ToV0_3_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VVITConverter::ToV0_3_3()
 {
+    // TODO. Delete if minimal supported version is 0.3.3
+    Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 3),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.3.3"));
     ConvertMeasurementsToV0_3_3();
     Save();
diff --git a/src/libs/ifc/xml/vvstconverter.cpp b/src/libs/ifc/xml/vvstconverter.cpp
index 051255156..5f7518dbf 100644
--- a/src/libs/ifc/xml/vvstconverter.cpp
+++ b/src/libs/ifc/xml/vvstconverter.cpp
@@ -150,6 +150,10 @@ void VVSTConverter::DowngradeToCurrentMaxVersion()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::AddNewTagsForV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     QDomElement rootElement = this->documentElement();
     QDomNode refChild = rootElement.firstChildElement("version");
 
@@ -171,6 +175,10 @@ void VVSTConverter::AddNewTagsForV0_4_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::RemoveTagsForV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     QDomElement rootElement = this->documentElement();
 
     {
@@ -193,6 +201,10 @@ void VVSTConverter::RemoveTagsForV0_4_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ConvertMeasurementsToV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     const QString tagBM = QStringLiteral("body-measurements");
 
     QDomElement bm = createElement(tagBM);
@@ -239,6 +251,10 @@ void VVSTConverter::ConvertMeasurementsToV0_4_0()
 //---------------------------------------------------------------------------------------------------------------------
 QDomElement VVSTConverter::AddMV0_4_0(const QString &name, qreal value, qreal sizeIncrease, qreal heightIncrease)
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     QDomElement element = createElement(QStringLiteral("m"));
 
     SetAttribute(element, QStringLiteral("name"), name);
@@ -254,6 +270,10 @@ QDomElement VVSTConverter::AddMV0_4_0(const QString &name, qreal value, qreal si
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::PM_SystemV0_4_1()
 {
+    // TODO. Delete if minimal supported version is 0.4.1
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 1),
+                      "Time to refactor the code.");
+
     QDomElement pm_system = createElement(QStringLiteral("pm_system"));
     pm_system.appendChild(createTextNode(QStringLiteral("998")));
 
@@ -267,6 +287,10 @@ void VVSTConverter::PM_SystemV0_4_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ConvertMeasurementsToV0_4_2()
 {
+    // TODO. Delete if minimal supported version is 0.4.2
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 2),
+                      "Time to refactor the code.");
+
     const QMap<QString, QString> names = OldNamesToNewNames_InV0_3_3();
     auto i = names.constBegin();
     while (i != names.constEnd())
@@ -296,6 +320,10 @@ void VVSTConverter::ConvertMeasurementsToV0_4_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ToV0_4_0()
 {
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
     AddRootComment();
     SetVersion(QStringLiteral("0.4.0"));
     AddNewTagsForV0_4_0();
@@ -307,6 +335,10 @@ void VVSTConverter::ToV0_4_0()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ToV0_4_1()
 {
+    // TODO. Delete if minimal supported version is 0.4.1
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 1),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.4.1"));
     PM_SystemV0_4_1();
     Save();
@@ -315,6 +347,10 @@ void VVSTConverter::ToV0_4_1()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ToV0_4_2()
 {
+    // TODO. Delete if minimal supported version is 0.4.2
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 2),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.4.2"));
     ConvertMeasurementsToV0_4_2();
     Save();
@@ -323,6 +359,10 @@ void VVSTConverter::ToV0_4_2()
 //---------------------------------------------------------------------------------------------------------------------
 void VVSTConverter::ToV0_4_3()
 {
+    // TODO. Delete if minimal supported version is 0.4.3
+    Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 3),
+                      "Time to refactor the code.");
+
     SetVersion(QStringLiteral("0.4.3"));
     Save();
 }

From 11e9b40cb19f52b230a90652e0da349e23894bd9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 17:52:56 +0200
Subject: [PATCH 026/208] Forgot to return a pointer.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 6a856519f..946c8a758 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -166,6 +166,8 @@ VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, const VPiece &newPiec
         connect(scene, &VMainGraphicsScene::EnableDetailItemSelection, piece, &VToolSeamAllowance::AllowSelecting);
         connect(scene, &VMainGraphicsScene::HighlightDetail, piece, &VToolSeamAllowance::Highlight);
         doc->AddTool(id, piece);
+
+        return piece;
     }
     return nullptr;
 }

From 2eea6482de34169484efb2ea29e021e53571fc51 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 17:53:38 +0200
Subject: [PATCH 027/208] From no one we should check count of VPiece.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 8c6eae650..6945564a7 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -2140,7 +2140,7 @@ void MainWindow::ActionDetails(bool checked)
 
         if(not qApp->getOpeningPattern())
         {
-            if (pattern->DataDetails()->count() == 0)
+            if (pattern->DataPieces()->count() == 0)
             {
                 QMessageBox::information(this, tr("Detail mode"), tr("You can't use now the Detail mode. "
                                                                      "Please, create at least one workpiece."),

From 6c0e4348e77c1f5cc6e14fe413300784fa8a3877 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 17:54:26 +0200
Subject: [PATCH 028/208] The app again parse tag "detail".

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp | 142 +++++++++++++++++------------
 src/app/valentina/xml/vpattern.h   |   1 +
 2 files changed, 87 insertions(+), 56 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index d50dcf7fb..c77fc37eb 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -30,6 +30,7 @@
 #include "../vwidgets/vabstractmainwindow.h"
 #include "../vtools/tools/vdatatool.h"
 #include "../vtools/tools/vtooldetail.h"
+#include "../vtools/tools/vtoolseamallowance.h"
 #include "../vtools/tools/vtooluniondetails.h"
 #include "../vtools/tools/drawTools/drawtools.h"
 #include "../vtools/tools/nodeDetails/nodedetails.h"
@@ -48,6 +49,7 @@
 #include "../vgeometry/vcubicbezier.h"
 #include "../vgeometry/vcubicbezierpath.h"
 #include "../core/vapplication.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "../vpatterndb/calculator.h"
 #include "../vpatterndb/vpatternpiecedata.h"
 #include "../vpatterndb/vpatterninfogeometry.h"
@@ -608,14 +610,14 @@ void VPattern::ParseDrawMode(const QDomNode &node, const Document &parse, const
  */
 void VPattern::ParseDetailElement(const QDomElement &domElement, const Document &parse)
 {
-//    Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
-//    try
-//    {
-//        VDetail detail;
-//        const quint32 id = GetParametrId(domElement);
+    Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
+    try
+    {
+        VPiece detail;
+        const quint32 id = GetParametrId(domElement);
 //        detail.setName(GetParametrString(domElement, AttrName, ""));
-//        detail.setMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
-//        detail.setMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
+        detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
+        detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
 //        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
 //        detail.setWidth(GetParametrDouble(domElement, VToolDetail::AttrWidth, "10.0"));
 //        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
@@ -623,47 +625,33 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
 //        detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
 
-//        QStringList types = QStringList() << VToolDetail::NodePoint << VToolDetail::NodeArc << VToolDetail::NodeSpline
-//                                          << VToolDetail::NodeSplinePath;
-//        const QDomNodeList nodeList = domElement.childNodes();
-//        const qint32 num = nodeList.size();
-//        for (qint32 i = 0; i < num; ++i)
-//        {
-//            const QDomElement element = nodeList.at(i).toElement();
-//            if (element.isNull() == false)
-//            {
-//                if (element.tagName() == VToolDetail::TagNode)
-//                {
-//                    const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-//                    const qreal mx = qApp->toPixel(GetParametrDouble(element, AttrMx, "0.0"));
-//                    const qreal my = qApp->toPixel(GetParametrDouble(element, AttrMy, "0.0"));
-//                    const bool reverse = GetParametrUInt(element, VToolDetail::AttrReverse, "0");
-//                    const NodeDetail nodeType = NodeDetail::Contour;
+        const QStringList tags = QStringList() << VToolSeamAllowance::TagNodes
+                                               << TagData
+                                               << TagPatternInfo
+                                               << TagGrainline;
 
-//                    const QString t = GetParametrString(element, AttrType, "NodePoint");
-//                    Tool tool;
-
-//                    switch (types.indexOf(t))
-//                    {
-//                        case 0: // VToolDetail::NodePoint
-//                            tool = Tool::NodePoint;
-//                            break;
-//                        case 1: // VToolDetail::NodeArc
-//                            tool = Tool::NodeArc;
-//                            break;
-//                        case 2: // VToolDetail::NodeSpline
-//                            tool = Tool::NodeSpline;
-//                            break;
-//                        case 3: // VToolDetail::NodeSplinePath
-//                            tool = Tool::NodeSplinePath;
-//                            break;
-//                        default:
-//                            VException e(tr("Wrong tag name '%1'.").arg(t));
-//                            throw e;
-//                    }
-//                    detail.append(VNodeDetail(id, tool, nodeType, mx, my, reverse));
-//                }
-//                else if (element.tagName() == TagData)
+        const QDomNodeList nodeList = domElement.childNodes();
+        for (qint32 i = 0; i < nodeList.size(); ++i)
+        {
+            const QDomElement element = nodeList.at(i).toElement();
+            if (not element.isNull())
+            {
+                switch (tags.indexOf(element.tagName()))
+                {
+                    case 0:// VToolSeamAllowance::TagNodes
+                        ParseDetailNodes(element, detail);
+                        break;
+                    case 1:// TagData
+                        break;
+                    case 2:// TagPatternInfo
+                        break;
+                    case 3:// TagGrainline
+                        break;
+                    default:
+                        break;
+                }
+            }
+//                if (element.tagName() == TagData)
 //                {
 //                    bool bVisible = GetParametrBool(element, AttrVisible, trueStr);
 //                    detail.GetPatternPieceData().SetVisible(bVisible);
@@ -735,17 +723,59 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //                    detail.GetGrainlineGeometry().SetArrowType(eAT);
 //                }
 //            }
-//        }
-//        VToolDetail::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
-//    }
-//    catch (const VExceptionBadId &e)
-//    {
-//        VExceptionObjectError excep(tr("Error creating or updating detail"), domElement);
-//        excep.AddMoreInformation(e.ErrorMessage());
-//        throw excep;
-//    }
+        }
+        VToolSeamAllowance::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
+    }
+    catch (const VExceptionBadId &e)
+    {
+        VExceptionObjectError excep(tr("Error creating or updating detail"), domElement);
+        excep.AddMoreInformation(e.ErrorMessage());
+        throw excep;
+    }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const
+{
+    const QStringList types = QStringList() << VToolSeamAllowance::NodePoint
+                                            << VToolSeamAllowance::NodeArc
+                                            << VToolSeamAllowance::NodeSpline
+                                            << VToolSeamAllowance::NodeSplinePath;
+
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagNode)
+        {
+            const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
+            const bool reverse = GetParametrUInt(element, VToolDetail::AttrReverse, "0");
+
+            const QString t = GetParametrString(element, AttrType, VToolSeamAllowance::NodePoint);
+            Tool tool;
+
+            switch (types.indexOf(t))
+            {
+                case 0: // VToolSeamAllowance::NodePoint
+                    tool = Tool::NodePoint;
+                    break;
+                case 1: // VToolSeamAllowance::NodeArc
+                    tool = Tool::NodeArc;
+                    break;
+                case 2: // VToolSeamAllowance::NodeSpline
+                    tool = Tool::NodeSpline;
+                    break;
+                case 3: // VToolSeamAllowance::NodeSplinePath
+                    tool = Tool::NodeSplinePath;
+                    break;
+                default:
+                    VException e(tr("Wrong tag name '%1'.").arg(t));
+                    throw e;
+            }
+            detail.Append(VPieceNode(id, tool, reverse));
+        }
+    }
+}
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDetails parse details tag.
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index b21f86751..08ba4bfda 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -115,6 +115,7 @@ private:
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
+    void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
     void           ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElement,

From f593d4ca5b205d5c19f44570d85335c87ccccf8d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 8 Nov 2016 19:11:47 +0200
Subject: [PATCH 029/208] Dialog seam allowance tool should show visualization
 only when user is creating new piece.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 56 +++++++++++--------
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  4 +-
 2 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index d37e136ea..567f8ad93 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -54,7 +54,10 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
 
-    vis = new VisToolPiece(data);
+    if (not applyAllowed)
+    {
+        vis = new VisToolPiece(data);
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -129,21 +132,24 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
 
         ValidObjects(MainPathIsValid());
 
-        auto visPath = qobject_cast<VisToolPiece *>(vis);
-        SCASSERT(visPath != nullptr);
-        const VPiece p = CreatePiece();
-        visPath->SetPiece(p);
-
-        if (p.CountNodes() == 1)
+        if (not applyAllowed)
         {
-            emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
-                            "<b>Enter</b> - finish creation"));
+            auto visPath = qobject_cast<VisToolPiece *>(vis);
+            SCASSERT(visPath != nullptr);
+            const VPiece p = CreatePiece();
+            visPath->SetPiece(p);
 
-            visPath->VisualMode(NULL_ID);
-        }
-        else
-        {
-            visPath->RefreshGeometry();
+            if (p.CountNodes() == 1)
+            {
+                emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
+                                "<b>Enter</b> - finish creation"));
+
+                visPath->VisualMode(NULL_ID);
+            }
+            else
+            {
+                visPath->RefreshGeometry();
+            }
         }
     }
 }
@@ -156,10 +162,13 @@ void DialogSeamAllowance::ShowDialog(bool click)
         emit ToolTip("");
         prepare = true;
 
-        auto visPath = qobject_cast<VisToolPiece *>(vis);
-        SCASSERT(visPath != nullptr);
-        visPath->SetMode(Mode::Show);
-        visPath->RefreshGeometry();
+        if (not applyAllowed)
+        {
+            auto visPath = qobject_cast<VisToolPiece *>(vis);
+            SCASSERT(visPath != nullptr);
+            visPath->SetMode(Mode::Show);
+            visPath->RefreshGeometry();
+        }
 
         // Fix issue #526. Dialog Detail is not on top after selection second object on Mac.
         setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
@@ -231,10 +240,13 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ListChanged()
 {
-    auto visPath = qobject_cast<VisToolPiece *>(vis);
-    SCASSERT(visPath != nullptr);
-    visPath->SetPiece(CreatePiece());
-    visPath->RefreshGeometry();
+    if (not applyAllowed)
+    {
+        auto visPath = qobject_cast<VisToolPiece *>(vis);
+        SCASSERT(visPath != nullptr);
+        visPath->SetPiece(CreatePiece());
+        visPath->RefreshGeometry();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 946c8a758..2287b4828 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -400,7 +400,9 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
     QAction *selectedAction = menu.exec(event->screenPos());
     if (selectedAction == actionOption)
     {
-        m_dialog = new DialogSeamAllowance(getData(), id, qApp->getMainWindow());
+        auto *dialog = new DialogSeamAllowance(getData(), id, qApp->getMainWindow());
+        dialog->EnableApply(true);
+        m_dialog = dialog;
         m_dialog->setModal(true);
         connect(m_dialog, &DialogTool::DialogClosed, this, &VToolSeamAllowance::FullUpdateFromGuiOk);
         SetDialog();

From b88663dcb485cc9aec980448516eac4f187c7baf Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 11:57:39 +0200
Subject: [PATCH 030/208] Returned undocommand "Delete piece".

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  81 +++++++++---
 src/libs/vtools/tools/vtoolseamallowance.h    |   5 +-
 src/libs/vtools/undocommands/deletepiece.cpp  | 116 ++++++++++++++++++
 src/libs/vtools/undocommands/deletepiece.h    |  59 +++++++++
 src/libs/vtools/undocommands/undocommands.pri |   6 +-
 5 files changed, 248 insertions(+), 19 deletions(-)
 create mode 100644 src/libs/vtools/undocommands/deletepiece.cpp
 create mode 100644 src/libs/vtools/undocommands/deletepiece.h

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 2287b4828..c6a283037 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -41,9 +41,15 @@
 #include "../vgeometry/vsplinepath.h"
 #include "../ifc/xml/vpatternconverter.h"
 #include "../undocommands/addpiece.h"
+#include "../undocommands/deletepiece.h"
+//#include "../undocommands/movepiece.h"
+//#include "../undocommands/savepieceoptions.h"
+//#include "../undocommands/togglepieceinlayout.h"
 
 #include <QGraphicsSceneMouseEvent>
+#include <QKeyEvent>
 #include <QMenu>
+#include <QMessageBox>
 
 // Current version of seam allowance tag nned for backward compatibility
 const quint8 VToolSeamAllowance::pieceVersion = 2;
@@ -172,6 +178,20 @@ VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, const VPiece &newPiec
     return nullptr;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::Remove(bool ask)
+{
+    try
+    {
+        DeleteTool(ask);
+    }
+    catch(const VExceptionToolWasDeleted &e)
+    {
+        Q_UNUSED(e);
+        return;//Leave this method immediately!!!
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
 {
@@ -394,8 +414,8 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
 //    const VDetail detail = VAbstractTool::data.GetDetail(id);
 //    inLayoutOption->setChecked(detail.IsInLayout());
 
-//    QAction *actionRemove = menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
-//    _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
+    QAction *actionRemove = menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+    _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
 
     QAction *selectedAction = menu.exec(event->screenPos());
     if (selectedAction == actionOption)
@@ -415,24 +435,41 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
 //        connect(togglePrint, &ToggleDetailInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
 //        qApp->getUndoStack()->push(togglePrint);
 //    }
-//    else if (selectedAction == actionRemove)
-//    {
-//        try
-//        {
-//            DeleteTool();
-//        }
-//        catch(const VExceptionToolWasDeleted &e)
-//        {
-//            Q_UNUSED(e);
-//            return;//Leave this method immediately!!!
-//        }
-//        return; //Leave this method immediately after call!!!
-    //    }
+    else if (selectedAction == actionRemove)
+    {
+        try
+        {
+            DeleteTool();
+        }
+        catch(const VExceptionToolWasDeleted &e)
+        {
+            Q_UNUSED(e);
+            return;//Leave this method immediately!!!
+        }
+        return; //Leave this method immediately after call!!!
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::keyReleaseEvent(QKeyEvent *event)
 {
+    switch (event->key())
+    {
+        case Qt::Key_Delete:
+            try
+            {
+                DeleteTool();
+            }
+            catch(const VExceptionToolWasDeleted &e)
+            {
+                Q_UNUSED(e);
+                return;//Leave this method immediately!!!
+            }
+            break;
+        default:
+            break;
+    }
+
     VNoBrushScalePathItem::keyReleaseEvent ( event );
 }
 
@@ -523,7 +560,21 @@ void VToolSeamAllowance::RefreshGeometry()
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::DeleteTool(bool ask)
 {
+    DeletePiece *delDet = new DeletePiece(doc, id, VAbstractTool::data.GetPiece(id));
+    if (ask)
+    {
+        if (ConfirmDeletion() == QMessageBox::No)
+        {
+            return;
+        }
+        /* If UnionDetails tool delete detail no need emit FullParsing.*/
+        connect(delDet, &DeletePiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
+    }
+    qApp->getUndoStack()->push(delDet);
 
+    // Throw exception, this will help prevent case when we forget to immediately quit function.
+    VExceptionToolWasDeleted e("Tool was used after deleting.");
+    throw e;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 836849aa9..878b3d011 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -65,6 +65,8 @@ public:
     static const QString NodeSpline;
     static const QString NodeSplinePath;
 
+    void Remove(bool ask);
+
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
     static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
 
@@ -93,6 +95,7 @@ protected:
     virtual void       contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE;
     virtual void       keyReleaseEvent(QKeyEvent * event) Q_DECL_OVERRIDE;
     virtual void       SetVisualization() Q_DECL_OVERRIDE {}
+    virtual void       DeleteTool(bool ask = true) Q_DECL_OVERRIDE;
 
 private:
     Q_DISABLE_COPY(VToolSeamAllowance)
@@ -116,8 +119,6 @@ private:
 
     template <typename Tool>
     Tool*              InitTool(VMainGraphicsScene *scene, const VPieceNode &node);
-
-    virtual void       DeleteTool(bool ask = true) Q_DECL_OVERRIDE;
 };
 
 #endif // VTOOLSEAMALLOWANCE_H
diff --git a/src/libs/vtools/undocommands/deletepiece.cpp b/src/libs/vtools/undocommands/deletepiece.cpp
new file mode 100644
index 000000000..44d79a54e
--- /dev/null
+++ b/src/libs/vtools/undocommands/deletepiece.cpp
@@ -0,0 +1,116 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   9 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "deletepiece.h"
+
+#include <QDomElement>
+#include <QHash>
+
+#include "../ifc/ifcdef.h"
+#include "../ifc/xml/vabstractpattern.h"
+#include "../ifc/xml/vdomdocument.h"
+#include "../vmisc/logging.h"
+#include "../vmisc/def.h"
+#include "../tools/vdatatool.h"
+#include "vundocommand.h"
+#include "../vpatterndb/vpiecenode.h"
+
+class QUndoCommand;
+
+//---------------------------------------------------------------------------------------------------------------------
+DeletePiece::DeletePiece(VAbstractPattern *doc, quint32 id, const VPiece &detail, QUndoCommand *parent)
+    : VUndoCommand(QDomElement(), doc, parent),
+      m_parentNode(),
+      m_siblingId(NULL_ID),
+      m_detail(detail)
+{
+    setText(tr("delete tool"));
+    nodeId = id;
+    QDomElement domElement = doc->elementById(id);
+    if (domElement.isElement())
+    {
+        xml = domElement.cloneNode().toElement();
+        m_parentNode = domElement.parentNode();
+        QDomNode previousDetail = domElement.previousSibling();
+        if (previousDetail.isNull())
+        {
+            m_siblingId = NULL_ID;
+        }
+        else
+        {
+            // Better save id of previous detail instead of reference to node.
+            m_siblingId = doc->GetParametrUInt(previousDetail.toElement(), VAbstractPattern::AttrId, NULL_ID_STR);
+        }
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't get detail by id = %u.", nodeId);
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+DeletePiece::~DeletePiece()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DeletePiece::undo()
+{
+    qCDebug(vUndo, "Undo.");
+
+    UndoDeleteAfterSibling(m_parentNode, m_siblingId);
+    emit NeedFullParsing();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DeletePiece::redo()
+{
+    qCDebug(vUndo, "Redo.");
+
+    QDomElement domElement = doc->elementById(nodeId);
+    if (domElement.isElement())
+    {
+        m_parentNode.removeChild(domElement);
+
+        // UnionDetails delete two old details and create one new.
+        // So when UnionDetail delete detail we can't use FullParsing. So we hide detail on scene directly.
+        QHash<quint32, VDataTool*>* tools = doc->getTools();
+        SCASSERT(tools != nullptr);
+        VToolSeamAllowance *toolDet = qobject_cast<VToolSeamAllowance*>(tools->value(nodeId));
+        SCASSERT(toolDet != nullptr);
+        toolDet->hide();
+
+        DecrementReferences(m_detail.GetNodes());
+        emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't get detail by id = %u.", nodeId);
+        return;
+    }
+}
diff --git a/src/libs/vtools/undocommands/deletepiece.h b/src/libs/vtools/undocommands/deletepiece.h
new file mode 100644
index 000000000..b06a77613
--- /dev/null
+++ b/src/libs/vtools/undocommands/deletepiece.h
@@ -0,0 +1,59 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   9 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 DELETEPIECE_H
+#define DELETEPIECE_H
+
+#include <QtGlobal>
+
+#include "../tools/vtoolseamallowance.h"
+#include "vpiece.h"
+#include "vundocommand.h"
+
+class QGraphicsItem;
+class QUndoCommand;
+class VAbstractPattern;
+
+class DeletePiece : public VUndoCommand
+{
+    Q_OBJECT
+public:
+    DeletePiece(VAbstractPattern *doc, quint32 id, const VPiece &m_detail, QUndoCommand *parent = nullptr);
+    virtual ~DeletePiece();
+
+    virtual void undo() Q_DECL_OVERRIDE;
+    virtual void redo() Q_DECL_OVERRIDE;
+private:
+    Q_DISABLE_COPY(DeletePiece)
+
+    QDomNode m_parentNode;
+    quint32  m_siblingId;
+    VPiece   m_detail;
+};
+
+#endif // DELETEPIECE_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index fe6ec5f59..5bdcf4b90 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -24,7 +24,8 @@ HEADERS += \
     $$PWD/label/moveabstractlabel.h \
     $$PWD/toggledetailinlayout.h \
     $$PWD/label/operationmovelabel.h \
-    $$PWD/addpiece.h
+    $$PWD/addpiece.h \
+    $$PWD/deletepiece.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -49,4 +50,5 @@ SOURCES += \
     $$PWD/label/moveabstractlabel.cpp \
     $$PWD/toggledetailinlayout.cpp \
     $$PWD/label/operationmovelabel.cpp \
-    $$PWD/addpiece.cpp
+    $$PWD/addpiece.cpp \
+    $$PWD/deletepiece.cpp

From 8601b2ae2ae9a6fc273df7289258e204cb1463f2 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 13:06:05 +0200
Subject: [PATCH 031/208] Returned undocommand "Move piece".

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp              |  2 +-
 src/libs/ifc/xml/vpatternconverter.cpp        |  2 -
 src/libs/vtools/tools/vtooldetail.cpp         |  6 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  | 70 ++++++++++++++++++-
 .../{movedetail.cpp => movepiece.cpp}         | 43 +++++++-----
 .../{movedetail.h => movepiece.h}             | 35 +++++-----
 src/libs/vtools/undocommands/undocommands.pri |  8 +--
 src/libs/vtools/undocommands/vundocommand.h   |  2 +-
 8 files changed, 120 insertions(+), 48 deletions(-)
 rename src/libs/vtools/undocommands/{movedetail.cpp => movepiece.cpp} (77%)
 rename src/libs/vtools/undocommands/{movedetail.h => movepiece.h} (78%)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 6945564a7..c7f6aa65e 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -135,7 +135,7 @@ MainWindow::MainWindow(QWidget *parent)
     connect(doc, &VPattern::SetEnabledGUI, this, &MainWindow::SetEnabledGUI);
     connect(doc, &VPattern::CheckLayout, [this]()
     {
-        if (pattern->DataDetails()->count() == 0)
+        if (pattern->DataPieces()->count() == 0)
         {
             if(not ui->actionDraw->isChecked())
             {
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index e4bbe71d7..1f004335e 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -1698,8 +1698,6 @@ void VPatternConverter::TagDetailToV0_4_0()
             dom.removeAttribute(strSupplement);
             dom.removeAttribute(strClosed);
             dom.removeAttribute(strWidth);
-            dom.removeAttribute(strMx);
-            dom.removeAttribute(strMy);
             dom.removeAttribute(strForbidFlipping);
             dom.removeAttribute(strInLayout);
 
diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp
index 912f81f7e..a2b4a9d05 100644
--- a/src/libs/vtools/tools/vtooldetail.cpp
+++ b/src/libs/vtools/tools/vtooldetail.cpp
@@ -74,7 +74,7 @@
 #include "../ifc/ifcdef.h"
 #include "../undocommands/adddet.h"
 #include "../undocommands/deletedetail.h"
-#include "../undocommands/movedetail.h"
+#include "../undocommands/movepiece.h"
 #include "../undocommands/savedetailoptions.h"
 #include "../undocommands/toggledetailinlayout.h"
 #include "../vgeometry/varc.h"
@@ -620,8 +620,8 @@ QVariant VToolDetail::itemChange(QGraphicsItem::GraphicsItemChange change, const
                // value - this is new position.
                const QPointF newPos = value.toPointF();
 
-               MoveDetail *moveDet = new MoveDetail(doc, newPos.x(), newPos.y(), id, scene());
-               connect(moveDet, &MoveDetail::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+               MovePiece *moveDet = new MovePiece(doc, newPos.x(), newPos.y(), id, scene());
+               connect(moveDet, &MovePiece::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
                qApp->getUndoStack()->push(moveDet);
 
                const QList<QGraphicsView *> viewList = scene()->views();
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index c6a283037..a722a31dc 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -42,11 +42,13 @@
 #include "../ifc/xml/vpatternconverter.h"
 #include "../undocommands/addpiece.h"
 #include "../undocommands/deletepiece.h"
-//#include "../undocommands/movepiece.h"
+#include "../undocommands/movepiece.h"
 //#include "../undocommands/savepieceoptions.h"
 //#include "../undocommands/togglepieceinlayout.h"
+#include "../vwidgets/vmaingraphicsview.h"
 
 #include <QGraphicsSceneMouseEvent>
+#include <QGraphicsView>
 #include <QKeyEvent>
 #include <QMenu>
 #include <QMessageBox>
@@ -260,7 +262,9 @@ void VToolSeamAllowance::GroupVisibility(quint32 object, bool visible)
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::FullUpdateFromFile()
-{}
+{
+    RefreshGeometry();
+}
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::FullUpdateFromGuiOk(int result)
@@ -329,6 +333,68 @@ void VToolSeamAllowance::RefreshDataInFile()
 //---------------------------------------------------------------------------------------------------------------------
 QVariant VToolSeamAllowance::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
 {
+    if (change == ItemPositionChange && scene())
+    {
+        // Each time we move something we call recalculation scene rect. In some cases this can cause moving
+        // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move.
+        static bool changeFinished = true;
+        if (changeFinished)
+        {
+            changeFinished = false;
+
+            // value - this is new position.
+            const QPointF newPos = value.toPointF();
+
+            MovePiece *moveDet = new MovePiece(doc, newPos.x(), newPos.y(), id, scene());
+            connect(moveDet, &MovePiece::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+            qApp->getUndoStack()->push(moveDet);
+
+            const QList<QGraphicsView *> viewList = scene()->views();
+            if (not viewList.isEmpty())
+            {
+                if (QGraphicsView *view = viewList.at(0))
+                {
+                    const int xmargin = 50;
+                    const int ymargin = 50;
+
+                    const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view);
+                    const QRectF itemRect = mapToScene(boundingRect()|childrenBoundingRect()).boundingRect();
+
+                    // If item's rect is bigger than view's rect ensureVisible works very unstable.
+                    if (itemRect.height() + 2*ymargin < viewRect.height() &&
+                        itemRect.width() + 2*xmargin < viewRect.width())
+                    {
+                        view->ensureVisible(itemRect, xmargin, ymargin);
+                    }
+                    else
+                    {
+                        // Ensure visible only small rect around a cursor
+                        VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
+                        SCASSERT(currentScene);
+                        const QPointF cursorPosition = currentScene->getScenePos();
+                        view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
+                    }
+                }
+            }
+            // Don't forget to update geometry, because first change never call full parse
+            RefreshGeometry();
+            changeFinished = true;
+        }
+    }
+
+    if (change == QGraphicsItem::ItemSelectedChange)
+    {
+        if (value == true)
+        {
+            // do stuff if selected
+            this->setFocus();
+        }
+        else
+        {
+            // do stuff if not selected
+        }
+    }
+
     return VNoBrushScalePathItem::itemChange(change, value);
 }
 
diff --git a/src/libs/vtools/undocommands/movedetail.cpp b/src/libs/vtools/undocommands/movepiece.cpp
similarity index 77%
rename from src/libs/vtools/undocommands/movedetail.cpp
rename to src/libs/vtools/undocommands/movepiece.cpp
index f06fd568d..46726ec9c 100644
--- a/src/libs/vtools/undocommands/movedetail.cpp
+++ b/src/libs/vtools/undocommands/movepiece.cpp
@@ -26,7 +26,7 @@
  **
  *************************************************************************/
 
-#include "movedetail.h"
+#include "movepiece.h"
 
 #include <QDomElement>
 
@@ -42,9 +42,14 @@ class QDomElement;
 class QUndoCommand;
 
 //---------------------------------------------------------------------------------------------------------------------
-MoveDetail::MoveDetail(VAbstractPattern *doc, const double &x, const double &y, const quint32 &id,
-                       QGraphicsScene *scene, QUndoCommand *parent)
-    : VUndoCommand(QDomElement(), doc, parent), oldX(0.0), oldY(0.0), newX(x), newY(y), scene(scene)
+MovePiece::MovePiece(VAbstractPattern *doc, const double &x, const double &y, const quint32 &id,
+                     QGraphicsScene *scene, QUndoCommand *parent)
+    : VUndoCommand(QDomElement(), doc, parent),
+      m_oldX(0.0),
+      m_oldY(0.0),
+      m_newX(x),
+      m_newY(y),
+      m_scene(scene)
 {
     setText(QObject::tr("move detail"));
     nodeId = id;
@@ -53,8 +58,8 @@ MoveDetail::MoveDetail(VAbstractPattern *doc, const double &x, const double &y,
     QDomElement domElement = doc->elementById(id);
     if (domElement.isElement())
     {
-        oldX = qApp->toPixel(doc->GetParametrDouble(domElement, AttrMx, "0.0"));
-        oldY = qApp->toPixel(doc->GetParametrDouble(domElement, AttrMy, "0.0"));
+        m_oldX = qApp->toPixel(doc->GetParametrDouble(domElement, AttrMx, "0.0"));
+        m_oldY = qApp->toPixel(doc->GetParametrDouble(domElement, AttrMy, "0.0"));
     }
     else
     {
@@ -64,18 +69,18 @@ MoveDetail::MoveDetail(VAbstractPattern *doc, const double &x, const double &y,
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-MoveDetail::~MoveDetail()
+MovePiece::~MovePiece()
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
-void MoveDetail::undo()
+void MovePiece::undo()
 {
     qCDebug(vUndo, "Undo.");
 
     QDomElement domElement = doc->elementById(nodeId);
     if (domElement.isElement())
     {
-        SaveCoordinates(domElement, oldX, oldY);
+        SaveCoordinates(domElement, m_oldX, m_oldY);
 
         emit NeedLiteParsing(Document::LiteParse);
     }
@@ -87,14 +92,14 @@ void MoveDetail::undo()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void MoveDetail::redo()
+void MovePiece::redo()
 {
     qCDebug(vUndo, "Redo.");
 
     QDomElement domElement = doc->elementById(nodeId);
     if (domElement.isElement())
     {
-        SaveCoordinates(domElement, newX, newY);
+        SaveCoordinates(domElement, m_newX, m_newY);
 
         if (redoFlag)
         {
@@ -102,7 +107,7 @@ void MoveDetail::redo()
         }
         else
         {
-            VMainGraphicsView::NewSceneRect(scene, qApp->getSceneView());
+            VMainGraphicsView::NewSceneRect(m_scene, qApp->getSceneView());
         }
         redoFlag = true;
     }
@@ -115,9 +120,9 @@ void MoveDetail::redo()
 
 //---------------------------------------------------------------------------------------------------------------------
 // cppcheck-suppress unusedFunction
-bool MoveDetail::mergeWith(const QUndoCommand *command)
+bool MovePiece::mergeWith(const QUndoCommand *command)
 {
-    const MoveDetail *moveCommand = static_cast<const MoveDetail *>(command);
+    const MovePiece *moveCommand = static_cast<const MovePiece *>(command);
     SCASSERT(moveCommand != nullptr);
     const quint32 id = moveCommand->getDetId();
 
@@ -126,19 +131,19 @@ bool MoveDetail::mergeWith(const QUndoCommand *command)
         return false;
     }
 
-    newX = moveCommand->getNewX();
-    newY = moveCommand->getNewY();
+    m_newX = moveCommand->getNewX();
+    m_newY = moveCommand->getNewY();
     return true;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int MoveDetail::id() const
+int MovePiece::id() const
 {
-    return static_cast<int>(UndoCommand::MoveDetail);
+    return static_cast<int>(UndoCommand::MovePiece);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void MoveDetail::SaveCoordinates(QDomElement &domElement, double x, double y)
+void MovePiece::SaveCoordinates(QDomElement &domElement, double x, double y)
 {
     doc->SetAttribute(domElement, AttrMx, QString().setNum(qApp->fromPixel(x)));
     doc->SetAttribute(domElement, AttrMy, QString().setNum(qApp->fromPixel(y)));
diff --git a/src/libs/vtools/undocommands/movedetail.h b/src/libs/vtools/undocommands/movepiece.h
similarity index 78%
rename from src/libs/vtools/undocommands/movedetail.h
rename to src/libs/vtools/undocommands/movepiece.h
index 37c0d1db2..95d0b5535 100644
--- a/src/libs/vtools/undocommands/movedetail.h
+++ b/src/libs/vtools/undocommands/movepiece.h
@@ -42,13 +42,14 @@ class QGraphicsScene;
 class QUndoCommand;
 class VAbstractPattern;
 
-class MoveDetail : public VUndoCommand
+class MovePiece : public VUndoCommand
 {
     Q_OBJECT
 public:
-    MoveDetail(VAbstractPattern *doc, const double &x, const double &y, const quint32 &id, QGraphicsScene *scene,
-               QUndoCommand *parent = 0);
-    virtual ~MoveDetail() Q_DECL_OVERRIDE;
+    MovePiece(VAbstractPattern *doc, const double &x, const double &y, const quint32 &id, QGraphicsScene *scene,
+               QUndoCommand *parent = nullptr);
+    virtual ~MovePiece();
+
     virtual void undo() Q_DECL_OVERRIDE;
     virtual void redo() Q_DECL_OVERRIDE;
     // cppcheck-suppress unusedFunction
@@ -58,31 +59,33 @@ public:
     double       getNewX() const;
     double       getNewY() const;
 private:
-    Q_DISABLE_COPY(MoveDetail)
-    double   oldX;
-    double   oldY;
-    double   newX;
-    double   newY;
-    QGraphicsScene *scene;
-    void         SaveCoordinates(QDomElement &domElement, double x, double y);
+    Q_DISABLE_COPY(MovePiece)
+
+    double          m_oldX;
+    double          m_oldY;
+    double          m_newX;
+    double          m_newY;
+    QGraphicsScene *m_scene;
+
+    void SaveCoordinates(QDomElement &domElement, double x, double y);
 };
 
 //---------------------------------------------------------------------------------------------------------------------
-inline quint32 MoveDetail::getDetId() const
+inline quint32 MovePiece::getDetId() const
 {
     return nodeId;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-inline double MoveDetail::getNewX() const
+inline double MovePiece::getNewX() const
 {
-    return newX;
+    return m_newX;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-inline double MoveDetail::getNewY() const
+inline double MovePiece::getNewY() const
 {
-    return newY;
+    return m_newY;
 }
 
 #endif // MOVEDETAIL_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index 5bdcf4b90..d031daf32 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -9,7 +9,6 @@ HEADERS += \
     $$PWD/movesplinepath.h \
     $$PWD/savetooloptions.h \
     $$PWD/savedetailoptions.h \
-    $$PWD/movedetail.h \
     $$PWD/deltool.h \
     $$PWD/deletepatternpiece.h \
     $$PWD/adddetnode.h \
@@ -25,7 +24,8 @@ HEADERS += \
     $$PWD/toggledetailinlayout.h \
     $$PWD/label/operationmovelabel.h \
     $$PWD/addpiece.h \
-    $$PWD/deletepiece.h
+    $$PWD/deletepiece.h \
+    $$PWD/movepiece.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -35,7 +35,6 @@ SOURCES += \
     $$PWD/movesplinepath.cpp \
     $$PWD/savetooloptions.cpp \
     $$PWD/savedetailoptions.cpp \
-    $$PWD/movedetail.cpp \
     $$PWD/deltool.cpp \
     $$PWD/deletepatternpiece.cpp \
     $$PWD/adddetnode.cpp \
@@ -51,4 +50,5 @@ SOURCES += \
     $$PWD/toggledetailinlayout.cpp \
     $$PWD/label/operationmovelabel.cpp \
     $$PWD/addpiece.cpp \
-    $$PWD/deletepiece.cpp
+    $$PWD/deletepiece.cpp \
+    $$PWD/movepiece.cpp
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index 9d92a1f0e..b8ae606ea 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -54,7 +54,7 @@ enum class UndoCommand: char { AddPatternPiece,
                                MoveSPoint,
                                SaveToolOptions,
                                SaveDetailOptions,
-                               MoveDetail,
+                               MovePiece,
                                DeleteTool,
                                DeletePatternPiece,
                                RenamePP,

From 988ce8f7f2ad45801e763265d5294dfc4e1626ab Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 14:11:58 +0200
Subject: [PATCH 032/208] Returned undocommand "Save piece options".

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp                |  71 +++++++++
 src/libs/vpatterndb/vpiece.h                  |   6 +
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  61 ++++++--
 src/libs/vtools/tools/vtoolseamallowance.h    |   6 +-
 .../vtools/undocommands/savepieceoptions.cpp  | 136 ++++++++++++++++++
 .../vtools/undocommands/savepieceoptions.h    |  75 ++++++++++
 src/libs/vtools/undocommands/undocommands.pri |   6 +-
 src/libs/vtools/undocommands/vundocommand.cpp |   9 ++
 src/libs/vtools/undocommands/vundocommand.h   |   2 +
 9 files changed, 360 insertions(+), 12 deletions(-)
 create mode 100644 src/libs/vtools/undocommands/savepieceoptions.cpp
 create mode 100644 src/libs/vtools/undocommands/savepieceoptions.h

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 5a44c47ae..874681bc7 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -244,6 +244,57 @@ void VPiece::SetMy(qreal value)
     d->m_my = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
+ * understand, what nodes need make invisible.
+ * @param det changed detail.
+ * @return  list with missing nodes.
+ */
+QVector<VPieceNode> VPiece::Missing(const VPiece &det) const
+{
+    if (d->m_nodes.size() == det.CountNodes()) //-V807
+    {
+        return QVector<VPieceNode>();
+    }
+
+    QSet<quint32> set1;
+    for (qint32 i = 0; i < d->m_nodes.size(); ++i)
+    {
+        set1.insert(d->m_nodes.at(i).GetId());
+    }
+
+    QSet<quint32> set2;
+    for (qint32 j = 0; j < det.CountNodes(); ++j)
+    {
+        set2.insert(det.at(j).GetId());
+    }
+
+    const QList<quint32> set3 = set1.subtract(set2).toList();
+    QVector<VPieceNode> nodes;
+    for (qint32 i = 0; i < set3.size(); ++i)
+    {
+        const int index = indexOfNode(d->m_nodes, set3.at(i));
+        if (index != -1)
+        {
+            nodes.append(d->m_nodes.at(index));
+        }
+    }
+
+    return nodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief indexOfNode return index in list node using id object.
+ * @param id object (arc, point, spline, splinePath) id.
+ * @return index in list or -1 id can't find.
+ */
+int VPiece::indexOfNode(const quint32 &id) const
+{
+    return indexOfNode(d->m_nodes, id);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
 {
@@ -317,3 +368,23 @@ QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) c
     }
     return end;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief indexOfNode return index in list node using id object.
+ * @param list list nodes detail.
+ * @param id object (arc, point, spline, splinePath) id.
+ * @return index in list or -1 id can't find.
+ */
+int VPiece::indexOfNode(const QVector<VPieceNode> &list, quint32 id)
+{
+    for (int i = 0; i < list.size(); ++i)
+    {
+        if (list.at(i).GetId() == id)
+        {
+            return i;
+        }
+    }
+    qDebug()<<"Can't find node.";
+    return -1;
+}
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 4ae3a267a..09261d836 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -71,11 +71,17 @@ public:
     qreal GetMy() const;
     void  SetMy(qreal value);
 
+    QVector<VPieceNode> Missing(const VPiece &det) const;
+
+    int indexOfNode(const quint32 &id) const;
+
 private:
     QSharedDataPointer<VPieceData> d;
 
     QPointF StartSegment(const VContainer *data, const int &i, bool reverse) const;
     QPointF EndSegment(const VContainer *data, const int &i, bool reverse) const;
+
+    static int indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };
 
 Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index a722a31dc..a8e2347e3 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -43,7 +43,7 @@
 #include "../undocommands/addpiece.h"
 #include "../undocommands/deletepiece.h"
 #include "../undocommands/movepiece.h"
-//#include "../undocommands/savepieceoptions.h"
+#include "../undocommands/savepieceoptions.h"
 //#include "../undocommands/togglepieceinlayout.h"
 #include "../vwidgets/vmaingraphicsview.h"
 
@@ -241,6 +241,35 @@ void VToolSeamAllowance::AddNodes(VAbstractPattern *doc, QDomElement &domElement
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece)
+{
+    SCASSERT(doc != nullptr);
+
+    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+    doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
+    doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
+    doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
+{
+
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
+{
+
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
+{
+
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QString VToolSeamAllowance::getTagName() const
 {
@@ -268,7 +297,21 @@ void VToolSeamAllowance::FullUpdateFromFile()
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::FullUpdateFromGuiOk(int result)
-{}
+{
+    if (result == QDialog::Accepted)
+    {
+        SCASSERT(not m_dialog.isNull());
+        DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(m_dialog.data());
+        SCASSERT(dialogTool != nullptr);
+        const VPiece newDet = dialogTool->GetPiece();
+        const VPiece oldDet = VAbstractTool::data.GetPiece(id);
+
+        SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id, this->scene());
+        connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+        qApp->getUndoStack()->push(saveCommand);
+    }
+    delete m_dialog;
+}
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::EnableToolMove(bool move)
@@ -301,10 +344,10 @@ void VToolSeamAllowance::AddToFile()
 
     QDomElement domElement = doc->createElement(getTagName());
 
-    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
-    doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
-    doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
-    doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
+    AddAttributes(doc, domElement, id, piece);
+    AddPatternPieceData(doc, domElement, piece);
+    AddPatternInfo(doc, domElement, piece);
+    AddGrainline(doc, domElement, piece);
 
     // nodes
     AddNodes(doc, domElement, piece);
@@ -490,7 +533,7 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
         dialog->EnableApply(true);
         m_dialog = dialog;
         m_dialog->setModal(true);
-        connect(m_dialog, &DialogTool::DialogClosed, this, &VToolSeamAllowance::FullUpdateFromGuiOk);
+        connect(m_dialog.data(), &DialogTool::DialogClosed, this, &VToolSeamAllowance::FullUpdateFromGuiOk);
         SetDialog();
         m_dialog->show();
     }
@@ -542,7 +585,7 @@ void VToolSeamAllowance::keyReleaseEvent(QKeyEvent *event)
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::SetDialog()
 {
-    SCASSERT(m_dialog != nullptr);
+    SCASSERT(not m_dialog.isNull());
     DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(m_dialog);
     SCASSERT(dialogTool != nullptr);
     dialogTool->SetPiece(VAbstractTool::data.GetPiece(id));
@@ -555,7 +598,7 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
                                        const QString &drawName, QGraphicsItem *parent)
     : VAbstractTool(doc, data, id),
       VNoBrushScalePathItem(parent),
-      m_dialog(nullptr),
+      m_dialog(),
       m_sceneDetails(scene),
       m_drawName(drawName)
 {
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 878b3d011..7e57059aa 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -69,6 +69,10 @@ public:
 
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
     static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
+    static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece);
+    static void AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
+    static void AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
+    static void AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
 
     virtual int        type() const Q_DECL_OVERRIDE {return Type;}
     enum { Type = UserType + static_cast<int>(Tool::Piece)};
@@ -101,7 +105,7 @@ private:
     Q_DISABLE_COPY(VToolSeamAllowance)
 
     /** @brief dialog dialog options. */
-    DialogTool         *m_dialog;
+    QPointer<DialogTool> m_dialog;
 
     /** @brief sceneDetails pointer to the scene. */
     VMainGraphicsScene *m_sceneDetails;
diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
new file mode 100644
index 000000000..cb78ca455
--- /dev/null
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -0,0 +1,136 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   9 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "savepieceoptions.h"
+
+#include <QDomElement>
+#include <QPointF>
+#include <QUndoCommand>
+#include <QDebug>
+
+#include "../ifc/xml/vabstractpattern.h"
+#include "../ifc/ifcdef.h"
+#include "../vmisc/logging.h"
+#include "../vmisc/def.h"
+#include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpatterninfogeometry.h"
+#include "../vpatterndb/vpatternpiecedata.h"
+#include "../vpatterndb/vgrainlinegeometry.h"
+#include "../tools/vtoolseamallowance.h"
+#include "vundocommand.h"
+
+class QDomElement;
+class QUndoCommand;
+
+//---------------------------------------------------------------------------------------------------------------------
+SavePieceOptions::SavePieceOptions(const VPiece &oldDet, const VPiece &newDet, VAbstractPattern *doc, quint32 id,
+                                   QGraphicsScene *scene, QUndoCommand *parent)
+    : VUndoCommand(QDomElement(), doc, parent),
+      m_oldDet(oldDet),
+      m_newDet(newDet),
+      m_scene(scene)
+{
+    setText(tr("save detail option"));
+    nodeId = id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+SavePieceOptions::~SavePieceOptions()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SavePieceOptions::undo()
+{
+    qCDebug(vUndo, "Undo.");
+
+    QDomElement domElement = doc->elementById(nodeId);
+    if (domElement.isElement())
+    {
+        VToolSeamAllowance::AddAttributes(doc, domElement, nodeId, m_oldDet);
+        doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
+        VToolSeamAllowance::AddPatternPieceData(doc, domElement, m_oldDet);
+        VToolSeamAllowance::AddPatternInfo(doc, domElement, m_oldDet);
+        VToolSeamAllowance::AddGrainline(doc, domElement, m_oldDet);
+        VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
+
+        IncrementReferences(m_oldDet.Missing(m_newDet));
+        emit NeedLiteParsing(Document::LiteParse);
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find detail with id = %u.", nodeId);
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SavePieceOptions::redo()
+{
+    qCDebug(vUndo, "Redo.");
+
+    QDomElement domElement = doc->elementById(nodeId);
+    if (domElement.isElement())
+    {
+        VToolSeamAllowance::AddAttributes(doc, domElement, nodeId, m_newDet);
+        doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
+        VToolSeamAllowance::AddPatternPieceData(doc, domElement, m_newDet);
+        VToolSeamAllowance::AddPatternInfo(doc, domElement, m_newDet);
+        VToolSeamAllowance::AddGrainline(doc, domElement, m_newDet);
+        VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
+
+        DecrementReferences(m_oldDet.Missing(m_newDet));
+        emit NeedLiteParsing(Document::LiteParse);
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find detail with id = %u.", nodeId);
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool SavePieceOptions::mergeWith(const QUndoCommand *command)
+{
+    const SavePieceOptions *saveCommand = static_cast<const SavePieceOptions *>(command);
+    SCASSERT(saveCommand != nullptr);
+    const quint32 id = saveCommand->DetId();
+
+    if (id != nodeId)
+    {
+        return false;
+    }
+
+    m_newDet = saveCommand->NewDet();
+    return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int SavePieceOptions::id() const
+{
+    return static_cast<int>(UndoCommand::SavePieceOptions);
+}
diff --git a/src/libs/vtools/undocommands/savepieceoptions.h b/src/libs/vtools/undocommands/savepieceoptions.h
new file mode 100644
index 000000000..306a0c4d0
--- /dev/null
+++ b/src/libs/vtools/undocommands/savepieceoptions.h
@@ -0,0 +1,75 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   9 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 SAVEPIECEOPTIONS_H
+#define SAVEPIECEOPTIONS_H
+
+#include <QtGlobal>
+
+#include "vpiece.h"
+#include "vundocommand.h"
+
+class QDomElement;
+class QGraphicsScene;
+class QUndoCommand;
+class VAbstractPattern;
+
+class SavePieceOptions : public VUndoCommand
+{
+public:
+    SavePieceOptions(const VPiece &m_oldDet, const VPiece &m_newDet, VAbstractPattern *doc, quint32 id,
+                     QGraphicsScene *m_scene, QUndoCommand *parent = nullptr);
+    virtual ~SavePieceOptions();
+
+    virtual void undo() Q_DECL_OVERRIDE;
+    virtual void redo() Q_DECL_OVERRIDE;
+    virtual bool mergeWith(const QUndoCommand *command) Q_DECL_OVERRIDE;
+    virtual int  id() const Q_DECL_OVERRIDE;
+    quint32      DetId() const;
+    VPiece       NewDet() const;
+private:
+    Q_DISABLE_COPY(SavePieceOptions)
+
+    const VPiece    m_oldDet;
+    VPiece          m_newDet;
+    QGraphicsScene *m_scene;
+};
+
+//---------------------------------------------------------------------------------------------------------------------
+inline quint32 SavePieceOptions::DetId() const
+{
+    return nodeId;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline VPiece SavePieceOptions::NewDet() const
+{
+    return m_newDet;
+}
+
+#endif // SAVEPIECEOPTIONS_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index d031daf32..2514e4765 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -25,7 +25,8 @@ HEADERS += \
     $$PWD/label/operationmovelabel.h \
     $$PWD/addpiece.h \
     $$PWD/deletepiece.h \
-    $$PWD/movepiece.h
+    $$PWD/movepiece.h \
+    $$PWD/savepieceoptions.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -51,4 +52,5 @@ SOURCES += \
     $$PWD/label/operationmovelabel.cpp \
     $$PWD/addpiece.cpp \
     $$PWD/deletepiece.cpp \
-    $$PWD/movepiece.cpp
+    $$PWD/movepiece.cpp \
+    $$PWD/savepieceoptions.cpp
diff --git a/src/libs/vtools/undocommands/vundocommand.cpp b/src/libs/vtools/undocommands/vundocommand.cpp
index 51a3ccd4c..fab10fab9 100644
--- a/src/libs/vtools/undocommands/vundocommand.cpp
+++ b/src/libs/vtools/undocommands/vundocommand.cpp
@@ -94,6 +94,15 @@ void VUndoCommand::DecrementReferences(const QVector<VNodeDetail> &nodes) const
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::IncrementReferences(const QVector<VPieceNode> &nodes) const
+{
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        doc->IncrementReferens(nodes.at(i).GetId());
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VUndoCommand::DecrementReferences(const QVector<VPieceNode> &nodes) const
 {
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index b8ae606ea..697346f63 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -54,6 +54,7 @@ enum class UndoCommand: char { AddPatternPiece,
                                MoveSPoint,
                                SaveToolOptions,
                                SaveDetailOptions,
+                               SavePieceOptions,
                                MovePiece,
                                DeleteTool,
                                DeletePatternPiece,
@@ -88,6 +89,7 @@ protected:
 
     void         IncrementReferences(const QVector<VNodeDetail> &nodes) const;
     void         DecrementReferences(const QVector<VNodeDetail> &nodes) const;
+    void         IncrementReferences(const QVector<VPieceNode> &nodes) const;
     void         DecrementReferences(const QVector<VPieceNode> &nodes) const;
 private:
     Q_DISABLE_COPY(VUndoCommand)

From 39d2ea41ac9f8974e27c4d6cd1a6acd8bbd290b9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 15:53:22 +0200
Subject: [PATCH 033/208] Returned undocommand "Toggle piece in layout".

--HG--
branch : feature
---
 src/app/valentina/dialogs/vwidgetdetails.cpp  | 33 +++++-----
 src/app/valentina/dialogs/vwidgetdetails.h    |  4 +-
 src/app/valentina/xml/vpattern.cpp            |  4 +-
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |  2 +
 src/libs/ifc/xml/vpatternconverter.cpp        |  2 -
 src/libs/vlayout/vabstractpiece.cpp           | 20 +++++-
 src/libs/vlayout/vabstractpiece.h             |  8 +++
 src/libs/vlayout/vabstractpiece_p.h           | 66 +++++++++++++++++++
 src/libs/vlayout/vlayout.pri                  |  3 +-
 src/libs/vpatterndb/vpiece.cpp                | 12 ++++
 src/libs/vpatterndb/vpiece.h                  |  3 +
 src/libs/vpatterndb/vpiece_p.h                |  8 ++-
 src/libs/vtools/tools/vtooldetail.cpp         |  6 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  | 26 ++++----
 ...ilinlayout.cpp => togglepieceinlayout.cpp} | 28 ++++----
 ...detailinlayout.h => togglepieceinlayout.h} | 10 +--
 src/libs/vtools/undocommands/undocommands.pri |  8 +--
 src/libs/vtools/undocommands/vundocommand.h   |  2 +-
 18 files changed, 177 insertions(+), 68 deletions(-)
 create mode 100644 src/libs/vlayout/vabstractpiece_p.h
 rename src/libs/vtools/undocommands/{toggledetailinlayout.cpp => togglepieceinlayout.cpp} (83%)
 rename src/libs/vtools/undocommands/{toggledetailinlayout.h => togglepieceinlayout.h} (87%)

diff --git a/src/app/valentina/dialogs/vwidgetdetails.cpp b/src/app/valentina/dialogs/vwidgetdetails.cpp
index 1942ca3fc..7fe50975a 100644
--- a/src/app/valentina/dialogs/vwidgetdetails.cpp
+++ b/src/app/valentina/dialogs/vwidgetdetails.cpp
@@ -31,7 +31,7 @@
 #include "../ifc/xml/vabstractpattern.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vmisc/vabstractapplication.h"
-#include "../vtools/undocommands/toggledetailinlayout.h"
+#include "../vtools/undocommands/togglepieceinlayout.h"
 
 #include <QMenu>
 #include <QUndoStack>
@@ -45,7 +45,7 @@ VWidgetDetails::VWidgetDetails(VContainer *data, VAbstractPattern *doc, QWidget
 {
     ui->setupUi(this);
 
-    FillTable(m_data->DataDetails());
+    FillTable(m_data->DataPieces());
 
     ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
 
@@ -62,7 +62,7 @@ VWidgetDetails::~VWidgetDetails()
 //---------------------------------------------------------------------------------------------------------------------
 void VWidgetDetails::UpdateList()
 {
-    FillTable(m_data->DataDetails());
+    FillTable(m_data->DataPieces());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -93,16 +93,16 @@ void VWidgetDetails::InLayoutStateChanged(int row, int column)
         return;
     }
 
-    const QHash<quint32, VDetail> *allDetails = m_data->DataDetails();
+    const QHash<quint32, VPiece> *allDetails = m_data->DataPieces();
     const bool inLayout = not allDetails->value(id).IsInLayout();
 
-    ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, inLayout, m_data, m_doc);
-    connect(togglePrint, &ToggleDetailInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
+    TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, inLayout, m_data, m_doc);
+    connect(togglePrint, &TogglePieceInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
     qApp->getUndoStack()->push(togglePrint);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VWidgetDetails::FillTable(const QHash<quint32, VDetail> *details)
+void VWidgetDetails::FillTable(const QHash<quint32, VPiece> *details)
 {
     const int selectedRow = ui->tableWidget->currentRow();
     ui->tableWidget->clear();
@@ -114,7 +114,7 @@ void VWidgetDetails::FillTable(const QHash<quint32, VDetail> *details)
     while (i != details->constEnd())
     {
         ++currentRow;
-        const VDetail det = i.value();
+        const VPiece det = i.value();
 
         QTableWidgetItem *item = new QTableWidgetItem();
         item->setTextAlignment(Qt::AlignHCenter);
@@ -134,7 +134,7 @@ void VWidgetDetails::FillTable(const QHash<quint32, VDetail> *details)
 
         ui->tableWidget->setItem(currentRow, 0, item);
 
-        QString name = det.getName();
+        QString name = det.GetName();
         if (name.isEmpty())
         {
             name = tr("Unnamed");
@@ -158,7 +158,7 @@ void VWidgetDetails::FillTable(const QHash<quint32, VDetail> *details)
 //---------------------------------------------------------------------------------------------------------------------
 void VWidgetDetails::ToggleSectionDetails(bool select)
 {
-    const QHash<quint32, VDetail> *allDetails = m_data->DataDetails();
+    const QHash<quint32, VPiece> *allDetails = m_data->DataPieces();
     if (allDetails->count() == 0)
     {
         return;
@@ -172,8 +172,8 @@ void VWidgetDetails::ToggleSectionDetails(bool select)
         {
             if (not select == allDetails->value(id).IsInLayout())
             {
-                ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, select, m_data, m_doc);
-                connect(togglePrint, &ToggleDetailInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
+                TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, select, m_data, m_doc);
+                connect(togglePrint, &TogglePieceInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
                 qApp->getUndoStack()->push(togglePrint);
             }
         }
@@ -193,7 +193,7 @@ void VWidgetDetails::ShowContextMenu(const QPoint &pos)
 
     QAction *actionInvertSelection = menu->addAction(tr("Invert selection"));
 
-    const QHash<quint32, VDetail> *allDetails = m_data->DataDetails();
+    const QHash<quint32, VPiece> *allDetails = m_data->DataPieces();
     if (allDetails->count() == 0)
     {
         return;
@@ -201,7 +201,7 @@ void VWidgetDetails::ShowContextMenu(const QPoint &pos)
 
     int selectedDetails = 0;
 
-    QHash<quint32, VDetail>::const_iterator iter = allDetails->constBegin();
+    auto iter = allDetails->constBegin();
     while (iter != allDetails->constEnd())
     {
         if(iter.value().IsInLayout())
@@ -220,7 +220,6 @@ void VWidgetDetails::ShowContextMenu(const QPoint &pos)
         actionSelectAll->setDisabled(true);
     }
 
-
     QAction *selectedAction = menu->exec(ui->tableWidget->viewport()->mapToGlobal(pos));
 
     bool select;
@@ -250,8 +249,8 @@ void VWidgetDetails::ShowContextMenu(const QPoint &pos)
             {
                 select = not allDetails->value(id).IsInLayout();
 
-                ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, select, m_data, m_doc);
-                connect(togglePrint, &ToggleDetailInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
+                TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, select, m_data, m_doc);
+                connect(togglePrint, &TogglePieceInLayout::UpdateList, this, &VWidgetDetails::UpdateList);
                 qApp->getUndoStack()->push(togglePrint);
             }
         }
diff --git a/src/app/valentina/dialogs/vwidgetdetails.h b/src/app/valentina/dialogs/vwidgetdetails.h
index 987bb74d1..f33ce9efc 100644
--- a/src/app/valentina/dialogs/vwidgetdetails.h
+++ b/src/app/valentina/dialogs/vwidgetdetails.h
@@ -33,7 +33,7 @@
 
 class VAbstractPattern;
 class VContainer;
-class VDetail;
+class VPiece;
 
 namespace Ui
 {
@@ -65,7 +65,7 @@ private:
     VAbstractPattern   *m_doc;
     VContainer         *m_data;
 
-    void FillTable(const QHash<quint32, VDetail> *details);
+    void FillTable(const QHash<quint32, VPiece> *details);
     void ToggleSectionDetails(bool select);
 };
 
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index c77fc37eb..fd36726f0 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -615,7 +615,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
     {
         VPiece detail;
         const quint32 id = GetParametrId(domElement);
-//        detail.setName(GetParametrString(domElement, AttrName, ""));
+        detail.SetName(GetParametrString(domElement, AttrName, ""));
         detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
         detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
 //        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
@@ -623,7 +623,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
 //        detail.setForbidFlipping(GetParametrUInt(domElement, VToolDetail::AttrForbidFlipping,
 //                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
-//        detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
+        detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
 
         const QStringList tags = QStringList() << VToolSeamAllowance::TagNodes
                                                << TagData
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index eb822a1c5..4cce2e334 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -412,6 +412,8 @@
                                                                            <xs:attribute name="version" type="pieceVersion"></xs:attribute>
                                                                            <xs:attribute name="mx" type="xs:double"></xs:attribute>
                                                                            <xs:attribute name="my" type="xs:double"></xs:attribute>
+                                                                           <xs:attribute name="name" type="xs:string"></xs:attribute>
+                                                                           <xs:attribute name="inLayout" type="xs:boolean"></xs:attribute>
                                                                      </xs:complexType>
                                                                </xs:element>
                                                          </xs:sequence>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index 1f004335e..86276b417 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -1694,12 +1694,10 @@ void VPatternConverter::TagDetailToV0_4_0()
 
         if (not dom.isNull())
         {
-            dom.removeAttribute(strName);
             dom.removeAttribute(strSupplement);
             dom.removeAttribute(strClosed);
             dom.removeAttribute(strWidth);
             dom.removeAttribute(strForbidFlipping);
-            dom.removeAttribute(strInLayout);
 
             dom.setAttribute(strVersion, "1");
 
diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 0309df112..5b7cecdf2 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -27,6 +27,7 @@
  *************************************************************************/
 
 #include "vabstractpiece.h"
+#include "vabstractpiece_p.h"
 
 #include <QLineF>
 #include <QSet>
@@ -37,13 +38,13 @@
 
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPiece::VAbstractPiece()
+    : d(new VAbstractPieceData)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPiece::VAbstractPiece(const VAbstractPiece &piece)
-{
-    Q_UNUSED(piece)
-}
+    :d (piece.d)
+{}
 
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPiece &VAbstractPiece::operator=(const VAbstractPiece &piece)
@@ -52,6 +53,7 @@ VAbstractPiece &VAbstractPiece::operator=(const VAbstractPiece &piece)
     {
         return *this;
     }
+    d = piece.d;
     return *this;
 }
 
@@ -59,6 +61,18 @@ VAbstractPiece &VAbstractPiece::operator=(const VAbstractPiece &piece)
 VAbstractPiece::~VAbstractPiece()
 {}
 
+//---------------------------------------------------------------------------------------------------------------------
+QString VAbstractPiece::GetName() const
+{
+    return d->m_name;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractPiece::SetName(const QString &value)
+{
+    d->m_name = value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 78caab9bd..491712f58 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -30,9 +30,11 @@
 #define VABSTRACTPIECE_H
 
 #include <QtGlobal>
+#include <QSharedDataPointer>
 
 template <class T> class QVector;
 class QPointF;
+class VAbstractPieceData;
 
 class VAbstractPiece
 {
@@ -42,12 +44,18 @@ public:
     VAbstractPiece &operator=(const VAbstractPiece &piece);
     virtual ~VAbstractPiece();
 
+    QString GetName() const;
+    void    SetName(const QString &value);
+
     static qreal            SumTrapezoids(const QVector<QPointF> &points);
     static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
     static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
 
 protected:
     static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast = true);
+
+private:
+    QSharedDataPointer<VAbstractPieceData> d;
 };
 
 #endif // VABSTRACTPIECE_H
diff --git a/src/libs/vlayout/vabstractpiece_p.h b/src/libs/vlayout/vabstractpiece_p.h
new file mode 100644
index 000000000..470d25ecb
--- /dev/null
+++ b/src/libs/vlayout/vabstractpiece_p.h
@@ -0,0 +1,66 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   9 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VABSTRACTPIECE_P_H
+#define VABSTRACTPIECE_P_H
+
+#include <QSharedData>
+#include <QString>
+
+#include "../vmisc/diagnostic.h"
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+
+class VAbstractPieceData : public QSharedData
+{
+public:
+    VAbstractPieceData()
+        : m_name()
+    {}
+
+    VAbstractPieceData(const VAbstractPieceData &piece)
+        : QSharedData(piece),
+          m_name(piece.m_name)
+    {}
+
+    ~VAbstractPieceData();
+
+    QString m_name;
+
+private:
+    VAbstractPieceData &operator=(const VAbstractPieceData &) Q_DECL_EQ_DELETE;
+};
+
+VAbstractPieceData::~VAbstractPieceData()
+{}
+
+QT_WARNING_POP
+
+#endif // VABSTRACTPIECE_P_H
+
diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri
index 434680020..29ef87f7c 100644
--- a/src/libs/vlayout/vlayout.pri
+++ b/src/libs/vlayout/vlayout.pri
@@ -19,7 +19,8 @@ HEADERS += \
     $$PWD/vtextmanager.h \
     $$PWD/vposter.h \
     $$PWD/vgraphicsfillitem.h \
-    $$PWD/vabstractpiece.h
+    $$PWD/vabstractpiece.h \
+    $$PWD/vabstractpiece_p.h
 
 SOURCES += \
     $$PWD/vlayoutgenerator.cpp \
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 874681bc7..5f25e37cb 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -244,6 +244,18 @@ void VPiece::SetMy(qreal value)
     d->m_my = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VPiece::IsInLayout() const
+{
+    return d->m_inLayout;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetInLayout(bool inLayout)
+{
+    d->m_inLayout = inLayout;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 09261d836..31e82d401 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -71,6 +71,9 @@ public:
     qreal GetMy() const;
     void  SetMy(qreal value);
 
+    bool IsInLayout() const;
+    void SetInLayout(bool inLayout);
+
     QVector<VPieceNode> Missing(const VPiece &det) const;
 
     int indexOfNode(const quint32 &id) const;
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 79001e36a..6ddf9fd80 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -44,14 +44,16 @@ public:
     VPieceData()
         : m_nodes(),
           m_mx(0),
-          m_my(0)
+          m_my(0),
+          m_inLayout(true)
     {}
 
     VPieceData(const VPieceData &detail)
         : QSharedData(detail),
           m_nodes(detail.m_nodes),
           m_mx(detail.m_mx),
-          m_my(detail.m_my)
+          m_my(detail.m_my),
+          m_inLayout(detail.m_inLayout)
     {}
 
     ~VPieceData();
@@ -62,6 +64,8 @@ public:
     qreal m_mx;
     qreal m_my;
 
+    bool m_inLayout;
+
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
 };
diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp
index a2b4a9d05..42b8f9afa 100644
--- a/src/libs/vtools/tools/vtooldetail.cpp
+++ b/src/libs/vtools/tools/vtooldetail.cpp
@@ -76,7 +76,7 @@
 #include "../undocommands/deletedetail.h"
 #include "../undocommands/movepiece.h"
 #include "../undocommands/savedetailoptions.h"
-#include "../undocommands/toggledetailinlayout.h"
+#include "../undocommands/togglepieceinlayout.h"
 #include "../vgeometry/varc.h"
 #include "../vgeometry/vcubicbezier.h"
 #include "../vgeometry/vcubicbezierpath.h"
@@ -805,9 +805,9 @@ void VToolDetail::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
     }
     else if (selectedAction == inLayoutOption)
     {
-        ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, selectedAction->isChecked(),
+        TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, selectedAction->isChecked(),
                                                                      &(VAbstractTool::data), doc);
-        connect(togglePrint, &ToggleDetailInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
+        connect(togglePrint, &TogglePieceInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
         qApp->getUndoStack()->push(togglePrint);
     }
     else if (selectedAction == actionRemove)
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index a8e2347e3..5dc59d2d6 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -44,7 +44,7 @@
 #include "../undocommands/deletepiece.h"
 #include "../undocommands/movepiece.h"
 #include "../undocommands/savepieceoptions.h"
-//#include "../undocommands/togglepieceinlayout.h"
+#include "../undocommands/togglepieceinlayout.h"
 #include "../vwidgets/vmaingraphicsview.h"
 
 #include <QGraphicsSceneMouseEvent>
@@ -247,9 +247,11 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     SCASSERT(doc != nullptr);
 
     doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+    doc->SetAttribute(domElement, AttrName, piece.GetName());
     doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
     doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
     doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
+    doc->SetAttribute(domElement, AttrInLayout, piece.IsInLayout());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -518,10 +520,10 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
     QMenu menu;
     QAction *actionOption = menu.addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
 
-//    QAction *inLayoutOption = menu.addAction(tr("In layout"));
-//    inLayoutOption->setCheckable(true);
-//    const VDetail detail = VAbstractTool::data.GetDetail(id);
-//    inLayoutOption->setChecked(detail.IsInLayout());
+    QAction *inLayoutOption = menu.addAction(tr("In layout"));
+    inLayoutOption->setCheckable(true);
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
+    inLayoutOption->setChecked(detail.IsInLayout());
 
     QAction *actionRemove = menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
     _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
@@ -537,13 +539,13 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
         SetDialog();
         m_dialog->show();
     }
-//    else if (selectedAction == inLayoutOption)
-//    {
-//        ToggleDetailInLayout *togglePrint = new ToggleDetailInLayout(id, selectedAction->isChecked(),
-//                                                                     &(VAbstractTool::data), doc);
-//        connect(togglePrint, &ToggleDetailInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
-//        qApp->getUndoStack()->push(togglePrint);
-//    }
+    else if (selectedAction == inLayoutOption)
+    {
+        TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, selectedAction->isChecked(),
+                                                                   &(VAbstractTool::data), doc);
+        connect(togglePrint, &TogglePieceInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
+        qApp->getUndoStack()->push(togglePrint);
+    }
     else if (selectedAction == actionRemove)
     {
         try
diff --git a/src/libs/vtools/undocommands/toggledetailinlayout.cpp b/src/libs/vtools/undocommands/togglepieceinlayout.cpp
similarity index 83%
rename from src/libs/vtools/undocommands/toggledetailinlayout.cpp
rename to src/libs/vtools/undocommands/togglepieceinlayout.cpp
index 88aa7daf2..7a3b65016 100644
--- a/src/libs/vtools/undocommands/toggledetailinlayout.cpp
+++ b/src/libs/vtools/undocommands/togglepieceinlayout.cpp
@@ -26,7 +26,7 @@
  **
  *************************************************************************/
 
-#include "toggledetailinlayout.h"
+#include "togglepieceinlayout.h"
 
 #include <QDomElement>
 #include <QHash>
@@ -38,30 +38,30 @@
 #include "../vmisc/def.h"
 #include "../vmisc/logging.h"
 #include "../vpatterndb/vcontainer.h"
-#include "../vpatterndb/vdetail.h"
+#include "../vpatterndb/vpiece.h"
 #include "vundocommand.h"
 
 class QUndoCommand;
 
 //---------------------------------------------------------------------------------------------------------------------
-ToggleDetailInLayout::ToggleDetailInLayout(quint32 id, bool state, VContainer *data, VAbstractPattern *doc,
+TogglePieceInLayout::TogglePieceInLayout(quint32 id, bool state, VContainer *data, VAbstractPattern *doc,
                                            QUndoCommand *parent)
     : VUndoCommand(QDomElement(), doc, parent),
       m_id(id),
       m_data(data),
-      m_oldState(m_data->DataDetails()->value(m_id).IsInLayout()),
+      m_oldState(m_data->DataPieces()->value(m_id).IsInLayout()),
       m_newState(state)
 {
     setText(tr("detail in layout list"));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-ToggleDetailInLayout::~ToggleDetailInLayout()
+TogglePieceInLayout::~TogglePieceInLayout()
 {
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void ToggleDetailInLayout::undo()
+void TogglePieceInLayout::undo()
 {
     qCDebug(vUndo, "ToggleDetailInLayout::undo().");
 
@@ -72,7 +72,7 @@ void ToggleDetailInLayout::undo()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void ToggleDetailInLayout::redo()
+void TogglePieceInLayout::redo()
 {
     qCDebug(vUndo, "ToggleDetailInLayout::redo().");
 
@@ -83,25 +83,25 @@ void ToggleDetailInLayout::redo()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int ToggleDetailInLayout::id() const
+int TogglePieceInLayout::id() const
 {
-    return static_cast<int>(UndoCommand::ToggleDetailInLayout);
+    return static_cast<int>(UndoCommand::TogglePieceInLayout);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-quint32 ToggleDetailInLayout::getDetId() const
+quint32 TogglePieceInLayout::getDetId() const
 {
     return m_id;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool ToggleDetailInLayout::getNewState() const
+bool TogglePieceInLayout::getNewState() const
 {
     return m_newState;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void ToggleDetailInLayout::Do(bool state)
+void TogglePieceInLayout::Do(bool state)
 {
     QDomElement detail = doc->elementById(m_id);
     if (detail.isElement())
@@ -115,9 +115,9 @@ void ToggleDetailInLayout::Do(bool state)
             detail.removeAttribute(AttrInLayout);
         }
 
-        VDetail det = m_data->DataDetails()->value(m_id);
+        VPiece det = m_data->DataPieces()->value(m_id);
         det.SetInLayout(state);
-        m_data->UpdateDetail(m_id, det);
+        m_data->UpdatePiece(m_id, det);
         emit UpdateList();
     }
     else
diff --git a/src/libs/vtools/undocommands/toggledetailinlayout.h b/src/libs/vtools/undocommands/togglepieceinlayout.h
similarity index 87%
rename from src/libs/vtools/undocommands/toggledetailinlayout.h
rename to src/libs/vtools/undocommands/togglepieceinlayout.h
index 9ba65da8c..d4879968e 100644
--- a/src/libs/vtools/undocommands/toggledetailinlayout.h
+++ b/src/libs/vtools/undocommands/togglepieceinlayout.h
@@ -41,13 +41,13 @@ class QUndoCommand;
 class VAbstractPattern;
 class VContainer;
 
-class ToggleDetailInLayout : public VUndoCommand
+class TogglePieceInLayout : public VUndoCommand
 {
     Q_OBJECT
 public:
-    ToggleDetailInLayout(quint32 id, bool state, VContainer *data, VAbstractPattern *doc,
-                         QUndoCommand *parent = nullptr);
-    virtual ~ToggleDetailInLayout();
+    TogglePieceInLayout(quint32 id, bool state, VContainer *data, VAbstractPattern *doc,
+                        QUndoCommand *parent = nullptr);
+    virtual ~TogglePieceInLayout();
     virtual void undo() Q_DECL_OVERRIDE;
     virtual void redo() Q_DECL_OVERRIDE;
     virtual int  id() const Q_DECL_OVERRIDE;
@@ -57,7 +57,7 @@ public:
 signals:
     void UpdateList();
 private:
-    Q_DISABLE_COPY(ToggleDetailInLayout)
+    Q_DISABLE_COPY(TogglePieceInLayout)
     quint32     m_id;
     VContainer *m_data;
     bool        m_oldState;
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index 2514e4765..c73295eee 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -21,12 +21,12 @@ HEADERS += \
     $$PWD/addgroup.h \
     $$PWD/delgroup.h \
     $$PWD/label/moveabstractlabel.h \
-    $$PWD/toggledetailinlayout.h \
     $$PWD/label/operationmovelabel.h \
     $$PWD/addpiece.h \
     $$PWD/deletepiece.h \
     $$PWD/movepiece.h \
-    $$PWD/savepieceoptions.h
+    $$PWD/savepieceoptions.h \
+    $$PWD/togglepieceinlayout.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -48,9 +48,9 @@ SOURCES += \
     $$PWD/addgroup.cpp \
     $$PWD/delgroup.cpp \
     $$PWD/label/moveabstractlabel.cpp \
-    $$PWD/toggledetailinlayout.cpp \
     $$PWD/label/operationmovelabel.cpp \
     $$PWD/addpiece.cpp \
     $$PWD/deletepiece.cpp \
     $$PWD/movepiece.cpp \
-    $$PWD/savepieceoptions.cpp
+    $$PWD/savepieceoptions.cpp \
+    $$PWD/togglepieceinlayout.cpp
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index 697346f63..d4fceb414 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -62,7 +62,7 @@ enum class UndoCommand: char { AddPatternPiece,
                                MoveLabel,
                                MoveDoubleLabel,
                                RotationMoveLabel,
-                               ToggleDetailInLayout
+                               TogglePieceInLayout
                              };
 
 class VNodeDetail;

From a6a492c8d307c6dff7b584e4ac52fbb09cec00d0 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 16:27:17 +0200
Subject: [PATCH 034/208] Better to give a piece default name.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index fd36726f0..ab13cbeb8 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -615,7 +615,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
     {
         VPiece detail;
         const quint32 id = GetParametrId(domElement);
-        detail.SetName(GetParametrString(domElement, AttrName, ""));
+        detail.SetName(GetParametrString(domElement, AttrName, tr("Detail")));
         detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
         detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
 //        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));

From 1c0dced61d1e44324e8bc53e8903569865a1b7c5 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 16:27:55 +0200
Subject: [PATCH 035/208] Apply button now works.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 31 ++++++++++++++------
 src/libs/vtools/tools/vtoolseamallowance.h   |  4 ++-
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 5dc59d2d6..04dd71ced 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -302,19 +302,17 @@ void VToolSeamAllowance::FullUpdateFromGuiOk(int result)
 {
     if (result == QDialog::Accepted)
     {
-        SCASSERT(not m_dialog.isNull());
-        DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(m_dialog.data());
-        SCASSERT(dialogTool != nullptr);
-        const VPiece newDet = dialogTool->GetPiece();
-        const VPiece oldDet = VAbstractTool::data.GetPiece(id);
-
-        SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id, this->scene());
-        connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-        qApp->getUndoStack()->push(saveCommand);
+        SaveDialogChange();
     }
     delete m_dialog;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::FullUpdateFromGuiApply()
+{
+    SaveDialogChange();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::EnableToolMove(bool move)
 {
@@ -536,6 +534,7 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
         m_dialog = dialog;
         m_dialog->setModal(true);
         connect(m_dialog.data(), &DialogTool::DialogClosed, this, &VToolSeamAllowance::FullUpdateFromGuiOk);
+        connect(m_dialog.data(), &DialogTool::DialogApplied, this, &VToolSeamAllowance::FullUpdateFromGuiApply);
         SetDialog();
         m_dialog->show();
     }
@@ -668,6 +667,20 @@ void VToolSeamAllowance::RefreshGeometry()
     this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SaveDialogChange()
+{
+    SCASSERT(not m_dialog.isNull());
+    DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(m_dialog.data());
+    SCASSERT(dialogTool != nullptr);
+    const VPiece newDet = dialogTool->GetPiece();
+    const VPiece oldDet = VAbstractTool::data.GetPiece(id);
+
+    SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id, this->scene());
+    connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(saveCommand);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::DeleteTool(bool ask)
 {
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 7e57059aa..5a3f6d4e9 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -83,6 +83,7 @@ public:
 public slots:
     virtual void       FullUpdateFromFile () Q_DECL_OVERRIDE;
     virtual void       FullUpdateFromGuiOk(int result);
+    void               FullUpdateFromGuiApply();
     void               EnableToolMove(bool move);
     virtual void       AllowHover(bool enabled) Q_DECL_OVERRIDE;
     virtual void       AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
@@ -119,7 +120,8 @@ private:
     VToolSeamAllowance(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation,
                        VMainGraphicsScene *scene, const QString &m_drawName, QGraphicsItem * parent = nullptr);
 
-    void               RefreshGeometry ();
+    void RefreshGeometry();
+    void SaveDialogChange();
 
     template <typename Tool>
     Tool*              InitTool(VMainGraphicsScene *scene, const VPieceNode &node);

From 836df6e3095c072097c418d7587280698b6d7e33 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 9 Nov 2016 16:29:28 +0200
Subject: [PATCH 036/208] Zoom fit best for details scene again working.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index c7f6aa65e..c8941b238 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -4332,7 +4332,7 @@ void MainWindow::ZoomFirstShow()
      * pattern will be moved. Looks very ugly. It is best solution that i have now.
      */
 
-    if (pattern->DataDetails()->size() > 0)
+    if (pattern->DataPieces()->size() > 0)
     {
         ActionDetails(true);
         ui->view->ZoomFitBest();

From 2489f525f7168878d331e140d261a3c731c58a06 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 11:27:59 +0200
Subject: [PATCH 037/208] Added tab Seam allowance. Disabled if Apply button is
 not active.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 1 +
 src/libs/vtools/dialogs/tools/dialogseamallowance.ui  | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 567f8ad93..830cd110e 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -72,6 +72,7 @@ void DialogSeamAllowance::EnableApply(bool enable)
     SCASSERT(bApply != nullptr);
     bApply->setEnabled(enable);
     applyAllowed = enable;
+    ui->tabSeamAllowance->setEnabled(applyAllowed);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 78d9d7889..d2c6808b9 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -80,6 +80,11 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tabSeamAllowance">
+      <attribute name="title">
+       <string>Seam allowance</string>
+      </attribute>
+     </widget>
     </widget>
    </item>
    <item>

From df20415e9ea7500f4a2dd7ad16ce4bcc421f5751 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 11:56:40 +0200
Subject: [PATCH 038/208] Returned "Forbid flipping" feature.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp                   |  4 ++--
 src/libs/ifc/schema/pattern/v0.4.0.xsd               |  1 +
 src/libs/ifc/xml/vpatternconverter.cpp               |  1 -
 src/libs/vlayout/vabstractpiece.cpp                  | 12 ++++++++++++
 src/libs/vlayout/vabstractpiece.h                    |  3 +++
 src/libs/vlayout/vabstractpiece_p.h                  |  8 ++++++--
 .../vtools/dialogs/tools/dialogseamallowance.cpp     |  6 ++++++
 src/libs/vtools/dialogs/tools/dialogseamallowance.ui | 10 ++++++++++
 src/libs/vtools/tools/vtoolseamallowance.cpp         |  6 ++++--
 src/libs/vtools/tools/vtoolseamallowance.h           |  1 +
 10 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index ab13cbeb8..0e6c2852c 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -621,8 +621,8 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
 //        detail.setWidth(GetParametrDouble(domElement, VToolDetail::AttrWidth, "10.0"));
 //        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
-//        detail.setForbidFlipping(GetParametrUInt(domElement, VToolDetail::AttrForbidFlipping,
-//                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
+        detail.SetForbidFlipping(GetParametrUInt(domElement, VToolSeamAllowance::AttrForbidFlipping,
+                                           QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
 
         const QStringList tags = QStringList() << VToolSeamAllowance::TagNodes
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 4cce2e334..bad75d2e5 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -414,6 +414,7 @@
                                                                            <xs:attribute name="my" type="xs:double"></xs:attribute>
                                                                            <xs:attribute name="name" type="xs:string"></xs:attribute>
                                                                            <xs:attribute name="inLayout" type="xs:boolean"></xs:attribute>
+                                                                           <xs:attribute name="forbidFlipping" type="xs:unsignedInt"></xs:attribute>
                                                                      </xs:complexType>
                                                                </xs:element>
                                                          </xs:sequence>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index 86276b417..95cfab0b3 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -1697,7 +1697,6 @@ void VPatternConverter::TagDetailToV0_4_0()
             dom.removeAttribute(strSupplement);
             dom.removeAttribute(strClosed);
             dom.removeAttribute(strWidth);
-            dom.removeAttribute(strForbidFlipping);
 
             dom.setAttribute(strVersion, "1");
 
diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 5b7cecdf2..18c90e178 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -73,6 +73,18 @@ void VAbstractPiece::SetName(const QString &value)
     d->m_name = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPiece::IsForbidFlipping() const
+{
+    return d->m_forbidFlipping;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractPiece::SetForbidFlipping(bool value)
+{
+    d->m_forbidFlipping = value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 491712f58..9bc90aac1 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -47,6 +47,9 @@ public:
     QString GetName() const;
     void    SetName(const QString &value);
 
+    bool IsForbidFlipping() const;
+    void SetForbidFlipping(bool value);
+
     static qreal            SumTrapezoids(const QVector<QPointF> &points);
     static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
     static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
diff --git a/src/libs/vlayout/vabstractpiece_p.h b/src/libs/vlayout/vabstractpiece_p.h
index 470d25ecb..831969199 100644
--- a/src/libs/vlayout/vabstractpiece_p.h
+++ b/src/libs/vlayout/vabstractpiece_p.h
@@ -41,17 +41,21 @@ class VAbstractPieceData : public QSharedData
 {
 public:
     VAbstractPieceData()
-        : m_name()
+        : m_name(),
+          m_forbidFlipping(false)
     {}
 
     VAbstractPieceData(const VAbstractPieceData &piece)
         : QSharedData(piece),
-          m_name(piece.m_name)
+          m_name(piece.m_name),
+          m_forbidFlipping(piece.m_forbidFlipping)
     {}
 
     ~VAbstractPieceData();
 
     QString m_name;
+    /** @brief forbidFlipping forbid piece be mirrored in a layout. */
+    bool    m_forbidFlipping;
 
 private:
     VAbstractPieceData &operator=(const VAbstractPieceData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 830cd110e..e80cceb72 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -50,6 +50,8 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     flagError = MainPathIsValid();
     CheckState();
 
+    ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
+
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
@@ -91,6 +93,8 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
         NewItem(m_piece.at(i));
     }
 
+    ui->checkBoxForbidFlipping->setChecked(m_piece.IsForbidFlipping());
+
     ValidObjects(MainPathIsValid());
 }
 
@@ -260,6 +264,8 @@ VPiece DialogSeamAllowance::CreatePiece() const
         piece.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
     }
 
+    piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
+
     return piece;
 }
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index d2c6808b9..dcf3c2ed6 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -58,6 +58,16 @@
          </item>
         </layout>
        </item>
+       <item>
+        <widget class="QCheckBox" name="checkBoxForbidFlipping">
+         <property name="toolTip">
+          <string>Forbid piece be mirrored in a layout.</string>
+         </property>
+         <property name="text">
+          <string>Forbid flipping</string>
+         </property>
+        </widget>
+       </item>
        <item>
         <widget class="QListWidget" name="listWidget">
          <property name="dragDropMode">
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 04dd71ced..c14a61dd9 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -59,8 +59,9 @@ const quint8 VToolSeamAllowance::pieceVersion = 2;
 const QString VToolSeamAllowance::TagNodes    = QStringLiteral("nodes");
 const QString VToolSeamAllowance::TagNode     = QStringLiteral("node");
 
-const QString VToolSeamAllowance::AttrVersion     = QStringLiteral("version");
-const QString VToolSeamAllowance::AttrNodeReverse = QStringLiteral("reverse");
+const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
+const QString VToolSeamAllowance::AttrNodeReverse    = QStringLiteral("reverse");
+const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 
 const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
 const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
@@ -252,6 +253,7 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
     doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
     doc->SetAttribute(domElement, AttrInLayout, piece.IsInLayout());
+    doc->SetAttribute(domElement, AttrForbidFlipping, static_cast<quint8>(piece.IsForbidFlipping()));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 5a3f6d4e9..d5dbba2bd 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -59,6 +59,7 @@ public:
 
     static const QString AttrVersion;
     static const QString AttrNodeReverse;
+    static const QString AttrForbidFlipping;
 
     static const QString NodeArc;
     static const QString NodePoint;

From de6015de4db81376220f4954690975aff61c9f64 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 12:51:06 +0200
Subject: [PATCH 039/208] Method GetParametrBool() should allow convert strings
 "1" and "0" to boolean.

--HG--
branch : feature
---
 src/libs/ifc/xml/vdomdocument.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp
index d2499b4fd..ff6952b0f 100644
--- a/src/libs/ifc/xml/vdomdocument.cpp
+++ b/src/libs/ifc/xml/vdomdocument.cpp
@@ -246,7 +246,10 @@ bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString
     {
         parametr = GetParametrString(domElement, name, defValue);
 
-        QStringList bools = QStringList() << QLatin1String("true") << QLatin1String("false");
+        const QStringList bools = QStringList() << QLatin1String("true")
+                                                << QLatin1String("false")
+                                                << QLatin1String("1")
+                                                << QLatin1String("0");
         switch (bools.indexOf(parametr))
         {
             case 0: // true
@@ -255,6 +258,12 @@ bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString
             case 1: // false
                 val = false;
                 break;
+            case 2: // 1
+                val = true;
+                break;
+            case 3: // 0
+                val = false;
+                break;
             default:// others
                 throw VExceptionConversionError(message, name);
                 break;

From a5fc19d7ec978bb8a6b68ba977189ab1dbfa3f64 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 12:53:02 +0200
Subject: [PATCH 040/208] Returned storing and reading base seam allowance
 values: width and enable/disable.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |   7 +-
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |   4 +-
 src/libs/ifc/xml/vpatternconverter.cpp        |   4 +-
 src/libs/vlayout/vabstractpiece.cpp           |  24 ++++
 src/libs/vlayout/vabstractpiece.h             |   6 +
 src/libs/vlayout/vabstractpiece_p.h           |  10 +-
 .../dialogs/tools/dialogseamallowance.cpp     |  19 ++++
 .../dialogs/tools/dialogseamallowance.h       |   1 +
 .../dialogs/tools/dialogseamallowance.ui      | 107 +++++++++++++++++-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |   6 +-
 src/libs/vtools/tools/vtoolseamallowance.h    |   2 +
 11 files changed, 180 insertions(+), 10 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 0e6c2852c..84166e993 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -618,10 +618,9 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetName(GetParametrString(domElement, AttrName, tr("Detail")));
         detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
         detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
-//        detail.setSeamAllowance(GetParametrUInt(domElement, VToolDetail::AttrSupplement, "1"));
-//        detail.setWidth(GetParametrDouble(domElement, VToolDetail::AttrWidth, "10.0"));
-//        detail.setClosed(GetParametrUInt(domElement, VToolDetail::AttrClosed, "1"));
-        detail.SetForbidFlipping(GetParametrUInt(domElement, VToolSeamAllowance::AttrForbidFlipping,
+        detail.SetSeamAllowance(GetParametrBool(domElement, VToolSeamAllowance::AttrSeamAllowance, falseStr));
+        detail.SetSAWidth(GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0.0"));
+        detail.SetForbidFlipping(GetParametrBool(domElement, VToolSeamAllowance::AttrForbidFlipping,
                                            QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
 
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index bad75d2e5..ac4a4907c 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -414,7 +414,9 @@
                                                                            <xs:attribute name="my" type="xs:double"></xs:attribute>
                                                                            <xs:attribute name="name" type="xs:string"></xs:attribute>
                                                                            <xs:attribute name="inLayout" type="xs:boolean"></xs:attribute>
-                                                                           <xs:attribute name="forbidFlipping" type="xs:unsignedInt"></xs:attribute>
+                                                                           <xs:attribute name="forbidFlipping" type="xs:boolean"></xs:attribute>
+                                                                           <xs:attribute name="width" type="xs:double"></xs:attribute>
+                                                                           <xs:attribute name="seamAllowance" type="xs:boolean"></xs:attribute>
                                                                      </xs:complexType>
                                                                </xs:element>
                                                          </xs:sequence>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index 95cfab0b3..11bc090fd 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -129,6 +129,7 @@ const QString strMx                        = QStringLiteral("mx");
 const QString strMy                        = QStringLiteral("my");
 const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
 const QString strInLayout                  = QStringLiteral("inLayout");
+const QString strSeamAllowance             = QStringLiteral("seamAllowance");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)
@@ -1694,9 +1695,10 @@ void VPatternConverter::TagDetailToV0_4_0()
 
         if (not dom.isNull())
         {
+            dom.setAttribute(strSeamAllowance, dom.attribute(strSupplement, "0"));
             dom.removeAttribute(strSupplement);
+
             dom.removeAttribute(strClosed);
-            dom.removeAttribute(strWidth);
 
             dom.setAttribute(strVersion, "1");
 
diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 18c90e178..003235c5b 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -85,6 +85,30 @@ void VAbstractPiece::SetForbidFlipping(bool value)
     d->m_forbidFlipping = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPiece::IsSeamAllowance() const
+{
+    return d->m_seamAllowance;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractPiece::SetSeamAllowance(bool value)
+{
+    d->m_seamAllowance = value;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VAbstractPiece::GetSAWidth() const
+{
+    return d->m_width;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractPiece::SetSAWidth(qreal value)
+{
+    value >= 0 ? d->m_width = value : d->m_width = 0;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 9bc90aac1..fdf6908c3 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -50,6 +50,12 @@ public:
     bool IsForbidFlipping() const;
     void SetForbidFlipping(bool value);
 
+    bool IsSeamAllowance() const;
+    void SetSeamAllowance(bool value);
+
+    qreal GetSAWidth() const;
+    void  SetSAWidth(qreal value);
+
     static qreal            SumTrapezoids(const QVector<QPointF> &points);
     static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
     static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
diff --git a/src/libs/vlayout/vabstractpiece_p.h b/src/libs/vlayout/vabstractpiece_p.h
index 831969199..745cdca56 100644
--- a/src/libs/vlayout/vabstractpiece_p.h
+++ b/src/libs/vlayout/vabstractpiece_p.h
@@ -42,13 +42,17 @@ class VAbstractPieceData : public QSharedData
 public:
     VAbstractPieceData()
         : m_name(),
-          m_forbidFlipping(false)
+          m_forbidFlipping(false),
+          m_seamAllowance(false),
+          m_width(0)
     {}
 
     VAbstractPieceData(const VAbstractPieceData &piece)
         : QSharedData(piece),
           m_name(piece.m_name),
-          m_forbidFlipping(piece.m_forbidFlipping)
+          m_forbidFlipping(piece.m_forbidFlipping),
+          m_seamAllowance(piece.m_seamAllowance),
+          m_width(piece.m_width)
     {}
 
     ~VAbstractPieceData();
@@ -56,6 +60,8 @@ public:
     QString m_name;
     /** @brief forbidFlipping forbid piece be mirrored in a layout. */
     bool    m_forbidFlipping;
+    bool    m_seamAllowance;
+    qreal   m_width;
 
 private:
     VAbstractPieceData &operator=(const VAbstractPieceData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index e80cceb72..b8c42a614 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -51,10 +51,19 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     CheckState();
 
     ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
+    ui->labelUnit->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+
+    if(qApp->patternUnit() == Unit::Inch)
+    {
+        ui->doubleSpinBoxSeams->setDecimals(5);
+    }
+    // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
+    ui->doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
 
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
+    connect(ui->checkBoxSeams, &QCheckBox::clicked, this, &DialogSeamAllowance::EnableSeamAllowance);
 
     if (not applyAllowed)
     {
@@ -94,6 +103,9 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
     }
 
     ui->checkBoxForbidFlipping->setChecked(m_piece.IsForbidFlipping());
+    ui->doubleSpinBoxSeams->setValue(m_piece.GetSAWidth());
+
+    EnableSeamAllowance(m_piece.IsSeamAllowance());
 
     ValidObjects(MainPathIsValid());
 }
@@ -254,6 +266,12 @@ void DialogSeamAllowance::ListChanged()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EnableSeamAllowance(bool enable)
+{
+    ui->groupBoxAutomatic->setEnabled(enable);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::CreatePiece() const
 {
@@ -265,6 +283,7 @@ VPiece DialogSeamAllowance::CreatePiece() const
     }
 
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
+    piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
 
     return piece;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 5657147a5..220894323 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -62,6 +62,7 @@ protected:
 private slots:
     void ShowContextMenu(const QPoint &pos);
     void ListChanged();
+    void EnableSeamAllowance(bool enable);
 
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index dcf3c2ed6..770b89f1d 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -94,6 +94,111 @@
       <attribute name="title">
        <string>Seam allowance</string>
       </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QCheckBox" name="checkBoxSeams">
+         <property name="text">
+          <string>Seam allowance</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBoxAutomatic">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="title">
+          <string>Automatic</string>
+         </property>
+         <property name="checkable">
+          <bool>false</bool>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <item>
+             <widget class="QLabel" name="labelEditWidth">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="locale">
+               <locale language="English" country="UnitedStates"/>
+              </property>
+              <property name="text">
+               <string>Width:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QDoubleSpinBox" name="doubleSpinBoxSeams">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximum">
+               <double>900.990000000000009</double>
+              </property>
+              <property name="singleStep">
+               <double>0.100000000000000</double>
+              </property>
+              <property name="value">
+               <double>1.000000000000000</double>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="labelUnit">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>cm</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <spacer name="verticalSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>219</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
      </widget>
     </widget>
    </item>
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index c14a61dd9..e92a573a8 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -62,6 +62,8 @@ const QString VToolSeamAllowance::TagNode     = QStringLiteral("node");
 const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
 const QString VToolSeamAllowance::AttrNodeReverse    = QStringLiteral("reverse");
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
+const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
+const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
 
 const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
 const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
@@ -253,7 +255,9 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(piece.GetMx()));
     doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(piece.GetMy()));
     doc->SetAttribute(domElement, AttrInLayout, piece.IsInLayout());
-    doc->SetAttribute(domElement, AttrForbidFlipping, static_cast<quint8>(piece.IsForbidFlipping()));
+    doc->SetAttribute(domElement, AttrForbidFlipping, piece.IsForbidFlipping());
+    doc->SetAttribute(domElement, AttrSeamAllowance, piece.IsSeamAllowance());
+    doc->SetAttribute(domElement, AttrWidth, piece.GetSAWidth());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index d5dbba2bd..cbb9eaec3 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -60,6 +60,8 @@ public:
     static const QString AttrVersion;
     static const QString AttrNodeReverse;
     static const QString AttrForbidFlipping;
+    static const QString AttrSeamAllowance;
+    static const QString AttrWidth;
 
     static const QString NodeArc;
     static const QString NodePoint;

From f992bb7bbdf5fcecff1d79dcf36d7df176d4695a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 14:06:09 +0200
Subject: [PATCH 041/208] Returned visualization of base seam allowance.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp          | 185 +++++++++++++++++++
 src/libs/vlayout/vabstractpiece.h            |   7 +
 src/libs/vpatterndb/vpiece.cpp               |  68 +++++++
 src/libs/vpatterndb/vpiece.h                 |   2 +
 src/libs/vtools/tools/vtoolseamallowance.cpp |  15 +-
 src/libs/vtools/tools/vtoolseamallowance.h   |   2 +
 6 files changed, 278 insertions(+), 1 deletion(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 003235c5b..4577f191b 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -109,6 +109,54 @@ void VAbstractPiece::SetSAWidth(qreal value)
     value >= 0 ? d->m_width = value : d->m_width = 0;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::Equidistant(const QVector<QPointF> &points, qreal width)
+{
+    QVector<QPointF> ekvPoints;
+
+    if (width <= 0)
+    {
+        qDebug()<<"Width <= 0.";
+        return QVector<QPointF>();
+    }
+
+    QVector<QPointF> p = CorrectEquidistantPoints(points);
+    if ( p.size() < 3 )
+    {
+        qDebug()<<"Not enough points for building the equidistant.";
+        return QVector<QPointF>();
+    }
+
+    if (p.last().toPoint() != p.first().toPoint())
+    {
+        p.append(p.at(0));// Should be always closed
+    }
+
+    for (qint32 i = 0; i < p.size(); ++i )
+    {
+        if ( i == 0)
+        {//first point
+            ekvPoints << EkvPoint(QLineF(p.at(p.size()-2), p.at(p.size()-1)), QLineF(p.at(1), p.at(0)), width);
+            continue;
+        }
+
+        if (i == p.size()-1)
+        {//last point
+            if (not ekvPoints.isEmpty())
+            {
+                ekvPoints.append(ekvPoints.at(0));
+            }
+            continue;
+        }
+        //points in the middle of polyline
+        ekvPoints << EkvPoint(QLineF(p.at(i-1), p.at(i)), QLineF(p.at(i+1), p.at(i)), width);
+    }
+
+    const bool removeFirstAndLast = false;
+    ekvPoints = CheckLoops(CorrectEquidistantPoints(ekvPoints, removeFirstAndLast));//Result path can contain loops
+    return ekvPoints;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
 {
@@ -349,3 +397,140 @@ QVector<QPointF> VAbstractPiece::RemoveDublicates(const QVector<QPointF> &points
 
     return p;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
+ * @param line1 first line.
+ * @param line2 second line.
+ * @param width width of equidistant.
+ * @return vector of points.
+ */
+QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &line2, qreal width)
+{
+    if (width <= 0)
+    {
+        return QVector<QPointF>();
+    }
+
+    QVector<QPointF> points;
+    if (line1.p2() != line2.p2())
+    {
+        qDebug()<<"Last points of two lines must be equal.";
+        return QVector<QPointF>();
+    }
+
+    QPointF CrosPoint;
+    const QLineF bigLine1 = ParallelLine(line1, width );
+    const QLineF bigLine2 = ParallelLine(QLineF(line2.p2(), line2.p1()), width );
+    QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint );
+    switch (type)
+    {
+        case (QLineF::BoundedIntersection):
+            points.append(CrosPoint);
+            return points;
+            break;
+        case (QLineF::UnboundedIntersection):
+        {
+            QLineF line( line1.p2(), CrosPoint );
+
+            const int angle1 = BisectorAngle(line1.p1(), line1.p2(), line2.p1());
+            const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
+
+            if (angle1 == angle2)
+            {//Regular equdistant case
+                const qreal length = line.length();
+                if (length > width*2.4)
+                { // Cutting too long a cut angle
+                    line.setLength(width); // Not sure about width value here
+                    QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular
+                    cutLine.setLength(length); // Decided take this length
+
+                    // We do not check intersection type because intersection must alwayse exist
+                    QPointF px;
+                    cutLine.setAngle(cutLine.angle()+90);
+                    QLineF::IntersectType type = bigLine1.intersect( cutLine, &px );
+                    if (type == QLineF::NoIntersection)
+                    {
+                        qDebug()<<"Couldn't find intersection with cut line.";
+                    }
+                    points.append(px);
+
+                    cutLine.setAngle(cutLine.angle()-180);
+                    type = bigLine2.intersect( cutLine, &px );
+                    if (type == QLineF::NoIntersection)
+                    {
+                        qDebug()<<"Couldn't find intersection with cut line.";
+                    }
+                    points.append(px);
+                }
+                else
+                {
+                    points.append(CrosPoint);
+                    return points;
+                }
+            }
+            else
+            {// Dart. Ignore if going outside of equdistant
+                const QLineF bigEdge = ParallelLine(QLineF(line1.p1(), line2.p1()), width );
+                QPointF px;
+                const QLineF::IntersectType type = bigEdge.intersect(line, &px);
+                if (type != QLineF::BoundedIntersection)
+                {
+                    points.append(CrosPoint);
+                    return points;
+                }
+            }
+            break;
+        }
+        case (QLineF::NoIntersection):
+            /*If we have correct lines this means lines lie on a line.*/
+            points.append(bigLine1.p2());
+            return points;
+            break;
+        default:
+            break;
+    }
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QLineF VAbstractPiece::ParallelLine(const QLineF &line, qreal width)
+{
+    const QLineF paralel = QLineF(SingleParallelPoint(line, 90, width),
+                                  SingleParallelPoint(QLineF(line.p2(), line.p1()), -90, width));
+    return paralel;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPointF VAbstractPiece::SingleParallelPoint(const QLineF &line, qreal angle, qreal width)
+{
+    QLineF pLine = line;
+    pLine.setAngle( pLine.angle() + angle );
+    pLine.setLength( width );
+    return pLine.p2();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int VAbstractPiece::BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3)
+{
+    QLineF line1(p2, p1);
+    QLineF line2(p2, p3);
+    QLineF bLine;
+
+    const qreal angle1 = line1.angleTo(line2);
+    const qreal angle2 = line2.angleTo(line1);
+
+    if (angle1 <= angle2)
+    {
+        bLine = line1;
+        bLine.setAngle(bLine.angle() + angle1/2.0);
+    }
+    else
+    {
+        bLine = line2;
+        bLine.setAngle(bLine.angle() + angle2/2.0);
+    }
+
+    return qRound(bLine.angle());
+}
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index fdf6908c3..230db9539 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -35,6 +35,7 @@
 template <class T> class QVector;
 class QPointF;
 class VAbstractPieceData;
+class QLineF;
 
 class VAbstractPiece
 {
@@ -56,6 +57,7 @@ public:
     qreal GetSAWidth() const;
     void  SetSAWidth(qreal value);
 
+    static QVector<QPointF> Equidistant(const QVector<QPointF> &points, qreal width);
     static qreal            SumTrapezoids(const QVector<QPointF> &points);
     static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
     static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
@@ -65,6 +67,11 @@ protected:
 
 private:
     QSharedDataPointer<VAbstractPieceData> d;
+
+    static QVector<QPointF> EkvPoint(const QLineF &line1, const QLineF &line2, qreal width);
+    static QLineF           ParallelLine(const QLineF &line, qreal width);
+    static QPointF          SingleParallelPoint(const QLineF &line, qreal angle, qreal width);
+    static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
 };
 
 #endif // VABSTRACTPIECE_H
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 5f25e37cb..da0183809 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -200,6 +200,50 @@ QVector<QPointF> VPiece::MainPathNodePoints(const VContainer *data) const
     return points;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
+{
+    SCASSERT(data != nullptr);
+
+    QVector<QPointF> pointsEkv;
+    if (not IsSeamAllowance())
+    {
+        return pointsEkv;
+    }
+
+    for (int i = 0; i< CountNodes(); ++i)
+    {
+        switch (at(i).GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
+                pointsEkv.append(*point);
+            }
+            break;
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+                const QPointF begin = StartSegment(data, i, at(i).GetReverse());
+                const QPointF end = EndSegment(data, i, at(i).GetReverse());
+
+                pointsEkv << curve->GetSegmentPoints(begin, end, at(i).GetReverse());
+            }
+            break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).GetTypeTool());
+                break;
+        }
+    }
+
+    pointsEkv = CheckLoops(CorrectEquidistantPoints(pointsEkv));//A path can contains loops
+    pointsEkv = Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit()));
+    return pointsEkv;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPainterPath VPiece::MainPathPath(const VContainer *data) const
 {
@@ -220,6 +264,30 @@ QPainterPath VPiece::MainPathPath(const VContainer *data) const
     return path;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QPainterPath VPiece::SeamAllowancePath(const VContainer *data) const
+{
+    const QVector<QPointF> pointsEkv = SeamAllowancePoints(data);
+    QPainterPath ekv;
+
+    // seam allowence
+    if (IsSeamAllowance())
+    {
+        if (not pointsEkv.isEmpty())
+        {
+            ekv.moveTo(pointsEkv.at(0));
+            for (qint32 i = 1; i < pointsEkv.count(); ++i)
+            {
+                ekv.lineTo(pointsEkv.at(i));
+            }
+
+            ekv.setFillRule(Qt::WindingFill);
+        }
+    }
+
+    return ekv;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VPiece::GetMx() const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 31e82d401..ad5834580 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -62,8 +62,10 @@ public:
 
     QVector<QPointF> MainPathPoints(const VContainer *data) const;
     QVector<QPointF> MainPathNodePoints(const VContainer *data) const;
+    QVector<QPointF> SeamAllowancePoints(const VContainer *data) const;
 
     QPainterPath MainPathPath(const VContainer *data) const;
+    QPainterPath SeamAllowancePath(const VContainer *data) const;
 
     qreal GetMx() const;
     void  SetMx(qreal value);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index e92a573a8..af6b06943 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -607,7 +607,8 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
       VNoBrushScalePathItem(parent),
       m_dialog(),
       m_sceneDetails(scene),
-      m_drawName(drawName)
+      m_drawName(drawName),
+      m_seamAllowance(new VNoBrushScalePathItem(this))
 {
     VPiece detail = data->GetPiece(id);
     for (int i = 0; i< detail.CountNodes(); ++i)
@@ -639,6 +640,7 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
     RefreshGeometry();
 
     this->setBrush(QBrush(Qt::Dense7Pattern));
+    m_seamAllowance->setBrush(QBrush(Qt::FDiagPattern));
 
     this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
     this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
@@ -670,6 +672,17 @@ void VToolSeamAllowance::RefreshGeometry()
     this->setPath(mainPath);
     this->setPos(detail.GetMx(), detail.GetMy());
 
+    if (detail.IsSeamAllowance())
+    {
+        mainPath.addPath(detail.SeamAllowancePath(this->getData()));
+        mainPath.setFillRule(Qt::OddEvenFill);
+        m_seamAllowance->setPath(mainPath);
+    }
+    else
+    {
+        m_seamAllowance->setPath(QPainterPath());
+    }
+
     this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
 }
 
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index cbb9eaec3..dd65595ee 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -115,6 +115,8 @@ private:
     VMainGraphicsScene *m_sceneDetails;
     QString             m_drawName;
 
+    VNoBrushScalePathItem *m_seamAllowance;
+
     void SetDialog();
 
     template<typename T>

From 49208a640d346eb34f5645aff76715c1e3819a4e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 10 Nov 2016 14:15:43 +0200
Subject: [PATCH 042/208] Fix few bugs with apllying changes for seam
 allowance.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 6 +++---
 src/libs/vtools/dialogs/tools/dialogseamallowance.ui  | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index b8c42a614..f721b81af 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -63,7 +63,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
-    connect(ui->checkBoxSeams, &QCheckBox::clicked, this, &DialogSeamAllowance::EnableSeamAllowance);
+    connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
 
     if (not applyAllowed)
     {
@@ -104,8 +104,7 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
 
     ui->checkBoxForbidFlipping->setChecked(m_piece.IsForbidFlipping());
     ui->doubleSpinBoxSeams->setValue(m_piece.GetSAWidth());
-
-    EnableSeamAllowance(m_piece.IsSeamAllowance());
+    ui->checkBoxSeams->setChecked(m_piece.IsSeamAllowance());
 
     ValidObjects(MainPathIsValid());
 }
@@ -283,6 +282,7 @@ VPiece DialogSeamAllowance::CreatePiece() const
     }
 
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
+    piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
     piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
 
     return piece;
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 770b89f1d..389f40739 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -101,7 +101,7 @@
           <string>Seam allowance</string>
          </property>
          <property name="checked">
-          <bool>true</bool>
+          <bool>false</bool>
          </property>
         </widget>
        </item>

From b84b9cf38776f0f2ae13d0798c2050fea8fc1212 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 12:54:17 +0200
Subject: [PATCH 043/208] New class VSAPoint;

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.h | 70 ++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 230db9539..0702bc8f4 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -31,12 +31,80 @@
 
 #include <QtGlobal>
 #include <QSharedDataPointer>
+#include <QPointF>
+
+#include "../vmisc/diagnostic.h"
 
 template <class T> class QVector;
-class QPointF;
+
 class VAbstractPieceData;
 class QLineF;
 
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+
+/**
+ * @brief The VSAPoint class seam allowance point
+ */
+class VSAPoint : public QPointF
+{
+public:
+    Q_DECL_CONSTEXPR VSAPoint();
+    Q_DECL_CONSTEXPR VSAPoint(const QPointF &p);
+
+    Q_DECL_CONSTEXPR qreal GetSABefore() const;
+                     void  SetSABefore(qreal value);
+
+    Q_DECL_CONSTEXPR qreal GetSAAfter() const;
+                     void  SetSAAfter(qreal value);
+
+private:
+    qreal m_before;
+    qreal m_after;
+};
+
+Q_DECLARE_TYPEINFO(VSAPoint, Q_MOVABLE_TYPE);
+
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint()
+    : QPointF(),
+      m_before(-1),
+      m_after(-1)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint(const QPointF &p)
+    : QPointF(p),
+      m_before(-1),
+      m_after(-1)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline qreal VSAPoint::GetSABefore() const
+{
+    return m_before;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline void VSAPoint::SetSABefore(qreal value)
+{
+    value < 0 ? m_before = -1 : m_before = value;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline qreal VSAPoint::GetSAAfter() const
+{
+    return m_after;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline void VSAPoint::SetSAAfter(qreal value)
+{
+    value < 0 ? m_after = -1 : m_after = value;
+}
+
+QT_WARNING_POP
+
 class VAbstractPiece
 {
 public:

From 703c2d589b55557cce577e5475b6405b55fb46a3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 16:26:00 +0200
Subject: [PATCH 044/208] Refactoring, prepare to use VSAPoint class.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 33 +++++++++++++++--------------
 src/libs/vlayout/vabstractpiece.h   |  7 +++---
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 4577f191b..897d97976 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -136,7 +136,8 @@ QVector<QPointF> VAbstractPiece::Equidistant(const QVector<QPointF> &points, qre
     {
         if ( i == 0)
         {//first point
-            ekvPoints << EkvPoint(QLineF(p.at(p.size()-2), p.at(p.size()-1)), QLineF(p.at(1), p.at(0)), width);
+            ekvPoints << EkvPoint(p.at(p.size()-2), p.at(p.size()-1),
+                                  p.at(1), p.at(0), width);
             continue;
         }
 
@@ -149,7 +150,8 @@ QVector<QPointF> VAbstractPiece::Equidistant(const QVector<QPointF> &points, qre
             continue;
         }
         //points in the middle of polyline
-        ekvPoints << EkvPoint(QLineF(p.at(i-1), p.at(i)), QLineF(p.at(i+1), p.at(i)), width);
+        ekvPoints << EkvPoint(p.at(i-1), p.at(i),
+                              p.at(i+1), p.at(i), width);
     }
 
     const bool removeFirstAndLast = false;
@@ -401,12 +403,11 @@ QVector<QPointF> VAbstractPiece::RemoveDublicates(const QVector<QPointF> &points
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
- * @param line1 first line.
- * @param line2 second line.
  * @param width width of equidistant.
  * @return vector of points.
  */
-QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &line2, qreal width)
+QVector<QPointF> VAbstractPiece::EkvPoint(const QPointF &p1Line1, const QPointF &p2Line1,
+                                          const QPointF &p1Line2, const QPointF &p2Line2, qreal width)
 {
     if (width <= 0)
     {
@@ -414,15 +415,15 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &lin
     }
 
     QVector<QPointF> points;
-    if (line1.p2() != line2.p2())
+    if (p2Line1 != p2Line2)
     {
         qDebug()<<"Last points of two lines must be equal.";
         return QVector<QPointF>();
     }
 
     QPointF CrosPoint;
-    const QLineF bigLine1 = ParallelLine(line1, width );
-    const QLineF bigLine2 = ParallelLine(QLineF(line2.p2(), line2.p1()), width );
+    const QLineF bigLine1 = ParallelLine(p1Line1, p2Line1, width );
+    const QLineF bigLine2 = ParallelLine(p2Line2, p1Line2, width );
     QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint );
     switch (type)
     {
@@ -432,9 +433,9 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &lin
             break;
         case (QLineF::UnboundedIntersection):
         {
-            QLineF line( line1.p2(), CrosPoint );
+            QLineF line( p2Line1, CrosPoint );
 
-            const int angle1 = BisectorAngle(line1.p1(), line1.p2(), line2.p1());
+            const int angle1 = BisectorAngle(p1Line1, p2Line1, p1Line2);
             const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
 
             if (angle1 == angle2)
@@ -472,7 +473,7 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &lin
             }
             else
             {// Dart. Ignore if going outside of equdistant
-                const QLineF bigEdge = ParallelLine(QLineF(line1.p1(), line2.p1()), width );
+                const QLineF bigEdge = ParallelLine(p1Line1, p1Line2, width );
                 QPointF px;
                 const QLineF::IntersectType type = bigEdge.intersect(line, &px);
                 if (type != QLineF::BoundedIntersection)
@@ -495,17 +496,17 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const QLineF &line1, const QLineF &lin
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QLineF VAbstractPiece::ParallelLine(const QLineF &line, qreal width)
+QLineF VAbstractPiece::ParallelLine(const QPointF &p1, const QPointF &p2, qreal width)
 {
-    const QLineF paralel = QLineF(SingleParallelPoint(line, 90, width),
-                                  SingleParallelPoint(QLineF(line.p2(), line.p1()), -90, width));
+    const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, width),
+                                  SingleParallelPoint(p2, p1, -90, width));
     return paralel;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPointF VAbstractPiece::SingleParallelPoint(const QLineF &line, qreal angle, qreal width)
+QPointF VAbstractPiece::SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width)
 {
-    QLineF pLine = line;
+    QLineF pLine(p1, p2);
     pLine.setAngle( pLine.angle() + angle );
     pLine.setLength( width );
     return pLine.p2();
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 0702bc8f4..fc473c8d5 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -136,9 +136,10 @@ protected:
 private:
     QSharedDataPointer<VAbstractPieceData> d;
 
-    static QVector<QPointF> EkvPoint(const QLineF &line1, const QLineF &line2, qreal width);
-    static QLineF           ParallelLine(const QLineF &line, qreal width);
-    static QPointF          SingleParallelPoint(const QLineF &line, qreal angle, qreal width);
+    static QVector<QPointF> EkvPoint(const QPointF &p1Line1, const QPointF &p2Line1,
+                                     const QPointF &p1Line2, const QPointF &p2Line2, qreal width);
+    static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
+    static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);
     static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
 };
 

From faad0419cf554d03d29445a883119aa67c466c4d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 17:55:02 +0200
Subject: [PATCH 045/208] Using class VSAPoint for drawing base seam allowance.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 96 +++--------------------------
 src/libs/vlayout/vabstractpiece.h   | 93 ++++++++++++++++++++++++++--
 src/libs/vpatterndb/vpiece.cpp      | 32 ++++++----
 src/libs/vpatterndb/vpiece.h        |  4 ++
 4 files changed, 121 insertions(+), 104 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 897d97976..c0d052653 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -32,9 +32,6 @@
 #include <QLineF>
 #include <QSet>
 #include <QVector>
-#include <QDebug>
-
-#include "../vgeometry/vgobject.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPiece::VAbstractPiece()
@@ -110,17 +107,15 @@ void VAbstractPiece::SetSAWidth(qreal value)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VAbstractPiece::Equidistant(const QVector<QPointF> &points, qreal width)
+QVector<QPointF> VAbstractPiece::Equidistant(const QVector<VSAPoint> &points, qreal width)
 {
-    QVector<QPointF> ekvPoints;
-
-    if (width <= 0)
+    if (width < 0)
     {
-        qDebug()<<"Width <= 0.";
+        qDebug()<<"Width < 0.";
         return QVector<QPointF>();
     }
 
-    QVector<QPointF> p = CorrectEquidistantPoints(points);
+    QVector<VSAPoint> p = CorrectEquidistantPoints(points);
     if ( p.size() < 3 )
     {
         qDebug()<<"Not enough points for building the equidistant.";
@@ -132,6 +127,7 @@ QVector<QPointF> VAbstractPiece::Equidistant(const QVector<QPointF> &points, qre
         p.append(p.at(0));// Should be always closed
     }
 
+    QVector<QPointF> ekvPoints;
     for (qint32 i = 0; i < p.size(); ++i )
     {
         if ( i == 0)
@@ -326,90 +322,16 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
     return ekvPoints;
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
- * @param points list of points equdistant.
- * @return corrected list.
- */
-QVector<QPointF> VAbstractPiece::CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast)
-{
-    if (points.size()<4)//Better don't check if only three points. We can destroy equidistant.
-    {
-        qDebug()<<"Only three points.";
-        return points;
-    }
-
-    //Clear equivalent points
-    QVector<QPointF> correctPoints = RemoveDublicates(points, removeFirstAndLast);
-
-    if (correctPoints.size()<3)
-    {
-        return correctPoints;
-    }
-
-    //Remove point on line
-    for (qint32 i = 1; i <correctPoints.size()-1; ++i)
-    {// In this case we alwayse will have bounded intersection, so all is need is to check if point i is on line.
-     // Unfortunatelly QLineF::intersect can't be used in this case because of the floating-point accuraccy problem.
-        if (VGObject::IsPointOnLineviaPDP(correctPoints.at(i), correctPoints.at(i-1), correctPoints.at(i+1)))
-        {
-            correctPoints.remove(i);
-        }
-    }
-
-    return correctPoints;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VAbstractPiece::RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast)
-{
-    QVector<QPointF> p = points;
-
-    if (removeFirstAndLast)
-    {
-        if (not p.isEmpty() && p.size() > 1)
-        {
-            // Path can't be closed
-            if (p.first() == p.last())
-            {
-            #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-                p.remove(p.size() - 1);
-            #else
-                p.removeLast();
-            #endif
-            }
-        }
-    }
-
-    for (int i = 0; i < p.size()-1; ++i)
-    {
-        if (p.at(i) == p.at(i+1))
-        {
-            if (not removeFirstAndLast && (i == p.size()-1))
-            {
-                continue;
-            }
-
-            p.erase(p.begin() + i + 1);
-            --i;
-            continue;
-        }
-    }
-
-    return p;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
  * @param width width of equidistant.
  * @return vector of points.
  */
-QVector<QPointF> VAbstractPiece::EkvPoint(const QPointF &p1Line1, const QPointF &p2Line1,
-                                          const QPointF &p1Line2, const QPointF &p2Line2, qreal width)
+QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,
+                                          const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width)
 {
-    if (width <= 0)
+    if (width < 0)
     {
         return QVector<QPointF>();
     }
@@ -496,7 +418,7 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const QPointF &p1Line1, const QPointF
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QLineF VAbstractPiece::ParallelLine(const QPointF &p1, const QPointF &p2, qreal width)
+QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
     const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, width),
                                   SingleParallelPoint(p2, p1, -90, width));
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index fc473c8d5..579f46965 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -32,8 +32,10 @@
 #include <QtGlobal>
 #include <QSharedDataPointer>
 #include <QPointF>
+#include <QDebug>
 
 #include "../vmisc/diagnostic.h"
+#include "../vgeometry/vgobject.h"
 
 template <class T> class QVector;
 
@@ -125,22 +127,101 @@ public:
     qreal GetSAWidth() const;
     void  SetSAWidth(qreal value);
 
-    static QVector<QPointF> Equidistant(const QVector<QPointF> &points, qreal width);
+    static QVector<QPointF> Equidistant(const QVector<VSAPoint> &points, qreal width);
     static qreal            SumTrapezoids(const QVector<QPointF> &points);
     static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
-    static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
+
+    template <class T>
+    static QVector<T> CorrectEquidistantPoints(const QVector<T> &points, bool removeFirstAndLast = true);
 
 protected:
-    static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast = true);
+    template <class T>
+    static QVector<T> RemoveDublicates(const QVector<T> &points, bool removeFirstAndLast = true);
 
 private:
     QSharedDataPointer<VAbstractPieceData> d;
 
-    static QVector<QPointF> EkvPoint(const QPointF &p1Line1, const QPointF &p2Line1,
-                                     const QPointF &p1Line2, const QPointF &p2Line2, qreal width);
-    static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
+    static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,
+                                     const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width);
+    static QLineF           ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
     static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);
     static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
 };
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
+ * @param points list of points equdistant.
+ * @return corrected list.
+ */
+template <class T>
+QVector<T> VAbstractPiece::CorrectEquidistantPoints(const QVector<T> &points, bool removeFirstAndLast)
+{
+    if (points.size()<4)//Better don't check if only three points. We can destroy equidistant.
+    {
+        qDebug()<<"Only three points.";
+        return points;
+    }
+
+    //Clear equivalent points
+    QVector<T> correctPoints = RemoveDublicates(points, removeFirstAndLast);
+
+    if (correctPoints.size()<3)
+    {
+        return correctPoints;
+    }
+
+    //Remove point on line
+    for (qint32 i = 1; i <correctPoints.size()-1; ++i)
+    {// In this case we alwayse will have bounded intersection, so all is need is to check if point i is on line.
+     // Unfortunatelly QLineF::intersect can't be used in this case because of the floating-point accuraccy problem.
+        if (VGObject::IsPointOnLineviaPDP(correctPoints.at(i), correctPoints.at(i-1), correctPoints.at(i+1)))
+        {
+            correctPoints.remove(i);
+        }
+    }
+
+    return correctPoints;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+template <class T>
+QVector<T> VAbstractPiece::RemoveDublicates(const QVector<T> &points, bool removeFirstAndLast)
+{
+    QVector<T> p = points;
+
+    if (removeFirstAndLast)
+    {
+        if (not p.isEmpty() && p.size() > 1)
+        {
+            // Path can't be closed
+            if (p.first() == p.last())
+            {
+            #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+                p.remove(p.size() - 1);
+            #else
+                p.removeLast();
+            #endif
+            }
+        }
+    }
+
+    for (int i = 0; i < p.size()-1; ++i)
+    {
+        if (p.at(i) == p.at(i+1))
+        {
+            if (not removeFirstAndLast && (i == p.size()-1))
+            {
+                continue;
+            }
+
+            p.erase(p.begin() + i + 1);
+            --i;
+            continue;
+        }
+    }
+
+    return p;
+}
+
 #endif // VABSTRACTPIECE_H
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index da0183809..57c52d277 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -205,12 +205,13 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
 {
     SCASSERT(data != nullptr);
 
-    QVector<QPointF> pointsEkv;
+
     if (not IsSeamAllowance())
     {
-        return pointsEkv;
+        return QVector<QPointF>();
     }
 
+    QVector<VSAPoint> pointsEkv;
     for (int i = 0; i< CountNodes(); ++i)
     {
         switch (at(i).GetTypeTool())
@@ -218,7 +219,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
             case (Tool::NodePoint):
             {
                 const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
-                pointsEkv.append(*point);
+                pointsEkv.append(VSAPoint(point->toQPointF()));
             }
             break;
             case (Tool::NodeArc):
@@ -226,11 +227,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
             case (Tool::NodeSplinePath):
             {
                 const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
-
-                const QPointF begin = StartSegment(data, i, at(i).GetReverse());
-                const QPointF end = EndSegment(data, i, at(i).GetReverse());
-
-                pointsEkv << curve->GetSegmentPoints(begin, end, at(i).GetReverse());
+                CurveSeamAllowanceSegment(pointsEkv, data, curve, i, at(i).GetReverse());
             }
             break;
             default:
@@ -239,9 +236,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
         }
     }
 
-    pointsEkv = CheckLoops(CorrectEquidistantPoints(pointsEkv));//A path can contains loops
-    pointsEkv = Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit()));
-    return pointsEkv;
+    return Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit()));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -375,6 +370,21 @@ int VPiece::indexOfNode(const quint32 &id) const
     return indexOfNode(d->m_nodes, id);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
+                                       const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
+{
+    const QPointF begin = StartSegment(data, i, reverse);
+    const QPointF end = EndSegment(data, i, reverse);
+
+    const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
+
+    for(int i = 0; i < points.size(); ++i)
+    {
+        pointsEkv.append(VSAPoint(points.at(i)));
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index ad5834580..11723c989 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -40,6 +40,8 @@ class VPieceNode;
 class QPointF;
 class VContainer;
 template <class T> class QVector;
+template <class T>class QSharedPointer;
+class VAbstractCurve;
 
 class VPiece : public VAbstractPiece
 {
@@ -83,6 +85,8 @@ public:
 private:
     QSharedDataPointer<VPieceData> d;
 
+    void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
+                                   const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
     QPointF StartSegment(const VContainer *data, const int &i, bool reverse) const;
     QPointF EndSegment(const VContainer *data, const int &i, bool reverse) const;
 

From 2fc24914841b5fc47e05f6f21f122e9d78e3ee59 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 17:58:13 +0200
Subject: [PATCH 046/208] Set local seam allowance when building an equdistant.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index c0d052653..8623f4ffa 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -420,8 +420,20 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
 //---------------------------------------------------------------------------------------------------------------------
 QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
-    const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, width),
-                                  SingleParallelPoint(p2, p1, -90, width));
+    qreal w1 = p1.GetSAAfter();
+    if (w1 < 0)
+    {
+        w1 = width;
+    }
+
+    qreal w2 = p2.GetSABefore();
+    if (w2 < 0)
+    {
+        w2 = width;
+    }
+
+    const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, w1),
+                                  SingleParallelPoint(p2, p1, -90, w2));
     return paralel;
 }
 

From dd8067e47f075325f75eb0396c7a416145f9591d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 20:15:06 +0200
Subject: [PATCH 047/208] Convert local seam allowance to pixels.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 8623f4ffa..4787c9893 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -28,6 +28,7 @@
 
 #include "vabstractpiece.h"
 #include "vabstractpiece_p.h"
+#include "../vmisc/vabstractapplication.h"
 
 #include <QLineF>
 #include <QSet>
@@ -420,13 +421,13 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
 //---------------------------------------------------------------------------------------------------------------------
 QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
-    qreal w1 = p1.GetSAAfter();
+    qreal w1 = qApp->toPixel(p1.GetSAAfter());
     if (w1 < 0)
     {
         w1 = width;
     }
 
-    qreal w2 = p2.GetSABefore();
+    qreal w2 = qApp->toPixel(p2.GetSABefore());
     if (w2 < 0)
     {
         w2 = width;

From ebd58376d901898e091e6b1edb1e84159221b733 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 20:15:44 +0200
Subject: [PATCH 048/208] Use method VAbstractCurve::PathLength to get length.

--HG--
branch : feature
---
 src/libs/vgeometry/vabstractcurve.cpp | 5 +++++
 src/libs/vgeometry/vabstractcurve.h   | 3 ++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp
index d50762799..d1f89096d 100644
--- a/src/libs/vgeometry/vabstractcurve.cpp
+++ b/src/libs/vgeometry/vabstractcurve.cpp
@@ -321,6 +321,11 @@ QPainterPath VAbstractCurve::ShowDirection(const QVector<QPointF> &points) const
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractCurve::PathLength(const QVector<QPointF> &path)
 {
+    if (path.size() < 2)
+    {
+        return 0;
+    }
+
     QPainterPath splinePath;
     splinePath.moveTo(path.at(0));
     for (qint32 i = 1; i < path.count(); ++i)
diff --git a/src/libs/vgeometry/vabstractcurve.h b/src/libs/vgeometry/vabstractcurve.h
index 13d16969c..3b58a8c2c 100644
--- a/src/libs/vgeometry/vabstractcurve.h
+++ b/src/libs/vgeometry/vabstractcurve.h
@@ -79,13 +79,14 @@ public:
     QString                  GetColor() const;
     void                     SetColor(const QString &color);
 
+    static qreal             PathLength(const QVector<QPointF> &path);
+
     static QVector<QPointF>  CurveIntersectLine(const QVector<QPointF> &points, const QLineF &line);
 
     virtual QString          NameForHistory(const QString &toolName) const=0;
 protected:
     QPainterPath             ShowDirection(const QVector<QPointF> &points) const;
     virtual void             CreateName() =0;
-    static qreal             PathLength(const QVector<QPointF> &path);
 private:
     QSharedDataPointer<VAbstractCurveData> d;
 

From 7490e3f8d646ae7c7edcd86606b68c8fbd8f2e5f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 11 Nov 2016 20:17:39 +0200
Subject: [PATCH 049/208] Calc local seam allowance for curve segment.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 88 +++++++++++++++++++++++++++++-----
 src/libs/vpatterndb/vpiece.h   |  4 +-
 2 files changed, 77 insertions(+), 15 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 57c52d277..8f8d02026 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -374,19 +374,77 @@ int VPiece::indexOfNode(const quint32 &id) const
 void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                        const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
 {
-    const QPointF begin = StartSegment(data, i, reverse);
-    const QPointF end = EndSegment(data, i, reverse);
+    const VSAPoint begin = StartSegment(data, i, reverse);
+    const VSAPoint end = EndSegment(data, i, reverse);
 
     const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
-
-    for(int i = 0; i < points.size(); ++i)
+    if (points.isEmpty())
     {
-        pointsEkv.append(VSAPoint(points.at(i)));
+        return;
+    }
+
+    qreal w1 = begin.GetSAAfter();
+    qreal w2 = end.GetSABefore();
+    if (w1 < 0 && w2 < 0)
+    {// no local widths
+        for(int i = 0; i < points.size(); ++i)
+        {
+            pointsEkv.append(VSAPoint(points.at(i)));
+        }
+    }
+    else
+    {
+        const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
+
+        w1 = ToPixel(w1, *data->GetPatternUnit());
+        if (w1 < 0)
+        {
+            w1 = width;
+        }
+
+        w2 = ToPixel(w1, *data->GetPatternUnit());
+        if (w2 < 0)
+        {
+            w2 = width;
+        }
+
+        const qreal wDiff = w2 - w1;// Difference between to local widths
+        const qreal fullLength = VAbstractCurve::PathLength(points);
+
+        VSAPoint p(points.at(0));//First point in the list
+        p.SetSAAfter(begin.GetSAAfter());
+        p.SetSABefore(begin.GetSABefore());
+        pointsEkv.append(p);
+
+        qreal length = 0; // how much we handle
+
+        for(int i = 1; i < points.size(); ++i)
+        {
+            p = VSAPoint(points.at(i));
+
+            if (i == points.size() - 1)
+            {// last point
+                p.SetSAAfter(end.GetSAAfter());
+                p.SetSABefore(end.GetSABefore());
+            }
+            else
+            {
+                length += QLineF(points.at(i-1), points.at(i)).length();
+
+                qreal localWidth = w1 + wDiff*(length/fullLength);
+                localWidth = FromPixel(localWidth, *data->GetPatternUnit());
+
+                p.SetSAAfter(localWidth);
+                p.SetSABefore(localWidth);
+            }
+
+            pointsEkv.append(p);
+        }
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse) const
+VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
 {
     if (i < 0 && i > CountNodes()-1)
     {
@@ -401,21 +459,23 @@ QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse)
         points = VGObject::GetReversePoints(points);
     }
 
-    QPointF begin = points.first();
+    VSAPoint begin = points.first();
     if (CountNodes() > 1)
     {
         if (i == 0)
         {
             if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
             {
-                begin = *data->GeometricObject<VPointF>(at(CountNodes()-1).GetId());
+                const VPieceNode node = at(CountNodes()-1);
+                begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
             }
         }
         else
         {
             if (at(i-1).GetTypeTool() == Tool::NodePoint)
             {
-                begin = *data->GeometricObject<VPointF>(at(i-1).GetId());
+                const VPieceNode node = at(i-1);
+                begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
             }
         }
     }
@@ -423,7 +483,7 @@ QPointF VPiece::StartSegment(const VContainer *data, const int &i, bool reverse)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) const
+VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
 {
     if (i < 0 && i > CountNodes()-1)
     {
@@ -438,21 +498,23 @@ QPointF VPiece::EndSegment(const VContainer *data, const int &i, bool reverse) c
         points = VGObject::GetReversePoints(points);
     }
 
-    QPointF end = points.last();
+    VSAPoint end = points.last();
     if (CountNodes() > 2)
     {
         if (i == CountNodes() - 1)
         {
             if (at(0).GetTypeTool() == Tool::NodePoint)
             {
-                end = *data->GeometricObject<VPointF>(at(0).GetId());
+                const VPieceNode node = at(0);
+                end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
             }
         }
         else
         {
             if (at(i+1).GetTypeTool() == Tool::NodePoint)
             {
-                end = *data->GeometricObject<VPointF>(at(i+1).GetId());
+                const VPieceNode node = at(i+1);
+                end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
             }
         }
     }
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 11723c989..0ebf87e4d 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -87,8 +87,8 @@ private:
 
     void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                    const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
-    QPointF StartSegment(const VContainer *data, const int &i, bool reverse) const;
-    QPointF EndSegment(const VContainer *data, const int &i, bool reverse) const;
+    VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
+    VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
 
     static int indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };

From c5536ab38a494a1d0d2b442f69ce327966288e6d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 12:41:04 +0200
Subject: [PATCH 050/208] Control seam allowance before and after values in a
 dialog.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode.cpp            |  30 +++
 src/libs/vpatterndb/vpiecenode.h              |   6 +
 src/libs/vpatterndb/vpiecenode_p.h            |  65 +++---
 .../dialogs/tools/dialogseamallowance.cpp     | 220 ++++++++++++++++++
 .../dialogs/tools/dialogseamallowance.h       |  11 +
 .../dialogs/tools/dialogseamallowance.ui      | 104 +++++++++
 6 files changed, 408 insertions(+), 28 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index f238e2f65..a98c155eb 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -98,6 +98,36 @@ void VPieceNode::SetReverse(bool reverse)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPieceNode::GetSABefore() const
+{
+    return d->m_saBefore;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetSABefore(qreal value)
+{
+    if (d->m_typeTool == Tool::NodePoint)
+    {
+        value < 0 ? d->m_saBefore = -1: d->m_saBefore = value;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPieceNode::GetSAAfter() const
+{
+    return d->m_saAfter;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetSAAfter(qreal value)
+{
+    if (d->m_typeTool == Tool::NodePoint)
+    {
+        value < 0 ? d->m_saAfter = -1: d->m_saAfter = value;
+    }
+}
+
 // Friend functions
 //---------------------------------------------------------------------------------------------------------------------
 QDataStream& operator<<(QDataStream& out, const VPieceNode& p)
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 62e3ad3fd..bc9751fcc 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -57,6 +57,12 @@ public:
 
     bool GetReverse() const;
     void SetReverse(bool reverse);
+
+    qreal GetSABefore() const;
+    void  SetSABefore(qreal value);
+
+    qreal GetSAAfter() const;
+    void  SetSAAfter(qreal value);
 private:
     QSharedDataPointer<VPieceNodeData> d;
 };
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index bdc54abb8..63433bed7 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -39,40 +39,49 @@ QT_WARNING_DISABLE_GCC("-Weffc++")
 class VPieceNodeData : public QSharedData
 {
 public:
-  VPieceNodeData()
-    : m_id(NULL_ID),
-      m_typeTool(Tool::NodePoint),
-      m_reverse(false)
-  {}
+    VPieceNodeData()
+        : m_id(NULL_ID),
+          m_typeTool(Tool::NodePoint),
+          m_reverse(false),
+          m_saBefore(-1),
+          m_saAfter(-1)
+    {}
 
-  VPieceNodeData(quint32 id, Tool typeTool, bool reverse)
-      : m_id(id),
-        m_typeTool(typeTool),
-        m_reverse(reverse)
-  {
-      if (m_typeTool == Tool::NodePoint)
-      {
-          m_reverse = false;
-      }
-  }
+    VPieceNodeData(quint32 id, Tool typeTool, bool reverse)
+        : m_id(id),
+          m_typeTool(typeTool),
+          m_reverse(reverse),
+          m_saBefore(-1),
+          m_saAfter(-1)
+    {
+        if (m_typeTool == Tool::NodePoint)
+        {
+            m_reverse = false;
+        }
+    }
 
-  VPieceNodeData (const VPieceNodeData& node)
-      : QSharedData(node),
-        m_id(node.m_id),
-        m_typeTool(node.m_typeTool),
-        m_reverse(node.m_reverse)
-  {}
+    VPieceNodeData (const VPieceNodeData& node)
+        : QSharedData(node),
+          m_id(node.m_id),
+          m_typeTool(node.m_typeTool),
+          m_reverse(node.m_reverse),
+          m_saBefore(node.m_saBefore),
+          m_saAfter(node.m_saAfter)
+    {}
 
-  ~VPieceNodeData();
+    ~VPieceNodeData();
 
-  /** @brief id object id. */
-  quint32 m_id;
+    /** @brief id object id. */
+    quint32 m_id;
 
-  /** @brief typeTool type of tool */
-  Tool m_typeTool;
+    /** @brief typeTool type of tool */
+    Tool m_typeTool;
 
-  /** @brief reverse true if need reverse points list for node. */
-  bool m_reverse;
+    /** @brief reverse true if need reverse points list for node. */
+    bool m_reverse;
+
+    qreal m_saBefore;
+    qreal m_saAfter;
 
 private:
     VPieceNodeData &operator=(const VPieceNodeData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index f721b81af..5ffc286d2 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -52,14 +52,37 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
 
     ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
     ui->labelUnit->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    ui->labelUnitBefore->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    ui->labelUnitAfter->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
 
     if(qApp->patternUnit() == Unit::Inch)
     {
         ui->doubleSpinBoxSeams->setDecimals(5);
+        ui->doubleSpinBoxSABefore->setDecimals(5);
+        ui->doubleSpinBoxSAAfter->setDecimals(5);
     }
     // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
     ui->doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
 
+    InitNodesList();
+    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::NodeChanged);
+    if (ui->comboBoxNodes->count() > 0)
+    {
+        NodeChanged(0);
+    }
+
+    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefBefore);
+    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefAfter);
+
+    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
+
+    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogSeamAllowance::ChangedSABefore);
+    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogSeamAllowance::ChangedSAAfter);
+
     ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
@@ -107,6 +130,8 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
     ui->checkBoxSeams->setChecked(m_piece.IsSeamAllowance());
 
     ValidObjects(MainPathIsValid());
+
+    ListChanged();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -263,12 +288,102 @@ void DialogSeamAllowance::ListChanged()
         visPath->SetPiece(CreatePiece());
         visPath->RefreshGeometry();
     }
+    InitNodesList();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::EnableSeamAllowance(bool enable)
 {
     ui->groupBoxAutomatic->setEnabled(enable);
+
+    if (enable)
+    {
+        InitNodesList();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::NodeChanged(int index)
+{
+    ui->doubleSpinBoxSABefore->setDisabled(true);
+    ui->doubleSpinBoxSAAfter->setDisabled(true);
+    ui->pushButtonDefBefore->setDisabled(true);
+    ui->pushButtonDefAfter->setDisabled(true);
+
+    ui->doubleSpinBoxSABefore->blockSignals(true);
+    ui->doubleSpinBoxSAAfter->blockSignals(true);
+
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+        const VPiece piece = CreatePiece();
+        const int nodeIndex = piece.indexOfNode(id);
+        if (nodeIndex != -1)
+        {
+            const VPieceNode node = piece.at(nodeIndex);
+
+            ui->doubleSpinBoxSABefore->setEnabled(true);
+            ui->doubleSpinBoxSAAfter->setEnabled(true);
+
+            qreal w1 = node.GetSABefore();
+            if (w1 < 0)
+            {
+                w1 = piece.GetSAWidth();
+            }
+            else
+            {
+                ui->pushButtonDefBefore->setEnabled(true);
+            }
+            ui->doubleSpinBoxSABefore->setValue(w1);
+
+            qreal w2 = node.GetSAAfter();
+            if (w2 < 0)
+            {
+                w2 = piece.GetSAWidth();
+            }
+            else
+            {
+                ui->pushButtonDefAfter->setEnabled(true);
+            }
+            ui->doubleSpinBoxSAAfter->setValue(w2);
+        }
+    }
+    else
+    {
+        ui->doubleSpinBoxSABefore->setValue(0);
+        ui->doubleSpinBoxSAAfter->setValue(0);
+    }
+
+    ui->doubleSpinBoxSABefore->blockSignals(false);
+    ui->doubleSpinBoxSAAfter->blockSignals(false);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ReturnDefBefore()
+{
+    SetCurrentSABefore(-1);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ReturnDefAfter()
+{
+    SetCurrentSAAfter(-1);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ChangedSABefore(double d)
+{
+    SetCurrentSABefore(d);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ChangedSAAfter(double d)
+{
+    SetCurrentSAAfter(d);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -447,3 +562,108 @@ QString DialogSeamAllowance::GetNodeName(const VPieceNode &node) const
 
     return name;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitNodesList()
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const quint32 id = ui->comboBoxNodes->itemData(ui->comboBoxNodes->currentIndex()).toUInt();
+#else
+    const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+#endif
+
+    ui->comboBoxNodes->blockSignals(true);
+    ui->comboBoxNodes->clear();
+
+    const VPiece piece = CreatePiece();
+
+    for (int i = 0; i < piece.CountNodes(); ++i)
+    {
+        const VPieceNode node = piece.at(i);
+        if (node.GetTypeTool() == Tool::NodePoint)
+        {
+            const QString name = GetNodeName(node);
+
+            ui->comboBoxNodes->addItem(name, node.GetId());
+        }
+    }
+    ui->comboBoxNodes->blockSignals(false);
+
+    const int index = ui->comboBoxNodes->findData(id);
+    if (index != -1)
+    {
+        ui->comboBoxNodes->setCurrentIndex(index);
+        NodeChanged(index);// Need in case combox index was not changed
+    }
+    else
+    {
+        if (ui->comboBoxNodes->count() > 0)
+        {
+            NodeChanged(0);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QListWidgetItem *DialogSeamAllowance::GetItemById(quint32 id)
+{
+    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidget->item(i);
+        const VPieceNode node = qvariant_cast<VPieceNode>(item->data(Qt::UserRole));
+
+        if (node.GetId() == id)
+        {
+            return item;
+        }
+    }
+    return nullptr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetCurrentSABefore(qreal value)
+{
+    const int index = ui->comboBoxNodes->currentIndex();
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetSABefore(value);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetCurrentSAAfter(qreal value)
+{
+    const int index = ui->comboBoxNodes->currentIndex();
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetSAAfter(value);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 220894323..d881dc6d3 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -63,6 +63,11 @@ private slots:
     void ShowContextMenu(const QPoint &pos);
     void ListChanged();
     void EnableSeamAllowance(bool enable);
+    void NodeChanged(int index);
+    void ReturnDefBefore();
+    void ReturnDefAfter();
+    void ChangedSABefore(double d);
+    void ChangedSAAfter(double d);
 
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
@@ -80,6 +85,12 @@ private:
     bool    FirstPointEqualLast() const;
     bool    MainPathIsClockwise() const;
     QString GetNodeName(const VPieceNode &node) const;
+    void    InitNodesList();
+
+    QListWidgetItem *GetItemById(quint32 id);
+
+    void SetCurrentSABefore(qreal value);
+    void SetCurrentSAAfter(qreal value);
 };
 
 #endif // DIALOGSEAMALLOWANCE_H
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 389f40739..27b66424e 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -182,6 +182,110 @@
             </item>
            </layout>
           </item>
+          <item>
+           <widget class="QGroupBox" name="groupBox">
+            <property name="title">
+             <string>Nodes</string>
+            </property>
+            <layout class="QFormLayout" name="formLayout">
+             <property name="fieldGrowthPolicy">
+              <enum>QFormLayout::ExpandingFieldsGrow</enum>
+             </property>
+             <item row="0" column="0">
+              <widget class="QLabel" name="labelNode">
+               <property name="text">
+                <string>Node:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="1">
+              <widget class="QComboBox" name="comboBoxNodes"/>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="labelSABefore">
+               <property name="toolTip">
+                <string>Seam allowance before node</string>
+               </property>
+               <property name="text">
+                <string>Before:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <layout class="QHBoxLayout" name="horizontalLayout">
+               <item>
+                <widget class="QDoubleSpinBox" name="doubleSpinBoxSABefore">
+                 <property name="maximum">
+                  <double>900.990000000000009</double>
+                 </property>
+                 <property name="singleStep">
+                  <double>0.100000000000000</double>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="labelUnitBefore">
+                 <property name="text">
+                  <string>cm</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButtonDefBefore">
+                 <property name="toolTip">
+                  <string>Return to default width</string>
+                 </property>
+                 <property name="text">
+                  <string>Default</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item row="2" column="0">
+              <widget class="QLabel" name="labelSAAfter">
+               <property name="toolTip">
+                <string>Seam allowance after node</string>
+               </property>
+               <property name="text">
+                <string>After:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="1">
+              <layout class="QHBoxLayout" name="horizontalLayout_3">
+               <item>
+                <widget class="QDoubleSpinBox" name="doubleSpinBoxSAAfter">
+                 <property name="maximum">
+                  <double>900.990000000000009</double>
+                 </property>
+                 <property name="singleStep">
+                  <double>0.100000000000000</double>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="labelUnitAfter">
+                 <property name="text">
+                  <string>cm</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButtonDefAfter">
+                 <property name="toolTip">
+                  <string>Return to default width</string>
+                 </property>
+                 <property name="text">
+                  <string>Default</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+          </item>
           <item>
            <spacer name="verticalSpacer">
             <property name="orientation">

From 6706f3b39d8b787a24c30b49ce123529f661f5ba Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 12:45:53 +0200
Subject: [PATCH 051/208] Use QDoubleSpinBox setSuffix() method instead
 independent label.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     |  8 +++---
 .../dialogs/tools/dialogseamallowance.ui      | 27 -------------------
 2 files changed, 5 insertions(+), 30 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 5ffc286d2..a3456798b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -51,9 +51,11 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     CheckState();
 
     ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
-    ui->labelUnit->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
-    ui->labelUnitBefore->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
-    ui->labelUnitAfter->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+
+    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    ui->doubleSpinBoxSeams->setSuffix(suffix);
+    ui->doubleSpinBoxSABefore->setSuffix(suffix);
+    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
 
     if(qApp->patternUnit() == Unit::Inch)
     {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 27b66424e..b9b178fe8 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -154,19 +154,6 @@
               </property>
              </widget>
             </item>
-            <item>
-             <widget class="QLabel" name="labelUnit">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="text">
-               <string>cm</string>
-              </property>
-             </widget>
-            </item>
             <item>
              <spacer name="horizontalSpacer">
               <property name="orientation">
@@ -223,13 +210,6 @@
                  </property>
                 </widget>
                </item>
-               <item>
-                <widget class="QLabel" name="labelUnitBefore">
-                 <property name="text">
-                  <string>cm</string>
-                 </property>
-                </widget>
-               </item>
                <item>
                 <widget class="QPushButton" name="pushButtonDefBefore">
                  <property name="toolTip">
@@ -264,13 +244,6 @@
                  </property>
                 </widget>
                </item>
-               <item>
-                <widget class="QLabel" name="labelUnitAfter">
-                 <property name="text">
-                  <string>cm</string>
-                 </property>
-                </widget>
-               </item>
                <item>
                 <widget class="QPushButton" name="pushButtonDefAfter">
                  <property name="toolTip">

From d0b0f55d1911af35cf40a079f322e3c38c7dd085 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 13:18:16 +0200
Subject: [PATCH 052/208] Read and write local seam allowance width (before and
 after).

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           |  9 +++++++--
 src/libs/ifc/schema/pattern/v0.4.0.xsd       |  6 ++++--
 src/libs/vtools/tools/vtoolseamallowance.cpp | 15 +++++++++++++--
 src/libs/vtools/tools/vtoolseamallowance.h   |  2 ++
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 84166e993..cb385888a 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -748,7 +748,9 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
         if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagNode)
         {
             const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-            const bool reverse = GetParametrUInt(element, VToolDetail::AttrReverse, "0");
+            const bool reverse = GetParametrUInt(element, VToolSeamAllowance::AttrNodeReverse, "0");
+            const qreal saBefore = GetParametrDouble(element, VToolSeamAllowance::AttrSABefore, "-1");
+            const qreal saAfter = GetParametrDouble(element, VToolSeamAllowance::AttrSAAfter, "-1");
 
             const QString t = GetParametrString(element, AttrType, VToolSeamAllowance::NodePoint);
             Tool tool;
@@ -771,7 +773,10 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
                     VException e(tr("Wrong tag name '%1'.").arg(t));
                     throw e;
             }
-            detail.Append(VPieceNode(id, tool, reverse));
+            VPieceNode node(id, tool, reverse);
+            node.SetSABefore(saBefore);
+            node.SetSAAfter(saAfter);
+            detail.Append(node);
         }
     }
 }
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index ac4a4907c..e98b35b89 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -399,9 +399,11 @@
 																						<xs:sequence>
 																						   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
 																								   <xs:complexType>
-																										 <xs:attribute name="type" type="xs:string"></xs:attribute>
-																										 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
+																										 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
 																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
+																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
 																								   </xs:complexType>
 																							 </xs:element>
 																						 </xs:sequence>
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index af6b06943..ae60b869c 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -64,6 +64,8 @@ const QString VToolSeamAllowance::AttrNodeReverse    = QStringLiteral("reverse")
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
+const QString VToolSeamAllowance::AttrSABefore       = QStringLiteral("before");
+const QString VToolSeamAllowance::AttrSAAfter        = QStringLiteral("after");
 
 const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
 const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
@@ -204,12 +206,21 @@ void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement,
 
     doc->SetAttribute(nod, AttrIdObject, node.GetId());
 
-    if (node.GetTypeTool() != Tool::NodePoint)
+    const Tool type = node.GetTypeTool();
+    if (type != Tool::NodePoint)
     {
         doc->SetAttribute(nod, AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
     }
+    else
+    {
+        const qreal w1 = node.GetSABefore();
+        w1 < 0 ? domElement.removeAttribute(AttrSABefore) : doc->SetAttribute(nod, AttrSABefore, w1);
 
-    switch (node.GetTypeTool())
+        const qreal w2 = node.GetSAAfter();
+        w2 < 0 ? domElement.removeAttribute(AttrSAAfter) : doc->SetAttribute(nod, AttrSAAfter, w2);
+    }
+
+    switch (type)
     {
         case (Tool::NodeArc):
             doc->SetAttribute(nod, AttrType, NodeArc);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index dd65595ee..8b1a76764 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -62,6 +62,8 @@ public:
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
     static const QString AttrWidth;
+    static const QString AttrSABefore;
+    static const QString AttrSAAfter;
 
     static const QString NodeArc;
     static const QString NodePoint;

From e1d559e1d34cd8b49b957549f60d4e5624071a39 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 13:31:37 +0200
Subject: [PATCH 053/208] Use information about local seam allowance when
 generating seam allowance in VPiece class.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 8f8d02026..aeef29177 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -214,24 +214,28 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
     QVector<VSAPoint> pointsEkv;
     for (int i = 0; i< CountNodes(); ++i)
     {
-        switch (at(i).GetTypeTool())
+        const VPieceNode node = at(i);
+        switch (node.GetTypeTool())
         {
             case (Tool::NodePoint):
             {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
-                pointsEkv.append(VSAPoint(point->toQPointF()));
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
+                VSAPoint p(point->toQPointF());
+                p.SetSAAfter(node.GetSAAfter());
+                p.SetSABefore(node.GetSABefore());
+                pointsEkv.append(p);
             }
             break;
             case (Tool::NodeArc):
             case (Tool::NodeSpline):
             case (Tool::NodeSplinePath):
             {
-                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
-                CurveSeamAllowanceSegment(pointsEkv, data, curve, i, at(i).GetReverse());
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
+                CurveSeamAllowanceSegment(pointsEkv, data, curve, i, node.GetReverse());
             }
             break;
             default:
-                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).GetTypeTool());
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
                 break;
         }
     }
@@ -402,7 +406,7 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
             w1 = width;
         }
 
-        w2 = ToPixel(w1, *data->GetPatternUnit());
+        w2 = ToPixel(w2, *data->GetPatternUnit());
         if (w2 < 0)
         {
             w2 = width;
@@ -468,6 +472,8 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
             {
                 const VPieceNode node = at(CountNodes()-1);
                 begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
+                begin.SetSAAfter(node.GetSAAfter());
+                begin.SetSABefore(node.GetSABefore());
             }
         }
         else
@@ -476,6 +482,8 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
             {
                 const VPieceNode node = at(i-1);
                 begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
+                begin.SetSAAfter(node.GetSAAfter());
+                begin.SetSABefore(node.GetSABefore());
             }
         }
     }
@@ -507,6 +515,8 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
             {
                 const VPieceNode node = at(0);
                 end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
+                end.SetSAAfter(node.GetSAAfter());
+                end.SetSABefore(node.GetSABefore());
             }
         }
         else
@@ -515,6 +525,8 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
             {
                 const VPieceNode node = at(i+1);
                 end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
+                end.SetSAAfter(node.GetSAAfter());
+                end.SetSABefore(node.GetSABefore());
             }
         }
     }

From caba2db95bef877d3590a0705e4800de2c9a2133 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 14:00:07 +0200
Subject: [PATCH 054/208] Make sure that a point is really lies on curve.

--HG--
branch : feature
---
 src/libs/vgeometry/vabstractcurve.cpp | 27 ++++++++++++++++++
 src/libs/vgeometry/vabstractcurve.h   |  2 ++
 src/libs/vpatterndb/vpiece.cpp        | 40 +++++++++++++++++++--------
 3 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp
index d1f89096d..514964aec 100644
--- a/src/libs/vgeometry/vabstractcurve.cpp
+++ b/src/libs/vgeometry/vabstractcurve.cpp
@@ -236,6 +236,33 @@ bool VAbstractCurve::IsIntersectLine(const QLineF &line) const
     return not points.isEmpty();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
+{
+    const QVector<QPointF> points = GetPoints();
+
+    if (points.isEmpty())
+    {
+        return false;
+    }
+    else if (points.size() < 2)
+    {
+        return points.at(0) == p;
+    }
+    else
+    {
+        for (qint32 i = 0; i < points.count()-1; ++i)
+        {
+            if (IsPointOnLineSegment(p, points.at(i), points.at(i+1)))
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VAbstractCurve::GetDuplicate() const
 {
diff --git a/src/libs/vgeometry/vabstractcurve.h b/src/libs/vgeometry/vabstractcurve.h
index 3b58a8c2c..629572adf 100644
--- a/src/libs/vgeometry/vabstractcurve.h
+++ b/src/libs/vgeometry/vabstractcurve.h
@@ -70,6 +70,8 @@ public:
     virtual QVector<QPointF> IntersectLine(const QLineF &line) const;
     virtual bool             IsIntersectLine(const QLineF &line) const;
 
+    bool                     IsPointOnCurve(const QPointF &p) const;
+
     virtual qreal            GetStartAngle () const=0;
     virtual qreal            GetEndAngle () const=0;
 
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index aeef29177..faaf6d956 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -471,9 +471,13 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
             if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
             {
                 const VPieceNode node = at(CountNodes()-1);
-                begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
-                begin.SetSAAfter(node.GetSAAfter());
-                begin.SetSABefore(node.GetSABefore());
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    begin = VSAPoint(p);
+                    begin.SetSAAfter(node.GetSAAfter());
+                    begin.SetSABefore(node.GetSABefore());
+                }
             }
         }
         else
@@ -481,9 +485,13 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
             if (at(i-1).GetTypeTool() == Tool::NodePoint)
             {
                 const VPieceNode node = at(i-1);
-                begin = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
-                begin.SetSAAfter(node.GetSAAfter());
-                begin.SetSABefore(node.GetSABefore());
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    begin = VSAPoint(p);
+                    begin.SetSAAfter(node.GetSAAfter());
+                    begin.SetSABefore(node.GetSABefore());
+                }
             }
         }
     }
@@ -514,9 +522,13 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
             if (at(0).GetTypeTool() == Tool::NodePoint)
             {
                 const VPieceNode node = at(0);
-                end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
-                end.SetSAAfter(node.GetSAAfter());
-                end.SetSABefore(node.GetSABefore());
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    end = VSAPoint(p);
+                    end.SetSAAfter(node.GetSAAfter());
+                    end.SetSABefore(node.GetSABefore());
+                }
             }
         }
         else
@@ -524,9 +536,13 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
             if (at(i+1).GetTypeTool() == Tool::NodePoint)
             {
                 const VPieceNode node = at(i+1);
-                end = VSAPoint(*data->GeometricObject<VPointF>(node.GetId()));
-                end.SetSAAfter(node.GetSAAfter());
-                end.SetSABefore(node.GetSABefore());
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    end = VSAPoint(p);
+                    end.SetSAAfter(node.GetSAAfter());
+                    end.SetSABefore(node.GetSABefore());
+                }
             }
         }
     }

From 878fdb615667e524568fd990bbbdef1fd9f4f501 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 14:05:47 +0200
Subject: [PATCH 055/208] Disable Group Nodes if the main list doesn't contain
 points.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index a3456798b..807ee663f 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -69,10 +69,6 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     InitNodesList();
     connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::NodeChanged);
-    if (ui->comboBoxNodes->count() > 0)
-    {
-        NodeChanged(0);
-    }
 
     connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefBefore);
     connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefAfter);
@@ -599,10 +595,7 @@ void DialogSeamAllowance::InitNodesList()
     }
     else
     {
-        if (ui->comboBoxNodes->count() > 0)
-        {
-            NodeChanged(0);
-        }
+        ui->comboBoxNodes->count() > 0 ? NodeChanged(0) : NodeChanged(-1);
     }
 }
 

From 585bfec12fa67d2a57660de7a9b0d0031e5759e4 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 15:41:15 +0200
Subject: [PATCH 056/208] Fix bug Tool seam allowance. The tool returned to
 previous position after selecting Apply or Ok buttons in the tool's dialog.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 28 ++++++++++---------
 .../dialogs/tools/dialogseamallowance.h       |  3 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  5 ++++
 3 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 807ee663f..00f26ed8b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -38,8 +38,9 @@
 DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
       ui(new Ui::DialogSeamAllowance),
-      m_piece(),
-      applyAllowed(false)// By default disabled
+      applyAllowed(false),// By default disabled
+      m_mx(0),
+      m_my(0)
 {
     ui->setupUi(this);
 
@@ -110,22 +111,24 @@ void DialogSeamAllowance::EnableApply(bool enable)
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::GetPiece() const
 {
-    return m_piece;
+    return CreatePiece();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::SetPiece(const VPiece &piece)
 {
-    m_piece = piece;
     ui->listWidget->clear();
-    for (int i = 0; i < m_piece.CountNodes(); ++i)
+    for (int i = 0; i < piece.CountNodes(); ++i)
     {
-        NewItem(m_piece.at(i));
+        NewItem(piece.at(i));
     }
 
-    ui->checkBoxForbidFlipping->setChecked(m_piece.IsForbidFlipping());
-    ui->doubleSpinBoxSeams->setValue(m_piece.GetSAWidth());
-    ui->checkBoxSeams->setChecked(m_piece.IsSeamAllowance());
+    ui->checkBoxForbidFlipping->setChecked(piece.IsForbidFlipping());
+    ui->doubleSpinBoxSeams->setValue(piece.GetSAWidth());
+    ui->checkBoxSeams->setChecked(piece.IsSeamAllowance());
+
+    m_mx = piece.GetMx();
+    m_my = piece.GetMy();
 
     ValidObjects(MainPathIsValid());
 
@@ -217,10 +220,7 @@ void DialogSeamAllowance::ShowDialog(bool click)
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::SaveData()
-{
-    m_piece.Clear();
-    m_piece = CreatePiece();
-}
+{}
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::CheckState()
@@ -397,6 +397,8 @@ VPiece DialogSeamAllowance::CreatePiece() const
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
     piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
     piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
+    piece.SetMx(m_mx);
+    piece.SetMy(m_my);
 
     return piece;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index d881dc6d3..e0603c301 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -73,8 +73,9 @@ private:
     Q_DISABLE_COPY(DialogSeamAllowance)
 
     Ui::DialogSeamAllowance *ui;
-    VPiece m_piece;
     bool   applyAllowed;
+    qreal  m_mx;
+    qreal  m_my;
 
     VPiece CreatePiece() const;
 
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index ae60b869c..391124a4b 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -437,6 +437,11 @@ QVariant VToolSeamAllowance::itemChange(QGraphicsItem::GraphicsItemChange change
                 }
             }
             // Don't forget to update geometry, because first change never call full parse
+            VPiece detail = VAbstractTool::data.GetPiece(id);
+            detail.SetMx(newPos.x());
+            detail.SetMy(newPos.y());
+            VAbstractTool::data.UpdatePiece(id, detail);
+
             RefreshGeometry();
             changeFinished = true;
         }

From 3544e5611e99a92ef35689acf56c1068e96729a6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 12 Nov 2016 16:49:21 +0200
Subject: [PATCH 057/208] Fix seam allowance bug.

Because of local seam allowance width bisector angles now can be not equal.
Enough will be to check if they have a same direction.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 4787c9893..6907634f3 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -361,7 +361,7 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
             const int angle1 = BisectorAngle(p1Line1, p2Line1, p1Line2);
             const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
 
-            if (angle1 == angle2)
+            if (qAbs(angle1 - angle2) < 180)// Go in a same direction
             {//Regular equdistant case
                 const qreal length = line.length();
                 if (length > width*2.4)

From 1a9af78befe6b54aeb52f3b1248f8adac9d2b364 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 13 Nov 2016 11:23:04 +0200
Subject: [PATCH 058/208] Fix seam allowance bug.

Fix reverse dart case.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 69 +++++++++++++++++++++++++----
 src/libs/vlayout/vabstractpiece.h   |  3 ++
 2 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 6907634f3..9661825ce 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -323,6 +323,31 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
     return ekvPoints;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR qreal VAbstractPiece::PointPosition(const QPointF &p, const QLineF &line)
+{
+    return (line.p2().x() - line.p1().x()) * (p.y() - line.p1().y()) -
+           (line.p2().y() - line.p1().y()) * (p.x() - line.p1().x());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VAbstractPiece::MaxLocalSA(const VSAPoint &p, qreal width)
+{
+    qreal w1 = qApp->toPixel(p.GetSAAfter());
+    if (w1 < 0)
+    {
+        w1 = width;
+    }
+
+    qreal w2 = qApp->toPixel(p.GetSABefore());
+    if (w2 < 0)
+    {
+        w2 = width;
+    }
+
+    return qMax(w1, w2);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
@@ -356,17 +381,18 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
             break;
         case (QLineF::UnboundedIntersection):
         {
+            const qreal localWidth = MaxLocalSA(p2Line1, width);
             QLineF line( p2Line1, CrosPoint );
 
             const int angle1 = BisectorAngle(p1Line1, p2Line1, p1Line2);
             const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
 
-            if (qAbs(angle1 - angle2) < 180)// Go in a same direction
+            if (qAbs(angle1 - angle2) < 90)// Go in a same direction
             {//Regular equdistant case
                 const qreal length = line.length();
-                if (length > width*2.4)
+                if (length > localWidth*2.4)
                 { // Cutting too long a cut angle
-                    line.setLength(width); // Not sure about width value here
+                    line.setLength(localWidth); // Not sure about width value here
                     QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular
                     cutLine.setLength(length); // Decided take this length
 
@@ -395,13 +421,30 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                 }
             }
             else
-            {// Dart. Ignore if going outside of equdistant
-                const QLineF bigEdge = ParallelLine(p1Line1, p1Line2, width );
-                QPointF px;
-                const QLineF::IntersectType type = bigEdge.intersect(line, &px);
-                if (type != QLineF::BoundedIntersection)
+            {
+                QLineF bisector(p2Line1, p1Line1);
+                bisector.setAngle(angle1);
+
+                const qreal result1 = PointPosition(bisector.p2(), QLineF(p1Line1, p2Line1));
+                const qreal result2 = PointPosition(bisector.p2(), QLineF(p2Line2, p1Line2));
+
+                if (result1 <=0 && result2 <= 0)
                 {
-                    points.append(CrosPoint);
+                    // Dart. Ignore if going outside of equdistant
+                    const QLineF bigEdge = ParallelLine(p1Line1, p1Line2, localWidth );
+                    QPointF px;
+                    const QLineF::IntersectType type = bigEdge.intersect(line, &px);
+                    if (type != QLineF::BoundedIntersection)
+                    {
+                        points.append(CrosPoint);
+                        return points;
+                    }
+                }
+                else
+                {
+                    const QLineF bigEdge = ParallelLine(bigLine1.p2(), bigLine2.p1(), localWidth );
+                    points.append(bigEdge.p1());
+                    points.append(bigEdge.p2());
                     return points;
                 }
             }
@@ -438,6 +481,14 @@ QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qrea
     return paralel;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QLineF VAbstractPiece::ParallelLine(const QPointF &p1, const QPointF &p2, qreal width)
+{
+    const QLineF paralel = QLineF(SingleParallelPoint(p1, p2, 90, width),
+                                  SingleParallelPoint(p2, p1, -90, width));
+    return paralel;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VAbstractPiece::SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 579f46965..2433b8eac 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -141,9 +141,12 @@ protected:
 private:
     QSharedDataPointer<VAbstractPieceData> d;
 
+    static Q_DECL_CONSTEXPR qreal PointPosition(const QPointF &p, const QLineF &line);
+    static qreal            MaxLocalSA(const VSAPoint &p, qreal width);
     static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,
                                      const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width);
     static QLineF           ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
+    static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
     static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);
     static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
 };

From 314ae2eb4cc016c0d7c978b8d0bf914239f9bf80 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 13 Nov 2016 20:11:00 +0200
Subject: [PATCH 059/208] Method VAbstractCurve::IsPointOnCurve use QPoint
 instead QPointF for more accurate result.

--HG--
branch : feature
---
 src/libs/vgeometry/vabstractcurve.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp
index 514964aec..341bb51ff 100644
--- a/src/libs/vgeometry/vabstractcurve.cpp
+++ b/src/libs/vgeometry/vabstractcurve.cpp
@@ -253,7 +253,7 @@ bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
     {
         for (qint32 i = 0; i < points.count()-1; ++i)
         {
-            if (IsPointOnLineSegment(p, points.at(i), points.at(i+1)))
+            if (IsPointOnLineSegment(p.toPoint(), points.at(i).toPoint(), points.at(i+1).toPoint()))
             {
                 return true;
             }

From ae7405d44f3c22f96823b1d90d9c43da4205eb74 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 13 Nov 2016 20:13:05 +0200
Subject: [PATCH 060/208] Method VPiece::CurveSeamAllowanceSegment. When start
 and end of a curve segment has standard seam allowance setup only first and
 last points.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index faaf6d956..7965fbcc5 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -393,7 +393,18 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
     {// no local widths
         for(int i = 0; i < points.size(); ++i)
         {
-            pointsEkv.append(VSAPoint(points.at(i)));
+            VSAPoint p(points.at(i));
+            if (i == 0)
+            { // first point
+                p.SetSAAfter(begin.GetSAAfter());
+                p.SetSABefore(begin.GetSABefore());
+            }
+            else if (i == points.size() - 1)
+            { // last point
+                p.SetSAAfter(end.GetSAAfter());
+                p.SetSABefore(end.GetSABefore());
+            }
+            pointsEkv.append(p);
         }
     }
     else

From 4de969daa2ca0bfe35091680a6e65ed9d7226005 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 13 Nov 2016 21:13:55 +0200
Subject: [PATCH 061/208] Much better way to compare bisectors.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 41 ++++++++++++++++++++++++-----
 src/libs/vlayout/vabstractpiece.h   |  3 ++-
 2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 9661825ce..2b791cd2b 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -384,10 +384,12 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
             const qreal localWidth = MaxLocalSA(p2Line1, width);
             QLineF line( p2Line1, CrosPoint );
 
-            const int angle1 = BisectorAngle(p1Line1, p2Line1, p1Line2);
-            const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
+            const QLineF b1 = BisectorLine(p1Line1, p2Line1, p1Line2);
+            const QLineF b2 = BisectorLine(bigLine1.p1(), CrosPoint, bigLine2.p2());
 
-            if (qAbs(angle1 - angle2) < 90)// Go in a same direction
+            const qreal angle = AngleBetweenBisectors(b1, b2);
+
+            if (angle <= 90)// Go in a same direction
             {//Regular equdistant case
                 const qreal length = line.length();
                 if (length > localWidth*2.4)
@@ -423,7 +425,7 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
             else
             {
                 QLineF bisector(p2Line1, p1Line1);
-                bisector.setAngle(angle1);
+                bisector.setAngle(b1.angle());
 
                 const qreal result1 = PointPosition(bisector.p2(), QLineF(p1Line1, p2Line1));
                 const qreal result2 = PointPosition(bisector.p2(), QLineF(p2Line2, p1Line2));
@@ -499,7 +501,7 @@ QPointF VAbstractPiece::SingleParallelPoint(const QPointF &p1, const QPointF &p2
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VAbstractPiece::BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3)
+QLineF VAbstractPiece::BisectorLine(const QPointF &p1, const QPointF &p2, const QPointF &p3)
 {
     QLineF line1(p2, p1);
     QLineF line2(p2, p3);
@@ -519,5 +521,32 @@ int VAbstractPiece::BisectorAngle(const QPointF &p1, const QPointF &p2, const QP
         bLine.setAngle(bLine.angle() + angle2/2.0);
     }
 
-    return qRound(bLine.angle());
+    return bLine;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qreal VAbstractPiece::AngleBetweenBisectors(const QLineF &b1, const QLineF &b2)
+{
+    const QLineF newB2 = b2.translated(-(b2.p1().x() - b1.p1().x()), -(b2.p1().y() - b1.p1().y()));
+
+    qreal angle1 = newB2.angleTo(b1);
+    if (VFuzzyComparePossibleNulls(angle1, 360))
+    {
+        angle1 = 0;
+    }
+
+    qreal angle2 = b1.angleTo(newB2);
+    if (VFuzzyComparePossibleNulls(angle2, 360))
+    {
+        angle2 = 0;
+    }
+
+    if (angle1 <= angle2)
+    {
+        return angle1;
+    }
+    else
+    {
+        return angle2;
+    }
 }
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 2433b8eac..dbe5b625e 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -148,7 +148,8 @@ private:
     static QLineF           ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
     static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
     static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);
-    static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
+    static QLineF           BisectorLine(const QPointF &p1, const QPointF &p2, const QPointF &p3);
+    static qreal            AngleBetweenBisectors(const QLineF &b1, const QLineF &b2);
 };
 
 //---------------------------------------------------------------------------------------------------------------------

From 98dad0fb72f459c634ee6c6c80bb0e831c6282af Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 16 Nov 2016 09:15:16 +0200
Subject: [PATCH 062/208] Fixed bug the Detail remains in Group list after the
 detail is deleted in Details mode.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index 93f74e225..b64ecc6a3 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -294,6 +294,7 @@ void VContainer::ClearForFullParse()
     _id = NULL_ID;
 
     d->details->clear();
+    d->pieces->clear();
     ClearVariables(VarType::Increment);
     ClearVariables(VarType::LineAngle);
     ClearVariables(VarType::LineLength);

From cf5afffd60b8be584fdcae7e067912dbeabd9889 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 16 Nov 2016 11:16:16 +0200
Subject: [PATCH 063/208] Fix seam allowance bug. Speacial "dart" case.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 2b791cd2b..9365964e6 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -438,8 +438,11 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                     const QLineF::IntersectType type = bigEdge.intersect(line, &px);
                     if (type != QLineF::BoundedIntersection)
                     {
-                        points.append(CrosPoint);
-                        return points;
+                        if (line.length() < QLineF(p2Line1, px).length())
+                        {
+                            points.append(CrosPoint);
+                            return points;
+                        }
                     }
                 }
                 else

From 4237456228bc82c02774669f4e5f2f397231736c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 17 Nov 2016 11:00:04 +0200
Subject: [PATCH 064/208] Fix seam allowance bug.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 9365964e6..9197eb72d 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -447,10 +447,30 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                 }
                 else
                 {
-                    const QLineF bigEdge = ParallelLine(bigLine1.p2(), bigLine2.p1(), localWidth );
-                    points.append(bigEdge.p1());
-                    points.append(bigEdge.p2());
-                    return points;
+                    const qreal result1 = PointPosition(CrosPoint, QLineF(p1Line1, p2Line1));
+                    const qreal result2 = PointPosition(CrosPoint, QLineF(p2Line2, p1Line2));
+
+                    if (result1 <=0 && result2 <= 0)
+                    {
+                        if (line.length() >= localWidth)
+                        {
+                            points.append(CrosPoint);
+                            return points;
+                        }
+                        else
+                        {
+                            line.setLength(localWidth);
+                            points.append(line.p2());
+                            return points;
+                        }
+                    }
+                    else
+                    {
+                        const QLineF bigEdge = ParallelLine(bigLine1.p2(), bigLine2.p1(), localWidth );
+                        points.append(bigEdge.p1());
+                        points.append(bigEdge.p2());
+                        return points;
+                    }
                 }
             }
             break;

From afb267c05c46fb5e69e817ba865bacaffd716c42 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 17 Nov 2016 11:37:10 +0200
Subject: [PATCH 065/208] Added several comments.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 40 ++++++++++++++++-------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 9197eb72d..8886879e9 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -350,15 +350,16 @@ qreal VAbstractPiece::MaxLocalSA(const VSAPoint &p, qreal width)
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
- * @param width width of equidistant.
- * @return vector of points.
+ * @brief EkvPoint return seam aloowance points in place of intersection two edges. Last points of two edges should be
+ * equal.
+ * @param width global seam allowance width.
+ * @return seam aloowance points.
  */
 QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,
                                           const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width)
 {
     if (width < 0)
-    {
+    { // width can't be < 0
         return QVector<QPointF>();
     }
 
@@ -366,35 +367,38 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
     if (p2Line1 != p2Line2)
     {
         qDebug()<<"Last points of two lines must be equal.";
-        return QVector<QPointF>();
+        return QVector<QPointF>(); // Wrong edges
     }
 
-    QPointF CrosPoint;
     const QLineF bigLine1 = ParallelLine(p1Line1, p2Line1, width );
     const QLineF bigLine2 = ParallelLine(p2Line2, p1Line2, width );
-    QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint );
+    QPointF CrosPoint;
+    const QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint );
     switch (type)
-    {
+    {// There are at least three big cases
         case (QLineF::BoundedIntersection):
+            // The easiest, real intersection
             points.append(CrosPoint);
             return points;
             break;
         case (QLineF::UnboundedIntersection):
-        {
+        { // Most common case
             const qreal localWidth = MaxLocalSA(p2Line1, width);
             QLineF line( p2Line1, CrosPoint );
 
+            // Checking two subcases
             const QLineF b1 = BisectorLine(p1Line1, p2Line1, p1Line2);
             const QLineF b2 = BisectorLine(bigLine1.p1(), CrosPoint, bigLine2.p2());
 
             const qreal angle = AngleBetweenBisectors(b1, b2);
 
+            // Comparison bisector angles helps to find direction
             if (angle <= 90)// Go in a same direction
             {//Regular equdistant case
                 const qreal length = line.length();
                 if (length > localWidth*2.4)
                 { // Cutting too long a cut angle
-                    line.setLength(localWidth); // Not sure about width value here
+                    line.setLength(localWidth);
                     QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular
                     cutLine.setLength(length); // Decided take this length
 
@@ -417,13 +421,13 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                     points.append(px);
                 }
                 else
-                {
+                { // The point just fine
                     points.append(CrosPoint);
                     return points;
                 }
             }
             else
-            {
+            { // Different directions
                 QLineF bisector(p2Line1, p1Line1);
                 bisector.setAngle(b1.angle());
 
@@ -431,8 +435,8 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                 const qreal result2 = PointPosition(bisector.p2(), QLineF(p2Line2, p1Line2));
 
                 if (result1 <=0 && result2 <= 0)
-                {
-                    // Dart. Ignore if going outside of equdistant
+                {// Dart case. A bisector watch outside. In some cases a point still valid, but ignore if going
+                 // outside of an equdistant.
                     const QLineF bigEdge = ParallelLine(p1Line1, p1Line2, localWidth );
                     QPointF px;
                     const QLineF::IntersectType type = bigEdge.intersect(line, &px);
@@ -446,26 +450,26 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                     }
                 }
                 else
-                {
+                { // New subcase. This is not a dart. An angle is acute and bisector watch inside.
                     const qreal result1 = PointPosition(CrosPoint, QLineF(p1Line1, p2Line1));
                     const qreal result2 = PointPosition(CrosPoint, QLineF(p2Line2, p1Line2));
 
                     if (result1 <=0 && result2 <= 0)
-                    {
+                    {// The cross point is still outside of a piece
                         if (line.length() >= localWidth)
                         {
                             points.append(CrosPoint);
                             return points;
                         }
                         else
-                        {
+                        {// but not enough far, fix it
                             line.setLength(localWidth);
                             points.append(line.p2());
                             return points;
                         }
                     }
                     else
-                    {
+                    {// Wrong cross point, probably inside of a piece. Manually creating correct seam allowance
                         const QLineF bigEdge = ParallelLine(bigLine1.p2(), bigLine2.p1(), localWidth );
                         points.append(bigEdge.p1());
                         points.append(bigEdge.p2());

From a284ac024e6bf864860e087afc05ac1ea3e0c01e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 17 Nov 2016 14:08:23 +0200
Subject: [PATCH 066/208] VSAPoint class should keep data in pixels. Make
 testing a lot easier.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp |  8 ++++----
 src/libs/vpatterndb/vpiece.cpp      | 27 ++++++++++++---------------
 src/libs/vpatterndb/vpiecenode.cpp  | 22 ++++++++++++++++++++++
 src/libs/vpatterndb/vpiecenode.h    |  2 ++
 4 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 8886879e9..c93c97e00 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -333,13 +333,13 @@ Q_DECL_CONSTEXPR qreal VAbstractPiece::PointPosition(const QPointF &p, const QLi
 //---------------------------------------------------------------------------------------------------------------------
 qreal VAbstractPiece::MaxLocalSA(const VSAPoint &p, qreal width)
 {
-    qreal w1 = qApp->toPixel(p.GetSAAfter());
+    qreal w1 = p.GetSAAfter();
     if (w1 < 0)
     {
         w1 = width;
     }
 
-    qreal w2 = qApp->toPixel(p.GetSABefore());
+    qreal w2 = p.GetSABefore();
     if (w2 < 0)
     {
         w2 = width;
@@ -493,13 +493,13 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
 //---------------------------------------------------------------------------------------------------------------------
 QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
-    qreal w1 = qApp->toPixel(p1.GetSAAfter());
+    qreal w1 = p1.GetSAAfter();
     if (w1 < 0)
     {
         w1 = width;
     }
 
-    qreal w2 = qApp->toPixel(p2.GetSABefore());
+    qreal w2 = p2.GetSABefore();
     if (w2 < 0)
     {
         w2 = width;
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 7965fbcc5..a3515cdf3 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -221,8 +221,9 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
             {
                 const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
                 VSAPoint p(point->toQPointF());
-                p.SetSAAfter(node.GetSAAfter());
-                p.SetSABefore(node.GetSABefore());
+
+                p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
                 pointsEkv.append(p);
             }
             break;
@@ -411,13 +412,11 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
     {
         const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
 
-        w1 = ToPixel(w1, *data->GetPatternUnit());
         if (w1 < 0)
         {
             w1 = width;
         }
 
-        w2 = ToPixel(w2, *data->GetPatternUnit());
         if (w2 < 0)
         {
             w2 = width;
@@ -445,9 +444,7 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
             else
             {
                 length += QLineF(points.at(i-1), points.at(i)).length();
-
-                qreal localWidth = w1 + wDiff*(length/fullLength);
-                localWidth = FromPixel(localWidth, *data->GetPatternUnit());
+                const qreal localWidth = w1 + wDiff*(length/fullLength);
 
                 p.SetSAAfter(localWidth);
                 p.SetSABefore(localWidth);
@@ -486,8 +483,8 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
                 if (curve->IsPointOnCurve(p))
                 {
                     begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter());
-                    begin.SetSABefore(node.GetSABefore());
+                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
                 }
             }
         }
@@ -500,8 +497,8 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
                 if (curve->IsPointOnCurve(p))
                 {
                     begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter());
-                    begin.SetSABefore(node.GetSABefore());
+                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
                 }
             }
         }
@@ -537,8 +534,8 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
                 if (curve->IsPointOnCurve(p))
                 {
                     end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter());
-                    end.SetSABefore(node.GetSABefore());
+                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
                 }
             }
         }
@@ -551,8 +548,8 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
                 if (curve->IsPointOnCurve(p))
                 {
                     end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter());
-                    end.SetSABefore(node.GetSABefore());
+                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
                 }
             }
         }
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index a98c155eb..32481a696 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -104,6 +104,17 @@ qreal VPieceNode::GetSABefore() const
     return d->m_saBefore;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPieceNode::GetSABefore(Unit unit) const
+{
+    qreal value = d->m_saBefore;
+    if (value >= 0)
+    {
+        value = ToPixel(value, unit);
+    }
+    return value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetSABefore(qreal value)
 {
@@ -119,6 +130,17 @@ qreal VPieceNode::GetSAAfter() const
     return d->m_saAfter;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPieceNode::GetSAAfter(Unit unit) const
+{
+    qreal value = d->m_saAfter;
+    if (value >= 0)
+    {
+        value = ToPixel(value, unit);
+    }
+    return value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetSAAfter(qreal value)
 {
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index bc9751fcc..4b4da1a2f 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -59,9 +59,11 @@ public:
     void SetReverse(bool reverse);
 
     qreal GetSABefore() const;
+    qreal GetSABefore(Unit unit) const;
     void  SetSABefore(qreal value);
 
     qreal GetSAAfter() const;
+    qreal GetSAAfter(Unit unit) const;
     void  SetSAAfter(qreal value);
 private:
     QSharedDataPointer<VPieceNodeData> d;

From 726d8614dc495d7bb0cfd3eb9d84fe86051e5fe3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 18 Nov 2016 12:58:47 +0200
Subject: [PATCH 067/208] Unit tests for testing seam allowance.

--HG--
branch : feature
---
 src/app/share/collection/test/seamtest1.val   |  162 ++
 src/app/share/collection/test/seamtest2.val   |   42 +
 src/app/share/collection/test/seamtest3.val   |   57 +
 src/libs/vlayout/vabstractpiece.h             |    9 +
 src/test/ValentinaTest/ValentinaTest.pro      |    6 +-
 src/test/ValentinaTest/qttestmainlambda.cpp   |    4 +-
 src/test/ValentinaTest/tst_vabstractpiece.cpp | 1665 +++++++++++++++++
 src/test/ValentinaTest/tst_vabstractpiece.h   |   56 +
 8 files changed, 1998 insertions(+), 3 deletions(-)
 create mode 100644 src/app/share/collection/test/seamtest1.val
 create mode 100644 src/app/share/collection/test/seamtest2.val
 create mode 100644 src/app/share/collection/test/seamtest3.val
 create mode 100644 src/test/ValentinaTest/tst_vabstractpiece.cpp
 create mode 100644 src/test/ValentinaTest/tst_vabstractpiece.h

diff --git a/src/app/share/collection/test/seamtest1.val b/src/app/share/collection/test/seamtest1.val
new file mode 100644
index 000000000..d36f80aba
--- /dev/null
+++ b/src/app/share/collection/test/seamtest1.val
@@ -0,0 +1,162 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<pattern>
+    <!--Pattern created with Valentina (http://www.valentina-project.org/).-->
+    <version>0.4.0</version>
+    <unit>cm</unit>
+    <author/>
+    <description/>
+    <notes/>
+    <measurements>merki27.vit</measurements>
+    <increments/>
+    <draw name="Чертеж 1">
+        <calculation>
+            <point type="single" x="0.79375" y="1.05833" id="1" name="А" mx="0.132292" my="0.264583"/>
+            <point type="endLine" typeLine="hair" id="2" name="А1" basePoint="1" mx="0.132292" lineColor="black" angle="270" my="0.264583" length="neck_back_to_waist_b"/>
+            <point type="endLine" typeLine="hair" id="3" name="А2" basePoint="2" mx="0.132292" lineColor="black" angle="0" my="0.264583" length="lowbust_circ/2+6"/>
+            <point type="alongLine" typeLine="none" id="4" name="А3" firstPoint="1" secondPoint="2" mx="0.0821985" lineColor="black" my="0.21449" length="lowbust_circ/12+13.7"/>
+            <point type="pointOfIntersection" id="5" name="А4" firstPoint="3" secondPoint="4" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="6" firstPoint="5" secondPoint="3" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="7" name="А5" basePoint="4" mx="0.132292" lineColor="black" angle="0" my="0.264583" length="lowbust_circ/8+7.4"/>
+            <point type="pointOfIntersection" id="8" name="А6" firstPoint="7" secondPoint="1" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="9" firstPoint="1" secondPoint="8" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="10" name="А7" firstPoint="1" secondPoint="4" mx="0.132292" lineColor="black" my="0.264583" length="8"/>
+            <point type="pointOfIntersection" id="11" name="А8" firstPoint="8" secondPoint="10" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="12" firstPoint="10" secondPoint="11" lineColor="black"/>
+            <line typeLine="hair" id="14" firstPoint="11" secondPoint="7" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="15" name="А9" firstPoint="11" secondPoint="7" mx="0.132292" lineColor="black" my="0.264583" length="(Line_А8_А5/2)+0.5"/>
+            <point type="endLine" typeLine="hair" id="16" name="А10" basePoint="5" mx="0.132292" lineColor="black" angle="90" my="0.264583" length="lowbust_circ/5+8.3+1"/>
+            <point type="endLine" typeLine="hair" id="17" name="А11" basePoint="5" mx="0.132292" lineColor="black" angle="180" my="0.264583" length="lowbust_circ/8+6.2"/>
+            <point type="pointOfIntersection" id="18" name="А12" firstPoint="17" secondPoint="16" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="19" firstPoint="18" secondPoint="17" lineColor="black"/>
+            <line typeLine="hair" id="20" firstPoint="18" secondPoint="16" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="21" name="А13" firstPoint="17" secondPoint="7" mx="0.132292" lineColor="black" my="0.264583" length="lowbust_circ/32"/>
+            <point type="pointOfIntersection" id="22" name="А14" firstPoint="21" secondPoint="15" mx="0.132292" my="0.264583"/>
+            <point type="alongLine" typeLine="none" id="23" name="А15" firstPoint="5" secondPoint="17" mx="0.182385" lineColor="black" my="0.264583" length="(Line_А4_А11/2)+0.7"/>
+            <line typeLine="hair" id="24" firstPoint="22" secondPoint="23" lineColor="black"/>
+            <line typeLine="hair" id="25" firstPoint="21" secondPoint="17" lineColor="black"/>
+            <line typeLine="hair" id="26" firstPoint="21" secondPoint="22" lineColor="black"/>
+            <line typeLine="hair" id="27" firstPoint="11" secondPoint="8" lineColor="black"/>
+            <line typeLine="hair" id="28" firstPoint="7" secondPoint="21" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="29" name="А16" firstPoint="7" secondPoint="21" mx="0.132292" lineColor="black" my="0.264583" length="Line_А5_А13/2"/>
+            <point type="pointOfIntersection" id="30" name="А17" firstPoint="29" secondPoint="2" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="31" firstPoint="29" secondPoint="30" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="32" name="А18" firstPoint="10" secondPoint="11" mx="0.132292" lineColor="black" my="0.264583" length="(Line_А7_А8/2)+1"/>
+            <point type="alongLine" typeLine="none" id="33" name="А19" firstPoint="16" secondPoint="18" mx="0.172819" lineColor="black" my="0.264583" length="lowbust_circ/24+3.4"/>
+            <point type="alongLine" typeLine="none" id="34" name="А20" firstPoint="16" secondPoint="5" mx="0.132292" lineColor="black" my="0.264583" length="Line_А10_А19+0.5"/>
+            <point type="pointOfIntersection" id="35" name="А21" firstPoint="33" secondPoint="34" mx="0.132292" my="0.264583"/>
+            <line typeLine="hair" id="38" firstPoint="35" secondPoint="16" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="39" name="А22" firstPoint="35" secondPoint="16" mx="0.132292" lineColor="black" my="0.264583" length="(Line_А21_А10/3)-0.5"/>
+            <spline point4="34" type="simpleInteractive" angle1="cos=270" angle2="sin=180" id="40" length1="4.89524" color="black" length2="4.34579" point1="33"/>
+            <line typeLine="hair" id="41" firstPoint="34" secondPoint="35" lineColor="black"/>
+            <line typeLine="hair" id="42" firstPoint="33" secondPoint="35" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="43" name="А23" firstPoint="33" secondPoint="18" mx="0.132292" lineColor="black" my="0.264583" length="8"/>
+            <point type="endLine" typeLine="none" id="44" name="А24" basePoint="43" mx="0.132292" lineColor="black" angle="270" my="0.264583" length="3.2"/>
+            <point type="lineIntersect" id="45" name="А25" p2Line1="44" p2Line2="17" p1Line1="33" p1Line2="18" mx="0.132292" my="0.264583"/>
+            <point type="alongLine" typeLine="none" id="46" name="А26" firstPoint="33" secondPoint="45" mx="0.132292" lineColor="black" my="0.264583" length="Line_А19_А25+1.8"/>
+            <point type="alongLine" typeLine="none" id="47" name="А27" firstPoint="1" secondPoint="8" mx="-0.514964" lineColor="black" my="0.552252" length="Line_А10_А19+0.2"/>
+            <point type="endLine" typeLine="hair" id="48" name="А28" basePoint="47" mx="-1.00881" lineColor="black" angle="90" my="-1.66652" length="Line_А_А27/3"/>
+            <spline point4="48" type="simpleInteractive" angle1="max=0" angle2="235.888" id="49" length1="2.42673" color="black" length2="3.03166" point1="1"/>
+            <point type="endLine" typeLine="none" id="50" name="А29" basePoint="48" mx="-0.745481" lineColor="black" angle="0" my="-1.52022" length="8"/>
+            <point type="endLine" typeLine="none" id="51" name="А30" basePoint="50" mx="0.132292" lineColor="black" angle="270" my="0.264583" length="2.6"/>
+            <point type="pointOfIntersection" id="52" name="А31" firstPoint="32" secondPoint="48" mx="-0.921036" my="-1.57874"/>
+            <point type="lineIntersect" id="53" name="А32" p2Line1="51" p2Line2="32" p1Line1="48" p1Line2="52" mx="-2.0914" my="-1.31541"/>
+            <point type="alongLine" typeLine="none" id="54" name="А33" firstPoint="53" secondPoint="51" mx="-1.82807" lineColor="black" my="0.0305105" length="1.5"/>
+            <point type="alongLine" typeLine="none" id="55" name="А34" firstPoint="54" secondPoint="51" mx="0.34558" lineColor="black" my="4.05045" length="lowbust_circ/32-0.8"/>
+            <point type="alongLine" typeLine="none" id="56" name="А35" firstPoint="48" secondPoint="51" mx="0.132292" lineColor="black" my="0.264583" length="Line_А19_А26+Line_А33_А34"/>
+            <point dartP3="55" type="trueDarts" my1="-1.63726" my2="-2.89101" id="57" mx1="-0.423631" mx2="2.30483" name1="А36" point1="58" baseLineP1="48" point2="59" name2="А37" dartP1="54" baseLineP2="56" dartP2="32"/>
+            <line typeLine="hair" id="60" firstPoint="48" secondPoint="58" lineColor="black"/>
+            <line typeLine="hair" id="61" firstPoint="32" secondPoint="58" lineColor="black"/>
+            <line typeLine="hair" id="62" firstPoint="32" secondPoint="59" lineColor="black"/>
+            <line typeLine="hair" id="63" firstPoint="59" secondPoint="56" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="64" name="А38" firstPoint="33" secondPoint="44" mx="0.132292" lineColor="black" my="0.264583" length="Line_А28_А36"/>
+            <line typeLine="hair" id="65" firstPoint="33" secondPoint="64" lineColor="black"/>
+            <line typeLine="hair" id="66" firstPoint="23" secondPoint="64" lineColor="black"/>
+            <arc type="simple" angle1="AngleLine_А15_А38" angle2="180" id="67" radius="Line_А14_А15" center="23" color="black"/>
+            <point type="cutArc" arc="67" id="68" name="А39" mx="0.132292" my="0.264583" length="lowbust_circ/12-3.2"/>
+            <point type="alongLine" typeLine="none" id="69" name="А40" firstPoint="23" secondPoint="68" mx="-1.12242" lineColor="black" my="-1.69277" length="Line_А15_А38"/>
+            <line typeLine="hair" id="70" firstPoint="23" secondPoint="69" lineColor="black"/>
+            <operation type="rotation" suffix="а1" id="71" center="23" angle="AngleLine_А15_А40-AngleLine_А15_А38">
+                <source>
+                    <item idObject="46"/>
+                </source>
+                <destination>
+                    <item idObject="72" mx="0.132292" my="0.264583"/>
+                </destination>
+            </operation>
+            <line typeLine="hair" id="73" firstPoint="69" secondPoint="72" lineColor="black"/>
+            <point type="normal" typeLine="hair" id="74" name="А41" firstPoint="56" secondPoint="59" mx="0.132292" lineColor="black" angle="0" my="0.264583" length="7"/>
+            <point type="normal" typeLine="hair" id="75" name="А42" firstPoint="72" secondPoint="69" mx="0.132292" lineColor="black" angle="180" my="0.264583" length="7"/>
+            <point type="bisector" typeLine="hair" id="77" thirdPoint="22" name="А43" firstPoint="29" secondPoint="21" mx="0.132292" lineColor="black" my="0.264583" length="Line_А5_А16/3+0.5"/>
+            <point type="bisector" typeLine="hair" id="78" thirdPoint="29" name="А44" firstPoint="15" secondPoint="7" mx="0.132292" lineColor="black" my="0.264583" length="Line_А5_А16/3+0.8"/>
+            <spline type="pathInteractive" id="100" color="black">
+                <pathPoint angle1="180.19" pSpline="29" angle2="0.189514" length1="0" length2="5.5002"/>
+                <pathPoint angle1="261.299" pSpline="22" angle2="81.2993" length1="2.57033" length2="5.3812"/>
+                <pathPoint angle1="327.914" pSpline="72" angle2="147.914" length1="8.44184" length2="13.3029"/>
+            </spline>
+            <point type="alongLine" typeLine="none" id="116" name="А45" firstPoint="11" secondPoint="15" mx="0.132292" lineColor="black" my="0.264583" length="(Line_А8_А5/2)"/>
+            <spline type="pathInteractive" id="117" color="black">
+                <pathPoint angle1="63.8459" pSpline="56" angle2="243.846" length1="0" length2="8.76616"/>
+                <pathPoint angle1="95.8866" pSpline="116" angle2="275.887" length1="1.32614" length2="2.74113"/>
+                <pathPoint angle1="180" pSpline="29" angle2="0" length1="5.03118" length2="1.36011"/>
+            </spline>
+            <operation type="moving" suffix="a1" id="149" angle="90.6703" length="40.35">
+                <source>
+                    <item idObject="117"/>
+                    <item idObject="100"/>
+                </source>
+                <destination>
+                    <item idObject="150" mx="2.14748e+09" my="2.14748e+09"/>
+                    <item idObject="151" mx="2.14748e+09" my="2.14748e+09"/>
+                </destination>
+            </operation>
+        </calculation>
+        <modeling>
+            <point type="modeling" inUse="true" id="155" idObject="4" mx="0.0821985" my="0.21449"/>
+            <point type="modeling" inUse="true" id="156" idObject="1" mx="0.132292" my="0.264583"/>
+            <spline type="modelingSpline" inUse="true" id="157" idObject="49"/>
+            <point type="modeling" inUse="true" id="158" idObject="48" mx="-1.00881" my="-1.66652"/>
+            <point type="modeling" inUse="true" id="159" idObject="58" mx="-0.423631" my="-1.63726"/>
+            <point type="modeling" inUse="true" id="160" idObject="32" mx="0.132292" my="0.264583"/>
+            <point type="modeling" inUse="true" id="161" idObject="59" mx="2.30483" my="-2.89101"/>
+            <point type="modeling" inUse="true" id="162" idObject="56" mx="0.132292" my="0.264583"/>
+            <spline type="modelingPath" inUse="true" id="163" idObject="117"/>
+            <point type="modeling" inUse="true" id="164" idObject="29" mx="0.132292" my="0.264583"/>
+        </modeling>
+        <details>
+            <detail id="165" name="" forbidFlipping="true" seamAllowance="true" mx="1.41527" inLayout="true" width="1" my="3.02812" version="2">
+                <nodes>
+                    <node before="2" type="NodePoint" after="0" idObject="155"/>
+                    <node before="0" type="NodePoint" idObject="156"/>
+                    <node type="NodeSpline" reverse="0" idObject="157"/>
+                    <node type="NodePoint" after="0" idObject="158"/>
+                    <node before="0" type="NodePoint" idObject="159"/>
+                    <node type="NodePoint" idObject="160"/>
+                    <node type="NodePoint" after="0" idObject="161"/>
+                    <node before="0" type="NodePoint" after="5" idObject="162"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="163"/>
+                    <node before="5" type="NodePoint" after="0" idObject="164"/>
+                </nodes>
+            </detail>
+        </details>
+        <groups/>
+    </draw>
+    <draw name="Чертеж 2">
+        <calculation>
+            <point type="single" x="36.3125" y="34.6144" id="141" name="Б" mx="0.132292" my="0.264583"/>
+            <point type="endLine" typeLine="hair" id="142" name="Б1" basePoint="141" mx="0.132292" lineColor="black" angle="0" my="0.264583" length="Line_А5_А16"/>
+            <point type="endLine" typeLine="hair" id="143" name="Б2" basePoint="141" mx="0.132292" lineColor="black" angle="90" my="0.264583" length="Line_А8_А5/2"/>
+            <point type="endLine" typeLine="hair" id="144" name="Б3" basePoint="143" mx="0.132292" lineColor="black" angle="90" my="0.264583" length="Line_Б_Б2"/>
+            <point type="endLine" typeLine="hair" id="145" name="Б4" basePoint="144" mx="0.132292" lineColor="black" angle="180" my="0.264583" length="Line_А18_А8"/>
+            <point type="endLine" typeLine="hair" id="146" name="Б5" basePoint="145" mx="0.132292" lineColor="black" angle="AngleLine_А18_А37" my="0.264583" length="Line_А18_А37"/>
+            <point type="endLine" typeLine="hair" id="147" name="Б6" basePoint="146" mx="0.132292" lineColor="black" angle="AngleLine_А37_А35" my="0.264583" length="Line_А37_А35"/>
+            <spline type="pathInteractive" id="148" color="black">
+                <pathPoint angle1="64.6053" pSpline="147" angle2="243.846" length1="0" length2="8.76616"/>
+                <pathPoint angle1="Angle2SplPath_А35_А16_Seg_1" pSpline="143" angle2="275.887" length1="C2LengthSplPath_А35_А16_Seg_1" length2="2.74113"/>
+                <pathPoint angle1="Angle2SplPath_А35_А16" pSpline="142" angle2="0.12" length1="4.97078" length2="1.36701"/>
+            </spline>
+        </calculation>
+        <modeling/>
+        <details/>
+        <groups/>
+    </draw>
+</pattern>
diff --git a/src/app/share/collection/test/seamtest2.val b/src/app/share/collection/test/seamtest2.val
new file mode 100644
index 000000000..751483d4e
--- /dev/null
+++ b/src/app/share/collection/test/seamtest2.val
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<pattern>
+    <!--Pattern created with Valentina (http://www.valentina-project.org/).-->
+    <version>0.4.0</version>
+    <unit>cm</unit>
+    <author/>
+    <description/>
+    <notes/>
+    <measurements/>
+    <increments/>
+    <draw name="Pattern piece 1">
+        <calculation>
+            <point type="single" x="0.79375" y="1.05833" id="1" name="A" mx="0.132292" my="0.264583"/>
+            <point type="endLine" typeLine="hair" id="2" name="A1" basePoint="1" mx="0.132292" lineColor="black" my="0.264583" angle="0" length="10"/>
+            <point type="normal" typeLine="hair" id="3" name="A2" firstPoint="2" secondPoint="1" mx="0.132292" lineColor="black" my="0.264583" angle="0" length="5"/>
+            <point type="alongLine" typeLine="none" id="4" name="A3" firstPoint="1" secondPoint="3" mx="0.132292" lineColor="black" my="0.264583" length="CurrentLength/2"/>
+            <spline type="simpleInteractive" point4="3" angle1="236.89" angle2="209.202" id="5" color="black" length1="1.06381" length2="2.9538" point1="4"/>
+            <spline type="simpleInteractive" point4="4" angle1="241.792" angle2="241.791" id="6" color="black" length1="2.22517" length2="2.12741" point1="1"/>
+        </calculation>
+        <modeling>
+            <point type="modeling" inUse="true" id="12" idObject="1" mx="0.132292" my="0.264583"/>
+            <point type="modeling" inUse="true" id="13" idObject="2" mx="0.132292" my="0.264583"/>
+            <point type="modeling" inUse="true" id="14" idObject="3" mx="0.132292" my="0.264583"/>
+            <spline type="modelingSpline" inUse="true" id="15" idObject="5"/>
+            <point type="modeling" inUse="true" id="16" idObject="4" mx="0.132292" my="0.264583"/>
+            <spline type="modelingSpline" inUse="true" id="17" idObject="6"/>
+        </modeling>
+        <details>
+            <detail id="18" name="" forbidFlipping="true" seamAllowance="true" mx="0" inLayout="true" width="1" my="0" version="2">
+                <nodes>
+                    <node type="NodePoint" idObject="12"/>
+                    <node type="NodePoint" idObject="13"/>
+                    <node type="NodePoint" idObject="14"/>
+                    <node type="NodeSpline" reverse="1" idObject="15"/>
+                    <node before="1.01" type="NodePoint" after="1.01" idObject="16"/>
+                    <node type="NodeSpline" reverse="1" idObject="17"/>
+                </nodes>
+            </detail>
+        </details>
+        <groups/>
+    </draw>
+</pattern>
diff --git a/src/app/share/collection/test/seamtest3.val b/src/app/share/collection/test/seamtest3.val
new file mode 100644
index 000000000..2141cf046
--- /dev/null
+++ b/src/app/share/collection/test/seamtest3.val
@@ -0,0 +1,57 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<pattern>
+    <!--Pattern created with Valentina (http://www.valentina-project.org/).-->
+    <version>0.4.0</version>
+    <unit>cm</unit>
+    <author/>
+    <description/>
+    <notes/>
+    <measurements/>
+    <increments/>
+    <draw name="Pattern piece 1">
+        <calculation>
+            <point type="single" x="0.79375" y="1.05833" id="1" name="A" mx="0.132292" my="0.264583"/>
+            <point type="endLine" typeLine="hair" id="2" name="A1" basePoint="1" mx="0.132292" lineColor="black" my="0.264583" angle="0" length="10"/>
+            <point type="normal" typeLine="hair" id="3" name="A2" firstPoint="2" secondPoint="1" mx="0.132292" lineColor="black" my="0.264583" angle="0" length="5"/>
+            <point type="alongLine" typeLine="none" id="4" name="A3" firstPoint="1" secondPoint="3" mx="0.132292" lineColor="black" my="0.264583" length="CurrentLength/2"/>
+            <point type="alongLine" typeLine="none" id="5" name="A4" firstPoint="4" secondPoint="3" mx="0.132292" lineColor="black" my="0.264583" length="CurrentLength/2"/>
+            <point type="alongLine" typeLine="none" id="6" name="A5" firstPoint="1" secondPoint="4" mx="0.132292" lineColor="black" my="0.264583" length="CurrentLength/2"/>
+            <spline type="pathInteractive" id="7" color="black">
+                <pathPoint angle1="65.3764" pSpline="3" angle2="245.376" length1="0" length2="2.1538"/>
+                <pathPoint angle1="248.531" pSpline="5" angle2="68.531" length1="1.80107" length2="2.63289"/>
+                <pathPoint angle1="42.0794" pSpline="4" angle2="222.079" length1="0.714555" length2="3.76242"/>
+                <pathPoint angle1="50.1229" pSpline="6" angle2="230.123" length1="2.19303" length2="2.72501"/>
+                <pathPoint angle1="228.872" pSpline="1" angle2="48.872" length1="0.486869" length2="0"/>
+            </spline>
+        </calculation>
+        <modeling>
+            <point type="modeling" inUse="true" id="8" idObject="1" mx="0.132292" my="0.264583"/>
+            <point type="modeling" inUse="true" id="9" idObject="2" mx="0.132292" my="0.264583"/>
+            <point type="modeling" inUse="true" id="10" idObject="3" mx="0.132292" my="0.264583"/>
+            <spline type="modelingPath" inUse="true" id="11" idObject="7"/>
+            <point type="modeling" inUse="true" id="12" idObject="5" mx="0.132292" my="0.264583"/>
+            <spline type="modelingPath" inUse="true" id="13" idObject="7"/>
+            <point type="modeling" inUse="true" id="14" idObject="4" mx="0.132292" my="0.264583"/>
+            <spline type="modelingPath" inUse="true" id="15" idObject="7"/>
+            <point type="modeling" inUse="true" id="16" idObject="6" mx="0.132292" my="0.264583"/>
+            <spline type="modelingPath" inUse="true" id="17" idObject="7"/>
+        </modeling>
+        <details>
+            <detail id="18" name="" forbidFlipping="true" seamAllowance="true" mx="0" inLayout="true" width="1" my="0" version="2">
+                <nodes>
+                    <node type="NodePoint" idObject="8"/>
+                    <node type="NodePoint" idObject="9"/>
+                    <node type="NodePoint" idObject="10"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="11"/>
+                    <node before="0.5" type="NodePoint" after="0.5" idObject="12"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="13"/>
+                    <node type="NodePoint" idObject="14"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="15"/>
+                    <node before="0.2" type="NodePoint" idObject="16"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="17"/>
+                </nodes>
+            </detail>
+        </details>
+        <groups/>
+    </draw>
+</pattern>
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index dbe5b625e..59fb95c5d 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -52,6 +52,7 @@ class VSAPoint : public QPointF
 {
 public:
     Q_DECL_CONSTEXPR VSAPoint();
+    Q_DECL_CONSTEXPR VSAPoint(qreal xpos, qreal ypos);
     Q_DECL_CONSTEXPR VSAPoint(const QPointF &p);
 
     Q_DECL_CONSTEXPR qreal GetSABefore() const;
@@ -65,6 +66,7 @@ private:
     qreal m_after;
 };
 
+Q_DECLARE_METATYPE(VSAPoint)
 Q_DECLARE_TYPEINFO(VSAPoint, Q_MOVABLE_TYPE);
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -74,6 +76,13 @@ Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint()
       m_after(-1)
 {}
 
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint(qreal xpos, qreal ypos)
+    : QPointF(xpos, ypos),
+      m_before(-1),
+      m_after(-1)
+{}
+
 //---------------------------------------------------------------------------------------------------------------------
 Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint(const QPointF &p)
     : QPointF(p),
diff --git a/src/test/ValentinaTest/ValentinaTest.pro b/src/test/ValentinaTest/ValentinaTest.pro
index 3f5c649de..121816100 100644
--- a/src/test/ValentinaTest/ValentinaTest.pro
+++ b/src/test/ValentinaTest/ValentinaTest.pro
@@ -53,7 +53,8 @@ SOURCES += \
     tst_vcubicbezierpath.cpp \
     tst_vgobject.cpp \
     tst_vsplinepath.cpp \
-    tst_vpointf.cpp
+    tst_vpointf.cpp \
+    tst_vabstractpiece.cpp
 
 win32-msvc*:SOURCES += stable.cpp
 
@@ -77,7 +78,8 @@ HEADERS += \
     tst_vcubicbezierpath.h \
     tst_vgobject.h \
     tst_vsplinepath.h \
-    tst_vpointf.h
+    tst_vpointf.h \
+    tst_vabstractpiece.h
 
 # Set using ccache. Function enable_ccache() defined in common.pri.
 $$enable_ccache()
diff --git a/src/test/ValentinaTest/qttestmainlambda.cpp b/src/test/ValentinaTest/qttestmainlambda.cpp
index 02cf31d74..2ec5cc81d 100644
--- a/src/test/ValentinaTest/qttestmainlambda.cpp
+++ b/src/test/ValentinaTest/qttestmainlambda.cpp
@@ -30,6 +30,7 @@
 
 #include "tst_vposter.h"
 #include "tst_vabstractdetail.h"
+#include "tst_vabstractpiece.h"
 #include "tst_vspline.h"
 #include "tst_nameregexp.h"
 #include "tst_vlayoutdetail.h"
@@ -66,7 +67,8 @@ int main(int argc, char** argv)
     ASSERT_TEST(new TST_FindPoint());
     ASSERT_TEST(new TST_VDetail());
     ASSERT_TEST(new TST_VPoster());
-    ASSERT_TEST(new TST_VAbstractDetail());
+    //ASSERT_TEST(new TST_VAbstractDetail());
+    ASSERT_TEST(new TST_VAbstractPiece());
     ASSERT_TEST(new TST_VSpline());
     ASSERT_TEST(new TST_VSplinePath());
     ASSERT_TEST(new TST_NameRegExp());
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp
new file mode 100644
index 000000000..fc8f67453
--- /dev/null
+++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp
@@ -0,0 +1,1665 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   17 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "tst_vabstractpiece.h"
+#include "../vlayout/vabstractpiece.h"
+
+#include <QPointF>
+#include <QVector>
+
+#include <QtTest>
+
+//---------------------------------------------------------------------------------------------------------------------
+TST_VAbstractPiece::TST_VAbstractPiece(QObject *parent)
+    : AbstractTest(parent)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::EquidistantRemoveLoop_data()
+{
+    QTest::addColumn<QVector<VSAPoint>>("points");
+    QTest::addColumn<qreal>("width");
+    QTest::addColumn<QVector<QPointF>>("ekvOrig");
+
+    // See file src/app/share/collection/test/seamtest1.val
+    QTest::newRow("Seam test 1") << InputPointsCase1()
+                                 << 37.795275590551185 // seam allowance width
+                                 << OutputPointsCase1();
+
+    // See file src/app/share/collection/test/seamtest2.val
+    QTest::newRow("Seam test 2") << InputPointsCase2()
+                                 << 37.795275590551185 // seam allowance width
+                                 << OutputPointsCase2();
+
+    // See file src/app/share/collection/test/seamtest3.val
+    QTest::newRow("Seam test 3") << InputPointsCase3()
+                                 << 37.795275590551185 // seam allowance width
+                                 << OutputPointsCase3();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::EquidistantRemoveLoop() const
+{
+    QFETCH(QVector<VSAPoint>, points);
+    QFETCH(qreal, width);
+    QFETCH(QVector<QPointF>, ekvOrig);
+
+    const QVector<QPointF> ekv = VAbstractPiece::Equidistant(points, width);
+
+    // Begin comparison
+    Comparison(ekv, ekvOrig);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsCase1() const
+{
+
+    QVector<VSAPoint> points;
+
+    VSAPoint p = VSAPoint(30.0, 894.8030236220472);
+    p.SetSAAfter(0);
+    p.SetSABefore(75.59055118110237);
+    points.append(p);
+
+    p = VSAPoint(30.0, 39.999874015748034);
+    //////p.SetSAAfter(-1);
+    p.SetSABefore(0);
+    points.append(p);
+
+    p = VSAPoint(30.0, 39.999874015748034);
+    //////p.SetSAAfter(-1);
+    p.SetSABefore(0);
+    points.append(p);
+
+    p = VSAPoint(47.64159471849116, 39.94788491648882);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(76.58589406160007, 39.22029871626823);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(96.8510955083063, 38.214779786537555);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(117.72526111352542, 36.63514697516433);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(139.00155591749595, 34.36192982961571);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(160.47314496045635, 31.27565789735886);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(181.9331932826451, 27.25686072586095);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(203.17486592430072, 22.18606786258914);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(223.99132792566166, 15.943808855010598);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(239.1756066691363, 10.378329140641144);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(249.07102191481937, 6.266596479372291);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(258.7437898355629, 1.7947951524770347);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(268.16805606139667, -3.0520086466112275);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(277.3179662223507, -8.2887487244591);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(286.16766594845456, -13.93035888763319);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(294.69130086973814, -19.991772942700095);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(302.86301661623133, -26.48792469622643);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(310.6569588179638, -33.433747954778795);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(318.04727310496537, -40.84417652492378);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(325.00810510726603, -48.73414421322801);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(331.51360045489537, -57.118584826258086);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(334.56692913385825, -61.522435695538036);
+    p.SetSAAfter(0);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(334.56692913385825, -61.522435695538036);
+    p.SetSAAfter(0);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(519.4465667350105, -36.01405338211436);
+    //////p.SetSAAfter(-1);
+    p.SetSABefore(0);
+    points.append(p);
+
+    p = VSAPoint(460.3937007874016, 342.36207874015753);
+    //////p.SetSAAfter(-1);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(620.5290071875437, -5.50631876178551);
+    p.SetSAAfter(0);
+    //////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(944.2945933263424, 136.63905516701567);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(0);
+    points.append(p);
+
+    p = VSAPoint(944.2945933263424, 136.63905516701567);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(0);
+    points.append(p);
+
+    p = VSAPoint(937.525981220313, 150.5000566598672);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(924.7444201119979, 177.43472401968558);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(912.8425448338431, 203.43742191080565);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(901.7902332810357, 228.52240953585334);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(891.5573633487625, 252.7039460974546);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(882.1138129322104, 275.99629079823535);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(869.2733175133695, 309.4054580978942);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(854.7606685168345, 350.82610676604395);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(842.8630996965477, 388.94665363817853);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(833.3396342140044, 423.88117233530545);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(825.9492952306994, 455.7437364784321);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(820.4511059081283, 484.6484196885659);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(816.6040894077858, 510.7092955867147);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(814.1672688911672, 534.0404377938855);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(812.8996675197675, 554.7559199310863);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(812.5603084550817, 572.9698156193242);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(812.9082148586052, 588.7961984796068);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(814.1809574610598, 608.5715133604979);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(815.1968503937007, 618.5825511811024);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(815.1968503937007, 618.5825511811024);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(815.7375399808675, 623.4475087782134);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(817.2456173381056, 633.4974833757362);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(819.2665464515061, 643.8914388413946);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(821.8012316951542, 654.584830268716);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(824.8505774431355, 665.5331127512278);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(828.4154880695357, 676.6917413824576);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(832.4968679484402, 688.0161712559327);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(837.0956214539344, 699.4618574651809);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(842.212652960104, 710.9842551037295);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(847.8488668410344, 722.5388192651058);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(854.0051674708111, 734.0810050428374);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(860.6824592235198, 745.5662675304518);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(867.8816464732456, 756.9500618214765);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(875.6036335940746, 768.187843009439);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(883.8493249600917, 779.2350661878667);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(892.6196249453828, 790.0471864502871);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(901.9154379240335, 800.5796588902277);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(911.7376682701291, 810.7879386012161);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(922.0872203577552, 820.6274806767794);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(932.9649985609971, 830.0537402104453);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(944.3719072539405, 839.0221722957415);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(956.3088508106711, 847.4882320261951);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(968.776733605274, 855.4073744953336);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(981.7764600118351, 862.7350547966848);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(995.3089344044396, 869.4267280237759);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1009.3750611571733, 875.4378492701345);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1023.9757446441214, 880.7238736292878);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1039.1118892393697, 885.2402561947638);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1054.784399317004, 888.9424520600894);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1070.994179251109, 891.7859163187926);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1087.7421334157707, 893.7261040644007);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1105.0291661850742, 894.7184703904409);
+    p.SetSAAfter(188.97637795275591);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1113.8976377952758, 894.8030236220472);
+    p.SetSAAfter(0);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    p = VSAPoint(1113.8976377952758, 894.8030236220472);
+    p.SetSAAfter(0);
+    p.SetSABefore(188.97637795275591);
+    points.append(p);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsCase1() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(30.0, 970.3935748031496);
+    points += QPointF(30.0, 2.1993068570824366);
+    points += QPointF(114.18582053395916, -1.0122621856204752);
+    points += QPointF(193.32267013775137, -14.358819619401812);
+    points += QPointF(242.10707671244683, -32.17908690671806);
+    points += QPointF(271.8971162152593, -50.207724037690014);
+    points += QPointF(295.9981384039675, -73.05193874264779);
+    points += QPointF(291.7916402578659, -67.42426694301096);
+    points += QPointF(556.8930273120665, -30.847456102511416);
+    points += QPointF(539.6101141051189, 79.89131577778163);
+    points += QPointF(585.9167315845334, -20.702420721823447);
+    points += QPointF(1117.424153174025, 212.64949937811681);
+    points += QPointF(1075.303535889726, 303.4417262358707);
+    points += QPointF(1034.367455532369, 409.91489458521534);
+    points += QPointF(1016.7086496269483, 470.1391211588565);
+    points += QPointF(1002.6502749276095, 549.8913110678527);
+    points += QPointF(1002.7092529129402, 594.4292010581551);
+    points += QPointF(1004.1768887194628, 604.1457258376107);
+    points += QPointF(1009.2070121912753, 620.6931338009274);
+    points += QPointF(1019.1613725437678, 641.9748709736807);
+    points += QPointF(1033.0209611044565, 662.9678611314132);
+    points += QPointF(1049.114087400246, 680.4406818558615);
+    points += QPointF(1065.8570577426399, 692.968441452634);
+    points += QPointF(1083.1677152645557, 700.9292457138567);
+    points += QPointF(1105.2479226099044, 705.3103889738845);
+    points += QPointF(1290.6502488400083, 712.9440934612204);
+    points += QPointF(1302.4161318705774, 881.6558256043734);
+    points += QPointF(30.0, 970.3935748031496);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsCase2() const
+{
+
+    QVector<VSAPoint> points;
+
+    VSAPoint p = VSAPoint(30.0, 39.999874015748034);
+    ////p.SetSAAfter(-1);
+    ////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 39.999874015748034);
+    ////p.SetSAAfter(-1);
+    ////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 228.97625196850396);
+    ////p.SetSAAfter(-1);
+    ////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 228.97625196850396);
+    ////p.SetSAAfter(-1);
+    ////p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(403.3769166670402, 231.4465511704684);
+    p.SetSAAfter(37.803178025111038);
+    p.SetSABefore(37.803178025111038);
+    points.append(p);
+
+    p = VSAPoint(394.1607984354165, 235.58132461572228);
+    p.SetSAAfter(37.818528535007879);
+    p.SetSABefore(37.818528535007879);
+    points.append(p);
+
+    p = VSAPoint(384.8923171505302, 238.7905285112787);
+    p.SetSAAfter(37.833434086432739);
+    p.SetSABefore(37.833434086432739);
+    points.append(p);
+
+    p = VSAPoint(375.59921131499664, 241.12018552459608);
+    p.SetSAAfter(37.847993627262561);
+    p.SetSABefore(37.847993627262561);
+    points.append(p);
+
+    p = VSAPoint(366.3092194314313, 242.61631832313287);
+    p.SetSAAfter(37.862293350550544);
+    p.SetSABefore(37.862293350550544);
+    points.append(p);
+
+    p = VSAPoint(357.0500800024495, 243.3249495743475);
+    p.SetSAAfter(37.876405426208798);
+    p.SetSABefore(37.876405426208798);
+    points.append(p);
+
+    p = VSAPoint(347.8495315306667, 243.2921019456984);
+    p.SetSAAfter(37.890387402651413);
+    p.SetSABefore(37.890387402651413);
+    points.append(p);
+
+    p = VSAPoint(338.73531251869827, 242.56379810464406);
+    p.SetSAAfter(37.904282247411182);
+    p.SetSABefore(37.904282247411182);
+    points.append(p);
+
+    p = VSAPoint(329.7351614691596, 241.18606071864286);
+    p.SetSAAfter(37.91811891950119);
+    p.SetSABefore(37.91811891950119);
+    points.append(p);
+
+    p = VSAPoint(320.876816884666, 239.20491245515328);
+    p.SetSAAfter(37.931913327979281);
+    p.SetSABefore(37.931913327979281);
+    points.append(p);
+
+    p = VSAPoint(312.18801726783295, 236.6663759816338);
+    p.SetSAAfter(37.945669528152067);
+    p.SetSABefore(37.945669528152067);
+    points.append(p);
+
+    p = VSAPoint(303.6965011212758, 233.61647396554275);
+    p.SetSAAfter(37.959381027682795);
+    p.SetSABefore(37.959381027682795);
+    points.append(p);
+
+    p = VSAPoint(295.43000694760997, 230.10122907433865);
+    p.SetSAAfter(37.973032106608528);
+    p.SetSABefore(37.973032106608528);
+    points.append(p);
+
+    p = VSAPoint(287.41627324945074, 226.16666397547993);
+    p.SetSAAfter(37.986599088053786);
+    p.SetSABefore(37.986599088053786);
+    points.append(p);
+
+    p = VSAPoint(279.6830385294136, 221.85880133642502);
+    p.SetSAAfter(38.000051524725791);
+    p.SetSABefore(38.000051524725791);
+    points.append(p);
+
+    p = VSAPoint(272.2580412901139, 217.2236638246324);
+    p.SetSAAfter(38.013353288194111);
+    p.SetSABefore(38.013353288194111);
+    points.append(p);
+
+    p = VSAPoint(265.16902003416703, 212.3072741075605);
+    p.SetSAAfter(38.026463563868212);
+    p.SetSABefore(38.026463563868212);
+    points.append(p);
+
+    p = VSAPoint(258.44371326418843, 207.15565485266765);
+    p.SetSAAfter(38.03933776597485);
+    p.SetSABefore(38.03933776597485);
+    points.append(p);
+
+    p = VSAPoint(252.1098594827934, 201.81482872741242);
+    p.SetSAAfter(38.051928395587325);
+    p.SetSABefore(38.051928395587325);
+    points.append(p);
+
+    p = VSAPoint(246.19519719259745, 196.33081839925325);
+    p.SetSAAfter(38.064185872874937);
+    p.SetSABefore(38.064185872874937);
+    points.append(p);
+
+    p = VSAPoint(240.72746489621585, 190.74964653564848);
+    p.SetSAAfter(38.076059384395691);
+    p.SetSABefore(38.076059384395691);
+    points.append(p);
+
+    p = VSAPoint(235.73440109626404, 185.11733580405664);
+    p.SetSAAfter(38.087497800100167);
+    p.SetSABefore(38.087497800100167);
+    points.append(p);
+
+    p = VSAPoint(231.24374429535737, 179.47990887193612);
+    p.SetSAAfter(38.098450736467157);
+    p.SetSABefore(38.098450736467157);
+    points.append(p);
+
+    p = VSAPoint(227.2832329961113, 173.88338840674544);
+    p.SetSAAfter(38.108869877607624);
+    p.SetSABefore(38.108869877607624);
+    points.append(p);
+
+    p = VSAPoint(223.88060570114112, 168.37379707594295);
+    p.SetSAAfter(38.118710724548052);
+    p.SetSABefore(38.118710724548052);
+    points.append(p);
+
+    p = VSAPoint(221.06360091306237, 162.99715754698713);
+    p.SetSAAfter(38.127935039089436);
+    p.SetSABefore(38.127935039089436);
+    points.append(p);
+
+    p = VSAPoint(218.8599571344903, 157.79949248733644);
+    p.SetSAAfter(38.136514404353001);
+    p.SetSABefore(38.136514404353001);
+    points.append(p);
+
+    p = VSAPoint(217.2974128680403, 152.82682456444928);
+    p.SetSAAfter(38.144435562325597);
+    p.SetSABefore(38.144435562325597);
+    points.append(p);
+
+    p = VSAPoint(216.40370661632784, 148.12517644578412);
+    p.SetSAAfter(38.15170849722444);
+    p.SetSABefore(38.15170849722444);
+    points.append(p);
+
+    p = VSAPoint(216.20657688196826, 143.7405707987994);
+    p.SetSAAfter(38.158378424653918);
+    p.SetSABefore(38.158378424653918);
+    points.append(p);
+
+    p = VSAPoint(216.7337621675769, 139.71903029095353);
+    p.SetSAAfter(38.164542166418755);
+    p.SetSABefore(38.164542166418755);
+    points.append(p);
+
+    p = VSAPoint(218.01300097576927, 136.10657758970495);
+    p.SetSAAfter(38.17036598425517);
+    p.SetSABefore(38.17036598425517);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(38.173228346456696);
+    p.SetSABefore(38.173228346456696);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(38.173228346456696);
+    p.SetSABefore(38.173228346456696);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(38.173228346456696);
+    p.SetSABefore(38.173228346456696);
+    points.append(p);
+
+    p = VSAPoint(217.1202289172026, 137.73030103616844);
+    p.SetSAAfter(38.167995197589178);
+    p.SetSABefore(38.167995197589178);
+    points.append(p);
+
+    p = VSAPoint(212.6973363405255, 143.4397404435662);
+    p.SetSAAfter(38.157878743288215);
+    p.SetSABefore(38.157878743288215);
+    points.append(p);
+
+    p = VSAPoint(207.48487786706698, 148.24866810991395);
+    p.SetSAAfter(38.147944713012919);
+    p.SetSABefore(38.147944713012919);
+    points.append(p);
+
+    p = VSAPoint(201.55301739671896, 152.18989767496004);
+    p.SetSAAfter(38.137968823998783);
+    p.SetSABefore(38.137968823998783);
+    points.append(p);
+
+    p = VSAPoint(194.9719188293733, 155.29624277845284);
+    p.SetSAAfter(38.127775030254007);
+    p.SetSABefore(38.127775030254007);
+    points.append(p);
+
+    p = VSAPoint(187.81174606492203, 157.6005170601407);
+    p.SetSAAfter(38.117238836985599);
+    p.SetSABefore(38.117238836985599);
+    points.append(p);
+
+    p = VSAPoint(180.14266300325704, 159.13553415977202);
+    p.SetSAAfter(38.106283289982827);
+    p.SetSABefore(38.106283289982827);
+    points.append(p);
+
+    p = VSAPoint(172.0348335442702, 159.93410771709506);
+    p.SetSAAfter(38.094871286509886);
+    p.SetSABefore(38.094871286509886);
+    points.append(p);
+
+    p = VSAPoint(163.55842158785353, 160.02905137185826);
+    p.SetSAAfter(38.082997200945435);
+    p.SetSABefore(38.082997200945435);
+    points.append(p);
+
+    p = VSAPoint(154.78359103389897, 159.4531787638099);
+    p.SetSAAfter(38.070679409075119);
+    p.SetSABefore(38.070679409075119);
+    points.append(p);
+
+    p = VSAPoint(145.78050578229832, 158.23930353269841);
+    p.SetSAAfter(38.057954219352141);
+    p.SetSABefore(38.057954219352141);
+    points.append(p);
+
+    p = VSAPoint(136.61932973294367, 156.42023931827214);
+    p.SetSAAfter(38.044871166362007);
+    p.SetSABefore(38.044871166362007);
+    points.append(p);
+
+    p = VSAPoint(127.37022678572683, 154.0287997602794);
+    p.SetSAAfter(38.031489421641503);
+    p.SetSABefore(38.031489421641503);
+    points.append(p);
+
+    p = VSAPoint(118.10336084053982, 151.09779849846862);
+    p.SetSAAfter(38.017875048227786);
+    p.SetSABefore(38.017875048227786);
+    points.append(p);
+
+    p = VSAPoint(108.88889579727454, 147.66004917258803);
+    p.SetSAAfter(38.00409885919936);
+    p.SetSABefore(38.00409885919936);
+    points.append(p);
+
+    p = VSAPoint(99.79699555582292, 143.7483654223861);
+    p.SetSAAfter(37.990234686678903);
+    p.SetSABefore(37.990234686678903);
+    points.append(p);
+
+    p = VSAPoint(90.8978240160769, 139.3955608876111);
+    p.SetSAAfter(37.976357907221328);
+    p.SetSABefore(37.976357907221328);
+    points.append(p);
+
+    p = VSAPoint(82.26154507792839, 134.63444920801146);
+    p.SetSAAfter(37.962544096747962);
+    p.SetSABefore(37.962544096747962);
+    points.append(p);
+
+    p = VSAPoint(73.95832264126932, 129.49784402333552);
+    p.SetSAAfter(37.94886770258455);
+    p.SetSABefore(37.94886770258455);
+    points.append(p);
+
+    p = VSAPoint(66.05832060599164, 124.01855897333157);
+    p.SetSAAfter(37.935400622146403);
+    p.SetSABefore(37.935400622146403);
+    points.append(p);
+
+    p = VSAPoint(58.63170287198729, 118.22940769774803);
+    p.SetSAAfter(37.922210567500777);
+    p.SetSABefore(37.922210567500777);
+    points.append(p);
+
+    p = VSAPoint(51.74863333914817, 112.16320383633325);
+    p.SetSAAfter(37.90935907207141);
+    p.SetSABefore(37.90935907207141);
+    points.append(p);
+
+    p = VSAPoint(45.47927590736623, 105.85276102883554);
+    p.SetSAAfter(37.896898960241472);
+    p.SetSABefore(37.896898960241472);
+    points.append(p);
+
+    p = VSAPoint(39.8937944765334, 99.33089291500332);
+    p.SetSAAfter(37.884871055952601);
+    p.SetSABefore(37.884871055952601);
+    points.append(p);
+
+    p = VSAPoint(35.062352946541615, 92.63041313458488);
+    p.SetSAAfter(37.873299866072891);
+    p.SetSABefore(37.873299866072891);
+    points.append(p);
+
+    p = VSAPoint(31.055115217282804, 85.78413532732864);
+    p.SetSAAfter(37.86218797621639);
+    p.SetSABefore(37.86218797621639);
+    points.append(p);
+
+    p = VSAPoint(27.94224518864889, 78.82487313298289);
+    p.SetSAAfter(37.851509027526909);
+    p.SetSABefore(37.851509027526909);
+    points.append(p);
+
+    p = VSAPoint(25.793906760531815, 71.78544019129603);
+    p.SetSAAfter(37.841199561247805);
+    p.SetSABefore(37.841199561247805);
+    points.append(p);
+
+    p = VSAPoint(24.68026383282351, 64.69865014201642);
+    p.SetSAAfter(37.831150915024352);
+    p.SetSABefore(37.831150915024352);
+    points.append(p);
+
+    p = VSAPoint(24.671480305415898, 57.597316624892386);
+    p.SetSAAfter(37.821203708860601);
+    p.SetSABefore(37.821203708860601);
+    points.append(p);
+
+    p = VSAPoint(25.837720078200917, 50.514253279672296);
+    p.SetSAAfter(37.811148513024627);
+    p.SetSABefore(37.811148513024627);
+    points.append(p);
+
+    p = VSAPoint(28.2491470510705, 43.48227374610451);
+    p.SetSAAfter(37.800735391906976);
+    p.SetSABefore(37.800735391906976);
+    points.append(p);
+
+    p = VSAPoint(30.0, 39.999874015748034);
+    ////p.SetSAAfter(-1);
+    ////p.SetSABefore(-1);
+    points.append(p);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsCase2() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(6.735602739585184, 2.204598425196849);
+    points += QPointF(445.748031496063, 2.204598425196849);
+    points += QPointF(445.748031496063, 252.741597064484);
+    points += QPointF(407.8726873421697, 270.9512393848742);
+    points += QPointF(383.35720786819263, 278.3073990947694);
+    points += QPointF(358.56601090183574, 281.29234689511463);
+    points += QPointF(311.52157429670274, 276.0460457687877);
+    points += QPointF(269.8658512160491, 259.9136567147091);
+    points += QPointF(234.63885608185402, 236.87965105367914);
+    points += QPointF(206.54666866938726, 209.66914671340476);
+    points += QPointF(196.38622691315896, 194.30278046741873);
+    points += QPointF(185.94813049770778, 196.9895807275079);
+    points += QPointF(139.55536916394507, 195.8595124134453);
+    points += QPointF(94.68200851242605, 182.9587775062589);
+    points += QPointF(53.04420235483193, 161.22643763678528);
+    points += QPointF(17.41948377984963, 131.4802352488134);
+    points += QPointF(3.037173945815, 113.17182142233789);
+    points += QPointF(-7.8903334763093635, 91.91076010344419);
+    points += QPointF(-13.507576311258223, 67.42815708759109);
+    points += QPointF(-11.452400232028667, 42.67167813028373);
+    points += QPointF(6.735602739585184, 2.204598425196849);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsCase3() const
+{
+    QVector<VSAPoint> points;
+
+    VSAPoint p = VSAPoint(30.0, 39.999874015748034);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 39.999874015748034);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 228.97625196850396);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(407.9527559055118, 228.97625196850396);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(406.33770829042953, 232.38064611626584);
+    p.SetSAAfter(37.381380099110068);
+    p.SetSABefore(37.381380099110068);
+    points.append(p);
+
+    p = VSAPoint(402.870644734503, 238.5569810399819);
+    p.SetSAAfter(36.603370955765051);
+    p.SetSABefore(36.603370955765051);
+    points.append(p);
+
+    p = VSAPoint(399.14591058639644, 243.99520937172397);
+    p.SetSAAfter(35.879339211886929);
+    p.SetSABefore(35.879339211886929);
+    points.append(p);
+
+    p = VSAPoint(395.19316295581496, 248.71848383837556);
+    p.SetSAAfter(35.202813177025682);
+    p.SetSABefore(35.202813177025682);
+    points.append(p);
+
+    p = VSAPoint(391.04205895246355, 252.7499571668203);
+    p.SetSAAfter(34.56719781657663);
+    p.SetSABefore(34.56719781657663);
+    points.append(p);
+
+    p = VSAPoint(386.72225568604733, 256.1127820839417);
+    p.SetSAAfter(33.965870279175178);
+    p.SetSABefore(33.965870279175178);
+    points.append(p);
+
+    p = VSAPoint(382.2634102662714, 258.8301113166233);
+    p.SetSAAfter(33.392312673818843);
+    p.SetSABefore(33.392312673818843);
+    points.append(p);
+
+    p = VSAPoint(377.6951798028408, 260.9250975917487);
+    p.SetSAAfter(32.840273714828662);
+    p.SetSABefore(32.840273714828662);
+    points.append(p);
+
+    p = VSAPoint(373.0472214054606, 262.4208936362013);
+    p.SetSAAfter(32.303940879158468);
+    p.SetSABefore(32.303940879158468);
+    points.append(p);
+
+    p = VSAPoint(368.34919218383584, 263.34065217686486);
+    p.SetSAAfter(31.778098176885351);
+    p.SetSABefore(31.778098176885351);
+    points.append(p);
+
+    p = VSAPoint(363.6307492476716, 263.7075259406228);
+    p.SetSAAfter(31.25824538248542);
+    p.SetSABefore(31.25824538248542);
+    points.append(p);
+
+    p = VSAPoint(358.921549706673, 263.5446676543588);
+    p.SetSAAfter(30.740662987580134);
+    p.SetSABefore(30.740662987580134);
+    points.append(p);
+
+    p = VSAPoint(354.251250670545, 262.87523004495625);
+    p.SetSAAfter(30.222419479548449);
+    p.SetSABefore(30.222419479548449);
+    points.append(p);
+
+    p = VSAPoint(349.6495092489928, 261.72236583929885);
+    p.SetSAAfter(29.701328542831337);
+    p.SetSABefore(29.701328542831337);
+    points.append(p);
+
+    p = VSAPoint(345.1459825517213, 260.1092277642701);
+    p.SetSAAfter(29.175869934623716);
+    p.SetSABefore(29.175869934623716);
+    points.append(p);
+
+    p = VSAPoint(340.7703276884358, 258.0589685467535);
+    p.SetSAAfter(28.645088729374258);
+    p.SetSABefore(28.645088729374258);
+    points.append(p);
+
+    p = VSAPoint(336.5522017688411, 255.59474091363262);
+    p.SetSAAfter(28.108485094878901);
+    p.SetSABefore(28.108485094878901);
+    points.append(p);
+
+    p = VSAPoint(332.52126190264244, 252.73969759179104);
+    p.SetSAAfter(27.565902911541084);
+    p.SetSABefore(27.565902911541084);
+    points.append(p);
+
+    p = VSAPoint(328.7071651995449, 249.51699130811238);
+    p.SetSAAfter(27.017421899167815);
+    p.SetSABefore(27.017421899167815);
+    points.append(p);
+
+    p = VSAPoint(325.1395687692534, 245.94977478948007);
+    p.SetSAAfter(26.463255170503039);
+    p.SetSABefore(26.463255170503039);
+    points.append(p);
+
+    p = VSAPoint(321.84812972147313, 242.06120076277773);
+    p.SetSAAfter(25.903652411137717);
+    p.SetSABefore(25.903652411137717);
+    points.append(p);
+
+    p = VSAPoint(318.86250516590917, 237.87442195488893);
+    p.SetSAAfter(25.338808050829666);
+    p.SetSABefore(25.338808050829666);
+    points.append(p);
+
+    p = VSAPoint(316.2123522122665, 233.4125910926972);
+    p.SetSAAfter(24.768773642603289);
+    p.SetSABefore(24.768773642603289);
+    points.append(p);
+
+    p = VSAPoint(313.9273279702502, 228.69886090308609);
+    p.SetSAAfter(24.19337403613525);
+    p.SetSABefore(24.19337403613525);
+    points.append(p);
+
+    p = VSAPoint(312.03708954956545, 223.75638411293914);
+    p.SetSAAfter(23.612127698143627);
+    p.SetSABefore(23.612127698143627);
+    points.append(p);
+
+    p = VSAPoint(310.57129405991714, 218.60831344913998);
+    p.SetSAAfter(23.024172586797707);
+    p.SetSABefore(23.024172586797707);
+    points.append(p);
+
+    p = VSAPoint(309.55959861101053, 213.27780163857204);
+    p.SetSAAfter(22.42820018785644);
+    p.SetSABefore(22.42820018785644);
+    points.append(p);
+
+    p = VSAPoint(309.03166031255046, 207.788001408119);
+    p.SetSAAfter(21.822401444747854);
+    p.SetSABefore(21.822401444747854);
+    points.append(p);
+
+    p = VSAPoint(309.01713627424215, 202.1620654846643);
+    p.SetSAAfter(21.204429040574471);
+    p.SetSABefore(21.204429040574471);
+    points.append(p);
+
+    p = VSAPoint(309.5456836057906, 196.42314659509157);
+    p.SetSAAfter(20.57138043760828);
+    p.SetSABefore(20.57138043760828);
+    points.append(p);
+
+    p = VSAPoint(310.64695941690104, 190.59439746628436);
+    p.SetSAAfter(19.919804940549692);
+    p.SetSABefore(19.919804940549692);
+    points.append(p);
+
+    p = VSAPoint(312.35062081727835, 184.6989708251262);
+    p.SetSAAfter(19.24573577317911);
+    p.SetSABefore(19.24573577317911);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(313.4645669291343, 181.73215748031558);
+    p.SetSAAfter(18.897637795275593);
+    p.SetSABefore(18.897637795275593);
+    points.append(p);
+
+    p = VSAPoint(315.0998723566189, 177.44976641127198);
+    p.SetSAAfter(19.446824166328746);
+    p.SetSABefore(19.446824166328746);
+    points.append(p);
+
+    p = VSAPoint(317.6731184586346, 169.45847196043132);
+    p.SetSAAfter(20.452631980165769);
+    p.SetSABefore(20.452631980165769);
+    points.append(p);
+
+    p = VSAPoint(319.4487651643931, 162.13409856250706);
+    p.SetSAAfter(21.355546141728666);
+    p.SetSABefore(21.355546141728666);
+    points.append(p);
+
+    p = VSAPoint(320.470410593102, 155.4530193599665);
+    p.SetSAAfter(22.165276674578177);
+    p.SetSABefore(22.165276674578177);
+    points.append(p);
+
+    p = VSAPoint(320.78165286396893, 149.39160749527696);
+    p.SetSAAfter(22.892420458564697);
+    p.SetSABefore(22.892420458564697);
+    points.append(p);
+
+    p = VSAPoint(320.4260900962016, 143.92623611090573);
+    p.SetSAAfter(23.548583135932272);
+    p.SetSABefore(23.548583135932272);
+    points.append(p);
+
+    p = VSAPoint(319.44732040900783, 139.03327834932014);
+    p.SetSAAfter(24.146396878545747);
+    p.SetSABefore(24.146396878545747);
+    points.append(p);
+
+    p = VSAPoint(317.88894192159495, 134.68910735298743);
+    p.SetSAAfter(24.699324443869902);
+    p.SetSABefore(24.699324443869902);
+    points.append(p);
+
+    p = VSAPoint(315.79455275317093, 130.870096264375);
+    p.SetSAAfter(25.221147659605332);
+    p.SetSABefore(25.221147659605332);
+    points.append(p);
+
+    p = VSAPoint(313.2077510229431, 127.55261822595011);
+    p.SetSAAfter(25.725143604791594);
+    p.SetSABefore(25.725143604791594);
+    points.append(p);
+
+    p = VSAPoint(310.1721348501194, 124.71304638018006);
+    p.SetSAAfter(26.223136485113741);
+    p.SetSABefore(26.223136485113741);
+    points.append(p);
+
+    p = VSAPoint(306.73130235390744, 122.32775386953216);
+    p.SetSAAfter(26.724730852906816);
+    p.SetSABefore(26.724730852906816);
+    points.append(p);
+
+    p = VSAPoint(302.9288516535148, 120.3731138364737);
+    p.SetSAAfter(27.236947738833074);
+    p.SetSABefore(27.236947738833074);
+    points.append(p);
+
+    p = VSAPoint(298.80838086814924, 118.82549942347202);
+    p.SetSAAfter(27.764271724915222);
+    p.SetSABefore(27.764271724915222);
+    points.append(p);
+
+    p = VSAPoint(294.41348811701835, 117.66128377299438);
+    p.SetSAAfter(28.308962477298437);
+    p.SetSABefore(28.308962477298437);
+    points.append(p);
+
+    p = VSAPoint(289.7877715193297, 116.85684002750813);
+    p.SetSAAfter(28.871463995346204);
+    p.SetSABefore(28.871463995346204);
+    points.append(p);
+
+    p = VSAPoint(282.5270013648352, 116.23547488513984);
+    p.SetSAAfter(29.744519639698659);
+    p.SetSABefore(29.744519639698659);
+    points.append(p);
+
+    p = VSAPoint(272.4138025206039, 116.50169653372318);
+    p.SetSAAfter(30.956550523683344);
+    p.SetSABefore(30.956550523683344);
+    points.append(p);
+
+    p = VSAPoint(262.16207443587984, 117.7817223666835);
+    p.SetSAAfter(32.194294958045219);
+    p.SetSABefore(32.194294958045219);
+    points.append(p);
+
+    p = VSAPoint(252.12060206432426, 119.88653752375922);
+    p.SetSAAfter(33.423457501774081);
+    p.SetSABefore(33.423457501774081);
+    points.append(p);
+
+    p = VSAPoint(242.63817035959835, 122.62712714468876);
+    p.SetSAAfter(34.605995611034089);
+    p.SetSABefore(34.605995611034089);
+    points.append(p);
+
+    p = VSAPoint(234.06356427536352, 125.81447636921058);
+    p.SetSAAfter(35.70195258686585);
+    p.SetSABefore(35.70195258686585);
+    points.append(p);
+
+    p = VSAPoint(226.74556876528095, 129.25957033706317);
+    p.SetSAAfter(36.670979260736637);
+    p.SetSABefore(36.670979260736637);
+    points.append(p);
+
+    p = VSAPoint(221.03296878301197, 132.77339418798488);
+    p.SetSAAfter(37.474483357433364);
+    p.SetSABefore(37.474483357433364);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(37.795275590551185);
+    p.SetSABefore(37.795275590551185);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(37.795275590551185);
+    p.SetSABefore(37.795275590551185);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(37.795275590551185);
+    p.SetSABefore(37.795275590551185);
+    points.append(p);
+
+    p = VSAPoint(218.97637795275608, 134.48806299212646);
+    p.SetSAAfter(37.795275590551185);
+    p.SetSABefore(37.795275590551185);
+    points.append(p);
+
+    p = VSAPoint(214.11186185064025, 138.80795875858354);
+    p.SetSAAfter(36.653502722568419);
+    p.SetSABefore(36.653502722568419);
+    points.append(p);
+
+    p = VSAPoint(205.18536816471078, 146.02812964687715);
+    p.SetSAAfter(34.638570080274732);
+    p.SetSABefore(34.638570080274732);
+    points.append(p);
+
+    p = VSAPoint(197.17461091794695, 151.63888788459965);
+    p.SetSAAfter(32.922124316374287);
+    p.SetSABefore(32.922124316374287);
+    points.append(p);
+
+    p = VSAPoint(190.02702368501878, 155.74482471949955);
+    p.SetSAAfter(31.475467886854414);
+    p.SetSABefore(31.475467886854414);
+    points.append(p);
+
+    p = VSAPoint(183.69004004059613, 158.45053139932526);
+    p.SetSAAfter(30.266183845834068);
+    p.SetSABefore(30.266183845834068);
+    points.append(p);
+
+    p = VSAPoint(178.11109355934906, 159.86059917182507);
+    p.SetSAAfter(29.256280085066027);
+    p.SetSABefore(29.256280085066027);
+    points.append(p);
+
+    p = VSAPoint(173.23761781594754, 160.07961928474754);
+    p.SetSAAfter(28.400113855274189);
+    p.SetSABefore(28.400113855274189);
+    points.append(p);
+
+    p = VSAPoint(169.01704638506152, 159.21218298584108);
+    p.SetSAAfter(27.643914239586497);
+    p.SetSABefore(27.643914239586497);
+    points.append(p);
+
+    p = VSAPoint(165.396812841361, 157.36288152285397);
+    p.SetSAAfter(26.930461655777069);
+    p.SetSABefore(26.930461655777069);
+    points.append(p);
+
+    p = VSAPoint(162.32435075951594, 154.63630614353477);
+    p.SetSAAfter(26.20953145720112);
+    p.SetSABefore(26.20953145720112);
+    points.append(p);
+
+    p = VSAPoint(159.7470937141963, 151.13704809563185);
+    p.SetSAAfter(25.44681460859611);
+    p.SetSABefore(25.44681460859611);
+    points.append(p);
+
+    p = VSAPoint(157.61247528007215, 146.96969862689363);
+    p.SetSAAfter(24.625073374270738);
+    p.SetSABefore(24.625073374270738);
+    points.append(p);
+
+    p = VSAPoint(155.86792903181333, 142.23884898506853);
+    p.SetSAAfter(23.740148635253075);
+    p.SetSABefore(23.740148635253075);
+    points.append(p);
+
+    p = VSAPoint(154.46088854408993, 137.049090417905);
+    p.SetSAAfter(22.796456338245449);
+    p.SetSABefore(22.796456338245449);
+    points.append(p);
+
+    p = VSAPoint(152.84240084594785, 128.65747053734566);
+    p.SetSAAfter(21.296571460906105);
+    p.SetSABefore(21.296571460906105);
+    points.append(p);
+
+    p = VSAPoint(150.86615884353574, 110.74781740906135);
+    p.SetSAAfter(18.134320368513631);
+    p.SetSABefore(18.134320368513631);
+    points.append(p);
+
+    p = VSAPoint(149.37382105332603, 94.00159365355543);
+    p.SetSAAfter(15.183683963183684);
+    p.SetSABefore(15.183683963183684);
+    points.append(p);
+
+    p = VSAPoint(147.90386548781373, 84.77492816049366);
+    p.SetSAAfter(13.543967770207646);
+    p.SetSABefore(13.543967770207646);
+    points.append(p);
+
+    p = VSAPoint(146.22482573007983, 79.58685396281504);
+    p.SetSAAfter(12.586956110891197);
+    p.SetSABefore(12.586956110891197);
+    points.append(p);
+
+    p = VSAPoint(144.767673193039, 77.0483056159666);
+    p.SetSAAfter(12.073257080584666);
+    p.SetSABefore(12.073257080584666);
+    points.append(p);
+
+    p = VSAPoint(142.9646628872432, 75.4105345645091);
+    p.SetSAAfter(11.645769545279848);
+    p.SetSABefore(11.645769545279848);
+    points.append(p);
+
+    p = VSAPoint(140.76322838736246, 74.77813205619103);
+    p.SetSAAfter(11.243788560650403);
+    p.SetSABefore(11.243788560650403);
+    points.append(p);
+
+    p = VSAPoint(138.11080326806675, 75.25568933876076);
+    p.SetSAAfter(10.77079881073082);
+    p.SetSABefore(10.77079881073082);
+    points.append(p);
+
+    p = VSAPoint(134.95482110402602, 76.94779765996674);
+    p.SetSAAfter(10.142330100270035);
+    p.SetSABefore(10.142330100270035);
+    points.append(p);
+
+    p = VSAPoint(131.24271546991025, 79.95904826755734);
+    p.SetSAAfter(9.3034514353721871);
+    p.SetSABefore(9.3034514353721871);
+    points.append(p);
+
+    p = VSAPoint(126.92191994038947, 84.39403240928104);
+    p.SetSAAfter(8.216780859744869);
+    p.SetSABefore(8.216780859744869);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    p.SetSAAfter(7.559055118110237);
+    p.SetSABefore(7.559055118110237);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    p.SetSAAfter(7.559055118110237);
+    p.SetSABefore(7.559055118110237);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    //p.SetSAAfter(-1);
+    p.SetSABefore(7.559055118110237);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    //p.SetSAAfter(-1);
+    p.SetSABefore(7.559055118110237);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    //p.SetSAAfter(-1);
+    p.SetSABefore(7.559055118110237);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(124.4881889763782, 87.24396850393732);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(121.4053345233613, 90.85541892105327);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(115.36650087404239, 97.1700051724747);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(109.48439793077911, 102.44240810316538);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(103.76400391356904, 106.72573235606063);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(98.2102970424097, 110.0730825740958);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(92.8282555372987, 112.53756340020624);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(87.62285761823352, 114.17227947732721);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(82.59908150521179, 115.03033544839411);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(77.76190541823104, 115.16483595634224);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(73.11630757728881, 114.62888564410696);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(68.66726620238268, 113.47558915462355);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(64.41975951351019, 111.7580511308274);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(60.3787657306689, 109.52937621565376);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(56.54926307385639, 106.84266905203805);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(52.93622976307019, 103.75103428291555);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(49.54464401830785, 100.30757655122164);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(44.854132804201555, 94.62627097468447);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(39.45938535079082, 86.2656734510919);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(35.040036121431584, 77.45366765004954);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(31.635910876104337, 68.61509071504);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(29.28683537478949, 60.17477978954592);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(28.03263537746753, 52.55757201704999);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(27.913136644118886, 46.188304541034846);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(28.62975536807624, 42.54811226326452);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(29.458368599363588, 40.697718569632514);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    p = VSAPoint(30.0, 39.999874015748034);
+    //p.SetSAAfter(-1);
+    //p.SetSABefore(-1);
+    points.append(p);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsCase3() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(11.491153250328935, 2.204598425196849);
+    points += QPointF(446.1486580403833, 2.204598425196849);
+    points += QPointF(443.58722975094355, 245.07202661708763);
+    points += QPointF(425.1137484290017, 268.68251714626723);
+    points += QPointF(410.710702976016, 281.17394700785115);
+    points += QPointF(394.6305380089911, 289.87868829070504);
+    points += QPointF(377.68935972259976, 294.42039446773254);
+    points += QPointF(345.2891679003724, 291.71681887702744);
+    points += QPointF(318.8954558500656, 277.387541146342);
+    points += QPointF(299.836181304411, 255.59117266176213);
+    points += QPointF(288.9960506469964, 228.68278781028684);
+    points += QPointF(288.09978928853826, 198.89092343273913);
+    points += QPointF(295.52398476771754, 175.7944621402967);
+    points += QPointF(298.35692700564954, 155.95491384399136);
+    points += QPointF(296.64544203481944, 147.53499165718873);
+    points += QPointF(295.62311476307525, 146.6781151558174);
+    points += QPointF(289.83631178459234, 145.65886137089512);
+    points += QPointF(263.86302969143765, 151.02798077389028);
+    points += QPointF(248.0011124529875, 159.32004134517877);
+    points += QPointF(209.38086747344968, 181.82248571472272);
+    points += QPointF(187.81719911027162, 188.34500166877712);
+    points += QPointF(165.71167711395094, 187.9030433207368);
+    points += QPointF(146.5634417196521, 177.22168648881313);
+    points += QPointF(136.34913944009722, 161.0107028740396);
+    points += QPointF(132.35548185589735, 132.14155778793625);
+    points += QPointF(124.85769773414223, 138.3166750745855);
+    points += QPointF(106.38084062481717, 148.13624736643095);
+    points += QPointF(86.3477370523643, 153.01816260877774);
+    points += QPointF(66.26289964510504, 152.16787828189516);
+    points += QPointF(48.254978841826016, 146.22324827751663);
+    points += QPointF(21.027781980991552, 125.39244823236324);
+    points += QPointF(6.486477180841129, 105.14630485769516);
+    points += QPointF(-4.426684646901568, 80.5250619079355);
+    points += QPointF(-10.01311360817298, 55.62988319219602);
+    points += QPointF(-8.687212589418436, 33.403943526036805);
+    points += QPointF(-3.18150493921823, 21.10903158131186);
+    points += QPointF(11.491153250328935, 2.204598425196849);
+
+    return points;
+}
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.h b/src/test/ValentinaTest/tst_vabstractpiece.h
new file mode 100644
index 000000000..cd2b37eed
--- /dev/null
+++ b/src/test/ValentinaTest/tst_vabstractpiece.h
@@ -0,0 +1,56 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   17 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 TST_VABSTRACTPIECE_H
+#define TST_VABSTRACTPIECE_H
+
+#include "../vmisc/abstracttest.h"
+
+class VSAPoint;
+
+class TST_VAbstractPiece : public AbstractTest
+{
+    Q_OBJECT
+public:
+    explicit TST_VAbstractPiece(QObject *parent = nullptr);
+
+private slots:
+    void EquidistantRemoveLoop_data();
+    void EquidistantRemoveLoop() const;
+private:
+    QVector<VSAPoint> InputPointsCase1() const;
+    QVector<QPointF>  OutputPointsCase1() const;
+
+    QVector<VSAPoint> InputPointsCase2() const;
+    QVector<QPointF>  OutputPointsCase2() const;
+
+    QVector<VSAPoint> InputPointsCase3() const;
+    QVector<QPointF>  OutputPointsCase3() const;
+};
+
+#endif // TST_VABSTRACTPIECE_H

From d38f318569628c4850856cbd057dfc8a4ed069e5 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 18 Nov 2016 13:24:19 +0200
Subject: [PATCH 068/208] Cppcheck warnings.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.h |  2 +-
 src/libs/vpatterndb/vpiece.cpp    | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 59fb95c5d..32101eb89 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -53,7 +53,7 @@ class VSAPoint : public QPointF
 public:
     Q_DECL_CONSTEXPR VSAPoint();
     Q_DECL_CONSTEXPR VSAPoint(qreal xpos, qreal ypos);
-    Q_DECL_CONSTEXPR VSAPoint(const QPointF &p);
+    Q_DECL_CONSTEXPR explicit VSAPoint(const QPointF &p);
 
     Q_DECL_CONSTEXPR qreal GetSABefore() const;
                      void  SetSABefore(qreal value);
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index a3515cdf3..84effaede 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -214,7 +214,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
     QVector<VSAPoint> pointsEkv;
     for (int i = 0; i< CountNodes(); ++i)
     {
-        const VPieceNode node = at(i);
+        const VPieceNode &node = at(i);
         switch (node.GetTypeTool())
         {
             case (Tool::NodePoint):
@@ -460,7 +460,7 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
 {
     if (i < 0 && i > CountNodes()-1)
     {
-        return QPointF();
+        return VSAPoint();
     }
 
     const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
@@ -471,14 +471,14 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
         points = VGObject::GetReversePoints(points);
     }
 
-    VSAPoint begin = points.first();
+    VSAPoint begin = VSAPoint(points.first());
     if (CountNodes() > 1)
     {
         if (i == 0)
         {
             if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode node = at(CountNodes()-1);
+                const VPieceNode &node = at(CountNodes()-1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -492,7 +492,7 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
         {
             if (at(i-1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode node = at(i-1);
+                const VPieceNode &node = at(i-1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -511,7 +511,7 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
 {
     if (i < 0 && i > CountNodes()-1)
     {
-        return QPointF();
+        return VSAPoint();
     }
 
     const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
@@ -522,14 +522,14 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
         points = VGObject::GetReversePoints(points);
     }
 
-    VSAPoint end = points.last();
+    VSAPoint end = VSAPoint(points.last());
     if (CountNodes() > 2)
     {
         if (i == CountNodes() - 1)
         {
             if (at(0).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode node = at(0);
+                const VPieceNode &node = at(0);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -543,7 +543,7 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
         {
             if (at(i+1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode node = at(i+1);
+                const VPieceNode &node = at(i+1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {

From c21aedc5411154744a48b0098b9c6aa5d08f4e74 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 19 Nov 2016 13:44:12 +0200
Subject: [PATCH 069/208] A seam allowance node angle. Read, write and set in
 the dialog. Not handled in seam allowance itself.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |  2 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd        | 11 +++
 src/libs/vmisc/def.h                          | 10 +++
 src/libs/vpatterndb/vpiecenode.cpp            | 12 ++++
 src/libs/vpatterndb/vpiecenode.h              |  3 +
 src/libs/vpatterndb/vpiecenode_p.h            | 11 ++-
 .../dialogs/tools/dialogseamallowance.cpp     | 67 ++++++++++++++++++-
 .../dialogs/tools/dialogseamallowance.h       |  2 +
 .../dialogs/tools/dialogseamallowance.ui      | 10 +++
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  8 +++
 10 files changed, 132 insertions(+), 4 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index cb385888a..d397a3434 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -751,6 +751,7 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
             const bool reverse = GetParametrUInt(element, VToolSeamAllowance::AttrNodeReverse, "0");
             const qreal saBefore = GetParametrDouble(element, VToolSeamAllowance::AttrSABefore, "-1");
             const qreal saAfter = GetParametrDouble(element, VToolSeamAllowance::AttrSAAfter, "-1");
+            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(GetParametrUInt(element, AttrAngle, "0"));
 
             const QString t = GetParametrString(element, AttrType, VToolSeamAllowance::NodePoint);
             Tool tool;
@@ -776,6 +777,7 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
             VPieceNode node(id, tool, reverse);
             node.SetSABefore(saBefore);
             node.SetSAAfter(saAfter);
+            node.SetAngleType(angle);
             detail.Append(node);
         }
     }
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index e98b35b89..0562a84f1 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -404,6 +404,7 @@
 																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
 																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
 																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
+																										 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
 																								   </xs:complexType>
 																							 </xs:element>
 																						 </xs:sequence>
@@ -638,4 +639,14 @@
        <xs:enumeration value="2"/><!--New version-->
      </xs:restriction>
    </xs:simpleType>
+   <xs:simpleType name="nodeAngle">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="0"/><!--by length-->
+       <xs:enumeration value="1"/><!--by points intersections-->
+       <xs:enumeration value="2"/><!--by second edge symmetry-->
+       <xs:enumeration value="3"/><!--by first edge symmetry-->
+       <xs:enumeration value="4"/><!--by first edge right angle-->
+       <xs:enumeration value="5"/><!--by first edge right angle-->
+     </xs:restriction>
+   </xs:simpleType>
    </xs:schema>
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index a5c420e90..f8e2655a3 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -64,6 +64,16 @@ enum class Source : char { FromGui, FromFile, FromTool };
 enum class NodeUsage : bool {NotInUse = false, InUse = true};
 enum class SelectionType : bool {ByMousePress, ByMouseRelease};
 
+enum class PieceNodeAngle : unsigned char
+{
+    ByLength = 0,
+    ByPointsIntersection,
+    ByFirstEdgeSymmetry,
+    BySecondEdgeSymmetry,
+    ByFirstEdgeRightAngle,
+    BySecondEdgeRightAngle
+};
+
 typedef unsigned char ToolVisHolderType;
 enum class Tool : ToolVisHolderType
 {
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index 32481a696..4a6f7af26 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -150,6 +150,18 @@ void VPieceNode::SetSAAfter(qreal value)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+PieceNodeAngle VPieceNode::GetAngleType() const
+{
+    return d->m_angleType;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetAngleType(PieceNodeAngle type)
+{
+    d->m_angleType = type;
+}
+
 // Friend functions
 //---------------------------------------------------------------------------------------------------------------------
 QDataStream& operator<<(QDataStream& out, const VPieceNode& p)
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 4b4da1a2f..2653e472f 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -65,6 +65,9 @@ public:
     qreal GetSAAfter() const;
     qreal GetSAAfter(Unit unit) const;
     void  SetSAAfter(qreal value);
+
+    PieceNodeAngle GetAngleType() const;
+    void           SetAngleType(PieceNodeAngle type);
 private:
     QSharedDataPointer<VPieceNodeData> d;
 };
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index 63433bed7..25a1c0bad 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -44,7 +44,8 @@ public:
           m_typeTool(Tool::NodePoint),
           m_reverse(false),
           m_saBefore(-1),
-          m_saAfter(-1)
+          m_saAfter(-1),
+          m_angleType(PieceNodeAngle::ByLength)
     {}
 
     VPieceNodeData(quint32 id, Tool typeTool, bool reverse)
@@ -52,7 +53,8 @@ public:
           m_typeTool(typeTool),
           m_reverse(reverse),
           m_saBefore(-1),
-          m_saAfter(-1)
+          m_saAfter(-1),
+          m_angleType(PieceNodeAngle::ByLength)
     {
         if (m_typeTool == Tool::NodePoint)
         {
@@ -66,7 +68,8 @@ public:
           m_typeTool(node.m_typeTool),
           m_reverse(node.m_reverse),
           m_saBefore(node.m_saBefore),
-          m_saAfter(node.m_saAfter)
+          m_saAfter(node.m_saAfter),
+          m_angleType(node.m_angleType)
     {}
 
     ~VPieceNodeData();
@@ -83,6 +86,8 @@ public:
     qreal m_saBefore;
     qreal m_saAfter;
 
+    PieceNodeAngle m_angleType;
+
 private:
     VPieceNodeData &operator=(const VPieceNodeData &) Q_DECL_EQ_DELETE;
 };
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 00f26ed8b..c6eae327c 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -87,10 +87,16 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
     connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
 
+    InitNodeAngles();
+    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::NodeAngleChanged);
+
     if (not applyAllowed)
     {
         vis = new VisToolPiece(data);
     }
+
+    ui->tabWidget->setCurrentIndex(1);// Show always first tab active on start.
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -307,9 +313,11 @@ void DialogSeamAllowance::NodeChanged(int index)
     ui->doubleSpinBoxSAAfter->setDisabled(true);
     ui->pushButtonDefBefore->setDisabled(true);
     ui->pushButtonDefAfter->setDisabled(true);
+    ui->comboBoxAngle->setDisabled(true);
 
     ui->doubleSpinBoxSABefore->blockSignals(true);
     ui->doubleSpinBoxSAAfter->blockSignals(true);
+    ui->comboBoxAngle->blockSignals(true);
 
     if (index != -1)
     {
@@ -322,10 +330,11 @@ void DialogSeamAllowance::NodeChanged(int index)
         const int nodeIndex = piece.indexOfNode(id);
         if (nodeIndex != -1)
         {
-            const VPieceNode node = piece.at(nodeIndex);
+            const VPieceNode &node = piece.at(nodeIndex);
 
             ui->doubleSpinBoxSABefore->setEnabled(true);
             ui->doubleSpinBoxSAAfter->setEnabled(true);
+            ui->comboBoxAngle->setEnabled(true);
 
             qreal w1 = node.GetSABefore();
             if (w1 < 0)
@@ -348,16 +357,54 @@ void DialogSeamAllowance::NodeChanged(int index)
                 ui->pushButtonDefAfter->setEnabled(true);
             }
             ui->doubleSpinBoxSAAfter->setValue(w2);
+
+            const int index = ui->comboBoxAngle->findData(static_cast<unsigned char>(node.GetAngleType()));
+            if (index != -1)
+            {
+                ui->comboBoxAngle->setCurrentIndex(index);
+            }
         }
     }
     else
     {
         ui->doubleSpinBoxSABefore->setValue(0);
         ui->doubleSpinBoxSAAfter->setValue(0);
+        ui->comboBoxAngle->setCurrentIndex(-1);
     }
 
     ui->doubleSpinBoxSABefore->blockSignals(false);
     ui->doubleSpinBoxSAAfter->blockSignals(false);
+    ui->comboBoxAngle->blockSignals(false);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::NodeAngleChanged(int index)
+{
+    const int i = ui->comboBoxNodes->currentIndex();
+    if (i != -1 && index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(i).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+        #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(ui->comboBoxAngle->itemData(index).toUInt());
+        #else
+            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(ui->comboBoxAngle->currentData().toUInt());
+        #endif
+
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetAngleType(angle);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -601,6 +648,24 @@ void DialogSeamAllowance::InitNodesList()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitNodeAngles()
+{
+    ui->comboBoxAngle->clear();
+
+    ui->comboBoxAngle->addItem(tr("by length"), static_cast<unsigned char>(PieceNodeAngle::ByLength));
+    ui->comboBoxAngle->addItem(tr("by points intersetions"),
+                               static_cast<unsigned char>(PieceNodeAngle::ByPointsIntersection));
+    ui->comboBoxAngle->addItem(tr("by second edge symmetry"),
+                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeSymmetry));
+    ui->comboBoxAngle->addItem(tr("by first edge symmetry"),
+                               static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeSymmetry));
+    ui->comboBoxAngle->addItem(tr("by first edge right angle"),
+                               static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeRightAngle));
+    ui->comboBoxAngle->addItem(tr("by second edge right angle"),
+                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeRightAngle));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QListWidgetItem *DialogSeamAllowance::GetItemById(quint32 id)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index e0603c301..35e903df1 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -64,6 +64,7 @@ private slots:
     void ListChanged();
     void EnableSeamAllowance(bool enable);
     void NodeChanged(int index);
+    void NodeAngleChanged(int index);
     void ReturnDefBefore();
     void ReturnDefAfter();
     void ChangedSABefore(double d);
@@ -87,6 +88,7 @@ private:
     bool    MainPathIsClockwise() const;
     QString GetNodeName(const VPieceNode &node) const;
     void    InitNodesList();
+    void    InitNodeAngles();
 
     QListWidgetItem *GetItemById(quint32 id);
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index b9b178fe8..bb48c8e31 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -256,6 +256,16 @@
                </item>
               </layout>
              </item>
+             <item row="3" column="0">
+              <widget class="QLabel" name="labelAngle">
+               <property name="text">
+                <string>Angle:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="3" column="1">
+              <widget class="QComboBox" name="comboBoxAngle"/>
+             </item>
             </layout>
            </widget>
           </item>
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 391124a4b..1bf5663b4 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -238,6 +238,14 @@ void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement,
             qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
             break;
     }
+
+    const unsigned char angleType = static_cast<unsigned char>(node.GetAngleType());
+
+    if (angleType > 0)
+    {
+        doc->SetAttribute(nod, AttrAngle, angleType);
+    }
+
     domElement.appendChild(nod);
 }
 

From 7aa7ba8e5728c56dcfc6ebf405691307671f95c9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 19 Nov 2016 15:29:54 +0200
Subject: [PATCH 070/208] Handle firt default angle type.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 82 +++++++++++++++++++----------
 src/libs/vlayout/vabstractpiece.h   | 32 +++++++++--
 src/libs/vpatterndb/vpiece.cpp      | 10 ++++
 3 files changed, 90 insertions(+), 34 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index c93c97e00..53d8e3903 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -395,36 +395,20 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
             // Comparison bisector angles helps to find direction
             if (angle <= 90)// Go in a same direction
             {//Regular equdistant case
-                const qreal length = line.length();
-                if (length > localWidth*2.4)
-                { // Cutting too long a cut angle
-                    line.setLength(localWidth);
-                    QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular
-                    cutLine.setLength(length); // Decided take this length
-
-                    // We do not check intersection type because intersection must alwayse exist
-                    QPointF px;
-                    cutLine.setAngle(cutLine.angle()+90);
-                    QLineF::IntersectType type = bigLine1.intersect( cutLine, &px );
-                    if (type == QLineF::NoIntersection)
-                    {
-                        qDebug()<<"Couldn't find intersection with cut line.";
-                    }
-                    points.append(px);
-
-                    cutLine.setAngle(cutLine.angle()-180);
-                    type = bigLine2.intersect( cutLine, &px );
-                    if (type == QLineF::NoIntersection)
-                    {
-                        qDebug()<<"Couldn't find intersection with cut line.";
-                    }
-                    points.append(px);
-                }
-                else
-                { // The point just fine
-                    points.append(CrosPoint);
-                    return points;
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wswitch-default")
+                switch (p2Line1.GetAngleType())
+                {
+                    case PieceNodeAngle::ByLength:
+                        return AngleByLength(p2Line1, bigLine1.p1(), CrosPoint, bigLine2.p2(), localWidth);
+                    case PieceNodeAngle::ByPointsIntersection:
+                    case PieceNodeAngle::ByFirstEdgeSymmetry:
+                    case PieceNodeAngle::BySecondEdgeSymmetry:
+                    case PieceNodeAngle::ByFirstEdgeRightAngle:
+                    case PieceNodeAngle::BySecondEdgeRightAngle:
+                        break;
                 }
+QT_WARNING_POP
             }
             else
             { // Different directions
@@ -437,6 +421,7 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
                 if (result1 <=0 && result2 <= 0)
                 {// Dart case. A bisector watch outside. In some cases a point still valid, but ignore if going
                  // outside of an equdistant.
+
                     const QLineF bigEdge = ParallelLine(p1Line1, p1Line2, localWidth );
                     QPointF px;
                     const QLineF::IntersectType type = bigEdge.intersect(line, &px);
@@ -490,6 +475,45 @@ QVector<QPointF> VAbstractPiece::EkvPoint(const VSAPoint &p1Line1, const VSAPoin
     return points;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleByLength(const QPointF &p2, const QPointF &sp1, const QPointF &sp2,
+                                               const QPointF &sp3, qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF line(p2, sp2);
+    const qreal length = line.length();
+    if (length > width*2.4)
+    { // Cutting too long a cut angle
+        line.setLength(width);
+        QLineF cutLine(line.p2(), sp2); // Cut line is a perpendicular
+        cutLine.setLength(length); // Decided take this length
+
+        // We do not check intersection type because intersection must alwayse exist
+        QPointF px;
+        cutLine.setAngle(cutLine.angle()+90);
+        QLineF::IntersectType type = QLineF(sp1, sp2).intersect(cutLine, &px);
+        if (type == QLineF::NoIntersection)
+        {
+            qDebug()<<"Couldn't find intersection with cut line.";
+        }
+        points.append(px);
+
+        cutLine.setAngle(cutLine.angle()-180);
+        type = QLineF(sp2, sp3).intersect(cutLine, &px);
+        if (type == QLineF::NoIntersection)
+        {
+            qDebug()<<"Couldn't find intersection with cut line.";
+        }
+        points.append(px);
+    }
+    else
+    { // The point just fine
+        points.append(sp2);
+    }
+    return points;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 32101eb89..341d29eb7 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -35,6 +35,7 @@
 #include <QDebug>
 
 #include "../vmisc/diagnostic.h"
+#include "../vmisc/def.h"
 #include "../vgeometry/vgobject.h"
 
 template <class T> class QVector;
@@ -61,9 +62,13 @@ public:
     Q_DECL_CONSTEXPR qreal GetSAAfter() const;
                      void  SetSAAfter(qreal value);
 
+    Q_DECL_CONSTEXPR PieceNodeAngle GetAngleType() const;
+                     void           SetAngleType(PieceNodeAngle value);
+
 private:
-    qreal m_before;
-    qreal m_after;
+    qreal          m_before;
+    qreal          m_after;
+    PieceNodeAngle m_angle;
 };
 
 Q_DECLARE_METATYPE(VSAPoint)
@@ -73,21 +78,24 @@ Q_DECLARE_TYPEINFO(VSAPoint, Q_MOVABLE_TYPE);
 Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint()
     : QPointF(),
       m_before(-1),
-      m_after(-1)
+      m_after(-1),
+      m_angle(PieceNodeAngle::ByLength)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
 Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint(qreal xpos, qreal ypos)
     : QPointF(xpos, ypos),
       m_before(-1),
-      m_after(-1)
+      m_after(-1),
+      m_angle(PieceNodeAngle::ByLength)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
 Q_DECL_CONSTEXPR inline VSAPoint::VSAPoint(const QPointF &p)
     : QPointF(p),
       m_before(-1),
-      m_after(-1)
+      m_after(-1),
+      m_angle(PieceNodeAngle::ByLength)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -114,6 +122,18 @@ inline void VSAPoint::SetSAAfter(qreal value)
     value < 0 ? m_after = -1 : m_after = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline PieceNodeAngle VSAPoint::GetAngleType() const
+{
+    return m_angle;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+inline void VSAPoint::SetAngleType(PieceNodeAngle value)
+{
+    m_angle = value;
+}
+
 QT_WARNING_POP
 
 class VAbstractPiece
@@ -154,6 +174,8 @@ private:
     static qreal            MaxLocalSA(const VSAPoint &p, qreal width);
     static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,
                                      const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width);
+    static QVector<QPointF> AngleByLength(const QPointF &p2, const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                          qreal width);
     static QLineF           ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
     static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
     static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 84effaede..bbc201647 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -224,6 +224,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
 
                 p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
                 p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                p.SetAngleType(node.GetAngleType());
                 pointsEkv.append(p);
             }
             break;
@@ -399,11 +400,13 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
             { // first point
                 p.SetSAAfter(begin.GetSAAfter());
                 p.SetSABefore(begin.GetSABefore());
+                p.SetAngleType(begin.GetAngleType());
             }
             else if (i == points.size() - 1)
             { // last point
                 p.SetSAAfter(end.GetSAAfter());
                 p.SetSABefore(end.GetSABefore());
+                p.SetAngleType(end.GetAngleType());
             }
             pointsEkv.append(p);
         }
@@ -428,6 +431,7 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
         VSAPoint p(points.at(0));//First point in the list
         p.SetSAAfter(begin.GetSAAfter());
         p.SetSABefore(begin.GetSABefore());
+        p.SetAngleType(begin.GetAngleType());
         pointsEkv.append(p);
 
         qreal length = 0; // how much we handle
@@ -440,6 +444,7 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
             {// last point
                 p.SetSAAfter(end.GetSAAfter());
                 p.SetSABefore(end.GetSABefore());
+                p.SetAngleType(end.GetAngleType());
             }
             else
             {
@@ -448,6 +453,7 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
 
                 p.SetSAAfter(localWidth);
                 p.SetSABefore(localWidth);
+                // curve points have angle type by default
             }
 
             pointsEkv.append(p);
@@ -485,6 +491,7 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
                     begin = VSAPoint(p);
                     begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
                     begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    begin.SetAngleType(node.GetAngleType());
                 }
             }
         }
@@ -499,6 +506,7 @@ VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
                     begin = VSAPoint(p);
                     begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
                     begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    begin.SetAngleType(node.GetAngleType());
                 }
             }
         }
@@ -536,6 +544,7 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
                     end = VSAPoint(p);
                     end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
                     end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    end.SetAngleType(node.GetAngleType());
                 }
             }
         }
@@ -550,6 +559,7 @@ VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
                     end = VSAPoint(p);
                     end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
                     end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    end.SetAngleType(node.GetAngleType());
                 }
             }
         }

From 854e54ebc0c983d90b0e41c86d7cac2f031a37d3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 19 Nov 2016 18:27:06 +0200
Subject: [PATCH 071/208] Handle seam allowance angles.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 215 +++++++++++++++++++++++++++-
 src/libs/vlayout/vabstractpiece.h   |  15 ++
 2 files changed, 228 insertions(+), 2 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index 53d8e3903..a5a64f8f5 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -29,11 +29,14 @@
 #include "vabstractpiece.h"
 #include "vabstractpiece_p.h"
 #include "../vmisc/vabstractapplication.h"
+#include "../vgeometry/vpointf.h"
 
 #include <QLineF>
 #include <QSet>
 #include <QVector>
 
+const qreal maxL = 2.4;
+
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPiece::VAbstractPiece()
     : d(new VAbstractPieceData)
@@ -402,11 +405,20 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
                     case PieceNodeAngle::ByLength:
                         return AngleByLength(p2Line1, bigLine1.p1(), CrosPoint, bigLine2.p2(), localWidth);
                     case PieceNodeAngle::ByPointsIntersection:
+                        return AngleByIntersection(p1Line1, p2Line1, p1Line2, bigLine1.p1(), CrosPoint, bigLine2.p2(),
+                                                   localWidth);
                     case PieceNodeAngle::ByFirstEdgeSymmetry:
+                        return AngleByFirstSymmetry(p1Line1, p2Line1, bigLine1.p1(), CrosPoint, bigLine2.p2(),
+                                                    localWidth);
                     case PieceNodeAngle::BySecondEdgeSymmetry:
+                        return AngleBySecondSymmetry(p2Line1, p1Line2, bigLine1.p1(), CrosPoint,bigLine2.p2(),
+                                                     localWidth);
                     case PieceNodeAngle::ByFirstEdgeRightAngle:
+                        return AngleByFirstRightAngle(p1Line1, p2Line1, bigLine1.p1(), CrosPoint, bigLine2.p2(),
+                                                      localWidth);
                     case PieceNodeAngle::BySecondEdgeRightAngle:
-                        break;
+                        return AngleBySecondRightAngle(p2Line1, p1Line2, bigLine1.p1(), CrosPoint, bigLine2.p2(),
+                                                       localWidth);
                 }
 QT_WARNING_POP
             }
@@ -483,7 +495,7 @@ QVector<QPointF> VAbstractPiece::AngleByLength(const QPointF &p2, const QPointF
 
     QLineF line(p2, sp2);
     const qreal length = line.length();
-    if (length > width*2.4)
+    if (length > width*maxL)
     { // Cutting too long a cut angle
         line.setLength(width);
         QLineF cutLine(line.p2(), sp2); // Cut line is a perpendicular
@@ -514,6 +526,205 @@ QVector<QPointF> VAbstractPiece::AngleByLength(const QPointF &p2, const QPointF
     return points;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleByIntersection(const QPointF &p1, const QPointF &p2, const QPointF &p3,
+                                                     const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                     qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF edge2(p2, p3);
+    QLineF sEdge1(sp1, sp2);
+
+    QPointF px;
+    QLineF::IntersectType type = edge2.intersect(sEdge1, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    QLineF edge1(p1, p2);
+    QLineF sEdge2(sp2, sp3);
+
+    type = edge1.intersect(sEdge2, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleByFirstSymmetry(const QPointF &p1, const QPointF &p2,
+                                                      const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                      qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF sEdge2(sp2, sp3);
+    QPointF fp1 = VPointF::FlipPF(sEdge2, p1);
+    QPointF fp2 = VPointF::FlipPF(sEdge2, p2);
+    QLineF fEdge(fp1, fp2);
+
+    QPointF px;
+    QLineF sEdge1(sp1, sp2);
+    QLineF::IntersectType type = fEdge.intersect(sEdge1, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    type = fEdge.intersect(sEdge2, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleBySecondSymmetry(const QPointF &p2, const QPointF &p3,
+                                                       const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                       qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF sEdge1(sp1, sp2);
+    QPointF fp2 = VPointF::FlipPF(sEdge1, p2);
+    QPointF fp3 = VPointF::FlipPF(sEdge1, p3);
+    QLineF fEdge(fp2, fp3);
+
+    QPointF px;
+    QLineF::IntersectType type = fEdge.intersect(sEdge1, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    QLineF sEdge2(sp2, sp3);
+    type = fEdge.intersect(sEdge2, &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleByFirstRightAngle(const QPointF &p1, const QPointF &p2,
+                                                        const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                        qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF edge1(p2, p1);
+    edge1.setAngle(edge1.angle()-90);
+
+    QPointF px;
+    QLineF::IntersectType type = edge1.intersect(QLineF(sp1, sp2), &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    type = edge1.intersect(QLineF(sp2, sp3), &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::AngleBySecondRightAngle(const QPointF &p2, const QPointF &p3,
+                                                         const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                         qreal width)
+{
+    QVector<QPointF> points;
+
+    QLineF edge2(p2, p3);
+    edge2.setAngle(edge2.angle()+90);
+
+    QPointF px;
+    QLineF::IntersectType type = edge2.intersect(QLineF(sp1, sp2), &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    type = edge2.intersect(QLineF(sp2, sp3), &px);
+    if (type == QLineF::NoIntersection)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+
+    if (QLineF(p2, px).length() > width*maxL)
+    {
+        return AngleByLength(p2, sp1, sp2, sp3, width);
+    }
+    points.append(px);
+
+    return points;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QLineF VAbstractPiece::ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
 {
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 341d29eb7..13ee0870c 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -176,6 +176,21 @@ private:
                                      const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width);
     static QVector<QPointF> AngleByLength(const QPointF &p2, const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
                                           qreal width);
+    static QVector<QPointF> AngleByIntersection(const QPointF &p1, const QPointF &p2, const QPointF &p3,
+                                                const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                qreal width);
+    static QVector<QPointF> AngleByFirstSymmetry(const QPointF &p1, const QPointF &p2,
+                                                 const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                 qreal width);
+    static QVector<QPointF> AngleBySecondSymmetry(const QPointF &p2, const QPointF &p3,
+                                                  const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                  qreal width);
+    static QVector<QPointF> AngleByFirstRightAngle(const QPointF &p1, const QPointF &p2,
+                                                   const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                   qreal width);
+    static QVector<QPointF> AngleBySecondRightAngle(const QPointF &p2, const QPointF &p3,
+                                                    const QPointF &sp1, const QPointF &sp2, const QPointF &sp3,
+                                                    qreal width);
     static QLineF           ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
     static QLineF           ParallelLine(const QPointF &p1, const QPointF &p2, qreal width);
     static QPointF          SingleParallelPoint(const QPointF &p1, const QPointF &p2, qreal angle, qreal width);

From cc3d97a015bf0c831833cc252eac640c97ae7609 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 19 Nov 2016 18:28:07 +0200
Subject: [PATCH 072/208] Change order the angle "by first edge symmetry".

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index c6eae327c..f263e5a15 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -656,10 +656,10 @@ void DialogSeamAllowance::InitNodeAngles()
     ui->comboBoxAngle->addItem(tr("by length"), static_cast<unsigned char>(PieceNodeAngle::ByLength));
     ui->comboBoxAngle->addItem(tr("by points intersetions"),
                                static_cast<unsigned char>(PieceNodeAngle::ByPointsIntersection));
-    ui->comboBoxAngle->addItem(tr("by second edge symmetry"),
-                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeSymmetry));
     ui->comboBoxAngle->addItem(tr("by first edge symmetry"),
                                static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeSymmetry));
+    ui->comboBoxAngle->addItem(tr("by second edge symmetry"),
+                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeSymmetry));
     ui->comboBoxAngle->addItem(tr("by first edge right angle"),
                                static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeRightAngle));
     ui->comboBoxAngle->addItem(tr("by second edge right angle"),

From f60c710ee10d50d68197665e1c2c0ad4d42fd5a6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 19 Nov 2016 18:52:47 +0200
Subject: [PATCH 073/208] Changes angle type allowed only for point nodes.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index 4a6f7af26..a475d6735 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -159,7 +159,10 @@ PieceNodeAngle VPieceNode::GetAngleType() const
 //---------------------------------------------------------------------------------------------------------------------
 void VPieceNode::SetAngleType(PieceNodeAngle type)
 {
-    d->m_angleType = type;
+    if (d->m_typeTool == Tool::NodePoint)
+    {
+        d->m_angleType = type;
+    }
 }
 
 // Friend functions

From f741e1387c3ff143abf048f75061cbdc7933fe87 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 22 Nov 2016 13:04:34 +0200
Subject: [PATCH 074/208] Added DialogPiecePath class. Not finished.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/dialogs.pri           |   9 +-
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 289 ++++++++++++++++++
 .../vtools/dialogs/tools/dialogpiecepath.h    |  77 +++++
 .../vtools/dialogs/tools/dialogpiecepath.ui   | 128 ++++++++
 .../dialogs/tools/dialogseamallowance.cpp     | 108 +------
 .../dialogs/tools/dialogseamallowance.h       |   3 -
 .../dialogs/tools/dialogseamallowance.ui      |  10 +-
 src/libs/vtools/dialogs/tools/dialogtool.cpp  | 110 +++++++
 src/libs/vtools/dialogs/tools/dialogtool.h    |   8 +
 9 files changed, 629 insertions(+), 113 deletions(-)
 create mode 100644 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
 create mode 100644 src/libs/vtools/dialogs/tools/dialogpiecepath.h
 create mode 100644 src/libs/vtools/dialogs/tools/dialogpiecepath.ui

diff --git a/src/libs/vtools/dialogs/dialogs.pri b/src/libs/vtools/dialogs/dialogs.pri
index 3c1543155..9767ea030 100644
--- a/src/libs/vtools/dialogs/dialogs.pri
+++ b/src/libs/vtools/dialogs/dialogs.pri
@@ -42,7 +42,8 @@ HEADERS += \
     $$PWD/tools/dialogflippingbyline.h \
     $$PWD/tools/dialogflippingbyaxis.h \
     $$PWD/tools/dialogmove.h \
-    $$PWD/tools/dialogseamallowance.h
+    $$PWD/tools/dialogseamallowance.h \
+    $$PWD/tools/dialogpiecepath.h
 
 SOURCES += \
     $$PWD/tools/dialogalongline.cpp \
@@ -84,7 +85,8 @@ SOURCES += \
     $$PWD/tools/dialogflippingbyline.cpp \
     $$PWD/tools/dialogflippingbyaxis.cpp \
     $$PWD/tools/dialogmove.cpp \
-    $$PWD/tools/dialogseamallowance.cpp
+    $$PWD/tools/dialogseamallowance.cpp \
+    $$PWD/tools/dialogpiecepath.cpp
 
 FORMS += \
     $$PWD/tools/dialogalongline.ui \
@@ -125,4 +127,5 @@ FORMS += \
     $$PWD/tools/dialogflippingbyline.ui \
     $$PWD/tools/dialogflippingbyaxis.ui \
     $$PWD/tools/dialogmove.ui \
-    $$PWD/tools/dialogseamallowance.ui
+    $$PWD/tools/dialogseamallowance.ui \
+    $$PWD/tools/dialogpiecepath.ui
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
new file mode 100644
index 000000000..d863f15c6
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -0,0 +1,289 @@
+/************************************************************************
+ **
+ **  @file   dialogpiecepath.cpp
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "dialogpiecepath.h"
+#include "ui_dialogpiecepath.h"
+#include "../vpatterndb/vpiecenode.h"
+
+#include <QMenu>
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
+    : DialogTool(data, toolId, parent),
+    ui(new Ui::DialogPiecePath),
+    m_showMode(true)
+{
+    ui->setupUi(this);
+    InitOkCancel(ui);
+
+    flagName = true;//We have default name of piece.
+    flagError = PathIsValid();
+    CheckState();
+
+    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
+
+    if (not m_showMode)
+    {
+        //vis = new VisToolPiecePath(data);
+    }
+    else
+    {
+        ui->comboBoxType->setDisabled(true);
+        ui->comboBoxPiece->setDisabled(true);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+DialogPiecePath::~DialogPiecePath()
+{
+    delete ui;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::DisableShowMode(bool disable)
+{
+    m_showMode = disable;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ChosenObject(quint32 id, const SceneObject &type)
+{
+    if (not prepare)
+    {
+        bool reverse = false;
+        if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier)
+        {
+            reverse = true;
+        }
+        switch (type)
+        {
+            case SceneObject::Arc:
+                NewItem(VPieceNode(id, Tool::NodeArc, reverse));
+                break;
+            case SceneObject::Point:
+                NewItem(VPieceNode(id, Tool::NodePoint));
+                break;
+            case SceneObject::Spline:
+                NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
+                break;
+            case SceneObject::SplinePath:
+                NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+                break;
+            case (SceneObject::Line):
+            case (SceneObject::Detail):
+            case (SceneObject::Unknown):
+            default:
+                qDebug() << "Got wrong scene object. Ignore.";
+                break;
+        }
+
+        ValidObjects(PathIsValid());
+
+        if (not m_showMode)
+        {
+//        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+//        SCASSERT(visPath != nullptr);
+//        const VPiecePath p = CreatePath();
+//        visPath->SetPath(p);
+
+//        if (p.CountNodes() == 1)
+//        {
+//            emit ToolTip(tr("Select main path objects, <b>Shift</b> - reverse direction curve, "
+//                            "<b>Enter</b> - finish creation"));
+
+//            visPath->VisualMode(NULL_ID);
+//        }
+//        else
+//        {
+//            visPath->RefreshGeometry();
+//        }
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ShowDialog(bool click)
+{
+    if (click == false)
+    {
+        emit ToolTip("");
+        prepare = true;
+
+        if (not m_showMode)
+        {
+//            auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+//            SCASSERT(visPath != nullptr);
+//            visPath->SetMode(Mode::Show);
+//            visPath->RefreshGeometry();
+        }
+        setModal(true);
+        show();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SaveData()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::CheckState()
+{
+    SCASSERT(bOk != nullptr);
+    bOk->setEnabled(flagName && flagError && ui->comboBoxPiece->count() > 0);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ShowContextMenu(const QPoint &pos)
+{
+    const int row = ui->listWidget->currentRow();
+    if (ui->listWidget->count() == 0 || row == -1 || row >= ui->listWidget->count())
+    {
+        return;
+    }
+
+    QMenu *menu = new QMenu(this);
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+    actionDelete->setEnabled(m_showMode);//Because we can't undo this operation when creating a piece.
+
+    QListWidgetItem *rowItem = ui->listWidget->item(row);
+    SCASSERT(rowItem != nullptr);
+    VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+
+    QAction *actionReverse = nullptr;
+    if (rowNode.GetTypeTool() != Tool::NodePoint)
+    {
+        actionReverse = menu->addAction(tr("Reverse"));
+        actionReverse->setCheckable(true);
+        actionReverse->setChecked(rowNode.GetReverse());
+    }
+
+    QAction *selectedAction = menu->exec(ui->listWidget->viewport()->mapToGlobal(pos));
+    if (selectedAction == actionDelete)
+    {
+        delete ui->listWidget->item(row);
+        ValidObjects(PathIsValid());
+    }
+    else if (selectedAction == actionReverse)
+    {
+        rowNode.SetReverse(not rowNode.GetReverse());
+        rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+        rowItem->setText(GetNodeName(rowNode));
+        ValidObjects(PathIsValid());
+    }
+
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ListChanged()
+{
+    if (not m_showMode)
+    {
+//        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+//        SCASSERT(visPath != nullptr);
+//        visPath->SetPiece(CreatePath());
+//        visPath->RefreshGeometry();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::NameChanged()
+{
+    if (ui->lineEditName->text().isEmpty())
+    {
+        flagName = false;
+        ChangeColor(ui->labelName, Qt::red);
+    }
+    else
+    {
+        flagName = true;
+        ChangeColor(ui->labelName, okColor);
+    }
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+//VPiecePath DialogPiecePath::GetPiecePath() const
+//{
+
+//}
+
+//---------------------------------------------------------------------------------------------------------------------
+//void DialogPiecePath::SetPiecePath(const VPiecePath &path)
+//{
+
+//}
+
+//---------------------------------------------------------------------------------------------------------------------
+//VPiecePath DialogPiecePath::CreatePath() const
+//{
+
+//}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogPiecePath::PathIsValid() const
+{
+//    QString url = DialogWarningIcon();
+
+//    if(CreatePath().Points(data).count() < 2)
+//    {
+//        url += tr("You need more points!");
+//        ui->helpLabel->setText(url);
+//        return false;
+//    }
+//    else
+//    {
+//        if (FirstPointEqualLast(ui->listWidget))
+//        {
+//            url += tr("First point cannot be equal to the last point!");
+//            ui->helpLabel->setText(url);
+//            return false;
+//        }
+//        else if (DoublePoints(ui->listWidget))
+//        {
+//            url += tr("You have double points!");
+//            ui->helpLabel->setText(url);
+//            return false;
+//        }
+//    }
+    ui->helpLabel->setText(tr("Ready!"));
+    return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ValidObjects(bool value)
+{
+    flagError = value;
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::NewItem(const VPieceNode &node)
+{
+    NewNodeItem(ui->listWidget, node);
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
new file mode 100644
index 000000000..f1d10f965
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -0,0 +1,77 @@
+/************************************************************************
+ **
+ **  @file   dialogpiecepath.h
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 DIALOGPIECEPATH_H
+#define DIALOGPIECEPATH_H
+
+#include "dialogtool.h"
+
+namespace Ui
+{
+    class DialogPiecePath;
+}
+
+class DialogPiecePath : public DialogTool
+{
+    Q_OBJECT
+public:
+    explicit DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent = nullptr);
+    virtual ~DialogPiecePath();
+
+    void DisableShowMode(bool disable);
+
+//    VPiecePath GetPiecePath() const;
+//    void       SetPiecePath(const VPiecePath &path);
+
+public slots:
+    virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
+    virtual void ShowDialog(bool click) Q_DECL_OVERRIDE;
+
+protected:
+    /** @brief SaveData Put dialog data in local variables */
+    virtual void SaveData() Q_DECL_OVERRIDE;
+    virtual void CheckState() Q_DECL_OVERRIDE;
+
+private slots:
+    void ShowContextMenu(const QPoint &pos);
+    void ListChanged();
+    void NameChanged();
+
+private:
+    Q_DISABLE_COPY(DialogPiecePath)
+    Ui::DialogPiecePath *ui;
+    bool m_showMode;
+
+//    VPiecePath CreatePath() const;
+
+    bool PathIsValid() const;
+    void ValidObjects(bool value);
+    void NewItem(const VPieceNode &node);
+};
+
+#endif // DIALOGPIECEPATH_H
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
new file mode 100644
index 000000000..6ae015961
--- /dev/null
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogPiecePath</class>
+ <widget class="QDialog" name="DialogPiecePath">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>365</width>
+    <height>337</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QFormLayout" name="formLayout">
+     <property name="fieldGrowthPolicy">
+      <enum>QFormLayout::ExpandingFieldsGrow</enum>
+     </property>
+     <item row="0" column="0">
+      <widget class="QLabel" name="labelName">
+       <property name="text">
+        <string>Name:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="lineEditName">
+       <property name="text">
+        <string>Unnamed path</string>
+       </property>
+       <property name="placeholderText">
+        <string>Create name for your path</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="labelType">
+       <property name="text">
+        <string>Type:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QComboBox" name="comboBoxType"/>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="labelPiece">
+       <property name="text">
+        <string>Piece:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QComboBox" name="comboBoxPiece"/>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QListWidget" name="listWidget">
+     <property name="dragDropMode">
+      <enum>QAbstractItemView::InternalMove</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="helpLabel">
+     <property name="text">
+      <string>Ready!</string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="scaledContents">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>DialogPiecePath</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>DialogPiecePath</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index f263e5a15..870061ff1 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -31,7 +31,6 @@
 #include "../vpatterndb/vpiecenode.h"
 #include "visualization/path/vistoolpiece.h"
 
-#include <QBuffer>
 #include <QMenu>
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -453,69 +452,13 @@ VPiece DialogSeamAllowance::CreatePiece() const
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::NewItem(const VPieceNode &node)
 {
-    SCASSERT(node.GetId() > NULL_ID);
-    QString name;
-    switch (node.GetTypeTool())
-    {
-        case (Tool::NodePoint):
-        case (Tool::NodeArc):
-        case (Tool::NodeSpline):
-        case (Tool::NodeSplinePath):
-        {
-            name = GetNodeName(node);
-            break;
-        }
-        default:
-            qDebug()<<"Got wrong tools. Ignore.";
-            return;
-    }
-
-
-
-    bool canAddNewPoint = false;
-
-    if(ui->listWidget->count() == 0)
-    {
-        canAddNewPoint = true;
-    }
-    else
-    {
-        if(RowId(ui->listWidget->count()-1) != node.GetId())
-        {
-            canAddNewPoint = true;
-        }
-    }
-
-    if(canAddNewPoint)
-    {
-        QListWidgetItem *item = new QListWidgetItem(name);
-        item->setFont(QFont("Times", 12, QFont::Bold));
-        item->setData(Qt::UserRole, QVariant::fromValue(node));
-        ui->listWidget->addItem(item);
-        ui->listWidget->setCurrentRow(ui->listWidget->count()-1);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-quint32 DialogSeamAllowance::RowId(int i) const
-{
-    const QListWidgetItem *rowItem = ui->listWidget->item(i);
-    SCASSERT(rowItem != nullptr);
-    const VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
-    return rowNode.GetId();
+    NewNodeItem(ui->listWidget, node);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 bool DialogSeamAllowance::MainPathIsValid() const
 {
-    const QIcon icon = QIcon::fromTheme("dialog-warning",
-                                  QIcon(":/icons/win.icon.theme/16x16/status/dialog-warning.png"));
-
-    const QPixmap pixmap = icon.pixmap(QSize(16, 16));
-    QByteArray byteArray;
-    QBuffer buffer(&byteArray);
-    pixmap.save(&buffer, "PNG");
-    QString url = QString("<img src=\"data:image/png;base64,") + byteArray.toBase64() + QLatin1String("\"/> ");
+    QString url = DialogWarningIcon();
 
     if(CreatePiece().MainPathPoints(data).count() < 3)
     {
@@ -531,23 +474,17 @@ bool DialogSeamAllowance::MainPathIsValid() const
             ui->helpLabel->setText(url);
             return false;
         }
-        if (FirstPointEqualLast())
+        if (FirstPointEqualLast(ui->listWidget))
         {
             url += tr("First point cannot be equal to the last point!");
             ui->helpLabel->setText(url);
             return false;
         }
-        else
+        else if (DoublePoints(ui->listWidget))
         {
-            for (int i=0, sz = ui->listWidget->count()-1; i<sz; ++i)
-            {
-                if (RowId(i) == RowId(i+1))
-                {
-                    url += tr("You have double points!");
-                    ui->helpLabel->setText(url);
-                    return false;
-                }
-            }
+            url += tr("You have double points!");
+            ui->helpLabel->setText(url);
+            return false;
         }
     }
     ui->helpLabel->setText(tr("Ready!"));
@@ -561,23 +498,6 @@ void DialogSeamAllowance::ValidObjects(bool value)
     CheckState();
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-bool DialogSeamAllowance::FirstPointEqualLast() const
-{
-    if (ui->listWidget->count() > 1)
-    {
-        if (RowId(0) == RowId(ui->listWidget->count()-1))
-        {
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return false;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 bool DialogSeamAllowance::MainPathIsClockwise() const
 {
@@ -596,20 +516,6 @@ bool DialogSeamAllowance::MainPathIsClockwise() const
     return false;
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-QString DialogSeamAllowance::GetNodeName(const VPieceNode &node) const
-{
-    const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(node.GetId());
-    QString name = obj->name();
-
-    if (node.GetTypeTool() != Tool::NodePoint && node.GetReverse())
-    {
-        name = QLatin1String("- ") + name;
-    }
-
-    return name;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::InitNodesList()
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 35e903df1..114967881 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -81,12 +81,9 @@ private:
     VPiece CreatePiece() const;
 
     void    NewItem(const VPieceNode &node);
-    quint32 RowId(int i) const;
     bool    MainPathIsValid() const;
     void    ValidObjects(bool value);
-    bool    FirstPointEqualLast() const;
     bool    MainPathIsClockwise() const;
-    QString GetNodeName(const VPieceNode &node) const;
     void    InitNodesList();
     void    InitNodeAngles();
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index bb48c8e31..6af522a18 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -14,14 +14,14 @@
    <string>Dialog</string>
   </property>
   <property name="windowIcon">
-   <iconset resource="../../../vmisc/share/resources/icon.qrc">
+   <iconset>
     <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>1</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -42,7 +42,7 @@
             <string/>
            </property>
            <property name="pixmap">
-            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/32x32/clockwise.png</pixmap>
+            <pixmap>:/icon/32x32/clockwise.png</pixmap>
            </property>
           </widget>
          </item>
@@ -301,9 +301,7 @@
    </item>
   </layout>
  </widget>
- <resources>
-  <include location="../../../vmisc/share/resources/icon.qrc"/>
- </resources>
+ <resources/>
  <connections>
   <connection>
    <sender>buttonBox</sender>
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp
index 4e6a92039..11f9d808f 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp
@@ -58,6 +58,7 @@
 #include <Qt>
 #include <QtDebug>
 #include <new>
+#include <QBuffer>
 
 #include "../ifc/xml/vdomdocument.h"
 #include "../qmuparser/qmudef.h"
@@ -66,6 +67,7 @@
 #include "../vpatterndb/calculator.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vpatterndb/vtranslatevars.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "../../tools/vabstracttool.h"
 #include "../ifc/xml/vabstractpattern.h"
 #include "../vgeometry/vabstractcurve.h"
@@ -392,6 +394,114 @@ quint32 DialogTool::DNumber(const QString &baseName) const
     return num;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 DialogTool::RowId(QListWidget *listWidget, int i)
+{
+    SCASSERT(listWidget != nullptr);
+    const QListWidgetItem *rowItem = listWidget->item(i);
+    SCASSERT(rowItem != nullptr);
+    const VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+    return rowNode.GetId();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogTool::FirstPointEqualLast(QListWidget *listWidget)
+{
+    SCASSERT(listWidget != nullptr);
+    if (listWidget->count() > 1)
+    {
+        return RowId(listWidget, 0) == RowId(listWidget, listWidget->count()-1);
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool DialogTool::DoublePoints(QListWidget *listWidget)
+{
+    SCASSERT(listWidget != nullptr);
+    for (int i=0, sz = listWidget->count()-1; i<sz; ++i)
+    {
+        if (RowId(listWidget, i) == RowId(listWidget, i+1))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogTool::DialogWarningIcon()
+{
+    const QIcon icon = QIcon::fromTheme("dialog-warning",
+                                  QIcon(":/icons/win.icon.theme/16x16/status/dialog-warning.png"));
+
+    const QPixmap pixmap = icon.pixmap(QSize(16, 16));
+    QByteArray byteArray;
+    QBuffer buffer(&byteArray);
+    pixmap.save(&buffer, "PNG");
+    const QString url = QString("<img src=\"data:image/png;base64,") + byteArray.toBase64() + QLatin1String("\"/> ");
+    return url;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogTool::GetNodeName(const VPieceNode &node) const
+{
+    const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(node.GetId());
+    QString name = obj->name();
+
+    if (node.GetTypeTool() != Tool::NodePoint && node.GetReverse())
+    {
+        name = QLatin1String("- ") + name;
+    }
+
+    return name;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node)
+{
+    SCASSERT(listWidget != nullptr);
+    SCASSERT(node.GetId() > NULL_ID);
+    QString name;
+    switch (node.GetTypeTool())
+    {
+        case (Tool::NodePoint):
+        case (Tool::NodeArc):
+        case (Tool::NodeSpline):
+        case (Tool::NodeSplinePath):
+        {
+            name = GetNodeName(node);
+            break;
+        }
+        default:
+            qDebug()<<"Got wrong tools. Ignore.";
+            return;
+    }
+
+    bool canAddNewPoint = false;
+
+    if(listWidget->count() == 0)
+    {
+        canAddNewPoint = true;
+    }
+    else
+    {
+        if(RowId(listWidget, listWidget->count()-1) != node.GetId())
+        {
+            canAddNewPoint = true;
+        }
+    }
+
+    if(canAddNewPoint)
+    {
+        QListWidgetItem *item = new QListWidgetItem(name);
+        item->setFont(QFont("Times", 12, QFont::Bold));
+        item->setData(Qt::UserRole, QVariant::fromValue(node));
+        listWidget->addItem(item);
+        listWidget->setCurrentRow(listWidget->count()-1);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool DialogTool::IsSplinePath(const QSharedPointer<VGObject> &obj) const
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h
index cc5d29af8..313f45c34 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.h
+++ b/src/libs/vtools/dialogs/tools/dialogtool.h
@@ -274,6 +274,14 @@ protected:
     void             MoveCursorToEnd(QPlainTextEdit *plainTextEdit);
     virtual bool     eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE;
     quint32          DNumber(const QString &baseName) const;
+
+    static quint32   RowId(QListWidget *listWidget, int i);
+    static bool      FirstPointEqualLast(QListWidget *listWidget);
+    static bool      DoublePoints(QListWidget *listWidget);
+    static QString   DialogWarningIcon();
+
+    QString          GetNodeName(const VPieceNode &node) const;
+    void             NewNodeItem(QListWidget *listWidget, const VPieceNode &node);
 private:
     void FillList(QComboBox *box, const QMap<QString, quint32> &list)const;
 

From 6b89f43e871c393ef8828b7e9a52f4c6045bdb35 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 22 Nov 2016 14:33:08 +0200
Subject: [PATCH 075/208] Tool button connected to tool dialog.

--HG--
branch : feature
---
 .../core/vtooloptionspropertybrowser.cpp      |   6 +-
 src/app/valentina/dialogs/dialoghistory.cpp   |   3 +-
 src/app/valentina/mainwindow.cpp              |  40 ++++++++-
 src/app/valentina/mainwindow.h                |   2 +
 src/app/valentina/mainwindow.ui               |  40 +++++++--
 src/app/valentina/share/resources/cursor.qrc  |   2 +
 .../share/resources/cursor/path_cursor.png    | Bin 0 -> 572 bytes
 .../share/resources/cursor/path_cursor@2x.png | Bin 0 -> 1218 bytes
 .../valentina/share/resources/toolicon.qrc    |   2 +
 .../share/resources/toolicon/32x32/path.png   | Bin 0 -> 752 bytes
 .../resources/toolicon/32x32/path@2x.png      | Bin 0 -> 1626 bytes
 .../share/resources/toolicon/svg/path.svg     |  85 ++++++++++++++++++
 src/app/valentina/xml/vpattern.cpp            |   3 +-
 src/libs/ifc/xml/vabstractpattern.cpp         |   8 +-
 src/libs/vmisc/def.h                          |   4 +-
 src/libs/vtools/dialogs/tooldialogs.h         |   1 +
 .../vtools/dialogs/tools/dialogpiecepath.cpp  |   2 +
 17 files changed, 178 insertions(+), 20 deletions(-)
 create mode 100644 src/app/valentina/share/resources/cursor/path_cursor.png
 create mode 100644 src/app/valentina/share/resources/cursor/path_cursor@2x.png
 create mode 100644 src/app/valentina/share/resources/toolicon/32x32/path.png
 create mode 100644 src/app/valentina/share/resources/toolicon/32x32/path@2x.png
 create mode 100644 src/app/valentina/share/resources/toolicon/svg/path.svg

diff --git a/src/app/valentina/core/vtooloptionspropertybrowser.cpp b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
index 99434e6d5..7c5dc3dcc 100644
--- a/src/app/valentina/core/vtooloptionspropertybrowser.cpp
+++ b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
@@ -77,7 +77,7 @@ void VToolOptionsPropertyBrowser::ClearPropertyBrowser()
 void VToolOptionsPropertyBrowser::ShowItemOptions(QGraphicsItem *item)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were used in switch.");
 
     switch (item->type())
     {
@@ -210,7 +210,7 @@ void VToolOptionsPropertyBrowser::UpdateOptions()
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were used in switch.");
 
     switch (currentItem->type())
     {
@@ -354,7 +354,7 @@ void VToolOptionsPropertyBrowser::userChangedData(VProperty *property)
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were used in switch.");
 
     switch (currentItem->type())
     {
diff --git a/src/app/valentina/dialogs/dialoghistory.cpp b/src/app/valentina/dialogs/dialoghistory.cpp
index 8b57fdadf..e394b31b3 100644
--- a/src/app/valentina/dialogs/dialoghistory.cpp
+++ b/src/app/valentina/dialogs/dialoghistory.cpp
@@ -208,7 +208,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QString DialogHistory::Record(const VToolRecord &tool)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used in history.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools was used in history.");
 
     const QDomElement domElem = doc->elementById(tool.getId());
     if (domElem.isElement() == false)
@@ -392,6 +392,7 @@ QString DialogHistory::Record(const VToolRecord &tool)
             case Tool::FlippingByLine:
             case Tool::FlippingByAxis:
             case Tool::Move:
+            case Tool::PiecePath:
                 return QString();
         }
     }
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index c8941b238..de188950a 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -952,6 +952,14 @@ void MainWindow::ToolDetail(bool checked)
                                                 &MainWindow::ApplyDetailsDialog<VToolSeamAllowance>);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::ToolPiecePath(bool checked)
+{
+    ToolSelectAllDrawObjects();
+    SetToolButton<DialogPiecePath>(checked, Tool::PiecePath, "://cursor/path_cursor.png", tr("Select path objects."),
+                                   &MainWindow::ClosedDialogPiecePath);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ClosedDialogDetail actions after closing DialogDetail.
@@ -1104,6 +1112,19 @@ void MainWindow::ClosedDialogGroup(int result)
     ArrowTool();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::ClosedDialogPiecePath(int result)
+{
+    SCASSERT(dialogTool != nullptr);
+    if (result == QDialog::Accepted)
+    {
+        DialogPiecePath *dialog = qobject_cast<DialogPiecePath*>(dialogTool);
+        SCASSERT(dialog != nullptr);
+
+    }
+    ArrowTool();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ToolCutArc handler tool cutArc.
@@ -1671,6 +1692,7 @@ void MainWindow::ToolBarDraws()
     });
 }
 
+//---------------------------------------------------------------------------------------------------------------------
 void MainWindow::ToolBarTools()
 {
     /*First we will try use Standard Shortcuts from Qt, but because keypad "-" and "+" not the same keys like in main
@@ -1717,6 +1739,9 @@ void MainWindow::InitToolButtons()
         connect(pointer, &QToolButton::clicked, this, &MainWindow::ArrowTool);
     }
 
+    // This check helps to find missed tools
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Check if all tools were connected.");
+
     connect(ui->toolButtonEndLine, &QToolButton::clicked, this, &MainWindow::ToolEndLine);
     connect(ui->toolButtonLine, &QToolButton::clicked, this, &MainWindow::ToolLine);
     connect(ui->toolButtonAlongLine, &QToolButton::clicked, this, &MainWindow::ToolAlongLine);
@@ -1731,6 +1756,7 @@ void MainWindow::InitToolButtons()
     connect(ui->toolButtonCubicBezierPath, &QToolButton::clicked, this, &MainWindow::ToolCubicBezierPath);
     connect(ui->toolButtonPointOfContact, &QToolButton::clicked, this, &MainWindow::ToolPointOfContact);
     connect(ui->toolButtonNewDetail, &QToolButton::clicked, this, &MainWindow::ToolDetail);
+    connect(ui->toolButtonPiecePath, &QToolButton::clicked, this, &MainWindow::ToolPiecePath);
     connect(ui->toolButtonHeight, &QToolButton::clicked, this, &MainWindow::ToolHeight);
     connect(ui->toolButtonTriangle, &QToolButton::clicked, this, &MainWindow::ToolTriangle);
     connect(ui->toolButtonPointOfIntersection, &QToolButton::clicked, this, &MainWindow::ToolPointOfIntersection);
@@ -1786,7 +1812,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::CancelTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools was handled.");
 
     qCDebug(vMainWindow, "Canceling tool.");
     delete dialogTool;
@@ -1875,6 +1901,9 @@ void MainWindow::CancelTool()
         case Tool::Piece:
             ui->toolButtonNewDetail->setChecked(false);
             break;
+        case Tool::PiecePath:
+            ui->toolButtonPiecePath->setChecked(false);
+            break;
         case Tool::Height:
             ui->toolButtonHeight->setChecked(false);
             break;
@@ -2987,7 +3016,7 @@ void MainWindow::SetEnableTool(bool enable)
     }
 
     // This check helps to find missed tools
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools were handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were handled.");
 
     //Drawing Tools
     ui->toolButtonEndLine->setEnabled(drawTools);
@@ -3004,6 +3033,7 @@ void MainWindow::SetEnableTool(bool enable)
     ui->toolButtonCubicBezierPath->setEnabled(drawTools);
     ui->toolButtonPointOfContact->setEnabled(drawTools);
     ui->toolButtonNewDetail->setEnabled(drawTools);
+    ui->toolButtonPiecePath->setEnabled(drawTools);
     ui->toolButtonHeight->setEnabled(drawTools);
     ui->toolButtonTriangle->setEnabled(drawTools);
     ui->toolButtonPointOfIntersection->setEnabled(drawTools);
@@ -3307,7 +3337,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::LastUsedTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were handled.");
 
     if (currentTool == lastUsedTool)
     {
@@ -3401,6 +3431,10 @@ void MainWindow::LastUsedTool()
             ui->toolButtonNewDetail->setChecked(true);
             ToolDetail(true);
             break;
+        case Tool::PiecePath:
+            ui->toolButtonPiecePath->setChecked(true);
+            ToolPiecePath(true);
+            break;
         case Tool::Height:
             ui->toolButtonHeight->setChecked(true);
             ToolHeight(true);
diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h
index 34851eaf5..aed7a8993 100644
--- a/src/app/valentina/mainwindow.h
+++ b/src/app/valentina/mainwindow.h
@@ -134,6 +134,7 @@ private slots:
     void ToolCutSplinePath(bool checked);
     void ToolPointOfContact(bool checked);
     void ToolDetail(bool checked);
+    void ToolPiecePath(bool checked);
     void ToolHeight(bool checked);
     void ToolTriangle(bool checked);
     void ToolPointOfIntersection(bool checked);
@@ -167,6 +168,7 @@ private slots:
     void ClosedDialogDetail(int result);
     void ClosedDialogUnionDetails(int result);
     void ClosedDialogGroup(int result);
+    void ClosedDialogPiecePath(int result);
 
     void LoadIndividual();
     void LoadStandard();
diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui
index 27f576e5e..cfad62823 100644
--- a/src/app/valentina/mainwindow.ui
+++ b/src/app/valentina/mainwindow.ui
@@ -48,7 +48,7 @@
        <string>Tools</string>
       </property>
       <property name="currentIndex">
-       <number>4</number>
+       <number>5</number>
       </property>
       <widget class="QWidget" name="page">
        <property name="geometry">
@@ -427,7 +427,7 @@
         <rect>
          <x>0</x>
          <y>0</y>
-         <width>117</width>
+         <width>130</width>
          <height>110</height>
         </rect>
        </property>
@@ -536,7 +536,7 @@
         <rect>
          <x>0</x>
          <y>0</y>
-         <width>117</width>
+         <width>130</width>
          <height>248</height>
         </rect>
        </property>
@@ -798,7 +798,7 @@
         <rect>
          <x>0</x>
          <y>0</y>
-         <width>117</width>
+         <width>130</width>
          <height>248</height>
         </rect>
        </property>
@@ -1241,8 +1241,8 @@
         <rect>
          <x>0</x>
          <y>0</y>
-         <width>117</width>
-         <height>104</height>
+         <width>130</width>
+         <height>150</height>
         </rect>
        </property>
        <property name="sizePolicy">
@@ -1343,6 +1343,32 @@
           </property>
          </widget>
         </item>
+        <item row="2" column="0">
+         <widget class="QToolButton" name="toolButtonPiecePath">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="toolTip">
+           <string>Piece path tool</string>
+          </property>
+          <property name="text">
+           <string notr="true">...</string>
+          </property>
+          <property name="icon">
+           <iconset resource="share/resources/toolicon.qrc">
+            <normaloff>:/toolicon/32x32/path.png</normaloff>:/toolicon/32x32/path.png</iconset>
+          </property>
+          <property name="iconSize">
+           <size>
+            <width>32</width>
+            <height>32</height>
+           </size>
+          </property>
+          <property name="checkable">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
        </layout>
       </widget>
       <widget class="QWidget" name="page_6">
@@ -2480,8 +2506,8 @@
   </customwidget>
  </customwidgets>
  <resources>
-  <include location="../../libs/vmisc/share/resources/icon.qrc"/>
   <include location="share/resources/toolicon.qrc"/>
+  <include location="../../libs/vmisc/share/resources/icon.qrc"/>
  </resources>
  <connections/>
 </ui>
diff --git a/src/app/valentina/share/resources/cursor.qrc b/src/app/valentina/share/resources/cursor.qrc
index b2631218b..56f67ddd5 100644
--- a/src/app/valentina/share/resources/cursor.qrc
+++ b/src/app/valentina/share/resources/cursor.qrc
@@ -76,5 +76,7 @@
         <file>cursor/flipping_axis_cursor@2x.png</file>
         <file>cursor/move_cursor.png</file>
         <file>cursor/move_cursor@2x.png</file>
+        <file>cursor/path_cursor.png</file>
+        <file>cursor/path_cursor@2x.png</file>
     </qresource>
 </RCC>
diff --git a/src/app/valentina/share/resources/cursor/path_cursor.png b/src/app/valentina/share/resources/cursor/path_cursor.png
new file mode 100644
index 0000000000000000000000000000000000000000..2819f260a57881bc5ad48b72a56fd76290c3ac66
GIT binary patch
literal 572
zcmV-C0>k}@P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10l7&;K~z|U?bb1C)L<9~@Lyu=P+O#6MT)DGQxIx<x(JFz-2DU&
zBDe@HPA&8s*vUcr0mMOZ(6Jo_p}Glz9g2%kRIJ`5ZMAW@o;{A-wP`Q8#s3m`-@Nbh
zOY#I>{%1Fzak-y>6u<h3*xo_>#B@IaeM7VY`hxh=1}Gho1t=BK2~Zm1cNah@h`j)X
zBlZI*6tT5WKw*eHfI<*?0X;`-9stl&#6bbw5Wy646TH5}=^_D{h^s^uzK@d5^L&%3
zZh(zL0x}U*?oP7shMNg5Vir<H@&LBwYtWTWPnZ(L%q6@^8EBtRGB(@78qRmxG;dOZ
zIuBxI_5#HCh_PN3Z{`cf65gjA=>(`@5ktK$-b~Ds8e?J0Sh{nq<0-Cd98wEO%BP6q
zVcU3uhq$eAJ}4{!LusSO{^bL16<M^Ilptnljp3+e{A?M;q0U4|a-zUb+%YvS)OnXM
z-jfZ_F;L~+MXqH`2UTV#d9=uQo%;#P2{)QIL>Y^6WrWHq^JhrDvNE{)H~B_5O=X>M
zgG$J=b*`LjdG&_|M68bTGUn}39=Eo2KrqbgAg5-yv&@h7^?v~kBO<nUj@~i=0000<
KMNUMnLSTZ#aPd|E

literal 0
HcmV?d00001

diff --git a/src/app/valentina/share/resources/cursor/path_cursor@2x.png b/src/app/valentina/share/resources/cursor/path_cursor@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..09c3a01ab0b367a1f670854405831cc9b8d9eb4b
GIT binary patch
literal 1218
zcmV;z1U>tSP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H11V2ecK~#90?b}OiRAm&v@!!n!L3u|oh!Go%$O2-B&_O^V7!#C4
z4JvUbi7~o#Ym5tV;|4WG;zC2BfX0PkBZ><mpbHTnD4O^{ML`~d2!(d;l+u1KZXrdd
z?QNNN`%k{4bLZaMbN=(4Z|*(4WsEV#7~@Jl!9HAD=|Cz)=o<%&QVF5o_zBlnHk|U)
z>q-fuZYK1&QoyL2355iVDhU@A7BFfgbQ@T}sE{y}fV!7(!O#NgT0)m(0_s-6a0Jw)
zguLMis5=Rf;R~oM2_qFyHxhD2E}$+Xbh<hLH7}tU0%}@9hvEpRSqbMAPe4sdD7Ju_
zlW<P)1=N&;cBK(eGZIQEpe7`oRaya6FX4>R3#e)d<q}Y}68=#>0aYpCwDJn5Iti5!
zP%#Oq0^9z^v~ma1$In=aV@VHK$n*>kV_x9EbT;pZ+j@y;D6lOgJ-7tif?bkJNM(4w
zhjraFHIhFaC%?s2<Z()6N?_RKu#m<!j<gaQ3A5>4#m+s<357r0|B)`Rt&%g~5|?H|
zk~JX}T(0HRd{*Adj))Brt)Xz4U#40GkU+v$Tukxm3{K7`Kb;e;tZ!z2nnzRY@8Y$H
z8x0|%KYyuw2_!Cu6^zTWJj>%*maHWcXz6BI#HSG#BKGE3mQ=urDoFajV{g*n`_swH
zJTFIdMjVWoo#eRVRgiH1(T$HsB0zkCbe?-7{>br7o;jrw@IEGvG|*BKNat7^(G{^J
zFk!I$j~RaQ8<8np3Rh2{Ibvs?jy(4dw(n8N6Ys%Or3}27bh0|4Jz{$pWVR+1ki&x|
zkGhBi8gslG5k=g^$gcxViZ55U6*It6lcGDt4sqUhGO~MtAF&#TiW^>e=;gaK?J4F_
zcm@o{ZY))!$wT01pfhkC!z+QUSS4<m)hszW`$}Ov$pvh{I`IQkHBAdGXbAC>Fhkxl
zUci%hv&3<gjV5OHGCsr$`Jjtn2OhzP<qEDG^e`{Y6#OvIK5zBCxu9%Om5C#?L~*a6
zBggHPj;HM8xhK!rh>uP)xzh2JmB6@&JrSK<JW%O)%1U5Tj+grG2A>TH`-OEuCo^+w
zjL1i94NUF-e&Rk^saeeA6xRfz&*QJCB=;n;@!v3(V_JrNpYc6Hps9<y15b+=yf1rL
zGcj)YRTqnx+s1os9M1B^60%8-TR}sXcNTH(Hli#CpJQpB`yw_)oR2uy_j7BZb5unw
zG_k&eHAhHKW!4>R-^QV-@jq}4$S*WL!Ghn&bl@g#p26-A&+OxPF~!@>{F)lzTvZ_e
z6MEvdm6rJR<Pd*igO))vsdPM~;t>wV{lm>&?482z10{Zmsu0l22jf{bmq`s=JjyHG
zyl#l#yU6sg=>`_}kZIz~E}nUTuao}nsu0l4<_1nR$BWsY?Yz+%KdUq(Z9LY%Lk&y|
g?4HH9!|9>_3-VR2WyLU;m;e9(07*qoM6N<$g2K=xqyPW_

literal 0
HcmV?d00001

diff --git a/src/app/valentina/share/resources/toolicon.qrc b/src/app/valentina/share/resources/toolicon.qrc
index 675a47d40..e93851223 100644
--- a/src/app/valentina/share/resources/toolicon.qrc
+++ b/src/app/valentina/share/resources/toolicon.qrc
@@ -74,5 +74,7 @@
         <file>toolicon/32x32/flipping_axis@2x.png</file>
         <file>toolicon/32x32/move.png</file>
         <file>toolicon/32x32/move@2x.png</file>
+        <file>toolicon/32x32/path.png</file>
+        <file>toolicon/32x32/path@2x.png</file>
     </qresource>
 </RCC>
diff --git a/src/app/valentina/share/resources/toolicon/32x32/path.png b/src/app/valentina/share/resources/toolicon/32x32/path.png
new file mode 100644
index 0000000000000000000000000000000000000000..a95d6e90d3bb87008cf90c2b194883bd641a9e68
GIT binary patch
literal 752
zcmV<M0uTL(P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10&Ph|K~z|U#n#V@RdpE0@z?jxRlHMUQh}P~7zUDol6q&1K?)3A
zq{Ot7z!usf!bKpokz6VL0U_wZt%!(-C=r1ZCS^05s35F`5ZR(KXJpRz{+N5dF6InK
zf^!GQdmcD^4}5u^&-?p*p7T5>SOlx{W?&@o>pCu;qq7)syRsoZsWZKecAYrP>7I#0
zotqoTtE55FcH(~4bn9PP1creYVFpc9S$3408DB&OpEy9^;&Ze%l3t>-lD}6I10UnJ
z$f?9LPYj@+!xfGX@O9wCZC<ajHt-Q{;ll<$HF*1RwH9oNYR0FLR-_Zz-*X6Pusbpx
zX=l7w3Pj|s0%9uia#;`uBPsGtB9sMjC6XHKDFvX(rbr&SQ3?P=t`(^mT#Qb*U`t#o
zUU!xPfNRA%R2IM=5Lj6XK#e<)c(xRPj1>jI-BJJoFBa=xW!1or0^r9|)FW4mKG6G_
zFwK^t6OQ*>JQ3z*L6diT4v=xUxcciopN5eSBJIe(k+nS&PArLhR^)vuvh%_H0B`V0
z&aRxvr#L@Gqg#QktncG!n*9;|wvS`q5fgnGdn<g74fwN<cb5L|(+fjv#?_pskyp6h
z&+aj1<`aL7rTt9I@M=bNIqi*HKFRNi_putC#K{&%R`B0LLH2Q>PU<JEB8`xbGu7bE
ze9zBJj*vf3LRwE6oh`BynT(ujvguKWs20aeIU$*i)Z$+1A`Q!^1_o+af*RV~P8_Q7
zWgwd`Mi^onzM4xx;QNeSztEb`8HPEXvoFoUG;v^@v)%aeKoNEr4g6E%%-8~o5S3v@
i6EEc4nBa#6___~3weLRZj>xP40000<MNUMnLSTY<7f%TQ

literal 0
HcmV?d00001

diff --git a/src/app/valentina/share/resources/toolicon/32x32/path@2x.png b/src/app/valentina/share/resources/toolicon/32x32/path@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..46efce5f682bd2b8d6e05fbd579e2ec6eb911e97
GIT binary patch
literal 1626
zcmV-g2BrClP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H11=mSLK~#90<=b0~T~!$e@ZZ{J?$g>*prjQlq!tCKL<+5qmxKom
za`6)5gGQnyQAABK8lyh=B+>XlG^rYhF`7o7nh2>0(L@^ou@<~k8!L!41v)@<XiKMa
z_Brj$UOucd<*+-2I-NOt!u}_dnYGvK_5Ig>eQWJ?`BuXs!$)W=W9Sf5y|5R0VdQLZ
z9q-QgdSpEY@pNQIA9wF2UnskaLV%6jh0mc8>63U(hvWqZBR4$8^9x}+TZlscA8h1i
zd_FQT&60xQf}w)Zf)QMr@!f^8U%3E*PazZxPZIXyZ+H%o{>WhDh7GJ)2>X=_5ZMsv
zM;Mbj`$;^DHUfhK46aX}GViEbfPmqd#K}_TiO&BFF!Uk5-(+tqb(dxHMWAW{qSV+0
zysj&wAERC(cs>GGN4B*XYbHTnf35_o7C_)vfvLds#kdTY;0lS{fF#8Fm%la|_-x=`
zE$%+T^10ftT!4)4;Bdxd#)%cgl^9?;W3tV$E4g=&9ZvO%Qy7YTaftnGJ}?*ii)9{g
zHNNMih7MBqI3D=s9)185tZc9)a3@yHQq=Y#?g%u`*7l+hfHVbuhMNjD;k>}!f}OKX
zfFdI;wnn}ZPIv!(fe#PyWN(;Ph@+gBb8k+O6T5yUTD-Svemz5zkLFC2L}<3SscLRL
zLz^pdo+yiu^UkWd^$ZhSn6sx_gcgU}yt!&_Jws$PXLrdH_QkZYst1m7e$L-ZBK)Xo
zUOh#NwK*@Ax<h>iMabDw@`A@>nqAiiP3|vw!Pcrd^%Oam<+Qs*7>f*5&8w$qvaQq=
zZmXJ8PmyzJ&QzBGzpt88&(UOOX)IXFBG?b;A%0v+*XxtmnIYy~UhqKGoO+I&Uv~-c
zLL}6w3&5VPzgM(bTPpz~e<?j$S2qC;mL9#KRsw`{;&uv=3u`4no5|9n;aUl>ycBd1
z7^sy1O_p}2BNMd}pf4RUo<iisS_z;t|DQqRV66n0=1tw{J`U7MfQ-#u$<_e>tc*;r
z5$Ver?^+8yNR5`mZLat7L2wr}5+HJGcRJ(eRdMM#CRtV582!ggUM)PJ!IyNM2ZR)i
zQ4e%BL|a|0KOR%q(Q6-(Ea#!x9*nfuS~?Fn5K|!bYacCcES&{RHF-zXyn2F3-d39Q
z#3tLS=G7B4+1%tv$@PC%3)j#2SZVJ+<{X${W!2mk6h~N|^TS!f<qqVp5@x?>0wu5I
zs*Lvq))kCr{CN%c?O^&$??kc|AIG<_x|H`<+%m#5uVnX>0B>Y)MG8T^5tjtU3m(H=
z3w2!u-on6Ws=z1FkY=YvCwpJu_C4(HekanO^TCX-My{Eq*q;sY>9Yx$4X}Y#4R&Ik
zbZ@7DqH||wBIDLS@Y}go@|CcWZ{zkze~|(gvJSBm87(|Fz~+ZjywBS+-rrf+tS*-o
zIU2ZgnC)k4KXgd^0`Dpq>D=C!LD5KC$>R;K-Ob^1sOxFCE_vGCnC=LTG;vfKu2-PJ
z^dM8W@YL4y=z=p8RbWTt%dh70W%O<0$^qUpl`buX=Q|{ZaWPqgrK5~);fY-wn|pOn
z$4-{s!}3Y8HXfHk#7Wm>R?}$E_&1lIp@^x#eSvQbvTrUN`U<W>m?kta*2$QZ{PCic
z%*K-XXKH~tp((jw(Xki1@+LaJ3%qdpt54ylk$Z+YbS@nFvaTg@EM<153-gbe%R<5F
zv1@}}c|++-@DLs;xPO#C%@>D0?2i-~ag?x9>gXd<b7#azaRJW;{xe^OVJ#yCm-mq^
zA*}A$9+XD7Ks>?ZlWZSO7c1u-0bvunBG(j*cD?{JC>qIAkN30Tk#xanUa^s1VspXp
zECX;ea58fJqv^Xo@5m4{?!bRDj(6_vv@)6vj-ws<!a`KOL*O%bddA)?w!gMem8a9%
zhZtXz29@E!MS+pP5&UMFPyDg7g}e|r#L+eUB&K0zSzt-$82iD%ZI31o=`G$`mn|dw
Y54CqdG56)XEdT%j07*qoM6N<$g02<=Hvj+t

literal 0
HcmV?d00001

diff --git a/src/app/valentina/share/resources/toolicon/svg/path.svg b/src/app/valentina/share/resources/toolicon/svg/path.svg
new file mode 100644
index 000000000..fede8eb12
--- /dev/null
+++ b/src/app/valentina/share/resources/toolicon/svg/path.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="32"
+   height="32"
+   id="svg3837"
+   inkscape:version="0.91 r"
+   sodipodi:docname="path.svg"
+   inkscape:export-filename="normal.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1855"
+     inkscape:window-height="1056"
+     id="namedview12"
+     showgrid="false"
+     inkscape:zoom="10.429825"
+     inkscape:cx="-10.695145"
+     inkscape:cy="17.373127"
+     inkscape:window-x="65"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1" />
+  <defs
+     id="defs3839" />
+  <metadata
+     id="metadata3842">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#f70000;stroke-width:1.808;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 0.69867705,29.000338 18.91523895,0"
+       id="path4205"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       d="m 4.55558,29.025223 a 1.7375,1.7294948 0 0 1 -3.475,0 1.7375,1.7294948 0 1 1 3.475,0 z"
+       id="path2985-2"
+       style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.56700003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#f70000;stroke-width:1.79597759;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 18.613918,3.1640977 c 16.627356,3.2556205 16.092696,24.3053213 0,25.7434553"
+       id="path3385"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
+       id="path5373"
+       d="m 20.178354,28.833465 a 1.8239208,1.9086996 0 0 1 -3.647841,0 1.8239208,1.9086996 0 1 1 3.647841,0 z" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
+       id="path5373-7"
+       d="m 20.424424,3.1415223 a 1.8239208,1.9086996 0 0 1 -3.647841,0 1.8239208,1.9086996 0 1 1 3.647841,0 z" />
+  </g>
+</svg>
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index d397a3434..4f9fd1722 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -3478,7 +3478,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QRectF VPattern::ActiveDrawBoundingRect() const
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49, "Not all tools was used.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50, "Not all tools were used.");
 
     QRectF rec;
 
@@ -3608,6 +3608,7 @@ QRectF VPattern::ActiveDrawBoundingRect() const
                 case Tool::NodeSpline:
                 case Tool::NodeSplinePath:
                 case Tool::Group:
+                case Tool::PiecePath:
                     break;
             }
         }
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index 05076bd9f..974d9f9ce 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -1422,7 +1422,7 @@ QStringList VAbstractPattern::ListPointExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagPoint);
@@ -1493,7 +1493,7 @@ QStringList VAbstractPattern::ListArcExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagArc);
@@ -1554,7 +1554,7 @@ QStringList VAbstractPattern::ListPathPointExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(AttrPathPoint);
@@ -1620,7 +1620,7 @@ QStringList VAbstractPattern::ListOperationExpressions() const
 {
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 49);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 50);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagOperation);
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index f8e2655a3..7d680bd38 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -103,6 +103,7 @@ enum class Tool : ToolVisHolderType
     PointOfContact,
     Detail,
     Piece,
+    PiecePath,
     NodePoint,
     NodeArc,
     NodeSpline,
@@ -170,7 +171,8 @@ enum class Vis : ToolVisHolderType
     ToolFlippingByLine,
     ToolFlippingByAxis,
     ToolMove,
-    ToolPiece
+    ToolPiece,
+    ToolPiecePath
 };
 
 enum class VarType : char { Measurement, Increment, LineLength, CurveLength, CurveCLength, LineAngle, CurveAngle,
diff --git a/src/libs/vtools/dialogs/tooldialogs.h b/src/libs/vtools/dialogs/tooldialogs.h
index d7f859cc1..07259d6fc 100644
--- a/src/libs/vtools/dialogs/tooldialogs.h
+++ b/src/libs/vtools/dialogs/tooldialogs.h
@@ -66,6 +66,7 @@
 #include "tools/dialogflippingbyline.h"
 #include "tools/dialogflippingbyaxis.h"
 #include "tools/dialogmove.h"
+#include "tools/dialogpiecepath.h"
 
 #include "support/dialogeditwrongformula.h"
 #include "support/dialogundo.h"
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index d863f15c6..fa119d6bf 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -56,6 +56,8 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
         ui->comboBoxType->setDisabled(true);
         ui->comboBoxPiece->setDisabled(true);
     }
+
+    show();//temporary
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From 5d5e677e2cbdf60c5b2283d7a0cdbb0a349447c5 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 12:54:46 +0200
Subject: [PATCH 076/208] Added class VPiecePath.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |   3 +-
 src/libs/vpatterndb/vpatterndb.pri            |   7 +-
 src/libs/vpatterndb/vpiece.cpp                | 253 ++-------------
 src/libs/vpatterndb/vpiece.h                  |  16 +-
 src/libs/vpatterndb/vpiece_p.h                |   7 +-
 src/libs/vpatterndb/vpiecepath.cpp            | 287 ++++++++++++++++++
 src/libs/vpatterndb/vpiecepath.h              |  74 +++++
 src/libs/vpatterndb/vpiecepath_p.h            |  67 ++++
 .../dialogs/tools/dialogseamallowance.cpp     |  15 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  25 +-
 src/libs/vtools/undocommands/addpiece.cpp     |   3 +-
 src/libs/vtools/undocommands/deletepiece.cpp  |   3 +-
 .../visualization/path/vistoolpiece.cpp       |   4 +-
 13 files changed, 491 insertions(+), 273 deletions(-)
 create mode 100644 src/libs/vpatterndb/vpiecepath.cpp
 create mode 100644 src/libs/vpatterndb/vpiecepath.h
 create mode 100644 src/libs/vpatterndb/vpiecepath_p.h

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 4f9fd1722..595fbae13 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -54,6 +54,7 @@
 #include "../vpatterndb/vpatternpiecedata.h"
 #include "../vpatterndb/vpatterninfogeometry.h"
 #include "../vpatterndb/vgrainlinegeometry.h"
+#include "../vpatterndb/vpiecepath.h"
 
 #include <QMessageBox>
 #include <QUndoStack>
@@ -778,7 +779,7 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
             node.SetSABefore(saBefore);
             node.SetSAAfter(saAfter);
             node.SetAngleType(angle);
-            detail.Append(node);
+            detail.GetPath().Append(node);
         }
     }
 }
diff --git a/src/libs/vpatterndb/vpatterndb.pri b/src/libs/vpatterndb/vpatterndb.pri
index 49256369c..b0d026efe 100644
--- a/src/libs/vpatterndb/vpatterndb.pri
+++ b/src/libs/vpatterndb/vpatterndb.pri
@@ -23,7 +23,8 @@ SOURCES += \
     $$PWD/vgrainlinegeometry.cpp \
     $$PWD/variables/vcurveclength.cpp \
     $$PWD/vpiece.cpp \
-    $$PWD/vpiecenode.cpp
+    $$PWD/vpiecenode.cpp \
+    $$PWD/vpiecepath.cpp
 
 win32-msvc*:SOURCES += $$PWD/stable.cpp
 
@@ -63,4 +64,6 @@ HEADERS += \
     $$PWD/vpiece.h \
     $$PWD/vpiece_p.h \
     $$PWD/vpiecenode.h \
-    $$PWD/vpiecenode_p.h
+    $$PWD/vpiecenode_p.h \
+    $$PWD/vpiecepath.h \
+    $$PWD/vpiecepath_p.h
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index bbc201647..1d0fafc0d 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -63,114 +63,27 @@ VPiece::~VPiece()
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief append append in the end of list node.
- * @param node new node.
- */
-void VPiece::Append(const VPieceNode &node)
+VPiecePath VPiece::GetPath() const
 {
-    d->m_nodes.append(node);
+    return d->m_path;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-/** @brief Clear detail full clear. */
-void VPiece::Clear()
+VPiecePath &VPiece::GetPath()
 {
-    ClearNodes();
+    return d->m_path;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-/** @brief ClearNodes clear list of nodes. */
-void VPiece::ClearNodes()
+void VPiece::SetPath(const VPiecePath &path)
 {
-    d->m_nodes.clear();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CountNode return count nodes.
- * @return count.
- */
-qint32 VPiece::CountNodes() const
-{
-    return d->m_nodes.size();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief operator [] find node by index in list.
- * @param indx index node in list.
- * @return node
- */
-VPieceNode &VPiece::operator [](int indx)
-{
-    return d->m_nodes[indx];
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief at find node by index in list.
- * @param indx index node in list.
- * @return const node.
- */
-const VPieceNode &VPiece::at(int indx) const
-{
-    return d->m_nodes.at(indx);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getNodes return list of nodes.
- * @return list of nodes.
- */
-QVector<VPieceNode> VPiece::GetNodes() const
-{
-    return d->m_nodes;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setNodes set list of nodes
- * @param value list of nodes
- */
-// cppcheck-suppress unusedFunction
-void VPiece::SetNodes(const QVector<VPieceNode> &nodes)
-{
-    d->m_nodes = nodes;
+    d->m_path = path;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
 {
-    QVector<QPointF> points;
-    for (int i = 0; i < CountNodes(); ++i)
-    {
-        switch (at(i).GetTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
-                points.append(*point);
-            }
-            break;
-            case (Tool::NodeArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-            {
-                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
-
-                const QPointF begin = StartSegment(data, i, at(i).GetReverse());
-                const QPointF end = EndSegment(data, i, at(i).GetReverse());
-
-                points << curve->GetSegmentPoints(begin, end, at(i).GetReverse());
-            }
-            break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).GetTypeTool());
-                break;
-        }
-    }
-
+    QVector<QPointF> points = GetPath().PathPoints(data);
     points = CheckLoops(CorrectEquidistantPoints(points));//A path can contains loops
     return points;
 }
@@ -178,26 +91,7 @@ QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiece::MainPathNodePoints(const VContainer *data) const
 {
-    QVector<QPointF> points;
-    for (int i = 0; i < CountNodes(); ++i)
-    {
-        switch (at(i).GetTypeTool())
-        {
-            case Tool::NodePoint:
-            {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
-                points.append(*point);
-            }
-            break;
-            case Tool::NodeArc:
-            case Tool::NodeSpline:
-            case Tool::NodeSplinePath:
-            default:
-                break;
-        }
-    }
-
-    return points;
+    return GetPath().PathNodePoints(data);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -212,9 +106,9 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
     }
 
     QVector<VSAPoint> pointsEkv;
-    for (int i = 0; i< CountNodes(); ++i)
+    for (int i = 0; i< d->m_path.CountNodes(); ++i)
     {
-        const VPieceNode &node = at(i);
+        const VPieceNode &node = d->m_path.at(i);
         switch (node.GetTypeTool())
         {
             case (Tool::NodePoint):
@@ -334,31 +228,32 @@ void VPiece::SetInLayout(bool inLayout)
  */
 QVector<VPieceNode> VPiece::Missing(const VPiece &det) const
 {
-    if (d->m_nodes.size() == det.CountNodes()) //-V807
+    const QVector<VPieceNode> pNodes = d->m_path.GetNodes();
+    if (pNodes.size() == det.GetPath().CountNodes()) //-V807
     {
         return QVector<VPieceNode>();
     }
 
     QSet<quint32> set1;
-    for (qint32 i = 0; i < d->m_nodes.size(); ++i)
+    for (qint32 i = 0; i < pNodes.size(); ++i)
     {
-        set1.insert(d->m_nodes.at(i).GetId());
+        set1.insert(pNodes.at(i).GetId());
     }
 
     QSet<quint32> set2;
-    for (qint32 j = 0; j < det.CountNodes(); ++j)
+    for (qint32 j = 0; j < det.GetPath().CountNodes(); ++j)
     {
-        set2.insert(det.at(j).GetId());
+        set2.insert(det.GetPath().at(j).GetId());
     }
 
     const QList<quint32> set3 = set1.subtract(set2).toList();
     QVector<VPieceNode> nodes;
     for (qint32 i = 0; i < set3.size(); ++i)
     {
-        const int index = indexOfNode(d->m_nodes, set3.at(i));
+        const int index = indexOfNode(pNodes, set3.at(i));
         if (index != -1)
         {
-            nodes.append(d->m_nodes.at(index));
+            nodes.append(pNodes.at(index));
         }
     }
 
@@ -373,15 +268,15 @@ QVector<VPieceNode> VPiece::Missing(const VPiece &det) const
  */
 int VPiece::indexOfNode(const quint32 &id) const
 {
-    return indexOfNode(d->m_nodes, id);
+    return indexOfNode(d->m_path.GetNodes(), id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                        const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
 {
-    const VSAPoint begin = StartSegment(data, i, reverse);
-    const VSAPoint end = EndSegment(data, i, reverse);
+    const VSAPoint begin = d->m_path.StartSegment(data, i, reverse);
+    const VSAPoint end = d->m_path.EndSegment(data, i, reverse);
 
     const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
     if (points.isEmpty())
@@ -461,112 +356,6 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-VSAPoint VPiece::StartSegment(const VContainer *data, int i, bool reverse) const
-{
-    if (i < 0 && i > CountNodes()-1)
-    {
-        return VSAPoint();
-    }
-
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
-
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
-    {
-        points = VGObject::GetReversePoints(points);
-    }
-
-    VSAPoint begin = VSAPoint(points.first());
-    if (CountNodes() > 1)
-    {
-        if (i == 0)
-        {
-            if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = at(CountNodes()-1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    begin.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-        else
-        {
-            if (at(i-1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = at(i-1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    begin.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-    }
-    return begin;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-VSAPoint VPiece::EndSegment(const VContainer *data, int i, bool reverse) const
-{
-    if (i < 0 && i > CountNodes()-1)
-    {
-        return VSAPoint();
-    }
-
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
-
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
-    {
-        points = VGObject::GetReversePoints(points);
-    }
-
-    VSAPoint end = VSAPoint(points.last());
-    if (CountNodes() > 2)
-    {
-        if (i == CountNodes() - 1)
-        {
-            if (at(0).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = at(0);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    end.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-        else
-        {
-            if (at(i+1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = at(i+1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    end.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-    }
-    return end;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief indexOfNode return index in list node using id object.
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 0ebf87e4d..243332d8d 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -42,6 +42,7 @@ class VContainer;
 template <class T> class QVector;
 template <class T>class QSharedPointer;
 class VAbstractCurve;
+class VPiecePath;
 
 class VPiece : public VAbstractPiece
 {
@@ -51,16 +52,9 @@ public:
     VPiece &operator=(const VPiece &piece);
     virtual ~VPiece();
 
-    void   Append(const VPieceNode &node);
-    void   Clear();
-    void   ClearNodes();
-    qint32 CountNodes() const;
-
-    VPieceNode & operator[](int indx);
-    const VPieceNode & at ( int indx ) const;
-
-    QVector<VPieceNode> GetNodes() const;
-    void                SetNodes(const QVector<VPieceNode> &nodes);
+    VPiecePath GetPath() const;
+    VPiecePath &GetPath();
+    void       SetPath(const VPiecePath &path);
 
     QVector<QPointF> MainPathPoints(const VContainer *data) const;
     QVector<QPointF> MainPathNodePoints(const VContainer *data) const;
@@ -87,8 +81,6 @@ private:
 
     void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                    const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
-    VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
-    VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
 
     static int indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 6ddf9fd80..ebb7acd6c 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -34,6 +34,7 @@
 
 #include "../vmisc/diagnostic.h"
 #include "vpiecenode.h"
+#include "vpiecepath.h"
 
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_GCC("-Weffc++")
@@ -42,7 +43,7 @@ class VPieceData : public QSharedData
 {
 public:
     VPieceData()
-        : m_nodes(),
+        : m_path(),
           m_mx(0),
           m_my(0),
           m_inLayout(true)
@@ -50,7 +51,7 @@ public:
 
     VPieceData(const VPieceData &detail)
         : QSharedData(detail),
-          m_nodes(detail.m_nodes),
+          m_path(detail.m_path),
           m_mx(detail.m_mx),
           m_my(detail.m_my),
           m_inLayout(detail.m_inLayout)
@@ -59,7 +60,7 @@ public:
     ~VPieceData();
 
     /** @brief nodes list detail nodes. */
-    QVector<VPieceNode> m_nodes;
+    VPiecePath m_path;
 
     qreal m_mx;
     qreal m_my;
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
new file mode 100644
index 000000000..d9445cff3
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -0,0 +1,287 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vpiecepath.h"
+#include "vpiecepath_p.h"
+#include "vcontainer.h"
+#include "../vgeometry/vpointf.h"
+#include "../vlayout/vabstractpiece.h"
+
+#include <QPainterPath>
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath::VPiecePath()
+    : d(new VPiecePathData)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath::VPiecePath(const VPiecePath &path)
+    : d (path.d)
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath &VPiecePath::operator=(const VPiecePath &path)
+{
+    if ( &path == this )
+    {
+        return *this;
+    }
+    d = path.d;
+    return *this;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath::~VPiecePath()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::Append(const VPieceNode &node)
+{
+    d->m_nodes.append(node);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::Clear()
+{
+    d->m_nodes.clear();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+qint32 VPiecePath::CountNodes() const
+{
+    return d->m_nodes.size();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode &VPiecePath::operator[](int indx)
+{
+    return d->m_nodes[indx];
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+const VPieceNode &VPiecePath::at(int indx) const
+{
+    return d->m_nodes.at(indx);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VPieceNode> VPiecePath::GetNodes() const
+{
+    return d->m_nodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::SetNodes(const QVector<VPieceNode> &nodes)
+{
+    d->m_nodes = nodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
+{
+    QVector<QPointF> points;
+    for (int i = 0; i < CountNodes(); ++i)
+    {
+        switch (at(i).GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
+                points.append(*point);
+            }
+            break;
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+                const QPointF begin = StartSegment(data, i, at(i).GetReverse());
+                const QPointF end = EndSegment(data, i, at(i).GetReverse());
+
+                points << curve->GetSegmentPoints(begin, end, at(i).GetReverse());
+            }
+            break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).GetTypeTool());
+                break;
+        }
+    }
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VPiecePath::PathNodePoints(const VContainer *data) const
+{
+    QVector<QPointF> points;
+    for (int i = 0; i < CountNodes(); ++i)
+    {
+        switch (at(i).GetTypeTool())
+        {
+            case Tool::NodePoint:
+            {
+                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).GetId());
+                points.append(*point);
+            }
+            break;
+            case Tool::NodeArc:
+            case Tool::NodeSpline:
+            case Tool::NodeSplinePath:
+            default:
+                break;
+        }
+    }
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPainterPath VPiecePath::PainterPath(const VContainer *data) const
+{
+    const QVector<QPointF> points = PathPoints(data);
+    QPainterPath path;
+
+    if (not points.isEmpty())
+    {
+        path.moveTo(points[0]);
+        for (qint32 i = 1; i < points.count(); ++i)
+        {
+            path.lineTo(points.at(i));
+        }
+        path.setFillRule(Qt::WindingFill);
+    }
+
+    return path;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
+{
+    if (i < 0 && i > CountNodes()-1)
+    {
+        return VSAPoint();
+    }
+
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+    QVector<QPointF> points = curve->GetPoints();
+    if (reverse)
+    {
+        points = VGObject::GetReversePoints(points);
+    }
+
+    VSAPoint begin = VSAPoint(points.first());
+    if (CountNodes() > 1)
+    {
+        if (i == 0)
+        {
+            if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
+            {
+                const VPieceNode &node = at(CountNodes()-1);
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    begin = VSAPoint(p);
+                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    begin.SetAngleType(node.GetAngleType());
+                }
+            }
+        }
+        else
+        {
+            if (at(i-1).GetTypeTool() == Tool::NodePoint)
+            {
+                const VPieceNode &node = at(i-1);
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    begin = VSAPoint(p);
+                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    begin.SetAngleType(node.GetAngleType());
+                }
+            }
+        }
+    }
+    return begin;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const
+{
+    if (i < 0 && i > CountNodes()-1)
+    {
+        return VSAPoint();
+    }
+
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+
+    QVector<QPointF> points = curve->GetPoints();
+    if (reverse)
+    {
+        points = VGObject::GetReversePoints(points);
+    }
+
+    VSAPoint end = VSAPoint(points.last());
+    if (CountNodes() > 2)
+    {
+        if (i == CountNodes() - 1)
+        {
+            if (at(0).GetTypeTool() == Tool::NodePoint)
+            {
+                const VPieceNode &node = at(0);
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    end = VSAPoint(p);
+                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    end.SetAngleType(node.GetAngleType());
+                }
+            }
+        }
+        else
+        {
+            if (at(i+1).GetTypeTool() == Tool::NodePoint)
+            {
+                const VPieceNode &node = at(i+1);
+                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+                if (curve->IsPointOnCurve(p))
+                {
+                    end = VSAPoint(p);
+                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+                    end.SetAngleType(node.GetAngleType());
+                }
+            }
+        }
+    }
+    return end;
+}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
new file mode 100644
index 000000000..b85c34c6d
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -0,0 +1,74 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECEPATH_H
+#define VPIECEPATH_H
+
+#include <QtGlobal>
+#include <QSharedDataPointer>
+
+class VPiecePathData;
+class VPieceNode;
+class QPointF;
+class VContainer;
+class VSAPoint;
+class QPainterPath;
+
+class VPiecePath
+{
+public:
+    VPiecePath();
+    VPiecePath(const VPiecePath &path);
+    VPiecePath &operator=(const VPiecePath &path);
+    ~VPiecePath();
+
+    void   Append(const VPieceNode &node);
+    void   Clear();
+    qint32 CountNodes() const;
+
+    VPieceNode & operator[](int indx);
+    const VPieceNode & at ( int indx ) const;
+
+    QVector<VPieceNode> GetNodes() const;
+    void                SetNodes(const QVector<VPieceNode> &nodes);
+
+    QVector<QPointF> PathPoints(const VContainer *data) const;
+    QVector<QPointF> PathNodePoints(const VContainer *data) const;
+
+    QPainterPath PainterPath(const VContainer *data) const;
+
+    VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
+    VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
+
+private:
+    QSharedDataPointer<VPiecePathData> d;
+};
+
+Q_DECLARE_TYPEINFO(VPiecePath, Q_MOVABLE_TYPE);
+
+#endif // VPIECEPATH_H
diff --git a/src/libs/vpatterndb/vpiecepath_p.h b/src/libs/vpatterndb/vpiecepath_p.h
new file mode 100644
index 000000000..de8efc3b7
--- /dev/null
+++ b/src/libs/vpatterndb/vpiecepath_p.h
@@ -0,0 +1,67 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECEPATH_P_H
+#define VPIECEPATH_P_H
+
+#include <QSharedData>
+#include <QVector>
+
+#include "../vmisc/diagnostic.h"
+#include "vpiecenode.h"
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Weffc++")
+
+class VPiecePathData : public QSharedData
+{
+public:
+    VPiecePathData()
+        : m_nodes()
+    {}
+
+    VPiecePathData(const VPiecePathData &path)
+        : QSharedData(path),
+          m_nodes(path.m_nodes)
+    {}
+
+    ~VPiecePathData();
+
+    QVector<VPieceNode> m_nodes;
+
+private:
+    VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE;
+};
+
+VPiecePathData::~VPiecePathData()
+{}
+
+QT_WARNING_POP
+
+#endif // VPIECEPATH_P_H
+
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 870061ff1..653e21f4a 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -29,6 +29,7 @@
 #include "dialogseamallowance.h"
 #include "ui_dialogseamallowance.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpiecepath.h"
 #include "visualization/path/vistoolpiece.h"
 
 #include <QMenu>
@@ -123,9 +124,9 @@ VPiece DialogSeamAllowance::GetPiece() const
 void DialogSeamAllowance::SetPiece(const VPiece &piece)
 {
     ui->listWidget->clear();
-    for (int i = 0; i < piece.CountNodes(); ++i)
+    for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
     {
-        NewItem(piece.at(i));
+        NewItem(piece.GetPath().at(i));
     }
 
     ui->checkBoxForbidFlipping->setChecked(piece.IsForbidFlipping());
@@ -186,7 +187,7 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
             const VPiece p = CreatePiece();
             visPath->SetPiece(p);
 
-            if (p.CountNodes() == 1)
+            if (p.GetPath().CountNodes() == 1)
             {
                 emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
                                 "<b>Enter</b> - finish creation"));
@@ -329,7 +330,7 @@ void DialogSeamAllowance::NodeChanged(int index)
         const int nodeIndex = piece.indexOfNode(id);
         if (nodeIndex != -1)
         {
-            const VPieceNode &node = piece.at(nodeIndex);
+            const VPieceNode &node = piece.GetPath().at(nodeIndex);
 
             ui->doubleSpinBoxSABefore->setEnabled(true);
             ui->doubleSpinBoxSAAfter->setEnabled(true);
@@ -437,7 +438,7 @@ VPiece DialogSeamAllowance::CreatePiece() const
     for (qint32 i = 0; i < ui->listWidget->count(); ++i)
     {
         QListWidgetItem *item = ui->listWidget->item(i);
-        piece.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
+        piece.GetPath().Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
     }
 
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
@@ -530,9 +531,9 @@ void DialogSeamAllowance::InitNodesList()
 
     const VPiece piece = CreatePiece();
 
-    for (int i = 0; i < piece.CountNodes(); ++i)
+    for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
     {
-        const VPieceNode node = piece.at(i);
+        const VPieceNode node = piece.GetPath().at(i);
         if (node.GetTypeTool() == Tool::NodePoint)
         {
             const QString name = GetNodeName(node);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 1bf5663b4..cfdc2892d 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -29,6 +29,7 @@
 #include "vtoolseamallowance.h"
 #include "../dialogs/tools/dialogseamallowance.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpiecepath.h"
 #include "nodeDetails/vnodearc.h"
 #include "nodeDetails/vnodepoint.h"
 #include "nodeDetails/vnodespline.h"
@@ -88,10 +89,10 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
     VPiece detail = dialogTool->GetPiece();
     QVector<VPieceNode> nodes;
     qApp->getUndoStack()->beginMacro("add detail");
-    for (int i = 0; i< detail.CountNodes(); ++i)
+    for (int i = 0; i< detail.GetPath().CountNodes(); ++i)
     {
         quint32 id = 0;
-        VPieceNode nodeD = detail.at(i);
+        VPieceNode nodeD = detail.GetPath().at(i);
         switch (nodeD.GetTypeTool())
         {
             case (Tool::NodePoint):
@@ -142,7 +143,7 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
         nodes.append(nodeD);
     }
 
-    detail.SetNodes(nodes);
+    detail.GetPath().SetNodes(nodes);
     VToolSeamAllowance *piece = Create(0, detail, scene, doc, data, Document::FullParse, Source::FromGui);
 
     if (piece != nullptr)
@@ -252,12 +253,12 @@ void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement,
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
-    if (piece.CountNodes() > 0)
+    if (piece.GetPath().CountNodes() > 0)
     {
         QDomElement nodesElement = doc->createElement(TagNodes);
-        for (int i = 0; i < piece.CountNodes(); ++i)
+        for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
         {
-            AddNode(doc, nodesElement, piece.at(i));
+            AddNode(doc, nodesElement, piece.GetPath().at(i));
         }
         domElement.appendChild(nodesElement);
     }
@@ -635,24 +636,24 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
       m_seamAllowance(new VNoBrushScalePathItem(this))
 {
     VPiece detail = data->GetPiece(id);
-    for (int i = 0; i< detail.CountNodes(); ++i)
+    for (int i = 0; i< detail.GetPath().CountNodes(); ++i)
     {
-        switch (detail.at(i).GetTypeTool())
+        switch (detail.GetPath().at(i).GetTypeTool())
         {
             case (Tool::NodePoint):
             {
-                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.at(i));
+                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.GetPath().at(i));
                 connect(tool, &VNodePoint::ShowContextMenu, this, &VToolSeamAllowance::contextMenuEvent);
                 break;
             }
             case (Tool::NodeArc):
-                doc->IncrementReferens(detail.at(i).GetId());
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
                 break;
             case (Tool::NodeSpline):
-                doc->IncrementReferens(detail.at(i).GetId());
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
                 break;
             case (Tool::NodeSplinePath):
-                doc->IncrementReferens(detail.at(i).GetId());
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
                 break;
             default:
                 qDebug()<<"Get wrong tool type. Ignore.";
diff --git a/src/libs/vtools/undocommands/addpiece.cpp b/src/libs/vtools/undocommands/addpiece.cpp
index e9d96e56c..185ac804f 100644
--- a/src/libs/vtools/undocommands/addpiece.cpp
+++ b/src/libs/vtools/undocommands/addpiece.cpp
@@ -28,6 +28,7 @@
 
 #include "addpiece.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpiecepath.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 AddPiece::AddPiece(const QDomElement &xml, VAbstractPattern *doc, const VPiece &detail, const QString &drawName,
@@ -61,7 +62,7 @@ void AddPiece::undo()
                 return;
             }
 
-            DecrementReferences(m_detail.GetNodes());
+            DecrementReferences(m_detail.GetPath().GetNodes());
         }
         else
         {
diff --git a/src/libs/vtools/undocommands/deletepiece.cpp b/src/libs/vtools/undocommands/deletepiece.cpp
index 44d79a54e..1aea7088c 100644
--- a/src/libs/vtools/undocommands/deletepiece.cpp
+++ b/src/libs/vtools/undocommands/deletepiece.cpp
@@ -39,6 +39,7 @@
 #include "../tools/vdatatool.h"
 #include "vundocommand.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpiecepath.h"
 
 class QUndoCommand;
 
@@ -105,7 +106,7 @@ void DeletePiece::redo()
         SCASSERT(toolDet != nullptr);
         toolDet->hide();
 
-        DecrementReferences(m_detail.GetNodes());
+        DecrementReferences(m_detail.GetPath().GetNodes());
         emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
     }
     else
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index 695c9cb9a..f2457842b 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -27,6 +27,7 @@
  *************************************************************************/
 
 #include "vistoolpiece.h"
+#include "../vpatterndb/vpiecepath.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VisToolPiece::VisToolPiece(const VContainer *data, QGraphicsItem *parent)
@@ -49,7 +50,7 @@ void VisToolPiece::RefreshGeometry()
 {
     HideAllItems();
 
-    if (m_piece.CountNodes() > 0)
+    if (m_piece.GetPath().CountNodes() > 0)
     {
         DrawPath(this, m_piece.MainPathPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
 
@@ -99,7 +100,6 @@ void VisToolPiece::HideAllItems()
         m_line2->setVisible(false);
     }
 
-    QVector<QGraphicsEllipseItem *> m_points;
     for (int i=0; i < m_points.size(); ++i)
     {
         if (QGraphicsEllipseItem *item = m_points.at(i))

From bb39410296fe684a0e0d24c2d7a6b0ff0af3046b Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 13:57:12 +0200
Subject: [PATCH 077/208] Added visualization creating a path.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 130 ++++++++++--------
 .../vtools/dialogs/tools/dialogpiecepath.h    |   6 +-
 .../visualization/path/vistoolpiecepath.cpp   | 100 ++++++++++++++
 .../visualization/path/vistoolpiecepath.h     |  63 +++++++++
 .../vtools/visualization/visualization.pri    |   6 +-
 5 files changed, 242 insertions(+), 63 deletions(-)
 create mode 100644 src/libs/vtools/visualization/path/vistoolpiecepath.cpp
 create mode 100644 src/libs/vtools/visualization/path/vistoolpiecepath.h

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index fa119d6bf..a33edaeee 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -29,6 +29,7 @@
 #include "dialogpiecepath.h"
 #include "ui_dialogpiecepath.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "visualization/path/vistoolpiecepath.h"
 
 #include <QMenu>
 
@@ -36,7 +37,7 @@
 DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
     ui(new Ui::DialogPiecePath),
-    m_showMode(true)
+    m_showMode(false)
 {
     ui->setupUi(this);
     InitOkCancel(ui);
@@ -49,15 +50,13 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
 
     if (not m_showMode)
     {
-        //vis = new VisToolPiecePath(data);
+        vis = new VisToolPiecePath(data);
     }
     else
     {
         ui->comboBoxType->setDisabled(true);
         ui->comboBoxPiece->setDisabled(true);
     }
-
-    show();//temporary
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -108,22 +107,22 @@ void DialogPiecePath::ChosenObject(quint32 id, const SceneObject &type)
 
         if (not m_showMode)
         {
-//        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
-//        SCASSERT(visPath != nullptr);
-//        const VPiecePath p = CreatePath();
-//        visPath->SetPath(p);
+            auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+            SCASSERT(visPath != nullptr);
+            const VPiecePath p = CreatePath();
+            visPath->SetPath(p);
 
-//        if (p.CountNodes() == 1)
-//        {
-//            emit ToolTip(tr("Select main path objects, <b>Shift</b> - reverse direction curve, "
-//                            "<b>Enter</b> - finish creation"));
+            if (p.CountNodes() == 1)
+            {
+                emit ToolTip(tr("Select main path objects, <b>Shift</b> - reverse direction curve, "
+                                "<b>Enter</b> - finish creation"));
 
-//            visPath->VisualMode(NULL_ID);
-//        }
-//        else
-//        {
-//            visPath->RefreshGeometry();
-//        }
+                visPath->VisualMode(NULL_ID);
+            }
+            else
+            {
+                visPath->RefreshGeometry();
+            }
         }
     }
 }
@@ -138,10 +137,10 @@ void DialogPiecePath::ShowDialog(bool click)
 
         if (not m_showMode)
         {
-//            auto visPath = qobject_cast<VisToolPiecePath *>(vis);
-//            SCASSERT(visPath != nullptr);
-//            visPath->SetMode(Mode::Show);
-//            visPath->RefreshGeometry();
+            auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+            SCASSERT(visPath != nullptr);
+            visPath->SetMode(Mode::Show);
+            visPath->RefreshGeometry();
         }
         setModal(true);
         show();
@@ -206,10 +205,10 @@ void DialogPiecePath::ListChanged()
 {
     if (not m_showMode)
     {
-//        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
-//        SCASSERT(visPath != nullptr);
-//        visPath->SetPiece(CreatePath());
-//        visPath->RefreshGeometry();
+        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+        SCASSERT(visPath != nullptr);
+        visPath->SetPath(CreatePath());
+        visPath->RefreshGeometry();
     }
 }
 
@@ -230,49 +229,64 @@ void DialogPiecePath::NameChanged()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-//VPiecePath DialogPiecePath::GetPiecePath() const
-//{
-
-//}
+VPiecePath DialogPiecePath::GetPiecePath() const
+{
+    return CreatePath();
+}
 
 //---------------------------------------------------------------------------------------------------------------------
-//void DialogPiecePath::SetPiecePath(const VPiecePath &path)
-//{
+void DialogPiecePath::SetPiecePath(const VPiecePath &path)
+{
+    ui->listWidget->clear();
+    for (int i = 0; i < path.CountNodes(); ++i)
+    {
+        NewItem(path.at(i));
+    }
 
-//}
+    ValidObjects(PathIsValid());
+
+    ListChanged();
+}
 
 //---------------------------------------------------------------------------------------------------------------------
-//VPiecePath DialogPiecePath::CreatePath() const
-//{
+VPiecePath DialogPiecePath::CreatePath() const
+{
+    VPiecePath path;
+    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidget->item(i);
+        path.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
+    }
 
-//}
+    return path;
+}
 
 //---------------------------------------------------------------------------------------------------------------------
 bool DialogPiecePath::PathIsValid() const
 {
-//    QString url = DialogWarningIcon();
+    QString url = DialogWarningIcon();
 
-//    if(CreatePath().Points(data).count() < 2)
-//    {
-//        url += tr("You need more points!");
-//        ui->helpLabel->setText(url);
-//        return false;
-//    }
-//    else
-//    {
-//        if (FirstPointEqualLast(ui->listWidget))
-//        {
-//            url += tr("First point cannot be equal to the last point!");
-//            ui->helpLabel->setText(url);
-//            return false;
-//        }
-//        else if (DoublePoints(ui->listWidget))
-//        {
-//            url += tr("You have double points!");
-//            ui->helpLabel->setText(url);
-//            return false;
-//        }
-//    }
+    if(CreatePath().PathPoints(data).count() < 2)
+    {
+        url += tr("You need more points!");
+        ui->helpLabel->setText(url);
+        return false;
+    }
+    else
+    {
+        if (FirstPointEqualLast(ui->listWidget))
+        {
+            url += tr("First point cannot be equal to the last point!");
+            ui->helpLabel->setText(url);
+            return false;
+        }
+        else if (DoublePoints(ui->listWidget))
+        {
+            url += tr("You have double points!");
+            ui->helpLabel->setText(url);
+            return false;
+        }
+    }
     ui->helpLabel->setText(tr("Ready!"));
     return true;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index f1d10f965..78a1056de 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -45,8 +45,8 @@ public:
 
     void DisableShowMode(bool disable);
 
-//    VPiecePath GetPiecePath() const;
-//    void       SetPiecePath(const VPiecePath &path);
+    VPiecePath GetPiecePath() const;
+    void       SetPiecePath(const VPiecePath &path);
 
 public slots:
     virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
@@ -67,7 +67,7 @@ private:
     Ui::DialogPiecePath *ui;
     bool m_showMode;
 
-//    VPiecePath CreatePath() const;
+    VPiecePath CreatePath() const;
 
     bool PathIsValid() const;
     void ValidObjects(bool value);
diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
new file mode 100644
index 000000000..a6755dbcc
--- /dev/null
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
@@ -0,0 +1,100 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vistoolpiecepath.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VisToolPiecePath::VisToolPiecePath(const VContainer *data, QGraphicsItem *parent)
+    : VisPath(data, parent),
+      m_points(),
+      m_line(nullptr),
+      m_path()
+{
+    m_line = InitItem<QGraphicsLineItem>(supportColor, this);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VisToolPiecePath::~VisToolPiecePath()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiecePath::RefreshGeometry()
+{
+    HideAllItems();
+
+    if (m_path.CountNodes() > 0)
+    {
+        DrawPath(this, m_path.PainterPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
+
+        const QVector<QPointF> nodes = m_path.PathNodePoints(Visualization::data);
+
+        for (int i = 0; i < nodes.size(); ++i)
+        {
+            QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
+            DrawPoint(point, nodes.at(i), supportColor);
+        }
+
+        if (mode == Mode::Creation)
+        {
+            const QVector<QPointF> points = m_path.PathPoints(Visualization::data);
+            if (points.size() > 0)
+            {
+                DrawLine(m_line, QLineF(points.last(), Visualization::scenePos), supportColor, Qt::DashLine);
+            }
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiecePath::SetPath(const VPiecePath &path)
+{
+    m_path = path;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QGraphicsEllipseItem *VisToolPiecePath::GetPoint(quint32 i, const QColor &color)
+{
+    return GetPointItem(Visualization::data, factor, m_points, i, color, this);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiecePath::HideAllItems()
+{
+    if (m_line)
+    {
+        m_line->setVisible(false);
+    }
+
+    for (int i=0; i < m_points.size(); ++i)
+    {
+        if (QGraphicsEllipseItem *item = m_points.at(i))
+        {
+            item->setVisible(false);
+        }
+    }
+}
diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.h b/src/libs/vtools/visualization/path/vistoolpiecepath.h
new file mode 100644
index 000000000..dc5c8d08e
--- /dev/null
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.h
@@ -0,0 +1,63 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   22 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VISTOOLPIECEPATH_H
+#define VISTOOLPIECEPATH_H
+
+#include <QtCore/QObject>
+#include <QtGlobal>
+
+#include "vispath.h"
+#include "../vpatterndb/vpiecepath.h"
+
+class VisToolPiecePath : public VisPath
+{
+    Q_OBJECT
+public:
+    VisToolPiecePath(const VContainer *data, QGraphicsItem *parent = nullptr);
+    virtual ~VisToolPiecePath();
+
+    virtual void RefreshGeometry() Q_DECL_OVERRIDE;
+    void         SetPath(const VPiecePath &piece);
+    virtual int  type() const Q_DECL_OVERRIDE {return Type;}
+    enum { Type = UserType + static_cast<int>(Vis::ToolPiecePath)};
+
+private:
+    Q_DISABLE_COPY(VisToolPiecePath)
+    QVector<QGraphicsEllipseItem *> m_points;
+
+    QGraphicsLineItem *m_line;
+
+    VPiecePath m_path;
+
+    QGraphicsEllipseItem* GetPoint(quint32 i, const QColor &color);
+
+    void HideAllItems();
+};
+
+#endif // VISTOOLPIECEPATH_H
diff --git a/src/libs/vtools/visualization/visualization.pri b/src/libs/vtools/visualization/visualization.pri
index 7f16b5713..30de372b5 100644
--- a/src/libs/vtools/visualization/visualization.pri
+++ b/src/libs/vtools/visualization/visualization.pri
@@ -38,7 +38,8 @@ HEADERS += \
     $$PWD/line/operation/visoperation.h \
     $$PWD/line/operation/vistoolflippingbyaxis.h \
     $$PWD/line/operation/vistoolmove.h \
-    $$PWD/path/vistoolpiece.h
+    $$PWD/path/vistoolpiece.h \
+    $$PWD/path/vistoolpiecepath.h
 
 SOURCES += \
     $$PWD/visualization.cpp \
@@ -77,4 +78,5 @@ SOURCES += \
     $$PWD/line/operation/visoperation.cpp \
     $$PWD/line/operation/vistoolflippingbyaxis.cpp \
     $$PWD/line/operation/vistoolmove.cpp \
-    $$PWD/path/vistoolpiece.cpp
+    $$PWD/path/vistoolpiece.cpp \
+    $$PWD/path/vistoolpiecepath.cpp

From 6793bb69f111c6fbe410bed54c85e9115e6d79f1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 14:50:30 +0200
Subject: [PATCH 078/208] Some updates for dialog.

--HG--
branch : feature
---
 src/libs/vmisc/def.h                          |  2 +
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 50 +++++++++++++++++--
 .../vtools/dialogs/tools/dialogpiecepath.h    |  5 ++
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index 7d680bd38..e8e14fa8f 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -74,6 +74,8 @@ enum class PieceNodeAngle : unsigned char
     BySecondEdgeRightAngle
 };
 
+enum class PiecePathType :  unsigned char {CutomSeamAllowance, InternalPath};
+
 typedef unsigned char ToolVisHolderType;
 enum class Tool : ToolVisHolderType
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index a33edaeee..792c5d4a6 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -42,12 +42,16 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     ui->setupUi(this);
     InitOkCancel(ui);
 
+    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
+
+    InitPathTypes();
+    connect(ui->comboBoxType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+            [this](){ValidObjects(PathIsValid());});
+
     flagName = true;//We have default name of piece.
     flagError = PathIsValid();
     CheckState();
 
-    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
-
     if (not m_showMode)
     {
         vis = new VisToolPiecePath(data);
@@ -155,7 +159,7 @@ void DialogPiecePath::SaveData()
 void DialogPiecePath::CheckState()
 {
     SCASSERT(bOk != nullptr);
-    bOk->setEnabled(flagName && flagError && ui->comboBoxPiece->count() > 0);
+    bOk->setEnabled(flagName && flagError);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -228,6 +232,13 @@ void DialogPiecePath::NameChanged()
     CheckState();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::InitPathTypes()
+{
+    ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CutomSeamAllowance));
+    //ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath DialogPiecePath::GetPiecePath() const
 {
@@ -248,6 +259,29 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
     ListChanged();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+PiecePathType DialogPiecePath::GetType() const
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const PiecePathType type =
+            static_cast<PiecePathType>(ui->comboBoxType->itemData(ui->comboBoxType->currentIndex()).toInt());
+#else
+    const PiecePathType type = static_cast<PiecePathType>(ui->comboBoxType->currentData().toInt());
+#endif
+
+    return type;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetType(PiecePathType type)
+{
+    const qint32 index = ui->comboBoxType->findData(static_cast<int>(type));
+    if (index != -1)
+    {
+        ui->comboBoxType->setCurrentIndex(index);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath DialogPiecePath::CreatePath() const
 {
@@ -274,7 +308,7 @@ bool DialogPiecePath::PathIsValid() const
     }
     else
     {
-        if (FirstPointEqualLast(ui->listWidget))
+        if (GetType() == PiecePathType::CutomSeamAllowance && FirstPointEqualLast(ui->listWidget))
         {
             url += tr("First point cannot be equal to the last point!");
             ui->helpLabel->setText(url);
@@ -287,6 +321,14 @@ bool DialogPiecePath::PathIsValid() const
             return false;
         }
     }
+
+    if (m_showMode && ui->comboBoxPiece->count() <= 0)
+    {
+        url += tr("List of pieces is empty!");
+        ui->helpLabel->setText(url);
+        return false;
+    }
+
     ui->helpLabel->setText(tr("Ready!"));
     return true;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 78a1056de..fcd347b5a 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -48,6 +48,9 @@ public:
     VPiecePath GetPiecePath() const;
     void       SetPiecePath(const VPiecePath &path);
 
+    PiecePathType GetType() const;
+    void          SetType(PiecePathType type);
+
 public slots:
     virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
     virtual void ShowDialog(bool click) Q_DECL_OVERRIDE;
@@ -67,6 +70,8 @@ private:
     Ui::DialogPiecePath *ui;
     bool m_showMode;
 
+    void InitPathTypes();
+
     VPiecePath CreatePath() const;
 
     bool PathIsValid() const;

From 34e5fd2cebbda39eb66b68cdf136dbdd180ec58d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:36:37 +0200
Subject: [PATCH 079/208] Check size of pieces list in "Create mode".

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 792c5d4a6..b95a50b96 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -322,7 +322,7 @@ bool DialogPiecePath::PathIsValid() const
         }
     }
 
-    if (m_showMode && ui->comboBoxPiece->count() <= 0)
+    if (not m_showMode && ui->comboBoxPiece->count() <= 0)
     {
         url += tr("List of pieces is empty!");
         ui->helpLabel->setText(url);

From 826411d595cbdb703113eef1d3d5fdc8febe00e9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:38:08 +0200
Subject: [PATCH 080/208] Make method GetActivDrawElement protected.

--HG--
branch : feature
---
 src/libs/ifc/xml/vabstractpattern.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index d5036b3f0..86e38028e 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -77,7 +77,6 @@ public:
     bool           ChangeNamePP(const QString& oldName, const QString &newName);
     bool           appendPP(const QString& name);
 
-    bool           GetActivDrawElement(QDomElement &element) const;
     bool           GetActivNodeElement(const QString& name, QDomElement& element) const;
 
     quint32        getCursor() const;
@@ -342,7 +341,8 @@ protected:
 
     void           SetChildTag(const QString& qsParent, const QString& qsChild, const QString& qsValue);
 
-    int GetIndexActivPP() const;
+    int  GetIndexActivPP() const;
+    bool GetActivDrawElement(QDomElement &element) const;
 private:
     Q_DISABLE_COPY(VAbstractPattern)
 
@@ -360,6 +360,7 @@ private:
     bool IsFunction(const QString& token) const;
 
     QPair<bool, QMap<quint32, quint32> > ParseItemElement(const QDomElement &domElement);
+
 };
 
 //---------------------------------------------------------------------------------------------------------------------

From 965e588a9d9b604ab2ccba518297fdf0c5173322 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:40:27 +0200
Subject: [PATCH 081/208] New piece attribute "united".

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           |  1 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd       |  1 +
 src/libs/vpatterndb/vpiece.cpp               | 12 ++++++++++++
 src/libs/vpatterndb/vpiece.h                 |  3 +++
 src/libs/vpatterndb/vpiece_p.h               |  7 +++++--
 src/libs/vtools/tools/vtoolseamallowance.cpp |  2 ++
 src/libs/vtools/tools/vtoolseamallowance.h   |  1 +
 7 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 595fbae13..a7ddee41c 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -624,6 +624,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetForbidFlipping(GetParametrBool(domElement, VToolSeamAllowance::AttrForbidFlipping,
                                            QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
+        detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
         const QStringList tags = QStringList() << VToolSeamAllowance::TagNodes
                                                << TagData
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 0562a84f1..fb24ee3e9 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -420,6 +420,7 @@
                                                                            <xs:attribute name="forbidFlipping" type="xs:boolean"></xs:attribute>
                                                                            <xs:attribute name="width" type="xs:double"></xs:attribute>
                                                                            <xs:attribute name="seamAllowance" type="xs:boolean"></xs:attribute>
+                                                                           <xs:attribute name="united" type="xs:boolean"></xs:attribute>
                                                                      </xs:complexType>
                                                                </xs:element>
                                                          </xs:sequence>
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 1d0fafc0d..b876ff8c6 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -219,6 +219,18 @@ void VPiece::SetInLayout(bool inLayout)
     d->m_inLayout = inLayout;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VPiece::IsUnited() const
+{
+    return d->m_united;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetUnited(bool united)
+{
+    d->m_united = united;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 243332d8d..1c17e3f2d 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -72,6 +72,9 @@ public:
     bool IsInLayout() const;
     void SetInLayout(bool inLayout);
 
+    bool IsUnited() const;
+    void SetUnited(bool united);
+
     QVector<VPieceNode> Missing(const VPiece &det) const;
 
     int indexOfNode(const quint32 &id) const;
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index ebb7acd6c..0511d4ae5 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -46,7 +46,8 @@ public:
         : m_path(),
           m_mx(0),
           m_my(0),
-          m_inLayout(true)
+          m_inLayout(true),
+          m_united(false)
     {}
 
     VPieceData(const VPieceData &detail)
@@ -54,7 +55,8 @@ public:
           m_path(detail.m_path),
           m_mx(detail.m_mx),
           m_my(detail.m_my),
-          m_inLayout(detail.m_inLayout)
+          m_inLayout(detail.m_inLayout),
+          m_united(detail.m_united)
     {}
 
     ~VPieceData();
@@ -66,6 +68,7 @@ public:
     qreal m_my;
 
     bool m_inLayout;
+    bool m_united;
 
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index cfdc2892d..aa6c46758 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -67,6 +67,7 @@ const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllow
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
 const QString VToolSeamAllowance::AttrSABefore       = QStringLiteral("before");
 const QString VToolSeamAllowance::AttrSAAfter        = QStringLiteral("after");
+const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 
 const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
 const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
@@ -278,6 +279,7 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrForbidFlipping, piece.IsForbidFlipping());
     doc->SetAttribute(domElement, AttrSeamAllowance, piece.IsSeamAllowance());
     doc->SetAttribute(domElement, AttrWidth, piece.GetSAWidth());
+    doc->SetAttribute(domElement, AttrUnited, piece.IsUnited());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 8b1a76764..04605a66e 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -64,6 +64,7 @@ public:
     static const QString AttrWidth;
     static const QString AttrSABefore;
     static const QString AttrSAAfter;
+    static const QString AttrUnited;
 
     static const QString NodeArc;
     static const QString NodePoint;

From 524e98d3728fec2e5c0c7d9bd32f8fa0a9d1f100 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:41:01 +0200
Subject: [PATCH 082/208] Get active pattern piece list of pieces.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp              | 16 ++++++-
 src/app/valentina/xml/vpattern.cpp            | 25 ++++++++++
 src/app/valentina/xml/vpattern.h              |  2 +
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 46 +++++++++++++++++++
 .../vtools/dialogs/tools/dialogpiecepath.h    |  6 +++
 src/libs/vtools/dialogs/tools/dialogtool.cpp  |  6 +++
 src/libs/vtools/dialogs/tools/dialogtool.h    |  1 +
 7 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index de188950a..ec5234dbf 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -58,6 +58,7 @@
 #include "dialogs/vwidgetgroups.h"
 #include "../vtools/undocommands/addgroup.h"
 #include "dialogs/vwidgetdetails.h"
+#include "../vpatterndb/vpiecepath.h"
 
 #include <QInputDialog>
 #include <QtDebug>
@@ -558,9 +559,16 @@ void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, cons
         ui->view->setShowToolOptions(false);
         dialogTool = new Dialog(pattern, 0, this);
 
-        if (t == Tool::Midpoint)
+        switch(t)
         {
-            dialogTool->Build(t);
+            case Tool::Midpoint:
+                dialogTool->Build(t);
+                break;
+            case Tool::PiecePath:
+                dialogTool->SetPiecesList(doc->GetActivePPPieces());
+                break;
+            default:
+                break;
         }
 
         VMainGraphicsScene *scene = qobject_cast<VMainGraphicsScene *>(currentScene);
@@ -1121,8 +1129,12 @@ void MainWindow::ClosedDialogPiecePath(int result)
         DialogPiecePath *dialog = qobject_cast<DialogPiecePath*>(dialogTool);
         SCASSERT(dialog != nullptr);
 
+        const PiecePathType type = dialog->GetType();
+        const VPiecePath path = dialog->GetPiecePath();
+        //VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
     }
     ArrowTool();
+    doc->LiteParseTree(Document::LiteParse);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index a7ddee41c..65e808953 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -350,6 +350,31 @@ quint32 VPattern::SPointActiveDraw()
     return 0;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VPattern::GetActivePPPieces() const
+{
+    QVector<quint32> pieces;
+    QDomElement drawElement;
+    if (GetActivDrawElement(drawElement))
+    {
+        const QDomElement details = drawElement.firstChildElement(TagDetails);
+        if (not details.isNull())
+        {
+            QDomElement detail = details.firstChildElement(TagDetail);
+            while(not detail.isNull())
+            {
+                bool united = GetParametrBool(detail, VToolSeamAllowance::AttrUnited, falseStr);
+                if (not united)
+                {
+                    pieces.append(GetParametrId(detail));
+                }
+                detail = detail.nextSiblingElement(TagDetail);
+            }
+        }
+    }
+    return pieces;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool VPattern::SaveDocument(const QString &fileName, QString &error) const
 {
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 08ba4bfda..0992f1a68 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -59,6 +59,8 @@ public:
 
     quint32        SPointActiveDraw();
 
+    QVector<quint32> GetActivePPPieces() const;
+
     virtual void   setXMLContent(const QString &fileName) Q_DECL_OVERRIDE;
     virtual bool   SaveDocument(const QString &fileName, QString &error) const Q_DECL_OVERRIDE;
 
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index b95a50b96..bdb3a1426 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -282,6 +282,52 @@ void DialogPiecePath::SetType(PiecePathType type)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 DialogPiecePath::GetPieceId() const
+{
+    quint32 id = NULL_ID;
+
+    if (ui->comboBoxPiece->count() > 0)
+    {
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    id = ui->comboBoxPiece->itemData(ui->comboBoxPiece->currentIndex()).toUInt();
+#else
+    id = ui->comboBoxPiece->currentData().toUInt();
+#endif
+    }
+
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetPieceId(quint32 id)
+{
+    if (ui->comboBoxPiece->count() <= 0)
+    {
+        const VPiece piece = data->GetPiece(id);
+        ui->comboBoxPiece->addItem(piece.GetName(), id);
+    }
+    else
+    {
+        const qint32 index = ui->comboBoxPiece->findData(id);
+        if (index != -1)
+        {
+            ui->comboBoxType->setCurrentIndex(index);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetPiecesList(const QVector<quint32> &list)
+{
+    for (int i=0; i < list.size(); ++i)
+    {
+        const VPiece piece = data->GetPiece(list.at(i));
+        ui->comboBoxPiece->addItem(piece.GetName(), list.at(i));
+    }
+    ValidObjects(PathIsValid());
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath DialogPiecePath::CreatePath() const
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index fcd347b5a..443e0d60f 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -51,6 +51,11 @@ public:
     PiecePathType GetType() const;
     void          SetType(PiecePathType type);
 
+    quint32 GetPieceId() const;
+    void    SetPieceId(quint32 id);
+
+    virtual void SetPiecesList(const QVector<quint32> &list) Q_DECL_OVERRIDE;
+
 public slots:
     virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
     virtual void ShowDialog(bool click) Q_DECL_OVERRIDE;
@@ -71,6 +76,7 @@ private:
     bool m_showMode;
 
     void InitPathTypes();
+    void InitListPieces();
 
     VPiecePath CreatePath() const;
 
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp
index 11f9d808f..a26626ce4 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp
@@ -1073,6 +1073,12 @@ void DialogTool::Build(const Tool &type)
     Q_UNUSED(type);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogTool::SetPiecesList(const QVector<quint32> &list)
+{
+    Q_UNUSED(list);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogTool::SetAssociatedTool(VAbstractTool *tool)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h
index 313f45c34..46ed7d9fa 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.h
+++ b/src/libs/vtools/dialogs/tools/dialogtool.h
@@ -95,6 +95,7 @@ public:
 
     virtual void     ShowDialog(bool click);
     virtual void     Build(const Tool &type);
+    virtual void     SetPiecesList(const QVector<quint32> &list);
 
     quint32          GetToolId() const;
     void             SetToolId(const quint32 &value);

From 1a73a1f870f245ad2796d7cab5ef97677aa138fe Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:43:31 +0200
Subject: [PATCH 083/208] Set clear button for field Name.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index bdb3a1426..d98a5ac1e 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -42,6 +42,10 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     ui->setupUi(this);
     InitOkCancel(ui);
 
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+    ui->lineEditName->setClearButtonEnabled(true);
+#endif
+
     connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
 
     InitPathTypes();

From 8a5c4a1a37d9eda84f99f622b56bc64ffd5cc2fb Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 23 Nov 2016 18:50:52 +0200
Subject: [PATCH 084/208] Check if a path is valid. Should contains at least
 one object.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp              |  3 ++-
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 23 +++++++++++--------
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index ec5234dbf..16c4dcb00 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -964,7 +964,8 @@ void MainWindow::ToolDetail(bool checked)
 void MainWindow::ToolPiecePath(bool checked)
 {
     ToolSelectAllDrawObjects();
-    SetToolButton<DialogPiecePath>(checked, Tool::PiecePath, "://cursor/path_cursor.png", tr("Select path objects."),
+    SetToolButton<DialogPiecePath>(checked, Tool::PiecePath, "://cursor/path_cursor.png",
+                                   tr("Select path objects, <b>Shift</b> - reverse direction curve"),
                                    &MainWindow::ClosedDialogPiecePath);
 }
 
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index d98a5ac1e..89fd992b8 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -140,18 +140,21 @@ void DialogPiecePath::ShowDialog(bool click)
 {
     if (click == false)
     {
-        emit ToolTip("");
-        prepare = true;
-
-        if (not m_showMode)
+        if (CreatePath().CountNodes() > 0)
         {
-            auto visPath = qobject_cast<VisToolPiecePath *>(vis);
-            SCASSERT(visPath != nullptr);
-            visPath->SetMode(Mode::Show);
-            visPath->RefreshGeometry();
+            emit ToolTip("");
+            prepare = true;
+
+            if (not m_showMode)
+            {
+                auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+                SCASSERT(visPath != nullptr);
+                visPath->SetMode(Mode::Show);
+                visPath->RefreshGeometry();
+            }
+            setModal(true);
+            show();
         }
-        setModal(true);
-        show();
     }
 }
 

From 422fb60dccbfd701fa18356fbc2cfbc54123b820 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:26:51 +0200
Subject: [PATCH 085/208] Each path should know its type.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp                |  3 ---
 src/libs/vpatterndb/vpiece.cpp                  |  2 +-
 src/libs/vpatterndb/vpiece_p.h                  |  4 ++--
 src/libs/vpatterndb/vpiecepath.cpp              | 17 +++++++++++++++++
 src/libs/vpatterndb/vpiecepath.h                |  6 ++++++
 src/libs/vpatterndb/vpiecepath_p.h              | 12 ++++++++++--
 .../vtools/dialogs/tools/dialogpiecepath.cpp    |  4 ++++
 src/libs/vtools/dialogs/tools/dialogpiecepath.h |  6 +++---
 8 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 16c4dcb00..eaa12321c 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -1129,9 +1129,6 @@ void MainWindow::ClosedDialogPiecePath(int result)
     {
         DialogPiecePath *dialog = qobject_cast<DialogPiecePath*>(dialogTool);
         SCASSERT(dialog != nullptr);
-
-        const PiecePathType type = dialog->GetType();
-        const VPiecePath path = dialog->GetPiecePath();
         //VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
     }
     ArrowTool();
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index b876ff8c6..dd3560597 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -38,7 +38,7 @@
 
 //---------------------------------------------------------------------------------------------------------------------
 VPiece::VPiece()
-    : VAbstractPiece(), d(new VPieceData)
+    : VAbstractPiece(), d(new VPieceData(PiecePathType::PiecePath))
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 0511d4ae5..3ec5cf61e 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -42,8 +42,8 @@ QT_WARNING_DISABLE_GCC("-Weffc++")
 class VPieceData : public QSharedData
 {
 public:
-    VPieceData()
-        : m_path(),
+    VPieceData(PiecePathType type)
+        : m_path(type),
           m_mx(0),
           m_my(0),
           m_inLayout(true),
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index d9445cff3..9fbf124a2 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -39,6 +39,11 @@ VPiecePath::VPiecePath()
     : d(new VPiecePathData)
 {}
 
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath::VPiecePath(PiecePathType type)
+    : d(new VPiecePathData(type))
+{}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath::VPiecePath(const VPiecePath &path)
     : d (path.d)
@@ -101,6 +106,18 @@ void VPiecePath::SetNodes(const QVector<VPieceNode> &nodes)
     d->m_nodes = nodes;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+PiecePathType VPiecePath::GetType() const
+{
+    return d->m_type;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::SetType(PiecePathType type)
+{
+    d->m_type = type;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
 {
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index b85c34c6d..daa6893ca 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -32,6 +32,8 @@
 #include <QtGlobal>
 #include <QSharedDataPointer>
 
+#include "../vmisc/def.h"
+
 class VPiecePathData;
 class VPieceNode;
 class QPointF;
@@ -43,6 +45,7 @@ class VPiecePath
 {
 public:
     VPiecePath();
+    VPiecePath(PiecePathType type);
     VPiecePath(const VPiecePath &path);
     VPiecePath &operator=(const VPiecePath &path);
     ~VPiecePath();
@@ -57,6 +60,9 @@ public:
     QVector<VPieceNode> GetNodes() const;
     void                SetNodes(const QVector<VPieceNode> &nodes);
 
+    PiecePathType GetType() const;
+    void          SetType(PiecePathType type);
+
     QVector<QPointF> PathPoints(const VContainer *data) const;
     QVector<QPointF> PathNodePoints(const VContainer *data) const;
 
diff --git a/src/libs/vpatterndb/vpiecepath_p.h b/src/libs/vpatterndb/vpiecepath_p.h
index de8efc3b7..ea3ca04b4 100644
--- a/src/libs/vpatterndb/vpiecepath_p.h
+++ b/src/libs/vpatterndb/vpiecepath_p.h
@@ -42,17 +42,25 @@ class VPiecePathData : public QSharedData
 {
 public:
     VPiecePathData()
-        : m_nodes()
+        : m_nodes(),
+          m_type(PiecePathType::Unknown)
+    {}
+
+    VPiecePathData(PiecePathType type)
+        : m_nodes(),
+          m_type(type)
     {}
 
     VPiecePathData(const VPiecePathData &path)
         : QSharedData(path),
-          m_nodes(path.m_nodes)
+          m_nodes(path.m_nodes),
+          m_type(path.m_type)
     {}
 
     ~VPiecePathData();
 
     QVector<VPieceNode> m_nodes;
+    PiecePathType m_type;
 
 private:
     VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 89fd992b8..dd9c221ee 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -261,6 +261,8 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
         NewItem(path.at(i));
     }
 
+    SetType(path.GetType());
+
     ValidObjects(PathIsValid());
 
     ListChanged();
@@ -345,6 +347,8 @@ VPiecePath DialogPiecePath::CreatePath() const
         path.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
     }
 
+    path.SetType(GetType());
+
     return path;
 }
 
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 443e0d60f..6a9e3d6ef 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -48,9 +48,6 @@ public:
     VPiecePath GetPiecePath() const;
     void       SetPiecePath(const VPiecePath &path);
 
-    PiecePathType GetType() const;
-    void          SetType(PiecePathType type);
-
     quint32 GetPieceId() const;
     void    SetPieceId(quint32 id);
 
@@ -83,6 +80,9 @@ private:
     bool PathIsValid() const;
     void ValidObjects(bool value);
     void NewItem(const VPieceNode &node);
+
+    PiecePathType GetType() const;
+    void          SetType(PiecePathType type);
 };
 
 #endif // DIALOGPIECEPATH_H

From 024f1373f6fbf1314d5da03dee3913352d1fdb57 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:27:47 +0200
Subject: [PATCH 086/208] Undocommand SavePieceOptions. Don't need anymore
 pointer to scene.

--HG--
branch : feature
---
 src/libs/vtools/undocommands/savepieceoptions.cpp | 6 ++----
 src/libs/vtools/undocommands/savepieceoptions.h   | 3 +--
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index cb78ca455..d03657474 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -48,12 +48,10 @@ class QDomElement;
 class QUndoCommand;
 
 //---------------------------------------------------------------------------------------------------------------------
-SavePieceOptions::SavePieceOptions(const VPiece &oldDet, const VPiece &newDet, VAbstractPattern *doc, quint32 id,
-                                   QGraphicsScene *scene, QUndoCommand *parent)
+SavePieceOptions::SavePieceOptions(const VPiece &oldDet, const VPiece &newDet, VAbstractPattern *doc, quint32 id, QUndoCommand *parent)
     : VUndoCommand(QDomElement(), doc, parent),
       m_oldDet(oldDet),
-      m_newDet(newDet),
-      m_scene(scene)
+      m_newDet(newDet)
 {
     setText(tr("save detail option"));
     nodeId = id;
diff --git a/src/libs/vtools/undocommands/savepieceoptions.h b/src/libs/vtools/undocommands/savepieceoptions.h
index 306a0c4d0..c50ad4aed 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.h
+++ b/src/libs/vtools/undocommands/savepieceoptions.h
@@ -43,7 +43,7 @@ class SavePieceOptions : public VUndoCommand
 {
 public:
     SavePieceOptions(const VPiece &m_oldDet, const VPiece &m_newDet, VAbstractPattern *doc, quint32 id,
-                     QGraphicsScene *m_scene, QUndoCommand *parent = nullptr);
+                     QUndoCommand *parent = nullptr);
     virtual ~SavePieceOptions();
 
     virtual void undo() Q_DECL_OVERRIDE;
@@ -57,7 +57,6 @@ private:
 
     const VPiece    m_oldDet;
     VPiece          m_newDet;
-    QGraphicsScene *m_scene;
 };
 
 //---------------------------------------------------------------------------------------------------------------------

From 8182f2979b11da3bef9f40c72a02b311529ce9d1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:30:26 +0200
Subject: [PATCH 087/208] Save VPiecePath in VContainer class.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.cpp | 30 ++++++++++++++++++++++++++++++
 src/libs/vpatterndb/vcontainer.h   |  9 ++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index b64ecc6a3..d93c043ee 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -179,6 +179,19 @@ VPiece VContainer::GetPiece(quint32 id) const
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath VContainer::GetPiecePath(quint32 id) const
+{
+    if (d->piecePaths->contains(id))
+    {
+        return d->piecePaths->value(id);
+    }
+    else
+    {
+        throw VExceptionBadId(tr("Can't find object"), id);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief AddGObject add new GObject to container
@@ -214,6 +227,14 @@ quint32 VContainer::AddPiece(const VPiece &detail)
     return id;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 VContainer::AddPiecePath(const VPiecePath &path)
+{
+    const quint32 id = getNextId();
+    d->piecePaths->insert(id, path);
+    return id;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VContainer::getId()
 {
@@ -295,6 +316,7 @@ void VContainer::ClearForFullParse()
 
     d->details->clear();
     d->pieces->clear();
+    d->piecePaths->clear();
     ClearVariables(VarType::Increment);
     ClearVariables(VarType::LineAngle);
     ClearVariables(VarType::LineLength);
@@ -530,6 +552,14 @@ void VContainer::UpdatePiece(quint32 id, const VPiece &detail)
     UpdateId(id);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VContainer::UpdatePiecePath(quint32 id, const VPiecePath &path)
+{
+    Q_ASSERT_X(id != NULL_ID, Q_FUNC_INFO, "id == 0"); //-V654 //-V712
+    d->piecePaths->insert(id, path);
+    UpdateId(id);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 qreal VContainer::GetTableValue(const QString &name, MeasurementsType patternType) const
 {
diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index 726b6bbf9..f83a98238 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -55,6 +55,7 @@
 #include "variables/vinternalvariable.h"
 #include "vdetail.h"
 #include "vpiece.h"
+#include "vpiecepath.h"
 #include "vtranslatevars.h"
 
 class VAbstractCubicBezierPath;
@@ -83,7 +84,9 @@ public:
           variables(QHash<QString, QSharedPointer<VInternalVariable> > ()),
           details(QSharedPointer<QHash<quint32, VDetail>>(new QHash<quint32, VDetail>())),
           pieces(QSharedPointer<QHash<quint32, VPiece>>(new QHash<quint32, VPiece>())),
-          trVars(trVars), patternUnit(patternUnit)
+          piecePaths(QSharedPointer<QHash<quint32, VPiecePath>>(new QHash<quint32, VPiecePath>())),
+          trVars(trVars),
+          patternUnit(patternUnit)
     {}
 
     VContainerData(const VContainerData &data)
@@ -112,6 +115,7 @@ public:
      */
     QSharedPointer<QHash<quint32, VDetail>> details;
     QSharedPointer<QHash<quint32, VPiece>> pieces;
+    QSharedPointer<QHash<quint32, VPiecePath>> piecePaths;
 
     const VTranslateVars *trVars;
     const Unit *patternUnit;
@@ -140,6 +144,7 @@ public:
     static const QSharedPointer<VGObject> GetFakeGObject(quint32 id);
     const VDetail      GetDetail(quint32 id) const;
     VPiece             GetPiece(quint32 id) const;
+    VPiecePath         GetPiecePath(quint32 id) const;
     qreal              GetTableValue(const QString& name, MeasurementsType patternType) const;
     template <typename T>
     QSharedPointer<T>  GetVariable(QString name) const;
@@ -150,6 +155,7 @@ public:
     quint32            AddGObject(VGObject *obj);
     quint32            AddDetail(const VDetail &detail);
     quint32            AddPiece(const VPiece &detail);
+    quint32            AddPiecePath(const VPiecePath &path);
     void               AddLine(const quint32 &firstPointId, const quint32 &secondPointId);
     void               AddArc(const QSharedPointer<VArc> &arc, const quint32 &arcId, const quint32 &parentId = NULL_ID);
     void               AddSpline(const QSharedPointer<VAbstractBezier> &curve, quint32 id, quint32 parentId = NULL_ID);
@@ -163,6 +169,7 @@ public:
     void               UpdateGObject(quint32 id, VGObject* obj);
     void               UpdateDetail(quint32 id, const VDetail &detail);
     void               UpdatePiece(quint32 id, const VPiece &detail);
+    void               UpdatePiecePath(quint32 id, const VPiecePath &path);
 
     void               Clear();
     void               ClearForFullParse();

From 7f1bab1ac69eda2723a86091e61a982c47d9349e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:31:27 +0200
Subject: [PATCH 088/208] Fix typo.

--HG--
branch : feature
---
 src/libs/vmisc/def.h                              | 2 +-
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index e8e14fa8f..170b7eed0 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -74,7 +74,7 @@ enum class PieceNodeAngle : unsigned char
     BySecondEdgeRightAngle
 };
 
-enum class PiecePathType :  unsigned char {CutomSeamAllowance, InternalPath};
+enum class PiecePathType :  unsigned char {PiecePath = 0, CustomSeamAllowance = 1, InternalPath = 2, Unknown = 3};
 
 typedef unsigned char ToolVisHolderType;
 enum class Tool : ToolVisHolderType
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index dd9c221ee..7b54ad11e 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -242,7 +242,7 @@ void DialogPiecePath::NameChanged()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::InitPathTypes()
 {
-    ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CutomSeamAllowance));
+    ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CustomSeamAllowance));
     //ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
 }
 
@@ -365,7 +365,7 @@ bool DialogPiecePath::PathIsValid() const
     }
     else
     {
-        if (GetType() == PiecePathType::CutomSeamAllowance && FirstPointEqualLast(ui->listWidget))
+        if (GetType() == PiecePathType::CustomSeamAllowance && FirstPointEqualLast(ui->listWidget))
         {
             url += tr("First point cannot be equal to the last point!");
             ui->helpLabel->setText(url);

From 0e78efc71464da9c5ee4bafde78bdab5a0e792b0 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:35:07 +0200
Subject: [PATCH 089/208] Move tag strings from VToolSeamAllowance class to
 VAbstractPattern class. The same strings use also VToolPiecePath class.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           | 18 +++++++-------
 src/libs/ifc/xml/vabstractpattern.cpp        |  9 +++++++
 src/libs/ifc/xml/vabstractpattern.h          |  9 +++++++
 src/libs/vtools/tools/vtoolseamallowance.cpp | 25 +++++++-------------
 src/libs/vtools/tools/vtoolseamallowance.h   |  9 -------
 5 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 65e808953..77962e3ea 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -651,7 +651,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
         detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
-        const QStringList tags = QStringList() << VToolSeamAllowance::TagNodes
+        const QStringList tags = QStringList() << VAbstractPattern::TagNodes
                                                << TagData
                                                << TagPatternInfo
                                                << TagGrainline;
@@ -664,7 +664,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
             {
                 switch (tags.indexOf(element.tagName()))
                 {
-                    case 0:// VToolSeamAllowance::TagNodes
+                    case 0:// VAbstractPattern::TagNodes
                         ParseDetailNodes(element, detail);
                         break;
                     case 1:// TagData
@@ -763,24 +763,24 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //---------------------------------------------------------------------------------------------------------------------
 void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const
 {
-    const QStringList types = QStringList() << VToolSeamAllowance::NodePoint
-                                            << VToolSeamAllowance::NodeArc
-                                            << VToolSeamAllowance::NodeSpline
-                                            << VToolSeamAllowance::NodeSplinePath;
+    const QStringList types = QStringList() << VAbstractPattern::NodePoint
+                                            << VAbstractPattern::NodeArc
+                                            << VAbstractPattern::NodeSpline
+                                            << VAbstractPattern::NodeSplinePath;
 
     const QDomNodeList nodeList = domElement.childNodes();
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagNode)
+        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
         {
             const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-            const bool reverse = GetParametrUInt(element, VToolSeamAllowance::AttrNodeReverse, "0");
+            const bool reverse = GetParametrUInt(element, VAbstractPattern::AttrNodeReverse, "0");
             const qreal saBefore = GetParametrDouble(element, VToolSeamAllowance::AttrSABefore, "-1");
             const qreal saAfter = GetParametrDouble(element, VToolSeamAllowance::AttrSAAfter, "-1");
             const PieceNodeAngle angle = static_cast<PieceNodeAngle>(GetParametrUInt(element, AttrAngle, "0"));
 
-            const QString t = GetParametrString(element, AttrType, VToolSeamAllowance::NodePoint);
+            const QString t = GetParametrString(element, AttrType, VAbstractPattern::NodePoint);
             Tool tool;
 
             switch (types.indexOf(t))
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index 974d9f9ce..3dd8510ad 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -89,6 +89,9 @@ const QString VAbstractPattern::TagSize             = QStringLiteral("size");
 const QString VAbstractPattern::TagShowDate         = QStringLiteral("showDate");
 const QString VAbstractPattern::TagShowMeasurements = QStringLiteral("showMeasurements");
 const QString VAbstractPattern::TagGrainline        = QStringLiteral("grainline");
+const QString VAbstractPattern::TagPath             = QStringLiteral("path");
+const QString VAbstractPattern::TagNodes            = QStringLiteral("nodes");
+const QString VAbstractPattern::TagNode             = QStringLiteral("node");
 
 const QString VAbstractPattern::AttrName            = QStringLiteral("name");
 const QString VAbstractPattern::AttrVisible         = QStringLiteral("visible");
@@ -101,6 +104,7 @@ const QString VAbstractPattern::AttrUserDefined     = QStringLiteral("userDef");
 const QString VAbstractPattern::AttrCutNumber       = QStringLiteral("cutNumber");
 const QString VAbstractPattern::AttrPlacement       = QStringLiteral("placement");
 const QString VAbstractPattern::AttrArrows          = QStringLiteral("arrows");
+const QString VAbstractPattern::AttrNodeReverse     = QStringLiteral("reverse");
 
 const QString VAbstractPattern::AttrAll             = QStringLiteral("all");
 
@@ -158,6 +162,11 @@ const QString VAbstractPattern::IncrementName        = QStringLiteral("name");
 const QString VAbstractPattern::IncrementFormula     = QStringLiteral("formula");
 const QString VAbstractPattern::IncrementDescription = QStringLiteral("description");
 
+const QString VAbstractPattern::NodeArc        = QStringLiteral("NodeArc");
+const QString VAbstractPattern::NodePoint      = QStringLiteral("NodePoint");
+const QString VAbstractPattern::NodeSpline     = QStringLiteral("NodeSpline");
+const QString VAbstractPattern::NodeSplinePath = QStringLiteral("NodeSplinePath");
+
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPattern::VAbstractPattern(QObject *parent)
     : QObject(parent), VDomDocument(), nameActivPP(QString()), cursor(0), tools(QHash<quint32, VDataTool*>()),
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index 86e38028e..d951656a5 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -193,6 +193,9 @@ public:
     static const QString TagShowDate;
     static const QString TagShowMeasurements;
     static const QString TagGrainline;
+    static const QString TagPath;
+    static const QString TagNodes;
+    static const QString TagNode;
 
     static const QString AttrName;
     static const QString AttrVisible;
@@ -205,6 +208,7 @@ public:
     static const QString AttrCutNumber;
     static const QString AttrPlacement;
     static const QString AttrArrows;
+    static const QString AttrNodeReverse;
 
     static const QString AttrAll;
 
@@ -262,6 +266,11 @@ public:
     static const QString IncrementFormula;
     static const QString IncrementDescription;
 
+    static const QString NodeArc;
+    static const QString NodePoint;
+    static const QString NodeSpline;
+    static const QString NodeSplinePath;
+
 signals:
     /**
      * @brief ChangedActivPP change active pattern peace.
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index aa6c46758..c3f06b6cf 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -57,11 +57,7 @@
 // Current version of seam allowance tag nned for backward compatibility
 const quint8 VToolSeamAllowance::pieceVersion = 2;
 
-const QString VToolSeamAllowance::TagNodes    = QStringLiteral("nodes");
-const QString VToolSeamAllowance::TagNode     = QStringLiteral("node");
-
 const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
-const QString VToolSeamAllowance::AttrNodeReverse    = QStringLiteral("reverse");
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
@@ -69,11 +65,6 @@ const QString VToolSeamAllowance::AttrSABefore       = QStringLiteral("before");
 const QString VToolSeamAllowance::AttrSAAfter        = QStringLiteral("after");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 
-const QString VToolSeamAllowance::NodeArc        = QStringLiteral("NodeArc");
-const QString VToolSeamAllowance::NodePoint      = QStringLiteral("NodePoint");
-const QString VToolSeamAllowance::NodeSpline     = QStringLiteral("NodeSpline");
-const QString VToolSeamAllowance::NodeSplinePath = QStringLiteral("NodeSplinePath");
-
 //---------------------------------------------------------------------------------------------------------------------
 VToolSeamAllowance::~VToolSeamAllowance()
 {
@@ -204,14 +195,14 @@ void VToolSeamAllowance::Remove(bool ask)
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
 {
-    QDomElement nod = doc->createElement(TagNode);
+    QDomElement nod = doc->createElement(VAbstractPattern::TagNode);
 
     doc->SetAttribute(nod, AttrIdObject, node.GetId());
 
     const Tool type = node.GetTypeTool();
     if (type != Tool::NodePoint)
     {
-        doc->SetAttribute(nod, AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
+        doc->SetAttribute(nod, VAbstractPattern::AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
     }
     else
     {
@@ -225,16 +216,16 @@ void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement,
     switch (type)
     {
         case (Tool::NodeArc):
-            doc->SetAttribute(nod, AttrType, NodeArc);
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeArc);
             break;
         case (Tool::NodePoint):
-            doc->SetAttribute(nod, AttrType, NodePoint);
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodePoint);
             break;
         case (Tool::NodeSpline):
-            doc->SetAttribute(nod, AttrType, NodeSpline);
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSpline);
             break;
         case (Tool::NodeSplinePath):
-            doc->SetAttribute(nod, AttrType, NodeSplinePath);
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSplinePath);
             break;
         default:
             qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
@@ -256,7 +247,7 @@ void VToolSeamAllowance::AddNodes(VAbstractPattern *doc, QDomElement &domElement
 {
     if (piece.GetPath().CountNodes() > 0)
     {
-        QDomElement nodesElement = doc->createElement(TagNodes);
+        QDomElement nodesElement = doc->createElement(VAbstractPattern::TagNodes);
         for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
         {
             AddNode(doc, nodesElement, piece.GetPath().at(i));
@@ -722,7 +713,7 @@ void VToolSeamAllowance::SaveDialogChange()
     const VPiece newDet = dialogTool->GetPiece();
     const VPiece oldDet = VAbstractTool::data.GetPiece(id);
 
-    SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id, this->scene());
+    SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id);
     connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
     qApp->getUndoStack()->push(saveCommand);
 }
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 04605a66e..a12de91d3 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -54,11 +54,7 @@ public:
 
     static const quint8 pieceVersion;
 
-    static const QString TagNodes;
-    static const QString TagNode;
-
     static const QString AttrVersion;
-    static const QString AttrNodeReverse;
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
     static const QString AttrWidth;
@@ -66,11 +62,6 @@ public:
     static const QString AttrSAAfter;
     static const QString AttrUnited;
 
-    static const QString NodeArc;
-    static const QString NodePoint;
-    static const QString NodeSpline;
-    static const QString NodeSplinePath;
-
     void Remove(bool ask);
 
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);

From 39b27e4b24f8900220a5b4de5dd42f8045c33d3f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 24 Nov 2016 21:35:54 +0200
Subject: [PATCH 090/208] New class VToolPiecePath.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |  87 +++++-
 src/app/valentina/xml/vpattern.h              |   4 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |  29 ++
 .../vtools/tools/nodeDetails/nodedetails.h    |   1 +
 .../tools/nodeDetails/vtoolpiecepath.cpp      | 264 ++++++++++++++++++
 .../vtools/tools/nodeDetails/vtoolpiecepath.h |  76 +++++
 src/libs/vtools/tools/tools.pri               |   6 +-
 7 files changed, 464 insertions(+), 3 deletions(-)
 create mode 100644 src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
 create mode 100644 src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 77962e3ea..c2c9ddf2b 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -586,7 +586,13 @@ void VPattern::ParseDrawMode(const QDomNode &node, const Document &parse, const
     {
         scene = sceneDetail;
     }
-    const QStringList tags = QStringList() << TagPoint << TagLine << TagSpline << TagArc << TagTools << TagOperation;
+    const QStringList tags = QStringList() << TagPoint
+                                           << TagLine
+                                           << TagSpline
+                                           << TagArc
+                                           << TagTools
+                                           << TagOperation
+                                           << TagPath;
     const QDomNodeList nodeList = node.childNodes();
     const qint32 num = nodeList.size();
     for (qint32 i = 0; i < num; ++i)
@@ -620,6 +626,10 @@ void VPattern::ParseDrawMode(const QDomNode &node, const Document &parse, const
                     qCDebug(vXML, "Tag operation.");
                     ParseOperationElement(scene, domElement, parse, domElement.attribute(AttrType, ""));
                     break;
+                case 6: // TagPath
+                    qCDebug(vXML, "Tag path.");
+                    ParsePathElement(scene, domElement, parse);
+                    break;
                 default:
                     VException e(tr("Wrong tag name '%1'.").arg(domElement.tagName()));
                     throw e;
@@ -3005,6 +3015,81 @@ void VPattern::ParseOperationElement(VMainGraphicsScene *scene, QDomElement &dom
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse)
+{
+    SCASSERT(scene != nullptr);
+    Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
+    try
+    {
+        quint32 id = 0;
+        ToolsCommonAttributes(domElement, id);
+        const QString defType = QString().setNum(static_cast<int>(PiecePathType::CustomSeamAllowance));
+        const PiecePathType type = static_cast<PiecePathType>(GetParametrUInt(domElement, AttrType, defType));
+        const quint32 idTool = GetParametrUInt(domElement, VAbstractNode::AttrIdTool, NULL_ID_STR);
+
+        VPiecePath path;
+        const QDomElement element = domElement.firstChildElement(VAbstractPattern::TagNodes);
+        if (not element.isNull())
+        {
+            ParsePathNodes(element, path);
+        }
+
+        path.SetType(type);
+
+        VToolPiecePath::Create(id, path, 0, scene, this, data, parse, Source::FromFile, "", idTool);
+    }
+    catch (const VExceptionBadId &e)
+    {
+        VExceptionObjectError excep(tr("Error creating or updating a piece path"), domElement);
+        excep.AddMoreInformation(e.ErrorMessage());
+        throw excep;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePathNodes(const QDomElement &domElement, VPiecePath &path) const
+{
+    const QStringList types = QStringList() << VAbstractPattern::NodePoint
+                                            << VAbstractPattern::NodeArc
+                                            << VAbstractPattern::NodeSpline
+                                            << VAbstractPattern::NodeSplinePath;
+
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
+        {
+            const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
+            const bool reverse = GetParametrUInt(element, VAbstractPattern::AttrNodeReverse, "0");
+
+            const QString t = GetParametrString(element, AttrType, VAbstractPattern::NodePoint);
+            Tool tool;
+
+            switch (types.indexOf(t))
+            {
+                case 0: // VAbstractPattern::NodePoint
+                    tool = Tool::NodePoint;
+                    break;
+                case 1: // VAbstractPattern::NodeArc
+                    tool = Tool::NodeArc;
+                    break;
+                case 2: // VAbstractPattern::NodeSpline
+                    tool = Tool::NodeSpline;
+                    break;
+                case 3: // VAbstractPattern::NodeSplinePath
+                    tool = Tool::NodeSplinePath;
+                    break;
+                default:
+                    VException e(tr("Wrong tag name '%1'.").arg(t));
+                    throw e;
+            }
+            path.Append(VPieceNode(id, tool, reverse));
+        }
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseIncrementsElement parse increments tag.
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 0992f1a68..e96387b05 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -132,6 +132,10 @@ private:
                                      const Document &parse, const QString& type);
     void           ParseOperationElement(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse,
                                          const QString& type);
+
+    void           ParsePathElement(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse);
+    void           ParsePathNodes(const QDomElement &domElement, VPiecePath &path) const;
+
     void           ParseIncrementsElement(const QDomNode& node);
     void           PrepareForParse(const Document &parse);
     void           ToolsCommonAttributes(const QDomElement &domElement, quint32 &id);
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index fb24ee3e9..40b3dc2f5 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -307,6 +307,29 @@
                                                                                  <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
                                                                            </xs:complexType>
                                                                      </xs:element>
+                                                                     <xs:element name="path" minOccurs="0" maxOccurs="unbounded">
+                                                                           <xs:complexType>
+																			   <xs:sequence>
+																				<xs:element name="nodes" minOccurs="1" maxOccurs="1">
+																					<xs:complexType>
+																						<xs:sequence>
+																						   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+																								   <xs:complexType>
+																										 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
+																										 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
+																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+																								   </xs:complexType>
+																							 </xs:element>
+																						 </xs:sequence>
+																					 </xs:complexType>
+																				</xs:element>
+																				</xs:sequence>
+                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
+                                                                                 <xs:attribute name="type" type="piecePathType"></xs:attribute>
+                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
+                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                           </xs:complexType>
+                                                                     </xs:element>
                                                                      <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">
                                                                        <xs:complexType>
                                                                              <xs:sequence>
@@ -650,4 +673,10 @@
        <xs:enumeration value="5"/><!--by first edge right angle-->
      </xs:restriction>
    </xs:simpleType>
+   <xs:simpleType name="piecePathType">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="1"/><!--custom seam allowance-->
+       <xs:enumeration value="2"/><!--internal path-->
+     </xs:restriction>
+   </xs:simpleType>
    </xs:schema>
diff --git a/src/libs/vtools/tools/nodeDetails/nodedetails.h b/src/libs/vtools/tools/nodeDetails/nodedetails.h
index 497136c6e..3f410f313 100644
--- a/src/libs/vtools/tools/nodeDetails/nodedetails.h
+++ b/src/libs/vtools/tools/nodeDetails/nodedetails.h
@@ -33,5 +33,6 @@
 #include "vnodepoint.h"
 #include "vnodespline.h"
 #include "vnodesplinepath.h"
+#include "vtoolpiecepath.h"
 
 #endif // NODEDETAILS_H
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
new file mode 100644
index 000000000..f3274f560
--- /dev/null
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -0,0 +1,264 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   24 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vtoolpiecepath.h"
+#include "../../dialogs/tools/dialogpiecepath.h"
+#include "../vpatterndb/vpiecepath.h"
+#include "../vpatterndb/vpiecenode.h"
+#include "../../undocommands/savepieceoptions.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolPiecePath *VToolPiecePath::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                       VContainer *data)
+{
+    SCASSERT(dialog != nullptr);
+    DialogPiecePath *dialogTool = qobject_cast<DialogPiecePath*>(dialog);
+    SCASSERT(dialogTool != nullptr);
+    const VPiecePath path = dialogTool->GetPiecePath();
+    const quint32 pieceId = dialogTool->GetPieceId();
+
+    VToolPiecePath *pathTool = Create(0, path, pieceId, scene, doc, data, Document::FullParse, Source::FromGui);
+    return pathTool;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolPiecePath *VToolPiecePath::Create(quint32 _id, const VPiecePath &path, quint32 pieceId, VMainGraphicsScene *scene,
+                                       VAbstractPattern *doc, VContainer *data, const Document &parse,
+                                       const Source &typeCreation, const QString &drawName, const quint32 &idTool)
+{
+    quint32 id = _id;
+    if (typeCreation == Source::FromGui)
+    {
+        id = data->AddPiecePath(path);
+    }
+    else
+    {
+        data->UpdatePiecePath(id, path);
+        if (parse != Document::FullParse)
+        {
+            doc->UpdateToolData(id, data);
+        }
+    }
+
+    VAbstractTool::AddRecord(id, Tool::PiecePath, doc);
+    if (parse == Document::FullParse)
+    {
+        //TODO Need create garbage collector and remove all nodes, that we don't use.
+        //Better check garbage before each saving file. Check only modeling tags.
+        VToolPiecePath *pathTool = new VToolPiecePath(doc, data, id, pieceId, typeCreation, drawName, idTool, doc);
+
+        doc->AddTool(id, pathTool);
+        if (idTool != NULL_ID)
+        {
+            //Some nodes we don't show on scene. Tool that create this nodes must free memory.
+            VDataTool *tool = doc->getTool(idTool);
+            SCASSERT(tool != nullptr);
+            pathTool->setParent(tool);// Adopted by a tool
+        }
+        else
+        {
+            // Try to prevent memory leak
+            scene->addItem(pathTool);// First adopted by scene
+            pathTool->hide();// If no one will use node, it will stay hidden
+            pathTool->SetParentType(ParentType::Scene);
+        }
+        return pathTool;
+    }
+    else
+    {
+        doc->UpdateToolData(id, data);
+    }
+    return nullptr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VToolPiecePath::getTagName() const
+{
+    return VAbstractPattern::TagPath;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
+{
+    QDomElement nod = doc->createElement(VAbstractPattern::TagNode);
+
+    doc->SetAttribute(nod, AttrIdObject, node.GetId());
+
+    const Tool type = node.GetTypeTool();
+    if (type != Tool::NodePoint)
+    {
+        doc->SetAttribute(nod, VAbstractPattern::AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
+    }
+
+    switch (type)
+    {
+        case (Tool::NodeArc):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeArc);
+            break;
+        case (Tool::NodePoint):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodePoint);
+            break;
+        case (Tool::NodeSpline):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSpline);
+            break;
+        case (Tool::NodeSplinePath):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSplinePath);
+            break;
+        default:
+            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+            break;
+    }
+
+    domElement.appendChild(nod);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path)
+{
+    if (path.CountNodes() > 0)
+    {
+        QDomElement nodesElement = doc->createElement(VAbstractPattern::TagNodes);
+        for (int i = 0; i < path.CountNodes(); ++i)
+        {
+            AddNode(doc, nodesElement, path.at(i));
+        }
+        domElement.appendChild(nodesElement);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::FullUpdateFromFile()
+{
+    RefreshGeometry();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AllowHover(bool enabled)
+{
+    Q_UNUSED(enabled)
+    // do nothing
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AllowSelecting(bool enabled)
+{
+    Q_UNUSED(enabled)
+    // do nothing
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AddToFile()
+{
+    QDomElement domElement = doc->createElement(getTagName());
+
+    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+
+    const VPiecePath path = VAbstractTool::data.GetPiecePath(id);
+    doc->SetAttribute(domElement, AttrType, static_cast<int>(path.GetType()));
+
+    if (idTool != NULL_ID)
+    {
+        doc->SetAttribute(domElement, AttrIdTool, idTool);
+    }
+
+    AddNodes(doc, domElement, path);
+
+    qApp->getUndoStack()->beginMacro(tr("new path"));
+
+    AddToModeling(domElement);
+
+    VPiece oldDet = VAbstractTool::data.GetPiece(m_pieceId);
+    VPiece newDet = oldDet;
+
+    if (path.GetType() == PiecePathType::InternalPath)
+    {
+
+    }
+    else if (path.GetType() == PiecePathType::CustomSeamAllowance)
+    {
+
+    }
+
+    SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
+    connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(saveCommand);
+
+    qApp->getUndoStack()->endMacro();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::RefreshDataInFile()
+{
+    QDomElement domElement = doc->elementById(id);
+    if (domElement.isElement())
+    {
+        if (idTool != NULL_ID)
+        {
+            doc->SetAttribute(domElement, AttrIdTool, idTool);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::ShowNode()
+{
+    if (parentType != ParentType::Scene)
+    {
+        show();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::HideNode()
+{
+    hide();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VToolPiecePath::VToolPiecePath(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 pieceId,
+                               const Source &typeCreation, const QString &drawName, const quint32 &idTool,
+                               QObject *qoParent, QGraphicsItem *parent)
+    :VAbstractNode(doc, data, id, 0, drawName, idTool, qoParent),
+      QGraphicsPathItem(parent),
+      m_pieceId(pieceId)
+{
+    RefreshGeometry();
+    ToolCreation(typeCreation);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::RefreshGeometry()
+{
+    const VPiecePath path = VAbstractTool::data.GetPiecePath(id);
+    if (path.GetType() == PiecePathType::InternalPath)
+    {
+        QPainterPath p = path.PainterPath(this->getData());
+        p.setFillRule(Qt::OddEvenFill);
+        this->setPath(p);
+    }
+}
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
new file mode 100644
index 000000000..c204dac34
--- /dev/null
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
@@ -0,0 +1,76 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   24 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 VTOOLPIECEPATH_H
+#define VTOOLPIECEPATH_H
+
+#include <QtGlobal>
+
+#include "vabstractnode.h"
+
+class DialogTool;
+
+class VToolPiecePath : public VAbstractNode, public QGraphicsPathItem
+{
+    Q_OBJECT
+public:
+    static VToolPiecePath* Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                  VContainer *data);
+    static VToolPiecePath *Create(quint32 _id, const VPiecePath &path, quint32 pieceId, VMainGraphicsScene *scene,
+                                  VAbstractPattern *doc, VContainer *data, const Document &parse,
+                                  const Source &typeCreation, const QString &drawName = QString(),
+                                  const quint32 &idTool = 0);
+
+    virtual int  type() const Q_DECL_OVERRIDE {return Type;}
+    enum { Type = UserType + static_cast<int>(Tool::PiecePath)};
+    virtual QString getTagName() const Q_DECL_OVERRIDE;
+
+    static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
+    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path);
+public slots:
+    virtual void FullUpdateFromFile () Q_DECL_OVERRIDE;
+    virtual void AllowHover(bool enabled) Q_DECL_OVERRIDE;
+    virtual void AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
+protected:
+    virtual void AddToFile() Q_DECL_OVERRIDE;
+    virtual void RefreshDataInFile() Q_DECL_OVERRIDE;
+    virtual void ShowNode() Q_DECL_OVERRIDE;
+    virtual void HideNode() Q_DECL_OVERRIDE;
+private:
+    Q_DISABLE_COPY(VToolPiecePath)
+
+    quint32 m_pieceId;
+
+    VToolPiecePath(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 pieceId,  const Source &typeCreation,
+                   const QString &drawName = QString(), const quint32 &idTool = 0, QObject *qoParent = nullptr,
+                   QGraphicsItem * parent = nullptr );
+
+    void RefreshGeometry();
+};
+
+#endif // VTOOLPIECEPATH_H
diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri
index 563ab6573..aa0251e7c 100644
--- a/src/libs/vtools/tools/tools.pri
+++ b/src/libs/vtools/tools/tools.pri
@@ -58,7 +58,8 @@ HEADERS += \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.h \
     $$PWD/drawTools/operation/flipping/vabstractflipping.h \
     $$PWD/drawTools/operation/vtoolmove.h \
-    $$PWD/vtoolseamallowance.h
+    $$PWD/vtoolseamallowance.h \
+    $$PWD/nodeDetails/vtoolpiecepath.h
 
 SOURCES += \
     $$PWD/vtooldetail.cpp \
@@ -114,4 +115,5 @@ SOURCES += \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.cpp \
     $$PWD/drawTools/operation/flipping/vabstractflipping.cpp \
     $$PWD/drawTools/operation/vtoolmove.cpp \
-    $$PWD/vtoolseamallowance.cpp
+    $$PWD/vtoolseamallowance.cpp \
+    $$PWD/nodeDetails/vtoolpiecepath.cpp

From 6c04b2e7cab53eca418ebc632d5b19e2e743518a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 13:19:38 +0200
Subject: [PATCH 091/208] Remove attribute "typeObject" since 0.4.0.

--HG--
branch : feature
---
 src/libs/ifc/schema/pattern/v0.4.0.xsd |  3 ---
 src/libs/ifc/xml/vpatternconverter.cpp | 32 ++++++++++++++++++++++++++
 src/libs/ifc/xml/vpatternconverter.h   |  1 +
 3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 40b3dc2f5..055575a49 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -280,7 +280,6 @@
                                                                                  <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
                                                                                  <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
                                                                                  <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="my" type="xs:double"></xs:attribute>
                                                                                  <xs:attribute name="type" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
@@ -291,7 +290,6 @@
                                                                            <xs:complexType>
                                                                                  <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
                                                                                  <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="type" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
                                                                                  <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
@@ -301,7 +299,6 @@
                                                                            <xs:complexType>
                                                                                  <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
                                                                                  <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="typeObject" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="type" type="xs:string"></xs:attribute>
                                                                                  <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
                                                                                  <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index 11bc090fd..0e02b69e0 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -130,6 +130,7 @@ const QString strMy                        = QStringLiteral("my");
 const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
 const QString strInLayout                  = QStringLiteral("inLayout");
 const QString strSeamAllowance             = QStringLiteral("seamAllowance");
+const QString strTypeObject                = QStringLiteral("typeObject");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)
@@ -575,6 +576,7 @@ void VPatternConverter::ToV0_4_0()
                       "Time to refactor the code.");
 
     SetVersion(QStringLiteral("0.4.0"));
+    TagRemoveAttributeTypeObjectInV0_4_0();
     TagDetailToV0_4_0();
     Save();
 }
@@ -1681,6 +1683,36 @@ void VPatternConverter::FixSubPaths(int i, quint32 id, quint32 baseCurve)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternConverter::TagRemoveAttributeTypeObjectInV0_4_0()
+{
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
+    const QDomNodeList list = elementsByTagName(strModeling);
+    for (int i = 0; i < list.size(); ++i)
+    {
+        QDomElement modeling = list.at(i).toElement();
+        if (not modeling.isNull())
+        {
+            QDomNode domNode = modeling.firstChild();
+            while (not domNode.isNull())
+            {
+                QDomElement domElement = domNode.toElement();
+                if (not domElement.isNull())
+                {
+                    if (domElement.hasAttribute(strTypeObject))
+                    {
+                        domElement.removeAttribute(strTypeObject);
+                    }
+                }
+                domNode = domNode.nextSibling();
+            }
+        }
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VPatternConverter::TagDetailToV0_4_0()
 {
diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h
index 483d8782b..95a979451 100644
--- a/src/libs/ifc/xml/vpatternconverter.h
+++ b/src/libs/ifc/xml/vpatternconverter.h
@@ -134,6 +134,7 @@ private:
     void FixCutPoint();
     void FixSubPaths(int i, quint32 id, quint32 baseCurve);
 
+    void TagRemoveAttributeTypeObjectInV0_4_0();
     void TagDetailToV0_4_0();
 };
 

From 6424a92559a5f9a7ca0ff2561965be1e6320e145 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 14:19:44 +0200
Subject: [PATCH 092/208] Read/write custom seam allowance record.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            | 32 +++++++++++++++--
 src/app/valentina/xml/vpattern.h              |  1 +
 src/libs/vmisc/def.h                          | 20 +++++++++++
 src/libs/vpatterndb/vpiece.cpp                | 12 +++++++
 src/libs/vpatterndb/vpiece.h                  |  3 ++
 src/libs/vpatterndb/vpiece_p.h                |  9 +++--
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  5 +++
 src/libs/vtools/tools/vtoolseamallowance.cpp  | 36 +++++++++++++++++++
 src/libs/vtools/tools/vtoolseamallowance.h    |  8 +++++
 .../vtools/undocommands/savepieceoptions.cpp  |  2 ++
 10 files changed, 123 insertions(+), 5 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index c2c9ddf2b..9d2b643ab 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -661,10 +661,11 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
         detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
-        const QStringList tags = QStringList() << VAbstractPattern::TagNodes
+        const QStringList tags = QStringList() << TagNodes
                                                << TagData
                                                << TagPatternInfo
-                                               << TagGrainline;
+                                               << TagGrainline
+                                               << VToolSeamAllowance::TagCSA;
 
         const QDomNodeList nodeList = domElement.childNodes();
         for (qint32 i = 0; i < nodeList.size(); ++i)
@@ -674,7 +675,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
             {
                 switch (tags.indexOf(element.tagName()))
                 {
-                    case 0:// VAbstractPattern::TagNodes
+                    case 0:// TagNodes
                         ParseDetailNodes(element, detail);
                         break;
                     case 1:// TagData
@@ -683,6 +684,9 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                         break;
                     case 3:// TagGrainline
                         break;
+                    case 4:// VToolSeamAllowance::TagCSA
+                        ParseDetailCSARecords(element, detail);
+                        break;
                     default:
                         break;
                 }
@@ -819,6 +823,28 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) c
         }
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const
+{
+    QVector<CustomSARecord> records;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagRecord)
+        {
+            CustomSARecord record;
+            record.startPoint = GetParametrUInt(element, VToolSeamAllowance::AttrStart, NULL_ID_STR);
+            record.path = GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
+            record.endPoint = GetParametrUInt(element, VToolSeamAllowance::AttrEnd, NULL_ID_STR);
+            record.reverse = GetParametrBool(element, VAbstractPattern::AttrNodeReverse, falseStr);
+            records.append(record);
+        }
+    }
+    detail.SetCustomSARecords(records);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDetails parse details tag.
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index e96387b05..0ab54d4f0 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -118,6 +118,7 @@ private:
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const;
+    void           ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
     void           ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElement,
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index 170b7eed0..e16eb5add 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -677,6 +677,26 @@ static inline bool VFuzzyComparePossibleNulls(double p1, double p2)
     }
 }
 
+/**
+ * @brief The CustomSA struct contains record about custom seam allowanse (SA).
+ */
+struct CustomSARecord
+{
+    CustomSARecord()
+        : startPoint(0),
+          path(0),
+          endPoint(0),
+          reverse(false)
+    {}
+
+    quint32 startPoint;
+    quint32 path;
+    quint32 endPoint;
+    bool reverse;
+};
+
+Q_DECLARE_TYPEINFO(CustomSARecord, Q_MOVABLE_TYPE);
+
 /****************************************************************************
 ** This file is derived from code bearing the following notice:
 ** The sole author of this file, Adam Higerd, has explicitly disclaimed all
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index dd3560597..a6f067437 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -231,6 +231,18 @@ void VPiece::SetUnited(bool united)
     d->m_united = united;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<CustomSARecord> VPiece::GetCustomSARecords() const
+{
+    return d->m_customSARecords;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetCustomSARecords(const QVector<CustomSARecord> &records)
+{
+    d->m_customSARecords = records;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 1c17e3f2d..bbc9a93db 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -75,6 +75,9 @@ public:
     bool IsUnited() const;
     void SetUnited(bool united);
 
+    QVector<CustomSARecord> GetCustomSARecords() const;
+    void                    SetCustomSARecords(const QVector<CustomSARecord> &records);
+
     QVector<VPieceNode> Missing(const VPiece &det) const;
 
     int indexOfNode(const quint32 &id) const;
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 3ec5cf61e..c8c42ad1a 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -33,6 +33,7 @@
 #include <QVector>
 
 #include "../vmisc/diagnostic.h"
+#include "../vmisc/def.h"
 #include "vpiecenode.h"
 #include "vpiecepath.h"
 
@@ -47,7 +48,8 @@ public:
           m_mx(0),
           m_my(0),
           m_inLayout(true),
-          m_united(false)
+          m_united(false),
+          m_customSARecords()
     {}
 
     VPieceData(const VPieceData &detail)
@@ -56,7 +58,8 @@ public:
           m_mx(detail.m_mx),
           m_my(detail.m_my),
           m_inLayout(detail.m_inLayout),
-          m_united(detail.m_united)
+          m_united(detail.m_united),
+          m_customSARecords(detail.m_customSARecords)
     {}
 
     ~VPieceData();
@@ -70,6 +73,8 @@ public:
     bool m_inLayout;
     bool m_united;
 
+    QVector<CustomSARecord> m_customSARecords;
+
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
 };
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index f3274f560..7527af36c 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -201,7 +201,12 @@ void VToolPiecePath::AddToFile()
     }
     else if (path.GetType() == PiecePathType::CustomSeamAllowance)
     {
+        CustomSARecord record;
+        record.path = m_pieceId;
 
+        QVector<CustomSARecord> records = newDet.GetCustomSARecords();
+        records.append(record);
+        newDet.SetCustomSARecords(records);
     }
 
     SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index c3f06b6cf..37ac7e0c8 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -57,6 +57,9 @@
 // Current version of seam allowance tag nned for backward compatibility
 const quint8 VToolSeamAllowance::pieceVersion = 2;
 
+const QString VToolSeamAllowance::TagCSA     = QStringLiteral("csa");
+const QString VToolSeamAllowance::TagRecord  = QStringLiteral("record");
+
 const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
@@ -64,6 +67,9 @@ const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
 const QString VToolSeamAllowance::AttrSABefore       = QStringLiteral("before");
 const QString VToolSeamAllowance::AttrSAAfter        = QStringLiteral("after");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
+const QString VToolSeamAllowance::AttrStart          = QStringLiteral("start");
+const QString VToolSeamAllowance::AttrPath           = QStringLiteral("path");
+const QString VToolSeamAllowance::AttrEnd            = QStringLiteral("end");
 
 //---------------------------------------------------------------------------------------------------------------------
 VToolSeamAllowance::~VToolSeamAllowance()
@@ -273,6 +279,34 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrUnited, piece.IsUnited());
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record)
+{
+    QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord);
+
+    doc->SetAttribute(recordNode, AttrStart, record.startPoint);
+    doc->SetAttribute(recordNode, AttrPath, record.path);
+    doc->SetAttribute(recordNode, AttrEnd, record.endPoint);
+    doc->SetAttribute(recordNode, VAbstractPattern::AttrNodeReverse, record.reverse);
+
+    domElement.appendChild(recordNode);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddCSARecords(VAbstractPattern *doc, QDomElement &domElement,
+                                       const QVector<CustomSARecord> &records)
+{
+    if (records.size() > 0)
+    {
+        QDomElement csaRecordsElement = doc->createElement(VToolSeamAllowance::TagCSA);
+        for (int i = 0; i < records.size(); ++i)
+        {
+            AddCSARecord(doc, csaRecordsElement, records.at(i));
+        }
+        domElement.appendChild(csaRecordsElement);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
@@ -370,6 +404,8 @@ void VToolSeamAllowance::AddToFile()
 
     // nodes
     AddNodes(doc, domElement, piece);
+    //custom seam allowance
+    AddCSARecords(doc, domElement, piece.GetCustomSARecords());
 
     AddPiece *addDet = new AddPiece(domElement, doc, piece, m_drawName);
     connect(addDet, &AddPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index a12de91d3..50037c4ae 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -54,6 +54,9 @@ public:
 
     static const quint8 pieceVersion;
 
+    static const QString TagCSA;
+    static const QString TagRecord;
+
     static const QString AttrVersion;
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
@@ -61,12 +64,17 @@ public:
     static const QString AttrSABefore;
     static const QString AttrSAAfter;
     static const QString AttrUnited;
+    static const QString AttrStart;
+    static const QString AttrPath;
+    static const QString AttrEnd;
 
     void Remove(bool ask);
 
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
     static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece);
+    static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record);
+    static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector<CustomSARecord> &records);
     static void AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index d03657474..25771c5b9 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -75,6 +75,7 @@ void SavePieceOptions::undo()
         VToolSeamAllowance::AddPatternInfo(doc, domElement, m_oldDet);
         VToolSeamAllowance::AddGrainline(doc, domElement, m_oldDet);
         VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
+        VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
 
         IncrementReferences(m_oldDet.Missing(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);
@@ -100,6 +101,7 @@ void SavePieceOptions::redo()
         VToolSeamAllowance::AddPatternInfo(doc, domElement, m_newDet);
         VToolSeamAllowance::AddGrainline(doc, domElement, m_newDet);
         VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
+        VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
 
         DecrementReferences(m_oldDet.Missing(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);

From cb95210d1e108d9261a1239271f7a5e1b51e0400 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 15:35:52 +0200
Subject: [PATCH 093/208] Rename VPiece::Missing.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp                    | 4 ++--
 src/libs/vpatterndb/vpiece.h                      | 2 +-
 src/libs/vtools/undocommands/savepieceoptions.cpp | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index a6f067437..e4968d6ec 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -245,12 +245,12 @@ void VPiece::SetCustomSARecords(const QVector<CustomSARecord> &records)
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
+ * @brief MissingNodes find missing nodes in detail. When we deleted object in detail and return this detail need
  * understand, what nodes need make invisible.
  * @param det changed detail.
  * @return  list with missing nodes.
  */
-QVector<VPieceNode> VPiece::Missing(const VPiece &det) const
+QVector<VPieceNode> VPiece::MissingNodes(const VPiece &det) const
 {
     const QVector<VPieceNode> pNodes = d->m_path.GetNodes();
     if (pNodes.size() == det.GetPath().CountNodes()) //-V807
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index bbc9a93db..5a7934e77 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -78,7 +78,7 @@ public:
     QVector<CustomSARecord> GetCustomSARecords() const;
     void                    SetCustomSARecords(const QVector<CustomSARecord> &records);
 
-    QVector<VPieceNode> Missing(const VPiece &det) const;
+    QVector<VPieceNode> MissingNodes(const VPiece &det) const;
 
     int indexOfNode(const quint32 &id) const;
 
diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index 25771c5b9..3d8390087 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -77,7 +77,7 @@ void SavePieceOptions::undo()
         VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
 
-        IncrementReferences(m_oldDet.Missing(m_newDet));
+        IncrementReferences(m_oldDet.MissingNodes(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);
     }
     else
@@ -103,7 +103,7 @@ void SavePieceOptions::redo()
         VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
 
-        DecrementReferences(m_oldDet.Missing(m_newDet));
+        DecrementReferences(m_oldDet.MissingNodes(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);
     }
     else

From 8e9b01a93a93f0ee88db72788918ed1139d0af81 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 16:12:33 +0200
Subject: [PATCH 094/208] Decrement/increment custom seam allowance in tool
 seam allowance undocommands.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp                | 39 +++++++++++--
 src/libs/vpatterndb/vpiece.h                  |  3 +-
 src/libs/vtools/undocommands/addpiece.cpp     |  1 +
 src/libs/vtools/undocommands/deletepiece.cpp  |  1 +
 .../vtools/undocommands/savepieceoptions.cpp  |  3 +
 src/libs/vtools/undocommands/vundocommand.cpp | 58 ++++++++++++++++++-
 src/libs/vtools/undocommands/vundocommand.h   |  7 +++
 7 files changed, 104 insertions(+), 8 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index e4968d6ec..a77a15540 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -250,12 +250,12 @@ void VPiece::SetCustomSARecords(const QVector<CustomSARecord> &records)
  * @param det changed detail.
  * @return  list with missing nodes.
  */
-QVector<VPieceNode> VPiece::MissingNodes(const VPiece &det) const
+QVector<quint32> VPiece::MissingNodes(const VPiece &det) const
 {
     const QVector<VPieceNode> pNodes = d->m_path.GetNodes();
     if (pNodes.size() == det.GetPath().CountNodes()) //-V807
     {
-        return QVector<VPieceNode>();
+        return QVector<quint32>();
     }
 
     QSet<quint32> set1;
@@ -271,19 +271,50 @@ QVector<VPieceNode> VPiece::MissingNodes(const VPiece &det) const
     }
 
     const QList<quint32> set3 = set1.subtract(set2).toList();
-    QVector<VPieceNode> nodes;
+    QVector<quint32> nodes;
     for (qint32 i = 0; i < set3.size(); ++i)
     {
         const int index = indexOfNode(pNodes, set3.at(i));
         if (index != -1)
         {
-            nodes.append(pNodes.at(index));
+            nodes.append(pNodes.at(index).GetId());
         }
     }
 
     return nodes;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
+{
+    const QVector<CustomSARecord> detRecords = det.GetCustomSARecords();
+    if (d->m_customSARecords.size() == detRecords.size()) //-V807
+    {
+        return QVector<quint32>();
+    }
+
+    QSet<quint32> set1;
+    for (qint32 i = 0; i < d->m_customSARecords.size(); ++i)
+    {
+        set1.insert(d->m_customSARecords.at(i).path);
+    }
+
+    QSet<quint32> set2;
+    for (qint32 j = 0; j < detRecords.size(); ++j)
+    {
+        set2.insert(detRecords.at(j).path);
+    }
+
+    const QList<quint32> set3 = set1.subtract(set2).toList();
+    QVector<quint32> r;
+    for (qint32 i = 0; i < set3.size(); ++i)
+    {
+        r.append(set3.at(i));
+    }
+
+    return r;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief indexOfNode return index in list node using id object.
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 5a7934e77..255beb9a4 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -78,7 +78,8 @@ public:
     QVector<CustomSARecord> GetCustomSARecords() const;
     void                    SetCustomSARecords(const QVector<CustomSARecord> &records);
 
-    QVector<VPieceNode> MissingNodes(const VPiece &det) const;
+    QVector<quint32> MissingNodes(const VPiece &det) const;
+    QVector<quint32> MissingCSAPath(const VPiece &det) const;
 
     int indexOfNode(const quint32 &id) const;
 
diff --git a/src/libs/vtools/undocommands/addpiece.cpp b/src/libs/vtools/undocommands/addpiece.cpp
index 185ac804f..c27b9e250 100644
--- a/src/libs/vtools/undocommands/addpiece.cpp
+++ b/src/libs/vtools/undocommands/addpiece.cpp
@@ -63,6 +63,7 @@ void AddPiece::undo()
             }
 
             DecrementReferences(m_detail.GetPath().GetNodes());
+            DecrementReferences(m_detail.GetCustomSARecords());
         }
         else
         {
diff --git a/src/libs/vtools/undocommands/deletepiece.cpp b/src/libs/vtools/undocommands/deletepiece.cpp
index 1aea7088c..6fb5fd5bf 100644
--- a/src/libs/vtools/undocommands/deletepiece.cpp
+++ b/src/libs/vtools/undocommands/deletepiece.cpp
@@ -107,6 +107,7 @@ void DeletePiece::redo()
         toolDet->hide();
 
         DecrementReferences(m_detail.GetPath().GetNodes());
+        DecrementReferences(m_detail.GetCustomSARecords());
         emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
     }
     else
diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index 3d8390087..ae7e28f3d 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -78,6 +78,7 @@ void SavePieceOptions::undo()
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
 
         IncrementReferences(m_oldDet.MissingNodes(m_newDet));
+        IncrementReferences(m_oldDet.MissingCSAPath(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);
     }
     else
@@ -104,6 +105,8 @@ void SavePieceOptions::redo()
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
 
         DecrementReferences(m_oldDet.MissingNodes(m_newDet));
+        DecrementReferences(m_oldDet.MissingCSAPath(m_newDet));
+
         emit NeedLiteParsing(Document::LiteParse);
     }
     else
diff --git a/src/libs/vtools/undocommands/vundocommand.cpp b/src/libs/vtools/undocommands/vundocommand.cpp
index fab10fab9..cd8351b65 100644
--- a/src/libs/vtools/undocommands/vundocommand.cpp
+++ b/src/libs/vtools/undocommands/vundocommand.cpp
@@ -95,19 +95,71 @@ void VUndoCommand::DecrementReferences(const QVector<VNodeDetail> &nodes) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VUndoCommand::IncrementReferences(const QVector<VPieceNode> &nodes) const
+void VUndoCommand::IncrementReferences(const QVector<quint32> &nodes) const
 {
     for (qint32 i = 0; i < nodes.size(); ++i)
     {
-        doc->IncrementReferens(nodes.at(i).GetId());
+        doc->IncrementReferens(nodes.at(i));
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::DecrementReferences(const QVector<quint32> &nodes) const
+{
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        doc->DecrementReferens(nodes.at(i));
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::IncrementReferences(const QVector<CustomSARecord> &nodes) const
+{
+    QVector<quint32> n;
+
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        n.append(nodes.at(i).path);
+    }
+
+    IncrementReferences(n);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::DecrementReferences(const QVector<CustomSARecord> &nodes) const
+{
+    QVector<quint32> n;
+
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        n.append(nodes.at(i).path);
+    }
+
+    DecrementReferences(n);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VUndoCommand::IncrementReferences(const QVector<VPieceNode> &nodes) const
+{
+    QVector<quint32> n;
+
+    for (qint32 i = 0; i < nodes.size(); ++i)
+    {
+        n.append(nodes.at(i).GetId());
+    }
+
+    IncrementReferences(n);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VUndoCommand::DecrementReferences(const QVector<VPieceNode> &nodes) const
 {
+    QVector<quint32> n;
+
     for (qint32 i = 0; i < nodes.size(); ++i)
     {
-        doc->DecrementReferens(nodes.at(i).GetId());
+        n.append(nodes.at(i).GetId());
     }
+
+    DecrementReferences(n);
 }
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index d4fceb414..dea2b9ff8 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -89,6 +89,13 @@ protected:
 
     void         IncrementReferences(const QVector<VNodeDetail> &nodes) const;
     void         DecrementReferences(const QVector<VNodeDetail> &nodes) const;
+
+    void         IncrementReferences(const QVector<quint32> &nodes) const;
+    void         DecrementReferences(const QVector<quint32> &nodes) const;
+
+    void         IncrementReferences(const QVector<CustomSARecord> &nodes) const;
+    void         DecrementReferences(const QVector<CustomSARecord> &nodes) const;
+
     void         IncrementReferences(const QVector<VPieceNode> &nodes) const;
     void         DecrementReferences(const QVector<VPieceNode> &nodes) const;
 private:

From 82d9fcba3f720b31e14873f3ad3d830186f0751c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 16:36:56 +0200
Subject: [PATCH 095/208] Connect MainWindow with VToolPiecePath.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index eaa12321c..9fc27ff44 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -53,6 +53,7 @@
 #include "../vtools/dialogs/tooldialogs.h"
 #include "tools/vtooldetail.h"
 #include "tools/vtoolseamallowance.h"
+#include "tools/nodeDetails/vtoolpiecepath.h"
 #include "tools/vtooluniondetails.h"
 #include "dialogs/dialogs.h"
 #include "dialogs/vwidgetgroups.h"
@@ -1129,7 +1130,7 @@ void MainWindow::ClosedDialogPiecePath(int result)
     {
         DialogPiecePath *dialog = qobject_cast<DialogPiecePath*>(dialogTool);
         SCASSERT(dialog != nullptr);
-        //VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
+        VToolPiecePath::Create(dialogTool, sceneDetails, doc, pattern);
     }
     ArrowTool();
     doc->LiteParseTree(Document::LiteParse);

From 20f8da230d26b06ac1a9406d27845d94a65bd410 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 16:37:32 +0200
Subject: [PATCH 096/208] Increment custom seam allowance in tool seam
 allowance.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 65 ++++++++++++--------
 src/libs/vtools/tools/vtoolseamallowance.h   |  3 +
 2 files changed, 44 insertions(+), 24 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 37ac7e0c8..14fa9bfbc 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -665,30 +665,8 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
       m_seamAllowance(new VNoBrushScalePathItem(this))
 {
     VPiece detail = data->GetPiece(id);
-    for (int i = 0; i< detail.GetPath().CountNodes(); ++i)
-    {
-        switch (detail.GetPath().at(i).GetTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.GetPath().at(i));
-                connect(tool, &VNodePoint::ShowContextMenu, this, &VToolSeamAllowance::contextMenuEvent);
-                break;
-            }
-            case (Tool::NodeArc):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
-                break;
-            case (Tool::NodeSpline):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
-                break;
-            case (Tool::NodeSplinePath):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
-                break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore.";
-                break;
-        }
-    }
+    InitNodes(detail, scene);
+    InitCSAPaths(detail);
     this->setFlag(QGraphicsItem::ItemIsMovable, true);
     this->setFlag(QGraphicsItem::ItemIsSelectable, true);
     RefreshGeometry();
@@ -754,6 +732,45 @@ void VToolSeamAllowance::SaveDialogChange()
     qApp->getUndoStack()->push(saveCommand);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::InitNodes(const VPiece &detail, VMainGraphicsScene *scene)
+{
+    for (int i = 0; i< detail.GetPath().CountNodes(); ++i)
+    {
+        switch (detail.GetPath().at(i).GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.GetPath().at(i));
+                connect(tool, &VNodePoint::ShowContextMenu, this, &VToolSeamAllowance::contextMenuEvent);
+                break;
+            }
+            case (Tool::NodeArc):
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
+                break;
+            case (Tool::NodeSpline):
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
+                break;
+            case (Tool::NodeSplinePath):
+                doc->IncrementReferens(detail.GetPath().at(i).GetId());
+                break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore.";
+                break;
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::InitCSAPaths(const VPiece &detail)
+{
+    QVector<CustomSARecord> records = detail.GetCustomSARecords();
+    for (int i = 0; i < records.size(); ++i)
+    {
+        doc->IncrementReferens(records.at(i).path);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::DeleteTool(bool ask)
 {
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 50037c4ae..cd15875c8 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -130,6 +130,9 @@ private:
     void RefreshGeometry();
     void SaveDialogChange();
 
+    void InitNodes(const VPiece &detail, VMainGraphicsScene *scene);
+    void InitCSAPaths(const VPiece &detail);
+
     template <typename Tool>
     Tool*              InitTool(VMainGraphicsScene *scene, const VPieceNode &node);
 };

From 109e23e40dd2ba859d012fbe9b97a4463a792b0a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 25 Nov 2016 16:41:52 +0200
Subject: [PATCH 097/208] Refactor VToolSeamAllowance::InitTool. Enough to pass
 only tool id.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 10 +++++-----
 src/libs/vtools/tools/vtoolseamallowance.h   |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 14fa9bfbc..a8cc7b7b2 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -741,7 +741,7 @@ void VToolSeamAllowance::InitNodes(const VPiece &detail, VMainGraphicsScene *sce
         {
             case (Tool::NodePoint):
             {
-                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.GetPath().at(i));
+                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.GetPath().at(i).GetId());
                 connect(tool, &VNodePoint::ShowContextMenu, this, &VToolSeamAllowance::contextMenuEvent);
                 break;
             }
@@ -812,17 +812,17 @@ template <typename Tool>
 /**
  * @brief InitTool initial node item on scene
  * @param scene pointer to scene.
- * @param node node of detail.
+ * @param toolId if of tool object.
  */
-Tool *VToolSeamAllowance::InitTool(VMainGraphicsScene *scene, const VPieceNode &node)
+Tool *VToolSeamAllowance::InitTool(VMainGraphicsScene *scene, quint32 toolId)
 {
     QHash<quint32, VDataTool*>* tools = doc->getTools();
     SCASSERT(tools != nullptr);
-    Tool *tool = qobject_cast<Tool*>(tools->value(node.GetId()));
+    Tool *tool = qobject_cast<Tool*>(tools->value(toolId));
     SCASSERT(tool != nullptr);
     connect(tool, &Tool::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
     tool->setParentItem(this);
     tool->SetParentType(ParentType::Item);
-    doc->IncrementReferens(node.GetId());
+    doc->IncrementReferens(toolId);
     return tool;
 }
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index cd15875c8..829541eae 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -134,7 +134,7 @@ private:
     void InitCSAPaths(const VPiece &detail);
 
     template <typename Tool>
-    Tool*              InitTool(VMainGraphicsScene *scene, const VPieceNode &node);
+    Tool*              InitTool(VMainGraphicsScene *scene, quint32 toolId);
 };
 
 #endif // VTOOLSEAMALLOWANCE_H

From ecdb53b7d042cc38b149444302a0010fa449e9ea Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 10:42:37 +0200
Subject: [PATCH 098/208] Save VPiecePath name.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp                |  2 ++
 src/libs/vpatterndb/vpiecepath.cpp                | 12 ++++++++++++
 src/libs/vpatterndb/vpiecepath.h                  |  3 +++
 src/libs/vpatterndb/vpiecepath_p.h                | 10 +++++++---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp |  2 ++
 5 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 9d2b643ab..e9f9ae6ba 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -3050,6 +3050,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
     {
         quint32 id = 0;
         ToolsCommonAttributes(domElement, id);
+        const QString name = GetParametrString(domElement, AttrName, tr("Unnamed path"));
         const QString defType = QString().setNum(static_cast<int>(PiecePathType::CustomSeamAllowance));
         const PiecePathType type = static_cast<PiecePathType>(GetParametrUInt(domElement, AttrType, defType));
         const quint32 idTool = GetParametrUInt(domElement, VAbstractNode::AttrIdTool, NULL_ID_STR);
@@ -3062,6 +3063,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
         }
 
         path.SetType(type);
+        path.SetName(name);
 
         VToolPiecePath::Create(id, path, 0, scene, this, data, parse, Source::FromFile, "", idTool);
     }
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 9fbf124a2..78e7fcbd0 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -118,6 +118,18 @@ void VPiecePath::SetType(PiecePathType type)
     d->m_type = type;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QString VPiecePath::GetName() const
+{
+    return d->m_name;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::SetName(const QString &name)
+{
+    d->m_name = name;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
 {
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index daa6893ca..5d83e0580 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -63,6 +63,9 @@ public:
     PiecePathType GetType() const;
     void          SetType(PiecePathType type);
 
+    QString GetName() const;
+    void    SetName(const QString &name);
+
     QVector<QPointF> PathPoints(const VContainer *data) const;
     QVector<QPointF> PathNodePoints(const VContainer *data) const;
 
diff --git a/src/libs/vpatterndb/vpiecepath_p.h b/src/libs/vpatterndb/vpiecepath_p.h
index ea3ca04b4..06ca8089e 100644
--- a/src/libs/vpatterndb/vpiecepath_p.h
+++ b/src/libs/vpatterndb/vpiecepath_p.h
@@ -43,24 +43,28 @@ class VPiecePathData : public QSharedData
 public:
     VPiecePathData()
         : m_nodes(),
-          m_type(PiecePathType::Unknown)
+          m_type(PiecePathType::Unknown),
+          m_name()
     {}
 
     VPiecePathData(PiecePathType type)
         : m_nodes(),
-          m_type(type)
+          m_type(type),
+          m_name()
     {}
 
     VPiecePathData(const VPiecePathData &path)
         : QSharedData(path),
           m_nodes(path.m_nodes),
-          m_type(path.m_type)
+          m_type(path.m_type),
+          m_name(path.m_name)
     {}
 
     ~VPiecePathData();
 
     QVector<VPieceNode> m_nodes;
     PiecePathType m_type;
+    QString m_name;
 
 private:
     VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 7b54ad11e..9d9caf303 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -262,6 +262,7 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
     }
 
     SetType(path.GetType());
+    ui->lineEditName->setText(path.GetName());
 
     ValidObjects(PathIsValid());
 
@@ -348,6 +349,7 @@ VPiecePath DialogPiecePath::CreatePath() const
     }
 
     path.SetType(GetType());
+    path.SetName(ui->lineEditName->text());
 
     return path;
 }

From 7fa1c6f901a7798ae770cffd57289b6e3a0d2a46 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 10:44:47 +0200
Subject: [PATCH 099/208] SavePieceOptions. Removed unused forward
 declaretions.

--HG--
branch : feature
---
 src/libs/vtools/undocommands/savepieceoptions.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/libs/vtools/undocommands/savepieceoptions.h b/src/libs/vtools/undocommands/savepieceoptions.h
index c50ad4aed..dd4b7f8cb 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.h
+++ b/src/libs/vtools/undocommands/savepieceoptions.h
@@ -34,8 +34,6 @@
 #include "vpiece.h"
 #include "vundocommand.h"
 
-class QDomElement;
-class QGraphicsScene;
 class QUndoCommand;
 class VAbstractPattern;
 

From 0d65f1f4d6222203ddb6e529fea99698c3c0e7ea Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 10:45:02 +0200
Subject: [PATCH 100/208] Fixed code style.

--HG--
branch : feature
---
 src/libs/vtools/undocommands/savepieceoptions.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index ae7e28f3d..92759370e 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -48,7 +48,8 @@ class QDomElement;
 class QUndoCommand;
 
 //---------------------------------------------------------------------------------------------------------------------
-SavePieceOptions::SavePieceOptions(const VPiece &oldDet, const VPiece &newDet, VAbstractPattern *doc, quint32 id, QUndoCommand *parent)
+SavePieceOptions::SavePieceOptions(const VPiece &oldDet, const VPiece &newDet, VAbstractPattern *doc, quint32 id,
+                                   QUndoCommand *parent)
     : VUndoCommand(QDomElement(), doc, parent),
       m_oldDet(oldDet),
       m_newDet(newDet)

From 9c3a49e43f47f9c2a27bc74101d8d1f1bf8d0bff Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 10:45:57 +0200
Subject: [PATCH 101/208] Renamed DialogPiecePath::DisableShowMode to
 DialogPiecePath::EnbleShowMode.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 2 +-
 src/libs/vtools/dialogs/tools/dialogpiecepath.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 9d9caf303..885700f4c 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -74,7 +74,7 @@ DialogPiecePath::~DialogPiecePath()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::DisableShowMode(bool disable)
+void DialogPiecePath::EnbleShowMode(bool disable)
 {
     m_showMode = disable;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 6a9e3d6ef..4e1f79d00 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -43,7 +43,7 @@ public:
     explicit DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent = nullptr);
     virtual ~DialogPiecePath();
 
-    void DisableShowMode(bool disable);
+    void EnbleShowMode(bool disable);
 
     VPiecePath GetPiecePath() const;
     void       SetPiecePath(const VPiecePath &path);

From fea2ec52fec35c7ecdc1e808ff1e4ace20be1e2e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 10:47:36 +0200
Subject: [PATCH 102/208] New section "Custom seam allowance".

--HG--
branch : feature
---
 src/libs/vmisc/def.h                          |   1 +
 src/libs/vpatterndb/vpiece.cpp                |  62 +---
 src/libs/vpatterndb/vpiece.h                  |   4 -
 src/libs/vpatterndb/vpiecepath.cpp            |  48 +++
 src/libs/vpatterndb/vpiecepath.h              |   4 +
 .../dialogs/tools/dialogseamallowance.cpp     | 285 ++++++++++++++++--
 .../dialogs/tools/dialogseamallowance.h       |  14 +-
 .../dialogs/tools/dialogseamallowance.ui      |  96 +++++-
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  14 +-
 .../vtools/tools/nodeDetails/vtoolpiecepath.h |   1 +
 .../undocommands/savepiecepathoptions.cpp     | 139 +++++++++
 .../undocommands/savepiecepathoptions.h       |  62 ++++
 src/libs/vtools/undocommands/undocommands.pri |   6 +-
 src/libs/vtools/undocommands/vundocommand.h   |   1 +
 14 files changed, 623 insertions(+), 114 deletions(-)
 create mode 100644 src/libs/vtools/undocommands/savepiecepathoptions.cpp
 create mode 100644 src/libs/vtools/undocommands/savepiecepathoptions.h

diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index e16eb5add..c90dd6c78 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -695,6 +695,7 @@ struct CustomSARecord
     bool reverse;
 };
 
+Q_DECLARE_METATYPE(CustomSARecord)
 Q_DECLARE_TYPEINFO(CustomSARecord, Q_MOVABLE_TYPE);
 
 /****************************************************************************
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index a77a15540..bd42a1945 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -252,36 +252,7 @@ void VPiece::SetCustomSARecords(const QVector<CustomSARecord> &records)
  */
 QVector<quint32> VPiece::MissingNodes(const VPiece &det) const
 {
-    const QVector<VPieceNode> pNodes = d->m_path.GetNodes();
-    if (pNodes.size() == det.GetPath().CountNodes()) //-V807
-    {
-        return QVector<quint32>();
-    }
-
-    QSet<quint32> set1;
-    for (qint32 i = 0; i < pNodes.size(); ++i)
-    {
-        set1.insert(pNodes.at(i).GetId());
-    }
-
-    QSet<quint32> set2;
-    for (qint32 j = 0; j < det.GetPath().CountNodes(); ++j)
-    {
-        set2.insert(det.GetPath().at(j).GetId());
-    }
-
-    const QList<quint32> set3 = set1.subtract(set2).toList();
-    QVector<quint32> nodes;
-    for (qint32 i = 0; i < set3.size(); ++i)
-    {
-        const int index = indexOfNode(pNodes, set3.at(i));
-        if (index != -1)
-        {
-            nodes.append(pNodes.at(index).GetId());
-        }
-    }
-
-    return nodes;
+    return d->m_path.MissingNodes(det.GetPath());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -315,17 +286,6 @@ QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
     return r;
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief indexOfNode return index in list node using id object.
- * @param id object (arc, point, spline, splinePath) id.
- * @return index in list or -1 id can't find.
- */
-int VPiece::indexOfNode(const quint32 &id) const
-{
-    return indexOfNode(d->m_path.GetNodes(), id);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                        const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
@@ -410,23 +370,3 @@ void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VCont
         }
     }
 }
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief indexOfNode return index in list node using id object.
- * @param list list nodes detail.
- * @param id object (arc, point, spline, splinePath) id.
- * @return index in list or -1 id can't find.
- */
-int VPiece::indexOfNode(const QVector<VPieceNode> &list, quint32 id)
-{
-    for (int i = 0; i < list.size(); ++i)
-    {
-        if (list.at(i).GetId() == id)
-        {
-            return i;
-        }
-    }
-    qDebug()<<"Can't find node.";
-    return -1;
-}
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 255beb9a4..3eca969ed 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -81,15 +81,11 @@ public:
     QVector<quint32> MissingNodes(const VPiece &det) const;
     QVector<quint32> MissingCSAPath(const VPiece &det) const;
 
-    int indexOfNode(const quint32 &id) const;
-
 private:
     QSharedDataPointer<VPieceData> d;
 
     void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
                                    const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
-
-    static int indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };
 
 Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 78e7fcbd0..87e1a9484 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -314,3 +314,51 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
     }
     return end;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VPiecePath::MissingNodes(const VPiecePath &path) const
+{
+    if (d->m_nodes.size() == path.CountNodes()) //-V807
+    {
+        return QVector<quint32>();
+    }
+
+    QSet<quint32> set1;
+    for (qint32 i = 0; i < d->m_nodes.size(); ++i)
+    {
+        set1.insert(d->m_nodes.at(i).GetId());
+    }
+
+    QSet<quint32> set2;
+    for (qint32 j = 0; j < path.CountNodes(); ++j)
+    {
+        set2.insert(path.at(j).GetId());
+    }
+
+    const QList<quint32> set3 = set1.subtract(set2).toList();
+    QVector<quint32> nodes;
+    for (qint32 i = 0; i < set3.size(); ++i)
+    {
+        const int index = indexOfNode(set3.at(i));
+        if (index != -1)
+        {
+            nodes.append(d->m_nodes.at(index).GetId());
+        }
+    }
+
+    return nodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int VPiecePath::indexOfNode(quint32 id) const
+{
+    for (int i = 0; i < d->m_nodes.size(); ++i)
+    {
+        if (d->m_nodes.at(i).GetId() == id)
+        {
+            return i;
+        }
+    }
+    qDebug()<<"Can't find node.";
+    return -1;
+}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 5d83e0580..facfa10f2 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -74,6 +74,10 @@ public:
     VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
     VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
 
+    QVector<quint32> MissingNodes(const VPiecePath &path) const;
+
+    int indexOfNode(quint32 id) const;
+
 private:
     QSharedDataPointer<VPiecePathData> d;
 };
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 653e21f4a..0b08a1595 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -31,6 +31,8 @@
 #include "../vpatterndb/vpiecenode.h"
 #include "../vpatterndb/vpiecepath.h"
 #include "visualization/path/vistoolpiece.h"
+#include "dialogpiecepath.h"
+#include "../../undocommands/savepiecepathoptions.h"
 
 #include <QMenu>
 
@@ -40,7 +42,8 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
       ui(new Ui::DialogSeamAllowance),
       applyAllowed(false),// By default disabled
       m_mx(0),
-      m_my(0)
+      m_my(0),
+      m_dialog()
 {
     ui->setupUi(this);
 
@@ -82,15 +85,25 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
             this, &DialogSeamAllowance::ChangedSAAfter);
 
-    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogSeamAllowance::ShowContextMenu);
-    connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
+    ui->listWidgetMainPath->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetMainPath, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowMainPathContextMenu);
+    connect(ui->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
     connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
 
     InitNodeAngles();
     connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::NodeAngleChanged);
 
+    ui->listWidgetCustomSA->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetCustomSA, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowCustomSAContextMenu);
+    connect(ui->listWidgetCustomSA, &QListWidget::currentRowChanged, this, &DialogSeamAllowance::CustomSAChanged);
+    connect(ui->comboBoxStartPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAStartPointChanged);
+    connect(ui->comboBoxEndPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAEndPointChanged);
+
     if (not applyAllowed)
     {
         vis = new VisToolPiece(data);
@@ -123,12 +136,31 @@ VPiece DialogSeamAllowance::GetPiece() const
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::SetPiece(const VPiece &piece)
 {
-    ui->listWidget->clear();
+    ui->listWidgetMainPath->clear();
     for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
     {
-        NewItem(piece.GetPath().at(i));
+        NewMainPathItem(piece.GetPath().at(i));
     }
 
+    ui->listWidgetCustomSA->blockSignals(true);
+    ui->listWidgetCustomSA->clear();
+    const QVector<CustomSARecord> records = piece.GetCustomSARecords();
+    for (int i = 0; i < records.size(); ++i)
+    {
+        NewCustomSA(records.at(i));
+    }
+    ui->listWidgetCustomSA->blockSignals(false);
+
+    ui->comboBoxStartPoint->blockSignals(true);
+    ui->comboBoxStartPoint->clear();
+    ui->comboBoxStartPoint->blockSignals(false);
+
+    ui->comboBoxEndPoint->blockSignals(true);
+    ui->comboBoxEndPoint->clear();
+    ui->comboBoxEndPoint->blockSignals(false);
+
+    CustomSAChanged(0);
+
     ui->checkBoxForbidFlipping->setChecked(piece.IsForbidFlipping());
     ui->doubleSpinBoxSeams->setValue(piece.GetSAWidth());
     ui->checkBoxSeams->setChecked(piece.IsSeamAllowance());
@@ -159,16 +191,16 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
         switch (type)
         {
             case SceneObject::Arc:
-                NewItem(VPieceNode(id, Tool::NodeArc, reverse));
+                NewMainPathItem(VPieceNode(id, Tool::NodeArc, reverse));
                 break;
             case SceneObject::Point:
-                NewItem(VPieceNode(id, Tool::NodePoint));
+                NewMainPathItem(VPieceNode(id, Tool::NodePoint));
                 break;
             case SceneObject::Spline:
-                NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
+                NewMainPathItem(VPieceNode(id, Tool::NodeSpline, reverse));
                 break;
             case SceneObject::SplinePath:
-                NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+                NewMainPathItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
                 break;
             case (SceneObject::Line):
             case (SceneObject::Detail):
@@ -241,10 +273,10 @@ void DialogSeamAllowance::CheckState()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
+void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
 {
-    const int row = ui->listWidget->currentRow();
-    if (ui->listWidget->count() == 0 || row == -1 || row >= ui->listWidget->count())
+    const int row = ui->listWidgetMainPath->currentRow();
+    if (ui->listWidgetMainPath->count() == 0 || row == -1 || row >= ui->listWidgetMainPath->count())
     {
         return;
     }
@@ -253,7 +285,7 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
     QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
     actionDelete->setEnabled(applyAllowed);//Because we can't undo this operation when creating a piece.
 
-    QListWidgetItem *rowItem = ui->listWidget->item(row);
+    QListWidgetItem *rowItem = ui->listWidgetMainPath->item(row);
     SCASSERT(rowItem != nullptr);
     VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
 
@@ -265,10 +297,10 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
         actionReverse->setChecked(rowNode.GetReverse());
     }
 
-    QAction *selectedAction = menu->exec(ui->listWidget->viewport()->mapToGlobal(pos));
+    QAction *selectedAction = menu->exec(ui->listWidgetMainPath->viewport()->mapToGlobal(pos));
     if (selectedAction == actionDelete)
     {
-        delete ui->listWidget->item(row);
+        delete ui->listWidgetMainPath->item(row);
         ValidObjects(MainPathIsValid());
     }
     else if (selectedAction == actionReverse)
@@ -282,6 +314,52 @@ void DialogSeamAllowance::ShowContextMenu(const QPoint &pos)
     ListChanged();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
+{
+    const int row = ui->listWidgetCustomSA->currentRow();
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
+    {
+        return;
+    }
+
+    QMenu *menu = new QMenu(this);
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+
+    QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
+    SCASSERT(rowItem != nullptr);
+    CustomSARecord record = qvariant_cast<CustomSARecord>(rowItem->data(Qt::UserRole));
+
+    QAction *actionReverse = menu->addAction(tr("Reverse"));
+    actionReverse->setCheckable(true);
+    actionReverse->setChecked(record.reverse);
+
+    QAction *actionOption = menu->addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
+
+    QAction *selectedAction = menu->exec(ui->listWidgetCustomSA->viewport()->mapToGlobal(pos));
+    if (selectedAction == actionDelete)
+    {
+        delete ui->listWidgetCustomSA->item(row);
+    }
+    else if (selectedAction == actionReverse)
+    {
+        record.reverse = not record.reverse;
+        rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
+        rowItem->setText(GetCustomSARecordName(record));
+    }
+    else if (selectedAction == actionOption)
+    {
+        auto *dialog = new DialogPiecePath(data, record.path, this);
+        dialog->SetPiecePath(data->GetPiecePath(record.path));
+        dialog->SetPieceId(toolId);
+        dialog->EnbleShowMode(true);
+        m_dialog = dialog;
+        m_dialog->setModal(true);
+        connect(m_dialog.data(), &DialogTool::DialogClosed, this, &DialogSeamAllowance::PathDialogClosed);
+        m_dialog->show();
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ListChanged()
 {
@@ -299,6 +377,7 @@ void DialogSeamAllowance::ListChanged()
 void DialogSeamAllowance::EnableSeamAllowance(bool enable)
 {
     ui->groupBoxAutomatic->setEnabled(enable);
+    ui->groupBoxCustom->setEnabled(enable);
 
     if (enable)
     {
@@ -327,7 +406,7 @@ void DialogSeamAllowance::NodeChanged(int index)
         const quint32 id = ui->comboBoxNodes->currentData().toUInt();
     #endif
         const VPiece piece = CreatePiece();
-        const int nodeIndex = piece.indexOfNode(id);
+        const int nodeIndex = piece.GetPath().indexOfNode(id);
         if (nodeIndex != -1)
         {
             const VPieceNode &node = piece.GetPath().at(nodeIndex);
@@ -377,6 +456,52 @@ void DialogSeamAllowance::NodeChanged(int index)
     ui->comboBoxAngle->blockSignals(false);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::CSAStartPointChanged(int index)
+{
+    const int row = ui->listWidgetCustomSA->currentRow();
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
+    {
+        return;
+    }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const quint32 startPoint = ui->comboBoxStartPoint->itemData(index).toUInt();
+#else
+    Q_UNUSED(index);
+    const quint32 startPoint = ui->comboBoxStartPoint->currentData().toUInt();
+#endif
+
+    QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
+    SCASSERT(rowItem != nullptr);
+    CustomSARecord record = qvariant_cast<CustomSARecord>(rowItem->data(Qt::UserRole));
+    record.startPoint = startPoint;
+    rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::CSAEndPointChanged(int index)
+{
+    const int row = ui->listWidgetCustomSA->currentRow();
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
+    {
+        return;
+    }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const quint32 endPoint = ui->comboBoxEndPoint->itemData(index).toUInt();
+#else
+    Q_UNUSED(index);
+    const quint32 endPoint = ui->comboBoxEndPoint->currentData().toUInt();
+#endif
+
+    QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
+    SCASSERT(rowItem != nullptr);
+    CustomSARecord record = qvariant_cast<CustomSARecord>(rowItem->data(Qt::UserRole));
+    record.endPoint = endPoint;
+    rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::NodeAngleChanged(int index)
 {
@@ -431,13 +556,69 @@ void DialogSeamAllowance::ChangedSAAfter(double d)
     SetCurrentSAAfter(d);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::CustomSAChanged(int row)
+{
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
+    {
+        return;
+    }
+
+    ui->comboBoxStartPoint->blockSignals(true);
+    ui->comboBoxEndPoint->blockSignals(true);
+
+    InitCSAPoint(ui->comboBoxStartPoint);
+    InitCSAPoint(ui->comboBoxEndPoint);
+
+    const QListWidgetItem *item = ui->listWidgetCustomSA->item( row );
+    SCASSERT(item != nullptr);
+    const CustomSARecord record = qvariant_cast<CustomSARecord>(item->data(Qt::UserRole));
+
+    {
+        const int index = ui->comboBoxStartPoint->findData(record.startPoint);
+        if (index != -1)
+        {
+            ui->comboBoxStartPoint->setCurrentIndex(index);
+        }
+    }
+
+    {
+        const int index = ui->comboBoxEndPoint->findData(record.endPoint);
+        if (index != -1)
+        {
+            ui->comboBoxEndPoint->setCurrentIndex(index);
+        }
+    }
+
+    ui->comboBoxStartPoint->blockSignals(false);
+    ui->comboBoxEndPoint->blockSignals(false);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::PathDialogClosed(int result)
+{
+    if (result == QDialog::Accepted)
+    {
+        SCASSERT(not m_dialog.isNull());
+        DialogPiecePath *dialogTool = qobject_cast<DialogPiecePath*>(m_dialog.data());
+        SCASSERT(dialogTool != nullptr);
+        const VPiecePath newPath = dialogTool->GetPiecePath();
+        const VPiecePath oldPath = data->GetPiecePath(dialogTool->GetPieceId());
+
+        SavePiecePathOptions *saveCommand = new SavePiecePathOptions(newPath, oldPath, qApp->getCurrentDocument(),
+                                                                     const_cast<VContainer *>(data), toolId);
+        qApp->getUndoStack()->push(saveCommand);
+    }
+    delete m_dialog;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::CreatePiece() const
 {
     VPiece piece;
-    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    for (qint32 i = 0; i < ui->listWidgetMainPath->count(); ++i)
     {
-        QListWidgetItem *item = ui->listWidget->item(i);
+        QListWidgetItem *item = ui->listWidgetMainPath->item(i);
         piece.GetPath().Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
     }
 
@@ -451,9 +632,43 @@ VPiece DialogSeamAllowance::CreatePiece() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::NewItem(const VPieceNode &node)
+void DialogSeamAllowance::NewMainPathItem(const VPieceNode &node)
 {
-    NewNodeItem(ui->listWidget, node);
+    NewNodeItem(ui->listWidgetMainPath, node);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::NewCustomSA(const CustomSARecord &record)
+{
+    if (record.path > NULL_ID)
+    {
+        const QString name = GetCustomSARecordName(record);
+
+        QListWidgetItem *item = new QListWidgetItem(name);
+        item->setFont(QFont("Times", 12, QFont::Bold));
+        item->setData(Qt::UserRole, QVariant::fromValue(record));
+        ui->listWidgetCustomSA->addItem(item);
+        ui->listWidgetCustomSA->setCurrentRow(ui->listWidgetCustomSA->count()-1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetCustomSARecordName(const CustomSARecord &record) const
+{
+    QString name;
+
+    if (record.path > NULL_ID)
+    {
+        const VPiecePath path = data->GetPiecePath(record.path);
+        name = path.GetName();
+
+        if (record.reverse)
+        {
+            name = QLatin1String("- ") + name;
+        }
+    }
+
+    return name;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -475,13 +690,13 @@ bool DialogSeamAllowance::MainPathIsValid() const
             ui->helpLabel->setText(url);
             return false;
         }
-        if (FirstPointEqualLast(ui->listWidget))
+        if (FirstPointEqualLast(ui->listWidgetMainPath))
         {
             url += tr("First point cannot be equal to the last point!");
             ui->helpLabel->setText(url);
             return false;
         }
-        else if (DoublePoints(ui->listWidget))
+        else if (DoublePoints(ui->listWidgetMainPath))
         {
             url += tr("You have double points!");
             ui->helpLabel->setText(url);
@@ -576,9 +791,9 @@ void DialogSeamAllowance::InitNodeAngles()
 //---------------------------------------------------------------------------------------------------------------------
 QListWidgetItem *DialogSeamAllowance::GetItemById(quint32 id)
 {
-    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    for (qint32 i = 0; i < ui->listWidgetMainPath->count(); ++i)
     {
-        QListWidgetItem *item = ui->listWidget->item(i);
+        QListWidgetItem *item = ui->listWidgetMainPath->item(i);
         const VPieceNode node = qvariant_cast<VPieceNode>(item->data(Qt::UserRole));
 
         if (node.GetId() == id)
@@ -636,3 +851,23 @@ void DialogSeamAllowance::SetCurrentSAAfter(qreal value)
         }
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitCSAPoint(QComboBox *box)
+{
+    SCASSERT(box != nullptr);
+    box->clear();
+    box->addItem(tr("Empty"), NULL_ID);
+
+    const VPiece piece = CreatePiece();
+
+    for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
+    {
+        const VPieceNode &node = piece.GetPath().at(i);
+        if (node.GetTypeTool() == Tool::NodePoint)
+        {
+            const QString name = GetNodeName(node);
+            box->addItem(name, node.GetId());
+        }
+    }
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 114967881..f90fa75df 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -60,15 +60,20 @@ protected:
     virtual void CheckState() Q_DECL_OVERRIDE;
 
 private slots:
-    void ShowContextMenu(const QPoint &pos);
+    void ShowMainPathContextMenu(const QPoint &pos);
+    void ShowCustomSAContextMenu(const QPoint &pos);
     void ListChanged();
     void EnableSeamAllowance(bool enable);
     void NodeChanged(int index);
+    void CSAStartPointChanged(int index);
+    void CSAEndPointChanged(int index);
     void NodeAngleChanged(int index);
     void ReturnDefBefore();
     void ReturnDefAfter();
     void ChangedSABefore(double d);
     void ChangedSAAfter(double d);
+    void CustomSAChanged(int row);
+    void PathDialogClosed(int result);
 
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
@@ -78,14 +83,19 @@ private:
     qreal  m_mx;
     qreal  m_my;
 
+    QPointer<DialogTool> m_dialog;
+
     VPiece CreatePiece() const;
 
-    void    NewItem(const VPieceNode &node);
+    void    NewMainPathItem(const VPieceNode &node);
+    void    NewCustomSA(const CustomSARecord &record);
+    QString GetCustomSARecordName(const CustomSARecord &record) const;
     bool    MainPathIsValid() const;
     void    ValidObjects(bool value);
     bool    MainPathIsClockwise() const;
     void    InitNodesList();
     void    InitNodeAngles();
+    void    InitCSAPoint(QComboBox *box);
 
     QListWidgetItem *GetItemById(quint32 id);
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 6af522a18..e27204d0f 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -7,21 +7,21 @@
     <x>0</x>
     <y>0</y>
     <width>559</width>
-    <height>423</height>
+    <height>476</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Dialog</string>
   </property>
   <property name="windowIcon">
-   <iconset>
+   <iconset resource="../../../vmisc/share/resources/icon.qrc">
     <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -42,7 +42,7 @@
             <string/>
            </property>
            <property name="pixmap">
-            <pixmap>:/icon/32x32/clockwise.png</pixmap>
+            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/32x32/clockwise.png</pixmap>
            </property>
           </widget>
          </item>
@@ -69,7 +69,7 @@
         </widget>
        </item>
        <item>
-        <widget class="QListWidget" name="listWidget">
+        <widget class="QListWidget" name="listWidgetMainPath">
          <property name="dragDropMode">
           <enum>QAbstractItemView::InternalMove</enum>
          </property>
@@ -94,7 +94,7 @@
       <attribute name="title">
        <string>Seam allowance</string>
       </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_4">
+      <layout class="QVBoxLayout" name="verticalLayout_5">
        <item>
         <widget class="QCheckBox" name="checkBoxSeams">
          <property name="text">
@@ -113,10 +113,19 @@
          <property name="title">
           <string>Automatic</string>
          </property>
+         <property name="flat">
+          <bool>false</bool>
+         </property>
          <property name="checkable">
           <bool>false</bool>
          </property>
          <layout class="QVBoxLayout" name="verticalLayout_3">
+          <property name="topMargin">
+           <number>9</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
           <item>
            <layout class="QHBoxLayout" name="horizontalLayout_2">
             <item>
@@ -269,22 +278,75 @@
             </layout>
            </widget>
           </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBoxCustom">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="title">
+          <string>Custom</string>
+         </property>
+         <property name="flat">
+          <bool>false</bool>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_4">
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
           <item>
-           <spacer name="verticalSpacer">
+           <widget class="QSplitter" name="splitter">
             <property name="orientation">
-             <enum>Qt::Vertical</enum>
+             <enum>Qt::Horizontal</enum>
             </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>20</width>
-              <height>219</height>
-             </size>
-            </property>
-           </spacer>
+            <widget class="QWidget" name="layoutWidget">
+             <layout class="QFormLayout" name="formLayout_2">
+              <property name="fieldGrowthPolicy">
+               <enum>QFormLayout::ExpandingFieldsGrow</enum>
+              </property>
+              <item row="0" column="0">
+               <widget class="QLabel" name="labelStartPoint">
+                <property name="text">
+                 <string>Start point:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QComboBox" name="comboBoxStartPoint"/>
+              </item>
+              <item row="1" column="0">
+               <widget class="QLabel" name="labelEndPoint">
+                <property name="text">
+                 <string>End point:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1">
+               <widget class="QComboBox" name="comboBoxEndPoint"/>
+              </item>
+             </layout>
+            </widget>
+            <widget class="QListWidget" name="listWidgetCustomSA"/>
+           </widget>
           </item>
          </layout>
         </widget>
        </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
       </layout>
      </widget>
     </widget>
@@ -301,7 +363,9 @@
    </item>
   </layout>
  </widget>
- <resources/>
+ <resources>
+  <include location="../../../vmisc/share/resources/icon.qrc"/>
+ </resources>
  <connections>
   <connection>
    <sender>buttonBox</sender>
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index 7527af36c..492c6d17d 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -151,6 +151,14 @@ void VToolPiecePath::AddNodes(VAbstractPattern *doc, QDomElement &domElement, co
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiecePath &path)
+{
+    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+    doc->SetAttribute(domElement, AttrName, path.GetName());
+    doc->SetAttribute(domElement, AttrType, static_cast<int>(path.GetType()));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::FullUpdateFromFile()
 {
@@ -175,11 +183,9 @@ void VToolPiecePath::AllowSelecting(bool enabled)
 void VToolPiecePath::AddToFile()
 {
     QDomElement domElement = doc->createElement(getTagName());
-
-    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
-
     const VPiecePath path = VAbstractTool::data.GetPiecePath(id);
-    doc->SetAttribute(domElement, AttrType, static_cast<int>(path.GetType()));
+
+    AddAttributes(doc, domElement, id, path);
 
     if (idTool != NULL_ID)
     {
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
index c204dac34..18f4e236d 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
@@ -52,6 +52,7 @@ public:
 
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
     static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path);
+    static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiecePath &path);
 public slots:
     virtual void FullUpdateFromFile () Q_DECL_OVERRIDE;
     virtual void AllowHover(bool enabled) Q_DECL_OVERRIDE;
diff --git a/src/libs/vtools/undocommands/savepiecepathoptions.cpp b/src/libs/vtools/undocommands/savepiecepathoptions.cpp
new file mode 100644
index 000000000..61f155e4b
--- /dev/null
+++ b/src/libs/vtools/undocommands/savepiecepathoptions.cpp
@@ -0,0 +1,139 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   26 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 "savepiecepathoptions.h"
+
+#include <QDomElement>
+#include <QUndoCommand>
+#include <QDebug>
+
+#include "../ifc/xml/vabstractpattern.h"
+#include "../vmisc/logging.h"
+#include "../tools/nodeDetails/vtoolpiecepath.h"
+
+class QDomElement;
+class QUndoCommand;
+
+//---------------------------------------------------------------------------------------------------------------------
+SavePiecePathOptions::SavePiecePathOptions(const VPiecePath &oldPath, const VPiecePath &newPath,
+                                           VAbstractPattern *doc, VContainer *data, quint32 id,
+                                           QUndoCommand *parent)
+    : VUndoCommand(QDomElement(), doc, parent),
+      m_oldPath(oldPath),
+      m_newPath(newPath),
+      m_data(data)
+{
+    setText(tr("save path options"));
+    nodeId = id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+SavePiecePathOptions::~SavePiecePathOptions()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SavePiecePathOptions::undo()
+{
+    qCDebug(vUndo, "Undo.");
+
+    QDomElement domElement = doc->elementById(nodeId);
+    if (domElement.isElement())
+    {
+        VToolPiecePath::AddAttributes(doc, domElement, nodeId, m_oldPath);
+        doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
+        VToolPiecePath::AddNodes(doc, domElement, m_oldPath);
+
+        IncrementReferences(m_oldPath.MissingNodes(m_newPath));
+
+        SCASSERT(m_data);
+        m_data->UpdatePiecePath(nodeId, m_oldPath);
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find path with id = %u.", nodeId);
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SavePiecePathOptions::redo()
+{
+    qCDebug(vUndo, "Redo.");
+
+    QDomElement domElement = doc->elementById(nodeId);
+    if (domElement.isElement())
+    {
+        VToolPiecePath::AddAttributes(doc, domElement, nodeId, m_newPath);
+        doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
+        VToolPiecePath::AddNodes(doc, domElement, m_newPath);
+
+        DecrementReferences(m_oldPath.MissingNodes(m_newPath));
+
+        SCASSERT(m_data);
+        m_data->UpdatePiecePath(nodeId, m_oldPath);
+    }
+    else
+    {
+        qCDebug(vUndo, "Can't find path with id = %u.", nodeId);
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool SavePiecePathOptions::mergeWith(const QUndoCommand *command)
+{
+    const SavePiecePathOptions *saveCommand = static_cast<const SavePiecePathOptions *>(command);
+    SCASSERT(saveCommand != nullptr);
+    const quint32 id = saveCommand->PathId();
+
+    if (id != nodeId)
+    {
+        return false;
+    }
+
+    m_newPath = saveCommand->NewPath();
+    return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int SavePiecePathOptions::id() const
+{
+    return static_cast<int>(UndoCommand::SavePiecePathOptions);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 SavePiecePathOptions::PathId() const
+{
+    return nodeId;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath SavePiecePathOptions::NewPath() const
+{
+    return m_newPath;
+}
diff --git a/src/libs/vtools/undocommands/savepiecepathoptions.h b/src/libs/vtools/undocommands/savepiecepathoptions.h
new file mode 100644
index 000000000..f869df012
--- /dev/null
+++ b/src/libs/vtools/undocommands/savepiecepathoptions.h
@@ -0,0 +1,62 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   26 11, 2016
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2016 Valentina project
+ **  <https://bitbucket.org/dismine/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 SAVEPIECEPATHOPTIONS_H
+#define SAVEPIECEPATHOPTIONS_H
+
+#include <QtGlobal>
+
+#include "../vpatterndb/vpiecepath.h"
+#include "vundocommand.h"
+
+class QUndoCommand;
+class VAbstractPattern;
+
+class SavePiecePathOptions : public VUndoCommand
+{
+public:
+    SavePiecePathOptions(const VPiecePath &oldPath, const VPiecePath &newPath, VAbstractPattern *doc,
+                         VContainer *data, quint32 id, QUndoCommand *parent = nullptr);
+    virtual ~SavePiecePathOptions();
+
+    virtual void undo() Q_DECL_OVERRIDE;
+    virtual void redo() Q_DECL_OVERRIDE;
+    virtual bool mergeWith(const QUndoCommand *command) Q_DECL_OVERRIDE;
+    virtual int  id() const Q_DECL_OVERRIDE;
+    quint32      PathId() const;
+    VPiecePath   NewPath() const;
+private:
+    Q_DISABLE_COPY(SavePiecePathOptions)
+
+    const VPiecePath m_oldPath;
+    VPiecePath       m_newPath;
+
+    VContainer *m_data;
+};
+
+#endif // SAVEPIECEPATHOPTIONS_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index c73295eee..a682f0e26 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -26,7 +26,8 @@ HEADERS += \
     $$PWD/deletepiece.h \
     $$PWD/movepiece.h \
     $$PWD/savepieceoptions.h \
-    $$PWD/togglepieceinlayout.h
+    $$PWD/togglepieceinlayout.h \
+    $$PWD/savepiecepathoptions.h
 
 SOURCES += \
     $$PWD/addtocalc.cpp \
@@ -53,4 +54,5 @@ SOURCES += \
     $$PWD/deletepiece.cpp \
     $$PWD/movepiece.cpp \
     $$PWD/savepieceoptions.cpp \
-    $$PWD/togglepieceinlayout.cpp
+    $$PWD/togglepieceinlayout.cpp \
+    $$PWD/savepiecepathoptions.cpp
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index dea2b9ff8..b6211a239 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -55,6 +55,7 @@ enum class UndoCommand: char { AddPatternPiece,
                                SaveToolOptions,
                                SaveDetailOptions,
                                SavePieceOptions,
+                               SavePiecePathOptions,
                                MovePiece,
                                DeleteTool,
                                DeletePatternPiece,

From 530203966e6ec65a7022941627ed282f96429e35 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 11:22:29 +0200
Subject: [PATCH 103/208] Added custom seam allowance to XSD schema.

--HG--
branch : feature
---
 src/libs/ifc/schema/pattern/v0.4.0.xsd | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 055575a49..6fa03906b 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -430,6 +430,20 @@
 																						 </xs:sequence>
 																					 </xs:complexType>
 																				</xs:element>
+																				<xs:element name="csa" minOccurs="0" maxOccurs="1">
+																					<xs:complexType>
+																						<xs:sequence>
+																						   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+																								   <xs:complexType>
+																										 <xs:attribute name="start" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
+																										 <xs:attribute name="end" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="reverse" type="xs:boolean"></xs:attribute>
+																								   </xs:complexType>
+																							 </xs:element>
+																						 </xs:sequence>
+																					 </xs:complexType>
+																				</xs:element>
                                                                            </xs:sequence>
                                                                            <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
                                                                            <xs:attribute name="version" type="pieceVersion"></xs:attribute>

From f56ea24810ad4c3dcf206fbd74d0697ca1ce3c28 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 11:58:44 +0200
Subject: [PATCH 104/208] Custom Path will work in two modes. The first extend
 automatic seam allowance, the second show custom deam allowance. In this case
 a path must have options for controling seam allowance.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            | 112 +++++++-----------
 src/app/valentina/xml/vpattern.h              |   2 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |   3 +
 src/libs/ifc/xml/vabstractpattern.cpp         |   2 +
 src/libs/ifc/xml/vabstractpattern.h           |   2 +
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  31 +----
 src/libs/vtools/tools/vabstracttool.cpp       |  57 +++++++++
 src/libs/vtools/tools/vabstracttool.h         |   6 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  48 +-------
 src/libs/vtools/tools/vtoolseamallowance.h    |   2 -
 10 files changed, 117 insertions(+), 148 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index e9f9ae6ba..a5f58cf22 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -520,6 +520,49 @@ void VPattern::customEvent(QEvent *event)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
+{
+    const quint32 id = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
+    const bool reverse = GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
+    const qreal saBefore = GetParametrDouble(domElement, VAbstractPattern::AttrSABefore, "-1");
+    const qreal saAfter = GetParametrDouble(domElement, VAbstractPattern::AttrSAAfter, "-1");
+    const PieceNodeAngle angle = static_cast<PieceNodeAngle>(GetParametrUInt(domElement, AttrAngle, "0"));
+
+    const QString t = GetParametrString(domElement, AttrType, VAbstractPattern::NodePoint);
+    Tool tool;
+
+    const QStringList types = QStringList() << VAbstractPattern::NodePoint
+                                            << VAbstractPattern::NodeArc
+                                            << VAbstractPattern::NodeSpline
+                                            << VAbstractPattern::NodeSplinePath;
+
+    switch (types.indexOf(t))
+    {
+        case 0: // VAbstractPattern::NodePoint
+            tool = Tool::NodePoint;
+            break;
+        case 1: // VAbstractPattern::NodeArc
+            tool = Tool::NodeArc;
+            break;
+        case 2: // VAbstractPattern::NodeSpline
+            tool = Tool::NodeSpline;
+            break;
+        case 3: // VAbstractPattern::NodeSplinePath
+            tool = Tool::NodeSplinePath;
+            break;
+        default:
+            VException e(tr("Wrong tag name '%1'.").arg(t));
+            throw e;
+    }
+    VPieceNode node(id, tool, reverse);
+    node.SetSABefore(saBefore);
+    node.SetSAAfter(saAfter);
+    node.SetAngleType(angle);
+
+    return node;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDrawElement parse draw tag.
@@ -777,49 +820,13 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 //---------------------------------------------------------------------------------------------------------------------
 void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const
 {
-    const QStringList types = QStringList() << VAbstractPattern::NodePoint
-                                            << VAbstractPattern::NodeArc
-                                            << VAbstractPattern::NodeSpline
-                                            << VAbstractPattern::NodeSplinePath;
-
     const QDomNodeList nodeList = domElement.childNodes();
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
         if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
         {
-            const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-            const bool reverse = GetParametrUInt(element, VAbstractPattern::AttrNodeReverse, "0");
-            const qreal saBefore = GetParametrDouble(element, VToolSeamAllowance::AttrSABefore, "-1");
-            const qreal saAfter = GetParametrDouble(element, VToolSeamAllowance::AttrSAAfter, "-1");
-            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(GetParametrUInt(element, AttrAngle, "0"));
-
-            const QString t = GetParametrString(element, AttrType, VAbstractPattern::NodePoint);
-            Tool tool;
-
-            switch (types.indexOf(t))
-            {
-                case 0: // VToolSeamAllowance::NodePoint
-                    tool = Tool::NodePoint;
-                    break;
-                case 1: // VToolSeamAllowance::NodeArc
-                    tool = Tool::NodeArc;
-                    break;
-                case 2: // VToolSeamAllowance::NodeSpline
-                    tool = Tool::NodeSpline;
-                    break;
-                case 3: // VToolSeamAllowance::NodeSplinePath
-                    tool = Tool::NodeSplinePath;
-                    break;
-                default:
-                    VException e(tr("Wrong tag name '%1'.").arg(t));
-                    throw e;
-            }
-            VPieceNode node(id, tool, reverse);
-            node.SetSABefore(saBefore);
-            node.SetSAAfter(saAfter);
-            node.SetAngleType(angle);
-            detail.GetPath().Append(node);
+            detail.GetPath().Append(ParseSANode(element));
         }
     }
 }
@@ -3078,42 +3085,13 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
 //---------------------------------------------------------------------------------------------------------------------
 void VPattern::ParsePathNodes(const QDomElement &domElement, VPiecePath &path) const
 {
-    const QStringList types = QStringList() << VAbstractPattern::NodePoint
-                                            << VAbstractPattern::NodeArc
-                                            << VAbstractPattern::NodeSpline
-                                            << VAbstractPattern::NodeSplinePath;
-
     const QDomNodeList nodeList = domElement.childNodes();
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
         if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
         {
-            const quint32 id = GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-            const bool reverse = GetParametrUInt(element, VAbstractPattern::AttrNodeReverse, "0");
-
-            const QString t = GetParametrString(element, AttrType, VAbstractPattern::NodePoint);
-            Tool tool;
-
-            switch (types.indexOf(t))
-            {
-                case 0: // VAbstractPattern::NodePoint
-                    tool = Tool::NodePoint;
-                    break;
-                case 1: // VAbstractPattern::NodeArc
-                    tool = Tool::NodeArc;
-                    break;
-                case 2: // VAbstractPattern::NodeSpline
-                    tool = Tool::NodeSpline;
-                    break;
-                case 3: // VAbstractPattern::NodeSplinePath
-                    tool = Tool::NodeSplinePath;
-                    break;
-                default:
-                    VException e(tr("Wrong tag name '%1'.").arg(t));
-                    throw e;
-            }
-            path.Append(VPieceNode(id, tool, reverse));
+            path.Append(ParseSANode(element));
         }
     }
 }
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 0ab54d4f0..9911da676 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -114,6 +114,8 @@ private:
     VMainGraphicsScene *sceneDraw;
     VMainGraphicsScene *sceneDetail;
 
+    VPieceNode     ParseSANode(const QDomElement &domElement) const;
+
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 6fa03906b..225ce799c 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -315,6 +315,9 @@
 																										 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
 																										 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
 																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
+																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
+																										 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
 																								   </xs:complexType>
 																							 </xs:element>
 																						 </xs:sequence>
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index 3dd8510ad..e2a7b692e 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -105,6 +105,8 @@ const QString VAbstractPattern::AttrCutNumber       = QStringLiteral("cutNumber"
 const QString VAbstractPattern::AttrPlacement       = QStringLiteral("placement");
 const QString VAbstractPattern::AttrArrows          = QStringLiteral("arrows");
 const QString VAbstractPattern::AttrNodeReverse     = QStringLiteral("reverse");
+const QString VAbstractPattern::AttrSABefore        = QStringLiteral("before");
+const QString VAbstractPattern::AttrSAAfter         = QStringLiteral("after");
 
 const QString VAbstractPattern::AttrAll             = QStringLiteral("all");
 
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index d951656a5..8ff0a8c61 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -209,6 +209,8 @@ public:
     static const QString AttrPlacement;
     static const QString AttrArrows;
     static const QString AttrNodeReverse;
+    static const QString AttrSABefore;
+    static const QString AttrSAAfter;
 
     static const QString AttrAll;
 
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index 492c6d17d..c1bbfa9b5 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -105,36 +105,7 @@ QString VToolPiecePath::getTagName() const
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
 {
-    QDomElement nod = doc->createElement(VAbstractPattern::TagNode);
-
-    doc->SetAttribute(nod, AttrIdObject, node.GetId());
-
-    const Tool type = node.GetTypeTool();
-    if (type != Tool::NodePoint)
-    {
-        doc->SetAttribute(nod, VAbstractPattern::AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
-    }
-
-    switch (type)
-    {
-        case (Tool::NodeArc):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeArc);
-            break;
-        case (Tool::NodePoint):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodePoint);
-            break;
-        case (Tool::NodeSpline):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSpline);
-            break;
-        case (Tool::NodeSplinePath):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSplinePath);
-            break;
-        default:
-            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-            break;
-    }
-
-    domElement.appendChild(nod);
+    domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index 98c06914a..556e0a77d 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -65,6 +65,7 @@
 #include "../vmisc/vcommonsettings.h"
 #include "../vmisc/logging.h"
 #include "../vpatterndb/vcontainer.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "../vwidgets/vgraphicssimpletextitem.h"
 #include "vdatatool.h"
 
@@ -431,3 +432,59 @@ void VAbstractTool::RefreshLine(QGraphicsEllipseItem *point, VGraphicsSimpleText
         lineName->setVisible(false);
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VAbstractTool::AddSANode(VAbstractPattern *doc, const QString &tagName, const VPieceNode &node)
+{
+    QDomElement nod = doc->createElement(tagName);
+
+    doc->SetAttribute(nod, AttrIdObject, node.GetId());
+
+    const Tool type = node.GetTypeTool();
+    if (type != Tool::NodePoint)
+    {
+        doc->SetAttribute(nod, VAbstractPattern::AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
+    }
+    else
+    {
+        const qreal w1 = node.GetSABefore();
+        if (w1 >= 0)
+        {
+            doc->SetAttribute(nod, VAbstractPattern::AttrSABefore, w1);
+        }
+
+        const qreal w2 = node.GetSAAfter();
+        if (w2 >= 0)
+        {
+            doc->SetAttribute(nod, VAbstractPattern::AttrSAAfter, w2);
+        }
+    }
+
+    switch (type)
+    {
+        case (Tool::NodeArc):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeArc);
+            break;
+        case (Tool::NodePoint):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodePoint);
+            break;
+        case (Tool::NodeSpline):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSpline);
+            break;
+        case (Tool::NodeSplinePath):
+            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSplinePath);
+            break;
+        default:
+            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+            break;
+    }
+
+    const unsigned char angleType = static_cast<unsigned char>(node.GetAngleType());
+
+    if (angleType > 0)
+    {
+        doc->SetAttribute(nod, AttrAngle, angleType);
+    }
+
+    return nod;
+}
diff --git a/src/libs/vtools/tools/vabstracttool.h b/src/libs/vtools/tools/vabstracttool.h
index b445c9ff9..3bc0187b7 100644
--- a/src/libs/vtools/tools/vabstracttool.h
+++ b/src/libs/vtools/tools/vabstracttool.h
@@ -146,8 +146,10 @@ protected:
     virtual void SetVisualization()=0;
     void ToolCreation(const Source &typeCreation);
 
-    static void RefreshLine(QGraphicsEllipseItem *point, VGraphicsSimpleTextItem *namePoint, QGraphicsLineItem *lineName,
-                            const qreal radius);
+    static void RefreshLine(QGraphicsEllipseItem *point, VGraphicsSimpleTextItem *namePoint,
+                            QGraphicsLineItem *lineName, const qreal radius);
+
+    static QDomElement AddSANode(VAbstractPattern *doc, const QString &tagName, const VPieceNode &node);
 private:
     Q_DISABLE_COPY(VAbstractTool)
 };
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index a8cc7b7b2..2ed36f232 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -64,8 +64,6 @@ const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version")
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
-const QString VToolSeamAllowance::AttrSABefore       = QStringLiteral("before");
-const QString VToolSeamAllowance::AttrSAAfter        = QStringLiteral("after");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 const QString VToolSeamAllowance::AttrStart          = QStringLiteral("start");
 const QString VToolSeamAllowance::AttrPath           = QStringLiteral("path");
@@ -201,51 +199,7 @@ void VToolSeamAllowance::Remove(bool ask)
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
 {
-    QDomElement nod = doc->createElement(VAbstractPattern::TagNode);
-
-    doc->SetAttribute(nod, AttrIdObject, node.GetId());
-
-    const Tool type = node.GetTypeTool();
-    if (type != Tool::NodePoint)
-    {
-        doc->SetAttribute(nod, VAbstractPattern::AttrNodeReverse, static_cast<quint8>(node.GetReverse()));
-    }
-    else
-    {
-        const qreal w1 = node.GetSABefore();
-        w1 < 0 ? domElement.removeAttribute(AttrSABefore) : doc->SetAttribute(nod, AttrSABefore, w1);
-
-        const qreal w2 = node.GetSAAfter();
-        w2 < 0 ? domElement.removeAttribute(AttrSAAfter) : doc->SetAttribute(nod, AttrSAAfter, w2);
-    }
-
-    switch (type)
-    {
-        case (Tool::NodeArc):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeArc);
-            break;
-        case (Tool::NodePoint):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodePoint);
-            break;
-        case (Tool::NodeSpline):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSpline);
-            break;
-        case (Tool::NodeSplinePath):
-            doc->SetAttribute(nod, AttrType, VAbstractPattern::NodeSplinePath);
-            break;
-        default:
-            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-            break;
-    }
-
-    const unsigned char angleType = static_cast<unsigned char>(node.GetAngleType());
-
-    if (angleType > 0)
-    {
-        doc->SetAttribute(nod, AttrAngle, angleType);
-    }
-
-    domElement.appendChild(nod);
+    domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 829541eae..17d55b26e 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -61,8 +61,6 @@ public:
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
     static const QString AttrWidth;
-    static const QString AttrSABefore;
-    static const QString AttrSAAfter;
     static const QString AttrUnited;
     static const QString AttrStart;
     static const QString AttrPath;

From 24e5aa1039c5fe0dbe2ccef26dc0061f17701ff6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 13:57:28 +0200
Subject: [PATCH 105/208] Fix crash.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index f83a98238..592b7c530 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -95,6 +95,7 @@ public:
           variables(data.variables),
           details(data.details),
           pieces(data.pieces),
+          piecePaths(data.piecePaths),
           trVars(data.trVars),
           patternUnit(data.patternUnit)
     {}

From 51df681fbc5266191115dcd5b49c3cdd061e0c3e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 13:58:17 +0200
Subject: [PATCH 106/208] Handle path seam allowance settings in separate tab.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 279 +++++++++++++++-
 .../vtools/dialogs/tools/dialogpiecepath.h    |  15 +
 .../vtools/dialogs/tools/dialogpiecepath.ui   | 315 ++++++++++++++----
 .../dialogs/tools/dialogseamallowance.cpp     |  22 +-
 .../dialogs/tools/dialogseamallowance.h       |   1 -
 .../dialogs/tools/dialogseamallowance.ui      |   2 +-
 src/libs/vtools/dialogs/tools/dialogtool.cpp  |  14 +
 src/libs/vtools/dialogs/tools/dialogtool.h    |   2 +
 8 files changed, 564 insertions(+), 86 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 885700f4c..7049a309d 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -37,7 +37,8 @@
 DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
     ui(new Ui::DialogPiecePath),
-    m_showMode(false)
+    m_showMode(false),
+    m_saWidth(0)
 {
     ui->setupUi(this);
     InitOkCancel(ui);
@@ -56,6 +57,37 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     flagError = PathIsValid();
     CheckState();
 
+    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    ui->doubleSpinBoxSeams->setSuffix(suffix);
+    ui->doubleSpinBoxSABefore->setSuffix(suffix);
+    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
+
+    if(qApp->patternUnit() == Unit::Inch)
+    {
+        ui->doubleSpinBoxSeams->setDecimals(5);
+        ui->doubleSpinBoxSABefore->setDecimals(5);
+        ui->doubleSpinBoxSAAfter->setDecimals(5);
+    }
+
+    InitNodesList();
+    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogPiecePath::NodeChanged);
+
+    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefBefore);
+    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefAfter);
+
+    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
+
+    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogPiecePath::ChangedSABefore);
+    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogPiecePath::ChangedSAAfter);
+
+    InitNodeAngles(ui->comboBoxAngle);
+    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogPiecePath::NodeAngleChanged);
+
     if (not m_showMode)
     {
         vis = new VisToolPiecePath(data);
@@ -65,6 +97,8 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
         ui->comboBoxType->setDisabled(true);
         ui->comboBoxPiece->setDisabled(true);
     }
+
+    ui->tabWidget->removeTab(1);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -221,6 +255,8 @@ void DialogPiecePath::ListChanged()
         visPath->SetPath(CreatePath());
         visPath->RefreshGeometry();
     }
+
+    InitNodesList();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -239,6 +275,101 @@ void DialogPiecePath::NameChanged()
     CheckState();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::NodeChanged(int index)
+{
+    ui->doubleSpinBoxSABefore->setDisabled(true);
+    ui->doubleSpinBoxSAAfter->setDisabled(true);
+    ui->pushButtonDefBefore->setDisabled(true);
+    ui->pushButtonDefAfter->setDisabled(true);
+    ui->comboBoxAngle->setDisabled(true);
+
+    ui->doubleSpinBoxSABefore->blockSignals(true);
+    ui->doubleSpinBoxSAAfter->blockSignals(true);
+    ui->comboBoxAngle->blockSignals(true);
+
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+        const VPiecePath path = CreatePath();
+        const int nodeIndex = path.indexOfNode(id);
+        if (nodeIndex != -1)
+        {
+            const VPieceNode &node = path.at(nodeIndex);
+
+            ui->doubleSpinBoxSABefore->setEnabled(true);
+            ui->doubleSpinBoxSAAfter->setEnabled(true);
+            ui->comboBoxAngle->setEnabled(true);
+
+            qreal w1 = node.GetSABefore();
+            if (w1 < 0)
+            {
+                w1 = m_saWidth;
+            }
+            else
+            {
+                ui->pushButtonDefBefore->setEnabled(true);
+            }
+            ui->doubleSpinBoxSABefore->setValue(w1);
+
+            qreal w2 = node.GetSAAfter();
+            if (w2 < 0)
+            {
+                w2 = m_saWidth;
+            }
+            else
+            {
+                ui->pushButtonDefAfter->setEnabled(true);
+            }
+            ui->doubleSpinBoxSAAfter->setValue(w2);
+
+            const int index = ui->comboBoxAngle->findData(static_cast<unsigned char>(node.GetAngleType()));
+            if (index != -1)
+            {
+                ui->comboBoxAngle->setCurrentIndex(index);
+            }
+        }
+    }
+    else
+    {
+        ui->doubleSpinBoxSABefore->setValue(0);
+        ui->doubleSpinBoxSAAfter->setValue(0);
+        ui->comboBoxAngle->setCurrentIndex(-1);
+    }
+
+    ui->doubleSpinBoxSABefore->blockSignals(false);
+    ui->doubleSpinBoxSAAfter->blockSignals(false);
+    ui->comboBoxAngle->blockSignals(false);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ReturnDefBefore()
+{
+    SetCurrentSABefore(-1);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ReturnDefAfter()
+{
+    SetCurrentSAAfter(-1);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ChangedSABefore(double d)
+{
+    SetCurrentSABefore(d);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ChangedSAAfter(double d)
+{
+    SetCurrentSAAfter(d);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::InitPathTypes()
 {
@@ -246,6 +377,74 @@ void DialogPiecePath::InitPathTypes()
     //ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::InitNodesList()
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const quint32 id = ui->comboBoxNodes->itemData(ui->comboBoxNodes->currentIndex()).toUInt();
+#else
+    const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+#endif
+
+    ui->comboBoxNodes->blockSignals(true);
+    ui->comboBoxNodes->clear();
+
+    const VPiecePath path = CreatePath();
+
+    for (int i = 0; i < path.CountNodes(); ++i)
+    {
+        const VPieceNode node = path.at(i);
+        if (node.GetTypeTool() == Tool::NodePoint)
+        {
+            const QString name = GetNodeName(node);
+
+            ui->comboBoxNodes->addItem(name, node.GetId());
+        }
+    }
+    ui->comboBoxNodes->blockSignals(false);
+
+    const int index = ui->comboBoxNodes->findData(id);
+    if (index != -1)
+    {
+        ui->comboBoxNodes->setCurrentIndex(index);
+        NodeChanged(index);// Need in case combox index was not changed
+    }
+    else
+    {
+        ui->comboBoxNodes->count() > 0 ? NodeChanged(0) : NodeChanged(-1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::NodeAngleChanged(int index)
+{
+    const int i = ui->comboBoxNodes->currentIndex();
+    if (i != -1 && index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(i).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+        #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(ui->comboBoxAngle->itemData(index).toUInt());
+        #else
+            const PieceNodeAngle angle = static_cast<PieceNodeAngle>(ui->comboBoxAngle->currentData().toUInt());
+        #endif
+
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetAngleType(angle);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath DialogPiecePath::GetPiecePath() const
 {
@@ -292,6 +491,70 @@ void DialogPiecePath::SetType(PiecePathType type)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QListWidgetItem *DialogPiecePath::GetItemById(quint32 id)
+{
+    for (qint32 i = 0; i < ui->listWidget->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidget->item(i);
+        const VPieceNode node = qvariant_cast<VPieceNode>(item->data(Qt::UserRole));
+
+        if (node.GetId() == id)
+        {
+            return item;
+        }
+    }
+    return nullptr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetCurrentSABefore(qreal value)
+{
+    const int index = ui->comboBoxNodes->currentIndex();
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetSABefore(value);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetCurrentSAAfter(qreal value)
+{
+    const int index = ui->comboBoxNodes->currentIndex();
+    if (index != -1)
+    {
+    #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+        const quint32 id = ui->comboBoxNodes->itemData(index).toUInt();
+    #else
+        const quint32 id = ui->comboBoxNodes->currentData().toUInt();
+    #endif
+
+        QListWidgetItem *rowItem = GetItemById(id);
+        if (rowItem)
+        {
+            VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
+            rowNode.SetSAAfter(value);
+            rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
+
+            ListChanged();
+        }
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 DialogPiecePath::GetPieceId() const
 {
@@ -327,6 +590,20 @@ void DialogPiecePath::SetPieceId(quint32 id)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetSAWidth(qreal width)
+{
+    if (width >=0)
+    {
+        m_saWidth = width;
+        ui->tabWidget->addTab(ui->tabSeamAllowance, QString());
+    }
+    else
+    {
+        ui->tabWidget->removeTab(1);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::SetPiecesList(const QVector<quint32> &list)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 4e1f79d00..6149853f9 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -51,6 +51,8 @@ public:
     quint32 GetPieceId() const;
     void    SetPieceId(quint32 id);
 
+    void SetSAWidth(qreal width);
+
     virtual void SetPiecesList(const QVector<quint32> &list) Q_DECL_OVERRIDE;
 
 public slots:
@@ -66,14 +68,22 @@ private slots:
     void ShowContextMenu(const QPoint &pos);
     void ListChanged();
     void NameChanged();
+    void NodeChanged(int index);
+    void ReturnDefBefore();
+    void ReturnDefAfter();
+    void ChangedSABefore(double d);
+    void ChangedSAAfter(double d);
 
 private:
     Q_DISABLE_COPY(DialogPiecePath)
     Ui::DialogPiecePath *ui;
     bool m_showMode;
+    qreal m_saWidth;
 
     void InitPathTypes();
     void InitListPieces();
+    void InitNodesList();
+    void NodeAngleChanged(int index);
 
     VPiecePath CreatePath() const;
 
@@ -83,6 +93,11 @@ private:
 
     PiecePathType GetType() const;
     void          SetType(PiecePathType type);
+
+    QListWidgetItem *GetItemById(quint32 id);
+
+    void SetCurrentSABefore(qreal value);
+    void SetCurrentSAAfter(qreal value);
 };
 
 #endif // DIALOGPIECEPATH_H
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
index 6ae015961..1041d3cc4 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
@@ -6,76 +6,265 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>365</width>
-    <height>337</height>
+    <width>480</width>
+    <height>409</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Dialog</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
+  <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
-    <layout class="QFormLayout" name="formLayout">
-     <property name="fieldGrowthPolicy">
-      <enum>QFormLayout::ExpandingFieldsGrow</enum>
-     </property>
-     <item row="0" column="0">
-      <widget class="QLabel" name="labelName">
-       <property name="text">
-        <string>Name:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="1">
-      <widget class="QLineEdit" name="lineEditName">
-       <property name="text">
-        <string>Unnamed path</string>
-       </property>
-       <property name="placeholderText">
-        <string>Create name for your path</string>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="0">
-      <widget class="QLabel" name="labelType">
-       <property name="text">
-        <string>Type:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="1">
-      <widget class="QComboBox" name="comboBoxType"/>
-     </item>
-     <item row="2" column="0">
-      <widget class="QLabel" name="labelPiece">
-       <property name="text">
-        <string>Piece:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="2" column="1">
-      <widget class="QComboBox" name="comboBoxPiece"/>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <widget class="QListWidget" name="listWidget">
-     <property name="dragDropMode">
-      <enum>QAbstractItemView::InternalMove</enum>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QLabel" name="helpLabel">
-     <property name="text">
-      <string>Ready!</string>
-     </property>
-     <property name="textFormat">
-      <enum>Qt::RichText</enum>
-     </property>
-     <property name="scaledContents">
-      <bool>false</bool>
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>1</number>
      </property>
+     <widget class="QWidget" name="tabPath">
+      <attribute name="title">
+       <string>Path</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <layout class="QFormLayout" name="formLayout">
+         <property name="fieldGrowthPolicy">
+          <enum>QFormLayout::ExpandingFieldsGrow</enum>
+         </property>
+         <item row="0" column="0">
+          <widget class="QLabel" name="labelName">
+           <property name="text">
+            <string>Name:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QLineEdit" name="lineEditName">
+           <property name="text">
+            <string>Unnamed path</string>
+           </property>
+           <property name="placeholderText">
+            <string>Create name for your path</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLabel" name="labelType">
+           <property name="text">
+            <string>Type:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QComboBox" name="comboBoxType"/>
+         </item>
+         <item row="2" column="0">
+          <widget class="QLabel" name="labelPiece">
+           <property name="text">
+            <string>Piece:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QComboBox" name="comboBoxPiece"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QListWidget" name="listWidget">
+         <property name="dragDropMode">
+          <enum>QAbstractItemView::InternalMove</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="helpLabel">
+         <property name="text">
+          <string>Ready!</string>
+         </property>
+         <property name="textFormat">
+          <enum>Qt::RichText</enum>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tabSeamAllowance">
+      <attribute name="title">
+       <string>Seam allowance</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="labelEditWidth">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="locale">
+            <locale language="English" country="UnitedStates"/>
+           </property>
+           <property name="text">
+            <string>Width:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QDoubleSpinBox" name="doubleSpinBoxSeams">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="readOnly">
+            <bool>true</bool>
+           </property>
+           <property name="maximum">
+            <double>900.990000000000009</double>
+           </property>
+           <property name="singleStep">
+            <double>0.100000000000000</double>
+           </property>
+           <property name="value">
+            <double>0.000000000000000</double>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>Nodes</string>
+         </property>
+         <layout class="QFormLayout" name="formLayout_2">
+          <property name="fieldGrowthPolicy">
+           <enum>QFormLayout::ExpandingFieldsGrow</enum>
+          </property>
+          <item row="0" column="0">
+           <widget class="QLabel" name="labelNode">
+            <property name="text">
+             <string>Node:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="comboBoxNodes"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="labelSABefore">
+            <property name="toolTip">
+             <string>Seam allowance before node</string>
+            </property>
+            <property name="text">
+             <string>Before:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QDoubleSpinBox" name="doubleSpinBoxSABefore">
+              <property name="maximum">
+               <double>900.990000000000009</double>
+              </property>
+              <property name="singleStep">
+               <double>0.100000000000000</double>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonDefBefore">
+              <property name="toolTip">
+               <string>Return to default width</string>
+              </property>
+              <property name="text">
+               <string>Default</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="labelSAAfter">
+            <property name="toolTip">
+             <string>Seam allowance after node</string>
+            </property>
+            <property name="text">
+             <string>After:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <item>
+             <widget class="QDoubleSpinBox" name="doubleSpinBoxSAAfter">
+              <property name="maximum">
+               <double>900.990000000000009</double>
+              </property>
+              <property name="singleStep">
+               <double>0.100000000000000</double>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonDefAfter">
+              <property name="toolTip">
+               <string>Return to default width</string>
+              </property>
+              <property name="text">
+               <string>Default</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item row="3" column="0">
+           <widget class="QLabel" name="labelAngle">
+            <property name="text">
+             <string>Angle:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1">
+           <widget class="QComboBox" name="comboBoxAngle"/>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 0b08a1595..5b07f2e24 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -91,7 +91,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     connect(ui->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
     connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
 
-    InitNodeAngles();
+    InitNodeAngles(ui->comboBoxAngle);
     connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::NodeAngleChanged);
 
@@ -109,7 +109,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
         vis = new VisToolPiece(data);
     }
 
-    ui->tabWidget->setCurrentIndex(1);// Show always first tab active on start.
+    ui->tabWidget->setCurrentIndex(0);// Show always first tab active on start.
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -770,24 +770,6 @@ void DialogSeamAllowance::InitNodesList()
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::InitNodeAngles()
-{
-    ui->comboBoxAngle->clear();
-
-    ui->comboBoxAngle->addItem(tr("by length"), static_cast<unsigned char>(PieceNodeAngle::ByLength));
-    ui->comboBoxAngle->addItem(tr("by points intersetions"),
-                               static_cast<unsigned char>(PieceNodeAngle::ByPointsIntersection));
-    ui->comboBoxAngle->addItem(tr("by first edge symmetry"),
-                               static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeSymmetry));
-    ui->comboBoxAngle->addItem(tr("by second edge symmetry"),
-                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeSymmetry));
-    ui->comboBoxAngle->addItem(tr("by first edge right angle"),
-                               static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeRightAngle));
-    ui->comboBoxAngle->addItem(tr("by second edge right angle"),
-                               static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeRightAngle));
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 QListWidgetItem *DialogSeamAllowance::GetItemById(quint32 id)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index f90fa75df..4675c0939 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -94,7 +94,6 @@ private:
     void    ValidObjects(bool value);
     bool    MainPathIsClockwise() const;
     void    InitNodesList();
-    void    InitNodeAngles();
     void    InitCSAPoint(QComboBox *box);
 
     QListWidgetItem *GetItemById(quint32 id);
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index e27204d0f..27f285d92 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>1</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp
index a26626ce4..611218f6b 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp
@@ -502,6 +502,20 @@ void DialogTool::NewNodeItem(QListWidget *listWidget, const VPieceNode &node)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogTool::InitNodeAngles(QComboBox *box)
+{
+    SCASSERT(box != nullptr);
+    box->clear();
+
+    box->addItem(tr("by length"), static_cast<unsigned char>(PieceNodeAngle::ByLength));
+    box->addItem(tr("by points intersetions"), static_cast<unsigned char>(PieceNodeAngle::ByPointsIntersection));
+    box->addItem(tr("by first edge symmetry"), static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeSymmetry));
+    box->addItem(tr("by second edge symmetry"), static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeSymmetry));
+    box->addItem(tr("by first edge right angle"), static_cast<unsigned char>(PieceNodeAngle::ByFirstEdgeRightAngle));
+    box->addItem(tr("by second edge right angle"), static_cast<unsigned char>(PieceNodeAngle::BySecondEdgeRightAngle));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool DialogTool::IsSplinePath(const QSharedPointer<VGObject> &obj) const
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h
index 46ed7d9fa..5de089cf6 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.h
+++ b/src/libs/vtools/dialogs/tools/dialogtool.h
@@ -283,6 +283,8 @@ protected:
 
     QString          GetNodeName(const VPieceNode &node) const;
     void             NewNodeItem(QListWidget *listWidget, const VPieceNode &node);
+
+    void             InitNodeAngles(QComboBox *box);
 private:
     void FillList(QComboBox *box, const QMap<QString, quint32> &list)const;
 

From 5156e0cf255c4f90cbca32710c3b35379213115d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 28 Nov 2016 14:52:31 +0200
Subject: [PATCH 107/208] Read/write piece path include type.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |  3 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |  9 ++-
 src/libs/vmisc/def.h                          | 10 ++-
 .../dialogs/tools/dialogseamallowance.cpp     | 63 ++++++++++++++++---
 .../dialogs/tools/dialogseamallowance.h       |  2 +
 .../dialogs/tools/dialogseamallowance.ui      | 12 +++-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  2 +
 src/libs/vtools/tools/vtoolseamallowance.h    |  1 +
 8 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index a5f58cf22..338021003 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -846,6 +846,9 @@ void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &deta
             record.path = GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
             record.endPoint = GetParametrUInt(element, VToolSeamAllowance::AttrEnd, NULL_ID_STR);
             record.reverse = GetParametrBool(element, VAbstractPattern::AttrNodeReverse, falseStr);
+            record.includeType = static_cast<PiecePathIncludeType>(GetParametrUInt(element,
+                                                                                   VToolSeamAllowance::AttrIncludeAs,
+                                                                                   "1"));
             records.append(record);
         }
     }
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 225ce799c..29e40d580 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -414,7 +414,7 @@
                                                                                        <xs:attribute name="my" type="xs:double"></xs:attribute>
                                                                                        <xs:attribute name="length" type="xs:string"></xs:attribute>
                                                                                        <xs:attribute name="rotation" type="xs:string"></xs:attribute>
-										       <xs:attribute name="arrows" type="arrowType"></xs:attribute>
+                                                                                       <xs:attribute name="arrows" type="arrowType"></xs:attribute>
                                                                                     </xs:complexType>
                                                                                </xs:element>
                                                                                <xs:element name="nodes" minOccurs="1" maxOccurs="1">
@@ -442,6 +442,7 @@
 																										 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
 																										 <xs:attribute name="end" type="xs:unsignedInt"></xs:attribute>
 																										 <xs:attribute name="reverse" type="xs:boolean"></xs:attribute>
+																										 <xs:attribute name="includeAs" type="piecePathIncludeType"></xs:attribute>
 																								   </xs:complexType>
 																							 </xs:element>
 																						 </xs:sequence>
@@ -693,4 +694,10 @@
        <xs:enumeration value="2"/><!--internal path-->
      </xs:restriction>
    </xs:simpleType>
+   <xs:simpleType name="piecePathIncludeType">
+     <xs:restriction base="xs:unsignedInt">
+       <xs:enumeration value="0"/><!--as main path-->
+       <xs:enumeration value="1"/><!--as custom seam allowance-->
+     </xs:restriction>
+   </xs:simpleType>
    </xs:schema>
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index c90dd6c78..63d489d2f 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -74,6 +74,12 @@ enum class PieceNodeAngle : unsigned char
     BySecondEdgeRightAngle
 };
 
+enum class PiecePathIncludeType : unsigned char
+{
+    AsMainPath = 0,
+    AsCustomSA
+};
+
 enum class PiecePathType :  unsigned char {PiecePath = 0, CustomSeamAllowance = 1, InternalPath = 2, Unknown = 3};
 
 typedef unsigned char ToolVisHolderType;
@@ -686,13 +692,15 @@ struct CustomSARecord
         : startPoint(0),
           path(0),
           endPoint(0),
-          reverse(false)
+          reverse(false),
+          includeType(PiecePathIncludeType::AsCustomSA)
     {}
 
     quint32 startPoint;
     quint32 path;
     quint32 endPoint;
     bool reverse;
+    PiecePathIncludeType includeType;
 };
 
 Q_DECLARE_METATYPE(CustomSARecord)
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 5b07f2e24..a6d79f25d 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -103,6 +103,8 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
             &DialogSeamAllowance::CSAStartPointChanged);
     connect(ui->comboBoxEndPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::CSAEndPointChanged);
+    connect(ui->comboBoxIncludeType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAIncludeTypeChanged);
 
     if (not applyAllowed)
     {
@@ -352,6 +354,10 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
         auto *dialog = new DialogPiecePath(data, record.path, this);
         dialog->SetPiecePath(data->GetPiecePath(record.path));
         dialog->SetPieceId(toolId);
+        if (record.includeType == PiecePathIncludeType::AsMainPath)
+        {
+            dialog->SetSAWidth(ui->doubleSpinBoxSeams->value());
+        }
         dialog->EnbleShowMode(true);
         m_dialog = dialog;
         m_dialog->setModal(true);
@@ -502,6 +508,29 @@ void DialogSeamAllowance::CSAEndPointChanged(int index)
     rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::CSAIncludeTypeChanged(int index)
+{
+    const int row = ui->listWidgetCustomSA->currentRow();
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
+    {
+        return;
+    }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    const PiecePathIncludeType type = static_cast<PiecePathIncludeType>(ui->comboBoxEndPoint->itemData(index).toUInt());
+#else
+    Q_UNUSED(index);
+    const PiecePathIncludeType type = static_cast<PiecePathIncludeType>(ui->comboBoxEndPoint->currentData().toUInt());
+#endif
+
+    QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
+    SCASSERT(rowItem != nullptr);
+    CustomSARecord record = qvariant_cast<CustomSARecord>(rowItem->data(Qt::UserRole));
+    record.includeType = type;
+    rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::NodeAngleChanged(int index)
 {
@@ -564,16 +593,12 @@ void DialogSeamAllowance::CustomSAChanged(int row)
         return;
     }
 
-    ui->comboBoxStartPoint->blockSignals(true);
-    ui->comboBoxEndPoint->blockSignals(true);
-
-    InitCSAPoint(ui->comboBoxStartPoint);
-    InitCSAPoint(ui->comboBoxEndPoint);
-
     const QListWidgetItem *item = ui->listWidgetCustomSA->item( row );
     SCASSERT(item != nullptr);
     const CustomSARecord record = qvariant_cast<CustomSARecord>(item->data(Qt::UserRole));
 
+    ui->comboBoxStartPoint->blockSignals(true);
+    InitCSAPoint(ui->comboBoxStartPoint);
     {
         const int index = ui->comboBoxStartPoint->findData(record.startPoint);
         if (index != -1)
@@ -581,7 +606,10 @@ void DialogSeamAllowance::CustomSAChanged(int row)
             ui->comboBoxStartPoint->setCurrentIndex(index);
         }
     }
+    ui->comboBoxStartPoint->blockSignals(false);
 
+    ui->comboBoxEndPoint->blockSignals(true);
+    InitCSAPoint(ui->comboBoxEndPoint);
     {
         const int index = ui->comboBoxEndPoint->findData(record.endPoint);
         if (index != -1)
@@ -589,9 +617,18 @@ void DialogSeamAllowance::CustomSAChanged(int row)
             ui->comboBoxEndPoint->setCurrentIndex(index);
         }
     }
-
-    ui->comboBoxStartPoint->blockSignals(false);
     ui->comboBoxEndPoint->blockSignals(false);
+
+    ui->comboBoxIncludeType->blockSignals(true);
+    InitSAIncludeType();
+    {
+        const int index = ui->comboBoxIncludeType->findData(static_cast<unsigned char>(record.includeType));
+        if (index != -1)
+        {
+            ui->comboBoxIncludeType->setCurrentIndex(index);
+        }
+    }
+    ui->comboBoxIncludeType->blockSignals(false);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -853,3 +890,13 @@ void DialogSeamAllowance::InitCSAPoint(QComboBox *box)
         }
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitSAIncludeType()
+{
+    ui->comboBoxIncludeType->clear();
+
+    ui->comboBoxIncludeType->addItem(tr("main path"), static_cast<unsigned char>(PiecePathIncludeType::AsMainPath));
+    ui->comboBoxIncludeType->addItem(tr("custom seam allowance"),
+                                     static_cast<unsigned char>(PiecePathIncludeType::AsCustomSA));
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 4675c0939..cd53f8da2 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -67,6 +67,7 @@ private slots:
     void NodeChanged(int index);
     void CSAStartPointChanged(int index);
     void CSAEndPointChanged(int index);
+    void CSAIncludeTypeChanged(int index);
     void NodeAngleChanged(int index);
     void ReturnDefBefore();
     void ReturnDefAfter();
@@ -95,6 +96,7 @@ private:
     bool    MainPathIsClockwise() const;
     void    InitNodesList();
     void    InitCSAPoint(QComboBox *box);
+    void    InitSAIncludeType();
 
     QListWidgetItem *GetItemById(quint32 id);
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 27f285d92..92caf7a2b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -326,6 +326,16 @@
               <item row="1" column="1">
                <widget class="QComboBox" name="comboBoxEndPoint"/>
               </item>
+              <item row="2" column="0">
+               <widget class="QLabel" name="labelIncludeType">
+                <property name="text">
+                 <string>Include as:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="1">
+               <widget class="QComboBox" name="comboBoxIncludeType"/>
+              </item>
              </layout>
             </widget>
             <widget class="QListWidget" name="listWidgetCustomSA"/>
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 2ed36f232..2f8bfa5d9 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -68,6 +68,7 @@ const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 const QString VToolSeamAllowance::AttrStart          = QStringLiteral("start");
 const QString VToolSeamAllowance::AttrPath           = QStringLiteral("path");
 const QString VToolSeamAllowance::AttrEnd            = QStringLiteral("end");
+const QString VToolSeamAllowance::AttrIncludeAs      = QStringLiteral("includeAs");
 
 //---------------------------------------------------------------------------------------------------------------------
 VToolSeamAllowance::~VToolSeamAllowance()
@@ -242,6 +243,7 @@ void VToolSeamAllowance::AddCSARecord(VAbstractPattern *doc, QDomElement &domEle
     doc->SetAttribute(recordNode, AttrPath, record.path);
     doc->SetAttribute(recordNode, AttrEnd, record.endPoint);
     doc->SetAttribute(recordNode, VAbstractPattern::AttrNodeReverse, record.reverse);
+    doc->SetAttribute(recordNode, AttrIncludeAs, static_cast<unsigned int>(record.includeType));
 
     domElement.appendChild(recordNode);
 }
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 17d55b26e..03a53157d 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -65,6 +65,7 @@ public:
     static const QString AttrStart;
     static const QString AttrPath;
     static const QString AttrEnd;
+    static const QString AttrIncludeAs;
 
     void Remove(bool ask);
 

From a3843beb0b00dc52487f3066c6ae3f9065b4e67e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:10:53 +0200
Subject: [PATCH 108/208] Insert custom seam allowance.

--HG--
branch : feature
---
 src/libs/vgeometry/vgobject.cpp    |  22 ----
 src/libs/vgeometry/vgobject.h      |  26 +++-
 src/libs/vpatterndb/vpiece.cpp     | 153 +++++++++++-------------
 src/libs/vpatterndb/vpiece.h       |   5 +-
 src/libs/vpatterndb/vpiecepath.cpp | 185 ++++++++++++++++++++++++++---
 src/libs/vpatterndb/vpiecepath.h   |  21 +++-
 6 files changed, 280 insertions(+), 132 deletions(-)

diff --git a/src/libs/vgeometry/vgobject.cpp b/src/libs/vgeometry/vgobject.cpp
index 713239bf7..9331bcd06 100644
--- a/src/libs/vgeometry/vgobject.cpp
+++ b/src/libs/vgeometry/vgobject.cpp
@@ -534,28 +534,6 @@ int VGObject::PointInCircle(const QPointF &p, const QPointF &center, qreal radiu
     return 2; // inside circle
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief GetReversePoint return revers container of points.
- * @param points container with points.
- * @return reverced points.
- */
-QVector<QPointF> VGObject::GetReversePoints(const QVector<QPointF> &points)
-{
-    if (points.isEmpty())
-    {
-        return points;
-    }
-    QVector<QPointF> reversePoints(points.size());
-    qint32 j = 0;
-    for (qint32 i = points.size() - 1; i >= 0; --i)
-    {
-        reversePoints.replace(j, points.at(i));
-        ++j;
-    }
-    return reversePoints;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief GetLengthContour return length of contour.
diff --git a/src/libs/vgeometry/vgobject.h b/src/libs/vgeometry/vgobject.h
index 328316fe9..360387f7e 100644
--- a/src/libs/vgeometry/vgobject.h
+++ b/src/libs/vgeometry/vgobject.h
@@ -90,7 +90,8 @@ public:
     static bool    IsPointOnLineSegment (const QPointF &t, const QPointF &p1, const QPointF &p2);
     static bool    IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2);
 
-    static QVector<QPointF> GetReversePoints(const QVector<QPointF> &points);
+    template <typename T>
+    static QVector<T> GetReversePoints(const QVector<T> &points);
     static int GetLengthContour(const QVector<QPointF> &contour, const QVector<QPointF> &newPoints);
 
     static double accuracyPointOnLine;
@@ -105,6 +106,29 @@ private:
     static int     PointInCircle (const QPointF &p, const QPointF &center, qreal radius);
 };
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief GetReversePoint return revers container of points.
+ * @param points container with points.
+ * @return reverced points.
+ */
+template <typename T>
+QVector<T> VGObject::GetReversePoints(const QVector<T> &points)
+{
+    if (points.isEmpty())
+    {
+        return points;
+    }
+    QVector<T> reversePoints(points.size());
+    qint32 j = 0;
+    for (qint32 i = points.size() - 1; i >= 0; --i)
+    {
+        reversePoints.replace(j, points.at(i));
+        ++j;
+    }
+    return reversePoints;
+}
+
 Q_DECLARE_TYPEINFO(VGObject, Q_MOVABLE_TYPE);
 
 #endif // VGOBJECT_H
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index bd42a1945..0b0f8b2d8 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -105,6 +105,11 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
         return QVector<QPointF>();
     }
 
+    const QVector<CustomSARecord> records = GetValidRecords();
+    int recordIndex = -1;
+    bool insertingCSA = false;
+    const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
+
     QVector<VSAPoint> pointsEkv;
     for (int i = 0; i< d->m_path.CountNodes(); ++i)
     {
@@ -113,21 +118,54 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
         {
             case (Tool::NodePoint):
             {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
-                VSAPoint p(point->toQPointF());
+                if (not insertingCSA)
+                {
+                    pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
 
-                p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                p.SetAngleType(node.GetAngleType());
-                pointsEkv.append(p);
+                    recordIndex = IsCSAStart(records, node.GetId());
+                    if (recordIndex != -1)
+                    {
+                        insertingCSA = true;
+
+                        const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path);
+                        QVector<VSAPoint> r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse);
+
+                        if (records.at(recordIndex).includeType == PiecePathIncludeType::AsCustomSA)
+                        {
+                            for (int j = 0; j < r.size(); ++j)
+                            {
+                                r[i].SetAngleType(PieceNodeAngle::ByLength);
+                                r[i].SetSABefore(0);
+                                r[i].SetSABefore(0);
+                            }
+                        }
+
+                        pointsEkv += r;
+                    }
+                }
+                else
+                {
+                    if (records.at(recordIndex).endPoint == node.GetId())
+                    {
+                        insertingCSA = false;
+                        recordIndex = -1;
+
+                        pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
+                    }
+                }
             }
             break;
             case (Tool::NodeArc):
             case (Tool::NodeSpline):
             case (Tool::NodeSplinePath):
             {
-                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
-                CurveSeamAllowanceSegment(pointsEkv, data, curve, i, node.GetReverse());
+                if (not insertingCSA)
+                {
+                    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
+
+                    pointsEkv += VPiecePath::CurveSeamAllowanceSegment(data, d->m_path.GetNodes(), curve, i,
+                                                                       node.GetReverse(), width);
+                }
             }
             break;
             default:
@@ -136,7 +174,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
         }
     }
 
-    return Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit()));
+    return Equidistant(pointsEkv, width);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -287,86 +325,31 @@ QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
-                                       const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
+QVector<CustomSARecord> VPiece::GetValidRecords() const
 {
-    const VSAPoint begin = d->m_path.StartSegment(data, i, reverse);
-    const VSAPoint end = d->m_path.EndSegment(data, i, reverse);
-
-    const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
-    if (points.isEmpty())
+    QVector<CustomSARecord> records;
+    for (int i = 0; i < d->m_customSARecords.size(); ++i)
     {
-        return;
-    }
+        const CustomSARecord &record = d->m_customSARecords.at(i);
 
-    qreal w1 = begin.GetSAAfter();
-    qreal w2 = end.GetSABefore();
-    if (w1 < 0 && w2 < 0)
-    {// no local widths
-        for(int i = 0; i < points.size(); ++i)
+        if (record.startPoint > NULL_ID && record.path > NULL_ID && record.endPoint > NULL_ID)
         {
-            VSAPoint p(points.at(i));
-            if (i == 0)
-            { // first point
-                p.SetSAAfter(begin.GetSAAfter());
-                p.SetSABefore(begin.GetSABefore());
-                p.SetAngleType(begin.GetAngleType());
-            }
-            else if (i == points.size() - 1)
-            { // last point
-                p.SetSAAfter(end.GetSAAfter());
-                p.SetSABefore(end.GetSABefore());
-                p.SetAngleType(end.GetAngleType());
-            }
-            pointsEkv.append(p);
-        }
-    }
-    else
-    {
-        const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
-
-        if (w1 < 0)
-        {
-            w1 = width;
-        }
-
-        if (w2 < 0)
-        {
-            w2 = width;
-        }
-
-        const qreal wDiff = w2 - w1;// Difference between to local widths
-        const qreal fullLength = VAbstractCurve::PathLength(points);
-
-        VSAPoint p(points.at(0));//First point in the list
-        p.SetSAAfter(begin.GetSAAfter());
-        p.SetSABefore(begin.GetSABefore());
-        p.SetAngleType(begin.GetAngleType());
-        pointsEkv.append(p);
-
-        qreal length = 0; // how much we handle
-
-        for(int i = 1; i < points.size(); ++i)
-        {
-            p = VSAPoint(points.at(i));
-
-            if (i == points.size() - 1)
-            {// last point
-                p.SetSAAfter(end.GetSAAfter());
-                p.SetSABefore(end.GetSABefore());
-                p.SetAngleType(end.GetAngleType());
-            }
-            else
-            {
-                length += QLineF(points.at(i-1), points.at(i)).length();
-                const qreal localWidth = w1 + wDiff*(length/fullLength);
-
-                p.SetSAAfter(localWidth);
-                p.SetSABefore(localWidth);
-                // curve points have angle type by default
-            }
-
-            pointsEkv.append(p);
+            records.append(record);
         }
     }
+    return records;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int VPiece::IsCSAStart(const QVector<CustomSARecord> &records, quint32 id)
+{
+    for (int i = 0; i < records.size(); ++i)
+    {
+        if (records.at(i).startPoint == id)
+        {
+            return i;
+        }
+    }
+
+    return -1;
 }
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 3eca969ed..099011102 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -84,8 +84,9 @@ public:
 private:
     QSharedDataPointer<VPieceData> d;
 
-    void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
-                                   const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
+    QVector<CustomSARecord> GetValidRecords() const;
+
+    static int IsCSAStart(const QVector<CustomSARecord> &records, quint32 id);
 };
 
 Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 87e1a9484..1f761267e 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -190,6 +190,44 @@ QVector<QPointF> VPiecePath::PathNodePoints(const VContainer *data) const
     return points;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> VPiecePath::SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const
+{
+    SCASSERT(data != nullptr);
+
+    QVector<VSAPoint> pointsEkv;
+    for (int i = 0; i< d->m_nodes.size(); ++i)
+    {
+        const VPieceNode &node = d->m_nodes.at(i);
+        switch (node.GetTypeTool())
+        {
+            case (Tool::NodePoint):
+            {
+                pointsEkv.append(PreparePointEkv(node, data));
+            }
+            break;
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
+                pointsEkv += CurveSeamAllowanceSegment(data, d->m_nodes, curve, i, node.GetReverse(), width);
+            }
+            break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
+                break;
+        }
+    }
+
+    if (reverse)
+    {
+        pointsEkv = VGObject::GetReversePoints(pointsEkv);
+    }
+
+    return pointsEkv;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPainterPath VPiecePath::PainterPath(const VContainer *data) const
 {
@@ -210,14 +248,14 @@ QPainterPath VPiecePath::PainterPath(const VContainer *data) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
+VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
 {
-    if (i < 0 && i > CountNodes()-1)
+    if (i < 0 && i > nodes.size()-1)
     {
         return VSAPoint();
     }
 
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
 
     QVector<QPointF> points = curve->GetPoints();
     if (reverse)
@@ -226,13 +264,13 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
     }
 
     VSAPoint begin = VSAPoint(points.first());
-    if (CountNodes() > 1)
+    if (nodes.size() > 1)
     {
         if (i == 0)
         {
-            if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
+            if (nodes.at(nodes.size()-1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode &node = at(CountNodes()-1);
+                const VPieceNode &node = nodes.at(nodes.size()-1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -245,9 +283,9 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
         }
         else
         {
-            if (at(i-1).GetTypeTool() == Tool::NodePoint)
+            if (nodes.at(i-1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode &node = at(i-1);
+                const VPieceNode &node = nodes.at(i-1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -263,14 +301,14 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const
+VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
 {
-    if (i < 0 && i > CountNodes()-1)
+    if (i < 0 && i > nodes.size()-1)
     {
         return VSAPoint();
     }
 
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
+    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
 
     QVector<QPointF> points = curve->GetPoints();
     if (reverse)
@@ -279,13 +317,13 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
     }
 
     VSAPoint end = VSAPoint(points.last());
-    if (CountNodes() > 2)
+    if (nodes.size() > 2)
     {
-        if (i == CountNodes() - 1)
+        if (i == nodes.size() - 1)
         {
-            if (at(0).GetTypeTool() == Tool::NodePoint)
+            if (nodes.at(0).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode &node = at(0);
+                const VPieceNode &node = nodes.at(0);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -298,9 +336,9 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
         }
         else
         {
-            if (at(i+1).GetTypeTool() == Tool::NodePoint)
+            if (nodes.at(i+1).GetTypeTool() == Tool::NodePoint)
             {
-                const VPieceNode &node = at(i+1);
+                const VPieceNode &node = nodes.at(i+1);
                 const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
                 if (curve->IsPointOnCurve(p))
                 {
@@ -362,3 +400,116 @@ int VPiecePath::indexOfNode(quint32 id) const
     qDebug()<<"Can't find node.";
     return -1;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
+{
+    return StartSegment(data, d->m_nodes, i, reverse);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const
+{
+    return EndSegment(data, d->m_nodes, i, reverse);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *data)
+{
+    const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
+    VSAPoint p(point->toQPointF());
+
+    p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+    p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+    p.SetAngleType(node.GetAngleType());
+
+    return p;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> VPiecePath::CurveSeamAllowanceSegment(const VContainer *data, const QVector<VPieceNode> &nodes,
+                                                        const QSharedPointer<VAbstractCurve> &curve, int i,
+                                                        bool reverse, qreal width)
+{
+    QVector<VSAPoint> pointsEkv;
+
+    const VSAPoint begin = StartSegment(data, nodes, i, reverse);
+    const VSAPoint end = EndSegment(data, nodes, i, reverse);
+
+    const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
+    if (points.isEmpty())
+    {
+        return pointsEkv;
+    }
+
+    qreal w1 = begin.GetSAAfter();
+    qreal w2 = end.GetSABefore();
+    if (w1 < 0 && w2 < 0)
+    {// no local widths
+        for(int i = 0; i < points.size(); ++i)
+        {
+            VSAPoint p(points.at(i));
+            if (i == 0)
+            { // first point
+                p.SetSAAfter(begin.GetSAAfter());
+                p.SetSABefore(begin.GetSABefore());
+                p.SetAngleType(begin.GetAngleType());
+            }
+            else if (i == points.size() - 1)
+            { // last point
+                p.SetSAAfter(end.GetSAAfter());
+                p.SetSABefore(end.GetSABefore());
+                p.SetAngleType(end.GetAngleType());
+            }
+            pointsEkv.append(p);
+        }
+    }
+    else
+    {
+        if (w1 < 0)
+        {
+            w1 = width;
+        }
+
+        if (w2 < 0)
+        {
+            w2 = width;
+        }
+
+        const qreal wDiff = w2 - w1;// Difference between to local widths
+        const qreal fullLength = VAbstractCurve::PathLength(points);
+
+        VSAPoint p(points.at(0));//First point in the list
+        p.SetSAAfter(begin.GetSAAfter());
+        p.SetSABefore(begin.GetSABefore());
+        p.SetAngleType(begin.GetAngleType());
+        pointsEkv.append(p);
+
+        qreal length = 0; // how much we handle
+
+        for(int i = 1; i < points.size(); ++i)
+        {
+            p = VSAPoint(points.at(i));
+
+            if (i == points.size() - 1)
+            {// last point
+                p.SetSAAfter(end.GetSAAfter());
+                p.SetSABefore(end.GetSABefore());
+                p.SetAngleType(end.GetAngleType());
+            }
+            else
+            {
+                length += QLineF(points.at(i-1), points.at(i)).length();
+                const qreal localWidth = w1 + wDiff*(length/fullLength);
+
+                p.SetSAAfter(localWidth);
+                p.SetSABefore(localWidth);
+                // curve points have angle type by default
+            }
+
+            pointsEkv.append(p);
+        }
+    }
+
+    return pointsEkv;
+}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index facfa10f2..7f90490bc 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -40,6 +40,7 @@ class QPointF;
 class VContainer;
 class VSAPoint;
 class QPainterPath;
+class VAbstractCurve;
 
 class VPiecePath
 {
@@ -66,18 +67,28 @@ public:
     QString GetName() const;
     void    SetName(const QString &name);
 
-    QVector<QPointF> PathPoints(const VContainer *data) const;
-    QVector<QPointF> PathNodePoints(const VContainer *data) const;
+    QVector<QPointF>  PathPoints(const VContainer *data) const;
+    QVector<QPointF>  PathNodePoints(const VContainer *data) const;
+    QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const;
 
     QPainterPath PainterPath(const VContainer *data) const;
 
-    VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
-    VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
-
     QVector<quint32> MissingNodes(const VPiecePath &path) const;
 
     int indexOfNode(quint32 id) const;
 
+    VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
+    VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
+
+    static VSAPoint StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
+    static VSAPoint EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
+
+    static VSAPoint PreparePointEkv(const VPieceNode &node, const VContainer *data);
+
+    static QVector<VSAPoint> CurveSeamAllowanceSegment(const VContainer *data, const QVector<VPieceNode> &nodes,
+                                                       const QSharedPointer<VAbstractCurve> &curve,
+                                                       int i, bool reverse, qreal width);
+
 private:
     QSharedDataPointer<VPiecePathData> d;
 };

From 83632bf284031ba3d07ac74191d91dc011b96ead Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:11:36 +0200
Subject: [PATCH 109/208] Fix two bugs with VPiecePath.

--HG--
branch : feature
---
 src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index c1bbfa9b5..d4c54609a 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -89,10 +89,6 @@ VToolPiecePath *VToolPiecePath::Create(quint32 _id, const VPiecePath &path, quin
         }
         return pathTool;
     }
-    else
-    {
-        doc->UpdateToolData(id, data);
-    }
     return nullptr;
 }
 
@@ -179,7 +175,7 @@ void VToolPiecePath::AddToFile()
     else if (path.GetType() == PiecePathType::CustomSeamAllowance)
     {
         CustomSARecord record;
-        record.path = m_pieceId;
+        record.path = id;
 
         QVector<CustomSARecord> records = newDet.GetCustomSARecords();
         records.append(record);
@@ -187,8 +183,9 @@ void VToolPiecePath::AddToFile()
     }
 
     SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
+    qApp->getUndoStack()->push(saveCommand);// First push then make a connect
+    VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
     connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(saveCommand);
 
     qApp->getUndoStack()->endMacro();
 }

From 7eb4e806c0db2ddabbdf462353b54b00e5f1392b Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:18:23 +0200
Subject: [PATCH 110/208] Declare default name for detail.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece_p.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/libs/vlayout/vabstractpiece_p.h b/src/libs/vlayout/vabstractpiece_p.h
index 745cdca56..c99abd5c0 100644
--- a/src/libs/vlayout/vabstractpiece_p.h
+++ b/src/libs/vlayout/vabstractpiece_p.h
@@ -31,6 +31,7 @@
 
 #include <QSharedData>
 #include <QString>
+#include <QCoreApplication>
 
 #include "../vmisc/diagnostic.h"
 
@@ -39,9 +40,10 @@ QT_WARNING_DISABLE_GCC("-Weffc++")
 
 class VAbstractPieceData : public QSharedData
 {
+    Q_DECLARE_TR_FUNCTIONS(VAbstractPieceData)
 public:
     VAbstractPieceData()
-        : m_name(),
+        : m_name(tr("Detail")),
           m_forbidFlipping(false),
           m_seamAllowance(false),
           m_width(0)

From 5cbb33a635a5c4be06760f1b0f8ff0791250ad41 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:28:46 +0200
Subject: [PATCH 111/208] Each VPiecePath has a name.

--HG--
branch : feature
---
 src/libs/ifc/schema/pattern/v0.4.0.xsd | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 29e40d580..e33dd7e8b 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -328,6 +328,7 @@
                                                                                  <xs:attribute name="type" type="piecePathType"></xs:attribute>
                                                                                  <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
                                                                                  <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
+                                                                                 <xs:attribute name="name" type="xs:string"></xs:attribute>
                                                                            </xs:complexType>
                                                                      </xs:element>
                                                                      <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">

From 14962270f6af5047e36aa06019ef2074af9094e9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:51:46 +0200
Subject: [PATCH 112/208] Refactoring.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 2f8bfa5d9..2a027a0ae 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -702,11 +702,7 @@ void VToolSeamAllowance::InitNodes(const VPiece &detail, VMainGraphicsScene *sce
                 break;
             }
             case (Tool::NodeArc):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
-                break;
             case (Tool::NodeSpline):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
-                break;
             case (Tool::NodeSplinePath):
                 doc->IncrementReferens(detail.GetPath().at(i).GetId());
                 break;

From b3f3f03cc30af348d2a19187d16b89cac5d16a7c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 14:58:00 +0200
Subject: [PATCH 113/208] Added custom increment and decrement methods for tool
 VToolPiecePath.

--HG--
branch : feature
---
 .../tools/nodeDetails/vtoolpiecepath.cpp      | 69 +++++++++++++++++++
 .../vtools/tools/nodeDetails/vtoolpiecepath.h |  6 ++
 2 files changed, 75 insertions(+)

diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index d4c54609a..48c804129 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -98,6 +98,55 @@ QString VToolPiecePath::getTagName() const
     return VAbstractPattern::TagPath;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::incrementReferens()
+{
+    ++_referens;
+    if (_referens == 1)
+    {
+        if (idTool != NULL_ID)
+        {
+            doc->IncrementReferens(idTool);
+        }
+        else
+        {
+            IncrementNodes(VAbstractTool::data.GetPiecePath(id));
+        }
+        ShowNode();
+        QDomElement domElement = doc->elementById(id);
+        if (domElement.isElement())
+        {
+            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::InUse);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::decrementReferens()
+{
+    if (_referens > 0)
+    {
+        --_referens;
+    }
+    if (_referens == 0)
+    {
+        if (idTool != NULL_ID)
+        {
+            doc->DecrementReferens(idTool);
+        }
+        else
+        {
+            DecrementNodes(VAbstractTool::data.GetPiecePath(id));
+        }
+        HideNode();
+        QDomElement domElement = doc->elementById(id);
+        if (domElement.isElement())
+        {
+            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::NotInUse);
+        }
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
 {
@@ -241,3 +290,23 @@ void VToolPiecePath::RefreshGeometry()
         this->setPath(p);
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::IncrementNodes(const VPiecePath &path) const
+{
+    for (int i = 0; i < path.CountNodes(); ++i)
+    {
+        const QSharedPointer<VGObject> node = VAbstractTool::data.GetGObject(path.at(i).GetId());
+        doc->IncrementReferens(node->getIdTool());
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::DecrementNodes(const VPiecePath &path) const
+{
+    for (int i = 0; i < path.CountNodes(); ++i)
+    {
+        const QSharedPointer<VGObject> node = VAbstractTool::data.GetGObject(path.at(i).GetId());
+        doc->DecrementReferens(node->getIdTool());
+    }
+}
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
index 18f4e236d..edc8e2273 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
@@ -50,6 +50,9 @@ public:
     enum { Type = UserType + static_cast<int>(Tool::PiecePath)};
     virtual QString getTagName() const Q_DECL_OVERRIDE;
 
+    virtual void incrementReferens() Q_DECL_OVERRIDE;
+    virtual void decrementReferens() Q_DECL_OVERRIDE;
+
     static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
     static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path);
     static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiecePath &path);
@@ -72,6 +75,9 @@ private:
                    QGraphicsItem * parent = nullptr );
 
     void RefreshGeometry();
+
+    void IncrementNodes(const VPiecePath &path) const;
+    void DecrementNodes(const VPiecePath &path) const;
 };
 
 #endif // VTOOLPIECEPATH_H

From 3ab96f01054ef479993fe37bf81c17cf895b36f2 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 15:29:29 +0200
Subject: [PATCH 114/208] Better to manually define values for enum in this
 case. Values used in file.

--HG--
branch : feature
---
 src/libs/vmisc/def.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index 63d489d2f..94ecaefe3 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -77,7 +77,7 @@ enum class PieceNodeAngle : unsigned char
 enum class PiecePathIncludeType : unsigned char
 {
     AsMainPath = 0,
-    AsCustomSA
+    AsCustomSA = 1
 };
 
 enum class PiecePathType :  unsigned char {PiecePath = 0, CustomSeamAllowance = 1, InternalPath = 2, Unknown = 3};

From ffec656d33a6f09b38c24c7aa5fa32d0e84c03f4 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 15:30:12 +0200
Subject: [PATCH 115/208] Fix bug. Used wrong index.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 0b0f8b2d8..0e79f1dc8 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -134,9 +134,9 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
                         {
                             for (int j = 0; j < r.size(); ++j)
                             {
-                                r[i].SetAngleType(PieceNodeAngle::ByLength);
-                                r[i].SetSABefore(0);
-                                r[i].SetSABefore(0);
+                                r[j].SetAngleType(PieceNodeAngle::ByLength);
+                                r[j].SetSABefore(0);
+                                r[j].SetSABefore(0);
                             }
                         }
 

From 9275968bbc344012b479ce60a72278aab34d01b7 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 15:30:33 +0200
Subject: [PATCH 116/208] Fix bug. Used wrong combobox.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogseamallowance.cpp   | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index a6d79f25d..849ff8d3a 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -518,10 +518,12 @@ void DialogSeamAllowance::CSAIncludeTypeChanged(int index)
     }
 
 #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
-    const PiecePathIncludeType type = static_cast<PiecePathIncludeType>(ui->comboBoxEndPoint->itemData(index).toUInt());
+    const PiecePathIncludeType type =
+            static_cast<PiecePathIncludeType>(ui->comboBoxIncludeType->itemData(index).toUInt());
 #else
     Q_UNUSED(index);
-    const PiecePathIncludeType type = static_cast<PiecePathIncludeType>(ui->comboBoxEndPoint->currentData().toUInt());
+    const PiecePathIncludeType type =
+            static_cast<PiecePathIncludeType>(ui->comboBoxIncludeType->currentData().toUInt());
 #endif
 
     QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
@@ -659,6 +661,14 @@ VPiece DialogSeamAllowance::CreatePiece() const
         piece.GetPath().Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
     }
 
+    QVector<CustomSARecord> records;
+    for (qint32 i = 0; i < ui->listWidgetCustomSA->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidgetCustomSA->item(i);
+        records.append(qvariant_cast<CustomSARecord>(item->data(Qt::UserRole)));
+    }
+    piece.SetCustomSARecords(records);
+
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
     piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
     piece.SetSAWidth(ui->doubleSpinBoxSeams->value());

From 3677a0484fb298a188d761fd8f10eb4ba5b0027d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 16:26:28 +0200
Subject: [PATCH 117/208] Fix copy paste issue.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 0e79f1dc8..2f7ccf040 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -136,7 +136,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
                             {
                                 r[j].SetAngleType(PieceNodeAngle::ByLength);
                                 r[j].SetSABefore(0);
-                                r[j].SetSABefore(0);
+                                r[j].SetSAAfter(0);
                             }
                         }
 

From 8bb3377a60ca15df53bbb1dec66f12f1f1ef1778 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 16:29:09 +0200
Subject: [PATCH 118/208] Fix several bugs in dialogs.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 25 ++++++++-----------
 .../vtools/dialogs/tools/dialogpiecepath.h    |  1 -
 .../dialogs/tools/dialogseamallowance.cpp     | 19 ++++++++++----
 3 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 7049a309d..478f08eb9 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -37,8 +37,7 @@
 DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
     ui(new Ui::DialogPiecePath),
-    m_showMode(false),
-    m_saWidth(0)
+    m_showMode(false)
 {
     ui->setupUi(this);
     InitOkCancel(ui);
@@ -88,15 +87,7 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogPiecePath::NodeAngleChanged);
 
-    if (not m_showMode)
-    {
-        vis = new VisToolPiecePath(data);
-    }
-    else
-    {
-        ui->comboBoxType->setDisabled(true);
-        ui->comboBoxPiece->setDisabled(true);
-    }
+    vis = new VisToolPiecePath(data);
 
     ui->tabWidget->removeTab(1);
 }
@@ -111,6 +102,8 @@ DialogPiecePath::~DialogPiecePath()
 void DialogPiecePath::EnbleShowMode(bool disable)
 {
     m_showMode = disable;
+    ui->comboBoxType->setDisabled(m_showMode);
+    ui->comboBoxPiece->setDisabled(m_showMode);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -308,7 +301,7 @@ void DialogPiecePath::NodeChanged(int index)
             qreal w1 = node.GetSABefore();
             if (w1 < 0)
             {
-                w1 = m_saWidth;
+                w1 = ui->doubleSpinBoxSeams->value();
             }
             else
             {
@@ -319,7 +312,7 @@ void DialogPiecePath::NodeChanged(int index)
             qreal w2 = node.GetSAAfter();
             if (w2 < 0)
             {
-                w2 = m_saWidth;
+                w2 = ui->doubleSpinBoxSeams->value();
             }
             else
             {
@@ -588,6 +581,8 @@ void DialogPiecePath::SetPieceId(quint32 id)
             ui->comboBoxType->setCurrentIndex(index);
         }
     }
+
+    ValidObjects(PathIsValid());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -595,8 +590,8 @@ void DialogPiecePath::SetSAWidth(qreal width)
 {
     if (width >=0)
     {
-        m_saWidth = width;
-        ui->tabWidget->addTab(ui->tabSeamAllowance, QString());
+        ui->tabWidget->addTab(ui->tabSeamAllowance, tr("Seam allowance"));
+        ui->doubleSpinBoxSeams->setValue(width);
     }
     else
     {
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 6149853f9..767694adc 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -78,7 +78,6 @@ private:
     Q_DISABLE_COPY(DialogPiecePath)
     Ui::DialogPiecePath *ui;
     bool m_showMode;
-    qreal m_saWidth;
 
     void InitPathTypes();
     void InitListPieces();
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 849ff8d3a..576fa9a3c 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -641,12 +641,21 @@ void DialogSeamAllowance::PathDialogClosed(int result)
         SCASSERT(not m_dialog.isNull());
         DialogPiecePath *dialogTool = qobject_cast<DialogPiecePath*>(m_dialog.data());
         SCASSERT(dialogTool != nullptr);
-        const VPiecePath newPath = dialogTool->GetPiecePath();
-        const VPiecePath oldPath = data->GetPiecePath(dialogTool->GetPieceId());
+        try
+        {
+            const VPiecePath newPath = dialogTool->GetPiecePath();
+            const VPiecePath oldPath = data->GetPiecePath(dialogTool->GetToolId());
 
-        SavePiecePathOptions *saveCommand = new SavePiecePathOptions(newPath, oldPath, qApp->getCurrentDocument(),
-                                                                     const_cast<VContainer *>(data), toolId);
-        qApp->getUndoStack()->push(saveCommand);
+            SavePiecePathOptions *saveCommand = new SavePiecePathOptions(oldPath, newPath, qApp->getCurrentDocument(),
+                                                                         const_cast<VContainer *>(data),
+                                                                         dialogTool->GetToolId());
+            qApp->getUndoStack()->push(saveCommand);
+        }
+        catch (const VExceptionBadId &e)
+        {
+            qCritical("%s\n\n%s\n\n%s", qUtf8Printable(tr("Error. Can't save piece path.")),
+                       qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation()));
+        }
     }
     delete m_dialog;
 }

From a2518509a4f7f6daa9a400602c66391c4e45d871 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 16:50:40 +0200
Subject: [PATCH 119/208] Clear comboxes when piece path was deleted.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 11 ++++++
 .../dialogs/tools/dialogseamallowance.ui      | 34 ++++++++++++++++---
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 576fa9a3c..146880f1c 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -592,6 +592,17 @@ void DialogSeamAllowance::CustomSAChanged(int row)
 {
     if (ui->listWidgetCustomSA->count() == 0 || row == -1 || row >= ui->listWidgetCustomSA->count())
     {
+        ui->comboBoxStartPoint->blockSignals(true);
+        ui->comboBoxStartPoint->clear();
+        ui->comboBoxStartPoint->blockSignals(false);
+
+        ui->comboBoxEndPoint->blockSignals(true);
+        ui->comboBoxEndPoint->clear();
+        ui->comboBoxEndPoint->blockSignals(false);
+
+        ui->comboBoxIncludeType->blockSignals(true);
+        ui->comboBoxIncludeType->clear();
+        ui->comboBoxIncludeType->blockSignals(false);
         return;
     }
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 92caf7a2b..48093e66a 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>559</width>
-    <height>476</height>
+    <width>476</width>
+    <height>504</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -301,11 +301,17 @@
             <property name="orientation">
              <enum>Qt::Horizontal</enum>
             </property>
+            <property name="opaqueResize">
+             <bool>true</bool>
+            </property>
             <widget class="QWidget" name="layoutWidget">
              <layout class="QFormLayout" name="formLayout_2">
               <property name="fieldGrowthPolicy">
                <enum>QFormLayout::ExpandingFieldsGrow</enum>
               </property>
+              <property name="horizontalSpacing">
+               <number>6</number>
+              </property>
               <item row="0" column="0">
                <widget class="QLabel" name="labelStartPoint">
                 <property name="text">
@@ -334,11 +340,31 @@
                </widget>
               </item>
               <item row="2" column="1">
-               <widget class="QComboBox" name="comboBoxIncludeType"/>
+               <widget class="QComboBox" name="comboBoxIncludeType">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
               </item>
              </layout>
             </widget>
-            <widget class="QListWidget" name="listWidgetCustomSA"/>
+            <widget class="QListWidget" name="listWidgetCustomSA">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="sizeIncrement">
+              <size>
+               <width>0</width>
+               <height>0</height>
+              </size>
+             </property>
+            </widget>
            </widget>
           </item>
          </layout>

From 3ee3fbd9cb2ce26e1472d2020dcd2a7b124b1fb3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 16:59:48 +0200
Subject: [PATCH 120/208] Improve validation custom seam allowance records.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 2f7ccf040..a59bf6a5f 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -332,7 +332,11 @@ QVector<CustomSARecord> VPiece::GetValidRecords() const
     {
         const CustomSARecord &record = d->m_customSARecords.at(i);
 
-        if (record.startPoint > NULL_ID && record.path > NULL_ID && record.endPoint > NULL_ID)
+        if (record.startPoint > NULL_ID
+                && record.path > NULL_ID
+                && record.endPoint > NULL_ID
+                && d->m_path.indexOfNode(record.startPoint) != -1
+                && d->m_path.indexOfNode(record.endPoint) != -1)
         {
             records.append(record);
         }

From 0739b3f8a3c1df4d3b59209afa8447bd07905c86 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 17:06:22 +0200
Subject: [PATCH 121/208] Update custom seam allowance settings if main path
 was changed.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 146880f1c..a9f65e39c 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -377,6 +377,7 @@ void DialogSeamAllowance::ListChanged()
         visPath->RefreshGeometry();
     }
     InitNodesList();
+    CustomSAChanged(ui->listWidgetCustomSA->currentRow());
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From c7d61aec49d6db517cfcd84e83afd4aac3b87ffb Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 17:39:13 +0200
Subject: [PATCH 122/208] Update piece path name after change.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogseamallowance.cpp | 16 ++++++++++++++++
 .../vtools/dialogs/tools/dialogseamallowance.h   |  1 +
 .../vtools/undocommands/savepiecepathoptions.cpp |  2 +-
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index a9f65e39c..5db25b0e9 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -662,6 +662,7 @@ void DialogSeamAllowance::PathDialogClosed(int result)
                                                                          const_cast<VContainer *>(data),
                                                                          dialogTool->GetToolId());
             qApp->getUndoStack()->push(saveCommand);
+            UpdateCurrentRecord();
         }
         catch (const VExceptionBadId &e)
         {
@@ -931,3 +932,18 @@ void DialogSeamAllowance::InitSAIncludeType()
     ui->comboBoxIncludeType->addItem(tr("custom seam allowance"),
                                      static_cast<unsigned char>(PiecePathIncludeType::AsCustomSA));
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::UpdateCurrentRecord()
+{
+    const int row = ui->listWidgetCustomSA->currentRow();
+    if (ui->listWidgetCustomSA->count() == 0 || row == -1)
+    {
+        return;
+    }
+
+    QListWidgetItem *item = ui->listWidgetCustomSA->item(row);
+    SCASSERT(item != nullptr);
+    const CustomSARecord record = qvariant_cast<CustomSARecord>(item->data(Qt::UserRole));
+    item->setText(GetCustomSARecordName(record));
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index cd53f8da2..4a6b986fc 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -97,6 +97,7 @@ private:
     void    InitNodesList();
     void    InitCSAPoint(QComboBox *box);
     void    InitSAIncludeType();
+    void    UpdateCurrentRecord();
 
     QListWidgetItem *GetItemById(quint32 id);
 
diff --git a/src/libs/vtools/undocommands/savepiecepathoptions.cpp b/src/libs/vtools/undocommands/savepiecepathoptions.cpp
index 61f155e4b..0c1520d76 100644
--- a/src/libs/vtools/undocommands/savepiecepathoptions.cpp
+++ b/src/libs/vtools/undocommands/savepiecepathoptions.cpp
@@ -95,7 +95,7 @@ void SavePiecePathOptions::redo()
         DecrementReferences(m_oldPath.MissingNodes(m_newPath));
 
         SCASSERT(m_data);
-        m_data->UpdatePiecePath(nodeId, m_oldPath);
+        m_data->UpdatePiecePath(nodeId, m_newPath);
     }
     else
     {

From 0c9a0347e9944658d884dadc3b6b104bbc4b5020 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 17:45:43 +0200
Subject: [PATCH 123/208] Turn on context menu in dialog piece path.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 478f08eb9..1b338fdd8 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -87,6 +87,9 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogPiecePath::NodeAngleChanged);
 
+    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogPiecePath::ShowContextMenu);
+
     vis = new VisToolPiecePath(data);
 
     ui->tabWidget->removeTab(1);

From e2579c231c10ee822e2ebc529446fb94f5782faa Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 19:39:40 +0200
Subject: [PATCH 124/208] Fix pointer to current scene. Show piece path
 visualization if the tool dialog was opened.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp                  |  8 +++-----
 src/libs/vmisc/vabstractapplication.cpp           |  6 +++---
 src/libs/vmisc/vabstractapplication.h             |  4 ++--
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 10 ++++++++++
 src/libs/vtools/dialogs/tools/dialogpiecepath.h   |  1 +
 src/libs/vwidgets/vmaingraphicsscene.cpp          |  9 +++++++--
 src/libs/vwidgets/vmaingraphicsscene.h            |  2 +-
 7 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 9fc27ff44..ba45ec3f5 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -309,9 +309,9 @@ QPointF MainWindow::StartPositionNewPP() const
 //---------------------------------------------------------------------------------------------------------------------
 void MainWindow::InitScenes()
 {
-    sceneDraw = new VMainGraphicsScene();
+    sceneDraw = new VMainGraphicsScene(this);
     currentScene = sceneDraw;
-    qApp->setCurrentScene(currentScene);
+    qApp->setCurrentScene(&currentScene);
     connect(this, &MainWindow::EnableItemMove, sceneDraw, &VMainGraphicsScene::EnableItemMove);
     connect(this, &MainWindow::ItemsSelection, sceneDraw, &VMainGraphicsScene::ItemsSelection);
 
@@ -331,7 +331,7 @@ void MainWindow::InitScenes()
 
     connect(sceneDraw, &VMainGraphicsScene::mouseMove, this, &MainWindow::MouseMove);
 
-    sceneDetails = new VMainGraphicsScene();
+    sceneDetails = new VMainGraphicsScene(this);
     connect(this, &MainWindow::EnableItemMove, sceneDetails, &VMainGraphicsScene::EnableItemMove);
 
     connect(this, &MainWindow::EnableNodeLabelSelection, sceneDetails, &VMainGraphicsScene::ToggleNodeLabelSelection);
@@ -3830,8 +3830,6 @@ MainWindow::~MainWindow()
     CleanLayout();
 
     delete doc;
-    delete sceneDetails;
-    delete sceneDraw;
     delete ui;
 }
 
diff --git a/src/libs/vmisc/vabstractapplication.cpp b/src/libs/vmisc/vabstractapplication.cpp
index 2acf0a9f3..b061115af 100644
--- a/src/libs/vmisc/vabstractapplication.cpp
+++ b/src/libs/vmisc/vabstractapplication.cpp
@@ -290,12 +290,12 @@ VCommonSettings *VAbstractApplication::Settings()
 //---------------------------------------------------------------------------------------------------------------------
 QGraphicsScene *VAbstractApplication::getCurrentScene() const
 {
-    SCASSERT(currentScene != nullptr);
-    return currentScene;
+    SCASSERT(*currentScene != nullptr);
+    return *currentScene;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VAbstractApplication::setCurrentScene(QGraphicsScene *value)
+void VAbstractApplication::setCurrentScene(QGraphicsScene **value)
 {
     currentScene = value;
 }
diff --git a/src/libs/vmisc/vabstractapplication.h b/src/libs/vmisc/vabstractapplication.h
index d55406d64..21b3daa4f 100644
--- a/src/libs/vmisc/vabstractapplication.h
+++ b/src/libs/vmisc/vabstractapplication.h
@@ -88,7 +88,7 @@ public:
     QString          LocaleToString(const T &value);
 
     QGraphicsScene  *getCurrentScene() const;
-    void             setCurrentScene(QGraphicsScene *value);
+    void             setCurrentScene(QGraphicsScene **value);
 
     VMainGraphicsView *getSceneView() const;
     void               setSceneView(VMainGraphicsView *value);
@@ -137,7 +137,7 @@ private:
     MeasurementsType   _patternType;
 
 
-    QGraphicsScene     *currentScene;
+    QGraphicsScene     **currentScene;
     VMainGraphicsView  *sceneView;
 
     VAbstractPattern   *doc;
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 1b338fdd8..4316fb2cd 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -199,6 +199,12 @@ void DialogPiecePath::CheckState()
     bOk->setEnabled(flagName && flagError);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::ShowVisualization()
+{
+    AddVisualization<VisToolPiecePath>();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::ShowContextMenu(const QPoint &pos)
 {
@@ -459,6 +465,10 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
     SetType(path.GetType());
     ui->lineEditName->setText(path.GetName());
 
+    VisToolPiecePath *visPath = qobject_cast<VisToolPiecePath *>(vis);
+    SCASSERT(visPath != nullptr);
+    visPath->SetPath(path);
+
     ValidObjects(PathIsValid());
 
     ListChanged();
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 767694adc..3f30be6a0 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -63,6 +63,7 @@ protected:
     /** @brief SaveData Put dialog data in local variables */
     virtual void SaveData() Q_DECL_OVERRIDE;
     virtual void CheckState() Q_DECL_OVERRIDE;
+    virtual void ShowVisualization() Q_DECL_OVERRIDE;
 
 private slots:
     void ShowContextMenu(const QPoint &pos);
diff --git a/src/libs/vwidgets/vmaingraphicsscene.cpp b/src/libs/vwidgets/vmaingraphicsscene.cpp
index 7f5ddf22c..974717884 100644
--- a/src/libs/vwidgets/vmaingraphicsscene.cpp
+++ b/src/libs/vwidgets/vmaingraphicsscene.cpp
@@ -51,8 +51,13 @@ class QRectF;
 /**
  * @brief VMainGraphicsScene default constructor.
  */
-VMainGraphicsScene::VMainGraphicsScene()
-    :QGraphicsScene(), horScrollBar(0), verScrollBar(0), scaleFactor(1), _transform(QTransform()), scenePos(QPointF()),
+VMainGraphicsScene::VMainGraphicsScene(QObject *parent)
+    : QGraphicsScene(parent),
+      horScrollBar(0),
+      verScrollBar(0),
+      scaleFactor(1),
+      _transform(QTransform()),
+      scenePos(QPointF()),
       origins()
 {}
 
diff --git a/src/libs/vwidgets/vmaingraphicsscene.h b/src/libs/vwidgets/vmaingraphicsscene.h
index e7db61531..301046096 100644
--- a/src/libs/vwidgets/vmaingraphicsscene.h
+++ b/src/libs/vwidgets/vmaingraphicsscene.h
@@ -54,7 +54,7 @@ class VMainGraphicsScene : public QGraphicsScene
 {
     Q_OBJECT
 public:
-    VMainGraphicsScene();
+    explicit VMainGraphicsScene(QObject *parent = nullptr);
     explicit VMainGraphicsScene(const QRectF & sceneRect, QObject * parent = nullptr);
     qint32        getHorScrollBar() const;
     void          setHorScrollBar(const qint32 &value);

From b3b957cf28dca2d99dac0d82ca8adb8dc306589b Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 29 Nov 2016 19:41:52 +0200
Subject: [PATCH 125/208] Minore fixes for dialogs.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.ui     | 12 +++++++++---
 src/libs/vtools/dialogs/tools/dialogseamallowance.ui |  4 ++--
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
index 1041d3cc4..0c414e4df 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
@@ -11,13 +11,17 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Dialog</string>
+   <string>Piece path tool</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../../../vmisc/share/resources/icon.qrc">
+    <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>1</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tabPath">
       <attribute name="title">
@@ -279,7 +283,9 @@
    </item>
   </layout>
  </widget>
- <resources/>
+ <resources>
+  <include location="../../../vmisc/share/resources/icon.qrc"/>
+ </resources>
  <connections>
   <connection>
    <sender>buttonBox</sender>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 48093e66a..047a79a7b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Dialog</string>
+   <string>Seam allowance tool</string>
   </property>
   <property name="windowIcon">
    <iconset resource="../../../vmisc/share/resources/icon.qrc">
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>1</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">

From 5ab4169fa29a5b9644ed6e835af09f5b07245151 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 30 Nov 2016 15:26:40 +0200
Subject: [PATCH 126/208] Because Piece path is not visible and information
 about point names left on Draw scene visualizations should show it too. It
 include not only point, but also label.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp                |  2 +-
 src/libs/vpatterndb/vpiece.h                  |  3 +-
 src/libs/vpatterndb/vpiecepath.cpp            |  4 +--
 src/libs/vpatterndb/vpiecepath.h              |  3 +-
 .../visualization/path/vistoolpiece.cpp       |  5 +--
 .../visualization/path/vistoolpiecepath.cpp   | 27 +++++++++++---
 .../visualization/path/vistoolpiecepath.h     |  6 ++--
 src/libs/vwidgets/vsimplepoint.cpp            | 35 ++++++++++++++++---
 src/libs/vwidgets/vsimplepoint.h              |  8 +++++
 9 files changed, 74 insertions(+), 19 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index a59bf6a5f..2d32a4be8 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -89,7 +89,7 @@ QVector<QPointF> VPiece::MainPathPoints(const VContainer *data) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VPiece::MainPathNodePoints(const VContainer *data) const
+QVector<VPointF> VPiece::MainPathNodePoints(const VContainer *data) const
 {
     return GetPath().PathNodePoints(data);
 }
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 099011102..6e4a842eb 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -38,6 +38,7 @@ class QPainterPath;
 class VPieceData;
 class VPieceNode;
 class QPointF;
+class VPointF;
 class VContainer;
 template <class T> class QVector;
 template <class T>class QSharedPointer;
@@ -57,7 +58,7 @@ public:
     void       SetPath(const VPiecePath &path);
 
     QVector<QPointF> MainPathPoints(const VContainer *data) const;
-    QVector<QPointF> MainPathNodePoints(const VContainer *data) const;
+    QVector<VPointF> MainPathNodePoints(const VContainer *data) const;
     QVector<QPointF> SeamAllowancePoints(const VContainer *data) const;
 
     QPainterPath MainPathPath(const VContainer *data) const;
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 1f761267e..b0b3ac8ee 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -166,9 +166,9 @@ QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VPiecePath::PathNodePoints(const VContainer *data) const
+QVector<VPointF> VPiecePath::PathNodePoints(const VContainer *data) const
 {
-    QVector<QPointF> points;
+    QVector<VPointF> points;
     for (int i = 0; i < CountNodes(); ++i)
     {
         switch (at(i).GetTypeTool())
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 7f90490bc..317ae75f8 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -37,6 +37,7 @@
 class VPiecePathData;
 class VPieceNode;
 class QPointF;
+class VPointF;
 class VContainer;
 class VSAPoint;
 class QPainterPath;
@@ -68,7 +69,7 @@ public:
     void    SetName(const QString &name);
 
     QVector<QPointF>  PathPoints(const VContainer *data) const;
-    QVector<QPointF>  PathNodePoints(const VContainer *data) const;
+    QVector<VPointF>  PathNodePoints(const VContainer *data) const;
     QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const;
 
     QPainterPath PainterPath(const VContainer *data) const;
diff --git a/src/libs/vtools/visualization/path/vistoolpiece.cpp b/src/libs/vtools/visualization/path/vistoolpiece.cpp
index f2457842b..8895dacaa 100644
--- a/src/libs/vtools/visualization/path/vistoolpiece.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiece.cpp
@@ -28,6 +28,7 @@
 
 #include "vistoolpiece.h"
 #include "../vpatterndb/vpiecepath.h"
+#include "../vgeometry/vpointf.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VisToolPiece::VisToolPiece(const VContainer *data, QGraphicsItem *parent)
@@ -54,12 +55,12 @@ void VisToolPiece::RefreshGeometry()
     {
         DrawPath(this, m_piece.MainPathPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
 
-        const QVector<QPointF> nodes = m_piece.MainPathNodePoints(Visualization::data);
+        const QVector<VPointF> nodes = m_piece.MainPathNodePoints(Visualization::data);
 
         for (int i = 0; i < nodes.size(); ++i)
         {
             QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
-            DrawPoint(point, nodes.at(i), supportColor);
+            DrawPoint(point, nodes.at(i).toQPointF(), supportColor);
         }
 
         if (mode == Mode::Creation)
diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
index a6755dbcc..470a4ffff 100644
--- a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
@@ -27,6 +27,8 @@
  *************************************************************************/
 
 #include "vistoolpiecepath.h"
+#include "../vwidgets/vsimplepoint.h"
+#include "../vgeometry/vpointf.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VisToolPiecePath::VisToolPiecePath(const VContainer *data, QGraphicsItem *parent)
@@ -51,12 +53,14 @@ void VisToolPiecePath::RefreshGeometry()
     {
         DrawPath(this, m_path.PainterPath(Visualization::data), mainColor, Qt::SolidLine, Qt::RoundCap);
 
-        const QVector<QPointF> nodes = m_path.PathNodePoints(Visualization::data);
+        const QVector<VPointF> nodes = m_path.PathNodePoints(Visualization::data);
 
         for (int i = 0; i < nodes.size(); ++i)
         {
-            QGraphicsEllipseItem *point = GetPoint(static_cast<quint32>(i), supportColor);
-            DrawPoint(point, nodes.at(i), supportColor);
+            VSimplePoint *point = GetPoint(static_cast<quint32>(i), supportColor);
+            point->SetOnlyPoint(mode == Mode::Creation);
+            point->RefreshGeometry(nodes.at(i));
+            point->setVisible(true);
         }
 
         if (mode == Mode::Creation)
@@ -77,9 +81,22 @@ void VisToolPiecePath::SetPath(const VPiecePath &path)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QGraphicsEllipseItem *VisToolPiecePath::GetPoint(quint32 i, const QColor &color)
+VSimplePoint *VisToolPiecePath::GetPoint(quint32 i, const QColor &color)
 {
-    return GetPointItem(Visualization::data, factor, m_points, i, color, this);
+    if (not m_points.isEmpty() && static_cast<quint32>(m_points.size() - 1) >= i)
+    {
+        return m_points.at(static_cast<int>(i));
+    }
+    else
+    {
+        VSimplePoint *point = new VSimplePoint(NULL_ID, color, *Visualization::data->GetPatternUnit(), &factor);
+        point->SetPointHighlight(true);
+        point->setParentItem(this);
+        m_points.append(point);
+
+        return point;
+    }
+    return nullptr;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.h b/src/libs/vtools/visualization/path/vistoolpiecepath.h
index dc5c8d08e..7ca400800 100644
--- a/src/libs/vtools/visualization/path/vistoolpiecepath.h
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.h
@@ -35,6 +35,8 @@
 #include "vispath.h"
 #include "../vpatterndb/vpiecepath.h"
 
+class VSimplePoint;
+
 class VisToolPiecePath : public VisPath
 {
     Q_OBJECT
@@ -49,13 +51,13 @@ public:
 
 private:
     Q_DISABLE_COPY(VisToolPiecePath)
-    QVector<QGraphicsEllipseItem *> m_points;
+    QVector<VSimplePoint *> m_points;
 
     QGraphicsLineItem *m_line;
 
     VPiecePath m_path;
 
-    QGraphicsEllipseItem* GetPoint(quint32 i, const QColor &color);
+    VSimplePoint *GetPoint(quint32 i, const QColor &color);
 
     void HideAllItems();
 };
diff --git a/src/libs/vwidgets/vsimplepoint.cpp b/src/libs/vwidgets/vsimplepoint.cpp
index 676dbcf48..f8bfa1d37 100644
--- a/src/libs/vwidgets/vsimplepoint.cpp
+++ b/src/libs/vwidgets/vsimplepoint.cpp
@@ -53,8 +53,13 @@ class QKeyEvent;
 
 //---------------------------------------------------------------------------------------------------------------------
 VSimplePoint::VSimplePoint(quint32 id, const QColor &currentColor, Unit patternUnit, qreal *factor, QObject *parent)
-    :VAbstractSimple(id, currentColor, patternUnit, factor, parent), QGraphicsEllipseItem(),
-      radius(ToPixel(DefPointRadius/*mm*/, Unit::Mm)), namePoint(nullptr), lineName(nullptr)
+    : VAbstractSimple(id, currentColor, patternUnit, factor, parent),
+      QGraphicsEllipseItem(),
+      radius(ToPixel(DefPointRadius/*mm*/, Unit::Mm)),
+      namePoint(nullptr),
+      lineName(nullptr),
+      m_onlyPoint(false),
+      m_isHighlight(false)
 {
     namePoint = new VGraphicsSimpleTextItem(this);
     connect(namePoint, &VGraphicsSimpleTextItem::ShowContextMenu, this, &VSimplePoint::ContextMenu);
@@ -64,7 +69,7 @@ VSimplePoint::VSimplePoint(quint32 id, const QColor &currentColor, Unit patternU
     connect(namePoint, &VGraphicsSimpleTextItem::NameChangePosition, this, &VSimplePoint::ChangedPosition);
     lineName = new QGraphicsLineItem(this);
     this->setBrush(QBrush(Qt::NoBrush));
-    SetPen(this, currentColor, WidthHairLine(patternUnit));
+    SetPen(this, currentColor, m_isHighlight ? WidthMainLine(patternUnit) : WidthHairLine(patternUnit));
     this->setAcceptHoverEvents(true);
     this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
 }
@@ -73,6 +78,26 @@ VSimplePoint::VSimplePoint(quint32 id, const QColor &currentColor, Unit patternU
 VSimplePoint::~VSimplePoint()
 {}
 
+//---------------------------------------------------------------------------------------------------------------------
+void VSimplePoint::SetOnlyPoint(bool value)
+{
+    m_onlyPoint = value;
+    namePoint->setVisible(not m_onlyPoint);
+    lineName->setVisible(not m_onlyPoint);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VSimplePoint::IsOnlyPoint() const
+{
+    return m_onlyPoint;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VSimplePoint::SetPointHighlight(bool value)
+{
+    m_isHighlight = value;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VSimplePoint::RefreshLine()
 {
@@ -106,7 +131,7 @@ void VSimplePoint::RefreshLine()
 void VSimplePoint::RefreshGeometry(const VPointF &point)
 {
     this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
-    SetPen(this, currentColor, WidthHairLine(patternUnit));
+    SetPen(this, currentColor, m_isHighlight ? WidthMainLine(patternUnit) : WidthHairLine(patternUnit));
     QRectF rec = QRectF(0, 0, radius*2, radius*2);
     rec.translate(-rec.center().x(), -rec.center().y());
     this->setRect(rec);
@@ -127,7 +152,7 @@ void VSimplePoint::RefreshGeometry(const VPointF &point)
 void VSimplePoint::SetEnabled(bool enabled)
 {
     VAbstractSimple::SetEnabled(enabled);
-    SetPen(this, currentColor, WidthHairLine(patternUnit));
+    SetPen(this, currentColor, m_isHighlight ? WidthMainLine(patternUnit) : WidthHairLine(patternUnit));
     SetPen(lineName, Qt::black, WidthHairLine(patternUnit));
     namePoint->setEnabled(enabled);
 }
diff --git a/src/libs/vwidgets/vsimplepoint.h b/src/libs/vwidgets/vsimplepoint.h
index 009f914e0..68785a802 100644
--- a/src/libs/vwidgets/vsimplepoint.h
+++ b/src/libs/vwidgets/vsimplepoint.h
@@ -62,6 +62,11 @@ public:
     virtual int  type() const Q_DECL_OVERRIDE {return Type;}
     enum { Type = UserType + static_cast<int>(Vis::SimplePoint)};
 
+    void SetOnlyPoint(bool value);
+    bool IsOnlyPoint() const;
+
+    void SetPointHighlight(bool value);
+
     void RefreshLine();
     void RefreshGeometry(const VPointF &point);
     virtual void SetEnabled(bool enabled) Q_DECL_OVERRIDE;
@@ -104,6 +109,9 @@ private:
 
     /** @brief lineName line what we see if label moved too away from point. */
     QGraphicsLineItem       *lineName;
+
+    bool m_onlyPoint;
+    bool m_isHighlight;
 };
 
 #endif // VSIMPLEPOINT_H

From 7b3c05dfa8a8e4b1df442c1542fc127a2114dab8 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 1 Dec 2016 20:44:29 +0200
Subject: [PATCH 127/208] Refactoring VPiecePath::StartSegment and
 VPiecePath::EndSegment.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecepath.cpp | 57 +++++++++++++-----------------
 src/libs/vpatterndb/vpiecepath.h   |  3 ++
 2 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index b0b3ac8ee..716058e95 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -250,7 +250,7 @@ QPainterPath VPiecePath::PainterPath(const VContainer *data) const
 //---------------------------------------------------------------------------------------------------------------------
 VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
 {
-    if (i < 0 && i > nodes.size()-1)
+    if (i < 0 || i > nodes.size()-1)
     {
         return VSAPoint();
     }
@@ -266,36 +266,10 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNo
     VSAPoint begin = VSAPoint(points.first());
     if (nodes.size() > 1)
     {
-        if (i == 0)
-        {
-            if (nodes.at(nodes.size()-1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = nodes.at(nodes.size()-1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    begin.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-        else
-        {
-            if (nodes.at(i-1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = nodes.at(i-1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    begin = VSAPoint(p);
-                    begin.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    begin.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    begin.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
+        int index = 0;
+        i == 0 ? index = nodes.size()-1 : index = i-1;
+
+        begin = CurvePoint(begin, data, nodes.at(index), curve);
     }
     return begin;
 }
@@ -303,7 +277,7 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNo
 //---------------------------------------------------------------------------------------------------------------------
 VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
 {
-    if (i < 0 && i > nodes.size()-1)
+    if (i < 0 || i > nodes.size()-1)
     {
         return VSAPoint();
     }
@@ -513,3 +487,22 @@ QVector<VSAPoint> VPiecePath::CurveSeamAllowanceSegment(const VContainer *data,
 
     return pointsEkv;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint VPiecePath::CurvePoint(const VSAPoint &candidate, const VContainer *data, const VPieceNode &node,
+                                const QSharedPointer<VAbstractCurve> &curve)
+{
+    VSAPoint point = candidate;
+    if (node.GetTypeTool() == Tool::NodePoint)
+    {
+        const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+        if (curve->IsPointOnCurve(p))
+        {
+            point = VSAPoint(p);
+            point.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
+            point.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+            point.SetAngleType(node.GetAngleType());
+        }
+    }
+    return point;
+}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 317ae75f8..dfbe580a5 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -92,6 +92,9 @@ public:
 
 private:
     QSharedDataPointer<VPiecePathData> d;
+
+    static VSAPoint CurvePoint(const VSAPoint &candidate, const VContainer *data, const VPieceNode &node,
+                               const QSharedPointer<VAbstractCurve> &curve);
 };
 
 Q_DECLARE_TYPEINFO(VPiecePath, Q_MOVABLE_TYPE);

From 939644692dc636d1f64a281321134f0ef26c9289 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 1 Dec 2016 20:47:15 +0200
Subject: [PATCH 128/208] Convert all mx and my values to local seam allowance.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           |  71 ++++++++-
 src/app/valentina/xml/vpattern.h             |   4 +-
 src/libs/ifc/ifcdef.cpp                      |   1 +
 src/libs/ifc/ifcdef.h                        |   1 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd       |   3 +
 src/libs/ifc/xml/vpatternconverter.cpp       |  12 +-
 src/libs/vpatterndb/vnodedetail.cpp          | 158 +++++++++++++++++++
 src/libs/vpatterndb/vnodedetail.h            |   8 +
 src/libs/vpatterndb/vpiecepath.cpp           | 135 ++++++++++++----
 src/libs/vpatterndb/vpiecepath.h             |   3 +
 src/libs/vtools/tools/vtoolseamallowance.cpp |  16 +-
 11 files changed, 376 insertions(+), 36 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 338021003..b785a9aa7 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -520,6 +520,43 @@ void VPattern::customEvent(QEvent *event)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VNodeDetail VPattern::ParseDetailNode(const QDomElement &domElement) const
+{
+    const quint32 id = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
+    const qreal mx = GetParametrDouble(domElement, AttrMx, "0.0");
+    const qreal my = GetParametrDouble(domElement, AttrMy, "0.0");
+    const bool reverse = GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
+    const NodeDetail nodeType = NodeDetail::Contour;
+
+    const QString t = GetParametrString(domElement, AttrType, "NodePoint");
+    Tool tool;
+
+    QStringList types = QStringList() << VAbstractPattern::NodePoint
+                                      << VAbstractPattern::NodeArc
+                                      << VAbstractPattern::NodeSpline
+                                      << VAbstractPattern::NodeSplinePath;
+    switch (types.indexOf(t))
+    {
+        case 0: // NodePoint
+            tool = Tool::NodePoint;
+            break;
+        case 1: // NodeArc
+            tool = Tool::NodeArc;
+            break;
+        case 2: // NodeSpline
+            tool = Tool::NodeSpline;
+            break;
+        case 3: // NodeSplinePath
+            tool = Tool::NodeSplinePath;
+            break;
+        default:
+            VException e(tr("Wrong tag name '%1'.").arg(t));
+            throw e;
+    }
+    return VNodeDetail(id, tool, nodeType, mx, my, reverse);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
 {
@@ -704,6 +741,8 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
         detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
+        const uint version = GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
+
         const QStringList tags = QStringList() << TagNodes
                                                << TagData
                                                << TagPatternInfo
@@ -719,7 +758,18 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                 switch (tags.indexOf(element.tagName()))
                 {
                     case 0:// TagNodes
-                        ParseDetailNodes(element, detail);
+                        if (version == 1)
+                        {
+                            // TODO. Delete if minimal supported version is 0.4.0
+                            Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                                              "Time to refactor the code.");
+                            const bool closed = GetParametrUInt(domElement, AttrClosed, "1");
+                            ParseDetailNodes(element, detail, closed);
+                        }
+                        else
+                        {
+                            ParsePieceNodes(element, detail);
+                        }
                         break;
                     case 1:// TagData
                         break;
@@ -818,7 +868,24 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const
+void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const
+{
+    QVector<VNodeDetail> oldNodes;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
+        {
+            oldNodes.append(ParseDetailNode(element));
+        }
+    }
+
+    detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, detail.GetSAWidth(), closed));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const
 {
     const QDomNodeList nodeList = domElement.childNodes();
     for (qint32 i = 0; i < nodeList.size(); ++i)
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 9911da676..73caf79d5 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -114,12 +114,14 @@ private:
     VMainGraphicsScene *sceneDraw;
     VMainGraphicsScene *sceneDetail;
 
+    VNodeDetail    ParseDetailNode(const QDomElement &domElement) const;
     VPieceNode     ParseSANode(const QDomElement &domElement) const;
 
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
-    void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const;
+    void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
+    void           ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp
index 450dede6e..bfb584913 100644
--- a/src/libs/ifc/ifcdef.cpp
+++ b/src/libs/ifc/ifcdef.cpp
@@ -136,6 +136,7 @@ const QString AttrArc         = QStringLiteral("arc");
 const QString AttrSuffix      = QStringLiteral("suffix");
 const QString AttrIdObject    = QStringLiteral("idObject");
 const QString AttrInLayout    = QStringLiteral("inLayout");
+const QString AttrClosed      = QStringLiteral("closed");
 
 const QString TypeLineNone           = QStringLiteral("none");
 const QString TypeLineLine           = QStringLiteral("hair");
diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h
index d3594f201..0b87156f2 100644
--- a/src/libs/ifc/ifcdef.h
+++ b/src/libs/ifc/ifcdef.h
@@ -137,6 +137,7 @@ extern const QString AttrArc;
 extern const QString AttrSuffix;
 extern const QString AttrIdObject;
 extern const QString AttrInLayout;
+extern const QString AttrClosed;
 
 extern const QString TypeLineNone;
 extern const QString TypeLineLine;
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index e33dd7e8b..4a76b947a 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -429,6 +429,8 @@
 																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
 																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
 																										 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
+																										 <xs:attribute name="mx" type="xs:double"></xs:attribute>
+																										 <xs:attribute name="my" type="xs:double"></xs:attribute>
 																								   </xs:complexType>
 																							 </xs:element>
 																						 </xs:sequence>
@@ -460,6 +462,7 @@
                                                                            <xs:attribute name="width" type="xs:double"></xs:attribute>
                                                                            <xs:attribute name="seamAllowance" type="xs:boolean"></xs:attribute>
                                                                            <xs:attribute name="united" type="xs:boolean"></xs:attribute>
+                                                                           <xs:attribute name="closed" type="xs:unsignedInt"></xs:attribute>
                                                                      </xs:complexType>
                                                                </xs:element>
                                                          </xs:sequence>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index 0e02b69e0..145c0fddb 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -1730,8 +1730,6 @@ void VPatternConverter::TagDetailToV0_4_0()
             dom.setAttribute(strSeamAllowance, dom.attribute(strSupplement, "0"));
             dom.removeAttribute(strSupplement);
 
-            dom.removeAttribute(strClosed);
-
             dom.setAttribute(strVersion, "1");
 
             const QStringList tags = QStringList() << strNode << strData << strPatternInfo << strGrainline;
@@ -1760,6 +1758,16 @@ void VPatternConverter::TagDetailToV0_4_0()
                                 tagNode.setAttribute(strReverse, element.attribute(strReverse, "0"));
                             }
 
+                            if (element.hasAttribute(strMx))
+                            {
+                                tagNode.setAttribute(strMx, element.attribute(strMx, "0"));
+                            }
+
+                            if (element.hasAttribute(strMy))
+                            {
+                                tagNode.setAttribute(strMy, element.attribute(strMy, "0"));
+                            }
+
                             tagNode.setAttribute(strType, element.attribute(strType, ""));
 
                             tagNodes.appendChild(tagNode);
diff --git a/src/libs/vpatterndb/vnodedetail.cpp b/src/libs/vpatterndb/vnodedetail.cpp
index decba2343..a26b86887 100644
--- a/src/libs/vpatterndb/vnodedetail.cpp
+++ b/src/libs/vpatterndb/vnodedetail.cpp
@@ -28,6 +28,13 @@
 
 #include "vnodedetail.h"
 #include "vnodedetail_p.h"
+#include "vpiecenode.h"
+#include "vpiecepath.h"
+#include "../vgeometry/vpointf.h"
+#include "../vpatterndb/vcontainer.h"
+
+#include <QLineF>
+#include <QVector>
 
 //---------------------------------------------------------------------------------------------------------------------
 VNodeDetail::VNodeDetail()
@@ -146,3 +153,154 @@ void VNodeDetail::setReverse(bool reverse)
         d->reverse = reverse;
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<VNodeDetail> &nodes, qreal width,
+                                         bool closed)
+{
+    if (width < 0)
+    {
+        width = 0;
+    }
+
+    VPiecePath path;
+    for (int i = 0; i < nodes.size(); ++i)
+    {
+        const VNodeDetail &node = nodes.at(i);
+        path.Append(VPieceNode(node.getId(), node.getTypeTool(), node.getReverse()));
+    }
+
+    auto LocalWidth = [width](qreal move) noexcept
+    {
+        qreal value = width + move;
+        if (value < 0)
+        {
+            value = 0;
+        }
+        return value;
+    };
+
+    if (path.PathPoints(data).size() > 2)
+    {
+        for (int i = 0; i < nodes.size(); ++i)
+        {
+            const VNodeDetail &node = nodes.at(i);
+            if (node.getTypeTool() == Tool::NodePoint)
+            {
+                if (not qFuzzyIsNull(node.getMx()) || not qFuzzyIsNull(node.getMy()))
+                {
+                    const QPointF previosPoint = path.NodePreviousPoint(data, i);
+                    const QPointF nextPoint = path.NodeNextPoint(data, i);
+
+                    const QPointF point = data->GeometricObject<VPointF>(node.getId())->toQPointF();
+
+                    const QPointF xPoint(point.x()+node.getMx(), point.y());
+                    const QPointF yPoint(point.x(), point.y()+node.getMy());
+
+                    if (IsSABefore(QLineF(point, previosPoint), QLineF(point, xPoint)))
+                    {
+                        path[i].SetSABefore(LocalWidth(node.getMx()));
+
+                        if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
+                        {
+                            path[i].SetSAAfter(LocalWidth(node.getMy()));
+                        }
+                    }
+                    else if (IsSABefore(QLineF(point, previosPoint), QLineF(point, yPoint)))
+                    {
+                        path[i].SetSABefore(LocalWidth(node.getMy()));
+
+                        if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
+                        {
+                            path[i].SetSAAfter(LocalWidth(node.getMx()));
+                        }
+                    }
+                    else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
+                    {
+                        path[i].SetSAAfter(LocalWidth(node.getMx()));
+                    }
+                    else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
+                    {
+                        path[i].SetSAAfter(LocalWidth(node.getMy()));
+                    }
+                }
+            }
+        }
+    }
+
+    if (not closed && path.CountNodes() > 1)
+    {
+        path[0].SetSABefore(0);
+        path[path.CountNodes()-1].SetSAAfter(0);
+    }
+
+    return path.GetNodes();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VNodeDetail::IsSABefore(const QLineF &saBaseLine, const QLineF &mLine)
+{
+    if (qFuzzyIsNull(mLine.length()))
+    {
+        return false;
+    }
+
+    QLineF saLine = saBaseLine;
+    saLine.setAngle(saLine.angle() - 90);
+
+    int saAngle = qRound(saLine.angle());
+    if (saAngle >= 360)
+    {
+        saAngle = 0;
+    }
+
+    int mTest1 = qRound(mLine.angle());
+    if (mTest1 >= 360)
+    {
+        mTest1 = 0;
+    }
+
+    QLineF mrLine = mLine;
+    mrLine.setAngle(mrLine.angle()+180);
+    int mTest2 = qRound(mrLine.angle());
+    if (mTest2 >=360)
+    {
+        mTest2 = 0;
+    }
+
+    return (saAngle == mTest1 || saAngle == mTest2);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VNodeDetail::IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine)
+{
+    if (qFuzzyIsNull(mLine.length()))
+    {
+        return false;
+    }
+
+    QLineF saLine = saBaseLine;
+    saLine.setAngle(saLine.angle() + 90);
+
+    int saAngle = qRound(saLine.angle());
+    if (saAngle >= 360)
+    {
+        saAngle = 0;
+    }
+
+    int mTest1 = qRound(mLine.angle());
+    if (mTest1 >= 360)
+    {
+        mTest1 = 0;
+    }
+
+    QLineF mrLine = mLine;
+    mrLine.setAngle(mrLine.angle()+180);
+    int mTest2 = qRound(mrLine.angle());
+    if (mTest2 >=360)
+    {
+        mTest2 = 0;
+    }
+
+    return (saAngle == mTest1 || saAngle == mTest2);
+}
diff --git a/src/libs/vpatterndb/vnodedetail.h b/src/libs/vpatterndb/vnodedetail.h
index d1c5ac152..ca6df9f04 100644
--- a/src/libs/vpatterndb/vnodedetail.h
+++ b/src/libs/vpatterndb/vnodedetail.h
@@ -37,6 +37,8 @@
 #include "../vmisc/def.h"
 
 class VNodeDetailData;
+class VPieceNode;
+class VContainer;
 
 /**
  * @brief The VNodeDetail class keep information about detail node.
@@ -122,8 +124,14 @@ public:
 
     bool        getReverse() const;
     void        setReverse(bool reverse);
+
+    static QVector<VPieceNode> Convert(const VContainer *data, const QVector<VNodeDetail> &nodes, qreal width,
+                                       bool closed);
 private:
     QSharedDataPointer<VNodeDetailData> d;
+
+    static bool IsSABefore(const QLineF &saBaseLine, const QLineF &mLine);
+    static bool IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine);
 };
 
 Q_DECLARE_METATYPE(VNodeDetail)
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 716058e95..cbaa5061a 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -293,36 +293,10 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode
     VSAPoint end = VSAPoint(points.last());
     if (nodes.size() > 2)
     {
-        if (i == nodes.size() - 1)
-        {
-            if (nodes.at(0).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = nodes.at(0);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    end.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
-        else
-        {
-            if (nodes.at(i+1).GetTypeTool() == Tool::NodePoint)
-            {
-                const VPieceNode &node = nodes.at(i+1);
-                const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-                if (curve->IsPointOnCurve(p))
-                {
-                    end = VSAPoint(p);
-                    end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-                    end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
-                    end.SetAngleType(node.GetAngleType());
-                }
-            }
-        }
+        int index = 0;
+        i == nodes.size() - 1 ? index = 0 : index = i+1;
+
+        end = CurvePoint(end, data, nodes.at(index), curve);
     }
     return end;
 }
@@ -387,6 +361,107 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
     return EndSegment(data, d->m_nodes, i, reverse);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QPointF VPiecePath::NodePreviousPoint(const VContainer *data, int i) const
+{
+    if (i < 0 || i > d->m_nodes.size()-1)
+    {
+        return QPointF();
+    }
+
+    if (d->m_nodes.size() > 1)
+    {
+        int index = 0;
+        if (i == 0)
+        {
+            index = d->m_nodes.size()-1;
+        }
+        else
+        {
+            index = i-1;
+        }
+
+        const VPieceNode &node = d->m_nodes.at(index);
+        switch (node.GetTypeTool())
+        {
+            case (Tool::NodePoint):
+                return *data->GeometricObject<VPointF>(node.GetId());
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
+
+                const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
+                const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
+
+                const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
+                if (points.size() > 1)
+                {
+                    return points.at(points.size()-2);
+                }
+            }
+                break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
+                break;
+        }
+    }
+
+    return QPointF();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPointF VPiecePath::NodeNextPoint(const VContainer *data, int i) const
+{
+    QPointF point;
+    if (i < 0 || i > d->m_nodes.size()-1)
+    {
+        return point;
+    }
+
+    if (d->m_nodes.size() > 1)
+    {
+        int index = 0;
+        if (i == d->m_nodes.size() - 1)
+        {
+            index = 0;
+        }
+        else
+        {
+            index = i+1;
+        }
+
+        const VPieceNode &node = d->m_nodes.at(index);
+        switch (node.GetTypeTool())
+        {
+            case (Tool::NodePoint):
+                return *data->GeometricObject<VPointF>(node.GetId());
+            case (Tool::NodeArc):
+            case (Tool::NodeSpline):
+            case (Tool::NodeSplinePath):
+            {
+                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
+
+                const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
+                const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
+
+                const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
+                if (points.size() > 1)
+                {
+                    return points.at(1);
+                }
+            }
+                break;
+            default:
+                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
+                break;
+        }
+    }
+
+    return point;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *data)
 {
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index dfbe580a5..63829bd0b 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -81,6 +81,9 @@ public:
     VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
     VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
 
+    QPointF NodePreviousPoint(const VContainer *data, int i) const;
+    QPointF NodeNextPoint(const VContainer *data, int i) const;
+
     static VSAPoint StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
     static VSAPoint EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
 
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 2a027a0ae..66f580c41 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -379,7 +379,21 @@ void VToolSeamAllowance::RefreshDataInFile()
             // TODO. Delete if minimal supported version is 0.4.0
             Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
                               "Time to refactor the code.");
-            doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
+
+            const uint version = doc->GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
+            if (version == 1)
+            {
+                const VPiece piece = VAbstractTool::data.GetPiece(id);
+
+                doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
+
+                doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
+                AddPatternPieceData(doc, domElement, piece);
+                AddPatternInfo(doc, domElement, piece);
+                AddGrainline(doc, domElement, piece);
+                AddNodes(doc, domElement, piece);
+                AddCSARecords(doc, domElement, piece.GetCustomSARecords());
+            }
         }
     }
 }

From e93eacc655698a95e70168e020d79b3011db1d11 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 13:31:59 +0200
Subject: [PATCH 129/208] Cppcheck warnings.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece_p.h     | 2 +-
 src/libs/vpatterndb/vpiecepath.h   | 2 +-
 src/libs/vpatterndb/vpiecepath_p.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index c8c42ad1a..2b9a8c961 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -43,7 +43,7 @@ QT_WARNING_DISABLE_GCC("-Weffc++")
 class VPieceData : public QSharedData
 {
 public:
-    VPieceData(PiecePathType type)
+    explicit VPieceData(PiecePathType type)
         : m_path(type),
           m_mx(0),
           m_my(0),
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 63829bd0b..783166eac 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -47,7 +47,7 @@ class VPiecePath
 {
 public:
     VPiecePath();
-    VPiecePath(PiecePathType type);
+    explicit VPiecePath(PiecePathType type);
     VPiecePath(const VPiecePath &path);
     VPiecePath &operator=(const VPiecePath &path);
     ~VPiecePath();
diff --git a/src/libs/vpatterndb/vpiecepath_p.h b/src/libs/vpatterndb/vpiecepath_p.h
index 06ca8089e..77bcfdf85 100644
--- a/src/libs/vpatterndb/vpiecepath_p.h
+++ b/src/libs/vpatterndb/vpiecepath_p.h
@@ -47,7 +47,7 @@ public:
           m_name()
     {}
 
-    VPiecePathData(PiecePathType type)
+    explicit VPiecePathData(PiecePathType type)
         : m_nodes(),
           m_type(type),
           m_name()

From 35f54c5cc7a841c3839aa3f7bce2ec21ce6546c6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 18:01:39 +0200
Subject: [PATCH 130/208] Added Internal path.

--HG--
branch : feature
---
 .../share/collection/MaleShirt/MaleShirt.val  | 328 ++++++++++--------
 src/app/valentina/xml/vpattern.cpp            |  34 +-
 src/app/valentina/xml/vpattern.h              |   1 +
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |  12 +
 src/libs/vpatterndb/vpiece.cpp                |  43 +++
 src/libs/vpatterndb/vpiece.h                  |   4 +
 src/libs/vpatterndb/vpiece_p.h                |   7 +-
 src/libs/vpatterndb/vpiecepath.cpp            |  12 +
 src/libs/vpatterndb/vpiecepath.h              |   3 +
 src/libs/vpatterndb/vpiecepath_p.h            |  10 +-
 .../vtools/dialogs/tools/dialogpiecepath.cpp  |  30 +-
 .../vtools/dialogs/tools/dialogpiecepath.h    |   3 +
 .../vtools/dialogs/tools/dialogpiecepath.ui   |  27 +-
 .../dialogs/tools/dialogseamallowance.cpp     | 106 +++++-
 .../dialogs/tools/dialogseamallowance.h       |   8 +-
 .../dialogs/tools/dialogseamallowance.ui      |  14 +
 .../tools/nodeDetails/vtoolpiecepath.cpp      |   9 +-
 src/libs/vtools/tools/vabstracttool.cpp       |  29 ++
 src/libs/vtools/tools/vabstracttool.h         |   1 +
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  37 ++
 src/libs/vtools/tools/vtoolseamallowance.h    |   3 +
 src/libs/vtools/undocommands/addpiece.cpp     |   1 +
 src/libs/vtools/undocommands/deletepiece.cpp  |   1 +
 .../vtools/undocommands/savepieceoptions.cpp  |   4 +
 24 files changed, 554 insertions(+), 173 deletions(-)

diff --git a/src/app/share/collection/MaleShirt/MaleShirt.val b/src/app/share/collection/MaleShirt/MaleShirt.val
index cec3bc8f0..8fbb0a6f9 100644
--- a/src/app/share/collection/MaleShirt/MaleShirt.val
+++ b/src/app/share/collection/MaleShirt/MaleShirt.val
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <pattern>
     <!--Pattern created with Valentina (http://www.valentina-project.org/).-->
-    <version>0.3.1</version>
+    <version>0.4.0</version>
     <unit>cm</unit>
     <author>Timo Virtaneva</author>
     <description>This a male shirt pattern.
@@ -14,7 +14,7 @@ The design is based on the measuring table. The table must be loaded, but the va
 Adjust/verify curves after parameter modifications.
 
 Delete layouts which are not needed.</description>
-    <notes></notes>
+    <notes/>
     <measurements>MaleShirt.vit</measurements>
     <increments>
         <increment name="#ToBeVerified" description="" formula="0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0"/>
@@ -197,49 +197,55 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="440" idObject="55" mx="0.132292" my="0.264583"/>
         </modeling>
         <details>
-            <detail closed="1" id="174" name="Yoke" supplement="1" mx="-8.05221" width="1" my="3.27846">
-                <node type="NodePoint" nodeType="Contour" idObject="167" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="168" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="169" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="170" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="171" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="172" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="173" mx="0" my="0"/>
+            <detail closed="1" id="174" name="Yoke" seamAllowance="1" mx="-8.05221" width="1" my="3.27846" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="167" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="168" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="169" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="170" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="171" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="172" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="173" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="401" name="FrontPanel" supplement="1" mx="-11.0934" width="1" my="6.43098">
-                <node type="NodePoint" nodeType="Contour" idObject="389" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="390" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="391" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="392" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="393" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="394" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="395" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="396" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="397" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="398" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="399" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="400" mx="0" my="0"/>
+            <detail closed="1" id="401" name="FrontPanel" seamAllowance="1" mx="-11.0934" width="1" my="6.43098" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="389" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="390" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="391" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="392" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="393" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="394" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="395" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="396" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="397" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="398" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="399" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="400" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="441" name="BackPanel" supplement="1" mx="-7.55641" width="1" my="6.27021">
-                <node type="NodePoint" nodeType="Contour" idObject="422" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="423" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="424" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="425" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="426" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="427" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="428" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="429" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="430" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="431" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="432" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="433" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="434" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="435" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="436" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="437" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="438" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="439" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="440" mx="0" my="0"/>
+            <detail closed="1" id="441" name="BackPanel" seamAllowance="1" mx="-7.55641" width="1" my="6.27021" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="422" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="423" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="424" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="425" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="426" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="427" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="428" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="429" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="430" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="431" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="432" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="433" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="434" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="435" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="436" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="437" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="438" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="439" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="440" mx="0" my="0"/>
+                </nodes>
             </detail>
         </details>
         <groups/>
@@ -310,36 +316,44 @@ Delete layouts which are not needed.</description>
             <spline type="modelingPath" inUse="true" id="331" idObject="312"/>
         </modeling>
         <details>
-            <detail closed="1" id="182" name="Pocket" supplement="1" mx="68.0595" width="1" my="45.4124">
-                <node type="NodePoint" nodeType="Contour" idObject="175" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="176" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="177" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="178" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="179" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="180" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="181" mx="0" my="0"/>
+            <detail closed="1" id="182" name="Pocket" seamAllowance="1" mx="68.0595" width="1" my="45.4124" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="175" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="176" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="177" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="178" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="179" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="180" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="181" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="320" name="PocketRound" supplement="1" mx="81.7244" width="1" my="45.8357">
-                <node type="NodePoint" nodeType="Contour" idObject="314" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="315" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="316" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="317" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="318" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="319" mx="0" my="0"/>
+            <detail closed="1" id="320" name="PocketRound" seamAllowance="1" mx="81.7244" width="1" my="45.8357" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="314" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="315" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="316" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="317" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="318" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="319" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="326" name="PocketFlap" supplement="1" mx="67.876" width="1" my="32.9628">
-                <node type="NodePoint" nodeType="Contour" idObject="321" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="322" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="323" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="324" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="325" mx="0" my="0"/>
+            <detail closed="1" id="326" name="PocketFlap" seamAllowance="1" mx="67.876" width="1" my="32.9628" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="321" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="322" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="323" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="324" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="325" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="332" name="PocketFlapRound" supplement="1" mx="81.7244" width="1" my="32.9627">
-                <node type="NodePoint" nodeType="Contour" idObject="327" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="328" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="329" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="330" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="331" mx="0" my="0"/>
+            <detail closed="1" id="332" name="PocketFlapRound" seamAllowance="1" mx="81.7244" width="1" my="32.9627" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="327" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="328" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="329" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="330" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="331" mx="0" my="0"/>
+                </nodes>
             </detail>
         </details>
         <groups/>
@@ -447,45 +461,53 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="299" idObject="97" mx="-0.222289" my="0.696084"/>
         </modeling>
         <details>
-            <detail closed="1" id="204" name="Collar" supplement="1" mx="27.4551" width="1" my="0.587081">
-                <node type="NodePoint" nodeType="Contour" idObject="200" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="201" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="202" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="203" mx="0" my="0"/>
+            <detail closed="1" id="204" name="Collar" seamAllowance="1" mx="27.4551" width="1" my="0.587081" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="200" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="201" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="202" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="203" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="209" name="CuffInterface" supplement="0" mx="26.9909" width="1" my="-8.22145">
-                <node type="NodePoint" nodeType="Contour" idObject="205" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="206" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="207" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="208" mx="0" my="0"/>
+            <detail closed="1" id="209" name="CuffInterface" seamAllowance="0" mx="26.9909" width="1" my="-8.22145" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="205" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="206" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="207" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="208" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="217" name="ShortSleeve" supplement="1" mx="-16.9664" width="1" my="-23.4126">
-                <node type="NodePoint" nodeType="Contour" idObject="210" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="211" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="212" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="213" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="214" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="215" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="216" mx="0" my="0"/>
+            <detail closed="1" id="217" name="ShortSleeve" seamAllowance="1" mx="-16.9664" width="1" my="-23.4126" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="210" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="211" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="212" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="213" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="214" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="215" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="216" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="300" name="FullSleeve" supplement="1" mx="-16.0896" width="1" my="15.2013">
-                <node type="NodePoint" nodeType="Contour" idObject="283" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="1" nodeType="Contour" idObject="284" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="285" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="286" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="0" nodeType="Contour" idObject="287" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="288" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="289" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="290" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="291" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="292" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="293" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="294" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="295" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="296" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="297" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="298" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="299" mx="0" my="0"/>
+            <detail closed="1" id="300" name="FullSleeve" seamAllowance="1" mx="-16.0896" width="1" my="15.2013" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="283" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="1" idObject="284" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="285" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="286" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="287" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="288" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="289" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="290" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="291" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="292" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="293" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="294" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="295" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="296" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="297" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="298" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="299" mx="0" my="0"/>
+                </nodes>
             </detail>
         </details>
         <groups/>
@@ -543,37 +565,45 @@ Delete layouts which are not needed.</description>
             <spline type="modelingSpline" inUse="true" id="254" idObject="248"/>
         </modeling>
         <details>
-            <detail closed="1" id="224" name="CollarBase" supplement="1" mx="28.4767" width="1" my="21.6501">
-                <node type="NodePoint" nodeType="Contour" idObject="218" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="219" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="220" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="221" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="1" nodeType="Contour" idObject="222" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="223" mx="0" my="0"/>
+            <detail closed="1" id="224" name="CollarBase" seamAllowance="1" mx="28.4767" width="1" my="21.6501" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="218" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="219" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="220" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="221" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="1" idObject="222" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="223" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="231" name="CollarBaseInterface" supplement="0" mx="28.6569" width="1" my="15.2047">
-                <node type="NodePoint" nodeType="Contour" idObject="225" mx="0" my="0"/>
-                <node type="NodeSplinePath" reverse="1" nodeType="Contour" idObject="226" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="227" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="228" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="1" nodeType="Contour" idObject="229" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="230" mx="0" my="0"/>
+            <detail closed="1" id="231" name="CollarBaseInterface" seamAllowance="0" mx="28.6569" width="1" my="15.2047" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="225" mx="0" my="0"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="226" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="227" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="228" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="1" idObject="229" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="230" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="238" name="CollarTop" supplement="1" mx="28.0866" width="1" my="9.53729">
-                <node type="NodePoint" nodeType="Contour" idObject="232" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="233" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="234" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="235" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="236" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="237" mx="0" my="0"/>
+            <detail closed="1" id="238" name="CollarTop" seamAllowance="1" mx="28.0866" width="1" my="9.53729" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="232" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="233" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="234" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="235" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="236" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="237" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="255" name="CollarTopInterface" supplement="0" mx="27.8619" width="1" my="-1.37137">
-                <node type="NodePoint" nodeType="Contour" idObject="249" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="250" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="251" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="252" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="253" mx="0" my="0"/>
-                <node type="NodeSpline" reverse="0" nodeType="Contour" idObject="254" mx="0" my="0"/>
+            <detail closed="1" id="255" name="CollarTopInterface" seamAllowance="0" mx="27.8619" width="1" my="-1.37137" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="249" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="250" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="251" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="252" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="253" mx="0" my="0"/>
+                    <node type="NodeSpline" reverse="0" idObject="254" mx="0" my="0"/>
+                </nodes>
             </detail>
         </details>
         <groups/>
@@ -609,20 +639,24 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="281" idObject="260" mx="0.132292" my="0.264583"/>
         </modeling>
         <details>
-            <detail closed="1" id="274" name="PlacketUnder" supplement="1" mx="27.725" width="1" my="-0.179464">
-                <node type="NodePoint" nodeType="Contour" idObject="270" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="271" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="272" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="273" mx="0" my="0"/>
+            <detail closed="1" id="274" name="PlacketUnder" seamAllowance="1" mx="27.725" width="1" my="-0.179464" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="270" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="271" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="272" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="273" mx="0" my="0"/>
+                </nodes>
             </detail>
-            <detail closed="1" id="282" name="PlacketTop" supplement="1" mx="46.1968" width="1" my="-5.58778">
-                <node type="NodePoint" nodeType="Contour" idObject="275" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="276" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="277" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="278" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="279" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="280" mx="0" my="0"/>
-                <node type="NodePoint" nodeType="Contour" idObject="281" mx="0" my="0"/>
+            <detail closed="1" id="282" name="PlacketTop" seamAllowance="1" mx="46.1968" width="1" my="-5.58778" version="1">
+                <nodes>
+                    <node type="NodePoint" idObject="275" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="276" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="277" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="278" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="279" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="280" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="281" mx="0" my="0"/>
+                </nodes>
             </detail>
         </details>
         <groups/>
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index b785a9aa7..c4ec79478 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -747,7 +747,8 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                                                << TagData
                                                << TagPatternInfo
                                                << TagGrainline
-                                               << VToolSeamAllowance::TagCSA;
+                                               << VToolSeamAllowance::TagCSA
+                                               << VToolSeamAllowance::TagIPaths;
 
         const QDomNodeList nodeList = domElement.childNodes();
         for (qint32 i = 0; i < nodeList.size(); ++i)
@@ -780,6 +781,8 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                     case 4:// VToolSeamAllowance::TagCSA
                         ParseDetailCSARecords(element, detail);
                         break;
+                    case 5:// VToolSeamAllowance::TagIPaths
+                        ParseDetailInternalPaths(element, detail);
                     default:
                         break;
                 }
@@ -875,7 +878,8 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, b
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
+        if (not element.isNull()
+                && element.tagName() == VAbstractPattern::TagNode) // Old detail version need this check!
         {
             oldNodes.append(ParseDetailNode(element));
         }
@@ -891,7 +895,7 @@ void VPattern::ParsePieceNodes(const QDomElement &domElement, VPiece &detail) co
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
+        if (not element.isNull())
         {
             detail.GetPath().Append(ParseSANode(element));
         }
@@ -906,7 +910,7 @@ void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &deta
     for (qint32 i = 0; i < nodeList.size(); ++i)
     {
         const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagRecord)
+        if (not element.isNull())
         {
             CustomSARecord record;
             record.startPoint = GetParametrUInt(element, VToolSeamAllowance::AttrStart, NULL_ID_STR);
@@ -922,6 +926,26 @@ void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &deta
     detail.SetCustomSARecords(records);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParseDetailInternalPaths(const QDomElement &domElement, VPiece &detail) const
+{
+    QVector<quint32> records;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull())
+        {
+            const quint32 path = GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
+            if (path > NULL_ID)
+            {
+                records.append(path);
+            }
+        }
+    }
+    detail.SetInternalPaths(records);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDetails parse details tag.
@@ -3131,6 +3155,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
         const QString defType = QString().setNum(static_cast<int>(PiecePathType::CustomSeamAllowance));
         const PiecePathType type = static_cast<PiecePathType>(GetParametrUInt(domElement, AttrType, defType));
         const quint32 idTool = GetParametrUInt(domElement, VAbstractNode::AttrIdTool, NULL_ID_STR);
+        const QString penType = GetParametrString(domElement, AttrTypeLine, TypeLineLine);
 
         VPiecePath path;
         const QDomElement element = domElement.firstChildElement(VAbstractPattern::TagNodes);
@@ -3141,6 +3166,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
 
         path.SetType(type);
         path.SetName(name);
+        path.SetPenType(VAbstractTool::LineStyleToPenStyle(penType));
 
         VToolPiecePath::Create(id, path, 0, scene, this, data, parse, Source::FromFile, "", idTool);
     }
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 73caf79d5..25d0f6ec6 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -123,6 +123,7 @@ private:
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
     void           ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const;
+    void           ParseDetailInternalPaths(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
     void           ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElement,
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 4a76b947a..af5e2e278 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -329,6 +329,7 @@
                                                                                  <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
                                                                                  <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
                                                                                  <xs:attribute name="name" type="xs:string"></xs:attribute>
+                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
                                                                            </xs:complexType>
                                                                      </xs:element>
                                                                      <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">
@@ -451,6 +452,17 @@
 																						 </xs:sequence>
 																					 </xs:complexType>
 																				</xs:element>
+																				<xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+																					<xs:complexType>
+																						<xs:sequence>
+																						   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+																								   <xs:complexType>
+																										 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
+																								   </xs:complexType>
+																							 </xs:element>
+																						 </xs:sequence>
+																					 </xs:complexType>
+																				</xs:element>
                                                                            </xs:sequence>
                                                                            <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
                                                                            <xs:attribute name="version" type="pieceVersion"></xs:attribute>
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 2d32a4be8..469e31daa 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -269,6 +269,18 @@ void VPiece::SetUnited(bool united)
     d->m_united = united;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VPiece::GetInternalPaths() const
+{
+    return d->m_internalPaths;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetInternalPaths(const QVector<quint32> &iPaths)
+{
+    d->m_internalPaths = iPaths;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<CustomSARecord> VPiece::GetCustomSARecords() const
 {
@@ -324,6 +336,37 @@ QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
     return r;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VPiece::MissingInternalPaths(const VPiece &det) const
+{
+    const QVector<quint32> detRecords = det.GetInternalPaths();
+    if (d->m_internalPaths.size() == detRecords.size()) //-V807
+    {
+        return QVector<quint32>();
+    }
+
+    QSet<quint32> set1;
+    for (qint32 i = 0; i < d->m_internalPaths.size(); ++i)
+    {
+        set1.insert(d->m_internalPaths.at(i));
+    }
+
+    QSet<quint32> set2;
+    for (qint32 j = 0; j < detRecords.size(); ++j)
+    {
+        set2.insert(detRecords.at(j));
+    }
+
+    const QList<quint32> set3 = set1.subtract(set2).toList();
+    QVector<quint32> r;
+    for (qint32 i = 0; i < set3.size(); ++i)
+    {
+        r.append(set3.at(i));
+    }
+
+    return r;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<CustomSARecord> VPiece::GetValidRecords() const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 6e4a842eb..6a65dee2e 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -76,11 +76,15 @@ public:
     bool IsUnited() const;
     void SetUnited(bool united);
 
+    QVector<quint32> GetInternalPaths() const;
+    void             SetInternalPaths(const QVector<quint32> &iPaths);
+
     QVector<CustomSARecord> GetCustomSARecords() const;
     void                    SetCustomSARecords(const QVector<CustomSARecord> &records);
 
     QVector<quint32> MissingNodes(const VPiece &det) const;
     QVector<quint32> MissingCSAPath(const VPiece &det) const;
+    QVector<quint32> MissingInternalPaths(const VPiece &det) const;
 
 private:
     QSharedDataPointer<VPieceData> d;
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 2b9a8c961..fcfc7e01b 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -49,7 +49,8 @@ public:
           m_my(0),
           m_inLayout(true),
           m_united(false),
-          m_customSARecords()
+          m_customSARecords(),
+          m_internalPaths()
     {}
 
     VPieceData(const VPieceData &detail)
@@ -59,7 +60,8 @@ public:
           m_my(detail.m_my),
           m_inLayout(detail.m_inLayout),
           m_united(detail.m_united),
-          m_customSARecords(detail.m_customSARecords)
+          m_customSARecords(detail.m_customSARecords),
+          m_internalPaths(detail.m_internalPaths)
     {}
 
     ~VPieceData();
@@ -74,6 +76,7 @@ public:
     bool m_united;
 
     QVector<CustomSARecord> m_customSARecords;
+    QVector<quint32>        m_internalPaths;
 
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index cbaa5061a..3e9718b76 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -130,6 +130,18 @@ void VPiecePath::SetName(const QString &name)
     d->m_name = name;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+Qt::PenStyle VPiecePath::GetPenType() const
+{
+    return d->m_penType;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiecePath::SetPenType(const Qt::PenStyle &type)
+{
+    d->m_penType = type;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
 {
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 783166eac..1f3dbf901 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -68,6 +68,9 @@ public:
     QString GetName() const;
     void    SetName(const QString &name);
 
+    Qt::PenStyle GetPenType() const;
+    void         SetPenType(const Qt::PenStyle &type);
+
     QVector<QPointF>  PathPoints(const VContainer *data) const;
     QVector<VPointF>  PathNodePoints(const VContainer *data) const;
     QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const;
diff --git a/src/libs/vpatterndb/vpiecepath_p.h b/src/libs/vpatterndb/vpiecepath_p.h
index 77bcfdf85..1ad364ce9 100644
--- a/src/libs/vpatterndb/vpiecepath_p.h
+++ b/src/libs/vpatterndb/vpiecepath_p.h
@@ -44,20 +44,23 @@ public:
     VPiecePathData()
         : m_nodes(),
           m_type(PiecePathType::Unknown),
-          m_name()
+          m_name(),
+          m_penType(Qt::SolidLine)
     {}
 
     explicit VPiecePathData(PiecePathType type)
         : m_nodes(),
           m_type(type),
-          m_name()
+          m_name(),
+          m_penType(Qt::SolidLine)
     {}
 
     VPiecePathData(const VPiecePathData &path)
         : QSharedData(path),
           m_nodes(path.m_nodes),
           m_type(path.m_type),
-          m_name(path.m_name)
+          m_name(path.m_name),
+          m_penType(path.m_penType)
     {}
 
     ~VPiecePathData();
@@ -65,6 +68,7 @@ public:
     QVector<VPieceNode> m_nodes;
     PiecePathType m_type;
     QString m_name;
+    Qt::PenStyle m_penType;
 
 private:
     VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 4316fb2cd..ed8d41b2b 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -30,6 +30,7 @@
 #include "ui_dialogpiecepath.h"
 #include "../vpatterndb/vpiecenode.h"
 #include "visualization/path/vistoolpiecepath.h"
+#include "../../tools/vabstracttool.h"
 
 #include <QMenu>
 
@@ -46,11 +47,17 @@ DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget
     ui->lineEditName->setClearButtonEnabled(true);
 #endif
 
+    FillComboBoxTypeLine(ui->comboBoxPenType, VAbstractTool::LineStylesPics());
+
     connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
 
     InitPathTypes();
     connect(ui->comboBoxType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
-            [this](){ValidObjects(PathIsValid());});
+            [this]()
+    {
+        ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath);
+        ValidObjects(PathIsValid());
+    });
 
     flagName = true;//We have default name of piece.
     flagError = PathIsValid();
@@ -376,7 +383,9 @@ void DialogPiecePath::ChangedSAAfter(double d)
 void DialogPiecePath::InitPathTypes()
 {
     ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CustomSeamAllowance));
-    //ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
+    ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
+
+    ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -468,6 +477,7 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
     VisToolPiecePath *visPath = qobject_cast<VisToolPiecePath *>(vis);
     SCASSERT(visPath != nullptr);
     visPath->SetPath(path);
+    SetPenType(path.GetPenType());
 
     ValidObjects(PathIsValid());
 
@@ -495,6 +505,21 @@ void DialogPiecePath::SetType(PiecePathType type)
     {
         ui->comboBoxType->setCurrentIndex(index);
     }
+
+    ui->comboBoxPenType->setEnabled(type == PiecePathType::InternalPath);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+Qt::PenStyle DialogPiecePath::GetPenType() const
+{
+    return VAbstractTool::LineStyleToPenStyle(GetComboBoxCurrentData(ui->comboBoxPenType, TypeLineLine));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetPenType(const Qt::PenStyle &type)
+{
+    ChangeCurrentData(ui->comboBoxPenType, VAbstractTool::PenStyleToLineStyle(type));
+    vis->setLineStyle(type);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -635,6 +660,7 @@ VPiecePath DialogPiecePath::CreatePath() const
 
     path.SetType(GetType());
     path.SetName(ui->lineEditName->text());
+    path.SetPenType(GetType() == PiecePathType::InternalPath ? GetPenType() : Qt::SolidLine);
 
     return path;
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 3f30be6a0..75c51429f 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -94,6 +94,9 @@ private:
     PiecePathType GetType() const;
     void          SetType(PiecePathType type);
 
+    Qt::PenStyle GetPenType() const;
+    void         SetPenType(const Qt::PenStyle &type);
+
     QListWidgetItem *GetItemById(quint32 id);
 
     void SetCurrentSABefore(qreal value);
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
index 0c414e4df..6ee68ac25 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
@@ -60,16 +60,39 @@
          <item row="1" column="1">
           <widget class="QComboBox" name="comboBoxType"/>
          </item>
-         <item row="2" column="0">
+         <item row="3" column="0">
           <widget class="QLabel" name="labelPiece">
            <property name="text">
             <string>Piece:</string>
            </property>
           </widget>
          </item>
-         <item row="2" column="1">
+         <item row="3" column="1">
           <widget class="QComboBox" name="comboBoxPiece"/>
          </item>
+         <item row="2" column="0">
+          <widget class="QLabel" name="labelPenType">
+           <property name="text">
+            <string>Type of pen:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QComboBox" name="comboBoxPenType">
+           <property name="minimumSize">
+            <size>
+             <width>80</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>80</width>
+             <height>14</height>
+            </size>
+           </property>
+          </widget>
+         </item>
         </layout>
        </item>
        <item>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 5db25b0e9..f08bcb45b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -106,6 +106,10 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     connect(ui->comboBoxIncludeType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::CSAIncludeTypeChanged);
 
+    ui->listWidgetInternalPaths->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetInternalPaths, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowInternalPathsContextMenu);
+
     if (not applyAllowed)
     {
         vis = new VisToolPiece(data);
@@ -127,6 +131,7 @@ void DialogSeamAllowance::EnableApply(bool enable)
     bApply->setEnabled(enable);
     applyAllowed = enable;
     ui->tabSeamAllowance->setEnabled(applyAllowed);
+    ui->tabInternalPaths->setEnabled(applyAllowed);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -153,6 +158,13 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
     }
     ui->listWidgetCustomSA->blockSignals(false);
 
+    ui->listWidgetInternalPaths->clear();
+    const QVector<quint32> iPaths = piece.GetInternalPaths();
+    for (int i = 0; i < iPaths.size(); ++i)
+    {
+        NewInternalPath(iPaths.at(i));
+    }
+
     ui->comboBoxStartPoint->blockSignals(true);
     ui->comboBoxStartPoint->clear();
     ui->comboBoxStartPoint->blockSignals(false);
@@ -347,7 +359,7 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
     {
         record.reverse = not record.reverse;
         rowItem->setData(Qt::UserRole, QVariant::fromValue(record));
-        rowItem->setText(GetCustomSARecordName(record));
+        rowItem->setText(GetPathName(record.path, record.reverse));
     }
     else if (selectedAction == actionOption)
     {
@@ -366,6 +378,42 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ShowInternalPathsContextMenu(const QPoint &pos)
+{
+    const int row = ui->listWidgetInternalPaths->currentRow();
+    if (ui->listWidgetInternalPaths->count() == 0 || row == -1 || row >= ui->listWidgetInternalPaths->count())
+    {
+        return;
+    }
+
+    QMenu *menu = new QMenu(this);
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+
+    QListWidgetItem *rowItem = ui->listWidgetInternalPaths->item(row);
+    SCASSERT(rowItem != nullptr);
+    const quint32 pathId = qvariant_cast<quint32>(rowItem->data(Qt::UserRole));
+
+    QAction *actionOption = menu->addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
+
+    QAction *selectedAction = menu->exec(ui->listWidgetInternalPaths->viewport()->mapToGlobal(pos));
+    if (selectedAction == actionDelete)
+    {
+        delete ui->listWidgetInternalPaths->item(row);
+    }
+    else if (selectedAction == actionOption)
+    {
+        auto *dialog = new DialogPiecePath(data, pathId, this);
+        dialog->SetPiecePath(data->GetPiecePath(pathId));
+        dialog->SetPieceId(toolId);
+        dialog->EnbleShowMode(true);
+        m_dialog = dialog;
+        m_dialog->setModal(true);
+        connect(m_dialog.data(), &DialogTool::DialogClosed, this, &DialogSeamAllowance::PathDialogClosed);
+        m_dialog->show();
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ListChanged()
 {
@@ -662,7 +710,8 @@ void DialogSeamAllowance::PathDialogClosed(int result)
                                                                          const_cast<VContainer *>(data),
                                                                          dialogTool->GetToolId());
             qApp->getUndoStack()->push(saveCommand);
-            UpdateCurrentRecord();
+            UpdateCurrentCustomSARecord();
+            UpdateCurrentInternalPathRecord();
         }
         catch (const VExceptionBadId &e)
         {
@@ -691,6 +740,14 @@ VPiece DialogSeamAllowance::CreatePiece() const
     }
     piece.SetCustomSARecords(records);
 
+    QVector<quint32> iPaths;
+    for (qint32 i = 0; i < ui->listWidgetInternalPaths->count(); ++i)
+    {
+        QListWidgetItem *item = ui->listWidgetInternalPaths->item(i);
+        iPaths.append(qvariant_cast<quint32>(item->data(Qt::UserRole)));
+    }
+    piece.SetInternalPaths(iPaths);
+
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
     piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
     piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
@@ -711,7 +768,7 @@ void DialogSeamAllowance::NewCustomSA(const CustomSARecord &record)
 {
     if (record.path > NULL_ID)
     {
-        const QString name = GetCustomSARecordName(record);
+        const QString name = GetPathName(record.path, record.reverse);
 
         QListWidgetItem *item = new QListWidgetItem(name);
         item->setFont(QFont("Times", 12, QFont::Bold));
@@ -722,16 +779,30 @@ void DialogSeamAllowance::NewCustomSA(const CustomSARecord &record)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QString DialogSeamAllowance::GetCustomSARecordName(const CustomSARecord &record) const
+void DialogSeamAllowance::NewInternalPath(quint32 path)
+{
+    if (path > NULL_ID)
+    {
+        const QString name = GetPathName(path);
+
+        QListWidgetItem *item = new QListWidgetItem(name);
+        item->setFont(QFont("Times", 12, QFont::Bold));
+        item->setData(Qt::UserRole, QVariant::fromValue(path));
+        ui->listWidgetInternalPaths->addItem(item);
+        ui->listWidgetInternalPaths->setCurrentRow(ui->listWidgetInternalPaths->count()-1);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetPathName(quint32 path, bool reverse) const
 {
     QString name;
 
-    if (record.path > NULL_ID)
+    if (path > NULL_ID)
     {
-        const VPiecePath path = data->GetPiecePath(record.path);
-        name = path.GetName();
+        name = data->GetPiecePath(path).GetName();
 
-        if (record.reverse)
+        if (reverse)
         {
             name = QLatin1String("- ") + name;
         }
@@ -934,7 +1005,7 @@ void DialogSeamAllowance::InitSAIncludeType()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::UpdateCurrentRecord()
+void DialogSeamAllowance::UpdateCurrentCustomSARecord()
 {
     const int row = ui->listWidgetCustomSA->currentRow();
     if (ui->listWidgetCustomSA->count() == 0 || row == -1)
@@ -945,5 +1016,20 @@ void DialogSeamAllowance::UpdateCurrentRecord()
     QListWidgetItem *item = ui->listWidgetCustomSA->item(row);
     SCASSERT(item != nullptr);
     const CustomSARecord record = qvariant_cast<CustomSARecord>(item->data(Qt::UserRole));
-    item->setText(GetCustomSARecordName(record));
+    item->setText(GetPathName(record.path, record.reverse));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::UpdateCurrentInternalPathRecord()
+{
+    const int row = ui->listWidgetInternalPaths->currentRow();
+    if (ui->listWidgetInternalPaths->count() == 0 || row == -1)
+    {
+        return;
+    }
+
+    QListWidgetItem *item = ui->listWidgetInternalPaths->item(row);
+    SCASSERT(item != nullptr);
+    const quint32 path = qvariant_cast<quint32>(item->data(Qt::UserRole));
+    item->setText(GetPathName(path));
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 4a6b986fc..c761f8d76 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -62,6 +62,8 @@ protected:
 private slots:
     void ShowMainPathContextMenu(const QPoint &pos);
     void ShowCustomSAContextMenu(const QPoint &pos);
+    void ShowInternalPathsContextMenu(const QPoint &pos);
+
     void ListChanged();
     void EnableSeamAllowance(bool enable);
     void NodeChanged(int index);
@@ -90,14 +92,16 @@ private:
 
     void    NewMainPathItem(const VPieceNode &node);
     void    NewCustomSA(const CustomSARecord &record);
-    QString GetCustomSARecordName(const CustomSARecord &record) const;
+    void    NewInternalPath(quint32 path);
+    QString GetPathName(quint32 path, bool reverse = false) const;
     bool    MainPathIsValid() const;
     void    ValidObjects(bool value);
     bool    MainPathIsClockwise() const;
     void    InitNodesList();
     void    InitCSAPoint(QComboBox *box);
     void    InitSAIncludeType();
-    void    UpdateCurrentRecord();
+    void    UpdateCurrentCustomSARecord();
+    void    UpdateCurrentInternalPathRecord();
 
     QListWidgetItem *GetItemById(quint32 id);
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 047a79a7b..75ff3623e 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -385,6 +385,20 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tabInternalPaths">
+      <attribute name="title">
+       <string>Internal paths</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_6">
+       <item>
+        <widget class="QListWidget" name="listWidgetInternalPaths">
+         <property name="dragDropMode">
+          <enum>QAbstractItemView::InternalMove</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index 48c804129..54fc53749 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -173,6 +173,7 @@ void VToolPiecePath::AddAttributes(VAbstractPattern *doc, QDomElement &domElemen
     doc->SetAttribute(domElement, VDomDocument::AttrId, id);
     doc->SetAttribute(domElement, AttrName, path.GetName());
     doc->SetAttribute(domElement, AttrType, static_cast<int>(path.GetType()));
+    doc->SetAttribute(domElement, AttrTypeLine, PenStyleToLineStyle(path.GetPenType()));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -219,7 +220,9 @@ void VToolPiecePath::AddToFile()
 
     if (path.GetType() == PiecePathType::InternalPath)
     {
-
+        QVector<quint32> iPaths = newDet.GetInternalPaths();
+        iPaths.append(id);
+        newDet.SetInternalPaths(iPaths);
     }
     else if (path.GetType() == PiecePathType::CustomSeamAllowance)
     {
@@ -287,7 +290,11 @@ void VToolPiecePath::RefreshGeometry()
     {
         QPainterPath p = path.PainterPath(this->getData());
         p.setFillRule(Qt::OddEvenFill);
+
         this->setPath(p);
+        QPen pen = this->pen();
+        pen.setStyle(path.GetPenType());
+        this->setPen(pen);
     }
 }
 
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index 556e0a77d..a1f59c1fa 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -197,6 +197,35 @@ Qt::PenStyle VAbstractTool::LineStyleToPenStyle(const QString &typeLine)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QString VAbstractTool::PenStyleToLineStyle(Qt::PenStyle penStyle)
+{
+    QT_WARNING_PUSH
+    QT_WARNING_DISABLE_GCC("-Wswitch-default")
+
+    switch (penStyle)
+    {
+        case Qt::NoPen:
+            return TypeLineNone;
+        case Qt::DashLine:
+            return TypeLineDashLine;
+        case Qt::DotLine:
+            return TypeLineDotLine;
+        case Qt::DashDotLine:
+            return TypeLineDashDotLine;
+        case Qt::DashDotDotLine:
+            return TypeLineDashDotDotLine;
+        case Qt::SolidLine:
+        case Qt::CustomDashLine:
+        default:
+            break;
+    }
+
+    QT_WARNING_POP
+
+    return TypeLineLine;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QMap<QString, QIcon> VAbstractTool::LineStylesPics()
 {
diff --git a/src/libs/vtools/tools/vabstracttool.h b/src/libs/vtools/tools/vabstracttool.h
index 3bc0187b7..17ccf8b69 100644
--- a/src/libs/vtools/tools/vabstracttool.h
+++ b/src/libs/vtools/tools/vabstracttool.h
@@ -75,6 +75,7 @@ public:
 
     static const QStringList    StylesList();
     static Qt::PenStyle         LineStyleToPenStyle(const QString &typeLine);
+    static QString              PenStyleToLineStyle(Qt::PenStyle penStyle);
     static QMap<QString, QIcon> LineStylesPics();
 
     static const QStringList      Colors();
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 66f580c41..1dea63415 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -34,6 +34,7 @@
 #include "nodeDetails/vnodepoint.h"
 #include "nodeDetails/vnodespline.h"
 #include "nodeDetails/vnodesplinepath.h"
+#include "nodeDetails/vtoolpiecepath.h"
 #include "../vgeometry/varc.h"
 #include "../vgeometry/vcubicbezier.h"
 #include "../vgeometry/vcubicbezierpath.h"
@@ -59,6 +60,7 @@ const quint8 VToolSeamAllowance::pieceVersion = 2;
 
 const QString VToolSeamAllowance::TagCSA     = QStringLiteral("csa");
 const QString VToolSeamAllowance::TagRecord  = QStringLiteral("record");
+const QString VToolSeamAllowance::TagIPaths  = QStringLiteral("iPaths");
 
 const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
@@ -263,6 +265,22 @@ void VToolSeamAllowance::AddCSARecords(VAbstractPattern *doc, QDomElement &domEl
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::AddInternalPaths(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &paths)
+{
+    if (paths.size() > 0)
+    {
+        QDomElement iPathsElement = doc->createElement(VToolSeamAllowance::TagIPaths);
+        for (int i = 0; i < paths.size(); ++i)
+        {
+            QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord);
+            doc->SetAttribute(recordNode, AttrPath, paths.at(i));
+            iPathsElement.appendChild(recordNode);
+        }
+        domElement.appendChild(iPathsElement);
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
@@ -362,6 +380,7 @@ void VToolSeamAllowance::AddToFile()
     AddNodes(doc, domElement, piece);
     //custom seam allowance
     AddCSARecords(doc, domElement, piece.GetCustomSARecords());
+    AddInternalPaths(doc, domElement, piece.GetInternalPaths());
 
     AddPiece *addDet = new AddPiece(domElement, doc, piece, m_drawName);
     connect(addDet, &AddPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
@@ -393,6 +412,7 @@ void VToolSeamAllowance::RefreshDataInFile()
                 AddGrainline(doc, domElement, piece);
                 AddNodes(doc, domElement, piece);
                 AddCSARecords(doc, domElement, piece.GetCustomSARecords());
+                AddInternalPaths(doc, domElement, piece.GetInternalPaths());
             }
         }
     }
@@ -637,6 +657,7 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
     VPiece detail = data->GetPiece(id);
     InitNodes(detail, scene);
     InitCSAPaths(detail);
+    InitInternalPaths(detail);
     this->setFlag(QGraphicsItem::ItemIsMovable, true);
     this->setFlag(QGraphicsItem::ItemIsSelectable, true);
     RefreshGeometry();
@@ -737,6 +758,22 @@ void VToolSeamAllowance::InitCSAPaths(const VPiece &detail)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::InitInternalPaths(const VPiece &detail)
+{
+    QVector<quint32> records = detail.GetInternalPaths();
+    for (int i = 0; i < records.size(); ++i)
+    {
+        QHash<quint32, VDataTool*>* tools = doc->getTools();
+        SCASSERT(tools != nullptr);
+        VToolPiecePath *tool = qobject_cast<VToolPiecePath*>(tools->value(records.at(i)));
+        SCASSERT(tool != nullptr);
+        tool->setParentItem(this);
+        tool->SetParentType(ParentType::Item);
+        doc->IncrementReferens(records.at(i));
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::DeleteTool(bool ask)
 {
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 03a53157d..3750b0823 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -56,6 +56,7 @@ public:
 
     static const QString TagCSA;
     static const QString TagRecord;
+    static const QString TagIPaths;
 
     static const QString AttrVersion;
     static const QString AttrForbidFlipping;
@@ -74,6 +75,7 @@ public:
     static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece);
     static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record);
     static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector<CustomSARecord> &records);
+    static void AddInternalPaths(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &paths);
     static void AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
@@ -131,6 +133,7 @@ private:
 
     void InitNodes(const VPiece &detail, VMainGraphicsScene *scene);
     void InitCSAPaths(const VPiece &detail);
+    void InitInternalPaths(const VPiece &detail);
 
     template <typename Tool>
     Tool*              InitTool(VMainGraphicsScene *scene, quint32 toolId);
diff --git a/src/libs/vtools/undocommands/addpiece.cpp b/src/libs/vtools/undocommands/addpiece.cpp
index c27b9e250..9f4ccc2ff 100644
--- a/src/libs/vtools/undocommands/addpiece.cpp
+++ b/src/libs/vtools/undocommands/addpiece.cpp
@@ -64,6 +64,7 @@ void AddPiece::undo()
 
             DecrementReferences(m_detail.GetPath().GetNodes());
             DecrementReferences(m_detail.GetCustomSARecords());
+            DecrementReferences(m_detail.GetInternalPaths());
         }
         else
         {
diff --git a/src/libs/vtools/undocommands/deletepiece.cpp b/src/libs/vtools/undocommands/deletepiece.cpp
index 6fb5fd5bf..d75e879a0 100644
--- a/src/libs/vtools/undocommands/deletepiece.cpp
+++ b/src/libs/vtools/undocommands/deletepiece.cpp
@@ -108,6 +108,7 @@ void DeletePiece::redo()
 
         DecrementReferences(m_detail.GetPath().GetNodes());
         DecrementReferences(m_detail.GetCustomSARecords());
+        DecrementReferences(m_detail.GetInternalPaths());
         emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
     }
     else
diff --git a/src/libs/vtools/undocommands/savepieceoptions.cpp b/src/libs/vtools/undocommands/savepieceoptions.cpp
index 92759370e..daeef8aab 100644
--- a/src/libs/vtools/undocommands/savepieceoptions.cpp
+++ b/src/libs/vtools/undocommands/savepieceoptions.cpp
@@ -77,9 +77,11 @@ void SavePieceOptions::undo()
         VToolSeamAllowance::AddGrainline(doc, domElement, m_oldDet);
         VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
+        VToolSeamAllowance::AddInternalPaths(doc, domElement, m_oldDet.GetInternalPaths());
 
         IncrementReferences(m_oldDet.MissingNodes(m_newDet));
         IncrementReferences(m_oldDet.MissingCSAPath(m_newDet));
+        IncrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
         emit NeedLiteParsing(Document::LiteParse);
     }
     else
@@ -104,9 +106,11 @@ void SavePieceOptions::redo()
         VToolSeamAllowance::AddGrainline(doc, domElement, m_newDet);
         VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
         VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
+        VToolSeamAllowance::AddInternalPaths(doc, domElement, m_newDet.GetInternalPaths());
 
         DecrementReferences(m_oldDet.MissingNodes(m_newDet));
         DecrementReferences(m_oldDet.MissingCSAPath(m_newDet));
+        DecrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
 
         emit NeedLiteParsing(Document::LiteParse);
     }

From 641a807f2430110ae01806b1083b667aa8aa5fb9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 18:44:24 +0200
Subject: [PATCH 131/208] Fix VToolPiecePath visualization.

--HG--
branch : feature
---
 src/libs/ifc/xml/vabstractpattern.cpp         | 13 +++++++---
 src/libs/ifc/xml/vabstractpattern.h           | 23 +++++------------
 .../vtools/dialogs/tools/dialogpiecepath.cpp  |  7 ++++++
 src/libs/vtools/tools/vtooldetail.cpp         |  4 +--
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  8 ++----
 src/libs/vtools/tools/vtooluniondetails.cpp   | 25 ++++++++-----------
 src/libs/vtools/undocommands/deletedetail.cpp |  4 +--
 src/libs/vtools/undocommands/deletepiece.cpp  |  4 +--
 8 files changed, 38 insertions(+), 50 deletions(-)

diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index e2a7b692e..b814b0292 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -169,10 +169,17 @@ const QString VAbstractPattern::NodePoint      = QStringLiteral("NodePoint");
 const QString VAbstractPattern::NodeSpline     = QStringLiteral("NodeSpline");
 const QString VAbstractPattern::NodeSplinePath = QStringLiteral("NodeSplinePath");
 
+QHash<quint32, VDataTool*> VAbstractPattern::tools = QHash<quint32, VDataTool*>();
+
 //---------------------------------------------------------------------------------------------------------------------
 VAbstractPattern::VAbstractPattern(QObject *parent)
-    : QObject(parent), VDomDocument(), nameActivPP(QString()), cursor(0), tools(QHash<quint32, VDataTool*>()),
-      toolsOnRemove(QVector<VDataTool*>()), history(QVector<VToolRecord>()), patternPieces(QStringList()),
+    : QObject(parent),
+      VDomDocument(),
+      nameActivPP(QString()),
+      cursor(0),
+      toolsOnRemove(QVector<VDataTool*>()),
+      history(QVector<VToolRecord>()),
+      patternPieces(QStringList()),
       modified(false)
 {}
 
@@ -1264,7 +1271,7 @@ void VAbstractPattern::SelectedDetail(quint32 id)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VAbstractPattern::ToolExists(const quint32 &id) const
+void VAbstractPattern::ToolExists(const quint32 &id)
 {
     if (tools.contains(id) == false)
     {
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index 8ff0a8c61..cc9f21899 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -90,9 +90,8 @@ public:
 
     virtual void   UpdateToolData(const quint32 &id, VContainer *data)=0;
 
-    QHash<quint32, VDataTool *> *getTools();
-    VDataTool     *getTool(const quint32 &id);
-    void           AddTool(const quint32 &id, VDataTool *tool);
+    static VDataTool* getTool(const quint32 &id);
+    static void       AddTool(const quint32 &id, VDataTool *tool);
 
     void           AddToolOnRemove(VDataTool *tool);
 
@@ -329,9 +328,6 @@ protected:
     /** @brief cursor cursor keep id tool after which we will add new tool in file. */
     quint32        cursor;
 
-    /** @brief tools list with pointer on tools. */
-    QHash<quint32, VDataTool*> tools;
-
     QVector<VDataTool*> toolsOnRemove;
 
     /** @brief history history records. */
@@ -343,7 +339,10 @@ protected:
     /** @brief modified keep state of the document for cases that do not cover QUndoStack*/
     mutable bool   modified;
 
-    void           ToolExists(const quint32 &id) const;
+    /** @brief tools list with pointer on tools. */
+    static QHash<quint32, VDataTool*> tools;
+
+    static void    ToolExists(const quint32 &id);
 
     void           SetActivPP(const QString& name);
 
@@ -374,14 +373,4 @@ private:
 
 };
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getTools return list of tools pointers.
- * @return list.
- */
-inline QHash<quint32, VDataTool *> *VAbstractPattern::getTools()
-{
-    return &tools;
-}
-
 #endif // VABSTRACTPATTERN_H
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index ed8d41b2b..9e08bdd31 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -31,6 +31,7 @@
 #include "../vpatterndb/vpiecenode.h"
 #include "visualization/path/vistoolpiecepath.h"
 #include "../../tools/vabstracttool.h"
+#include "../../tools/vtoolseamallowance.h"
 
 #include <QMenu>
 
@@ -210,6 +211,12 @@ void DialogPiecePath::CheckState()
 void DialogPiecePath::ShowVisualization()
 {
     AddVisualization<VisToolPiecePath>();
+
+    VToolSeamAllowance *tool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(GetPieceId()));
+    SCASSERT(tool != nullptr);
+    auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+    SCASSERT(visPath != nullptr);
+    visPath->setParentItem(tool);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp
index 42b8f9afa..35ba30b6b 100644
--- a/src/libs/vtools/tools/vtooldetail.cpp
+++ b/src/libs/vtools/tools/vtooldetail.cpp
@@ -1239,9 +1239,7 @@ template <typename Tool>
 //cppcheck-suppress unusedFunction
 Tool* VToolDetail::InitTool(VMainGraphicsScene *scene, const VNodeDetail &node)
 {
-    QHash<quint32, VDataTool*>* tools = doc->getTools();
-    SCASSERT(tools != nullptr);
-    Tool *tool = qobject_cast<Tool*>(tools->value(node.getId()));
+    Tool *tool = qobject_cast<Tool*>(doc->getTool(node.getId()));
     SCASSERT(tool != nullptr);
     connect(tool, &Tool::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
     tool->setParentItem(this);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 1dea63415..d721844eb 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -764,9 +764,7 @@ void VToolSeamAllowance::InitInternalPaths(const VPiece &detail)
     QVector<quint32> records = detail.GetInternalPaths();
     for (int i = 0; i < records.size(); ++i)
     {
-        QHash<quint32, VDataTool*>* tools = doc->getTools();
-        SCASSERT(tools != nullptr);
-        VToolPiecePath *tool = qobject_cast<VToolPiecePath*>(tools->value(records.at(i)));
+        VToolPiecePath *tool = qobject_cast<VToolPiecePath*>(doc->getTool(records.at(i)));
         SCASSERT(tool != nullptr);
         tool->setParentItem(this);
         tool->SetParentType(ParentType::Item);
@@ -819,9 +817,7 @@ template <typename Tool>
  */
 Tool *VToolSeamAllowance::InitTool(VMainGraphicsScene *scene, quint32 toolId)
 {
-    QHash<quint32, VDataTool*>* tools = doc->getTools();
-    SCASSERT(tools != nullptr);
-    Tool *tool = qobject_cast<Tool*>(tools->value(toolId));
+    Tool *tool = qobject_cast<Tool*>(doc->getTool(toolId));
     SCASSERT(tool != nullptr);
     connect(tool, &Tool::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
     tool->setParentItem(this);
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index 6002152eb..7b35d040b 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -647,24 +647,19 @@ VToolUnionDetails* VToolUnionDetails::Create(const quint32 _id, const VDetail &d
         newDetail.setMx(d1.getMx());
         newDetail.setMy(d1.getMy());
         VToolDetail::Create(0, newDetail, scene, doc, data, parse, Source::FromTool, drawName);
-        QHash<quint32, VDataTool*>* tools = doc->getTools();
-        SCASSERT(tools != nullptr);
+
+        auto RemoveDetail = [doc](quint32 id)
+        {
+            VToolDetail *toolDet = qobject_cast<VToolDetail*>(doc->getTool(id));
+            SCASSERT(toolDet != nullptr);
+            bool ask = false;
+            toolDet->Remove(ask);
+        };
 
         if (not retainPieces)
         {
-            {
-                VToolDetail *toolDet = qobject_cast<VToolDetail*>(tools->value(d1id));
-                SCASSERT(toolDet != nullptr);
-                bool ask = false;
-                toolDet->Remove(ask);
-            }
-
-            {
-                VToolDetail *toolDet = qobject_cast<VToolDetail*>(tools->value(d2id));
-                SCASSERT(toolDet != nullptr);
-                const bool ask = false;
-                toolDet->Remove(ask);
-            }
+            RemoveDetail(d1id);
+            RemoveDetail(d2id);
         }
 
         SCASSERT(not children.isEmpty())
diff --git a/src/libs/vtools/undocommands/deletedetail.cpp b/src/libs/vtools/undocommands/deletedetail.cpp
index 50140d16a..b6eff7437 100644
--- a/src/libs/vtools/undocommands/deletedetail.cpp
+++ b/src/libs/vtools/undocommands/deletedetail.cpp
@@ -96,9 +96,7 @@ void DeleteDetail::redo()
 
         // UnionDetails delete two old details and create one new.
         // So when UnionDetail delete detail we can't use FullParsing. So we hide detail on scene directly.
-        QHash<quint32, VDataTool*>* tools = doc->getTools();
-        SCASSERT(tools != nullptr);
-        VToolDetail *toolDet = qobject_cast<VToolDetail*>(tools->value(nodeId));
+        VToolDetail *toolDet = qobject_cast<VToolDetail*>(doc->getTool(nodeId));
         SCASSERT(toolDet != nullptr);
         toolDet->hide();
 
diff --git a/src/libs/vtools/undocommands/deletepiece.cpp b/src/libs/vtools/undocommands/deletepiece.cpp
index d75e879a0..fba723c2f 100644
--- a/src/libs/vtools/undocommands/deletepiece.cpp
+++ b/src/libs/vtools/undocommands/deletepiece.cpp
@@ -100,9 +100,7 @@ void DeletePiece::redo()
 
         // UnionDetails delete two old details and create one new.
         // So when UnionDetail delete detail we can't use FullParsing. So we hide detail on scene directly.
-        QHash<quint32, VDataTool*>* tools = doc->getTools();
-        SCASSERT(tools != nullptr);
-        VToolSeamAllowance *toolDet = qobject_cast<VToolSeamAllowance*>(tools->value(nodeId));
+        VToolSeamAllowance *toolDet = qobject_cast<VToolSeamAllowance*>(doc->getTool(nodeId));
         SCASSERT(toolDet != nullptr);
         toolDet->hide();
 

From ffa241ea0d7ec48cde3eadf19a64bd478e25c16f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 18:51:36 +0200
Subject: [PATCH 132/208] Removed brush for main path.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 11 +++++------
 src/libs/vtools/tools/vtoolseamallowance.h   |  3 ++-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index d721844eb..b3d052731 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -488,14 +488,14 @@ QVariant VToolSeamAllowance::itemChange(QGraphicsItem::GraphicsItemChange change
         }
     }
 
-    return VNoBrushScalePathItem::itemChange(change, value);
+    return QGraphicsPathItem::itemChange(change, value);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
     // Special for not selectable item first need to call standard mousePressEvent then accept event
-    VNoBrushScalePathItem::mousePressEvent(event);
+    QGraphicsPathItem::mousePressEvent(event);
 
     // Somehow clicking on notselectable object do not clean previous selections.
     if (not (flags() & ItemIsSelectable) && scene())
@@ -528,7 +528,7 @@ void VToolSeamAllowance::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
         //Disable cursor-arrow-closehand
         RestoreOverrideCursor(cursorArrowCloseHand);
     }
-    VNoBrushScalePathItem::mouseReleaseEvent(event);
+    QGraphicsPathItem::mouseReleaseEvent(event);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -630,7 +630,7 @@ void VToolSeamAllowance::keyReleaseEvent(QKeyEvent *event)
             break;
     }
 
-    VNoBrushScalePathItem::keyReleaseEvent ( event );
+    QGraphicsPathItem::keyReleaseEvent ( event );
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -648,7 +648,7 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
                                        const Source &typeCreation, VMainGraphicsScene *scene,
                                        const QString &drawName, QGraphicsItem *parent)
     : VAbstractTool(doc, data, id),
-      VNoBrushScalePathItem(parent),
+      QGraphicsPathItem(parent),
       m_dialog(),
       m_sceneDetails(scene),
       m_drawName(drawName),
@@ -662,7 +662,6 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
     this->setFlag(QGraphicsItem::ItemIsSelectable, true);
     RefreshGeometry();
 
-    this->setBrush(QBrush(Qt::Dense7Pattern));
     m_seamAllowance->setBrush(QBrush(Qt::FDiagPattern));
 
     this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 3750b0823..e23ef708e 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -32,6 +32,7 @@
 #include <QtGlobal>
 #include <qcompilerdetection.h>
 #include <QObject>
+#include <QGraphicsPathItem>
 
 #include "../vwidgets/vnobrushscalepathitem.h"
 #include "vabstracttool.h"
@@ -40,7 +41,7 @@ class VMainGraphicsScene;
 class DialogTool;
 class VPiece;
 
-class VToolSeamAllowance : public VAbstractTool, public VNoBrushScalePathItem
+class VToolSeamAllowance : public VAbstractTool, public QGraphicsPathItem
 {
     Q_OBJECT
 public:

From 0d1179a451a8f83bb8021ca19243d4e45a30a4cd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 18:53:09 +0200
Subject: [PATCH 133/208] Allow delete object when creating a main path.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index f08bcb45b..192e709b2 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -297,7 +297,6 @@ void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
 
     QMenu *menu = new QMenu(this);
     QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
-    actionDelete->setEnabled(applyAllowed);//Because we can't undo this operation when creating a piece.
 
     QListWidgetItem *rowItem = ui->listWidgetMainPath->item(row);
     SCASSERT(rowItem != nullptr);

From 0a11ec59fb75987561c63bd90c8a70ce5d9f3ad3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 18:57:43 +0200
Subject: [PATCH 134/208] Show Delete option last in a context menu.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp      | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 192e709b2..7a9b62e7b 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -296,7 +296,6 @@ void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
     }
 
     QMenu *menu = new QMenu(this);
-    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
 
     QListWidgetItem *rowItem = ui->listWidgetMainPath->item(row);
     SCASSERT(rowItem != nullptr);
@@ -310,6 +309,8 @@ void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
         actionReverse->setChecked(rowNode.GetReverse());
     }
 
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+
     QAction *selectedAction = menu->exec(ui->listWidgetMainPath->viewport()->mapToGlobal(pos));
     if (selectedAction == actionDelete)
     {
@@ -337,7 +338,7 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
     }
 
     QMenu *menu = new QMenu(this);
-    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+    QAction *actionOption = menu->addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
 
     QListWidgetItem *rowItem = ui->listWidgetCustomSA->item(row);
     SCASSERT(rowItem != nullptr);
@@ -347,7 +348,7 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
     actionReverse->setCheckable(true);
     actionReverse->setChecked(record.reverse);
 
-    QAction *actionOption = menu->addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
 
     QAction *selectedAction = menu->exec(ui->listWidgetCustomSA->viewport()->mapToGlobal(pos));
     if (selectedAction == actionDelete)
@@ -387,13 +388,8 @@ void DialogSeamAllowance::ShowInternalPathsContextMenu(const QPoint &pos)
     }
 
     QMenu *menu = new QMenu(this);
-    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
-
-    QListWidgetItem *rowItem = ui->listWidgetInternalPaths->item(row);
-    SCASSERT(rowItem != nullptr);
-    const quint32 pathId = qvariant_cast<quint32>(rowItem->data(Qt::UserRole));
-
     QAction *actionOption = menu->addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
 
     QAction *selectedAction = menu->exec(ui->listWidgetInternalPaths->viewport()->mapToGlobal(pos));
     if (selectedAction == actionDelete)
@@ -402,6 +398,10 @@ void DialogSeamAllowance::ShowInternalPathsContextMenu(const QPoint &pos)
     }
     else if (selectedAction == actionOption)
     {
+        QListWidgetItem *rowItem = ui->listWidgetInternalPaths->item(row);
+        SCASSERT(rowItem != nullptr);
+        const quint32 pathId = qvariant_cast<quint32>(rowItem->data(Qt::UserRole));
+
         auto *dialog = new DialogPiecePath(data, pathId, this);
         dialog->SetPiecePath(data->GetPiecePath(pathId));
         dialog->SetPieceId(toolId);

From c2da41bbf029a0dfdd2d46e7b411061ac6028800 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 19:18:58 +0200
Subject: [PATCH 135/208] Undo selection of last object if was selected twice.

--HG--
branch : feature
---
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 73 ++++++++++++++-----
 .../vtools/dialogs/tools/dialogpiecepath.h    |  2 +
 .../dialogs/tools/dialogseamallowance.cpp     | 73 ++++++++++++++-----
 .../dialogs/tools/dialogseamallowance.h       |  2 +
 4 files changed, 110 insertions(+), 40 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 9e08bdd31..fb3690b68 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -127,26 +127,36 @@ void DialogPiecePath::ChosenObject(quint32 id, const SceneObject &type)
         {
             reverse = true;
         }
-        switch (type)
+        if (id != GetLastId())
         {
-            case SceneObject::Arc:
-                NewItem(VPieceNode(id, Tool::NodeArc, reverse));
-                break;
-            case SceneObject::Point:
-                NewItem(VPieceNode(id, Tool::NodePoint));
-                break;
-            case SceneObject::Spline:
-                NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
-                break;
-            case SceneObject::SplinePath:
-                NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
-                break;
-            case (SceneObject::Line):
-            case (SceneObject::Detail):
-            case (SceneObject::Unknown):
-            default:
-                qDebug() << "Got wrong scene object. Ignore.";
-                break;
+            switch (type)
+            {
+                case SceneObject::Arc:
+                    NewItem(VPieceNode(id, Tool::NodeArc, reverse));
+                    break;
+                case SceneObject::Point:
+                    NewItem(VPieceNode(id, Tool::NodePoint));
+                    break;
+                case SceneObject::Spline:
+                    NewItem(VPieceNode(id, Tool::NodeSpline, reverse));
+                    break;
+                case SceneObject::SplinePath:
+                    NewItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+                    break;
+                case (SceneObject::Line):
+                case (SceneObject::Detail):
+                case (SceneObject::Unknown):
+                default:
+                    qDebug() << "Got wrong scene object. Ignore.";
+                    break;
+            }
+        }
+        else
+        {
+            if (ui->listWidget->count() > 1)
+            {
+                delete GetItemById(id);
+            }
         }
 
         ValidObjects(PathIsValid());
@@ -163,7 +173,14 @@ void DialogPiecePath::ChosenObject(quint32 id, const SceneObject &type)
                 emit ToolTip(tr("Select main path objects, <b>Shift</b> - reverse direction curve, "
                                 "<b>Enter</b> - finish creation"));
 
-                visPath->VisualMode(NULL_ID);
+                if (not qApp->getCurrentScene()->items().contains(visPath))
+                {
+                    visPath->VisualMode(NULL_ID);
+                }
+                else
+                {
+                    visPath->RefreshGeometry();
+                }
             }
             else
             {
@@ -545,6 +562,22 @@ QListWidgetItem *DialogPiecePath::GetItemById(quint32 id)
     return nullptr;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 DialogPiecePath::GetLastId() const
+{
+    const int count = ui->listWidget->count();
+    if (count > 0)
+    {
+        QListWidgetItem *item = ui->listWidget->item(count-1);
+        const VPieceNode node = qvariant_cast<VPieceNode>(item->data(Qt::UserRole));
+        return node.GetId();
+    }
+    else
+    {
+        return NULL_ID;
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::SetCurrentSABefore(qreal value)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index 75c51429f..c1f06c163 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -99,6 +99,8 @@ private:
 
     QListWidgetItem *GetItemById(quint32 id);
 
+    quint32 GetLastId() const;
+
     void SetCurrentSABefore(qreal value);
     void SetCurrentSAAfter(qreal value);
 };
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 7a9b62e7b..9407993e9 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -202,26 +202,36 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
         {
             reverse = true;
         }
-        switch (type)
+        if (id != GetLastId())
         {
-            case SceneObject::Arc:
-                NewMainPathItem(VPieceNode(id, Tool::NodeArc, reverse));
-                break;
-            case SceneObject::Point:
-                NewMainPathItem(VPieceNode(id, Tool::NodePoint));
-                break;
-            case SceneObject::Spline:
-                NewMainPathItem(VPieceNode(id, Tool::NodeSpline, reverse));
-                break;
-            case SceneObject::SplinePath:
-                NewMainPathItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
-                break;
-            case (SceneObject::Line):
-            case (SceneObject::Detail):
-            case (SceneObject::Unknown):
-            default:
-                qDebug() << "Got wrong scene object. Ignore.";
-                break;
+            switch (type)
+            {
+                case SceneObject::Arc:
+                    NewMainPathItem(VPieceNode(id, Tool::NodeArc, reverse));
+                    break;
+                case SceneObject::Point:
+                    NewMainPathItem(VPieceNode(id, Tool::NodePoint));
+                    break;
+                case SceneObject::Spline:
+                    NewMainPathItem(VPieceNode(id, Tool::NodeSpline, reverse));
+                    break;
+                case SceneObject::SplinePath:
+                    NewMainPathItem(VPieceNode(id, Tool::NodeSplinePath, reverse));
+                    break;
+                case (SceneObject::Line):
+                case (SceneObject::Detail):
+                case (SceneObject::Unknown):
+                default:
+                    qDebug() << "Got wrong scene object. Ignore.";
+                    break;
+            }
+        }
+        else
+        {
+            if (ui->listWidgetMainPath->count() > 1)
+            {
+                delete GetItemById(id);
+            }
         }
 
         ValidObjects(MainPathIsValid());
@@ -238,7 +248,14 @@ void DialogSeamAllowance::ChosenObject(quint32 id, const SceneObject &type)
                 emit ToolTip(tr("Select main path objects clockwise, <b>Shift</b> - reverse direction curve, "
                                 "<b>Enter</b> - finish creation"));
 
-                visPath->VisualMode(NULL_ID);
+                if (not qApp->getCurrentScene()->items().contains(visPath))
+                {
+                    visPath->VisualMode(NULL_ID);
+                }
+                else
+                {
+                    visPath->RefreshGeometry();
+                }
             }
             else
             {
@@ -925,6 +942,22 @@ QListWidgetItem *DialogSeamAllowance::GetItemById(quint32 id)
     return nullptr;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+quint32 DialogSeamAllowance::GetLastId() const
+{
+    const int count = ui->listWidgetMainPath->count();
+    if (count > 0)
+    {
+        QListWidgetItem *item = ui->listWidgetMainPath->item(count-1);
+        const VPieceNode node = qvariant_cast<VPieceNode>(item->data(Qt::UserRole));
+        return node.GetId();
+    }
+    else
+    {
+        return NULL_ID;
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::SetCurrentSABefore(qreal value)
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index c761f8d76..2890ea3f4 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -105,6 +105,8 @@ private:
 
     QListWidgetItem *GetItemById(quint32 id);
 
+    quint32 GetLastId() const;
+
     void SetCurrentSABefore(qreal value);
     void SetCurrentSAAfter(qreal value);
 };

From 1f96114c0b4680fce2bddd5e29ef74789cd80c78 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 19:47:17 +0200
Subject: [PATCH 136/208] Allow delete object when creating a path.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index fb3690b68..a21fc3587 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -247,7 +247,6 @@ void DialogPiecePath::ShowContextMenu(const QPoint &pos)
 
     QMenu *menu = new QMenu(this);
     QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
-    actionDelete->setEnabled(m_showMode);//Because we can't undo this operation when creating a piece.
 
     QListWidgetItem *rowItem = ui->listWidget->item(row);
     SCASSERT(rowItem != nullptr);

From bf4f9a3c61eb2a8d6a80d550c687bb998ec6d3c9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 3 Dec 2016 19:51:25 +0200
Subject: [PATCH 137/208] Check if option Reverse is available.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp     | 5 +++--
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index a21fc3587..5d039e29a 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -246,7 +246,6 @@ void DialogPiecePath::ShowContextMenu(const QPoint &pos)
     }
 
     QMenu *menu = new QMenu(this);
-    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
 
     QListWidgetItem *rowItem = ui->listWidget->item(row);
     SCASSERT(rowItem != nullptr);
@@ -260,13 +259,15 @@ void DialogPiecePath::ShowContextMenu(const QPoint &pos)
         actionReverse->setChecked(rowNode.GetReverse());
     }
 
+    QAction *actionDelete = menu->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
+
     QAction *selectedAction = menu->exec(ui->listWidget->viewport()->mapToGlobal(pos));
     if (selectedAction == actionDelete)
     {
         delete ui->listWidget->item(row);
         ValidObjects(PathIsValid());
     }
-    else if (selectedAction == actionReverse)
+    else if (rowNode.GetTypeTool() != Tool::NodePoint && selectedAction == actionReverse)
     {
         rowNode.SetReverse(not rowNode.GetReverse());
         rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 9407993e9..8dea602d6 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -334,7 +334,7 @@ void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
         delete ui->listWidgetMainPath->item(row);
         ValidObjects(MainPathIsValid());
     }
-    else if (selectedAction == actionReverse)
+    else if (rowNode.GetTypeTool() != Tool::NodePoint && selectedAction == actionReverse)
     {
         rowNode.SetReverse(not rowNode.GetReverse());
         rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));

From 251a717c6f27f132e8a60471e34dc4baa05be434 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 4 Dec 2016 18:14:43 +0200
Subject: [PATCH 138/208] Broken seam allowance. Fix wrong curve.

--HG--
branch : feature
---
 .../share/collection/MaleShirt/MaleShirt.val  | 292 +++++++++---------
 1 file changed, 146 insertions(+), 146 deletions(-)

diff --git a/src/app/share/collection/MaleShirt/MaleShirt.val b/src/app/share/collection/MaleShirt/MaleShirt.val
index 8fbb0a6f9..1ac2621df 100644
--- a/src/app/share/collection/MaleShirt/MaleShirt.val
+++ b/src/app/share/collection/MaleShirt/MaleShirt.val
@@ -197,54 +197,54 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="440" idObject="55" mx="0.132292" my="0.264583"/>
         </modeling>
         <details>
-            <detail closed="1" id="174" name="Yoke" seamAllowance="1" mx="-8.05221" width="1" my="3.27846" version="1">
+            <detail closed="1" id="174" name="Yoke" seamAllowance="1" mx="-8.05221" width="1" my="3.27846" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="167" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="168" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="169" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="170" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="171" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="172" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="173" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="167"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="168"/>
+                    <node type="NodePoint" idObject="169"/>
+                    <node type="NodePoint" idObject="170"/>
+                    <node type="NodeSpline" reverse="0" idObject="171"/>
+                    <node type="NodePoint" idObject="172"/>
+                    <node type="NodePoint" idObject="173"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="401" name="FrontPanel" seamAllowance="1" mx="-11.0934" width="1" my="6.43098" version="1">
+            <detail closed="1" id="401" name="FrontPanel" seamAllowance="1" mx="-11.0934" width="1" my="6.43098" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="389" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="390" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="391" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="392" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="393" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="394" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="395" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="396" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="397" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="398" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="399" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="400" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="389"/>
+                    <node type="NodePoint" idObject="390"/>
+                    <node type="NodePoint" idObject="391"/>
+                    <node type="NodeSpline" reverse="0" idObject="392"/>
+                    <node type="NodePoint" idObject="393"/>
+                    <node type="NodePoint" idObject="394"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="395"/>
+                    <node type="NodePoint" idObject="396"/>
+                    <node type="NodePoint" idObject="397"/>
+                    <node type="NodePoint" idObject="398"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="399"/>
+                    <node type="NodePoint" idObject="400"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="441" name="BackPanel" seamAllowance="1" mx="-7.55641" width="1" my="6.27021" version="1">
+            <detail closed="1" id="441" name="BackPanel" seamAllowance="1" mx="-7.55641" width="1" my="6.27021" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="422" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="423" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="424" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="425" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="426" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="427" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="428" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="429" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="430" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="431" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="432" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="433" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="434" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="435" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="436" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="437" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="438" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="439" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="440" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="422"/>
+                    <node type="NodePoint" idObject="423"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="424"/>
+                    <node type="NodePoint" idObject="425"/>
+                    <node type="NodePoint" idObject="426"/>
+                    <node type="NodePoint" idObject="427"/>
+                    <node type="NodePoint" idObject="428"/>
+                    <node type="NodePoint" idObject="429"/>
+                    <node type="NodePoint" idObject="430"/>
+                    <node type="NodePoint" idObject="431"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="432"/>
+                    <node type="NodePoint" idObject="433"/>
+                    <node type="NodePoint" idObject="434"/>
+                    <node type="NodePoint" idObject="435"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="436"/>
+                    <node type="NodePoint" idObject="437"/>
+                    <node type="NodeSpline" reverse="0" idObject="438"/>
+                    <node type="NodePoint" idObject="439"/>
+                    <node type="NodePoint" idObject="440"/>
                 </nodes>
             </detail>
         </details>
@@ -316,43 +316,43 @@ Delete layouts which are not needed.</description>
             <spline type="modelingPath" inUse="true" id="331" idObject="312"/>
         </modeling>
         <details>
-            <detail closed="1" id="182" name="Pocket" seamAllowance="1" mx="68.0595" width="1" my="45.4124" version="1">
+            <detail closed="1" id="182" name="Pocket" seamAllowance="1" mx="68.0595" width="1" my="45.4124" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="175" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="176" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="177" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="178" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="179" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="180" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="181" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="175"/>
+                    <node type="NodePoint" idObject="176"/>
+                    <node type="NodePoint" idObject="177"/>
+                    <node type="NodePoint" idObject="178"/>
+                    <node type="NodePoint" idObject="179"/>
+                    <node type="NodePoint" idObject="180"/>
+                    <node type="NodePoint" idObject="181"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="320" name="PocketRound" seamAllowance="1" mx="81.7244" width="1" my="45.8357" version="1">
+            <detail closed="1" id="320" name="PocketRound" seamAllowance="1" mx="81.7244" width="1" my="45.8357" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="314" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="315" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="316" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="317" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="318" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="319" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="314"/>
+                    <node type="NodePoint" idObject="315"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="316"/>
+                    <node type="NodePoint" idObject="317"/>
+                    <node type="NodePoint" idObject="318"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="319"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="326" name="PocketFlap" seamAllowance="1" mx="67.876" width="1" my="32.9628" version="1">
+            <detail closed="1" id="326" name="PocketFlap" seamAllowance="1" mx="67.876" width="1" my="32.9628" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="321" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="322" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="323" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="324" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="325" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="321"/>
+                    <node type="NodePoint" idObject="322"/>
+                    <node type="NodePoint" idObject="323"/>
+                    <node type="NodePoint" idObject="324"/>
+                    <node type="NodePoint" idObject="325"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="332" name="PocketFlapRound" seamAllowance="1" mx="81.7244" width="1" my="32.9627" version="1">
+            <detail closed="1" id="332" name="PocketFlapRound" seamAllowance="1" mx="81.7244" width="1" my="32.9627" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="327" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="328" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="329" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="330" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="331" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="327"/>
+                    <node type="NodePoint" idObject="328"/>
+                    <node type="NodePoint" idObject="329"/>
+                    <node type="NodePoint" idObject="330"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="331"/>
                 </nodes>
             </detail>
         </details>
@@ -407,7 +407,7 @@ Delete layouts which are not needed.</description>
             <line typeLine="hair" id="107" firstPoint="99" secondPoint="96" lineColor="black"/>
             <line typeLine="hair" id="108" firstPoint="98" secondPoint="94" lineColor="black"/>
             <line typeLine="hair" id="109" firstPoint="100" secondPoint="93" lineColor="black"/>
-            <spline type="simpleInteractive" point4="89" angle1="12.2644" angle2="338.776" id="110" color="black" length1="4.83467" length2="0.851297" point1="104"/>
+            <spline type="simpleInteractive" point4="89" angle1="12.2644" angle2="208.953" id="110" color="black" length1="4.83467" length2="0.750071" point1="104"/>
             <spline type="simpleInteractive" point4="100" angle1="164.47" angle2="0" id="111" color="black" length1="2.91869" length2="0" point1="106"/>
             <line typeLine="hair" id="112" firstPoint="96" secondPoint="95" lineColor="black"/>
             <line typeLine="hair" id="113" firstPoint="94" secondPoint="92" lineColor="black"/>
@@ -461,52 +461,52 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="299" idObject="97" mx="-0.222289" my="0.696084"/>
         </modeling>
         <details>
-            <detail closed="1" id="204" name="Collar" seamAllowance="1" mx="27.4551" width="1" my="0.587081" version="1">
+            <detail closed="1" id="204" name="Collar" seamAllowance="1" mx="27.4551" width="1" my="0.587081" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="200" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="201" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="202" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="203" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="200"/>
+                    <node type="NodePoint" idObject="201"/>
+                    <node type="NodePoint" idObject="202"/>
+                    <node type="NodePoint" idObject="203"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="209" name="CuffInterface" seamAllowance="0" mx="26.9909" width="1" my="-8.22145" version="1">
+            <detail closed="1" id="209" name="CuffInterface" seamAllowance="0" mx="26.9909" width="1" my="-8.22145" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="205" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="206" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="207" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="208" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="205"/>
+                    <node type="NodePoint" idObject="206"/>
+                    <node type="NodePoint" idObject="207"/>
+                    <node type="NodePoint" idObject="208"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="217" name="ShortSleeve" seamAllowance="1" mx="-16.9664" width="1" my="-23.4126" version="1">
+            <detail closed="1" id="217" name="ShortSleeve" seamAllowance="1" mx="-16.9664" width="1" my="-23.4126" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="210" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="211" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="212" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="213" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="214" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="215" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="216" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="210"/>
+                    <node type="NodePoint" idObject="211"/>
+                    <node type="NodePoint" idObject="212"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="213"/>
+                    <node type="NodePoint" idObject="214"/>
+                    <node type="NodePoint" idObject="215"/>
+                    <node type="NodePoint" idObject="216"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="300" name="FullSleeve" seamAllowance="1" mx="-16.0896" width="1" my="15.2013" version="1">
+            <detail closed="1" id="300" name="FullSleeve" seamAllowance="1" mx="-16.0896" width="1" my="15.2013" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="283" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="1" idObject="284" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="285" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="286" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="0" idObject="287" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="288" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="289" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="290" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="291" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="292" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="293" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="294" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="295" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="296" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="297" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="298" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="299" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="283"/>
+                    <node type="NodeSpline" reverse="1" idObject="284"/>
+                    <node type="NodePoint" idObject="285"/>
+                    <node type="NodePoint" idObject="286"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="287"/>
+                    <node type="NodePoint" idObject="288"/>
+                    <node type="NodePoint" idObject="289"/>
+                    <node type="NodeSpline" reverse="0" idObject="290"/>
+                    <node type="NodePoint" idObject="291"/>
+                    <node type="NodePoint" idObject="292"/>
+                    <node type="NodePoint" idObject="293"/>
+                    <node type="NodePoint" idObject="294"/>
+                    <node type="NodePoint" idObject="295"/>
+                    <node type="NodePoint" idObject="296"/>
+                    <node type="NodePoint" idObject="297"/>
+                    <node type="NodePoint" idObject="298"/>
+                    <node type="NodePoint" idObject="299"/>
                 </nodes>
             </detail>
         </details>
@@ -565,44 +565,44 @@ Delete layouts which are not needed.</description>
             <spline type="modelingSpline" inUse="true" id="254" idObject="248"/>
         </modeling>
         <details>
-            <detail closed="1" id="224" name="CollarBase" seamAllowance="1" mx="28.4767" width="1" my="21.6501" version="1">
+            <detail closed="1" id="224" name="CollarBase" seamAllowance="1" mx="28.4767" width="1" my="21.6501" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="218" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="219" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="220" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="221" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="1" idObject="222" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="223" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="218"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="219"/>
+                    <node type="NodePoint" idObject="220"/>
+                    <node type="NodePoint" idObject="221"/>
+                    <node type="NodeSpline" reverse="1" idObject="222"/>
+                    <node type="NodePoint" idObject="223"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="231" name="CollarBaseInterface" seamAllowance="0" mx="28.6569" width="1" my="15.2047" version="1">
+            <detail closed="1" id="231" name="CollarBaseInterface" seamAllowance="0" mx="28.6569" width="1" my="15.2047" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="225" mx="0" my="0"/>
-                    <node type="NodeSplinePath" reverse="1" idObject="226" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="227" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="228" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="1" idObject="229" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="230" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="225"/>
+                    <node type="NodeSplinePath" reverse="1" idObject="226"/>
+                    <node type="NodePoint" idObject="227"/>
+                    <node type="NodePoint" idObject="228"/>
+                    <node type="NodeSpline" reverse="1" idObject="229"/>
+                    <node type="NodePoint" idObject="230"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="238" name="CollarTop" seamAllowance="1" mx="28.0866" width="1" my="9.53729" version="1">
+            <detail closed="1" id="238" name="CollarTop" seamAllowance="1" mx="28.0866" width="1" my="9.53729" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="232" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="233" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="234" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="235" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="236" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="237" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="232"/>
+                    <node type="NodeSpline" reverse="0" idObject="233"/>
+                    <node type="NodePoint" idObject="234"/>
+                    <node type="NodePoint" idObject="235"/>
+                    <node type="NodeSpline" reverse="0" idObject="236"/>
+                    <node type="NodePoint" idObject="237"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="255" name="CollarTopInterface" seamAllowance="0" mx="27.8619" width="1" my="-1.37137" version="1">
+            <detail closed="1" id="255" name="CollarTopInterface" seamAllowance="0" mx="27.8619" width="1" my="-1.37137" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="249" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="250" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="251" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="252" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="253" mx="0" my="0"/>
-                    <node type="NodeSpline" reverse="0" idObject="254" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="249"/>
+                    <node type="NodePoint" idObject="250"/>
+                    <node type="NodeSpline" reverse="0" idObject="251"/>
+                    <node type="NodePoint" idObject="252"/>
+                    <node type="NodePoint" idObject="253"/>
+                    <node type="NodeSpline" reverse="0" idObject="254"/>
                 </nodes>
             </detail>
         </details>
@@ -639,23 +639,23 @@ Delete layouts which are not needed.</description>
             <point type="modeling" inUse="true" id="281" idObject="260" mx="0.132292" my="0.264583"/>
         </modeling>
         <details>
-            <detail closed="1" id="274" name="PlacketUnder" seamAllowance="1" mx="27.725" width="1" my="-0.179464" version="1">
+            <detail closed="1" id="274" name="PlacketUnder" seamAllowance="1" mx="27.725" width="1" my="-0.179464" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="270" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="271" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="272" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="273" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="270"/>
+                    <node type="NodePoint" idObject="271"/>
+                    <node type="NodePoint" idObject="272"/>
+                    <node type="NodePoint" idObject="273"/>
                 </nodes>
             </detail>
-            <detail closed="1" id="282" name="PlacketTop" seamAllowance="1" mx="46.1968" width="1" my="-5.58778" version="1">
+            <detail closed="1" id="282" name="PlacketTop" seamAllowance="1" mx="46.1968" width="1" my="-5.58778" version="2">
                 <nodes>
-                    <node type="NodePoint" idObject="275" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="276" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="277" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="278" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="279" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="280" mx="0" my="0"/>
-                    <node type="NodePoint" idObject="281" mx="0" my="0"/>
+                    <node type="NodePoint" idObject="275"/>
+                    <node type="NodePoint" idObject="276"/>
+                    <node type="NodePoint" idObject="277"/>
+                    <node type="NodePoint" idObject="278"/>
+                    <node type="NodePoint" idObject="279"/>
+                    <node type="NodePoint" idObject="280"/>
+                    <node type="NodePoint" idObject="281"/>
                 </nodes>
             </detail>
         </details>

From 39a8165bd531715e1b5c93c26f49116df0b57446 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 4 Dec 2016 18:29:12 +0200
Subject: [PATCH 139/208] Update details list after each full parse.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index ba45ec3f5..0610ca39e 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -2690,6 +2690,7 @@ void MainWindow::FullParseFile()
     SetEnableTool(comboBoxDraws->count() > 0);
     patternReadOnly = doc->IsReadOnly();
     SetEnableWidgets(true);
+    detailsWidget->UpdateList();
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From 93535d8f19208b8ea980ba39cde517005986ea2f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 10 Dec 2016 20:09:03 +0200
Subject: [PATCH 140/208] Port new test case. Zigzag in main path.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.h | 39 +++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 13ee0870c..3040ffc5d 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -214,24 +214,49 @@ QVector<T> VAbstractPiece::CorrectEquidistantPoints(const QVector<T> &points, bo
     }
 
     //Clear equivalent points
-    QVector<T> correctPoints = RemoveDublicates(points, removeFirstAndLast);
+    QVector<T> buf1 = RemoveDublicates(points, removeFirstAndLast);
 
-    if (correctPoints.size()<3)
+    if (buf1.size()<3)
     {
-        return correctPoints;
+        return buf1;
     }
 
+    QVector<T> buf2;
     //Remove point on line
-    for (qint32 i = 1; i <correctPoints.size()-1; ++i)
+    for (qint32 i = 0; i < buf1.size(); ++i)
     {// In this case we alwayse will have bounded intersection, so all is need is to check if point i is on line.
      // Unfortunatelly QLineF::intersect can't be used in this case because of the floating-point accuraccy problem.
-        if (VGObject::IsPointOnLineviaPDP(correctPoints.at(i), correctPoints.at(i-1), correctPoints.at(i+1)))
+        int prev = i-1;
+        int next = i+1;
+        if (i == 0)
         {
-            correctPoints.remove(i);
+            prev = buf1.size() - 1;
+        }
+        else if (i == buf1.size() - 1)
+        {
+            next = 0;
+        }
+
+        const QPointF &iPoint = buf1.at(i);
+        const QPointF &prevPoint = buf1.at(prev);
+        const QPointF &nextPoint = buf1.at(next);
+
+        if (not VGObject::IsPointOnLineviaPDP(buf1.at(i), buf1.at(prev), buf1.at(next))
+                && prevPoint != nextPoint) // not zigzag
+        {
+            buf2.append(buf1.at(i));
+        }
+        else if ((i == 0 || i == buf1.size() - 1) && (iPoint == prevPoint || iPoint == nextPoint))
+        {
+            // If RemoveDublicates does not remove these points it is a valid case.
+            // Case where last point equal first point
+            buf2.append(buf1.at(i));
         }
     }
 
-    return correctPoints;
+    buf2 = RemoveDublicates(buf2, false);
+
+    return buf2;
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From b6d0aa1a1f3281ba83b0060efbae4f4bd0049b36 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 20 Dec 2016 17:50:39 +0200
Subject: [PATCH 141/208] Tool seam allowance add support for elliptical arc.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           | 6 +++++-
 src/libs/vtools/tools/vtoolseamallowance.cpp | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 562f4519d..4557c6761 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -577,7 +577,8 @@ VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
     const QStringList types = QStringList() << VAbstractPattern::NodePoint
                                             << VAbstractPattern::NodeArc
                                             << VAbstractPattern::NodeSpline
-                                            << VAbstractPattern::NodeSplinePath;
+                                            << VAbstractPattern::NodeSplinePath
+                                            << VAbstractPattern::NodeElArc;
 
     switch (types.indexOf(t))
     {
@@ -593,6 +594,9 @@ VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
         case 3: // VAbstractPattern::NodeSplinePath
             tool = Tool::NodeSplinePath;
             break;
+        case 4: // NodeElArc
+            tool = Tool::NodeElArc;
+            break;
         default:
             VException e(tr("Wrong tag name '%1'.").arg(t));
             throw e;
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index b3d052731..f3a16736e 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -31,11 +31,13 @@
 #include "../vpatterndb/vpiecenode.h"
 #include "../vpatterndb/vpiecepath.h"
 #include "nodeDetails/vnodearc.h"
+#include "nodeDetails/vnodeellipticalarc.h"
 #include "nodeDetails/vnodepoint.h"
 #include "nodeDetails/vnodespline.h"
 #include "nodeDetails/vnodesplinepath.h"
 #include "nodeDetails/vtoolpiecepath.h"
 #include "../vgeometry/varc.h"
+#include "../vgeometry/vellipticalarc.h"
 #include "../vgeometry/vcubicbezier.h"
 #include "../vgeometry/vcubicbezierpath.h"
 #include "../vgeometry/vpointf.h"
@@ -106,6 +108,12 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
                 VNodeArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
             }
             break;
+            case (Tool::NodeElArc):
+            {
+                id = CreateNode<VEllipticalArc>(data, nodeD.GetId());
+                VNodeEllipticalArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+            }
+            break;
             case (Tool::NodeSpline):
             {
                 const auto obj = data->GetGObject(nodeD.GetId());
@@ -736,6 +744,7 @@ void VToolSeamAllowance::InitNodes(const VPiece &detail, VMainGraphicsScene *sce
                 break;
             }
             case (Tool::NodeArc):
+            case (Tool::NodeElArc):
             case (Tool::NodeSpline):
             case (Tool::NodeSplinePath):
                 doc->IncrementReferens(detail.GetPath().at(i).GetId());

From ff87b32ae94177a96d8c84d89b5c8cea1a36caf8 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 23 Dec 2016 14:00:50 +0200
Subject: [PATCH 142/208] Port changes for issue #603.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 31 +++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index a5a64f8f5..a20985498 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -203,7 +203,7 @@ qreal VAbstractPiece::SumTrapezoids(const QVector<QPointF> &points)
  */
 QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
 {
-    const int count = points.size();
+    int count = points.size();
     /*If we got less than 4 points no need seek loops.*/
     if (count < 4)
     {
@@ -302,13 +302,32 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
         switch (status)
         {
             case ParallelIntersection:
+            {
                 /*We have found a loop.*/
-                // Theoretically there is no big difference which point j or jNext to select.
-                // In the end we will draw a line in any case.
-                ekvPoints.append(points.at(i));
-                ekvPoints.append(points.at(jNext));
-                i = j;
+                // Very tricky case
+                // See the file "collection/bugs/Issue_#603.val"
+                const QLineF line1(points.at(i+1), points.at(j));
+                const QLineF line2(points.at(i), points.at(jNext));
+
+                if (line1.length() <= line2.length())
+                {
+                    // In this case we did not check a loop edges and can just skip them
+                    ekvPoints.append(points.at(i));
+                    ekvPoints.append(points.at(jNext));
+
+                    i = j; // Skip a loo
+                }
+                else
+                {
+                    // In this case a loop edges probably was also chacked and added to the list
+                    ekvPoints.clear();// Previous data is wrong and belong to loop.
+                    ekvPoints.append(points.at(j));
+                    ekvPoints.append(points.at(i+1));
+
+                    count = j+1;// All beyond this belong to loop.
+                }
                 break;
+            }
             case BoundedIntersection:
                 /*We have found a loop.*/
                 ekvPoints.append(points.at(i));

From 7f105e97e0eecf0c37303e14b8024a2f1aa17a83 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 3 Jan 2017 11:50:55 +0200
Subject: [PATCH 143/208] Port changes from issue #606.

--HG--
branch : feature
---
 src/libs/ifc/schema/pattern/v0.4.0.xsd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 56e821feb..d8b2f8066 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -535,7 +535,7 @@
          </xs:element>
     <xs:simpleType name="shortName">
         <xs:restriction base="xs:string">   
-            <xs:pattern value="^([^0-9*/^+\-=\s()?%:;!.,`'\&quot;]){1,1}([^*/^+\-=\s()?%:;!.,`'\&quot;]){0,}$"/>
+            <xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
         </xs:restriction>
     </xs:simpleType>
     <xs:simpleType name="units">

From 12162e49e81aa4d3ddd606b45576b6ea67d0215c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 11 Jan 2017 14:53:16 +0200
Subject: [PATCH 144/208] Port changes from develop branch.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.cpp | 187 ++++++++++++++++++++++------
 src/libs/vlayout/vabstractpiece.h   |   5 +
 2 files changed, 151 insertions(+), 41 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index a20985498..061375072 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -34,6 +34,7 @@
 #include <QLineF>
 #include <QSet>
 #include <QVector>
+#include <QPainterPath>
 
 const qreal maxL = 2.4;
 
@@ -207,7 +208,6 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
     /*If we got less than 4 points no need seek loops.*/
     if (count < 4)
     {
-        qDebug()<<"Less then 4 points. Doesn't need check for loops.";
         return points;
     }
 
@@ -235,7 +235,6 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
         // That's why we parse from the end
         for (j = count-1; j >= i+2; --j)
         {
-
             j == count-1 ? jNext = 0 : jNext = j+1;
             QLineF line2(points.at(j), points.at(jNext));
 
@@ -257,11 +256,7 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
               // Method IsPointOnLineviaPDP will check it.
                 if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1))
                     // Lines are not neighbors
-                    && uniqueVertices.size() == 4
-                    && line1.p2() != line2.p2()
-                    && line1.p1() != line2.p1()
-                    && line1.p2() != line2.p1()
-                    && line1.p1() != line2.p2())
+                    && uniqueVertices.size() == 4)
                 {
                     // Left to catch case where segments are on the same line, but do not have real intersections.
                     QLineF tmpLine1 = line1;
@@ -279,21 +274,28 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
 
                     if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection)
                     { // Now we really sure that lines are on the same lines and have real intersections.
-                        status = ParallelIntersection;
-                        break;
+                        QPointF cPoint;
+                        const bool caseFlag = ParallelCrossPoint(line1, line2, cPoint);
+                        if (not caseFlag || CheckIntersection(points, i, i+1, j, jNext, cPoint))
+                        {
+                            status = ParallelIntersection;
+                            break;
+                        }
                     }
                 }
             }
             else if (intersect == QLineF::BoundedIntersection)
             {
-                if (uniqueVertices.size() == 4
-                    && line1.p1() != crosPoint
-                    && line1.p2() != crosPoint
-                    && line2.p1() != crosPoint
-                    && line2.p2() != crosPoint)
+                if (uniqueVertices.size() == 4)
                 { // Break, but not if lines are neighbors
-                    status = BoundedIntersection;
-                    break;
+                    if ((line1.p1() != crosPoint
+                        && line1.p2() != crosPoint
+                        && line2.p1() != crosPoint
+                        && line2.p2() != crosPoint) || CheckIntersection(points, i, i+1, j, jNext, crosPoint))
+                    {
+                        status = BoundedIntersection;
+                        break;
+                    }
                 }
             }
             status = NoIntersection;
@@ -302,34 +304,12 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
         switch (status)
         {
             case ParallelIntersection:
-            {
                 /*We have found a loop.*/
-                // Very tricky case
-                // See the file "collection/bugs/Issue_#603.val"
-                const QLineF line1(points.at(i+1), points.at(j));
-                const QLineF line2(points.at(i), points.at(jNext));
-
-                if (line1.length() <= line2.length())
-                {
-                    // In this case we did not check a loop edges and can just skip them
-                    ekvPoints.append(points.at(i));
-                    ekvPoints.append(points.at(jNext));
-
-                    i = j; // Skip a loo
-                }
-                else
-                {
-                    // In this case a loop edges probably was also chacked and added to the list
-                    ekvPoints.clear();// Previous data is wrong and belong to loop.
-                    ekvPoints.append(points.at(j));
-                    ekvPoints.append(points.at(i+1));
-
-                    count = j+1;// All beyond this belong to loop.
-                }
+                ekvPoints.append(points.at(i));
+                ekvPoints.append(points.at(jNext));
+                jNext > j ? i = jNext : i = j; // Skip a loop
                 break;
-            }
             case BoundedIntersection:
-                /*We have found a loop.*/
                 ekvPoints.append(points.at(i));
                 ekvPoints.append(crosPoint);
                 i = j;
@@ -831,3 +811,128 @@ qreal VAbstractPiece::AngleBetweenBisectors(const QLineF &b1, const QLineF &b2)
         return angle2;
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPiece::CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
+                                        const QPointF &crossPoint)
+{
+    QVector<QPointF> sub1 = SubPath(points, iNext, j);
+    sub1.append(crossPoint);
+    sub1 = CheckLoops(CorrectEquidistantPoints(sub1, false));
+    const qreal sub1Sum = SumTrapezoids(sub1);
+
+    QVector<QPointF> sub2 = SubPath(points, jNext, i);
+    sub2.append(crossPoint);
+    sub2 = CheckLoops(CorrectEquidistantPoints(sub2, false));
+    const qreal sub2Sum = SumTrapezoids(sub2);
+
+    if (sub1Sum < 0 && sub2Sum < 0)
+    {
+        if (Crossing(sub1, sub2))
+        {
+            return true;
+        }
+    }
+    else
+    {
+        if (not Crossing(sub1, sub2))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPiece::ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point)
+{
+    const bool l1p1el2p1 = (line1.p1() == line2.p1());
+    const bool l1p2el2p2 = (line1.p2() == line2.p2());
+    const bool l1p1el2p2 = (line1.p1() == line2.p2());
+    const bool l1p2el2p1 = (line1.p2() == line2.p1());
+
+    if (l1p2el2p2 || l1p2el2p1)
+    {
+        point = line1.p2();
+        return true;
+    }
+    else if (l1p1el2p1 || l1p1el2p2)
+    {
+        point = line1.p1();
+        return true;
+    }
+    else
+    {
+        point = QPointF();
+        return false;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPiece::Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2)
+{
+    if (sub1.isEmpty() || sub2.isEmpty())
+    {
+        return false;
+    }
+
+    const QRectF sub1Rect = QPolygonF(sub1).boundingRect();
+    const QRectF sub2Rect = QPolygonF(sub2).boundingRect();
+    if (not sub1Rect.intersects(sub2Rect))
+    {
+        return false;
+    }
+
+    QPainterPath sub1Path;
+    sub1Path.setFillRule(Qt::WindingFill);
+    sub1Path.moveTo(sub1.at(0));
+    for (qint32 i = 1; i < sub1.count(); ++i)
+    {
+        sub1Path.lineTo(sub1.at(i));
+    }
+    sub1Path.lineTo(sub1.at(0));
+
+    QPainterPath sub2Path;
+    sub2Path.setFillRule(Qt::WindingFill);
+    sub2Path.moveTo(sub2.at(0));
+    for (qint32 i = 1; i < sub2.count(); ++i)
+    {
+        sub2Path.lineTo(sub2.at(i));
+    }
+    sub2Path.lineTo(sub2.at(0));
+
+    if (not sub1Path.intersects(sub2Path))
+    {
+        return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VAbstractPiece::SubPath(const QVector<QPointF> &path, int startIndex, int endIndex)
+{
+    if (path.isEmpty()
+       || startIndex < 0 || startIndex >= path.size()
+       || endIndex < 0 || endIndex >= path.size()
+       || startIndex == endIndex)
+    {
+        return path;
+    }
+
+    QVector<QPointF> subPath;
+    int i = startIndex - 1;
+    do
+    {
+        ++i;
+        if (i >= path.size())
+        {
+            i = 0;
+        }
+        subPath.append(path.at(i));
+    } while (i != endIndex);
+
+    return subPath;
+}
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 3040ffc5d..fd618fe37 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -170,6 +170,11 @@ protected:
 private:
     QSharedDataPointer<VAbstractPieceData> d;
 
+    static bool             CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
+                                              const QPointF &crossPoint);
+    static bool             ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point);
+    static bool             Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2);
+    static QVector<QPointF> SubPath(const QVector<QPointF> &path, int startIndex, int endIndex);
     static Q_DECL_CONSTEXPR qreal PointPosition(const QPointF &p, const QLineF &line);
     static qreal            MaxLocalSA(const VSAPoint &p, qreal width);
     static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,

From 3634867c47006cefdfc24d55f8eeabe4a52951cd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 11 Jan 2017 15:01:49 +0200
Subject: [PATCH 145/208] Try to fix Qt error.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode.cpp | 2 ++
 src/libs/vpatterndb/vpiecenode.h   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index a475d6735..1401121eb 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -29,6 +29,8 @@
 #include "vpiecenode.h"
 #include "vpiecenode_p.h"
 
+#include <QDataStream>
+
 //---------------------------------------------------------------------------------------------------------------------
 VPieceNode::VPieceNode()
     : d(new VPieceNodeData)
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 2653e472f..89c212cb2 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -36,6 +36,7 @@
 #include "../vmisc/def.h"
 
 class VPieceNodeData;
+class QDataStream;
 
 class VPieceNode
 {

From c9cb6adc3658751bab87abc06a0c92301fa35937 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 12 Jan 2017 15:51:08 +0200
Subject: [PATCH 146/208] VToolSeamAllowance add grain line and labels. Only
 the tool.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp               |  72 +++
 src/libs/vpatterndb/vpiece.h                 |  14 +
 src/libs/vpatterndb/vpiece_p.h               |  22 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp | 448 ++++++++++++++++++-
 src/libs/vtools/tools/vtoolseamallowance.h   |  40 +-
 5 files changed, 584 insertions(+), 12 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 469e31daa..398866c27 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -367,6 +367,78 @@ QVector<quint32> VPiece::MissingInternalPaths(const VPiece &det) const
     return r;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetPatternPieceData(const VPatternPieceData &data)
+{
+    d->m_ppData = data;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Returns full access to the pattern piece data object
+ * @return pattern piece data object
+ */
+VPatternPieceData &VPiece::GetPatternPieceData()
+{
+    return d->m_ppData;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Returns the read only reference to the pattern piece data object
+ * @return pattern piece data object
+ */
+const VPatternPieceData &VPiece::GetPatternPieceData() const
+{
+    return d->m_ppData;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetPatternInfo(const VPatternInfoGeometry &info)
+{
+    d->m_piPatternInfo = info;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Returns full access to the pattern info geometry object
+ * @return pattern info geometry object
+ */
+VPatternInfoGeometry &VPiece::GetPatternInfo()
+{
+    return d->m_piPatternInfo;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Returns the read only reference to the pattern info geometry object
+ * @return pattern info geometry object
+ */
+const VPatternInfoGeometry &VPiece::GetPatternInfo() const
+{
+    return d->m_piPatternInfo;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief VDetail::GetGrainlineGeometry full access to the grainline geometry object
+ * @return reference to grainline geometry object
+ */
+VGrainlineGeometry &VPiece::GetGrainlineGeometry()
+{
+    return d->m_glGrainline;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief VDetail::GetGrainlineGeometry returns the read-only reference to the grainline geometry object
+ * @return reference to grainline geometry object
+ */
+const VGrainlineGeometry &VPiece::GetGrainlineGeometry() const
+{
+    return d->m_glGrainline;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<CustomSARecord> VPiece::GetValidRecords() const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 6a65dee2e..47bc31f05 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -44,6 +44,9 @@ template <class T> class QVector;
 template <class T>class QSharedPointer;
 class VAbstractCurve;
 class VPiecePath;
+class VPatternInfoGeometry;
+class VPatternPieceData;
+class VGrainlineGeometry;
 
 class VPiece : public VAbstractPiece
 {
@@ -86,6 +89,17 @@ public:
     QVector<quint32> MissingCSAPath(const VPiece &det) const;
     QVector<quint32> MissingInternalPaths(const VPiece &det) const;
 
+    void                     SetPatternPieceData(const VPatternPieceData &data);
+    VPatternPieceData&       GetPatternPieceData();
+    const VPatternPieceData& GetPatternPieceData() const;
+
+    void                        SetPatternInfo(const VPatternInfoGeometry &info);
+    VPatternInfoGeometry&       GetPatternInfo();
+    const VPatternInfoGeometry& GetPatternInfo() const;
+
+    VGrainlineGeometry&         GetGrainlineGeometry();
+    const VGrainlineGeometry&   GetGrainlineGeometry() const;
+
 private:
     QSharedDataPointer<VPieceData> d;
 
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index fcfc7e01b..53791ae3b 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -36,6 +36,9 @@
 #include "../vmisc/def.h"
 #include "vpiecenode.h"
 #include "vpiecepath.h"
+#include "vpatternpiecedata.h"
+#include "vpatterninfogeometry.h"
+#include "vgrainlinegeometry.h"
 
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_GCC("-Weffc++")
@@ -50,7 +53,10 @@ public:
           m_inLayout(true),
           m_united(false),
           m_customSARecords(),
-          m_internalPaths()
+          m_internalPaths(),
+          m_ppData(),
+          m_piPatternInfo(),
+          m_glGrainline()
     {}
 
     VPieceData(const VPieceData &detail)
@@ -61,7 +67,10 @@ public:
           m_inLayout(detail.m_inLayout),
           m_united(detail.m_united),
           m_customSARecords(detail.m_customSARecords),
-          m_internalPaths(detail.m_internalPaths)
+          m_internalPaths(detail.m_internalPaths),
+          m_ppData(detail.m_ppData),
+          m_piPatternInfo(detail.m_piPatternInfo),
+          m_glGrainline(detail.m_glGrainline)
     {}
 
     ~VPieceData();
@@ -78,6 +87,15 @@ public:
     QVector<CustomSARecord> m_customSARecords;
     QVector<quint32>        m_internalPaths;
 
+    /** @brief Pattern piece data */
+    VPatternPieceData m_ppData;
+
+    /** @brief Pattern info coordinates */
+    VPatternInfoGeometry m_piPatternInfo;
+
+    /** @brief m_glGrainline grainline geometry object*/
+    VGrainlineGeometry m_glGrainline;
+
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
 };
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index f3a16736e..d245c8089 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -30,6 +30,9 @@
 #include "../dialogs/tools/dialogseamallowance.h"
 #include "../vpatterndb/vpiecenode.h"
 #include "../vpatterndb/vpiecepath.h"
+#include "../vpatterndb/calculator.h"
+#include "../vpatterndb/vpatterninfogeometry.h"
+#include "../vpatterndb/vpatternpiecedata.h"
 #include "nodeDetails/vnodearc.h"
 #include "nodeDetails/vnodeellipticalarc.h"
 #include "nodeDetails/vnodepoint.h"
@@ -68,11 +71,14 @@ const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version")
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
+const QString VToolSeamAllowance::AttrHeight         = QStringLiteral("height");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 const QString VToolSeamAllowance::AttrStart          = QStringLiteral("start");
 const QString VToolSeamAllowance::AttrPath           = QStringLiteral("path");
 const QString VToolSeamAllowance::AttrEnd            = QStringLiteral("end");
 const QString VToolSeamAllowance::AttrIncludeAs      = QStringLiteral("includeAs");
+const QString VToolSeamAllowance::AttrFont           = QStringLiteral("fontSize");
+const QString VToolSeamAllowance::AttrRotation       = QStringLiteral("rotation");
 
 //---------------------------------------------------------------------------------------------------------------------
 VToolSeamAllowance::~VToolSeamAllowance()
@@ -151,6 +157,7 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
     }
 
     detail.GetPath().SetNodes(nodes);
+
     VToolSeamAllowance *piece = Create(0, detail, scene, doc, data, Document::FullParse, Source::FromGui);
 
     if (piece != nullptr)
@@ -292,19 +299,61 @@ void VToolSeamAllowance::AddInternalPaths(VAbstractPattern *doc, QDomElement &do
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
+    QDomElement domData = doc->createElement(VAbstractPattern::TagData);
+    const VPatternPieceData& data = piece.GetPatternPieceData();
+    doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter());
+    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
+    doc->SetAttribute(domData, AttrMx, data.GetPos().x());
+    doc->SetAttribute(domData, AttrMy, data.GetPos().y());
+    doc->SetAttribute(domData, AttrWidth, data.GetLabelWidth());
+    doc->SetAttribute(domData, AttrHeight, data.GetLabelHeight());
+    doc->SetAttribute(domData, AttrFont, data.GetFontSize());
+    doc->SetAttribute(domData, AttrRotation, data.GetRotation());
 
+    for (int i = 0; i < data.GetMCPCount(); ++i)
+    {
+        const MaterialCutPlacement mcp = data.GetMCP(i);
+        QDomElement domMCP = doc->createElement(VAbstractPattern::TagMCP);
+        doc->SetAttribute(domMCP, VAbstractPattern::AttrMaterial, int(mcp.m_eMaterial));
+        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
+        {
+            doc->SetAttribute(domMCP, VAbstractPattern::AttrUserDefined, mcp.m_qsMaterialUserDef);
+        }
+        doc->SetAttribute(domMCP, VAbstractPattern::AttrCutNumber, mcp.m_iCutNumber);
+        doc->SetAttribute(domMCP, VAbstractPattern::AttrPlacement, int(mcp.m_ePlacement));
+        domData.appendChild(domMCP);
+    }
+    domElement.appendChild(domData);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
-
+    QDomElement domData = doc->createElement(VAbstractPattern::TagPatternInfo);
+    const VPatternInfoGeometry& geom = piece.GetPatternInfo();
+    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true ? trueStr : falseStr);
+    doc->SetAttribute(domData, AttrMx, geom.GetPos().x());
+    doc->SetAttribute(domData, AttrMy, geom.GetPos().y());
+    doc->SetAttribute(domData, AttrWidth, geom.GetLabelWidth());
+    doc->SetAttribute(domData, AttrHeight, geom.GetLabelHeight());
+    doc->SetAttribute(domData, AttrFont, geom.GetFontSize());
+    doc->SetAttribute(domData, AttrRotation, geom.GetRotation());
+    domElement.appendChild(domData);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
 {
-
+    // grainline
+    QDomElement domData = doc->createElement(VAbstractPattern::TagGrainline);
+    const VGrainlineGeometry& glGeom = piece.GetGrainlineGeometry();
+    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true ? trueStr : falseStr);
+    doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x());
+    doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y());
+    doc->SetAttribute(domData, AttrLength, glGeom.GetLength());
+    doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation());
+    doc->SetAttribute(domData, VAbstractPattern::AttrArrows, int(glGeom.GetArrowType()));
+    domElement.appendChild(domData);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -366,12 +415,376 @@ void VToolSeamAllowance::AllowSelecting(bool enabled)
     setFlag(QGraphicsItem::ItemIsSelectable, enabled);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::ResetChildren(QGraphicsItem *pItem)
+{
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
+    VTextGraphicsItem* pVGI = dynamic_cast<VTextGraphicsItem*>(pItem);
+    if (pVGI != m_dataLabel)
+    {
+        if (detail.GetPatternPieceData().IsVisible())
+        {
+            m_dataLabel->Reset();
+        }
+    }
+    if (pVGI != m_patternInfo)
+    {
+        if (detail.GetPatternInfo().IsVisible())
+        {
+            m_patternInfo->Reset();
+        }
+    }
+    VGrainlineItem* pGLI = dynamic_cast<VGrainlineItem*>(pItem);
+    if (pGLI != m_grainLine)
+    {
+        if (detail.GetGrainlineGeometry().IsVisible())
+        {
+            m_grainLine->Reset();
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::UpdateAll()
+{
+    m_sceneDetails->update();
+    update();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::retranslateUi()
+{
+    UpdateLabel();
+    UpdatePatternInfo();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::Highlight(quint32 id)
 {
     setSelected(this->id == id);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief UpdateLabel updates the text label, making it just big enough for the text to fit it
+ */
+void VToolSeamAllowance::UpdateLabel()
+{
+    const VDetail detail = VAbstractTool::data.GetDetail(id);
+    const VPatternPieceData& data = detail.GetPatternPieceData();
+
+    if (data.IsVisible() == true)
+    {
+        QFont fnt = qApp->font();
+        {
+            const int iFS = data.GetFontSize();
+            iFS < MIN_FONT_SIZE ? fnt.setPixelSize(MIN_FONT_SIZE) : fnt.setPixelSize(iFS);
+        }
+        m_dataLabel->SetFont(fnt);
+        m_dataLabel->SetSize(data.GetLabelWidth(), data.GetLabelHeight());
+        m_dataLabel->UpdateData(detail.getName(), data);
+        QPointF pt = data.GetPos();
+        QRectF rectBB;
+        rectBB.setTopLeft(pt);
+        rectBB.setWidth(m_dataLabel->boundingRect().width());
+        rectBB.setHeight(m_dataLabel->boundingRect().height());
+        qreal dX;
+        qreal dY;
+        if (m_dataLabel->IsContained(rectBB, data.GetRotation(), dX, dY) == false)
+        {
+            pt.setX(pt.x() + dX);
+            pt.setY(pt.y() + dY);
+        }
+
+        m_dataLabel->setPos(pt);
+        m_dataLabel->setRotation(data.GetRotation());
+        m_dataLabel->Update();
+        m_dataLabel->show();
+    }
+    else
+    {
+        m_dataLabel->hide();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief UpdatePatternInfo updates the pattern info label
+ */
+void VToolSeamAllowance::UpdatePatternInfo()
+{
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
+    const VPatternInfoGeometry& geom = detail.GetPatternInfo();
+
+    if (geom.IsVisible() == true)
+    {
+        QFont fnt = qApp->font();
+        int iFS = geom.GetFontSize();
+        if (iFS < MIN_FONT_SIZE)
+        {
+            iFS = MIN_FONT_SIZE;
+        }
+        fnt.setPixelSize(iFS);
+        m_patternInfo->SetFont(fnt);
+        m_patternInfo->SetSize(geom.GetLabelWidth(), geom.GetLabelHeight());
+        m_patternInfo->UpdateData(doc, getData()->size(), getData()->height());
+
+        QPointF pt = geom.GetPos();
+        QRectF rectBB;
+        rectBB.setTopLeft(pt);
+        rectBB.setWidth(m_patternInfo->boundingRect().width());
+        rectBB.setHeight(m_patternInfo->boundingRect().height());
+        qreal dX;
+        qreal dY;
+        if (m_patternInfo->IsContained(rectBB, geom.GetRotation(), dX, dY) == false)
+        {
+            pt.setX(pt.x() + dX);
+            pt.setY(pt.y() + dY);
+        }
+
+        m_patternInfo->setPos(pt);
+        m_patternInfo->setRotation(geom.GetRotation());
+        m_patternInfo->Update();
+        m_patternInfo->GetTextLines() > 0 ? m_patternInfo->show() : m_patternInfo->hide();
+    }
+    else
+    {
+        m_patternInfo->hide();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief VToolDetail::UpdateGrainline updates the grain line item
+ */
+void VToolSeamAllowance::UpdateGrainline()
+{
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
+    const VGrainlineGeometry& geom = detail.GetGrainlineGeometry();
+
+    if (geom.IsVisible() == true)
+    {
+        qreal dRotation;
+        qreal dLength;
+        try
+        {
+            QString qsFormula;
+            qsFormula = geom.GetRotation().replace("\n", " ");
+            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
+
+            Calculator cal1;
+            dRotation = cal1.EvalFormula(VDataTool::data.PlainVariables(), qsFormula);
+
+            qsFormula = geom.GetLength().replace("\n", " ");
+            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
+            Calculator cal2;
+            dLength = cal2.EvalFormula(VDataTool::data.PlainVariables(), qsFormula);
+        }
+        catch(...)
+        {
+            m_grainLine->hide();
+            return;
+        }
+
+        m_grainLine->UpdateGeometry(geom.GetPos(), dRotation, ToPixel(dLength, *VDataTool::data.GetPatternUnit()),
+                                    geom.GetArrowType());
+        m_grainLine->show();
+    }
+    else
+    {
+        m_grainLine->hide();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief SaveMoveDetail saves the move detail operation to the undo stack
+ */
+void VToolSeamAllowance::SaveMoveDetail(const QPointF& ptPos)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternPieceData().SetPos(ptPos);
+    newDet.GetPatternPieceData().SetLabelWidth(m_dataLabel->boundingRect().width());
+    newDet.GetPatternPieceData().SetLabelHeight(m_dataLabel->boundingRect().height());
+    newDet.GetPatternPieceData().SetFontSize(m_dataLabel->GetFontSize());
+    newDet.GetPatternPieceData().SetRotation(m_dataLabel->rotation());
+
+    SavePieceOptions* moveCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    moveCommand->setText(tr("move pattern piece label"));
+    connect(moveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(moveCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief SaveResizeDetail saves the resize detail label operation to the undo stack
+ */
+void VToolSeamAllowance::SaveResizeDetail(qreal dLabelW, int iFontSize)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternPieceData().SetLabelWidth(dLabelW);
+    newDet.GetPatternPieceData().SetLabelHeight(m_dataLabel->boundingRect().height());
+    newDet.GetPatternPieceData().SetFontSize(iFontSize);
+    newDet.GetPatternPieceData().SetRotation(m_dataLabel->rotation());
+    SavePieceOptions* resizeCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    resizeCommand->setText(tr("resize pattern piece label"));
+    connect(resizeCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(resizeCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief SaveRotationDetail saves the rotation detail label operation to the undo stack
+ */
+void VToolSeamAllowance::SaveRotationDetail(qreal dRot)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternPieceData().SetPos(m_dataLabel->pos());
+    newDet.GetPatternPieceData().SetLabelWidth(m_dataLabel->boundingRect().width());
+    newDet.GetPatternPieceData().SetLabelHeight(m_dataLabel->boundingRect().height());
+    newDet.GetPatternPieceData().SetFontSize(m_dataLabel->GetFontSize());
+    newDet.GetPatternPieceData().SetRotation(dRot);
+
+    SavePieceOptions* rotateCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    rotateCommand->setText(tr("rotate pattern piece label"));
+    connect(rotateCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(rotateCommand);
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief SaveMovePattern saves the pattern label position
+ */
+void VToolSeamAllowance::SaveMovePattern(const QPointF &ptPos)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternInfo().SetPos(ptPos);
+    newDet.GetPatternInfo().SetLabelWidth(m_patternInfo->boundingRect().width());
+    newDet.GetPatternInfo().SetLabelHeight(m_patternInfo->boundingRect().height());
+    newDet.GetPatternInfo().SetFontSize(m_patternInfo->GetFontSize());
+    newDet.GetPatternInfo().SetRotation(m_patternInfo->rotation());
+
+    SavePieceOptions* moveCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    moveCommand->setText(tr("move pattern info label"));
+    connect(moveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(moveCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief: SaveResizePattern saves the pattern label width and font size
+ */
+void VToolSeamAllowance::SaveResizePattern(qreal dLabelW, int iFontSize)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternInfo().SetLabelWidth(dLabelW);
+    newDet.GetPatternInfo().SetLabelHeight(m_patternInfo->boundingRect().height());
+    newDet.GetPatternInfo().SetFontSize(iFontSize);
+    newDet.GetPatternInfo().SetRotation(m_patternInfo->rotation());
+    SavePieceOptions* resizeCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    resizeCommand->setText(tr("resize pattern info label"));
+    connect(resizeCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(resizeCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SaveRotationPattern(qreal dRot)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetPatternInfo().SetPos(m_patternInfo->pos());
+    newDet.GetPatternInfo().SetLabelWidth(m_patternInfo->boundingRect().width());
+    newDet.GetPatternInfo().SetLabelHeight(m_patternInfo->boundingRect().height());
+    newDet.GetPatternInfo().SetFontSize(m_patternInfo->GetFontSize());
+    newDet.GetPatternInfo().SetRotation(dRot);
+
+    SavePieceOptions* rotateCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    rotateCommand->setText(tr("rotate pattern info label"));
+    connect(rotateCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(rotateCommand);
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SaveMoveGrainline(const QPointF& ptPos)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+    newDet.GetGrainlineGeometry().SetPos(ptPos);
+    qDebug() << "******* new grainline pos" << ptPos;
+
+    SavePieceOptions* moveCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    moveCommand->setText(tr("move grainline"));
+    connect(moveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(moveCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SaveResizeGrainline(qreal dLength)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+
+    dLength = FromPixel(dLength, *VDataTool::data.GetPatternUnit());
+    newDet.GetGrainlineGeometry().SetLength(qApp->LocaleToString(dLength));
+    SavePieceOptions* resizeCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    resizeCommand->setText(tr("resize grainline"));
+    connect(resizeCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(resizeCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolSeamAllowance::SaveRotateGrainline(qreal dRot, const QPointF& ptPos)
+{
+    VPiece oldDet = VAbstractTool::data.GetPiece(id);
+    VPiece newDet = oldDet;
+
+    dRot = qRadiansToDegrees(dRot);
+    newDet.GetGrainlineGeometry().SetRotation(qApp->LocaleToString(dRot));
+    newDet.GetGrainlineGeometry().SetPos(ptPos);
+    SavePieceOptions* rotateCommand = new SavePieceOptions(oldDet, newDet, doc, id);
+    rotateCommand->setText(tr("rotate grainline"));
+    connect(rotateCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+    qApp->getUndoStack()->push(rotateCommand);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief VToolDetail::paint draws a bounding box around detail, if one of its text or grainline items is not idle.
+ */
+void VToolSeamAllowance::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    if (scene()->views().count() > 0)
+    {
+        const QPoint pt0 = scene()->views().at(0)->mapFromScene(0, 0);
+        const QPoint pt = scene()->views().at(0)->mapFromScene(0, 100);
+
+        const QPoint p = pt - pt0;
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+        const qreal dScale = qSqrt(QPoint::dotProduct(p, p));
+#else
+        const qreal dScale = qSqrt(p.x() * p.x() + p.y() * p.y());
+#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+        m_grainLine->SetScale(100/dScale);
+    }
+
+    if (m_dataLabel->IsIdle() == false || m_patternInfo->IsIdle() == false || m_grainLine->IsIdle() == false)
+    {
+        painter->save();
+        painter->setPen(QPen(Qt::black, 3, Qt::DashLine));
+        painter->drawRect(boundingRect().adjusted(1, 1, -1, -1));
+        painter->restore();
+    }
+    QGraphicsPathItem::paint(painter, option, widget);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddToFile()
 {
@@ -660,7 +1073,10 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
       m_dialog(),
       m_sceneDetails(scene),
       m_drawName(drawName),
-      m_seamAllowance(new VNoBrushScalePathItem(this))
+      m_seamAllowance(new VNoBrushScalePathItem(this)),
+      m_dataLabel(new VTextGraphicsItem(this)),
+      m_patternInfo(new VTextGraphicsItem(this)),
+      m_grainLine(new VGrainlineItem(this))
 {
     VPiece detail = data->GetPiece(id);
     InitNodes(detail, scene);
@@ -690,6 +1106,31 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
         RefreshDataInFile();
     }
     setAcceptHoverEvents(true);
+
+    connect(m_dataLabel, &VTextGraphicsItem::SignalMoved, this, &VToolSeamAllowance::SaveMoveDetail);
+    connect(m_dataLabel, &VTextGraphicsItem::SignalResized, this, &VToolSeamAllowance::SaveResizeDetail);
+    connect(m_dataLabel, &VTextGraphicsItem::SignalRotated, this, &VToolSeamAllowance::SaveRotationDetail);
+
+    connect(m_patternInfo, &VTextGraphicsItem::SignalMoved, this, &VToolSeamAllowance::SaveMovePattern);
+    connect(m_patternInfo, &VTextGraphicsItem::SignalResized, this, &VToolSeamAllowance::SaveResizePattern);
+    connect(m_patternInfo, &VTextGraphicsItem::SignalRotated, this, &VToolSeamAllowance::SaveRotationPattern);
+
+    connect(m_grainLine, &VGrainlineItem::SignalMoved, this, &VToolSeamAllowance::SaveMoveGrainline);
+    connect(m_grainLine, &VGrainlineItem::SignalResized, this, &VToolSeamAllowance::SaveResizeGrainline);
+    connect(m_grainLine, &VGrainlineItem::SignalRotated, this, &VToolSeamAllowance::SaveRotateGrainline);
+
+    connect(doc, &VAbstractPattern::patternChanged, this, &VToolSeamAllowance::UpdatePatternInfo);
+    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolSeamAllowance::UpdateLabel);
+    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolSeamAllowance::UpdatePatternInfo);
+    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolSeamAllowance::UpdateGrainline);
+
+    connect(m_sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolSeamAllowance::UpdateLabel);
+    connect(m_sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolSeamAllowance::UpdatePatternInfo);
+    connect(m_sceneDetails, &VMainGraphicsScene::LanguageChanged, this, &VToolSeamAllowance::retranslateUi);
+
+    UpdateLabel();
+    UpdatePatternInfo();
+    UpdateGrainline();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -728,6 +1169,7 @@ void VToolSeamAllowance::SaveDialogChange()
     SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, id);
     connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
     qApp->getUndoStack()->push(saveCommand);
+    UpdateLabel();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index e23ef708e..286ec4d59 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -36,6 +36,8 @@
 
 #include "../vwidgets/vnobrushscalepathitem.h"
 #include "vabstracttool.h"
+#include "vtextgraphicsitem.h"
+#include "vgrainlineitem.h"
 
 class VMainGraphicsScene;
 class DialogTool;
@@ -63,11 +65,14 @@ public:
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
     static const QString AttrWidth;
+    static const QString AttrHeight;
     static const QString AttrUnited;
     static const QString AttrStart;
     static const QString AttrPath;
     static const QString AttrEnd;
     static const QString AttrIncludeAs;
+    static const QString AttrFont;
+    static const QString AttrRotation;
 
     void Remove(bool ask);
 
@@ -88,14 +93,32 @@ public:
     virtual void       ShowVisualization(bool show) Q_DECL_OVERRIDE;
     virtual void       GroupVisibility(quint32 object, bool visible) Q_DECL_OVERRIDE;
 public slots:
-    virtual void       FullUpdateFromFile () Q_DECL_OVERRIDE;
-    virtual void       FullUpdateFromGuiOk(int result);
-    void               FullUpdateFromGuiApply();
-    void               EnableToolMove(bool move);
-    virtual void       AllowHover(bool enabled) Q_DECL_OVERRIDE;
-    virtual void       AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
-    void               Highlight(quint32 id);
+    virtual void FullUpdateFromFile () Q_DECL_OVERRIDE;
+    virtual void FullUpdateFromGuiOk(int result);
+    void         FullUpdateFromGuiApply();
+    void         EnableToolMove(bool move);
+    virtual void AllowHover(bool enabled) Q_DECL_OVERRIDE;
+    virtual void AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
+    virtual void ResetChildren(QGraphicsItem* pItem);
+    virtual void UpdateAll();
+    virtual void retranslateUi();
+    void         Highlight(quint32 id);
+protected slots:
+    virtual void UpdateLabel();
+    virtual void UpdatePatternInfo();
+    virtual void UpdateGrainline();
+    virtual void SaveMoveDetail(const QPointF &ptPos);
+    virtual void SaveResizeDetail(qreal dLabelW, int iFontSize);
+    virtual void SaveRotationDetail(qreal dRot);
+    virtual void SaveMovePattern(const QPointF& ptPos);
+    virtual void SaveResizePattern(qreal dLabelW, int iFontSize);
+    virtual void SaveRotationPattern(qreal dRot);
+    virtual void SaveMoveGrainline(const QPointF& ptPos);
+    virtual void SaveResizeGrainline(qreal dLength);
+    virtual void SaveRotateGrainline(qreal dRot, const QPointF& ptPos);
 protected:
+    virtual void       paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+                             QWidget *widget) Q_DECL_OVERRIDE;
     virtual void       AddToFile () Q_DECL_OVERRIDE;
     virtual void       RefreshDataInFile() Q_DECL_OVERRIDE;
     virtual QVariant   itemChange ( GraphicsItemChange change, const QVariant &value ) Q_DECL_OVERRIDE;
@@ -120,6 +143,9 @@ private:
     QString             m_drawName;
 
     VNoBrushScalePathItem *m_seamAllowance;
+    VTextGraphicsItem     *m_dataLabel;
+    VTextGraphicsItem     *m_patternInfo;
+    VGrainlineItem        *m_grainLine;
 
     void SetDialog();
 

From 1b8ecdcb27d256a1169d27b44ff45f22f9a24f73 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 12 Jan 2017 15:58:45 +0200
Subject: [PATCH 147/208] Refactoring names.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp | 8 ++++----
 src/app/valentina/xml/vpattern.h   | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index e41cc28e0..1b37c5a5b 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -792,10 +792,10 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                     case 3:// TagGrainline
                         break;
                     case 4:// VToolSeamAllowance::TagCSA
-                        ParseDetailCSARecords(element, detail);
+                        ParsePieceCSARecords(element, detail);
                         break;
                     case 5:// VToolSeamAllowance::TagIPaths
-                        ParseDetailInternalPaths(element, detail);
+                        ParsePieceInternalPaths(element, detail);
                     default:
                         break;
                 }
@@ -916,7 +916,7 @@ void VPattern::ParsePieceNodes(const QDomElement &domElement, VPiece &detail) co
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const
+void VPattern::ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const
 {
     QVector<CustomSARecord> records;
     const QDomNodeList nodeList = domElement.childNodes();
@@ -940,7 +940,7 @@ void VPattern::ParseDetailCSARecords(const QDomElement &domElement, VPiece &deta
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParseDetailInternalPaths(const QDomElement &domElement, VPiece &detail) const
+void VPattern::ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const
 {
     QVector<quint32> records;
     const QDomNodeList nodeList = domElement.childNodes();
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 53d3b663a..0ea76b4dd 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -122,8 +122,8 @@ private:
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
     void           ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
-    void           ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const;
-    void           ParseDetailInternalPaths(const QDomElement &domElement, VPiece &detail) const;
+    void           ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const;
+    void           ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
     void           ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElement,

From e7adac78baf987dddd262b5e95303b32617fc7a6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 12 Jan 2017 16:08:27 +0200
Subject: [PATCH 148/208] Parse grainline and labels data tool Seam allowance.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp | 153 +++++++++++++++--------------
 src/app/valentina/xml/vpattern.h   |   3 +
 2 files changed, 84 insertions(+), 72 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 1b37c5a5b..155705c29 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -786,10 +786,13 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                         }
                         break;
                     case 1:// TagData
+                        ParsePieceDataTag(element, detail);
                         break;
                     case 2:// TagPatternInfo
+                        ParsePiecePatternInfo(element, detail);
                         break;
                     case 3:// TagGrainline
+                        ParsePieceGrainline(element, detail);
                         break;
                     case 4:// VToolSeamAllowance::TagCSA
                         ParsePieceCSARecords(element, detail);
@@ -800,78 +803,6 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                         break;
                 }
             }
-//                if (element.tagName() == TagData)
-//                {
-//                    bool bVisible = GetParametrBool(element, AttrVisible, trueStr);
-//                    detail.GetPatternPieceData().SetVisible(bVisible);
-//                    try
-//                    {
-//                        QString qsLetter = GetParametrString(element, AttrLetter, "");
-//                        detail.GetPatternPieceData().SetLetter(qsLetter);
-//                    } catch(...)
-//                    {
-//                        detail.GetPatternPieceData().SetLetter("");
-//                    }
-//                    QPointF ptPos;
-//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-//                    detail.GetPatternPieceData().SetPos(ptPos);
-//                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
-//                    detail.GetPatternPieceData().SetLabelWidth(dLW);
-//                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
-//                    detail.GetPatternPieceData().SetLabelHeight(dLH);
-//                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
-//                    detail.GetPatternPieceData().SetFontSize(iFS);
-//                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
-//                    detail.GetPatternPieceData().SetRotation(dRot);
-
-//                    QDomNodeList nodeListMCP = element.childNodes();
-//                    for (int iMCP = 0; iMCP < nodeListMCP.count(); ++iMCP)
-//                    {
-//                        MaterialCutPlacement mcp;
-//                        QDomElement domMCP = nodeListMCP.at(iMCP).toElement();
-//                        mcp.m_eMaterial = MaterialType(GetParametrUInt(domMCP, AttrMaterial, 0));
-//                        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-//                        {
-//                            mcp.m_qsMaterialUserDef = GetParametrString(domMCP, AttrUserDefined, "");
-//                        }
-//                        mcp.m_iCutNumber = static_cast<int>(GetParametrUInt(domMCP, AttrCutNumber, 0));
-//                        mcp.m_ePlacement = PlacementType(GetParametrUInt(domMCP, AttrPlacement, 0));
-//                        detail.GetPatternPieceData().Append(mcp);
-//                    }
-//                }
-//                else if (element.tagName() == TagPatternInfo)
-//                {
-//                    detail.GetPatternInfo().SetVisible(GetParametrBool(element, AttrVisible, trueStr));
-//                    QPointF ptPos;
-//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-//                    detail.GetPatternInfo().SetPos(ptPos);
-//                    qreal dLW = GetParametrDouble(element, VToolDetail::AttrWidth, "0");
-//                    detail.GetPatternInfo().SetLabelWidth(dLW);
-//                    qreal dLH = GetParametrDouble(element, VToolDetail::AttrHeight, "0");
-//                    detail.GetPatternInfo().SetLabelHeight(dLH);
-//                    int iFS = static_cast<int>(GetParametrUInt(element, VToolDetail::AttrFont, "0"));
-//                    detail.GetPatternInfo().SetFontSize(iFS);
-//                    qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0");
-//                    detail.GetPatternInfo().SetRotation(dRot);
-//                }
-//                else if (element.tagName() == TagGrainline)
-//                {
-//                    detail.GetGrainlineGeometry().SetVisible(GetParametrBool(element, AttrVisible, falseStr));
-//                    QPointF ptPos;
-//                    ptPos.setX(GetParametrDouble(element, AttrMx, "0"));
-//                    ptPos.setY(GetParametrDouble(element, AttrMy, "0"));
-//                    detail.GetGrainlineGeometry().SetPos(ptPos);
-//                    QString qsLength = GetParametrString(element, AttrLength, "0");
-//                    detail.GetGrainlineGeometry().SetLength(qsLength);
-//                    QString qsRot = GetParametrString(element, VToolDetail::AttrRotation, "90");
-//                    detail.GetGrainlineGeometry().SetRotation(qsRot);
-//                    VGrainlineGeometry::ArrowType eAT =
-//                            VGrainlineGeometry::ArrowType(GetParametrUInt(element, AttrArrows, "0"));
-//                    detail.GetGrainlineGeometry().SetArrowType(eAT);
-//                }
-//            }
         }
         VToolSeamAllowance::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
     }
@@ -959,6 +890,84 @@ void VPattern::ParsePieceInternalPaths(const QDomElement &domElement, VPiece &de
     detail.SetInternalPaths(records);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const
+{
+    detail.GetPatternPieceData().SetVisible(GetParametrBool(domElement, AttrVisible, trueStr));
+    try
+    {
+        QString qsLetter = GetParametrString(domElement, AttrLetter, "");
+        detail.GetPatternPieceData().SetLetter(qsLetter);
+    }
+    catch(const VExceptionEmptyParameter &e)
+    {
+        Q_UNUSED(e)
+        detail.GetPatternPieceData().SetLetter("");
+    }
+    QPointF ptPos;
+    ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
+    ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
+    detail.GetPatternPieceData().SetPos(ptPos);
+    qreal dLW = GetParametrDouble(domElement, VToolDetail::AttrWidth, "0");
+    detail.GetPatternPieceData().SetLabelWidth(dLW);
+    qreal dLH = GetParametrDouble(domElement, VToolDetail::AttrHeight, "0");
+    detail.GetPatternPieceData().SetLabelHeight(dLH);
+    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolDetail::AttrFont, "0"));
+    detail.GetPatternPieceData().SetFontSize(iFS);
+    qreal dRot = GetParametrDouble(domElement, VToolDetail::AttrRotation, "0");
+    detail.GetPatternPieceData().SetRotation(dRot);
+
+    QDomNodeList nodeListMCP = domElement.childNodes();
+    for (int iMCP = 0; iMCP < nodeListMCP.count(); ++iMCP)
+    {
+        MaterialCutPlacement mcp;
+        QDomElement domMCP = nodeListMCP.at(iMCP).toElement();
+        mcp.m_eMaterial = MaterialType(GetParametrUInt(domMCP, AttrMaterial, 0));
+        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
+        {
+            mcp.m_qsMaterialUserDef = GetParametrString(domMCP, AttrUserDefined, "");
+        }
+        mcp.m_iCutNumber = static_cast<int>(GetParametrUInt(domMCP, AttrCutNumber, 0));
+        mcp.m_ePlacement = PlacementType(GetParametrUInt(domMCP, AttrPlacement, 0));
+        detail.GetPatternPieceData().Append(mcp);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePiecePatternInfo(const QDomElement &domElement, VPiece &detail) const
+{
+    detail.GetPatternInfo().SetVisible(GetParametrBool(domElement, AttrVisible, trueStr));
+    QPointF ptPos;
+    ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
+    ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
+    detail.GetPatternInfo().SetPos(ptPos);
+    qreal dLW = GetParametrDouble(domElement, VToolDetail::AttrWidth, "0");
+    detail.GetPatternInfo().SetLabelWidth(dLW);
+    qreal dLH = GetParametrDouble(domElement, VToolDetail::AttrHeight, "0");
+    detail.GetPatternInfo().SetLabelHeight(dLH);
+    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolDetail::AttrFont, "0"));
+    detail.GetPatternInfo().SetFontSize(iFS);
+    qreal dRot = GetParametrDouble(domElement, VToolDetail::AttrRotation, "0");
+    detail.GetPatternInfo().SetRotation(dRot);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPattern::ParsePieceGrainline(const QDomElement &domElement, VPiece &detail) const
+{
+    detail.GetGrainlineGeometry().SetVisible(GetParametrBool(domElement, AttrVisible, falseStr));
+    QPointF ptPos;
+    ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
+    ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
+    detail.GetGrainlineGeometry().SetPos(ptPos);
+    QString qsLength = GetParametrString(domElement, AttrLength, "0");
+    detail.GetGrainlineGeometry().SetLength(qsLength);
+    QString qsRot = GetParametrString(domElement, VToolDetail::AttrRotation, "90");
+    detail.GetGrainlineGeometry().SetRotation(qsRot);
+    VGrainlineGeometry::ArrowType eAT =
+            VGrainlineGeometry::ArrowType(GetParametrUInt(domElement, AttrArrows, "0"));
+    detail.GetGrainlineGeometry().SetArrowType(eAT);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDetails parse details tag.
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 0ea76b4dd..8b444e36e 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -124,6 +124,9 @@ private:
     void           ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const;
+    void           ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const;
+    void           ParsePiecePatternInfo(const QDomElement &domElement, VPiece &detail) const;
+    void           ParsePieceGrainline(const QDomElement &domElement, VPiece &detail) const;
     void           ParseDetails(const QDomElement &domElement, const Document &parse);
 
     void           ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElement,

From 297b73a951e138192709c383f09233b9c48e1eb5 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 12 Jan 2017 19:09:00 +0200
Subject: [PATCH 149/208] VToolSeamAllowance add grainline and labels. Only the
 dialog.

--HG--
branch : feature
---
 .../dialogs/tools/dialogseamallowance.cpp     | 599 ++++++++++++++--
 .../dialogs/tools/dialogseamallowance.h       |  45 +-
 .../dialogs/tools/dialogseamallowance.ui      | 637 +++++++++++++++++-
 3 files changed, 1218 insertions(+), 63 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 8dea602d6..8738ac42d 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -30,86 +30,48 @@
 #include "ui_dialogseamallowance.h"
 #include "../vpatterndb/vpiecenode.h"
 #include "../vpatterndb/vpiecepath.h"
+#include "../vpatterndb/calculator.h"
 #include "visualization/path/vistoolpiece.h"
 #include "dialogpiecepath.h"
 #include "../../undocommands/savepiecepathoptions.h"
+#include "../support/dialogeditwrongformula.h"
 
 #include <QMenu>
+#include <QtNumeric>
 
 //---------------------------------------------------------------------------------------------------------------------
 DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
       ui(new Ui::DialogSeamAllowance),
       applyAllowed(false),// By default disabled
+      m_bAddMode(true),
       m_mx(0),
       m_my(0),
-      m_dialog()
+      m_dialog(),
+      m_qslMaterials(),
+      m_qslPlacements(),
+      m_conMCP(),
+      m_oldData(),
+      m_oldGeom(),
+      m_oldGrainline(),
+      m_iRotBaseHeight(0),
+      m_iLenBaseHeight(0)
 {
     ui->setupUi(this);
 
     InitOkCancelApply(ui);
     EnableApply(applyAllowed);
 
+    InitMainPathTab();
+    InitSeamAllowanceTab();
+    InitInternalPathsTab();
+    InitPatternPieceDataTab();
+    InitGrainlineTab();
+
     flagName = true;//We have default name of piece.
     flagError = MainPathIsValid();
     CheckState();
 
-    ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
-
-    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
-    ui->doubleSpinBoxSeams->setSuffix(suffix);
-    ui->doubleSpinBoxSABefore->setSuffix(suffix);
-    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
-
-    if(qApp->patternUnit() == Unit::Inch)
-    {
-        ui->doubleSpinBoxSeams->setDecimals(5);
-        ui->doubleSpinBoxSABefore->setDecimals(5);
-        ui->doubleSpinBoxSAAfter->setDecimals(5);
-    }
-    // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
-    ui->doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
-
-    InitNodesList();
-    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogSeamAllowance::NodeChanged);
-
-    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefBefore);
-    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefAfter);
-
-    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
-
-    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogSeamAllowance::ChangedSABefore);
-    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogSeamAllowance::ChangedSAAfter);
-
-    ui->listWidgetMainPath->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->listWidgetMainPath, &QListWidget::customContextMenuRequested, this,
-            &DialogSeamAllowance::ShowMainPathContextMenu);
-    connect(ui->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
-    connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
-
-    InitNodeAngles(ui->comboBoxAngle);
-    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogSeamAllowance::NodeAngleChanged);
-
-    ui->listWidgetCustomSA->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->listWidgetCustomSA, &QListWidget::customContextMenuRequested, this,
-            &DialogSeamAllowance::ShowCustomSAContextMenu);
-    connect(ui->listWidgetCustomSA, &QListWidget::currentRowChanged, this, &DialogSeamAllowance::CustomSAChanged);
-    connect(ui->comboBoxStartPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogSeamAllowance::CSAStartPointChanged);
-    connect(ui->comboBoxEndPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogSeamAllowance::CSAEndPointChanged);
-    connect(ui->comboBoxIncludeType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogSeamAllowance::CSAIncludeTypeChanged);
-
-    ui->listWidgetInternalPaths->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->listWidgetInternalPaths, &QListWidget::customContextMenuRequested, this,
-            &DialogSeamAllowance::ShowInternalPathsContextMenu);
-
     if (not applyAllowed)
     {
         vis = new VisToolPiece(data);
@@ -132,6 +94,8 @@ void DialogSeamAllowance::EnableApply(bool enable)
     applyAllowed = enable;
     ui->tabSeamAllowance->setEnabled(applyAllowed);
     ui->tabInternalPaths->setEnabled(applyAllowed);
+    ui->tabPatternPieceData->setEnabled(applyAllowed);
+    ui->tabGrainline->setEnabled(applyAllowed);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -178,11 +142,34 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
     ui->checkBoxForbidFlipping->setChecked(piece.IsForbidFlipping());
     ui->doubleSpinBoxSeams->setValue(piece.GetSAWidth());
     ui->checkBoxSeams->setChecked(piece.IsSeamAllowance());
+    ui->lineEditName->setText(piece.GetName());
 
     m_mx = piece.GetMx();
     m_my = piece.GetMy();
 
+    ui->lineEditLetter->setText(piece.GetPatternPieceData().GetLetter());
+    ui->checkBoxDetail->setChecked(piece.GetPatternPieceData().IsVisible());
+    ui->checkBoxPattern->setChecked(piece.GetPatternInfo().IsVisible());
+
+    m_conMCP.clear();
+    for (int i = 0; i < piece.GetPatternPieceData().GetMCPCount(); ++i)
+    {
+        m_conMCP << piece.GetPatternPieceData().GetMCP(i);
+    }
+
+    UpdateList();
+
+    ui->checkBoxGrainline->setChecked(piece.GetGrainlineGeometry().IsVisible());
+    ui->lineEditRotFormula->setPlainText(piece.GetGrainlineGeometry().GetRotation());
+    ui->lineEditLenFormula->setPlainText(piece.GetGrainlineGeometry().GetLength());
+    ui->comboBoxArrow->setCurrentIndex(int(piece.GetGrainlineGeometry().GetArrowType()));
+
+    m_oldData = piece.GetPatternPieceData();
+    m_oldGeom = piece.GetPatternInfo();
+    m_oldGrainline = piece.GetGrainlineGeometry();
+
     ValidObjects(MainPathIsValid());
+    EnableGrainlineRotation();
 
     ListChanged();
 }
@@ -303,6 +290,140 @@ void DialogSeamAllowance::CheckState()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::UpdateList()
+{
+    ui->listWidgetMCP->clear();
+    for (int i = 0; i < m_conMCP.count(); ++i)
+    {
+        MaterialCutPlacement mcp = m_conMCP.at(i);
+        QString qsText = tr("Cut %1 of %2%3").arg(mcp.m_iCutNumber);
+        if (mcp.m_eMaterial < MaterialType::mtUserDefined)
+        {
+            qsText = qsText.arg(m_qslMaterials[int(mcp.m_eMaterial)]);
+        }
+        else
+        {
+            qsText = qsText.arg(mcp.m_qsMaterialUserDef);
+        }
+        if (mcp.m_ePlacement == PlacementType::ptCutOnFold)
+        {
+            qsText = qsText.arg(QLatin1String(" ") + tr("on Fold"));
+        }
+        else
+        {
+            qsText = qsText.arg("");
+        }
+
+        ui->listWidgetMCP->addItem(qsText);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::AddUpdate()
+{
+    MaterialCutPlacement mcp;
+    QStringList qslUserMaterials = qApp->Settings()->GetUserDefinedMaterials();
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+    int i = ui->comboBoxMaterial->itemData(ui->comboBoxMaterial->currentIndex()).toInt();
+#else
+    int i = ui->comboBoxMaterial->currentData().toInt();
+#endif
+    QString qsMat = ui->comboBoxMaterial->currentText();
+    if (i < m_qslMaterials.count() && qsMat == m_qslMaterials[i])
+    {
+        mcp.m_eMaterial = MaterialType(i);
+        mcp.m_qsMaterialUserDef.clear();
+    }
+    else
+    {
+        mcp.m_eMaterial = MaterialType::mtUserDefined;
+        mcp.m_qsMaterialUserDef = qsMat;
+        // check if we have new user defined material
+        bool bFound = false;
+        for (int i = 0; i < qslUserMaterials.count() && bFound == false; ++i)
+        {
+            if (mcp.m_qsMaterialUserDef == qslUserMaterials[i])
+            {
+                bFound = true;
+            }
+        }
+        if (bFound == false)
+        {
+            qApp->Settings()->AddUserDefinedMaterial(mcp.m_qsMaterialUserDef);
+            qApp->Settings()->sync();
+            ui->comboBoxMaterial->addItem(mcp.m_qsMaterialUserDef, int(MaterialType::mtUserDefined));
+        }
+    }
+
+    mcp.m_iCutNumber = ui->spinBoxCutNumber->value();
+    mcp.m_ePlacement = PlacementType(ui->comboBoxPlacement->currentIndex());
+
+    if (m_bAddMode == true)
+    {
+        m_conMCP << mcp;
+    }
+    else
+    {
+        int iR = ui->listWidgetMCP->currentRow();
+        SCASSERT(iR >= 0)
+        m_conMCP[iR] = mcp;
+        SetAddMode();
+    }
+    UpdateList();
+    ClearFields();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::Cancel()
+{
+    ClearFields();
+    SetAddMode();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::Remove()
+{
+    int iR = ui->listWidgetMCP->currentRow();
+    SCASSERT(iR >= 0)
+    m_conMCP.removeAt(iR);
+    UpdateList();
+    ClearFields();
+    SetAddMode();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::NameDetailChanged()
+{
+    SCASSERT(labelEditNamePoint != nullptr)
+    QLineEdit* edit = qobject_cast<QLineEdit*>(sender());
+    if (edit)
+    {
+        if (edit->text().isEmpty())
+        {
+            flagName = false;
+            ChangeColor(labelEditNamePoint, Qt::red);
+            QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png");
+            ui->tabWidget->setTabIcon(1, icon);
+        }
+        else
+        {
+            flagName = true;
+            ChangeColor(labelEditNamePoint, okColor);
+            QIcon icon;
+            ui->tabWidget->setTabIcon(1, icon);
+        }
+    }
+    CheckState();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::MaterialChanged()
+{
+    ui->pushButtonAdd->setEnabled(ui->comboBoxMaterial->currentText().isEmpty() == false);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ShowMainPathContextMenu(const QPoint &pos)
 {
@@ -738,6 +859,208 @@ void DialogSeamAllowance::PathDialogClosed(int result)
     delete m_dialog;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::UpdateValues()
+{
+    QPlainTextEdit* apleSender[2];
+    apleSender[0] = ui->lineEditRotFormula;
+    apleSender[1] = ui->lineEditLenFormula;
+    bool bFormulasOK = true;
+
+    for (int i = 0; i < 2; ++i)
+    {
+        QLabel* plbVal;
+        QLabel* plbText;
+        QString qsUnit;
+        if (i == 0)
+        {
+            plbVal = ui->labelRot;
+            plbText = ui->labelEditRot;
+            QChar ch(0x00b0);
+            qsUnit = ch;
+        }
+        else
+        {
+            plbVal = ui->labelLen;
+            plbText = ui->labelEditLen;
+            qsUnit = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit());
+        }
+
+        plbVal->setToolTip(tr("Value"));
+
+        QString qsFormula = apleSender[i]->toPlainText().simplified();
+        Calculator cal;
+        QString qsVal;
+        try
+        {
+            qsFormula.replace("\n", " ");
+            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
+            qreal dVal;
+            dVal = cal.EvalFormula(data->PlainVariables(), qsFormula);
+            if (qIsInf(dVal) == true || qIsNaN(dVal) == true)
+            {
+                throw qmu::QmuParserError(tr("Infinite/undefined result"));
+            }
+            else if (i == 1 && dVal <= 0.0)
+            {
+                throw qmu::QmuParserError(tr("Length should be positive"));
+            }
+            else
+            {
+                qsVal.setNum(dVal, 'f', 2);
+                ChangeColor(plbText, okColor);
+            }
+        }
+        catch (qmu::QmuParserError &e)
+        {
+            qsVal.clear();
+            ChangeColor(plbText, Qt::red);
+            bFormulasOK = false;
+            plbVal->setToolTip(tr("Parser error: %1").arg(e.GetMsg()));
+        }
+
+        if (qsVal.isEmpty() == false)
+        {
+            qsVal += qsUnit;
+        }
+        plbVal->setText(qsVal);
+    }
+
+    bOk->setEnabled(bFormulasOK);
+    if (bFormulasOK == false)
+    {
+        QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png");
+        ui->tabWidget->setTabIcon(ui->tabWidget->indexOf(ui->tabGrainline), icon);
+    }
+    else
+    {
+        ResetWarning();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetAddMode()
+{
+    ui->pushButtonAdd->setText(tr("Add"));
+    ui->pushButtonCancel->hide();
+    ui->pushButtonRemove->hide();
+    ui->listWidgetMCP->setCurrentRow(-1);
+    m_bAddMode = true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetEditMode()
+{
+    int iR = ui->listWidgetMCP->currentRow();
+    // this method can be called by clicking on item or by update. In the latter case there is nothing else to do!
+    if (iR < 0 || iR >= m_conMCP.count())
+    {
+        return;
+    }
+
+    ui->pushButtonAdd->setText(tr("Update"));
+    ui->pushButtonCancel->show();
+    ui->pushButtonRemove->show();
+
+    MaterialCutPlacement mcp = m_conMCP.at(iR);
+    if (mcp.m_eMaterial == MaterialType::mtUserDefined)
+    {
+        int iRow = qApp->Settings()->GetUserDefinedMaterials().indexOf(mcp.m_qsMaterialUserDef);
+        if (iRow >= 0)
+        {
+            ui->comboBoxMaterial->setCurrentIndex(iRow + m_qslMaterials.count());
+        }
+        else
+        {
+            ui->comboBoxMaterial->setCurrentText(mcp.m_qsMaterialUserDef);
+        }
+    }
+    else
+    {
+        ui->comboBoxMaterial->setCurrentIndex(int(mcp.m_eMaterial));
+    }
+    ui->spinBoxCutNumber->setValue(mcp.m_iCutNumber);
+    ui->comboBoxPlacement->setCurrentIndex(int(mcp.m_ePlacement));
+
+    m_bAddMode = false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EnableGrainlineRotation()
+{
+    ui->lineEditRotFormula->setEnabled(ui->checkBoxGrainline->isChecked());
+    ui->lineEditLenFormula->setEnabled(ui->checkBoxGrainline->isChecked());
+    ui->pushButtonRot->setEnabled(ui->checkBoxGrainline->isChecked());
+    ui->pushButtonLen->setEnabled(ui->checkBoxGrainline->isChecked());
+    ui->pushButtonShowLen->setEnabled(ui->checkBoxGrainline->isChecked());
+    ui->pushButtonShowRot->setEnabled(ui->checkBoxGrainline->isChecked());
+
+    if (ui->checkBoxGrainline->isChecked() == true)
+    {
+        UpdateValues();
+    }
+    else
+    {
+        ChangeColor(ui->labelEditLen, okColor);
+        ChangeColor(ui->labelEditRot, okColor);
+        bOk->setEnabled(true);
+        ResetWarning();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EditFormula()
+{
+    QPlainTextEdit* pleFormula;
+    bool bCheckZero;
+
+    if (sender() == ui->pushButtonLen)
+    {
+        pleFormula = ui->lineEditLenFormula;
+        bCheckZero = true;
+    }
+    else if (sender() == ui->pushButtonRot)
+    {
+        pleFormula = ui->lineEditRotFormula;
+        bCheckZero = false;
+    }
+    else
+    {
+        // should not get here!
+        return;
+    }
+
+    DialogEditWrongFormula dlg(data, NULL_ID, this);
+    dlg.SetFormula(pleFormula->toPlainText());
+    dlg.setCheckZero(bCheckZero);
+    if (dlg.exec() == QDialog::Accepted)
+    {
+        QString qsFormula = dlg.GetFormula();
+        qsFormula.replace("\n", " ");
+        pleFormula->setPlainText(qsFormula);
+        UpdateValues();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::DeployRotation()
+{
+    DeployFormula(ui->lineEditRotFormula, ui->pushButtonShowRot, m_iRotBaseHeight);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::DeployLength()
+{
+    DeployFormula(ui->lineEditLenFormula, ui->pushButtonShowLen, m_iLenBaseHeight);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ResetWarning()
+{
+    QIcon icon;
+    ui->tabWidget->setTabIcon(ui->tabWidget->indexOf(ui->tabGrainline), icon);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::CreatePiece() const
 {
@@ -767,9 +1090,33 @@ VPiece DialogSeamAllowance::CreatePiece() const
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
     piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
     piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
+    piece.SetName(ui->lineEditName->text());
     piece.SetMx(m_mx);
     piece.SetMy(m_my);
 
+    piece.GetPatternPieceData().SetLetter(ui->lineEditLetter->text());
+
+    for (int i = 0; i < m_conMCP.count(); ++i)
+    {
+        piece.GetPatternPieceData().Append(m_conMCP[i]);
+    }
+
+    piece.GetPatternPieceData().SetPos(m_oldData.GetPos());
+    piece.GetPatternPieceData().SetLabelWidth(m_oldData.GetLabelWidth());
+    piece.GetPatternPieceData().SetLabelHeight(m_oldData.GetLabelHeight());
+    piece.GetPatternPieceData().SetFontSize(m_oldData.GetFontSize());
+    piece.GetPatternPieceData().SetRotation(m_oldData.GetRotation());
+    piece.GetPatternPieceData().SetVisible(ui->checkBoxDetail->isChecked());
+
+    piece.GetPatternInfo() = m_oldGeom;
+    piece.GetPatternInfo().SetVisible(ui->checkBoxPattern->isChecked());
+
+    piece.GetGrainlineGeometry() = m_oldGrainline;
+    piece.GetGrainlineGeometry().SetVisible(ui->checkBoxGrainline->isChecked());
+    piece.GetGrainlineGeometry().SetRotation(ui->lineEditRotFormula->toPlainText());
+    piece.GetGrainlineGeometry().SetLength(ui->lineEditLenFormula->toPlainText());
+    piece.GetGrainlineGeometry().SetArrowType(VGrainlineGeometry::ArrowType(ui->comboBoxArrow->currentIndex()));
+
     return piece;
 }
 
@@ -1006,6 +1353,67 @@ void DialogSeamAllowance::SetCurrentSAAfter(qreal value)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitMainPathTab()
+{
+    ui->checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
+
+    ui->listWidgetMainPath->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetMainPath, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowMainPathContextMenu);
+    connect(ui->listWidgetMainPath->model(), &QAbstractItemModel::rowsMoved, this, &DialogSeamAllowance::ListChanged);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitSeamAllowanceTab()
+{
+    connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
+
+    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    ui->doubleSpinBoxSeams->setSuffix(suffix);
+    ui->doubleSpinBoxSABefore->setSuffix(suffix);
+    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
+
+    if(qApp->patternUnit() == Unit::Inch)
+    {
+        ui->doubleSpinBoxSeams->setDecimals(5);
+        ui->doubleSpinBoxSABefore->setDecimals(5);
+        ui->doubleSpinBoxSAAfter->setDecimals(5);
+    }
+    // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
+    ui->doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
+
+    InitNodesList();
+    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::NodeChanged);
+
+    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefBefore);
+    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefAfter);
+
+    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
+
+    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogSeamAllowance::ChangedSABefore);
+    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
+            this, &DialogSeamAllowance::ChangedSAAfter);
+
+    InitNodeAngles(ui->comboBoxAngle);
+    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::NodeAngleChanged);
+
+    ui->listWidgetCustomSA->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetCustomSA, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowCustomSAContextMenu);
+    connect(ui->listWidgetCustomSA, &QListWidget::currentRowChanged, this, &DialogSeamAllowance::CustomSAChanged);
+    connect(ui->comboBoxStartPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAStartPointChanged);
+    connect(ui->comboBoxEndPoint, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAEndPointChanged);
+    connect(ui->comboBoxIncludeType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogSeamAllowance::CSAIncludeTypeChanged);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::InitCSAPoint(QComboBox *box)
 {
@@ -1036,6 +1444,75 @@ void DialogSeamAllowance::InitSAIncludeType()
                                      static_cast<unsigned char>(PiecePathIncludeType::AsCustomSA));
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitInternalPathsTab()
+{
+    ui->listWidgetInternalPaths->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidgetInternalPaths, &QListWidget::customContextMenuRequested, this,
+            &DialogSeamAllowance::ShowInternalPathsContextMenu);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitPatternPieceDataTab()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+    ui->lineEditName->setClearButtonEnabled(true);
+    ui->lineEditLetter->setClearButtonEnabled(true);
+#endif
+
+    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogSeamAllowance::NameDetailChanged);
+
+    m_qslMaterials << QApplication::translate("Detail", "Fabric", 0)
+                   << QApplication::translate("Detail", "Lining", 0)
+                   << QApplication::translate("Detail", "Interfacing", 0)
+                   << QApplication::translate("Detail", "Interlining", 0);
+
+    for (int i = 0; i < m_qslMaterials.count(); ++i)
+    {
+        ui->comboBoxMaterial->addItem(m_qslMaterials[i], i);
+    }
+
+    const QStringList qsl = qApp->Settings()->GetUserDefinedMaterials();
+    for (int i = 0; i < qsl.count(); ++i)
+    {
+        ui->comboBoxMaterial->addItem(qsl.at(i), int(MaterialType::mtUserDefined));
+    }
+
+    m_qslPlacements << tr("None") << tr("Cut on fold");
+    ui->comboBoxPlacement->addItems(m_qslPlacements);
+    ui->pushButtonRot->setIcon(QIcon("://icon/16x16/fx.png"));
+    ui->pushButtonLen->setIcon(QIcon("://icon/16x16/fx.png"));
+
+    connect(ui->pushButtonAdd, &QPushButton::clicked, this, &DialogSeamAllowance::AddUpdate);
+    connect(ui->pushButtonCancel, &QPushButton::clicked, this, &DialogSeamAllowance::Cancel);
+    connect(ui->pushButtonRemove, &QPushButton::clicked, this, &DialogSeamAllowance::Remove);
+    connect(ui->listWidgetMCP, &QListWidget::itemClicked, this, &DialogSeamAllowance::SetEditMode);
+    connect(ui->comboBoxMaterial, &QComboBox::currentTextChanged, this, &DialogSeamAllowance::MaterialChanged);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::InitGrainlineTab()
+{
+    connect(ui->checkBoxGrainline, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableGrainlineRotation);
+    connect(ui->pushButtonRot, &QPushButton::clicked, this, &DialogSeamAllowance::EditFormula);
+    connect(ui->pushButtonLen, &QPushButton::clicked, this, &DialogSeamAllowance::EditFormula);
+    connect(ui->lineEditLenFormula, &QPlainTextEdit::textChanged, this, &DialogSeamAllowance::UpdateValues);
+    connect(ui->lineEditRotFormula, &QPlainTextEdit::textChanged, this, &DialogSeamAllowance::UpdateValues);
+
+    connect(ui->pushButtonShowRot, &QPushButton::clicked, this, &DialogSeamAllowance::DeployRotation);
+    connect(ui->pushButtonShowLen, &QPushButton::clicked, this, &DialogSeamAllowance::DeployLength);
+
+    SetAddMode();
+    EnableGrainlineRotation();
+
+    ui->comboBoxArrow->addItem(tr("Both"));
+    ui->comboBoxArrow->addItem(tr("Just front"));
+    ui->comboBoxArrow->addItem(tr("Just rear"));
+
+    m_iRotBaseHeight = ui->lineEditRotFormula->height();
+    m_iLenBaseHeight = ui->lineEditLenFormula->height();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::UpdateCurrentCustomSARecord()
 {
@@ -1065,3 +1542,11 @@ void DialogSeamAllowance::UpdateCurrentInternalPathRecord()
     const quint32 path = qvariant_cast<quint32>(item->data(Qt::UserRole));
     item->setText(GetPathName(path));
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::ClearFields()
+{
+    ui->comboBoxMaterial->setCurrentIndex(0);
+    ui->spinBoxCutNumber->setValue(0);
+    ui->comboBoxPlacement->setCurrentIndex(0);
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 2890ea3f4..4e7f659a8 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -31,6 +31,9 @@
 
 #include "dialogtool.h"
 #include "../vpatterndb/vpiece.h"
+#include "../vpatterndb/vpatterninfogeometry.h"
+#include "../vpatterndb/vpatternpiecedata.h"
+#include "../vpatterndb/vgrainlinegeometry.h"
 
 namespace Ui
 {
@@ -59,7 +62,15 @@ protected:
     virtual void SaveData() Q_DECL_OVERRIDE;
     virtual void CheckState() Q_DECL_OVERRIDE;
 
+protected slots:
+    void UpdateList();
+    void AddUpdate();
+    void Cancel();
+    void Remove();
+
 private slots:
+    void NameDetailChanged();
+    void MaterialChanged();
     void ShowMainPathContextMenu(const QPoint &pos);
     void ShowCustomSAContextMenu(const QPoint &pos);
     void ShowInternalPathsContextMenu(const QPoint &pos);
@@ -78,16 +89,37 @@ private slots:
     void CustomSAChanged(int row);
     void PathDialogClosed(int result);
 
+    void UpdateValues();
+    void SetAddMode();
+    void SetEditMode();
+    void EnableGrainlineRotation();
+    void EditFormula();
+    void DeployRotation();
+    void DeployLength();
+    void ResetWarning();
+
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
 
     Ui::DialogSeamAllowance *ui;
     bool   applyAllowed;
+    bool   m_bAddMode;
     qreal  m_mx;
     qreal  m_my;
 
     QPointer<DialogTool> m_dialog;
 
+    QStringList      m_qslMaterials;
+    QStringList      m_qslPlacements;
+    // temporary container for Material/Cut/Placement 3-tuples
+    MCPContainer m_conMCP;
+
+    VPatternPieceData    m_oldData;
+    VPatternInfoGeometry m_oldGeom;
+    VGrainlineGeometry   m_oldGrainline;
+    int                  m_iRotBaseHeight;
+    int                  m_iLenBaseHeight;
+
     VPiece CreatePiece() const;
 
     void    NewMainPathItem(const VPieceNode &node);
@@ -97,11 +129,9 @@ private:
     bool    MainPathIsValid() const;
     void    ValidObjects(bool value);
     bool    MainPathIsClockwise() const;
-    void    InitNodesList();
-    void    InitCSAPoint(QComboBox *box);
-    void    InitSAIncludeType();
     void    UpdateCurrentCustomSARecord();
     void    UpdateCurrentInternalPathRecord();
+    void    ClearFields();
 
     QListWidgetItem *GetItemById(quint32 id);
 
@@ -109,6 +139,15 @@ private:
 
     void SetCurrentSABefore(qreal value);
     void SetCurrentSAAfter(qreal value);
+
+    void InitMainPathTab();
+    void InitSeamAllowanceTab();
+    void InitNodesList();
+    void InitCSAPoint(QComboBox *box);
+    void InitSAIncludeType();
+    void InitInternalPathsTab();
+    void InitPatternPieceDataTab();
+    void InitGrainlineTab();
 };
 
 #endif // DIALOGSEAMALLOWANCE_H
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index 75ff3623e..ff18f4b2d 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>476</width>
-    <height>504</height>
+    <width>521</width>
+    <height>493</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>0</number>
+      <number>4</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -399,6 +399,637 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tabPatternPieceData">
+      <attribute name="title">
+       <string>Pattern piece data</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_9">
+       <item>
+        <widget class="QSplitter" name="splitter_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <widget class="QWidget" name="layoutWidget1">
+          <layout class="QVBoxLayout" name="verticalLayout_7">
+           <item>
+            <layout class="QFormLayout" name="formLayout_3">
+             <property name="fieldGrowthPolicy">
+              <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+             </property>
+             <item row="0" column="0">
+              <widget class="QLabel" name="label_5">
+               <property name="text">
+                <string>Letter:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="1">
+              <widget class="QLineEdit" name="lineEditLetter">
+               <property name="maxLength">
+                <number>3</number>
+               </property>
+               <property name="placeholderText">
+                <string>Letter of pattern piece</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="labelEditName">
+               <property name="text">
+                <string>Name of detail:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="QLineEdit" name="lineEditName">
+               <property name="text">
+                <string>Detail</string>
+               </property>
+               <property name="maxLength">
+                <number>30</number>
+               </property>
+               <property name="placeholderText">
+                <string>Name can't be empty</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <widget class="QGroupBox" name="groupBox_2">
+             <property name="title">
+              <string>Material/Cut number/Placement</string>
+             </property>
+             <layout class="QGridLayout" name="gridLayout_3">
+              <item row="1" column="0">
+               <widget class="QLabel" name="label_8">
+                <property name="text">
+                 <string>Cut number:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0" colspan="2">
+               <widget class="QLabel" name="label_7">
+                <property name="text">
+                 <string>Material type:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="2" colspan="2">
+               <widget class="QComboBox" name="comboBoxMaterial">
+                <property name="toolTip">
+                 <string>You can choose one of the predefined materials or enter a new one</string>
+                </property>
+                <property name="editable">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="2" colspan="2">
+               <widget class="QSpinBox" name="spinBoxCutNumber">
+                <property name="minimum">
+                 <number>1</number>
+                </property>
+                <property name="maximum">
+                 <number>1000</number>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0">
+               <widget class="QLabel" name="label_9">
+                <property name="text">
+                 <string>Placement:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="2" colspan="2">
+               <widget class="QComboBox" name="comboBoxPlacement"/>
+              </item>
+              <item row="3" column="0">
+               <widget class="QPushButton" name="pushButtonAdd">
+                <property name="text">
+                 <string>Add</string>
+                </property>
+               </widget>
+              </item>
+              <item row="3" column="1" colspan="2">
+               <widget class="QPushButton" name="pushButtonCancel">
+                <property name="text">
+                 <string>Cancel</string>
+                </property>
+               </widget>
+              </item>
+              <item row="3" column="3">
+               <widget class="QPushButton" name="pushButtonRemove">
+                <property name="text">
+                 <string>Remove</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
+            <layout class="QVBoxLayout" name="verticalLayout_8">
+             <item>
+              <widget class="QCheckBox" name="checkBoxDetail">
+               <property name="text">
+                <string>Detail label visible</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QCheckBox" name="checkBoxPattern">
+               <property name="text">
+                <string>Pattern label visible</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QListWidget" name="listWidgetMCP">
+          <property name="minimumSize">
+           <size>
+            <width>180</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="focusPolicy">
+           <enum>Qt::ClickFocus</enum>
+          </property>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tabGrainline">
+      <attribute name="title">
+       <string>Grainline</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_10">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item>
+          <widget class="QCheckBox" name="checkBoxGrainline">
+           <property name="text">
+            <string>Grainline visible</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_11">
+         <item alignment="Qt::AlignLeft">
+          <widget class="QLabel" name="labelEditRot">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>159</red>
+                 <green>158</green>
+                 <blue>158</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="text">
+            <string>Rotation:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_4">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QToolButton" name="pushButtonRot">
+           <property name="toolTip">
+            <string>Formula wizard</string>
+           </property>
+           <property name="text">
+            <string notr="true">...</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../../../vmisc/share/resources/icon.qrc">
+             <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>24</width>
+             <height>24</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="labelEqual">
+           <property name="text">
+            <string/>
+           </property>
+           <property name="pixmap">
+            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="labelRot">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>87</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="baseSize">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Value</string>
+           </property>
+           <property name="text">
+            <string notr="true">_</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_12">
+         <item>
+          <widget class="QPlainTextEdit" name="lineEditRotFormula">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>28</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Calculation</string>
+           </property>
+           <property name="tabChangesFocus">
+            <bool>true</bool>
+           </property>
+           <property name="plainText">
+            <string notr="true"/>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pushButtonShowRot">
+           <property name="maximumSize">
+            <size>
+             <width>18</width>
+             <height>18</height>
+            </size>
+           </property>
+           <property name="sizeIncrement">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+           <property name="text">
+            <string notr="true"/>
+           </property>
+           <property name="icon">
+            <iconset theme="go-down">
+             <normaloff>.</normaloff>.</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="flat">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_13">
+         <item alignment="Qt::AlignLeft">
+          <widget class="QLabel" name="labelEditLen">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>159</red>
+                 <green>158</green>
+                 <blue>158</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="text">
+            <string>Length:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_5">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QToolButton" name="pushButtonLen">
+           <property name="toolTip">
+            <string>Formula wizard</string>
+           </property>
+           <property name="text">
+            <string notr="true">...</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../../../vmisc/share/resources/icon.qrc">
+             <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>24</width>
+             <height>24</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="labelEqual_2">
+           <property name="text">
+            <string/>
+           </property>
+           <property name="pixmap">
+            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="labelLen">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>87</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="baseSize">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Value</string>
+           </property>
+           <property name="text">
+            <string notr="true">_</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_14">
+         <item>
+          <widget class="QPlainTextEdit" name="lineEditLenFormula">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>28</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Calculation</string>
+           </property>
+           <property name="tabChangesFocus">
+            <bool>true</bool>
+           </property>
+           <property name="plainText">
+            <string notr="true"/>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pushButtonShowLen">
+           <property name="maximumSize">
+            <size>
+             <width>18</width>
+             <height>18</height>
+            </size>
+           </property>
+           <property name="sizeIncrement">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+           <property name="text">
+            <string notr="true"/>
+           </property>
+           <property name="icon">
+            <iconset theme="go-down">
+             <normaloff>.</normaloff>.</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="flat">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_5">
+         <item>
+          <widget class="QLabel" name="labelEditLen_2">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>0</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>159</red>
+                 <green>158</green>
+                 <blue>158</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
+           </property>
+           <property name="text">
+            <string>Arrows:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="comboBoxArrow"/>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>

From 29490b9e66d2734b866ce39417b357765b533213 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 12 Jan 2017 19:17:13 +0200
Subject: [PATCH 150/208] Removed dialog Detail.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/dialogs.pri           |    3 -
 src/libs/vtools/dialogs/tooldialogs.h         |    1 -
 .../vtools/dialogs/tools/dialogdetail.cpp     | 1046 ---------------
 src/libs/vtools/dialogs/tools/dialogdetail.h  |  151 ---
 src/libs/vtools/dialogs/tools/dialogdetail.ui | 1116 -----------------
 src/libs/vtools/tools/vtooldetail.cpp         |  185 ++-
 6 files changed, 92 insertions(+), 2410 deletions(-)
 delete mode 100644 src/libs/vtools/dialogs/tools/dialogdetail.cpp
 delete mode 100644 src/libs/vtools/dialogs/tools/dialogdetail.h
 delete mode 100644 src/libs/vtools/dialogs/tools/dialogdetail.ui

diff --git a/src/libs/vtools/dialogs/dialogs.pri b/src/libs/vtools/dialogs/dialogs.pri
index 9073adfcb..d21b0a6ba 100644
--- a/src/libs/vtools/dialogs/dialogs.pri
+++ b/src/libs/vtools/dialogs/dialogs.pri
@@ -11,7 +11,6 @@ HEADERS += \
     $$PWD/tools/dialogcutarc.h \
     $$PWD/tools/dialogcutspline.h \
     $$PWD/tools/dialogcutsplinepath.h \
-    $$PWD/tools/dialogdetail.h \
     $$PWD/tools/dialogendline.h \
     $$PWD/tools/dialogheight.h \
     $$PWD/tools/dialogline.h \
@@ -55,7 +54,6 @@ SOURCES += \
     $$PWD/tools/dialogcutarc.cpp \
     $$PWD/tools/dialogcutspline.cpp \
     $$PWD/tools/dialogcutsplinepath.cpp \
-    $$PWD/tools/dialogdetail.cpp \
     $$PWD/tools/dialogendline.cpp \
     $$PWD/tools/dialogheight.cpp \
     $$PWD/tools/dialogline.cpp \
@@ -99,7 +97,6 @@ FORMS += \
     $$PWD/tools/dialogcutarc.ui \
     $$PWD/tools/dialogcutspline.ui \
     $$PWD/tools/dialogcutsplinepath.ui \
-    $$PWD/tools/dialogdetail.ui \
     $$PWD/tools/dialogendline.ui \
     $$PWD/tools/dialogheight.ui \
     $$PWD/tools/dialogline.ui \
diff --git a/src/libs/vtools/dialogs/tooldialogs.h b/src/libs/vtools/dialogs/tooldialogs.h
index 42a2a50c7..b42272af1 100644
--- a/src/libs/vtools/dialogs/tooldialogs.h
+++ b/src/libs/vtools/dialogs/tooldialogs.h
@@ -33,7 +33,6 @@
 #include "tools/dialogarc.h"
 #include "tools/dialogarcwithlength.h"
 #include "tools/dialogbisector.h"
-#include "tools/dialogdetail.h"
 #include "tools/dialogseamallowance.h"
 #include "tools/dialogendline.h"
 #include "tools/dialogline.h"
diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.cpp b/src/libs/vtools/dialogs/tools/dialogdetail.cpp
deleted file mode 100644
index 2a6667ddb..000000000
--- a/src/libs/vtools/dialogs/tools/dialogdetail.cpp
+++ /dev/null
@@ -1,1046 +0,0 @@
-/************************************************************************
- **
- **  @file   dialogdetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "dialogdetail.h"
-
-#include <QtNumeric>
-#include <QBuffer>
-#include <QByteArray>
-#include <QCheckBox>
-#include <QComboBox>
-#include <QDialogButtonBox>
-#include <QDoubleSpinBox>
-#include <QFlags>
-#include <QFont>
-#include <QIcon>
-#include <QLabel>
-#include <QLatin1String>
-#include <QLineEdit>
-#include <QList>
-#include <QListWidget>
-#include <QListWidgetItem>
-#include <QMessageLogger>
-#include <QPixmap>
-#include <QPointF>
-#include <QPushButton>
-#include <QSharedPointer>
-#include <QSize>
-#include <QSpinBox>
-#include <QTabWidget>
-#include <QToolButton>
-#include <QVariant>
-#include <QVector>
-#include <Qt>
-#include <QtDebug>
-#include <new>
-
-#include "../ifc/xml/vdomdocument.h"
-#include "../vpatterndb/vcontainer.h"
-#include "../vpatterndb/calculator.h"
-#include "../vgeometry/vgobject.h"
-#include "../vmisc/vabstractapplication.h"
-#include "dialogtool.h"
-#include "vnodedetail.h"
-#include "../support/dialogeditwrongformula.h"
-
-class QPointF;
-class QWidget;
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief DialogDetail create dialog
- * @param data container with data
- * @param parent parent widget
- */
-DialogDetail::DialogDetail(const VContainer *data, const quint32 &toolId, QWidget *parent)
-    :DialogTool(data, toolId, parent), ui(), detail(VDetail()), supplement(true), closed(true), flagWidth(true),
-      m_bAddMode(true), m_qslMaterials(), m_qslPlacements(), m_conMCP(), m_oldData(), m_oldGeom(), m_oldGrainline(),
-      m_iRotBaseHeight(0), m_iLenBaseHeight(0)
-{
-    ui.setupUi(this);
-
-#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
-    ui.lineEditName->setClearButtonEnabled(true);
-    ui.lineEditLetter->setClearButtonEnabled(true);
-#endif
-
-    ui.checkBoxForbidFlipping->setChecked(qApp->Settings()->GetForbidWorkpieceFlipping());
-
-    labelEditNamePoint = ui.labelEditName;
-    ui.labelUnit->setText( VDomDocument::UnitsToStr(qApp->patternUnit(), true));
-    ui.labelUnitX->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
-    ui.labelUnitY->setText(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
-
-    if(qApp->patternUnit() == Unit::Inch)
-    {
-        ui.doubleSpinBoxSeams->setDecimals(5);
-    }
-    // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
-    ui.doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
-
-    bOk = ui.buttonBox->button(QDialogButtonBox::Ok);
-    SCASSERT(bOk != nullptr)
-    connect(bOk, &QPushButton::clicked, this, &DialogTool::DialogAccepted);
-    QPushButton *bCancel = ui.buttonBox->button(QDialogButtonBox::Cancel);
-    SCASSERT(bCancel != nullptr)
-    connect(bCancel, &QPushButton::clicked, this, &DialogTool::DialogRejected);
-
-    flagName = true;//We have default name of detail.
-    ChangeColor(labelEditNamePoint, okColor);
-    CheckState();
-
-    connect(ui.listWidget, &QListWidget::currentRowChanged, this, &DialogDetail::ObjectChanged);
-    connect(ui.doubleSpinBoxBiasX,  static_cast<void (QDoubleSpinBox::*)(qreal)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogDetail::BiasXChanged);
-    connect(ui.doubleSpinBoxBiasY,  static_cast<void (QDoubleSpinBox::*)(qreal)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogDetail::BiasYChanged);
-    connect(ui.doubleSpinBoxSeams,  static_cast<void (QDoubleSpinBox::*)(qreal)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogDetail::AlowenceChanged);
-    connect(ui.checkBoxSeams, &QCheckBox::clicked, this, &DialogDetail::ClickedSeams);
-    connect(ui.checkBoxClosed, &QCheckBox::clicked, this, &DialogDetail::ClickedClosed);
-    connect(ui.checkBoxReverse, &QCheckBox::clicked, this, &DialogDetail::ClickedReverse);
-    connect(ui.lineEditName, &QLineEdit::textChanged, this, &DialogDetail::NameDetailChanged);
-
-    connect(ui.toolButtonDelete, &QToolButton::clicked, this, &DialogDetail::DeleteItem);
-    connect(ui.toolButtonUp, &QToolButton::clicked, this, &DialogDetail::ScrollUp);
-    connect(ui.toolButtonDown, &QToolButton::clicked, this, &DialogDetail::ScrollDown);
-
-    m_qslMaterials << QApplication::translate("Detail", "Fabric", 0)
-                   << QApplication::translate("Detail", "Lining", 0)
-                   << QApplication::translate("Detail", "Interfacing", 0)
-                   << QApplication::translate("Detail", "Interlining", 0);
-
-    for (int i = 0; i < m_qslMaterials.count(); ++i)
-    {
-        ui.comboBoxMaterial->addItem(m_qslMaterials[i], i);
-    }
-
-    QStringList qsl = qApp->Settings()->GetUserDefinedMaterials();
-    for (int i = 0; i < qsl.count(); ++i)
-    {
-        ui.comboBoxMaterial->addItem(qsl[i], int(MaterialType::mtUserDefined));
-    }
-
-    m_qslPlacements << tr("None") << tr("Cut on fold");
-    ui.comboBoxPlacement->addItems(m_qslPlacements);
-    ui.pushButtonRot->setIcon(QIcon("://icon/16x16/fx.png"));
-    ui.pushButtonLen->setIcon(QIcon("://icon/16x16/fx.png"));
-
-    connect(ui.pushButtonAdd, &QPushButton::clicked, this, &DialogDetail::AddUpdate);
-    connect(ui.pushButtonCancel, &QPushButton::clicked, this, &DialogDetail::Cancel);
-    connect(ui.pushButtonRemove, &QPushButton::clicked, this, &DialogDetail::Remove);
-    connect(ui.listWidgetMCP, &QListWidget::itemClicked, this, &DialogDetail::SetEditMode);
-    connect(ui.comboBoxMaterial, &QComboBox::currentTextChanged, this, &DialogDetail::MaterialChanged);
-    connect(ui.checkBoxGrainline, &QCheckBox::toggled, this, &DialogDetail::EnableGrainlineRotation);
-    connect(ui.pushButtonRot, &QPushButton::clicked, this, &DialogDetail::EditFormula);
-    connect(ui.pushButtonLen, &QPushButton::clicked, this, &DialogDetail::EditFormula);
-    connect(ui.lineEditLenFormula, &QPlainTextEdit::textChanged, this, &DialogDetail::UpdateValues);
-    connect(ui.lineEditRotFormula, &QPlainTextEdit::textChanged, this, &DialogDetail::UpdateValues);
-
-    connect(ui.pushButtonShowRot, &QPushButton::clicked, this, &DialogDetail::DeployRotation);
-    connect(ui.pushButtonShowLen, &QPushButton::clicked, this, &DialogDetail::DeployLength);
-
-    SetAddMode();
-    EnableGrainlineRotation();
-
-    ui.comboBoxArrow->addItem(tr("Both"));
-    ui.comboBoxArrow->addItem(tr("Just front"));
-    ui.comboBoxArrow->addItem(tr("Just rear"));
-
-    ui.tabWidget->setCurrentIndex(0);
-
-    m_iRotBaseHeight = ui.lineEditRotFormula->height();
-    m_iLenBaseHeight = ui.lineEditLenFormula->height();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ChoosedObject gets id and type of selected object. Save right data and ignore wrong.
- * @param id id of objects (points, arcs, splines, spline paths)
- * @param type type of object
- */
-void DialogDetail::ChosenObject(quint32 id, const SceneObject &type)
-{
-    if (type != SceneObject::Line && type != SceneObject::Detail)
-    {
-        switch (type)
-        {
-            case (SceneObject::Arc):
-                NewItem(id, Tool::NodeArc, NodeDetail::Contour);
-                break;
-            case (SceneObject::ElArc):
-                NewItem(id, Tool::NodeElArc, NodeDetail::Contour);
-                break;
-            case (SceneObject::Point):
-                NewItem(id, Tool::NodePoint, NodeDetail::Contour);
-                break;
-            case (SceneObject::Spline):
-                NewItem(id, Tool::NodeSpline, NodeDetail::Contour);
-                break;
-            case (SceneObject::SplinePath):
-                NewItem(id, Tool::NodeSplinePath, NodeDetail::Contour);
-                break;
-            case (SceneObject::Line):
-            case (SceneObject::Detail):
-            case (SceneObject::Unknown):
-            default:
-                qDebug()<<tr("Got wrong scene object. Ignore.");
-                break;
-        }
-
-        if (ui.listWidget->count() > 0)
-        {
-            EnableObjectGUI(true);
-        }
-
-        ValidObjects(DetailIsValid());
-        // Fix issue #526. Dialog Detail is not on top after selection second object on Mac.
-        setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
-        this->show();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::SaveData()
-{
-    detail.Clear();
-    detail = CreateDetail();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::CheckState()
-{
-    SCASSERT(bOk != nullptr)
-    bOk->setEnabled(flagFormula && flagName && flagError && flagWidth);
-    // In case dialog hasn't apply button
-    if ( bApply != nullptr)
-    {
-        bApply->setEnabled(bOk->isEnabled());
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::UpdateList()
-{
-    ui.listWidgetMCP->clear();
-    for (int i = 0; i < m_conMCP.count(); ++i)
-    {
-        MaterialCutPlacement mcp = m_conMCP.at(i);
-        QString qsText = tr("Cut %1 of %2%3").arg(mcp.m_iCutNumber);
-        if (mcp.m_eMaterial < MaterialType::mtUserDefined)
-        {
-            qsText = qsText.arg(m_qslMaterials[int(mcp.m_eMaterial)]);
-        }
-        else
-        {
-            qsText = qsText.arg(mcp.m_qsMaterialUserDef);
-        }
-        if (mcp.m_ePlacement == PlacementType::ptCutOnFold)
-        {
-            qsText = qsText.arg(QLatin1String(" ") + tr("on Fold"));
-        }
-        else
-        {
-            qsText = qsText.arg("");
-        }
-
-        ui.listWidgetMCP->addItem(qsText);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::AddUpdate()
-{
-    MaterialCutPlacement mcp;
-    QStringList qslUserMaterials = qApp->Settings()->GetUserDefinedMaterials();
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
-    int i = ui.comboBoxMaterial->itemData(ui.comboBoxMaterial->currentIndex()).toInt();
-#else
-    int i = ui.comboBoxMaterial->currentData().toInt();
-#endif
-    QString qsMat = ui.comboBoxMaterial->currentText();
-    if (i < m_qslMaterials.count() && qsMat == m_qslMaterials[i])
-    {
-        mcp.m_eMaterial = MaterialType(i);
-        mcp.m_qsMaterialUserDef.clear();
-    }
-    else
-    {
-        mcp.m_eMaterial = MaterialType::mtUserDefined;
-        mcp.m_qsMaterialUserDef = qsMat;
-        // check if we have new user defined material
-        bool bFound = false;
-        for (int i = 0; i < qslUserMaterials.count() && bFound == false; ++i)
-        {
-            if (mcp.m_qsMaterialUserDef == qslUserMaterials[i])
-            {
-                bFound = true;
-            }
-        }
-        if (bFound == false)
-        {
-            qApp->Settings()->AddUserDefinedMaterial(mcp.m_qsMaterialUserDef);
-            qApp->Settings()->sync();
-            ui.comboBoxMaterial->addItem(mcp.m_qsMaterialUserDef, int(MaterialType::mtUserDefined));
-        }
-    }
-
-    mcp.m_iCutNumber = ui.spinBoxCutNumber->value();
-    mcp.m_ePlacement = PlacementType(ui.comboBoxPlacement->currentIndex());
-
-    if (m_bAddMode == true)
-    {
-        m_conMCP << mcp;
-    }
-    else
-    {
-        int iR = ui.listWidgetMCP->currentRow();
-        SCASSERT(iR >= 0)
-        m_conMCP[iR] = mcp;
-        SetAddMode();
-    }
-    UpdateList();
-    ClearFields();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::Cancel()
-{
-    ClearFields();
-    SetAddMode();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::Remove()
-{
-    int iR = ui.listWidgetMCP->currentRow();
-    SCASSERT(iR >= 0)
-    m_conMCP.removeAt(iR);
-    UpdateList();
-    ClearFields();
-    SetAddMode();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::NameDetailChanged()
-{
-    SCASSERT(labelEditNamePoint != nullptr)
-    QLineEdit* edit = qobject_cast<QLineEdit*>(sender());
-    if (edit)
-    {
-        if (edit->text().isEmpty())
-        {
-            flagName = false;
-            ChangeColor(labelEditNamePoint, Qt::red);
-            QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png");
-            ui.tabWidget->setTabIcon(1, icon);
-        }
-        else
-        {
-            flagName = true;
-            ChangeColor(labelEditNamePoint, okColor);
-            QIcon icon;
-            ui.tabWidget->setTabIcon(1, icon);
-        }
-    }
-    CheckState();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::MaterialChanged()
-{
-    ui.pushButtonAdd->setEnabled(ui.comboBoxMaterial->currentText().isEmpty() == false);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief NewItem add new object (point, arc, spline or spline path) to list
- * @param id id of object
- * @param typeTool type of tool
- * @param typeNode type of node in detail
- * @param mx offset respect to x
- * @param my offset respect to y
- * @param reverse reverse list of points
- */
-void DialogDetail::NewItem(quint32 id, const Tool &typeTool, const NodeDetail &typeNode,
-                           qreal mx, qreal my, bool reverse)
-{
-    SCASSERT(id > NULL_ID)
-    QString name;
-    switch (typeTool)
-    {
-        case (Tool::NodePoint):
-        case (Tool::NodeArc):
-        case (Tool::NodeElArc):
-        case (Tool::NodeSpline):
-        case (Tool::NodeSplinePath):
-        {
-            const QSharedPointer<VGObject> obj = data->GeometricObject<VGObject>(id);
-            name = obj->name();
-            break;
-        }
-        default:
-            qDebug()<<"Got wrong tools. Ignore.";
-            return;
-    }
-
-    bool canAddNewPoint = false;
-
-    if(ui.listWidget->count() == 0)
-    {
-        canAddNewPoint = true;
-        ui.toolButtonUp->setEnabled(false);
-        ui.toolButtonDown->setEnabled(false);
-    }
-    else
-    {
-        if(RowId(ui.listWidget->count()-1) != id)
-        {
-            canAddNewPoint = true;
-        }
-        ui.toolButtonUp->setEnabled(true);
-        ui.toolButtonDown->setEnabled(true);
-    }
-
-    if(canAddNewPoint)
-    {
-        QListWidgetItem *item = new QListWidgetItem(name);
-        item->setFont(QFont("Times", 12, QFont::Bold));
-        VNodeDetail node(id, typeTool, typeNode, mx, my, reverse);
-        item->setData(Qt::UserRole, QVariant::fromValue(node));
-        ui.listWidget->addItem(item);
-        ui.listWidget->setCurrentRow(ui.listWidget->count()-1);
-
-        ui.doubleSpinBoxBiasX->blockSignals(true);
-        ui.doubleSpinBoxBiasY->blockSignals(true);
-
-        ui.doubleSpinBoxBiasX->setValue(qApp->fromPixel(node.getMx()));
-        ui.doubleSpinBoxBiasY->setValue(qApp->fromPixel(node.getMy()));
-        if (node.getTypeTool() == Tool::NodePoint)
-        {
-            ui.checkBoxReverse->setChecked(false);
-            ui.checkBoxReverse->setEnabled(false);
-        }
-        else
-        {
-            ui.checkBoxReverse->setEnabled(true);
-            ui.checkBoxReverse->setChecked(node.getReverse());
-        }
-
-        ui.doubleSpinBoxBiasX->blockSignals(false);
-        ui.doubleSpinBoxBiasY->blockSignals(false);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-VDetail DialogDetail::CreateDetail() const
-{
-    VDetail detail;
-    for (qint32 i = 0; i < ui.listWidget->count(); ++i)
-    {
-        QListWidgetItem *item = ui.listWidget->item(i);
-        detail.append( qvariant_cast<VNodeDetail>(item->data(Qt::UserRole)));
-    }
-    detail.setWidth(ui.doubleSpinBoxSeams->value());
-    detail.setName(ui.lineEditName->text());
-    detail.setSeamAllowance(supplement);
-    detail.setClosed(closed);
-    detail.setForbidFlipping(ui.checkBoxForbidFlipping->isChecked());
-
-    detail.GetPatternPieceData().SetLetter(ui.lineEditLetter->text());
-
-    for (int i = 0; i < m_conMCP.count(); ++i)
-    {
-        detail.GetPatternPieceData().Append(m_conMCP[i]);
-    }
-
-    detail.GetPatternPieceData().SetPos(m_oldData.GetPos());
-    detail.GetPatternPieceData().SetLabelWidth(m_oldData.GetLabelWidth());
-    detail.GetPatternPieceData().SetLabelHeight(m_oldData.GetLabelHeight());
-    detail.GetPatternPieceData().SetFontSize(m_oldData.GetFontSize());
-    detail.GetPatternPieceData().SetRotation(m_oldData.GetRotation());
-    detail.GetPatternPieceData().SetVisible(ui.checkBoxDetail->isChecked());
-
-    detail.GetPatternInfo() = m_oldGeom;
-    detail.GetPatternInfo().SetVisible(ui.checkBoxPattern->isChecked());
-
-    detail.GetGrainlineGeometry() = m_oldGrainline;
-    detail.GetGrainlineGeometry().SetVisible(ui.checkBoxGrainline->isChecked());
-    detail.GetGrainlineGeometry().SetRotation(ui.lineEditRotFormula->toPlainText());
-    detail.GetGrainlineGeometry().SetLength(ui.lineEditLenFormula->toPlainText());
-    VGrainlineGeometry::ArrowType eAT = VGrainlineGeometry::ArrowType(ui.comboBoxArrow->currentIndex());
-    detail.GetGrainlineGeometry().SetArrowType(eAT);
-
-    return detail;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ValidObjects(bool value)
-{
-    flagError = value;
-    CheckState();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::EnableObjectGUI(bool value)
-{
-    ui.toolButtonDelete->setEnabled(value);
-    ui.doubleSpinBoxBiasX->setEnabled(value);
-    ui.doubleSpinBoxBiasY->setEnabled(value);
-
-    if (value == false)
-    {
-        ui.checkBoxReverse->setEnabled(value);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-quint32 DialogDetail::RowId(int i) const
-{
-    const QListWidgetItem *rowItem = ui.listWidget->item(i);
-    SCASSERT(rowItem != nullptr)
-    const VNodeDetail rowNode = qvariant_cast<VNodeDetail>(rowItem->data(Qt::UserRole));
-    return rowNode.getId();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setDetails set detail
- * @param value detail
- */
-void DialogDetail::setDetail(const VDetail &value)
-{
-    detail = value;
-    ui.listWidget->clear();
-    for (int i = 0; i < detail.CountNode(); ++i)
-    {
-        const VNodeDetail &node = detail.at(i);
-        NewItem(node.getId(), node.getTypeTool(), node.getTypeNode(), node.getMx(),
-                node.getMy(), node.getReverse());
-    }
-    ui.lineEditName->setText(detail.getName());
-    ui.checkBoxSeams->setChecked(detail.getSeamAllowance());
-    ui.checkBoxClosed->setChecked(detail.getClosed());
-    ui.checkBoxForbidFlipping->setChecked(detail.getForbidFlipping());
-    ClickedClosed(detail.getClosed());
-    ClickedSeams(detail.getSeamAllowance());
-    ui.doubleSpinBoxSeams->setValue(detail.getWidth());
-    ui.listWidget->setCurrentRow(0);
-    ui.listWidget->setFocus(Qt::OtherFocusReason);
-    ui.toolButtonDelete->setEnabled(true);
-
-    ui.lineEditLetter->setText(detail.GetPatternPieceData().GetLetter());
-    ui.checkBoxDetail->setChecked(detail.GetPatternPieceData().IsVisible());
-    ui.checkBoxPattern->setChecked(detail.GetPatternInfo().IsVisible());
-
-    m_conMCP.clear();
-    for (int i = 0; i < detail.GetPatternPieceData().GetMCPCount(); ++i)
-    {
-        m_conMCP << detail.GetPatternPieceData().GetMCP(i);
-    }
-
-    UpdateList();
-
-    ui.checkBoxGrainline->setChecked(detail.GetGrainlineGeometry().IsVisible());
-    ui.lineEditRotFormula->setPlainText(detail.GetGrainlineGeometry().GetRotation());
-    ui.lineEditLenFormula->setPlainText(detail.GetGrainlineGeometry().GetLength());
-    ui.comboBoxArrow->setCurrentIndex(int(detail.GetGrainlineGeometry().GetArrowType()));
-
-    m_oldData = detail.GetPatternPieceData();
-    m_oldGeom = detail.GetPatternInfo();
-    m_oldGrainline = detail.GetGrainlineGeometry();
-
-    ValidObjects(DetailIsValid());
-    EnableGrainlineRotation();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief BiasXChanged changed value of offset for object respect to x
- * @param d value in mm
- */
-void DialogDetail::BiasXChanged(qreal d)
-{
-    qint32 row = ui.listWidget->currentRow();
-    QListWidgetItem *item = ui.listWidget->item( row );
-    SCASSERT(item != nullptr)
-    VNodeDetail node = qvariant_cast<VNodeDetail>(item->data(Qt::UserRole));
-    node.setMx(qApp->toPixel(d));
-    item->setData(Qt::UserRole, QVariant::fromValue(node));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief BiasYChanged changed value of offset for object respect to y
- * @param d value in mm
- */
-void DialogDetail::BiasYChanged(qreal d)
-{
-    qint32 row = ui.listWidget->currentRow();
-    QListWidgetItem *item = ui.listWidget->item( row );
-    SCASSERT(item != nullptr)
-    VNodeDetail node = qvariant_cast<VNodeDetail>(item->data(Qt::UserRole));
-    node.setMy(qApp->toPixel(d));
-    item->setData(Qt::UserRole, QVariant::fromValue(node));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::AlowenceChanged(qreal d)
-{
-    if (ui.doubleSpinBoxSeams->isEnabled())
-    {
-        if (d <= 0)
-        {
-            flagWidth = false;
-            ChangeColor(ui.labelEditWidth, errorColor);
-        }
-        else
-        {
-            flagWidth = true;
-            ChangeColor(ui.labelEditWidth, okColor);
-        }
-        CheckState();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ClickedSeams save supplement of seams for detail
- * @param checked 1 - need supplement, 0 - don't need supplement
- */
-void DialogDetail::ClickedSeams(bool checked)
-{
-    supplement = checked;
-    ui.checkBoxClosed->setEnabled(checked);
-    ui.doubleSpinBoxSeams->setEnabled(checked);
-
-    if (checked && ui.doubleSpinBoxSeams->value() <= 0)
-    {
-        flagWidth = false;
-        ChangeColor(ui.labelEditWidth, errorColor);
-    }
-    else
-    {
-        flagWidth = true;
-        ChangeColor(ui.labelEditWidth, okColor);
-    }
-    CheckState();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ClickedClosed save closed equdistant or not
- * @param checked 1 - closed, 0 - don't closed
- */
-void DialogDetail::ClickedClosed(bool checked)
-{
-    closed = checked;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ClickedReverse(bool checked)
-{
-    qint32 row = ui.listWidget->currentRow();
-    QListWidgetItem *item = ui.listWidget->item( row );
-    SCASSERT(item != nullptr)
-    VNodeDetail node = qvariant_cast<VNodeDetail>(item->data(Qt::UserRole));
-    node.setReverse(checked);
-    item->setData(Qt::UserRole, QVariant::fromValue(node));
-    ValidObjects(DetailIsValid());
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ObjectChanged changed new object (point, arc, spline or spline path) form list
- * @param row number of row
- */
-void DialogDetail::ObjectChanged(int row)
-{
-    if (ui.listWidget->count() == 0 || row == -1 || row >= ui.listWidget->count())
-    {
-        return;
-    }
-    const QListWidgetItem *item = ui.listWidget->item( row );
-    SCASSERT(item != nullptr)
-    const VNodeDetail node = qvariant_cast<VNodeDetail>(item->data(Qt::UserRole));
-    ui.doubleSpinBoxBiasX->setValue(qApp->fromPixel(node.getMx()));
-    ui.doubleSpinBoxBiasY->setValue(qApp->fromPixel(node.getMy()));
-    if (node.getTypeTool() == Tool::NodePoint)
-    {
-        ui.checkBoxReverse->setChecked(false);
-        ui.checkBoxReverse->setEnabled(false);
-    }
-    else
-    {
-        ui.checkBoxReverse->setEnabled(true);
-        ui.checkBoxReverse->setChecked(node.getReverse());
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief DeleteItem delete item from list
- */
-void DialogDetail::DeleteItem()
-{
-    if (ui.listWidget->count() == 1)
-    {
-        EnableObjectGUI(false);
-    }
-
-    delete ui.listWidget->item(ui.listWidget->currentRow());
-    ValidObjects(DetailIsValid());
-
-    if(ui.listWidget->count() < 2)
-    {
-        ui.toolButtonUp->setEnabled(false);
-        ui.toolButtonDown->setEnabled(false);
-    }
-    else
-    {
-        ui.toolButtonUp->setEnabled(true);
-        ui.toolButtonDown->setEnabled(true);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ScrollUp()
-{
-    if (ui.listWidget->count() > 1)
-    {
-        QListWidgetItem *item = ui.listWidget->takeItem(0);
-        ui.listWidget->addItem(item);
-        ValidObjects(DetailIsValid());
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ScrollDown()
-{
-    if (ui.listWidget->count() > 1)
-    {
-        QListWidgetItem *item = ui.listWidget->takeItem(ui.listWidget->count()-1);
-        ui.listWidget->insertItem(0, item);
-        ValidObjects(DetailIsValid());
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool DialogDetail::DetailIsValid() const
-{
-    const QIcon icon = QIcon::fromTheme("dialog-warning",
-                                  QIcon(":/icons/win.icon.theme/16x16/status/dialog-warning.png"));
-
-    const QPixmap pixmap = icon.pixmap(QSize(16, 16));
-    QByteArray byteArray;
-    QBuffer buffer(&byteArray);
-    pixmap.save(&buffer, "PNG");
-    QString url = QString("<img src=\"data:image/png;base64,") + byteArray.toBase64() + QLatin1String("\"/> ");
-
-    if(CreateDetail().ContourPoints(data).count() < 3)
-    {
-        url += tr("You need more points!");
-        ui.helpLabel->setText(url);
-        return false;
-    }
-    else
-    {
-        if(not DetailIsClockwise())
-        {
-            url += tr("You have to choose points in a clockwise direction!");
-            ui.helpLabel->setText(url);
-            return false;
-        }
-        if (FirstPointEqualLast())
-        {
-            url += tr("First point cannot be equal to the last point!");
-            ui.helpLabel->setText(url);
-            return false;
-        }
-        else
-        {
-            for (int i=0, sz = ui.listWidget->count()-1; i<sz; ++i)
-            {
-                if (RowId(i) == RowId(i+1))
-                {
-                    url += tr("You have double points!");
-                    ui.helpLabel->setText(url);
-                    return false;
-                }
-            }
-        }
-    }
-    ui.helpLabel->setText(tr("Ready!"));
-    return true;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool DialogDetail::FirstPointEqualLast() const
-{
-    if (ui.listWidget->count() > 1)
-    {
-        if (RowId(0) == RowId(ui.listWidget->count()-1))
-        {
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return false;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool DialogDetail::DetailIsClockwise() const
-{
-    const QVector<QPointF> points = CreateDetail().ContourPoints(data);
-
-    if(points.count() < 3)
-    {
-        return false;
-    }
-
-    const qreal res = VDetail::SumTrapezoids(points);
-    if (res < 0)
-    {
-        return true;
-    }
-    return false;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ClearFields()
-{
-    ui.comboBoxMaterial->setCurrentIndex(0);
-    ui.spinBoxCutNumber->setValue(0);
-    ui.comboBoxPlacement->setCurrentIndex(0);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::UpdateValues()
-{
-    QPlainTextEdit* apleSender[2];
-    apleSender[0] = ui.lineEditRotFormula;
-    apleSender[1] = ui.lineEditLenFormula;
-    bool bFormulasOK = true;
-
-    for (int i = 0; i < 2; ++i)
-    {
-        QLabel* plbVal;
-        QLabel* plbText;
-        QString qsUnit;
-        if (i == 0)
-        {
-            plbVal = ui.labelRot;
-            plbText = ui.labelEditRot;
-            QChar ch(0x00b0);
-            qsUnit = ch;
-        }
-        else
-        {
-            plbVal = ui.labelLen;
-            plbText = ui.labelEditLen;
-            qsUnit = " " + VDomDocument::UnitsToStr(qApp->patternUnit());
-        }
-
-        QString qsFormula = apleSender[i]->toPlainText().simplified();
-        Calculator cal;
-        QString qsVal;
-        try
-        {
-            qsFormula.replace("\n", " ");
-            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
-            qreal dVal;
-            dVal = cal.EvalFormula(data->PlainVariables(), qsFormula);
-            if (qIsInf(dVal) == true || qIsNaN(dVal) == true)
-            {
-                throw qmu::QmuParserError(tr("Infinite/undefined result"));
-            }
-            else if (i == 1 && dVal <= 0.0)
-            {
-                throw qmu::QmuParserError(tr("Length should be positive"));
-            }
-            else
-            {
-                qsVal.setNum(dVal, 'f', 2);
-                ChangeColor(plbText, okColor);
-            }
-        }
-        catch (...)
-        {
-            qsVal.clear();
-            ChangeColor(plbText, Qt::red);
-            bFormulasOK = false;
-        }
-
-        if (qsVal.isEmpty() == false)
-        {
-            qsVal += qsUnit;
-        }
-        plbVal->setText(qsVal);
-    }
-
-    bOk->setEnabled(bFormulasOK);
-    if (bFormulasOK == false)
-    {
-        QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png");
-        ui.tabWidget->setTabIcon(2, icon);
-    }
-    else
-    {
-        ResetWarning();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::SetAddMode()
-{
-    ui.pushButtonAdd->setText(tr("Add"));
-    ui.pushButtonCancel->hide();
-    ui.pushButtonRemove->hide();
-    ui.listWidgetMCP->setCurrentRow(-1);
-    m_bAddMode = true;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::SetEditMode()
-{
-    int iR = ui.listWidgetMCP->currentRow();
-    // this method can be called by clicking on item or by update. In the latter case there is nothing else to do!
-    if (iR < 0 || iR >= m_conMCP.count())
-    {
-        return;
-    }
-
-    ui.pushButtonAdd->setText(tr("Update"));
-    ui.pushButtonCancel->show();
-    ui.pushButtonRemove->show();
-
-    MaterialCutPlacement mcp = m_conMCP.at(iR);
-    if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-    {
-        int iRow = qApp->Settings()->GetUserDefinedMaterials().indexOf(mcp.m_qsMaterialUserDef);
-        if (iRow >= 0)
-        {
-            ui.comboBoxMaterial->setCurrentIndex(iRow + m_qslMaterials.count());
-        }
-        else
-        {
-            ui.comboBoxMaterial->setCurrentText(mcp.m_qsMaterialUserDef);
-        }
-    }
-    else
-    {
-        ui.comboBoxMaterial->setCurrentIndex(int(mcp.m_eMaterial));
-    }
-    ui.spinBoxCutNumber->setValue(mcp.m_iCutNumber);
-    ui.comboBoxPlacement->setCurrentIndex(int(mcp.m_ePlacement));
-
-    m_bAddMode = false;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::EnableGrainlineRotation()
-{
-    ui.lineEditRotFormula->setEnabled(ui.checkBoxGrainline->isChecked());
-    ui.lineEditLenFormula->setEnabled(ui.checkBoxGrainline->isChecked());
-    ui.pushButtonRot->setEnabled(ui.checkBoxGrainline->isChecked());
-    ui.pushButtonLen->setEnabled(ui.checkBoxGrainline->isChecked());
-    ui.pushButtonShowLen->setEnabled(ui.checkBoxGrainline->isChecked());
-    ui.pushButtonShowRot->setEnabled(ui.checkBoxGrainline->isChecked());
-
-    if (ui.checkBoxGrainline->isChecked() == true)
-    {
-        UpdateValues();
-    }
-    else
-    {
-        ChangeColor(ui.labelEditLen, okColor);
-        ChangeColor(ui.labelEditRot, okColor);
-        bOk->setEnabled(true);
-        ResetWarning();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::EditFormula()
-{
-    QPlainTextEdit* pleFormula;
-    bool bCheckZero;
-
-    if (sender() == ui.pushButtonLen)
-    {
-        pleFormula = ui.lineEditLenFormula;
-        bCheckZero = true;
-    }
-    else if (sender() == ui.pushButtonRot)
-    {
-        pleFormula = ui.lineEditRotFormula;
-        bCheckZero = false;
-    }
-    else
-    {
-        // should not get here!
-        return;
-    }
-
-    DialogEditWrongFormula dlg(data, NULL_ID, this);
-    dlg.SetFormula(pleFormula->toPlainText());
-    dlg.setCheckZero(bCheckZero);
-    if (dlg.exec() == QDialog::Accepted)
-    {
-        QString qsFormula = dlg.GetFormula();
-        qsFormula.replace("\n", " ");
-        pleFormula->setPlainText(qsFormula);
-        UpdateValues();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::DeployRotation()
-{
-    DeployFormula(ui.lineEditRotFormula, ui.pushButtonShowRot, m_iRotBaseHeight);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::DeployLength()
-{
-    DeployFormula(ui.lineEditLenFormula, ui.pushButtonShowLen, m_iLenBaseHeight);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogDetail::ResetWarning()
-{
-    QIcon icon;
-    ui.tabWidget->setTabIcon(2, icon);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-
diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.h b/src/libs/vtools/dialogs/tools/dialogdetail.h
deleted file mode 100644
index cecc051d7..000000000
--- a/src/libs/vtools/dialogs/tools/dialogdetail.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/************************************************************************
- **
- **  @file   dialogdetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 DIALOGDETAIL_H
-#define DIALOGDETAIL_H
-
-#include <qcompilerdetection.h>
-#include <QMetaObject>
-#include <QObject>
-#include <QString>
-#include <QStringList>
-#include <QtGlobal>
-
-#include "../vmisc/def.h"
-#include "../vpatterndb/vdetail.h"
-#include "../vpatterndb/vpatterninfogeometry.h"
-#include "../vpatterndb/vpatternpiecedata.h"
-#include "../vpatterndb/vgrainlinegeometry.h"
-#include "dialogtool.h"
-#include "ui_dialogdetail.h"
-
-class QWidget;
-class VContainer;
-
-/**
- * @brief The DialogDetail class dialog for ToolDetai. Help create detail and edit option.
- */
-class DialogDetail : public DialogTool
-{
-    Q_OBJECT
-public:
-    DialogDetail(const VContainer *data, const quint32 &toolId, QWidget *parent = nullptr);
-
-    VDetail          getDetail() const;
-    void             setDetail(const VDetail &value);
-public slots:
-    virtual void     ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
-    void             BiasXChanged(qreal d);
-    void             BiasYChanged(qreal d);
-    void             AlowenceChanged(qreal d);
-    void             ClickedSeams(bool checked);
-    void             ClickedClosed(bool checked);
-    void             ClickedReverse(bool checked);
-    void             ObjectChanged(int row);
-    void             DeleteItem();
-    void             ScrollUp();
-    void             ScrollDown();
-protected:
-    /**
-     * @brief SaveData Put dialog data in local variables
-     */
-    virtual void     SaveData() Q_DECL_OVERRIDE;
-    virtual void     CheckState() Q_DECL_OVERRIDE;
-
-protected slots:
-    void             UpdateList();
-    void             AddUpdate();
-    void             Cancel();
-    void             Remove();
-
-private slots:
-    void             NameDetailChanged();
-    void             MaterialChanged();
-private:
-
-    /** @brief ui keeps information about user interface */
-    Ui::DialogDetail ui;
-
-    /** @brief detail detail */
-    VDetail          detail;
-
-    /** @brief supplement keep option supplement of seams */
-    bool             supplement;
-
-    /** @brief closed keep option about equdistant (closed or not) */
-    bool             closed;
-    bool             flagWidth;
-    bool             m_bAddMode;
-
-    QStringList      m_qslMaterials;
-    QStringList      m_qslPlacements;
-    // temporary container for Material/Cut/Placement 3-tuples
-    MCPContainer     m_conMCP;
-    VPatternPieceData       m_oldData;
-    VPatternInfoGeometry    m_oldGeom;
-    VGrainlineGeometry      m_oldGrainline;
-    int                     m_iRotBaseHeight;
-    int                     m_iLenBaseHeight;
-
-
-    bool             DetailIsValid() const;
-    bool             FirstPointEqualLast() const;
-    bool             DetailIsClockwise() const;
-
-    void             NewItem(quint32 id, const Tool &typeTool, const NodeDetail &typeNode,
-                             qreal mx = 0, qreal my = 0, bool reverse = false);
-    VDetail          CreateDetail() const;
-    void             ValidObjects(bool value);
-    void             EnableObjectGUI(bool value);
-
-    void             ClearFields();
-
-    quint32          RowId(int i) const;
-
-private slots:
-    void             UpdateValues();
-    void             SetAddMode();
-    void             SetEditMode();
-    void             EnableGrainlineRotation();
-    void             EditFormula();
-    void             DeployRotation();
-    void             DeployLength();
-    void             ResetWarning();
-};
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getDetails return detail
- * @return detail
- */
-inline VDetail DialogDetail::getDetail() const
-{
-    return detail;
-}
-
-#endif // DIALOGDETAIL_H
diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.ui b/src/libs/vtools/dialogs/tools/dialogdetail.ui
deleted file mode 100644
index 699792160..000000000
--- a/src/libs/vtools/dialogs/tools/dialogdetail.ui
+++ /dev/null
@@ -1,1116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>DialogDetail</class>
- <widget class="QDialog" name="DialogDetail">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>581</width>
-    <height>478</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Seam allowance tool</string>
-  </property>
-  <property name="windowIcon">
-   <iconset>
-    <normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
-  </property>
-  <property name="locale">
-   <locale language="English" country="UnitedStates"/>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_7">
-   <item>
-    <widget class="QTabWidget" name="tabWidget">
-     <property name="currentIndex">
-      <number>0</number>
-     </property>
-     <widget class="QWidget" name="tab">
-      <attribute name="title">
-       <string>General</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_3">
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_8">
-         <item>
-          <widget class="QLabel" name="label_3">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-           <property name="pixmap">
-            <pixmap>:/icon/32x32/clockwise.png</pixmap>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_4">
-           <property name="text">
-            <string>All objects in path should follow in clockwise direction.</string>
-           </property>
-           <property name="wordWrap">
-            <bool>true</bool>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item>
-        <widget class="QSplitter" name="splitter_2">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <widget class="QWidget" name="layoutWidget">
-          <layout class="QVBoxLayout" name="verticalLayout_2">
-           <item>
-            <layout class="QHBoxLayout" name="horizontalLayout_3">
-             <property name="spacing">
-              <number>6</number>
-             </property>
-             <property name="sizeConstraint">
-              <enum>QLayout::SetDefaultConstraint</enum>
-             </property>
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <item>
-              <widget class="QLabel" name="label">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                 <horstretch>1</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="text">
-                <string>Bias X:</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QDoubleSpinBox" name="doubleSpinBoxBiasX">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                 <horstretch>1</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimum">
-                <double>-900.990000000000009</double>
-               </property>
-               <property name="maximum">
-                <double>900.990000000000009</double>
-               </property>
-               <property name="singleStep">
-                <double>0.100000000000000</double>
-               </property>
-               <property name="value">
-                <double>0.000000000000000</double>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QLabel" name="labelUnitX">
-               <property name="text">
-                <string>cm</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <layout class="QHBoxLayout" name="horizontalLayout_4">
-             <item>
-              <widget class="QLabel" name="label_2">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                 <horstretch>1</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="text">
-                <string>Bias Y:</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QDoubleSpinBox" name="doubleSpinBoxBiasY">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                 <horstretch>1</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimum">
-                <double>-900.990000000000009</double>
-               </property>
-               <property name="maximum">
-                <double>900.990000000000009</double>
-               </property>
-               <property name="singleStep">
-                <double>0.100000000000000</double>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QLabel" name="labelUnitY">
-               <property name="text">
-                <string>cm</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <layout class="QHBoxLayout" name="horizontalLayout_6">
-             <item>
-              <widget class="QCheckBox" name="checkBoxReverse">
-               <property name="text">
-                <string>Reverse</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <widget class="QGroupBox" name="groupBox">
-             <property name="title">
-              <string>Options</string>
-             </property>
-             <layout class="QVBoxLayout" name="verticalLayout">
-              <item>
-               <widget class="QCheckBox" name="checkBoxForbidFlipping">
-                <property name="toolTip">
-                 <string>Forbid piece be mirrored in a layout.</string>
-                </property>
-                <property name="text">
-                 <string>Forbid flipping</string>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <widget class="QCheckBox" name="checkBoxSeams">
-                <property name="text">
-                 <string>Seam allowance</string>
-                </property>
-                <property name="checked">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_2">
-                <item>
-                 <widget class="QLabel" name="labelEditWidth">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                    <horstretch>1</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="locale">
-                   <locale language="English" country="UnitedStates"/>
-                  </property>
-                  <property name="text">
-                   <string>Width:</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QDoubleSpinBox" name="doubleSpinBoxSeams">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                    <horstretch>1</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="maximum">
-                   <double>900.990000000000009</double>
-                  </property>
-                  <property name="singleStep">
-                   <double>0.100000000000000</double>
-                  </property>
-                  <property name="value">
-                   <double>1.000000000000000</double>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QLabel" name="labelUnit">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="text">
-                   <string>cm</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-              <item>
-               <widget class="QCheckBox" name="checkBoxClosed">
-                <property name="text">
-                 <string>Closed</string>
-                </property>
-                <property name="checked">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_16">
-                <property name="sizeConstraint">
-                 <enum>QLayout::SetFixedSize</enum>
-                </property>
-                <property name="leftMargin">
-                 <number>10</number>
-                </property>
-                <property name="topMargin">
-                 <number>10</number>
-                </property>
-                <property name="rightMargin">
-                 <number>10</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>10</number>
-                </property>
-                <item alignment="Qt::AlignLeft">
-                 <widget class="QToolButton" name="toolButtonDelete">
-                  <property name="enabled">
-                   <bool>false</bool>
-                  </property>
-                  <property name="text">
-                   <string>Delete</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer">
-                  <property name="orientation">
-                   <enum>Qt::Horizontal</enum>
-                  </property>
-                  <property name="sizeHint" stdset="0">
-                   <size>
-                    <width>40</width>
-                    <height>20</height>
-                   </size>
-                  </property>
-                 </spacer>
-                </item>
-                <item alignment="Qt::AlignRight">
-                 <widget class="QToolButton" name="toolButtonDown">
-                  <property name="toolTip">
-                   <string>Scroll down the list</string>
-                  </property>
-                  <property name="text">
-                   <string notr="true">...</string>
-                  </property>
-                  <property name="icon">
-                   <iconset theme="go-down">
-                    <normaloff>.</normaloff>.</iconset>
-                  </property>
-                 </widget>
-                </item>
-                <item alignment="Qt::AlignRight">
-                 <widget class="QToolButton" name="toolButtonUp">
-                  <property name="toolTip">
-                   <string>Scroll up the list</string>
-                  </property>
-                  <property name="text">
-                   <string notr="true">...</string>
-                  </property>
-                  <property name="icon">
-                   <iconset theme="go-up">
-                    <normaloff>.</normaloff>.</iconset>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QListWidget" name="listWidget"/>
-        </widget>
-       </item>
-       <item>
-        <widget class="QLabel" name="helpLabel">
-         <property name="text">
-          <string>Ready!</string>
-         </property>
-         <property name="textFormat">
-          <enum>Qt::RichText</enum>
-         </property>
-         <property name="scaledContents">
-          <bool>false</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_2">
-      <attribute name="title">
-       <string>Pattern piece data</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_5">
-       <item>
-        <widget class="QSplitter" name="splitter">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <widget class="QWidget" name="layoutWidget1">
-          <layout class="QVBoxLayout" name="verticalLayout_4">
-           <item>
-            <layout class="QFormLayout" name="formLayout">
-             <property name="fieldGrowthPolicy">
-              <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-             </property>
-             <item row="0" column="0">
-              <widget class="QLabel" name="label_5">
-               <property name="text">
-                <string>Letter:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="0" column="1">
-              <widget class="QLineEdit" name="lineEditLetter">
-               <property name="maxLength">
-                <number>3</number>
-               </property>
-               <property name="placeholderText">
-                <string>Letter of pattern piece</string>
-               </property>
-              </widget>
-             </item>
-             <item row="1" column="0">
-              <widget class="QLabel" name="labelEditName">
-               <property name="text">
-                <string>Name of detail:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="1" column="1">
-              <widget class="QLineEdit" name="lineEditName">
-               <property name="text">
-                <string>Detail</string>
-               </property>
-               <property name="maxLength">
-                <number>30</number>
-               </property>
-               <property name="placeholderText">
-                <string>Name can't be empty</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <widget class="QGroupBox" name="groupBox_2">
-             <property name="title">
-              <string>Material/Cut number/Placement</string>
-             </property>
-             <layout class="QGridLayout" name="gridLayout_3">
-              <item row="1" column="0">
-               <widget class="QLabel" name="label_8">
-                <property name="text">
-                 <string>Cut number:</string>
-                </property>
-               </widget>
-              </item>
-              <item row="0" column="0" colspan="2">
-               <widget class="QLabel" name="label_7">
-                <property name="text">
-                 <string>Material type:</string>
-                </property>
-               </widget>
-              </item>
-              <item row="0" column="2" colspan="2">
-               <widget class="QComboBox" name="comboBoxMaterial">
-                <property name="toolTip">
-                 <string>You can choose one of the predefined materials or enter a new one</string>
-                </property>
-                <property name="editable">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item row="1" column="2" colspan="2">
-               <widget class="QSpinBox" name="spinBoxCutNumber">
-                <property name="minimum">
-                 <number>1</number>
-                </property>
-                <property name="maximum">
-                 <number>1000</number>
-                </property>
-               </widget>
-              </item>
-              <item row="2" column="0">
-               <widget class="QLabel" name="label_9">
-                <property name="text">
-                 <string>Placement:</string>
-                </property>
-               </widget>
-              </item>
-              <item row="2" column="2" colspan="2">
-               <widget class="QComboBox" name="comboBoxPlacement"/>
-              </item>
-              <item row="3" column="0">
-               <widget class="QPushButton" name="pushButtonAdd">
-                <property name="text">
-                 <string>Add</string>
-                </property>
-               </widget>
-              </item>
-              <item row="3" column="1" colspan="2">
-               <widget class="QPushButton" name="pushButtonCancel">
-                <property name="text">
-                 <string>Cancel</string>
-                </property>
-               </widget>
-              </item>
-              <item row="3" column="3">
-               <widget class="QPushButton" name="pushButtonRemove">
-                <property name="text">
-                 <string>Remove</string>
-                </property>
-               </widget>
-              </item>
-             </layout>
-            </widget>
-           </item>
-           <item>
-            <layout class="QVBoxLayout" name="verticalLayout_6">
-             <item>
-              <widget class="QCheckBox" name="checkBoxDetail">
-               <property name="text">
-                <string>Detail label visible</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QCheckBox" name="checkBoxPattern">
-               <property name="text">
-                <string>Pattern label visible</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QListWidget" name="listWidgetMCP">
-          <property name="minimumSize">
-           <size>
-            <width>180</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="focusPolicy">
-           <enum>Qt::ClickFocus</enum>
-          </property>
-         </widget>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_3">
-      <property name="cursor">
-       <cursorShape>ArrowCursor</cursorShape>
-      </property>
-      <attribute name="title">
-       <string>Grainline</string>
-      </attribute>
-      <widget class="QWidget" name="horizontalLayoutWidget">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>10</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout">
-        <item>
-         <widget class="QCheckBox" name="checkBoxGrainline">
-          <property name="text">
-           <string>Grainline visible</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="layoutWidget_2">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>60</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout_11">
-        <item alignment="Qt::AlignLeft">
-         <widget class="QLabel" name="labelEditRot">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="palette">
-           <palette>
-            <active>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>255</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </active>
-            <inactive>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>255</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </inactive>
-            <disabled>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>159</red>
-                <green>158</green>
-                <blue>158</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </disabled>
-           </palette>
-          </property>
-          <property name="text">
-           <string>Rotation:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_4">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QToolButton" name="pushButtonRot">
-          <property name="toolTip">
-           <string>Formula wizard</string>
-          </property>
-          <property name="text">
-           <string notr="true">...</string>
-          </property>
-          <property name="icon">
-           <iconset>
-            <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
-          </property>
-          <property name="iconSize">
-           <size>
-            <width>24</width>
-            <height>24</height>
-           </size>
-          </property>
-         </widget>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QLabel" name="labelEqual">
-          <property name="text">
-           <string/>
-          </property>
-          <property name="pixmap">
-           <pixmap>:/icon/24x24/equal.png</pixmap>
-          </property>
-         </widget>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QLabel" name="labelRot">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="minimumSize">
-           <size>
-            <width>87</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="baseSize">
-           <size>
-            <width>0</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Value</string>
-          </property>
-          <property name="text">
-           <string notr="true">_</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="layoutWidget_3">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>110</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout_12">
-        <item>
-         <widget class="QPlainTextEdit" name="lineEditRotFormula">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>16777215</width>
-            <height>28</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Calculation</string>
-          </property>
-          <property name="tabChangesFocus">
-           <bool>true</bool>
-          </property>
-          <property name="plainText">
-           <string notr="true"/>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pushButtonShowRot">
-          <property name="maximumSize">
-           <size>
-            <width>18</width>
-            <height>18</height>
-           </size>
-          </property>
-          <property name="sizeIncrement">
-           <size>
-            <width>0</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-          </property>
-          <property name="text">
-           <string notr="true"/>
-          </property>
-          <property name="icon">
-           <iconset theme="go-down">
-            <normaloff>.</normaloff>.</iconset>
-          </property>
-          <property name="iconSize">
-           <size>
-            <width>16</width>
-            <height>16</height>
-           </size>
-          </property>
-          <property name="flat">
-           <bool>true</bool>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="layoutWidget_4">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>160</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout_13">
-        <item alignment="Qt::AlignLeft">
-         <widget class="QLabel" name="labelEditLen">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="palette">
-           <palette>
-            <active>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>255</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </active>
-            <inactive>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>255</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </inactive>
-            <disabled>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>159</red>
-                <green>158</green>
-                <blue>158</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </disabled>
-           </palette>
-          </property>
-          <property name="text">
-           <string>Length:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_5">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QToolButton" name="pushButtonLen">
-          <property name="toolTip">
-           <string>Formula wizard</string>
-          </property>
-          <property name="text">
-           <string notr="true">...</string>
-          </property>
-          <property name="icon">
-           <iconset>
-            <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
-          </property>
-          <property name="iconSize">
-           <size>
-            <width>24</width>
-            <height>24</height>
-           </size>
-          </property>
-         </widget>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QLabel" name="labelEqual_2">
-          <property name="text">
-           <string/>
-          </property>
-          <property name="pixmap">
-           <pixmap>:/icon/24x24/equal.png</pixmap>
-          </property>
-         </widget>
-        </item>
-        <item alignment="Qt::AlignRight">
-         <widget class="QLabel" name="labelLen">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="minimumSize">
-           <size>
-            <width>87</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="baseSize">
-           <size>
-            <width>0</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Value</string>
-          </property>
-          <property name="text">
-           <string notr="true">_</string>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="layoutWidget_5">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>210</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout_14">
-        <item>
-         <widget class="QPlainTextEdit" name="lineEditLenFormula">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="maximumSize">
-           <size>
-            <width>16777215</width>
-            <height>28</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>Calculation</string>
-          </property>
-          <property name="tabChangesFocus">
-           <bool>true</bool>
-          </property>
-          <property name="plainText">
-           <string notr="true"/>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QPushButton" name="pushButtonShowLen">
-          <property name="maximumSize">
-           <size>
-            <width>18</width>
-            <height>18</height>
-           </size>
-          </property>
-          <property name="sizeIncrement">
-           <size>
-            <width>0</width>
-            <height>0</height>
-           </size>
-          </property>
-          <property name="toolTip">
-           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-          </property>
-          <property name="text">
-           <string notr="true"/>
-          </property>
-          <property name="icon">
-           <iconset theme="go-down">
-            <normaloff>.</normaloff>.</iconset>
-          </property>
-          <property name="iconSize">
-           <size>
-            <width>16</width>
-            <height>16</height>
-           </size>
-          </property>
-          <property name="flat">
-           <bool>true</bool>
-          </property>
-         </widget>
-        </item>
-       </layout>
-      </widget>
-      <widget class="QWidget" name="horizontalLayoutWidget_2">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>260</y>
-         <width>541</width>
-         <height>41</height>
-        </rect>
-       </property>
-       <layout class="QHBoxLayout" name="horizontalLayout_5">
-        <item>
-         <widget class="QLabel" name="labelEditLen_2">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="palette">
-           <palette>
-            <active>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>0</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </active>
-            <inactive>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>0</red>
-                <green>0</green>
-                <blue>0</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </inactive>
-            <disabled>
-             <colorrole role="WindowText">
-              <brush brushstyle="SolidPattern">
-               <color alpha="255">
-                <red>159</red>
-                <green>158</green>
-                <blue>158</blue>
-               </color>
-              </brush>
-             </colorrole>
-            </disabled>
-           </palette>
-          </property>
-          <property name="text">
-           <string>Arrows:</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <widget class="QComboBox" name="comboBoxArrow"/>
-        </item>
-        <item>
-         <spacer name="horizontalSpacer_2">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>40</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-       </layout>
-      </widget>
-     </widget>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <tabstops>
-  <tabstop>lineEditName</tabstop>
-  <tabstop>comboBoxMaterial</tabstop>
-  <tabstop>spinBoxCutNumber</tabstop>
-  <tabstop>comboBoxPlacement</tabstop>
-  <tabstop>pushButtonAdd</tabstop>
-  <tabstop>pushButtonCancel</tabstop>
-  <tabstop>pushButtonRemove</tabstop>
-  <tabstop>toolButtonUp</tabstop>
-  <tabstop>listWidget</tabstop>
-  <tabstop>checkBoxClosed</tabstop>
-  <tabstop>toolButtonDelete</tabstop>
-  <tabstop>doubleSpinBoxBiasX</tabstop>
-  <tabstop>doubleSpinBoxBiasY</tabstop>
-  <tabstop>checkBoxReverse</tabstop>
-  <tabstop>checkBoxSeams</tabstop>
-  <tabstop>doubleSpinBoxSeams</tabstop>
-  <tabstop>toolButtonDown</tabstop>
-  <tabstop>checkBoxForbidFlipping</tabstop>
-  <tabstop>checkBoxDetail</tabstop>
-  <tabstop>checkBoxPattern</tabstop>
-  <tabstop>lineEditLetter</tabstop>
- </tabstops>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>DialogDetail</receiver>
-   <slot>accept()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>248</x>
-     <y>254</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>157</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>DialogDetail</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>316</x>
-     <y>260</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>286</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp
index 1432446f7..5a4abc1b0 100644
--- a/src/libs/vtools/tools/vtooldetail.cpp
+++ b/src/libs/vtools/tools/vtooldetail.cpp
@@ -66,7 +66,6 @@
 #include <QtDebug>
 #include <new>
 
-#include "../dialogs/tools/dialogdetail.h"
 #include "../dialogs/tools/dialogtool.h"
 #include "../ifc/exception/vexception.h"
 #include "../ifc/xml/vdomdocument.h"
@@ -236,9 +235,9 @@ VToolDetail::~VToolDetail()
 void VToolDetail::setDialog()
 {
     SCASSERT(dialog != nullptr)
-    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-    SCASSERT(dialogTool != nullptr)
-    dialogTool->setDetail(VAbstractTool::data.GetDetail(id));
+//    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
+//    SCASSERT(dialogTool != nullptr)
+//    dialogTool->setDetail(VAbstractTool::data.GetDetail(id));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -252,79 +251,79 @@ void VToolDetail::setDialog()
 void VToolDetail::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data)
 {
     SCASSERT(dialog != nullptr)
-    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-    SCASSERT(dialogTool != nullptr)
-    VDetail detail = dialogTool->getDetail();
-    VDetail det;
-    qApp->getUndoStack()->beginMacro("add detail");
-    for (int i = 0; i< detail.CountNode(); ++i)
-    {
-        quint32 id = 0;
-        const VNodeDetail &nodeD = detail.at(i);
-        switch (nodeD.getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                id = CreateNode<VPointF>(data, nodeD.getId());
-                VNodePoint::Create(doc, data, scene, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeArc):
-            {
-                id = CreateNode<VArc>(data, nodeD.getId());
-                VNodeArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeElArc):
-            {
-                id = CreateNode<VEllipticalArc>(data, nodeD.getId());
-                VNodeEllipticalArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeSpline):
-            {
-                const auto obj = data->GetGObject(nodeD.getId());
-                if (obj->getType() == GOType::Spline)
-                {
-                    id = CreateNode<VSpline>(data, nodeD.getId());
-                }
-                else
-                {
-                    id = CreateNode<VCubicBezier>(data, nodeD.getId());
-                }
-                VNodeSpline::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeSplinePath):
-            {
-                const auto obj = data->GetGObject(nodeD.getId());
-                if (obj->getType() == GOType::SplinePath)
-                {
-                    id = CreateNode<VSplinePath>(data, nodeD.getId());
-                }
-                else
-                {
-                    id = CreateNode<VCubicBezierPath>(data, nodeD.getId());
-                }
-                VNodeSplinePath::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            default:
-                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-                break;
-        }
-        VNodeDetail node(id, nodeD.getTypeTool(), NodeDetail::Contour, nodeD.getMx(), nodeD.getMy(),
-                         nodeD.getReverse());
-        det.append(node);
-    }
-    det.setName(detail.getName());
-    det.setWidth(detail.getWidth());
-    det.setClosed(detail.getClosed());
-    det.setSeamAllowance(detail.getSeamAllowance());
-    det.setForbidFlipping(detail.getForbidFlipping());
-    det.SetPatternPieceData(detail.GetPatternPieceData());
-    det.SetPatternInfo(detail.GetPatternInfo());
-    Create(0, det, scene, doc, data, Document::FullParse, Source::FromGui);
+//    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
+//    SCASSERT(dialogTool != nullptr)
+//    VDetail detail = dialogTool->getDetail();
+//    VDetail det;
+//    qApp->getUndoStack()->beginMacro("add detail");
+//    for (int i = 0; i< detail.CountNode(); ++i)
+//    {
+//        quint32 id = 0;
+//        const VNodeDetail &nodeD = detail.at(i);
+//        switch (nodeD.getTypeTool())
+//        {
+//            case (Tool::NodePoint):
+//            {
+//                id = CreateNode<VPointF>(data, nodeD.getId());
+//                VNodePoint::Create(doc, data, scene, id, nodeD.getId(), Document::FullParse, Source::FromGui);
+//            }
+//            break;
+//            case (Tool::NodeArc):
+//            {
+//                id = CreateNode<VArc>(data, nodeD.getId());
+//                VNodeArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
+//            }
+//            break;
+//            case (Tool::NodeElArc):
+//            {
+//                id = CreateNode<VEllipticalArc>(data, nodeD.getId());
+//                VNodeEllipticalArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
+//            }
+//            break;
+//            case (Tool::NodeSpline):
+//            {
+//                const auto obj = data->GetGObject(nodeD.getId());
+//                if (obj->getType() == GOType::Spline)
+//                {
+//                    id = CreateNode<VSpline>(data, nodeD.getId());
+//                }
+//                else
+//                {
+//                    id = CreateNode<VCubicBezier>(data, nodeD.getId());
+//                }
+//                VNodeSpline::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
+//            }
+//            break;
+//            case (Tool::NodeSplinePath):
+//            {
+//                const auto obj = data->GetGObject(nodeD.getId());
+//                if (obj->getType() == GOType::SplinePath)
+//                {
+//                    id = CreateNode<VSplinePath>(data, nodeD.getId());
+//                }
+//                else
+//                {
+//                    id = CreateNode<VCubicBezierPath>(data, nodeD.getId());
+//                }
+//                VNodeSplinePath::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
+//            }
+//            break;
+//            default:
+//                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+//                break;
+//        }
+//        VNodeDetail node(id, nodeD.getTypeTool(), NodeDetail::Contour, nodeD.getMx(), nodeD.getMy(),
+//                         nodeD.getReverse());
+//        det.append(node);
+//    }
+//    det.setName(detail.getName());
+//    det.setWidth(detail.getWidth());
+//    det.setClosed(detail.getClosed());
+//    det.setSeamAllowance(detail.getSeamAllowance());
+//    det.setForbidFlipping(detail.getForbidFlipping());
+//    det.SetPatternPieceData(detail.GetPatternPieceData());
+//    det.SetPatternInfo(detail.GetPatternInfo());
+//    Create(0, det, scene, doc, data, Document::FullParse, Source::FromGui);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -403,16 +402,16 @@ void VToolDetail::FullUpdateFromGuiOk(int result)
     if (result == QDialog::Accepted)
     {
         SCASSERT(dialog != nullptr)
-        DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-        SCASSERT(dialogTool != nullptr)
-        const VDetail newDet = dialogTool->getDetail();
-        const VDetail oldDet = VAbstractTool::data.GetDetail(id);
+//        DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
+//        SCASSERT(dialogTool != nullptr)
+//        const VDetail newDet = dialogTool->getDetail();
+//        const VDetail oldDet = VAbstractTool::data.GetDetail(id);
 
-        qDebug() << "VToolDetail Position" << newDet.GetPatternPieceData().GetPos();
-        SaveDetailOptions *saveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-        connect(saveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-        qApp->getUndoStack()->push(saveCommand);
-        UpdateLabel();
+//        qDebug() << "VToolDetail Position" << newDet.GetPatternPieceData().GetPos();
+//        SaveDetailOptions *saveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
+//        connect(saveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+//        qApp->getUndoStack()->push(saveCommand);
+//        UpdateLabel();
     }
     delete dialog;
     dialog = nullptr;
@@ -801,13 +800,13 @@ void VToolDetail::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
     QAction *selectedAction = menu.exec(event->screenPos());
     if (selectedAction == actionOption)
     {
-        dialog = new DialogDetail(getData(), id, qApp->getMainWindow());
-        dialog->setModal(true);
-        connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
-                dialog, &DialogTool::ChosenObject);
-        connect(dialog, &DialogTool::DialogClosed, this, &VToolDetail::FullUpdateFromGuiOk);
-        setDialog();
-        dialog->show();
+//        dialog = new DialogDetail(getData(), id, qApp->getMainWindow());
+//        dialog->setModal(true);
+//        connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
+//                dialog, &DialogTool::ChosenObject);
+//        connect(dialog, &DialogTool::DialogClosed, this, &VToolDetail::FullUpdateFromGuiOk);
+//        setDialog();
+//        dialog->show();
     }
     else if (selectedAction == inLayoutOption)
     {

From f51d32d88e6f6c419edf9c9b00570cca094fbe0d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 10:24:48 +0200
Subject: [PATCH 151/208] Move static methods to private section.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtooluniondetails.h | 25 +++++++++++++----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/libs/vtools/tools/vtooluniondetails.h b/src/libs/vtools/tools/vtooluniondetails.h
index fae483cda..c7b44b6da 100644
--- a/src/libs/vtools/tools/vtooluniondetails.h
+++ b/src/libs/vtools/tools/vtooluniondetails.h
@@ -73,8 +73,6 @@ public:
                                      const Document &parse,
                                      const Source &typeCreation,
                                      bool retainPieces = false);
-    static void  PointsOnEdge(const VDetail &d, const quint32 &index, VPointF &p1, VPointF &p2, VContainer *data);
-    static void  FindIndexJ(const qint32 &pointsD2, const VDetail &d2, const quint32 &indexD2, qint32 &j);
     static QVector<VDetail> GetDetailFromFile(VAbstractPattern *doc, const QDomElement &domElement);
 
     static const QString ToolType;
@@ -88,15 +86,7 @@ public:
     static const QString AttrNodeType;
     static const QString NodeTypeContour;
     static const QString NodeTypeModeling;
-    static void  AddToNewDetail(VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
-                                VDetail &newDetail, const VDetail &det, const int &i, const quint32 &idTool,
-                                QVector<quint32> &children, const QString &drawName, const qreal &dx = 0,
-                                const qreal &dy = 0, const quint32 &pRotate = NULL_ID, const qreal &angle = 0);
-    static void  UpdatePoints(VContainer *data, const VDetail &det, const int &i,
-                              QVector<quint32> &children, const qreal &dx = 0, const qreal &dy = 0,
-                              const quint32 &pRotate = NULL_ID, const qreal &angle = 0);
-    static void  BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate,
-                                 const qreal &angle);
+
     virtual QString getTagName() const Q_DECL_OVERRIDE;
     virtual void ShowVisualization(bool show) Q_DECL_OVERRIDE;
     virtual void incrementReferens() Q_DECL_OVERRIDE;
@@ -144,6 +134,19 @@ private:
     static QVector<quint32> AllChildren(VAbstractPattern *doc, quint32 id);
     static quint32          TakeNextId(QVector<quint32> &children);
     static QString          DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id);
+    static void             PointsOnEdge(const VDetail &d, const quint32 &index, VPointF &p1, VPointF &p2,
+                                         VContainer *data);
+    static void             FindIndexJ(const qint32 &pointsD2, const VDetail &d2, const quint32 &indexD2, qint32 &j);
+    static void             AddToNewDetail(VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
+                                           VDetail &newDetail, const VDetail &det, const int &i, const quint32 &idTool,
+                                           QVector<quint32> &children, const QString &drawName, const qreal &dx = 0,
+                                           const qreal &dy = 0, const quint32 &pRotate = NULL_ID,
+                                           const qreal &angle = 0);
+    static void             UpdatePoints(VContainer *data, const VDetail &det, const int &i, QVector<quint32> &children,
+                                         const qreal &dx = 0, const qreal &dy = 0, const quint32 &pRotate = NULL_ID,
+                                         const qreal &angle = 0);
+    static void             BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate,
+                                            const qreal &angle);
 };
 
 #endif // VTOOLUNIONDETAILS_H

From 548f7844f4f0d3131fca653950d9af5cd3083fc9 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 15:19:27 +0200
Subject: [PATCH 152/208] Missed to replace VDetail by VPiece.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtoolseamallowance.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index d245c8089..a8fd22f23 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -470,7 +470,7 @@ void VToolSeamAllowance::Highlight(quint32 id)
  */
 void VToolSeamAllowance::UpdateLabel()
 {
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
+    const VPiece detail = VAbstractTool::data.GetPiece(id);
     const VPatternPieceData& data = detail.GetPatternPieceData();
 
     if (data.IsVisible() == true)
@@ -482,7 +482,7 @@ void VToolSeamAllowance::UpdateLabel()
         }
         m_dataLabel->SetFont(fnt);
         m_dataLabel->SetSize(data.GetLabelWidth(), data.GetLabelHeight());
-        m_dataLabel->UpdateData(detail.getName(), data);
+        m_dataLabel->UpdateData(detail.GetName(), data);
         QPointF pt = data.GetPos();
         QRectF rectBB;
         rectBB.setTopLeft(pt);

From c0658243063a940be5deebde0a2fa581f2ccd3df Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 16:06:03 +0200
Subject: [PATCH 153/208] Fix crash when create an internal path.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 5d039e29a..78c7eac97 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -229,11 +229,14 @@ void DialogPiecePath::ShowVisualization()
 {
     AddVisualization<VisToolPiecePath>();
 
-    VToolSeamAllowance *tool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(GetPieceId()));
-    SCASSERT(tool != nullptr);
-    auto visPath = qobject_cast<VisToolPiecePath *>(vis);
-    SCASSERT(visPath != nullptr);
-    visPath->setParentItem(tool);
+    if (m_showMode)
+    {
+        VToolSeamAllowance *tool = qobject_cast<VToolSeamAllowance*>(VAbstractPattern::getTool(GetPieceId()));
+        SCASSERT(tool != nullptr);
+        auto visPath = qobject_cast<VisToolPiecePath *>(vis);
+        SCASSERT(visPath != nullptr);
+        visPath->setParentItem(tool);
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From dabac6b17d283c5f9fb74cbaefd60e16c8e7d5e4 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 16:06:39 +0200
Subject: [PATCH 154/208] Better help messages.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 78c7eac97..c3247f8f1 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -723,7 +723,7 @@ bool DialogPiecePath::PathIsValid() const
     {
         if (GetType() == PiecePathType::CustomSeamAllowance && FirstPointEqualLast(ui->listWidget))
         {
-            url += tr("First point cannot be equal to the last point!");
+            url += tr("First point of <b>custom seam allowance</b> cannot be equal to the last point!");
             ui->helpLabel->setText(url);
             return false;
         }
@@ -737,7 +737,7 @@ bool DialogPiecePath::PathIsValid() const
 
     if (not m_showMode && ui->comboBoxPiece->count() <= 0)
     {
-        url += tr("List of pieces is empty!");
+        url += tr("List of objects is empty!");
         ui->helpLabel->setText(url);
         return false;
     }

From 59c9a0b4006bcd136463760fc88609c5771971ae Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 16:57:49 +0200
Subject: [PATCH 155/208] Allow a user to select a point covered by
 visualization.

--HG--
branch : feature
---
 .../visualization/path/vistoolpiecepath.cpp   |  1 +
 src/libs/vwidgets/vsimplepoint.cpp            | 60 +++++++++++++------
 src/libs/vwidgets/vsimplepoint.h              |  4 ++
 3 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
index 470a4ffff..e0c4a5750 100644
--- a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
@@ -92,6 +92,7 @@ VSimplePoint *VisToolPiecePath::GetPoint(quint32 i, const QColor &color)
         VSimplePoint *point = new VSimplePoint(NULL_ID, color, *Visualization::data->GetPatternUnit(), &factor);
         point->SetPointHighlight(true);
         point->setParentItem(this);
+        point->SetVisualizationMode(true);
         m_points.append(point);
 
         return point;
diff --git a/src/libs/vwidgets/vsimplepoint.cpp b/src/libs/vwidgets/vsimplepoint.cpp
index f8bfa1d37..8d1980e3a 100644
--- a/src/libs/vwidgets/vsimplepoint.cpp
+++ b/src/libs/vwidgets/vsimplepoint.cpp
@@ -59,7 +59,8 @@ VSimplePoint::VSimplePoint(quint32 id, const QColor &currentColor, Unit patternU
       namePoint(nullptr),
       lineName(nullptr),
       m_onlyPoint(false),
-      m_isHighlight(false)
+      m_isHighlight(false),
+      m_visualizationMode(false)
 {
     namePoint = new VGraphicsSimpleTextItem(this);
     connect(namePoint, &VGraphicsSimpleTextItem::ShowContextMenu, this, &VSimplePoint::ContextMenu);
@@ -92,6 +93,19 @@ bool VSimplePoint::IsOnlyPoint() const
     return m_onlyPoint;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VSimplePoint::SetVisualizationMode(bool value)
+{
+    m_visualizationMode = value;
+    this->setFlag(QGraphicsItem::ItemIsFocusable, not m_visualizationMode);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VSimplePoint::IsVisualizationMode() const
+{
+    return m_visualizationMode;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void VSimplePoint::SetPointHighlight(bool value)
 {
@@ -209,24 +223,31 @@ void VSimplePoint::ChangedPosition(const QPointF &pos)
 //---------------------------------------------------------------------------------------------------------------------
 void VSimplePoint::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
-    // Special for not selectable item first need to call standard mousePressEvent then accept event
-    QGraphicsEllipseItem::mousePressEvent(event);
-
-    // Somehow clicking on notselectable object do not clean previous selections.
-    if (not (flags() & ItemIsSelectable) && scene())
+    if (m_visualizationMode)
     {
-        scene()->clearSelection();
-    }
-
-    if (selectionType == SelectionType::ByMouseRelease)
-    {
-        event->accept();// Special for not selectable item first need to call standard mousePressEvent then accept event
+        event->ignore();
     }
     else
     {
-        if (event->button() == Qt::LeftButton)
+        // Special for not selectable item first need to call standard mousePressEvent then accept event
+        QGraphicsEllipseItem::mousePressEvent(event);
+
+        // Somehow clicking on notselectable object do not clean previous selections.
+        if (not (flags() & ItemIsSelectable) && scene())
         {
-            emit Choosed(id);
+            scene()->clearSelection();
+        }
+
+        if (selectionType == SelectionType::ByMouseRelease)
+        {// Special for not selectable item first need to call standard mousePressEvent then accept event
+            event->accept();
+        }
+        else
+        {
+            if (event->button() == Qt::LeftButton)
+            {
+                emit Choosed(id);
+            }
         }
     }
 }
@@ -234,14 +255,17 @@ void VSimplePoint::mousePressEvent(QGraphicsSceneMouseEvent *event)
 //---------------------------------------------------------------------------------------------------------------------
 void VSimplePoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
 {
-    if (selectionType == SelectionType::ByMouseRelease)
+    if (not m_visualizationMode)
     {
-        if (event->button() == Qt::LeftButton)
+        if (selectionType == SelectionType::ByMouseRelease)
         {
-            emit Choosed(id);
+            if (event->button() == Qt::LeftButton)
+            {
+                emit Choosed(id);
+            }
         }
+        QGraphicsEllipseItem::mouseReleaseEvent(event);
     }
-    QGraphicsEllipseItem::mouseReleaseEvent(event);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vwidgets/vsimplepoint.h b/src/libs/vwidgets/vsimplepoint.h
index 68785a802..7378f5362 100644
--- a/src/libs/vwidgets/vsimplepoint.h
+++ b/src/libs/vwidgets/vsimplepoint.h
@@ -65,6 +65,9 @@ public:
     void SetOnlyPoint(bool value);
     bool IsOnlyPoint() const;
 
+    void SetVisualizationMode(bool value);
+    bool IsVisualizationMode() const;
+
     void SetPointHighlight(bool value);
 
     void RefreshLine();
@@ -112,6 +115,7 @@ private:
 
     bool m_onlyPoint;
     bool m_isHighlight;
+    bool m_visualizationMode;
 };
 
 #endif // VSIMPLEPOINT_H

From 970762d0b3191bbed46765bff81b6d0ea6ec3e16 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 17:03:15 +0200
Subject: [PATCH 156/208] Allow a user to select a curve covered by
 visualization.

--HG--
branch : feature
---
 src/libs/vtools/visualization/path/vistoolpiecepath.cpp | 8 ++++++++
 src/libs/vtools/visualization/path/vistoolpiecepath.h   | 3 +++
 2 files changed, 11 insertions(+)

diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
index e0c4a5750..a5e294f2a 100644
--- a/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.cpp
@@ -30,6 +30,8 @@
 #include "../vwidgets/vsimplepoint.h"
 #include "../vgeometry/vpointf.h"
 
+#include <QGraphicsSceneMouseEvent>
+
 //---------------------------------------------------------------------------------------------------------------------
 VisToolPiecePath::VisToolPiecePath(const VContainer *data, QGraphicsItem *parent)
     : VisPath(data, parent),
@@ -80,6 +82,12 @@ void VisToolPiecePath::SetPath(const VPiecePath &path)
     m_path = path;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VisToolPiecePath::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    event->ignore();
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VSimplePoint *VisToolPiecePath::GetPoint(quint32 i, const QColor &color)
 {
diff --git a/src/libs/vtools/visualization/path/vistoolpiecepath.h b/src/libs/vtools/visualization/path/vistoolpiecepath.h
index 7ca400800..591561059 100644
--- a/src/libs/vtools/visualization/path/vistoolpiecepath.h
+++ b/src/libs/vtools/visualization/path/vistoolpiecepath.h
@@ -49,6 +49,9 @@ public:
     virtual int  type() const Q_DECL_OVERRIDE {return Type;}
     enum { Type = UserType + static_cast<int>(Vis::ToolPiecePath)};
 
+protected:
+    virtual void mousePressEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE;
+
 private:
     Q_DISABLE_COPY(VisToolPiecePath)
     QVector<VSimplePoint *> m_points;

From af51e5e24027b2684a11cd0376a80a480984b276 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 19:07:14 +0200
Subject: [PATCH 157/208] Seam allowance tool already initializated and can't
 init the path.

--HG--
branch : feature
---
 .../tools/nodeDetails/vtoolpiecepath.cpp      | 21 +++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index 54fc53749..e86ff9d1c 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -31,6 +31,7 @@
 #include "../vpatterndb/vpiecepath.h"
 #include "../vpatterndb/vpiecenode.h"
 #include "../../undocommands/savepieceoptions.h"
+#include "../vtoolseamallowance.h"
 
 //---------------------------------------------------------------------------------------------------------------------
 VToolPiecePath *VToolPiecePath::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
@@ -82,10 +83,22 @@ VToolPiecePath *VToolPiecePath::Create(quint32 _id, const VPiecePath &path, quin
         }
         else
         {
-            // Try to prevent memory leak
-            scene->addItem(pathTool);// First adopted by scene
-            pathTool->hide();// If no one will use node, it will stay hidden
-            pathTool->SetParentType(ParentType::Scene);
+            if (typeCreation == Source::FromGui && path.GetType() == PiecePathType::InternalPath)
+            { // Seam allowance tool already initializated and can't init the path
+                SCASSERT(pieceId > NULL_ID);
+                VToolSeamAllowance *saTool = qobject_cast<VToolSeamAllowance*>(doc->getTool(pieceId));
+                SCASSERT(saTool != nullptr);
+                pathTool->setParentItem(saTool);
+                pathTool->SetParentType(ParentType::Item);
+                doc->IncrementReferens(id);
+            }
+            else
+            {
+                // Try to prevent memory leak
+                scene->addItem(pathTool);// First adopted by scene
+                pathTool->hide();// If no one will use node, it will stay hidden
+                pathTool->SetParentType(ParentType::Scene);
+            }
         }
         return pathTool;
     }

From e974f75b51788727b040a2a8f37404e20cfd1900 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 13 Jan 2017 19:09:22 +0200
Subject: [PATCH 158/208] Make Internal path first in list.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index c3247f8f1..d9d017a80 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -409,8 +409,8 @@ void DialogPiecePath::ChangedSAAfter(double d)
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::InitPathTypes()
 {
-    ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CustomSeamAllowance));
     ui->comboBoxType->addItem(tr("Internal path"), static_cast<int>(PiecePathType::InternalPath));
+    ui->comboBoxType->addItem(tr("Custom seam allowance"), static_cast<int>(PiecePathType::CustomSeamAllowance));
 
     ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath);
 }

From c48dc6b4a23d35a49ace8cd930a3b806a1466c67 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 14 Jan 2017 11:52:39 +0200
Subject: [PATCH 159/208] Update scene size after full parse.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index ded62710f..412f16af2 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -2713,6 +2713,9 @@ void MainWindow::FullParseFile()
     patternReadOnly = doc->IsReadOnly();
     SetEnableWidgets(true);
     detailsWidget->UpdateList();
+
+    VMainGraphicsView::NewSceneRect(sceneDraw, qApp->getSceneView());
+    VMainGraphicsView::NewSceneRect(sceneDetails, qApp->getSceneView());
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From 4cc232fc744c56c59b60344a437c418d59063def Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 14 Jan 2017 12:10:21 +0200
Subject: [PATCH 160/208] Fix crash. Valentina crashes when change name of
 piece.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 8738ac42d..9be77474d 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -69,6 +69,7 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
     InitGrainlineTab();
 
     flagName = true;//We have default name of piece.
+    ChangeColor(ui->labelEditName, okColor);
     flagError = MainPathIsValid();
     CheckState();
 
@@ -396,21 +397,20 @@ void DialogSeamAllowance::Remove()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::NameDetailChanged()
 {
-    SCASSERT(labelEditNamePoint != nullptr)
     QLineEdit* edit = qobject_cast<QLineEdit*>(sender());
     if (edit)
     {
         if (edit->text().isEmpty())
         {
             flagName = false;
-            ChangeColor(labelEditNamePoint, Qt::red);
+            ChangeColor(ui->labelEditName, Qt::red);
             QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png");
             ui->tabWidget->setTabIcon(1, icon);
         }
         else
         {
             flagName = true;
-            ChangeColor(labelEditNamePoint, okColor);
+            ChangeColor(ui->labelEditName, okColor);
             QIcon icon;
             ui->tabWidget->setTabIcon(1, icon);
         }

From 5442eb40b923ec2f768197b155878adc3e92979a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 16 Jan 2017 11:59:02 +0200
Subject: [PATCH 161/208] Move methods to class VAbstractPattern to be able to
 use them for tool Unite Details.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp    | 63 +------------------------
 src/app/valentina/xml/vpattern.h      |  2 -
 src/libs/ifc/xml/vabstractpattern.cpp | 66 ++++++++++++++++++++++++++-
 src/libs/ifc/xml/vabstractpattern.h   |  7 ++-
 src/libs/ifc/xml/vdomdocument.cpp     | 22 ++++-----
 src/libs/ifc/xml/vdomdocument.h       | 16 +++----
 6 files changed, 91 insertions(+), 85 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 155705c29..1c5d0b82b 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -562,53 +562,6 @@ VNodeDetail VPattern::ParseDetailNode(const QDomElement &domElement) const
     return VNodeDetail(id, tool, nodeType, mx, my, reverse);
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
-{
-    const quint32 id = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
-    const bool reverse = GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
-    const qreal saBefore = GetParametrDouble(domElement, VAbstractPattern::AttrSABefore, "-1");
-    const qreal saAfter = GetParametrDouble(domElement, VAbstractPattern::AttrSAAfter, "-1");
-    const PieceNodeAngle angle = static_cast<PieceNodeAngle>(GetParametrUInt(domElement, AttrAngle, "0"));
-
-    const QString t = GetParametrString(domElement, AttrType, VAbstractPattern::NodePoint);
-    Tool tool;
-
-    const QStringList types = QStringList() << VAbstractPattern::NodePoint
-                                            << VAbstractPattern::NodeArc
-                                            << VAbstractPattern::NodeSpline
-                                            << VAbstractPattern::NodeSplinePath
-                                            << VAbstractPattern::NodeElArc;
-
-    switch (types.indexOf(t))
-    {
-        case 0: // VAbstractPattern::NodePoint
-            tool = Tool::NodePoint;
-            break;
-        case 1: // VAbstractPattern::NodeArc
-            tool = Tool::NodeArc;
-            break;
-        case 2: // VAbstractPattern::NodeSpline
-            tool = Tool::NodeSpline;
-            break;
-        case 3: // VAbstractPattern::NodeSplinePath
-            tool = Tool::NodeSplinePath;
-            break;
-        case 4: // NodeElArc
-            tool = Tool::NodeElArc;
-            break;
-        default:
-            VException e(tr("Wrong tag name '%1'.").arg(t));
-            throw e;
-    }
-    VPieceNode node(id, tool, reverse);
-    node.SetSABefore(saBefore);
-    node.SetSAAfter(saAfter);
-    node.SetAngleType(angle);
-
-    return node;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseDrawElement parse draw tag.
@@ -782,7 +735,7 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                         }
                         else
                         {
-                            ParsePieceNodes(element, detail);
+                            detail.SetPath(ParsePieceNodes(element));
                         }
                         break;
                     case 1:// TagData
@@ -832,20 +785,6 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, b
     detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, detail.GetSAWidth(), closed));
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const
-{
-    const QDomNodeList nodeList = domElement.childNodes();
-    for (qint32 i = 0; i < nodeList.size(); ++i)
-    {
-        const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull())
-        {
-            detail.GetPath().Append(ParseSANode(element));
-        }
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VPattern::ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const
 {
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 8b444e36e..49da3ab46 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -115,13 +115,11 @@ private:
     VMainGraphicsScene *sceneDetail;
 
     VNodeDetail    ParseDetailNode(const QDomElement &domElement) const;
-    VPieceNode     ParseSANode(const QDomElement &domElement) const;
 
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
-    void           ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const;
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index c30ee0164..5f04dfa3e 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -45,6 +45,7 @@
 #include "../ifc/exception/vexceptionbadid.h"
 #include "../ifc/ifcdef.h"
 #include "../vpatterndb/vcontainer.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "../vtools/tools/vdatatool.h"
 #include "vpatternconverter.h"
 #include "vdomdocument.h"
@@ -555,7 +556,70 @@ void VAbstractPattern::AddTool(const quint32 &id, VDataTool *tool)
 {
     Q_ASSERT_X(id != 0, Q_FUNC_INFO, "id == 0");
     SCASSERT(tool != nullptr)
-    tools.insert(id, tool);
+            tools.insert(id, tool);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath VAbstractPattern::ParsePieceNodes(const QDomElement &domElement)
+{
+    VPiecePath path;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull())
+        {
+            path.Append(ParseSANode(element));
+        }
+    }
+    return path;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
+{
+    const quint32 id = VDomDocument::GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
+    const bool reverse = VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
+    const qreal saBefore = VDomDocument::GetParametrDouble(domElement, VAbstractPattern::AttrSABefore, "-1");
+    const qreal saAfter = VDomDocument::GetParametrDouble(domElement, VAbstractPattern::AttrSAAfter, "-1");
+    const PieceNodeAngle angle = static_cast<PieceNodeAngle>(VDomDocument::GetParametrUInt(domElement, AttrAngle, "0"));
+
+    const QString t = VDomDocument::GetParametrString(domElement, AttrType, VAbstractPattern::NodePoint);
+    Tool tool;
+
+    const QStringList types = QStringList() << VAbstractPattern::NodePoint
+                                            << VAbstractPattern::NodeArc
+                                            << VAbstractPattern::NodeSpline
+                                            << VAbstractPattern::NodeSplinePath
+                                            << VAbstractPattern::NodeElArc;
+
+    switch (types.indexOf(t))
+    {
+        case 0: // VAbstractPattern::NodePoint
+            tool = Tool::NodePoint;
+            break;
+        case 1: // VAbstractPattern::NodeArc
+            tool = Tool::NodeArc;
+            break;
+        case 2: // VAbstractPattern::NodeSpline
+            tool = Tool::NodeSpline;
+            break;
+        case 3: // VAbstractPattern::NodeSplinePath
+            tool = Tool::NodeSplinePath;
+            break;
+        case 4: // NodeElArc
+            tool = Tool::NodeElArc;
+            break;
+        default:
+            VException e(QObject::tr("Wrong tag name '%1'.").arg(t));
+            throw e;
+    }
+    VPieceNode node(id, tool, reverse);
+    node.SetSABefore(saBefore);
+    node.SetSAAfter(saAfter);
+    node.SetAngleType(angle);
+
+    return node;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index 1e2c8e34c..a8d6052e6 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -45,6 +45,8 @@
 #include "vtoolrecord.h"
 
 class QDomElement;
+class VPiecePath;
+class VPieceNode;
 
 enum class Document : char { LiteParse, LitePPParse, FullParse };
 enum class LabelType : char {NewPatternPiece, NewLabel};
@@ -93,6 +95,8 @@ public:
     static VDataTool* getTool(const quint32 &id);
     static void       AddTool(const quint32 &id, VDataTool *tool);
 
+    static VPiecePath ParsePieceNodes(const QDomElement &domElement);
+
     void           AddToolOnRemove(VDataTool *tool);
 
     QVector<VToolRecord> *getHistory();
@@ -344,7 +348,8 @@ protected:
     /** @brief tools list with pointer on tools. */
     static QHash<quint32, VDataTool*> tools;
 
-    static void    ToolExists(const quint32 &id);
+    static void       ToolExists(const quint32 &id);
+    static VPieceNode ParseSANode(const QDomElement &domElement);
 
     void           SetActivPP(const QString& name);
 
diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp
index 307ffeb16..f8efed3e9 100644
--- a/src/libs/ifc/xml/vdomdocument.cpp
+++ b/src/libs/ifc/xml/vdomdocument.cpp
@@ -203,7 +203,7 @@ bool VDomDocument::find(const QDomElement &node, const QString& id)
  * @param name attribute name
  * @return long long value
  */
-quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue) const
+quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue)
 {
     Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name of parametr is empty");
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null"); //-V591
@@ -212,7 +212,7 @@ quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QStri
     QString parametr;
     quint32 id = 0;
 
-    QString message = tr("Can't convert toUInt parameter");
+    const QString message = QObject::tr("Can't convert toUInt parameter");
     try
     {
         parametr = GetParametrString(domElement, name, defValue);
@@ -233,7 +233,7 @@ quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QStri
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString &name, const QString &defValue) const
+bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString &name, const QString &defValue)
 {
     Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name of parametr is empty");
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
@@ -241,7 +241,7 @@ bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString
     QString parametr;
     bool val = true;
 
-    QString message = tr("Can't convert toBool parameter");
+    const QString message = QObject::tr("Can't convert toBool parameter");
     try
     {
         parametr = GetParametrString(domElement, name, defValue);
@@ -280,7 +280,7 @@ bool VDomDocument::GetParametrBool(const QDomElement &domElement, const QString
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-NodeUsage VDomDocument::GetParametrUsage(const QDomElement &domElement, const QString &name) const
+NodeUsage VDomDocument::GetParametrUsage(const QDomElement &domElement, const QString &name)
 {
     const bool value = GetParametrBool(domElement, name, trueStr);
     if (value)
@@ -315,7 +315,7 @@ void VDomDocument::SetParametrUsage(QDomElement &domElement, const QString &name
  * @throw VExceptionEmptyParameter when attribute is empty
  */
 QString VDomDocument::GetParametrString(const QDomElement &domElement, const QString &name,
-                                        const QString &defValue) const
+                                        const QString &defValue)
 {
     Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name of parametr is empty");
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
@@ -324,7 +324,7 @@ QString VDomDocument::GetParametrString(const QDomElement &domElement, const QSt
     {
         if (defValue.isEmpty())
         {
-            throw VExceptionEmptyParameter(tr("Got empty parameter"), name, domElement);
+            throw VExceptionEmptyParameter(QObject::tr("Got empty parameter"), name, domElement);
         }
         else
         {
@@ -341,7 +341,7 @@ QString VDomDocument::GetParametrString(const QDomElement &domElement, const QSt
  * @param name attribute name
  * @return double value
  */
-qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QString &name, const QString &defValue) const
+qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QString &name, const QString &defValue)
 {
     Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name of parametr is empty");
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
@@ -349,7 +349,7 @@ qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QStri
     bool ok = false;
     qreal param = 0;
 
-    QString message = tr("Can't convert toDouble parameter");
+    const QString message = QObject::tr("Can't convert toDouble parameter");
     try
     {
         QString parametr = GetParametrString(domElement, name, defValue);
@@ -374,13 +374,13 @@ qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QStri
  * @param domElement tag in xml tree.
  * @return id value.
  */
-quint32 VDomDocument::GetParametrId(const QDomElement &domElement) const
+quint32 VDomDocument::GetParametrId(const QDomElement &domElement)
 {
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
 
     quint32 id = NULL_ID;
 
-    const QString message = tr("Got wrong parameter id. Need only id > 0.");
+    const QString message = QObject::tr("Got wrong parameter id. Need only id > 0.");
     try
     {
         id = GetParametrUInt(domElement, VDomDocument::AttrId, NULL_ID_STR);
diff --git a/src/libs/ifc/xml/vdomdocument.h b/src/libs/ifc/xml/vdomdocument.h
index 1d1ed589b..540be9aea 100644
--- a/src/libs/ifc/xml/vdomdocument.h
+++ b/src/libs/ifc/xml/vdomdocument.h
@@ -96,16 +96,16 @@ public:
     template <typename T>
     void SetAttribute(QDomElement &domElement, const QString &name, const T &value) const;
 
-    quint32        GetParametrUInt(const QDomElement& domElement, const QString &name, const QString &defValue) const;
-    bool           GetParametrBool(const QDomElement& domElement, const QString &name, const QString &defValue) const;
+    static quint32 GetParametrUInt(const QDomElement& domElement, const QString &name, const QString &defValue);
+    static bool    GetParametrBool(const QDomElement& domElement, const QString &name, const QString &defValue);
 
-    NodeUsage      GetParametrUsage(const QDomElement& domElement, const QString &name) const;
-    void           SetParametrUsage(QDomElement& domElement, const QString &name, const NodeUsage &value);
+    static NodeUsage GetParametrUsage(const QDomElement& domElement, const QString &name);
+    static void      SetParametrUsage(QDomElement& domElement, const QString &name, const NodeUsage &value);
 
-    QString        GetParametrString(const QDomElement& domElement, const QString &name,
-                                     const QString &defValue = QString()) const;
-    qreal          GetParametrDouble(const QDomElement& domElement, const QString &name, const QString &defValue) const;
-    quint32        GetParametrId(const QDomElement& domElement) const;
+    static QString GetParametrString(const QDomElement& domElement, const QString &name,
+                                     const QString &defValue = QString());
+    static qreal   GetParametrDouble(const QDomElement& domElement, const QString &name, const QString &defValue);
+    static quint32 GetParametrId(const QDomElement& domElement);
 
     static void    ValidateXML(const QString &schema, const QString &fileName);
     virtual void   setXMLContent(const QString &fileName);

From 60810c4d04f8b1926106cf8d343d9c7091fe1d64 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 16 Jan 2017 12:06:50 +0200
Subject: [PATCH 162/208] Use parent implementation for methods
 incrementReferens() and decrementReferens() where possible.

--HG--
branch : feature
---
 src/libs/vtools/tools/nodeDetails/vabstractnode.cpp  | 7 ++-----
 src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp | 7 ++-----
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/src/libs/vtools/tools/nodeDetails/vabstractnode.cpp b/src/libs/vtools/tools/nodeDetails/vabstractnode.cpp
index 381509163..a8e2f433c 100644
--- a/src/libs/vtools/tools/nodeDetails/vabstractnode.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vabstractnode.cpp
@@ -75,7 +75,7 @@ void VAbstractNode::ShowVisualization(bool show)
 //---------------------------------------------------------------------------------------------------------------------
 void VAbstractNode::incrementReferens()
 {
-    ++_referens;
+    VAbstractTool::incrementReferens();
     if (_referens == 1)
     {
         if (idTool != NULL_ID)
@@ -102,10 +102,7 @@ void VAbstractNode::incrementReferens()
  */
 void VAbstractNode::decrementReferens()
 {
-    if (_referens > 0)
-    {
-        --_referens;
-    }
+    VAbstractTool::decrementReferens();
     if (_referens == 0)
     {
         if (idTool != NULL_ID)
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index e86ff9d1c..053748e9f 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -114,7 +114,7 @@ QString VToolPiecePath::getTagName() const
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::incrementReferens()
 {
-    ++_referens;
+    VAbstractTool::incrementReferens();
     if (_referens == 1)
     {
         if (idTool != NULL_ID)
@@ -137,10 +137,7 @@ void VToolPiecePath::incrementReferens()
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::decrementReferens()
 {
-    if (_referens > 0)
-    {
-        --_referens;
-    }
+    VAbstractTool::decrementReferens();
     if (_referens == 0)
     {
         if (idTool != NULL_ID)

From 6faa0bc3180fdc7e6ac6c5fc6303abcfb8261daa Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 16 Jan 2017 12:08:13 +0200
Subject: [PATCH 163/208] First successful build. The redesign is not finished.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp          |   14 +-
 src/libs/vpatterndb/vpiecepath.cpp          |   86 +
 src/libs/vpatterndb/vpiecepath.h            |    7 +-
 src/libs/vtools/tools/vtooluniondetails.cpp | 2103 ++++++++++---------
 src/libs/vtools/tools/vtooluniondetails.h   |   83 +-
 5 files changed, 1231 insertions(+), 1062 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 1c5d0b82b..a8756eadc 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -3164,13 +3164,17 @@ void VPattern::ParseToolsElement(VMainGraphicsScene *scene, const QDomElement &d
             {
                 quint32 id = 0;
                 ToolsCommonAttributes(domElement, id);
-                const quint32 indexD1 = GetParametrUInt(domElement, VToolUnionDetails::AttrIndexD1, "-1");
-                const quint32 indexD2 = GetParametrUInt(domElement, VToolUnionDetails::AttrIndexD2, "-1");
 
-                const QVector<VDetail> vector = VToolUnionDetails::GetDetailFromFile(this, domElement);
+                VToolUnionDetailsInitData initData;
+                initData.indexD1 = GetParametrUInt(domElement, VToolUnionDetails::AttrIndexD1, "-1");
+                initData.indexD2 = GetParametrUInt(domElement, VToolUnionDetails::AttrIndexD2, "-1");
+                initData.scene = scene;
+                initData.doc = this;
+                initData.data = data;
+                initData.parse = parse;
+                initData.typeCreation = Source::FromFile;
 
-                VToolUnionDetails::Create(id, vector[0], vector[1], 0, 0, indexD1, indexD2, scene, this, data, parse,
-                                          Source::FromFile);
+                VToolUnionDetails::Create(id, initData);
             }
             catch (const VExceptionBadId &e)
             {
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 3e9718b76..e0ed91595 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -361,6 +361,92 @@ int VPiecePath::indexOfNode(quint32 id) const
     return -1;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief NodeOnEdge return nodes located on edge with index.
+ * @param index index of edge.
+ * @param p1 first node.
+ * @param p2 second node.
+ */
+void VPiecePath::NodeOnEdge(quint32 index, VPieceNode &p1, VPieceNode &p2) const
+{
+    const QVector<VPieceNode> list = ListNodePoint();
+    if (index > static_cast<quint32>(list.size()))
+    {
+        qDebug()<<"Wrong edge index index ="<<index;
+        return;
+    }
+    p1 = list.at(static_cast<int>(index));
+    if (index + 1 > static_cast<quint32>(list.size()) - 1)
+    {
+        p2 = list.at(0);
+    }
+    else
+    {
+        p2 = list.at(static_cast<int>(index+1));
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief listNodePoint return list nodes only with points.
+ * @return list points node.
+ */
+QVector<VPieceNode> VPiecePath::ListNodePoint() const
+{
+    QVector<VPieceNode> list;
+    for (int i = 0; i < d->m_nodes.size(); ++i) //-V807
+    {
+        if (d->m_nodes.at(i).GetTypeTool() == Tool::NodePoint)
+        {
+            list.append(d->m_nodes.at(i));
+        }
+    }
+    return list;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief RemoveEdge return path without edge with index.
+ * @param index idex of edge.
+ * @return path without edge with index.
+ */
+VPiecePath VPiecePath::RemoveEdge(quint32 index) const
+{
+    VPiecePath path(*this);
+    path.Clear();
+
+    // Edge can be only segment. We ignore all curves inside segments.
+    const quint32 edges = static_cast<quint32>(ListNodePoint().size());
+    quint32 k = 0;
+    for (quint32 i=0; i<edges; ++i)
+    {
+        if (i == index)
+        {
+            path.Append(this->at(static_cast<int>(k)));
+            ++k;
+        }
+        else
+        {
+            VPieceNode p1;
+            VPieceNode p2;
+            this->NodeOnEdge(i, p1, p2);
+            const int j1 = this->indexOfNode(p1.GetId());
+            int j2 = this->indexOfNode(p2.GetId());
+            if (j2 == 0)
+            {
+                j2 = this->CountNodes();
+            }
+            for (int j=j1; j<j2; ++j)
+            {// Add "segment" except last point. Inside can be curves too.
+                path.Append(this->at(j));
+                ++k;
+            }
+        }
+    }
+    return path;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
 {
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 1f3dbf901..557d8541d 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -79,7 +79,12 @@ public:
 
     QVector<quint32> MissingNodes(const VPiecePath &path) const;
 
-    int indexOfNode(quint32 id) const;
+    int  indexOfNode(quint32 id) const;
+    void NodeOnEdge(quint32 index, VPieceNode &p1, VPieceNode &p2) const;
+
+    QVector<VPieceNode> ListNodePoint() const;
+
+    VPiecePath RemoveEdge(quint32 index) const;
 
     VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
     VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index 44773e649..a7ad91eff 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -58,6 +58,8 @@
 #include "../vmisc/logging.h"
 #include "../vmisc/vabstractapplication.h"
 #include "../vpatterndb/vcontainer.h"
+#include "../vpatterndb/vpiecepath.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "../dialogs/tools/dialogtool.h"
 #include "nodeDetails/vnodearc.h"
 #include "nodeDetails/vnodeellipticalarc.h"
@@ -66,7 +68,7 @@
 #include "nodeDetails/vnodesplinepath.h"
 #include "vdatatool.h"
 #include "vnodedetail.h"
-#include "vtooldetail.h"
+#include "vtoolseamallowance.h"
 
 class QDomElement;
 class QDomNode;
@@ -92,1040 +94,55 @@ Q_LOGGING_CATEGORY(vToolUnion, "v.toolUnion")
 
 QT_WARNING_POP
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VToolUnionDetails costructor.
- * @param doc dom document container.
- * @param data dom document container.
- * @param id object id in container.
- * @param d1 first detail.
- * @param d2 second detail.
- * @param indexD1 index edge in first detail.
- * @param indexD2 index edge in second detail.
- * @param typeCreation way we create this tool.
- * @param parent parent object.
- */
-VToolUnionDetails::VToolUnionDetails(VAbstractPattern *doc, VContainer *data, const quint32 &id, const VDetail &d1,
-                                     const VDetail &d2, const quint32 &indexD1, const quint32 &indexD2,
-                                     const Source &typeCreation, const QString &drawName, QObject *parent)
-    :VAbstractTool(doc, data, id, parent), d1(d1), d2(d2), indexD1(indexD1), indexD2(indexD2), drawName(drawName)
+namespace
 {
-    _referens = 0;
-    ToolCreation(typeCreation);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddToNewDetail create united detail adding one node per time.
- * @param doc dom document container.
- * @param data container with variables.
- * @param newDetail united detail.
- * @param det detail what we union.
- * @param i index node in detail.
- * @param idTool id tool union details.
- * @param children list of children
- * @param drawName name of pattern piece
- * @param dx bias node x axis.
- * @param dy bias node y axis.
- * @param pRotate point rotation.
- * @param angle angle rotation.
- */
-void VToolUnionDetails::AddToNewDetail(VMainGraphicsScene *scene, VAbstractPattern *doc,
-                                       VContainer *data, VDetail &newDetail, const VDetail &det, const int &i,
-                                       const quint32 &idTool, QVector<quint32> &children, const QString &drawName,
-                                       const qreal &dx, const qreal &dy, const quint32 &pRotate, const qreal &angle)
+VPiecePath GetPieceMainPath(int piece, VAbstractPattern *doc, quint32 id)
 {
-    quint32 id = 0, idObject = 0;
-    switch (det.at(i).getTypeTool())
+    const QDomElement tool = doc->elementById(id);
+    if (tool.isNull())
     {
-        case (Tool::NodePoint):
+        VException e(QString("Can't get tool by id='%1'.").arg(id));
+        throw e;
+    }
+
+    const QDomNodeList nodesList = tool.childNodes();
+    for (qint32 i = 0; i < nodesList.size(); ++i)
+    {
+        const QDomElement element = nodesList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
         {
-            VPointF *point = new VPointF(*data->GeometricObject<VPointF>(det.at(i).getId()));
-            point->setMode(Draw::Modeling);
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+            const QDomNodeList detList = element.childNodes();
+            for (qint32 j = 0; j < detList.size(); ++j)
             {
-                BiasRotatePoint(point, dx, dy, *data->GeometricObject<VPointF>(pRotate), angle);
-            }
-
-            idObject = data->AddGObject(point);
-            children.append(idObject);
-            VPointF *point1 = new VPointF(*point);
-            point1->setMode(Draw::Modeling);
-            id = data->AddGObject(point1);
-            VNodePoint::Create(doc, data, scene, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
-        }
-        break;
-        case (Tool::NodeArc):
-        {
-            const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(det.at(i).getId());
-            VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
-            VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
-            VPointF *center = new VPointF(arc->GetCenter());
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(&p1, dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(center, dx, dy, p, angle);
-            }
-
-            QLineF l1(*center, p1);
-            QLineF l2(*center, p2);
-            center->setMode(Draw::Modeling);
-            quint32 idCenter = data->AddGObject(center);
-            Q_UNUSED(idCenter)
-            VArc *arc1 = new VArc(*center, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
-                                  QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle()));
-            arc1->setMode(Draw::Modeling);
-            idObject = data->AddGObject(arc1);
-            children.append(idObject);
-
-            VArc *arc2 = new VArc(*arc1);
-            arc2->setMode(Draw::Modeling);
-            id = data->AddGObject(arc2);
-
-            VNodeArc::Create(doc, data, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
-        }
-        break;
-        case (Tool::NodeElArc):
-        {
-            const QSharedPointer<VEllipticalArc> arc = data->GeometricObject<VEllipticalArc>(det.at(i).getId());
-            VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
-            VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
-            VPointF *center = new VPointF(arc->GetCenter());
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(&p1, dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(center, dx, dy, p, angle);
-            }
-
-            QLineF l1(*center, p1);
-            QLineF l2(*center, p2);
-            center->setMode(Draw::Modeling);
-            quint32 idCenter = data->AddGObject(center);
-            Q_UNUSED(idCenter)
-            VEllipticalArc *arc1 = new VEllipticalArc (*center, arc->GetRadius1(), arc->GetRadius2(),
-                                                       arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
-                                                       l1.angle(), QString().setNum(l1.angle()), l2.angle(),
-                                                       QString().setNum(l2.angle()), 0, "0");
-            arc1->setMode(Draw::Modeling);
-            idObject = data->AddGObject(arc1);
-            children.append(idObject);
-
-            VEllipticalArc *arc2 = new VEllipticalArc(*arc1);
-            arc2->setMode(Draw::Modeling);
-            id = data->AddGObject(arc2);
-
-            VNodeEllipticalArc::Create(doc, data, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
-        }
-        break;
-        case (Tool::NodeSpline):
-        {
-            const QSharedPointer<VAbstractCubicBezier> spline =
-                    data->GeometricObject<VAbstractCubicBezier>(det.at(i).getId());
-
-            QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
-            VPointF p2 = VPointF(spline->GetP2());
-            VPointF p3 = VPointF(spline->GetP3());
-            QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(p1.data(), dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(&p3, dx, dy, p, angle);
-                BiasRotatePoint(p4.data(), dx, dy, p, angle);
-            }
-
-            VSpline *spl = new VSpline(*p1, p2, p3, *p4, 0, Draw::Modeling);
-            idObject = data->AddGObject(spl);
-            children.append(idObject);
-
-            VSpline *spl1 = new VSpline(*spl);
-            spl1->setMode(Draw::Modeling);
-            id = data->AddGObject(spl1);
-            VNodeSpline::Create(doc, data, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
-        }
-        break;
-        case (Tool::NodeSplinePath):
-        {
-            VSplinePath *path = new VSplinePath();
-            path->setMode(Draw::Modeling);
-            const QSharedPointer<VAbstractCubicBezierPath> splinePath =
-                    data->GeometricObject<VAbstractCubicBezierPath>(det.at(i).getId());
-            for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
-            {
-                const VSpline spline = splinePath->GetSpline(i);
-
-                VPointF *p1 = new VPointF(spline.GetP1());
-                VPointF p2 = VPointF(spline.GetP2());
-                VPointF p3 = VPointF(spline.GetP3());
-                VPointF *p4 = new VPointF(spline.GetP4());
-                if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+                const QDomElement element = detList.at(j).toElement();
+                if (not element.isNull()
+                        && element.tagName() == VAbstractPattern::TagNodes
+                        && j+1 == piece)
                 {
-                    const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                    BiasRotatePoint(p1, dx, dy, p, angle);
-                    BiasRotatePoint(&p2, dx, dy, p, angle);
-                    BiasRotatePoint(&p3, dx, dy, p, angle);
-                    BiasRotatePoint(p4, dx, dy, p, angle);
-                }
-
-                VSpline spl = VSpline(*p1, p2, p3, *p4);
-                if (i==1)
-                {
-                    const qreal angle1 = spl.GetStartAngle()+180;
-                    const QString angle1F = QString().number(angle1);
-
-                    path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
-                                              0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
-                }
-
-                const qreal angle2 = spl.GetEndAngle()+180;
-                const QString angle2F = QString().number(angle2);
-                qreal pL2 = 0;
-                QString pL2F("0");
-                if (i+1 <= splinePath->CountSubSpl())
-                {
-                    const VSpline nextSpline = splinePath->GetSpline(i+1);
-                    pL2 = nextSpline.GetC1Length();
-                    pL2F = nextSpline.GetC1LengthFormula();
-                }
-
-                path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
-                                          spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
-
-                delete p4;
-                delete p1;
-            }
-            idObject = data->AddGObject(path);
-            children.append(idObject);
-
-            VSplinePath *path1 = new VSplinePath(*path);
-            path1->setMode(Draw::Modeling);
-            id = data->AddGObject(path1);
-            VNodeSplinePath::Create(doc, data, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
-        }
-        break;
-        default:
-            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-            break;
-    }
-    newDetail.append(VNodeDetail(id, det.at(i).getTypeTool(), NodeDetail::Contour, 0, 0, det.at(i).getReverse()));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UpdatePoints update data for united details.
- * @param data container with variables.
- * @param det detail what we union.
- * @param i index node in detail.
- * @param children list ids of all children.
- * @param dx bias node x axis.
- * @param dy bias node y axis.
- * @param pRotate point rotation.
- * @param angle angle rotation.
- */
-void VToolUnionDetails::UpdatePoints(VContainer *data, const VDetail &det, const int &i,
-                                     QVector<quint32> &children, const qreal &dx, const qreal &dy,
-                                     const quint32 &pRotate,
-                                     const qreal &angle)
-{
-    switch (det.at(i).getTypeTool())
-    {
-        case (Tool::NodePoint):
-        {
-            VPointF *point = new VPointF(*data->GeometricObject<VPointF>(det.at(i).getId()));
-            point->setMode(Draw::Modeling);
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                BiasRotatePoint(point, dx, dy, *data->GeometricObject<VPointF>(pRotate), angle);
-            }
-            data->UpdateGObject(TakeNextId(children), point);
-        }
-        break;
-        case (Tool::NodeArc):
-        {
-            const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(det.at(i).getId());
-            VPointF p1 = VPointF(arc->GetP1());
-            VPointF p2 = VPointF(arc->GetP2());
-            QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(&p1, dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(center.data(), dx, dy, p, angle);
-            }
-
-            QLineF l1(*center, p1);
-            QLineF l2(*center, p2);
-
-            VArc *arc1 = new VArc(*center, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
-                                  QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle()));
-            arc1->setMode(Draw::Modeling);
-            data->UpdateGObject(TakeNextId(children), arc1);
-        }
-        break;
-        case (Tool::NodeElArc):
-        {
-            const QSharedPointer<VEllipticalArc> arc = data->GeometricObject<VEllipticalArc>(det.at(i).getId());
-            VPointF p1 = VPointF(arc->GetP1());
-            VPointF p2 = VPointF(arc->GetP2());
-            QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(&p1, dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(center.data(), dx, dy, p, angle);
-            }
-
-            QLineF l1(*center, p1);
-            QLineF l2(*center, p2);
-
-            VEllipticalArc *arc1 = new VEllipticalArc (*center, arc->GetRadius1(), arc->GetRadius2(),
-                                                       arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
-                                                       l1.angle(), QString().setNum(l1.angle()), l2.angle(),
-                                                       QString().setNum(l2.angle()), 0, "0");
-            arc1->setMode(Draw::Modeling);
-            data->UpdateGObject(TakeNextId(children), arc1);
-        }
-        break;
-        case (Tool::NodeSpline):
-        {
-            const QSharedPointer<VAbstractCubicBezier> spline =
-                    data->GeometricObject<VAbstractCubicBezier>(det.at(i).getId());
-
-            QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
-            VPointF p2 = VPointF(spline->GetP2());
-            VPointF p3 = VPointF(spline->GetP3());
-            QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
-
-            if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-            {
-                const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                BiasRotatePoint(p1.data(), dx, dy, p, angle);
-                BiasRotatePoint(&p2, dx, dy, p, angle);
-                BiasRotatePoint(&p3, dx, dy, p, angle);
-                BiasRotatePoint(p4.data(), dx, dy, p, angle);
-            }
-
-            VSpline *spl = new VSpline(*p1, p2, p3, *p4, 0, Draw::Modeling);
-            data->UpdateGObject(TakeNextId(children), spl);
-        }
-        break;
-        case (Tool::NodeSplinePath):
-        {
-            VSplinePath *path = new VSplinePath();
-            path->setMode(Draw::Modeling);
-            const QSharedPointer<VAbstractCubicBezierPath> splinePath =
-                    data->GeometricObject<VAbstractCubicBezierPath>(det.at(i).getId());
-            SCASSERT(splinePath != nullptr)
-            for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
-            {
-                const VSpline spline = splinePath->GetSpline(i);
-
-                QScopedPointer<VPointF> p1(new VPointF(spline.GetP1()));
-                VPointF p2 = VPointF(spline.GetP2());
-                VPointF p3 = VPointF(spline.GetP3());
-                QScopedPointer<VPointF> p4(new VPointF(spline.GetP4()));
-
-                if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
-                {
-                    const QPointF p = *data->GeometricObject<VPointF>(pRotate);
-
-                    BiasRotatePoint(p1.data(), dx, dy, p, angle);
-                    BiasRotatePoint(&p2, dx, dy, p, angle);
-                    BiasRotatePoint(&p3, dx, dy, p, angle);
-                    BiasRotatePoint(p4.data(), dx, dy, p, angle);
-                }
-
-                VSpline spl = VSpline(*p1, p2, p3, *p4);
-                if (i==1)
-                {
-                    const qreal angle1 = spl.GetStartAngle()+180;
-                    const QString angle1F = QString().number(angle1);
-
-                    path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
-                                              0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
-                }
-
-                const qreal angle2 = spl.GetEndAngle()+180;
-                const QString angle2F = QString().number(angle2);
-
-                qreal pL2 = 0;
-                QString pL2F("0");
-                if (i+1 <= splinePath->CountSubSpl())
-                {
-                    const VSpline nextSpline = splinePath->GetSpline(i+1);
-                    pL2 = nextSpline.GetC1Length();
-                    pL2F = nextSpline.GetC1LengthFormula();
-                }
-
-                path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
-                                          spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
-            }
-            data->UpdateGObject(TakeNextId(children), path);
-        }
-        break;
-        default:
-            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-            break;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief BiasRotatePoint bias and rotate point.
- * @param point point.
- * @param dx bias x axis.
- * @param dy bias y axis.
- * @param pRotate point rotation.
- * @param angle angle rotation.
- */
-void VToolUnionDetails::BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate,
-                                        const qreal &angle)
-{
-    point->setX(point->x()+dx);
-    point->setY(point->y()+dy);
-    QLineF line(pRotate, *point);
-    line.setAngle(line.angle()+angle);
-    point->setX(line.p2().x());
-    point->setY(line.p2().y());
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QString VToolUnionDetails::getTagName() const
-{
-    return VAbstractPattern::TagTools;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::ShowVisualization(bool show)
-{
-    Q_UNUSED(show)
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::incrementReferens()
-{
-    ++_referens;
-    if (_referens == 1)
-    {
-        IncrementReferences(d1);
-        IncrementReferences(d2);
-
-        QDomElement domElement = doc->elementById(id);
-        if (domElement.isElement())
-        {
-            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::InUse);
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::decrementReferens()
-{
-    if (_referens > 0)
-    {
-        --_referens;
-    }
-    if (_referens == 0)
-    {
-        DecrementReferences(d1);
-        DecrementReferences(d2);
-
-        QDomElement domElement = doc->elementById(id);
-        if (domElement.isElement())
-        {
-            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::NotInUse);
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::GroupVisibility(quint32 object, bool visible)
-{
-    Q_UNUSED(object)
-    Q_UNUSED(visible)
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Create help create tool from GUI.
- * @param dialog dialog.
- * @param doc dom document container.
- * @param data container with variables.
- */
-VToolUnionDetails* VToolUnionDetails::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
-                                             VContainer *data)
-{
-    SCASSERT(dialog != nullptr)
-    DialogUnionDetails *dialogTool = qobject_cast<DialogUnionDetails*>(dialog);
-    SCASSERT(dialogTool != nullptr)
-    VDetail d1 = data->GetDetail(dialogTool->getD1());
-    VDetail d2 = data->GetDetail(dialogTool->getD2());
-    quint32 indexD1 = static_cast<quint32>(dialogTool->getIndexD1());
-    quint32 indexD2 = static_cast<quint32>(dialogTool->getIndexD2());
-    const bool retainPieces = dialogTool->RetainPieces();
-    qApp->getUndoStack()->beginMacro(tr("union details"));
-    VToolUnionDetails* tool = Create(0, d1, d2, dialogTool->getD1(), dialogTool->getD2(), indexD1, indexD2, scene,
-                                     doc, data, Document::FullParse, Source::FromGui, retainPieces);
-    qApp->getUndoStack()->endMacro();
-    return tool;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Create help create tool.
- * @param _id tool id, 0 if tool doesn't exist yet.
- * @param d1 first detail.
- * @param d2 second detail.
- * @param d1id id first detail.
- * @param d2id id second detail.
- * @param indexD1 index edge in first detail.
- * @param indexD2 index edge in second detail.
- * @param scene pointer to scene.
- * @param doc dom document container.
- * @param data container with variables.
- * @param parse parser file mode.
- * @param typeCreation way we create this tool.
- */
-VToolUnionDetails* VToolUnionDetails::Create(const quint32 _id, const VDetail &d1, const VDetail &d2,
-                                             const quint32 &d1id, const quint32 &d2id, const quint32 &indexD1,
-                                             const quint32 &indexD2, VMainGraphicsScene *scene, VAbstractPattern *doc,
-                                             VContainer *data, const Document &parse, const Source &typeCreation,
-                                             bool retainPieces)
-{
-    VToolUnionDetails *unionDetails = nullptr;
-    quint32 id = _id;
-    QString drawName;
-    if (typeCreation == Source::FromGui)
-    {
-        id = data->getNextId();
-        drawName = DrawName(doc, d1id, d2id);
-        SCASSERT(not drawName.isEmpty())
-    }
-    else
-    {
-        if (parse != Document::FullParse)
-        {
-            doc->UpdateToolData(id, data);
-        }
-    }
-
-    //First add tool to file
-    VAbstractTool::AddRecord(id, Tool::UnionDetails, doc);
-    if (parse == Document::FullParse)
-    {
-        //Scene doesn't show this tool, so doc will destroy this object.
-        unionDetails = new VToolUnionDetails(doc, data, id, d1, d2, indexD1, indexD2, typeCreation, drawName, doc);
-        doc->AddTool(id, unionDetails);
-        // Unfortunatelly doc will destroy all objects only in the end, but we should delete them before each FullParse
-        doc->AddToolOnRemove(unionDetails);
-    }
-    //Then create new details
-    VNodeDetail det1p1;
-    VNodeDetail det1p2;
-    d1.NodeOnEdge(indexD1, det1p1, det1p2);
-    Q_UNUSED(det1p2)
-
-    VPointF point1;
-    VPointF point2;
-    PointsOnEdge(d1, indexD1, point1, point2, data);
-
-    VPointF point3;
-    VPointF point4;
-    PointsOnEdge(d2, indexD2, point3, point4, data);
-
-    const qreal dx = point1.x() - point4.x();
-    const qreal dy = point1.y() - point4.y();
-
-    point3.setX(point3.x()+dx);
-    point3.setY(point3.y()+dy);
-
-    point4.setX(point4.x()+dx);
-    point4.setY(point4.y()+dy);
-
-    const QLineF p4p3 = QLineF(point4, point3);
-    const QLineF p1p2 = QLineF(point1, point2);
-
-    const qreal angle = p4p3.angleTo(p1p2);
-    qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
-
-    const qint32 countNodeD1 = d1.RemoveEdge(indexD1).CountNode();
-    const qint32 countNodeD2 = d2.RemoveEdge(indexD2).CountNode();
-
-    if (typeCreation == Source::FromGui)
-    {
-        qint32 i = 0;
-        VDetail newDetail;
-        QVector<quint32> children;
-        do
-        {
-            AddToNewDetail(scene, doc, data, newDetail, d1.RemoveEdge(indexD1), i, id, children, drawName);
-            ++i;
-            if (i > d1.indexOfNode(det1p1.getId()) && pointsD2 < countNodeD2-1)
-            {
-                qint32 j = 0;
-                FindIndexJ(pointsD2, d2, indexD2, j);
-                do
-                {
-                    if (j >= countNodeD2)
-                    {
-                        j=0;
-                    }
-                    AddToNewDetail(scene, doc, data, newDetail, d2.RemoveEdge(indexD2), j, id, children, drawName,
-                                   dx, dy, det1p1.getId(), angle);
-                    ++pointsD2;
-                    ++j;
-                } while (pointsD2 < countNodeD2-1);
-            }
-        } while (i < countNodeD1);
-
-        newDetail.setName(tr("United detail"));
-        newDetail.setWidth(d1.getWidth());
-        newDetail.setMx(d1.getMx());
-        newDetail.setMy(d1.getMy());
-        VToolDetail::Create(0, newDetail, scene, doc, data, parse, Source::FromTool, drawName);
-
-        auto RemoveDetail = [doc](quint32 id)
-        {
-            VToolDetail *toolDet = qobject_cast<VToolDetail*>(doc->getTool(id));
-            SCASSERT(toolDet != nullptr);
-            bool ask = false;
-            toolDet->Remove(ask);
-        };
-
-        if (not retainPieces)
-        {
-            RemoveDetail(d1id);
-            RemoveDetail(d2id);
-        }
-
-        SCASSERT(not children.isEmpty())
-        SaveChildren(doc, id, children);
-    }
-    else
-    {
-        QVector<quint32> children = AllChildren(doc, id);
-        if (not children.isEmpty())
-        {
-            // This check need for backward compatibility
-            // Remove check and "else" part if min version is 0.3.2
-            Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
-                              "Time to refactor the code.");
-            if (children.size() == countNodeD1 + countNodeD2-1)
-            {
-                qint32 i = 0;
-                do
-                {
-                    UpdatePoints(data, d1.RemoveEdge(indexD1), i, children);
-                    ++i;
-                    if (i > d1.indexOfNode(det1p1.getId()) && pointsD2 < countNodeD2-1)
-                    {
-                        VDetail d2REdge = d2.RemoveEdge(indexD2);
-                        qint32 j = 0;
-                        FindIndexJ(pointsD2, d2, indexD2, j);
-                        do
-                        {
-                            if (j >= countNodeD2)
-                            {
-                                j=0;
-                            }
-                            UpdatePoints(data, d2REdge, j, children, dx, dy, det1p1.getId(), angle);
-                            ++pointsD2;
-                            ++j;
-                        } while (pointsD2 < countNodeD2-1);
-                    }
-                } while (i<countNodeD1);
-            }
-            else // remove if min version is 0.3.2
-            {
-                qint32 i = 0;
-                do
-                {
-                    ++i;
-                    if (i > d1.indexOfNode(det1p1.getId()))
-                    {
-                        const int childrenCount = children.size();
-                        VDetail d2REdge = d2.RemoveEdge(indexD2);
-                        qint32 j = 0;
-                        FindIndexJ(pointsD2, d2, indexD2, j);
-                        do
-                        {
-                            if (j >= countNodeD2)
-                            {
-                                j=0;
-                            }
-                            UpdatePoints(data, d2REdge, j, children, dx, dy, det1p1.getId(), angle);
-                            ++pointsD2;
-                            ++j;
-                        } while (pointsD2 < childrenCount);
-                        break;
-                    }
-                } while (i<countNodeD1);
-            }
-        }
-    }
-    return unionDetails;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::PointsOnEdge(const VDetail &d, const quint32 &index, VPointF &p1, VPointF &p2, VContainer *data)
-{
-    VNodeDetail det2p1;
-    VNodeDetail det2p2;
-    d.NodeOnEdge(index, det2p1, det2p2);
-    p1 = VPointF(*data->GeometricObject<VPointF>(det2p1.getId()));
-    p2 = VPointF(*data->GeometricObject<VPointF>(det2p2.getId()));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::FindIndexJ(const qint32 &pointsD2, const VDetail &d2, const quint32 &indexD2, qint32 &j)
-{
-    if (pointsD2 == 0)
-    {
-        VNodeDetail node1;
-        VNodeDetail node2;
-        d2.NodeOnEdge(indexD2, node1, node2);
-        const VDetail removedD2 = d2.RemoveEdge(indexD2);
-        const int k = removedD2.indexOfNode(node2.getId());
-        SCASSERT(k != -1)
-        if (k == removedD2.CountNode()-1)
-        {//We have last node in detail, we wil begin from 0
-            j = 0;
-        }
-        else
-        {// Continue from next node
-            j = k+1;
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief GetDetailFromFile parse detail from file.
- * @param doc dom document container.
- * @param domElement tag in xml tree.
- * @return detail stored in file.
- */
-QVector<VDetail> VToolUnionDetails::GetDetailFromFile(VAbstractPattern *doc, const QDomElement &domElement)
-{
-    QVector<VDetail> vector;
-    QDomNodeList detailList = domElement.childNodes();
-    qint32 num = detailList.size();
-    for (qint32 i = 0; i < num; ++i)
-    {
-        QDomElement element = detailList.at(i).toElement();
-        if (element.isNull() == false)
-        {
-            if (element.tagName() == VToolUnionDetails::TagDetail)
-            {
-                VDetail d;
-                QDomNodeList nodeList = element.childNodes();
-                qint32 num = nodeList.size();
-                for (qint32 j = 0; j < num; ++j)
-                {
-                    QDomElement element = nodeList.at(j).toElement();
-                    if (element.isNull() == false)
-                    {
-                        if (element.tagName() == VToolUnionDetails::TagNode)
-                        {
-                            quint32 id = doc->GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
-                            qreal mx = qApp->toPixel(doc->GetParametrDouble(element, AttrMx, "0.0"));
-                            qreal my = qApp->toPixel(doc->GetParametrDouble(element, AttrMy, "0.0"));
-                            const bool reversed = doc->GetParametrUInt(element, VToolDetail::AttrReverse, "0");
-                            Tool tool = Tool::NodePoint;
-                            NodeDetail nodeType = NodeDetail::Contour;
-                            QString t = doc->GetParametrString(element, "type", "NodePoint");
-                            if (t == QLatin1String("NodePoint"))
-                            {
-                                tool = Tool::NodePoint;
-                            }
-                            else if (t == QLatin1String("NodeArc"))
-                            {
-                                tool = Tool::NodeArc;
-                            }
-                            else if (t == QLatin1String("NodeElArc"))
-                            {
-                                tool = Tool::NodeElArc;
-                            }
-                            else if (t == QLatin1String("NodeSpline"))
-                            {
-                                tool = Tool::NodeSpline;
-                            }
-                            else if (t == QLatin1String("NodeSplinePath"))
-                            {
-                                tool = Tool::NodeSplinePath;
-                            }
-                            d.append(VNodeDetail(id, tool, nodeType, mx, my, reversed));
-                        }
-                    }
-                }
-                vector.append(d);
-            }
-        }
-    }
-    return vector;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddToFile add tag with informations about tool into file.
- */
-void VToolUnionDetails::AddToFile()
-{
-    QDomElement domElement = doc->createElement(getTagName());
-
-    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
-    doc->SetAttribute(domElement, AttrType, ToolType);
-    doc->SetAttribute(domElement, AttrIndexD1, indexD1);
-    doc->SetAttribute(domElement, AttrIndexD2, indexD2);
-
-    AddDetail(domElement, d1);
-    AddDetail(domElement, d2);
-
-    AddToModeling(domElement);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief RefreshDataInFile refresh attributes in file. If attributes don't exist create them.
- */
-void VToolUnionDetails::RefreshDataInFile()
-{
-    QDomElement domElement = doc->elementById(id);
-    if (domElement.isElement())
-    {
-        doc->SetAttribute(domElement, AttrIndexD1, indexD1);
-        doc->SetAttribute(domElement, AttrIndexD2, indexD2);
-
-        QDomNode domNode = domElement.firstChild();
-        domNode = UpdateDetail(domNode, d1);
-        UpdateDetail(domNode, d2);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddDetail add detail to xml file.
- * @param domElement tag in xml tree.
- * @param d detail.
- */
-void VToolUnionDetails::AddDetail(QDomElement &domElement, VDetail &d)
-{
-    QDomElement det = doc->createElement(TagDetail);
-
-    for (int i = 0; i < d.CountNode(); ++i)
-    {
-        AddNode(det, d.at(i));
-    }
-
-    domElement.appendChild(det);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddNode add node to xml file.
- * @param domElement tag in xml tree.
- * @param node node.
- */
-void VToolUnionDetails::AddNode(QDomElement &domElement, const VNodeDetail &node)
-{
-    //Right now method similar to method in class VToolDetail.
-    VToolDetail::AddNode(doc, domElement, node);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UpdateDetail update detail in xml tree.
- * @param domNode dom node.
- * @param d detail.
- * @return return next detail tag in xml tree if exist.
- */
-QDomNode VToolUnionDetails::UpdateDetail(const QDomNode &domNode, const VDetail &d)
-{
-    //QDomNode domNode = domElement.firstChild();
-    while (domNode.isNull() == false)
-    {
-        if (domNode.isElement())
-        {
-            QDomElement domElement = domNode.toElement();
-            if (domElement.isNull() == false)
-            {
-                if (domElement.tagName() == VToolUnionDetails::TagDetail)
-                {
-                    VDomDocument::RemoveAllChildren(domElement);//delete all nodes in detail
-                    for (int i = 0; i < d.CountNode(); ++i)
-                    {
-                        AddNode(domElement, d.at(i));//rewrite nodes of detail
-                    }
-                    break;
+                    return VAbstractPattern::ParsePieceNodes(element);
                 }
             }
         }
     }
-    return domNode.nextSibling();
+
+    return VPiecePath();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddToModeling add tool to xml tree.
- * @param domElement tag in xml tree.
- */
-void VToolUnionDetails::AddToModeling(const QDomElement &domElement)
+VPiecePath GetPiece1MainPath(VAbstractPattern *doc, quint32 id)
 {
-    QDomElement modeling = doc->GetDraw(drawName).firstChildElement(VAbstractPattern::TagModeling);
-    if (not modeling.isNull())
-    {
-        modeling.appendChild(domElement);
-    }
-    else
-    {
-        qCDebug(vToolUnion, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagModeling));
-        return;
-    }
+    return GetPieceMainPath(1, doc, id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::IncrementReferences(const VDetail &d) const
+VPiecePath GetPiece2MainPath(VAbstractPattern *doc, quint32 id)
 {
-    for (int i = 0; i < d.CountNode(); ++i)
-    {
-        switch (d.at(i).getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                const auto point = VAbstractTool::data.GeometricObject<VPointF>(d.at(i).getId());
-                doc->IncrementReferens(point->getIdTool());
-                break;
-            }
-            case (Tool::NodeArc):
-            case (Tool::NodeElArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-                doc->IncrementReferens(d.at(i).getId());
-                break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore.";
-                break;
-        }
-    }
+    return GetPieceMainPath(2, doc, id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::DecrementReferences(const VDetail &d) const
-{
-    for (int i = 0; i < d.CountNode(); ++i)
-    {
-        switch (d.at(i).getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                const auto point = VAbstractTool::data.GeometricObject<VPointF>(d.at(i).getId());
-                doc->DecrementReferens(point->getIdTool());
-                break;
-            }
-            case (Tool::NodeArc):
-            case (Tool::NodeElArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-                doc->DecrementReferens(d.at(i).getId());
-                break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore.";
-                break;
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolUnionDetails::SaveChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
-{
-    QDomElement toolUnion = doc->elementById(id);
-    if (toolUnion.isNull())
-    {
-        return;
-    }
-
-    QDomElement tagChildren = doc->createElement(TagChildren);
-
-    for (int i=0; i<children.size(); ++i)
-    {
-        QDomElement tagChild = doc->createElement(TagChild);
-        tagChild.appendChild(doc->createTextNode(QString().setNum(children.at(i))));
-        tagChildren.appendChild(tagChild);
-    }
-
-    toolUnion.appendChild(tagChildren);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> VToolUnionDetails::AllChildren(VAbstractPattern *doc, quint32 id)
-{
-    const QDomElement toolUnion = doc->elementById(id);
-    if (toolUnion.isNull())
-    {
-        return QVector<quint32>();
-    }
-
-    const QDomElement tagChildren = toolUnion.firstChildElement(TagChildren);
-    if (tagChildren.isNull())
-    {
-        return QVector<quint32>();
-    }
-
-    QVector<quint32> childrenId;
-    const QDomNodeList listChildren = tagChildren.elementsByTagName(TagChild);
-    for (int i=0; i < listChildren.size(); ++i)
-    {
-        const QDomElement domElement = listChildren.at(i).toElement();
-        if (not domElement.isNull())
-        {
-            childrenId.append(domElement.text().toUInt());
-        }
-    }
-    return childrenId;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-quint32 VToolUnionDetails::TakeNextId(QVector<quint32> &children)
-{
-    quint32 idChild = NULL_ID;
-    if (not children.isEmpty())
-    {
-#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
-        idChild = children.takeFirst();
-#else
-        idChild = children.first();
-        children.remove(0);
-#endif
-    }
-    else
-    {
-        idChild = NULL_ID;
-    }
-    return idChild;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QString VToolUnionDetails::DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id)
+QString DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id)
 {
     const QDomElement detail1 = doc->elementById(d1id);
     if (detail1.isNull())
@@ -1191,3 +208,1063 @@ QString VToolUnionDetails::DrawName(VAbstractPattern *doc, quint32 d1id, quint32
         return draw2Name;
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief BiasRotatePoint bias and rotate point.
+ * @param point point.
+ * @param dx bias x axis.
+ * @param dy bias y axis.
+ * @param pRotate point rotation.
+ * @param angle angle rotation.
+ */
+void BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate, const qreal &angle)
+{
+    point->setX(point->x()+dx);
+    point->setY(point->y()+dy);
+    QLineF line(pRotate, *point);
+    line.setAngle(line.angle()+angle);
+    point->setX(line.p2().x());
+    point->setY(line.p2().y());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void PointsOnEdge(const VPiece &d, quint32 index, VPointF &p1, VPointF &p2, VContainer *data)
+{
+    VPieceNode det2p1;
+    VPieceNode det2p2;
+    d.GetPath().NodeOnEdge(index, det2p1, det2p2);
+    p1 = VPointF(*data->GeometricObject<VPointF>(det2p1.GetId()));
+    p2 = VPointF(*data->GeometricObject<VPointF>(det2p2.GetId()));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UnionInitParameters(const VToolUnionDetailsInitData &initData, VPieceNode &det1p1, qreal &dx, qreal &dy,
+                         qreal &angle)
+{
+    const VPiece d1 = initData.data->GetPiece(initData.d1id);
+    VPieceNode det1p2;
+    d1.GetPath().NodeOnEdge(initData.indexD1, det1p1, det1p2);
+    Q_UNUSED(det1p2)
+
+    VPointF point1;
+    VPointF point2;
+    PointsOnEdge(d1, initData.indexD1, point1, point2, initData.data);
+
+    VPointF point3;
+    VPointF point4;
+    const VPiece d2 = initData.data->GetPiece(initData.d2id);
+    PointsOnEdge(d2, initData.indexD2, point3, point4, initData.data);
+
+    dx = point1.x() - point4.x();
+    dy = point1.y() - point4.y();
+
+    point3.setX(point3.x()+dx);
+    point3.setY(point3.y()+dy);
+
+    point4.setX(point4.x()+dx);
+    point4.setY(point4.y()+dy);
+
+    const QLineF p4p3 = QLineF(point4, point3);
+    const QLineF p1p2 = QLineF(point1, point2);
+
+    angle = p4p3.angleTo(p1p2);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 AddNodePoint(const VPieceNode &node, const VToolUnionDetailsInitData &initData, quint32 idTool,
+                     QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                     quint32 pRotate, qreal angle)
+{
+    QScopedPointer<VPointF> point(new VPointF(*initData.data->GeometricObject<VPointF>(node.GetId())));
+    point->setMode(Draw::Modeling);
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        BiasRotatePoint(point.data(), dx, dy, *initData.data->GeometricObject<VPointF>(pRotate), angle);
+    }
+
+    QScopedPointer<VPointF> point1(new VPointF(*point));
+
+    const quint32 idObject = initData.data->AddGObject(point.take());
+    children.append(idObject);
+    point1->setMode(Draw::Modeling);
+    const quint32 id = initData.data->AddGObject(point1.take());
+    VNodePoint::Create(initData.doc, initData.data, initData.scene, id, idObject, Document::FullParse, Source::FromGui,
+                       drawName, idTool);
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 AddNodeArc(const VPieceNode &node, const VToolUnionDetailsInitData &initData, quint32 idTool,
+                   QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                   quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VArc> arc = initData.data->GeometricObject<VArc>(node.GetId());
+    VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
+    VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
+    QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *initData.data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(&p1, dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(center.data(), dx, dy, p, angle);
+    }
+
+    QLineF l1(*center, p1);
+    QLineF l2(*center, p2);
+    center->setMode(Draw::Modeling);
+    VPointF *tmpCenter = center.take();
+    const quint32 idCenter = initData.data->AddGObject(tmpCenter);
+    Q_UNUSED(idCenter)
+    QScopedPointer<VArc> arc1(new VArc(*tmpCenter, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
+                                       QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle())));
+    arc1->setMode(Draw::Modeling);
+
+    QScopedPointer<VArc>arc2(new VArc(*arc1));
+
+    const quint32 idObject = initData.data->AddGObject(arc1.take());
+    children.append(idObject);
+
+    arc2->setMode(Draw::Modeling);
+    const quint32 id = initData.data->AddGObject(arc2.take());
+
+    VNodeArc::Create(initData.doc, initData.data, id, idObject, Document::FullParse, Source::FromGui, drawName, idTool);
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 AddNodeElArc(const VPieceNode &node, const VToolUnionDetailsInitData &initData, quint32 idTool,
+                     QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                     quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VEllipticalArc> arc = initData.data->GeometricObject<VEllipticalArc>(node.GetId());
+    VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
+    VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
+    QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *initData.data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(&p1, dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(center.data(), dx, dy, p, angle);
+    }
+
+    QLineF l1(*center, p1);
+    QLineF l2(*center, p2);
+    center->setMode(Draw::Modeling);
+    VPointF *tmpCenter = center.take();
+    quint32 idCenter = initData.data->AddGObject(tmpCenter);
+    Q_UNUSED(idCenter)
+    QScopedPointer<VEllipticalArc> arc1(new VEllipticalArc (*tmpCenter, arc->GetRadius1(), arc->GetRadius2(),
+                                                            arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
+                                                            l1.angle(), QString().setNum(l1.angle()), l2.angle(),
+                                                            QString().setNum(l2.angle()), 0, "0"));
+    arc1->setMode(Draw::Modeling);
+
+    QScopedPointer<VEllipticalArc> arc2(new VEllipticalArc(*arc1));
+
+    const quint32 idObject = initData.data->AddGObject(arc1.take());
+    children.append(idObject);
+
+    arc2->setMode(Draw::Modeling);
+    const quint32 id = initData.data->AddGObject(arc2.take());
+
+    VNodeEllipticalArc::Create(initData.doc, initData.data, id, idObject, Document::FullParse, Source::FromGui,
+                               drawName, idTool);
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 AddNodeSpline(const VPieceNode &node, const VToolUnionDetailsInitData &initData, quint32 idTool,
+                      QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                      quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VAbstractCubicBezier> spline =
+            initData.data->GeometricObject<VAbstractCubicBezier>(node.GetId());
+
+    QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
+    VPointF p2 = VPointF(spline->GetP2());
+    VPointF p3 = VPointF(spline->GetP3());
+    QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *initData.data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(p1.data(), dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(&p3, dx, dy, p, angle);
+        BiasRotatePoint(p4.data(), dx, dy, p, angle);
+    }
+
+    VSpline *spl = new VSpline(*p1, p2, p3, *p4, 0, Draw::Modeling);
+    const quint32 idObject = initData.data->AddGObject(spl);
+    children.append(idObject);
+
+    VSpline *spl1 = new VSpline(*spl);
+    spl1->setMode(Draw::Modeling);
+    const quint32 id = initData.data->AddGObject(spl1);
+    VNodeSpline::Create(initData.doc, initData.data, id, idObject, Document::FullParse, Source::FromGui, drawName,
+                        idTool);
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 AddNodeSplinePath(const VPieceNode &node, const VToolUnionDetailsInitData &initData, quint32 idTool,
+                          QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                          quint32 pRotate, qreal angle)
+{
+    QScopedPointer<VSplinePath> path(new VSplinePath());
+    path->setMode(Draw::Modeling);
+    const QSharedPointer<VAbstractCubicBezierPath> splinePath =
+            initData.data->GeometricObject<VAbstractCubicBezierPath>(node.GetId());
+    for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
+    {
+        const VSpline spline = splinePath->GetSpline(i);
+
+        QScopedPointer<VPointF> p1(new VPointF(spline.GetP1()));
+        VPointF p2 = VPointF(spline.GetP2());
+        VPointF p3 = VPointF(spline.GetP3());
+        QScopedPointer<VPointF> p4(new VPointF(spline.GetP4()));
+        if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+        {
+            const QPointF p = *initData.data->GeometricObject<VPointF>(pRotate);
+
+            BiasRotatePoint(p1.data(), dx, dy, p, angle);
+            BiasRotatePoint(&p2, dx, dy, p, angle);
+            BiasRotatePoint(&p3, dx, dy, p, angle);
+            BiasRotatePoint(p4.data(), dx, dy, p, angle);
+        }
+
+        VSpline spl = VSpline(*p1, p2, p3, *p4);
+        if (i==1)
+        {
+            const qreal angle1 = spl.GetStartAngle()+180;
+            const QString angle1F = QString().number(angle1);
+
+            path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
+                                      0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
+        }
+
+        const qreal angle2 = spl.GetEndAngle()+180;
+        const QString angle2F = QString().number(angle2);
+        qreal pL2 = 0;
+        QString pL2F("0");
+        if (i+1 <= splinePath->CountSubSpl())
+        {
+            const VSpline nextSpline = splinePath->GetSpline(i+1);
+            pL2 = nextSpline.GetC1Length();
+            pL2F = nextSpline.GetC1LengthFormula();
+        }
+
+        path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
+                                  spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
+    }
+    QScopedPointer<VSplinePath> path1(new VSplinePath(*path));
+
+    const quint32 idObject = initData.data->AddGObject(path.take());
+    children.append(idObject);
+
+    path1->setMode(Draw::Modeling);
+    const quint32 id = initData.data->AddGObject(path1.take());
+
+    VNodeSplinePath::Create(initData.doc, initData.data, id, idObject, Document::FullParse, Source::FromGui, drawName,
+                            idTool);
+    return id;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief AddToNewDetail create united detail adding one node per time.
+ */
+void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDetail, const VPiecePath &det, int i,
+                        quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx = 0, qreal dy = 0,
+                        quint32 pRotate = NULL_ID, qreal angle = 0);
+
+void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDetail, const VPiecePath &det, int i,
+                        quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                        quint32 pRotate, qreal angle)
+{
+    const VPieceNode &node = det.at(i);
+    quint32 id = 0;
+    switch (node.GetTypeTool())
+    {
+        case (Tool::NodePoint):
+            id = AddNodePoint(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeArc):
+            id = AddNodeArc(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeElArc):
+            id = AddNodeElArc(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeSpline):
+            id = AddNodeSplinePath(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeSplinePath):
+            id = AddNodeSplinePath(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            break;
+        default:
+            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+            break;
+    }
+    newDetail.GetPath().Append(VPieceNode(id, node.GetTypeTool(), node.GetReverse()));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void FindIndexJ(qint32 pointsD2, const VPiecePath &d2Path, quint32 indexD2, qint32 &j)
+{
+    if (pointsD2 == 0)
+    {
+        VPieceNode node1;
+        VPieceNode node2;
+        d2Path.NodeOnEdge(indexD2, node1, node2);
+        const VPiecePath removedD2 = d2Path.RemoveEdge(indexD2);
+        const int k = removedD2.indexOfNode(node2.GetId());
+        SCASSERT(k != -1)
+        if (k == removedD2.CountNodes()-1)
+        {//We have last node in detail, we wil begin from 0
+            j = 0;
+        }
+        else
+        {// Continue from next node
+            j = k+1;
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SaveNodesChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
+{
+    QDomElement toolUnion = doc->elementById(id);
+    if (toolUnion.isNull())
+    {
+        return;
+    }
+
+    QDomElement tagChildren = doc->createElement(VToolUnionDetails::TagChildren);
+    QDomElement tagNodes = doc->createElement(VAbstractPattern::TagNodes);
+
+    for (int i=0; i<children.size(); ++i)
+    {
+        QDomElement tagChild = doc->createElement(VToolUnionDetails::TagChild);
+        tagChild.appendChild(doc->createTextNode(QString().setNum(children.at(i))));
+        tagNodes.appendChild(tagChild);
+    }
+
+    tagChildren.appendChild(tagNodes);
+    toolUnion.appendChild(tagChildren);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetNodesChildren(VAbstractPattern *doc, quint32 id)
+{
+    const QDomElement toolUnion = doc->elementById(id);
+    if (toolUnion.isNull())
+    {
+        return QVector<quint32>();
+    }
+
+    const QDomElement tagChildren = toolUnion.firstChildElement(VToolUnionDetails::TagChildren);
+    if (tagChildren.isNull())
+    {
+        return QVector<quint32>();
+    }
+
+    const QDomElement tagNodes = tagChildren.firstChildElement(VAbstractPattern::TagNodes);
+    if (tagNodes.isNull())
+    {
+        return QVector<quint32>();
+    }
+
+    QVector<quint32> childrenId;
+    const QDomNodeList listChildren = tagNodes.elementsByTagName(VToolUnionDetails::TagChild);
+    for (int i=0; i < listChildren.size(); ++i)
+    {
+        const QDomElement domElement = listChildren.at(i).toElement();
+        if (not domElement.isNull())
+        {
+            childrenId.append(domElement.text().toUInt());
+        }
+    }
+    return childrenId;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 TakeNextId(QVector<quint32> &children)
+{
+    quint32 idChild = NULL_ID;
+    if (not children.isEmpty())
+    {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+        idChild = children.takeFirst();
+#else
+        idChild = children.first();
+        children.remove(0);
+#endif
+    }
+    else
+    {
+        idChild = NULL_ID;
+    }
+    return idChild;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateNodePoint(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
+                     quint32 pRotate, qreal angle)
+{
+    QScopedPointer<VPointF> point(new VPointF(*data->GeometricObject<VPointF>(node.GetId())));
+    point->setMode(Draw::Modeling);
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        BiasRotatePoint(point.data(), dx, dy, *data->GeometricObject<VPointF>(pRotate), angle);
+    }
+    data->UpdateGObject(TakeNextId(children), point.take());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateNodeArc(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
+                   quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(node.GetId());
+    VPointF p1 = VPointF(arc->GetP1());
+    VPointF p2 = VPointF(arc->GetP2());
+    QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(&p1, dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(center.data(), dx, dy, p, angle);
+    }
+
+    QLineF l1(*center, p1);
+    QLineF l2(*center, p2);
+
+    QScopedPointer<VArc> arc1(new VArc(*center, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
+                                       QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle())));
+    arc1->setMode(Draw::Modeling);
+    data->UpdateGObject(TakeNextId(children), arc1.take());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateNodeElArc(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
+                     quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VEllipticalArc> arc = data->GeometricObject<VEllipticalArc>(node.GetId());
+    VPointF p1 = VPointF(arc->GetP1());
+    VPointF p2 = VPointF(arc->GetP2());
+    QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(&p1, dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(center.data(), dx, dy, p, angle);
+    }
+
+    QLineF l1(*center, p1);
+    QLineF l2(*center, p2);
+
+    QScopedPointer<VEllipticalArc> arc1(new VEllipticalArc (*center, arc->GetRadius1(), arc->GetRadius2(),
+                                                            arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
+                                                            l1.angle(), QString().setNum(l1.angle()), l2.angle(),
+                                                            QString().setNum(l2.angle()), 0, "0"));
+    arc1->setMode(Draw::Modeling);
+    data->UpdateGObject(TakeNextId(children), arc1.take());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateNodeSpline(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
+                      quint32 pRotate, qreal angle)
+{
+    const QSharedPointer<VAbstractCubicBezier> spline =
+            data->GeometricObject<VAbstractCubicBezier>(node.GetId());
+
+    QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
+    VPointF p2 = VPointF(spline->GetP2());
+    VPointF p3 = VPointF(spline->GetP3());
+    QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
+
+    if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+    {
+        const QPointF p = *data->GeometricObject<VPointF>(pRotate);
+
+        BiasRotatePoint(p1.data(), dx, dy, p, angle);
+        BiasRotatePoint(&p2, dx, dy, p, angle);
+        BiasRotatePoint(&p3, dx, dy, p, angle);
+        BiasRotatePoint(p4.data(), dx, dy, p, angle);
+    }
+
+    QScopedPointer<VSpline> spl(new VSpline(*p1, p2, p3, *p4, 0, Draw::Modeling));
+    data->UpdateGObject(TakeNextId(children), spl.take());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateNodeSplinePath(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
+                          quint32 pRotate, qreal angle)
+{
+    QScopedPointer<VSplinePath> path(new VSplinePath());
+    path->setMode(Draw::Modeling);
+    const QSharedPointer<VAbstractCubicBezierPath> splinePath =
+            data->GeometricObject<VAbstractCubicBezierPath>(node.GetId());
+    SCASSERT(splinePath != nullptr)
+    for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
+    {
+        const VSpline spline = splinePath->GetSpline(i);
+
+        QScopedPointer<VPointF> p1(new VPointF(spline.GetP1()));
+        VPointF p2 = VPointF(spline.GetP2());
+        VPointF p3 = VPointF(spline.GetP3());
+        QScopedPointer<VPointF> p4(new VPointF(spline.GetP4()));
+
+        if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
+        {
+            const QPointF p = *data->GeometricObject<VPointF>(pRotate);
+
+            BiasRotatePoint(p1.data(), dx, dy, p, angle);
+            BiasRotatePoint(&p2, dx, dy, p, angle);
+            BiasRotatePoint(&p3, dx, dy, p, angle);
+            BiasRotatePoint(p4.data(), dx, dy, p, angle);
+        }
+
+        VSpline spl = VSpline(*p1, p2, p3, *p4);
+        if (i==1)
+        {
+            const qreal angle1 = spl.GetStartAngle()+180;
+            const QString angle1F = QString().number(angle1);
+
+            path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
+                                      0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
+        }
+
+        const qreal angle2 = spl.GetEndAngle()+180;
+        const QString angle2F = QString().number(angle2);
+
+        qreal pL2 = 0;
+        QString pL2F("0");
+        if (i+1 <= splinePath->CountSubSpl())
+        {
+            const VSpline nextSpline = splinePath->GetSpline(i+1);
+            pL2 = nextSpline.GetC1Length();
+            pL2F = nextSpline.GetC1LengthFormula();
+        }
+
+        path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
+                                  spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
+    }
+    data->UpdateGObject(TakeNextId(children), path.take());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief UpdateNodes update nodes of united detail.
+ * @param data container with variables.
+ * @param det detail's nodes.
+ * @param i index node in detail.
+ * @param children list ids of all children.
+ * @param dx bias node x axis.
+ * @param dy bias node y axis.
+ * @param pRotate point rotation.
+ * @param angle angle rotation.
+ */
+void UpdateNodes(VContainer *data, const VPiecePath &det, int i, QVector<quint32> &children,
+                 qreal dx = 0, qreal dy = 0, quint32 pRotate = NULL_ID, qreal angle = 0);
+void UpdateNodes(VContainer *data, const VPiecePath &det, int i, QVector<quint32> &children, qreal dx, qreal dy,
+                 quint32 pRotate, qreal angle)
+{
+    const VPieceNode &node = det.at(i);
+    switch (node.GetTypeTool())
+    {
+        case (Tool::NodePoint):
+            UpdateNodePoint(data, node, children, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeArc):
+            UpdateNodeArc(data, node, children, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeElArc):
+            UpdateNodeElArc(data, node, children, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeSpline):
+            UpdateNodeSpline(data, node, children, dx, dy, pRotate, angle);
+            break;
+        case (Tool::NodeSplinePath):
+            UpdateNodeSplinePath(data, node, children, dx, dy, pRotate, angle);
+            break;
+        default:
+            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+            break;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsInitData &initData,
+                        const VPieceNode &det1p1, qreal dx, qreal dy, qreal angle)
+{
+    const QString drawName = DrawName(initData.doc, initData.d1id, initData.d2id);
+    SCASSERT(not drawName.isEmpty())
+
+    const VPiece d1 = initData.data->GetPiece(initData.d1id);
+    const VPiecePath d1Path = d1.GetPath().RemoveEdge(initData.indexD1);
+
+    const VPiece d2 = initData.data->GetPiece(initData.d2id);
+    const VPiecePath d2Path = d2.GetPath().RemoveEdge(initData.indexD2);
+
+    const qint32 countNodeD1 = d1Path.CountNodes();
+    const qint32 countNodeD2 = d2Path.CountNodes();
+
+    qint32 i = 0;
+    VPiece newDetail;
+    QVector<quint32> children;
+    const int det1P1Index = d1.GetPath().indexOfNode(det1p1.GetId());
+    do
+    {
+        AddNodeToNewDetail(initData, newDetail, d1Path, i, id, children, drawName);
+        ++i;
+        if (i > det1P1Index && pointsD2 < countNodeD2-1)
+        {
+            qint32 j = 0;
+            FindIndexJ(pointsD2, d2.GetPath(), initData.indexD2, j);
+            do
+            {
+                if (j >= countNodeD2)
+                {
+                    j=0;
+                }
+                AddNodeToNewDetail(initData, newDetail, d2Path, j, id, children, drawName, dx, dy, det1p1.GetId(),
+                                   angle);
+                ++pointsD2;
+                ++j;
+            } while (pointsD2 < countNodeD2-1);
+        }
+    } while (i < countNodeD1);
+
+    SCASSERT(not children.isEmpty())
+    SaveNodesChildren(initData.doc, id, children);
+
+    newDetail.SetName(QObject::tr("United detail"));
+    newDetail.SetSAWidth(d1.GetSAWidth());
+    newDetail.SetMx(d1.GetMx());
+    newDetail.SetMy(d1.GetMy());
+    VToolSeamAllowance::Create(0, newDetail, initData.scene, initData.doc, initData.data, initData.parse,
+                               Source::FromTool, drawName);
+
+    auto RemoveDetail = [initData](quint32 id)
+    {
+        VToolSeamAllowance *toolDet = qobject_cast<VToolSeamAllowance*>(initData.doc->getTool(id));
+        SCASSERT(toolDet != nullptr);
+        bool ask = false;
+        toolDet->Remove(ask);
+    };
+
+    if (not initData.retainPieces)
+    {
+        RemoveDetail(initData.d1id);
+        RemoveDetail(initData.d2id);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsInitData &initData,
+                        const VPieceNode &det1p1, qreal dx, qreal dy, qreal angle)
+{
+    const VPiecePath d1Path = GetPiece1MainPath(initData.doc, initData.d1id);
+    const VPiecePath d1REPath = d1Path.RemoveEdge(initData.indexD1);
+
+    const VPiecePath d2Path = GetPiece2MainPath(initData.doc, initData.d2id);
+    const VPiecePath d2REPath = d2Path.RemoveEdge(initData.indexD2);
+
+    const qint32 countNodeD1 = d1REPath.CountNodes();
+    const qint32 countNodeD2 = d2REPath.CountNodes();
+
+    QVector<quint32> children = GetNodesChildren(initData.doc, id);
+    if (not children.isEmpty())
+    {
+        // This check need for backward compatibility
+        // Remove check and "else" part if min version is 0.3.2
+        Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
+                          "Time to refactor the code.");
+        if (children.size() == countNodeD1 + countNodeD2-1)
+        {
+            qint32 i = 0;
+            const int indexOfNode = d1Path.indexOfNode(det1p1.GetId());
+            do
+            {
+                UpdateNodes(initData.data, d1REPath, i, children);
+                ++i;
+                if (i > indexOfNode && pointsD2 < countNodeD2-1)
+                {
+                    qint32 j = 0;
+                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
+                    do
+                    {
+                        if (j >= countNodeD2)
+                        {
+                            j=0;
+                        }
+                        UpdateNodes(initData.data, d2REPath, j, children, dx, dy, det1p1.GetId(), angle);
+                        ++pointsD2;
+                        ++j;
+                    } while (pointsD2 < countNodeD2-1);
+                }
+            } while (i<countNodeD1);
+        }
+        else // remove if min version is 0.3.2
+        {
+            qint32 i = 0;
+            const int indexOfNode = d1Path.indexOfNode(det1p1.GetId());
+            do
+            {
+                ++i;
+                if (i > indexOfNode)
+                {
+                    const int childrenCount = children.size();
+                    qint32 j = 0;
+                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
+                    do
+                    {
+                        if (j >= countNodeD2)
+                        {
+                            j=0;
+                        }
+                        UpdateNodes(initData.data, d2REPath, j, children, dx, dy, det1p1.GetId(), angle);
+                        ++pointsD2;
+                        ++j;
+                    } while (pointsD2 < childrenCount);
+                    break;
+                }
+            } while (i<countNodeD1);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UniteDetails(quint32 id, const VToolUnionDetailsInitData &initData)
+{
+    VPieceNode det1p1;
+    qreal dx = 0;
+    qreal dy = 0;
+    qreal angle = 0;
+    UnionInitParameters(initData, det1p1, dx, dy, angle);
+
+    qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
+
+    if (initData.typeCreation == Source::FromGui)
+    {
+        CreateUnitedDetail(pointsD2, id, initData, det1p1, dx, dy, angle);
+    }
+    else
+    {
+        UpdateUnitedDetail(pointsD2, id, initData, det1p1, dx, dy, angle);
+    }
+}
+} // static functions
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief VToolUnionDetails costructor.
+ * @param id object id in container.
+ * @param initData global init data.
+ * @param parent parent object.
+ */
+VToolUnionDetails::VToolUnionDetails(quint32 id, const VToolUnionDetailsInitData &initData,
+                                     QObject *parent)
+    : VAbstractTool(initData.doc, initData.data, id, parent),
+      d1id(initData.d1id),
+      d2id(initData.d2id),
+      indexD1(initData.indexD1),
+      indexD2(initData.indexD2)
+{
+    _referens = 0;
+    ToolCreation(initData.typeCreation);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VToolUnionDetails::getTagName() const
+{
+    return VAbstractPattern::TagTools;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolUnionDetails::ShowVisualization(bool show)
+{
+    Q_UNUSED(show)
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolUnionDetails::incrementReferens()
+{
+    VDataTool::incrementReferens();
+    if (_referens == 1)
+    {
+        const QVector<quint32> objects = GetReferenceObjects();
+        for(int i = 0; i < objects.size(); ++i)
+        {
+            doc->IncrementReferens(objects.at(i));
+        }
+
+        QDomElement domElement = doc->elementById(id);
+        if (domElement.isElement())
+        {
+            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::InUse);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolUnionDetails::decrementReferens()
+{
+    VDataTool::decrementReferens();
+    if (_referens == 0)
+    {
+        const QVector<quint32> objects = GetReferenceObjects();
+        for(int i = 0; i < objects.size(); ++i)
+        {
+            doc->DecrementReferens(objects.at(i));
+        }
+
+        QDomElement domElement = doc->elementById(id);
+        if (domElement.isElement())
+        {
+            doc->SetParametrUsage(domElement, AttrInUse, NodeUsage::NotInUse);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VToolUnionDetails::GroupVisibility(quint32 object, bool visible)
+{
+    Q_UNUSED(object)
+    Q_UNUSED(visible)
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Create help create tool from GUI.
+ * @param dialog dialog.
+ * @param doc dom document container.
+ * @param data container with variables.
+ */
+VToolUnionDetails* VToolUnionDetails::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                             VContainer *data)
+{
+    SCASSERT(dialog != nullptr)
+    const DialogUnionDetails *dialogTool = qobject_cast<DialogUnionDetails*>(dialog);
+    SCASSERT(dialogTool != nullptr)
+
+    VToolUnionDetailsInitData initData;
+    initData.d1id = dialogTool->getD1();
+    initData.d2id = dialogTool->getD2();
+    initData.indexD1 = static_cast<quint32>(dialogTool->getIndexD1());
+    initData.indexD2 = static_cast<quint32>(dialogTool->getIndexD2());
+    initData.scene = scene;
+    initData.doc = doc;
+    initData.data = data;
+    initData.parse = Document::FullParse;
+    initData.typeCreation = Source::FromGui;
+    initData.retainPieces = dialogTool->RetainPieces();
+
+    qApp->getUndoStack()->beginMacro(tr("union details"));
+    VToolUnionDetails* tool = Create(0, initData);
+    qApp->getUndoStack()->endMacro();
+    return tool;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Create help create tool.
+ * @param _id tool id, 0 if tool doesn't exist yet.
+ * @param d1 first detail.
+ * @param d2 second detail.
+ * @param d1id id first detail.
+ * @param d2id id second detail.
+ * @param indexD1 index edge in first detail.
+ * @param indexD2 index edge in second detail.
+ * @param scene pointer to scene.
+ * @param doc dom document container.
+ * @param data container with variables.
+ * @param parse parser file mode.
+ * @param typeCreation way we create this tool.
+ */
+VToolUnionDetails* VToolUnionDetails::Create(const quint32 _id, const VToolUnionDetailsInitData &initData)
+{
+    VToolUnionDetails *unionDetails = nullptr;
+    quint32 id = _id;
+    if (initData.typeCreation == Source::FromGui)
+    {
+        id = initData.data->getNextId();
+    }
+    else
+    {
+        if (initData.parse != Document::FullParse)
+        {
+            initData.doc->UpdateToolData(id, initData.data);
+        }
+    }
+
+    //First add tool to file
+    VAbstractTool::AddRecord(id, Tool::UnionDetails, initData.doc);
+    if (initData.parse == Document::FullParse)
+    {
+        //Scene doesn't show this tool, so doc will destroy this object.
+        unionDetails = new VToolUnionDetails(id, initData);
+        initData.doc->AddTool(id, unionDetails);
+        // Unfortunatelly doc will destroy all objects only in the end, but we should delete them before each FullParse
+        initData.doc->AddToolOnRemove(unionDetails);
+    }
+    UniteDetails(id, initData);
+    return unionDetails;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief AddToFile add tag with informations about tool into file.
+ */
+void VToolUnionDetails::AddToFile()
+{
+    QDomElement domElement = doc->createElement(getTagName());
+
+    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
+    doc->SetAttribute(domElement, AttrType, ToolType);
+    doc->SetAttribute(domElement, AttrIndexD1, indexD1);
+    doc->SetAttribute(domElement, AttrIndexD2, indexD2);
+
+    AddDetail(domElement, data.GetPiece(d1id));
+    AddDetail(domElement, data.GetPiece(d2id));
+
+    AddToModeling(domElement);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief RefreshDataInFile refresh attributes in file. If attributes don't exist create them.
+ */
+void VToolUnionDetails::RefreshDataInFile()
+{
+    // do nothing
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief AddDetail add detail to xml file.
+ * @param domElement tag in xml tree.
+ * @param d detail.
+ */
+void VToolUnionDetails::AddDetail(QDomElement &domElement, const VPiece &d) const
+{
+    QDomElement det = doc->createElement(TagDetail);
+
+    // nodes
+    VToolSeamAllowance::AddNodes(doc, det, d);
+    //custom seam allowance
+    VToolSeamAllowance::AddCSARecords(doc, det, d.GetCustomSARecords());
+    VToolSeamAllowance::AddInternalPaths(doc, det, d.GetInternalPaths());
+
+    domElement.appendChild(det);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief AddToModeling add tool to xml tree.
+ * @param domElement tag in xml tree.
+ */
+void VToolUnionDetails::AddToModeling(const QDomElement &domElement)
+{
+    const QString drawName = DrawName(doc, d1id, d2id);
+    SCASSERT(not drawName.isEmpty())
+
+    QDomElement modeling = doc->GetDraw(drawName).firstChildElement(VAbstractPattern::TagModeling);
+    if (not modeling.isNull())
+    {
+        modeling.appendChild(domElement);
+    }
+    else
+    {
+        qCCritical(vToolUnion, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagModeling));
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VToolUnionDetails::GetReferenceObjects() const
+{
+    QVector<quint32> list;
+    const QDomElement tool = doc->elementById(id);
+    if (tool.isNull())
+    {
+        return list;
+    }
+
+    const QStringList parts = QStringList() << VAbstractPattern::TagNodes     /*0*/
+                                            << VToolSeamAllowance::TagCSA     /*1*/
+                                            << VToolSeamAllowance::TagIPaths; /*2*/
+
+    const QDomNodeList nodesList = tool.childNodes();
+    for (qint32 i = 0; i < nodesList.size(); ++i)
+    {
+        const QDomElement element = nodesList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        {
+            const QDomNodeList detList = element.childNodes();
+            for (qint32 j = 0; j < detList.size(); ++j)
+            {
+                const QDomElement element = detList.at(j).toElement();
+                if (not element.isNull())
+                {
+                    switch (parts.indexOf(element.tagName()))
+                    {
+                        case 0://VAbstractPattern::TagNodes
+                            list += NodesReferenceObjects(element);
+                            break;
+                        case 1://VToolSeamAllowance::TagCSA
+                        case 2://VToolSeamAllowance::TagIPaths
+                        {
+                            const quint32 id = doc->GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
+                            if (id > NULL_ID)
+                            {
+                                list.append(id);
+                            }
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+    }
+    return list;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VToolUnionDetails::NodesReferenceObjects(const QDomElement &nodes) const
+{
+    QVector<quint32> list;
+
+    const QDomNodeList nodeList = nodes.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagNode)
+        {
+            const quint32 id = doc->GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
+            if (id > NULL_ID)
+            {
+                list.append(id);
+            }
+        }
+    }
+
+    return list;
+}
diff --git a/src/libs/vtools/tools/vtooluniondetails.h b/src/libs/vtools/tools/vtooluniondetails.h
index c7b44b6da..2265a0677 100644
--- a/src/libs/vtools/tools/vtooluniondetails.h
+++ b/src/libs/vtools/tools/vtooluniondetails.h
@@ -43,7 +43,7 @@
 #include "../ifc/xml/vabstractpattern.h"
 #include "../vmisc/def.h"
 #include "vabstracttool.h"
-#include "vdetail.h"
+#include "../vpatterndb/vpiece.h"
 
 class DialogTool;
 class QDomElement;
@@ -54,6 +54,33 @@ class VMainGraphicsScene;
 class VNodeDetail;
 class VPointF;
 
+struct VToolUnionDetailsInitData
+{
+    VToolUnionDetailsInitData()
+        : d1id(NULL_ID),
+          d2id(NULL_ID),
+          indexD1(NULL_ID),
+          indexD2(NULL_ID),
+          scene(nullptr),
+          doc(nullptr),
+          data(nullptr),
+          parse(Document::FullParse),
+          typeCreation(Source::FromFile),
+          retainPieces(false)
+    {}
+
+    quint32 d1id;
+    quint32 d2id;
+    quint32 indexD1;
+    quint32 indexD2;
+    VMainGraphicsScene *scene;
+    VAbstractPattern *doc;
+    VContainer *data;
+    Document parse;
+    Source typeCreation;
+    bool retainPieces;
+};
+
 /**
  * @brief The VToolUnionDetails class tool union details.
  */
@@ -67,13 +94,7 @@ public:
     virtual void setDialog() {}
     static VToolUnionDetails *Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
                                      VContainer *data);
-    static VToolUnionDetails *Create(const quint32 _id, const VDetail &d1,  const VDetail &d2, const quint32 &d1id,
-                                     const quint32 &d2id, const quint32 &indexD1, const quint32 &indexD2,
-                                     VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
-                                     const Document &parse,
-                                     const Source &typeCreation,
-                                     bool retainPieces = false);
-    static QVector<VDetail> GetDetailFromFile(VAbstractPattern *doc, const QDomElement &domElement);
+    static VToolUnionDetails *Create(const quint32 _id, const VToolUnionDetailsInitData &initData);
 
     static const QString ToolType;
     static const QString TagDetail;
@@ -105,48 +126,24 @@ protected:
     virtual void SetVisualization() Q_DECL_OVERRIDE {}
 private:
     Q_DISABLE_COPY(VToolUnionDetails)
-    /** @brief d1 first detail. */
-    VDetail      d1;
+    /** @brief d1 first detail id. */
+    quint32 d1id;
 
-    /** @brief d2 second detail. */
-    VDetail      d2;
+    /** @brief d2 second detail id. */
+    quint32 d2id;
 
     /** @brief indexD1 index edge in first detail. */
-    quint32      indexD1;
+    quint32 indexD1;
 
     /** @brief indexD2 index edge in second detail. */
-    quint32      indexD2;
+    quint32 indexD2;
 
-    QString      drawName;
+    VToolUnionDetails(quint32 id, const VToolUnionDetailsInitData &initData, QObject *parent = nullptr);
 
-    VToolUnionDetails(VAbstractPattern *doc, VContainer *data, const quint32 &id, const VDetail &d1, const VDetail &d2,
-                      const quint32 &indexD1, const quint32 &indexD2, const Source &typeCreation,
-                      const QString &drawName, QObject *parent = nullptr);
-
-    void         AddDetail(QDomElement &domElement, VDetail &d);
-    void         AddNode(QDomElement &domElement, const VNodeDetail &node);
-    QDomNode     UpdateDetail(const QDomNode &domNode, const VDetail &d);
-    void         AddToModeling(const QDomElement &domElement);
-    void         IncrementReferences(const VDetail &d) const;
-    void         DecrementReferences(const VDetail &d) const;
-
-    static void             SaveChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children);
-    static QVector<quint32> AllChildren(VAbstractPattern *doc, quint32 id);
-    static quint32          TakeNextId(QVector<quint32> &children);
-    static QString          DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id);
-    static void             PointsOnEdge(const VDetail &d, const quint32 &index, VPointF &p1, VPointF &p2,
-                                         VContainer *data);
-    static void             FindIndexJ(const qint32 &pointsD2, const VDetail &d2, const quint32 &indexD2, qint32 &j);
-    static void             AddToNewDetail(VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
-                                           VDetail &newDetail, const VDetail &det, const int &i, const quint32 &idTool,
-                                           QVector<quint32> &children, const QString &drawName, const qreal &dx = 0,
-                                           const qreal &dy = 0, const quint32 &pRotate = NULL_ID,
-                                           const qreal &angle = 0);
-    static void             UpdatePoints(VContainer *data, const VDetail &det, const int &i, QVector<quint32> &children,
-                                         const qreal &dx = 0, const qreal &dy = 0, const quint32 &pRotate = NULL_ID,
-                                         const qreal &angle = 0);
-    static void             BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate,
-                                            const qreal &angle);
+    void             AddDetail(QDomElement &domElement, const VPiece &d) const;
+    void             AddToModeling(const QDomElement &domElement);
+    QVector<quint32> GetReferenceObjects() const;
+    QVector<quint32> NodesReferenceObjects(const QDomElement &nodes) const;
 };
 
 #endif // VTOOLUNIONDETAILS_H

From 8eba46ade1387f23a0862ae00e89a41cbf2fcaa6 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 16 Jan 2017 17:37:15 +0200
Subject: [PATCH 164/208] The tool redesign was finnised. Code is not tested.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |  48 +-
 src/app/valentina/xml/vpattern.h              |   2 -
 src/libs/ifc/xml/vabstractpattern.cpp         |  48 ++
 src/libs/ifc/xml/vabstractpattern.h           |   8 +-
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  69 +--
 .../vtools/tools/nodeDetails/vtoolpiecepath.h |   2 -
 src/libs/vtools/tools/vabstracttool.cpp       |  26 +
 src/libs/vtools/tools/vabstracttool.h         |   5 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  34 +-
 src/libs/vtools/tools/vtoolseamallowance.h    |   6 -
 src/libs/vtools/tools/vtooluniondetails.cpp   | 500 ++++++++++++++----
 11 files changed, 502 insertions(+), 246 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index a8756eadc..5c1479232 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -748,10 +748,10 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                         ParsePieceGrainline(element, detail);
                         break;
                     case 4:// VToolSeamAllowance::TagCSA
-                        ParsePieceCSARecords(element, detail);
+                        detail.SetCustomSARecords(ParsePieceCSARecords(element));
                         break;
                     case 5:// VToolSeamAllowance::TagIPaths
-                        ParsePieceInternalPaths(element, detail);
+                        detail.SetInternalPaths(ParsePieceInternalPaths(element));
                     default:
                         break;
                 }
@@ -785,50 +785,6 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, b
     detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, detail.GetSAWidth(), closed));
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const
-{
-    QVector<CustomSARecord> records;
-    const QDomNodeList nodeList = domElement.childNodes();
-    for (qint32 i = 0; i < nodeList.size(); ++i)
-    {
-        const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull())
-        {
-            CustomSARecord record;
-            record.startPoint = GetParametrUInt(element, VToolSeamAllowance::AttrStart, NULL_ID_STR);
-            record.path = GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
-            record.endPoint = GetParametrUInt(element, VToolSeamAllowance::AttrEnd, NULL_ID_STR);
-            record.reverse = GetParametrBool(element, VAbstractPattern::AttrNodeReverse, falseStr);
-            record.includeType = static_cast<PiecePathIncludeType>(GetParametrUInt(element,
-                                                                                   VToolSeamAllowance::AttrIncludeAs,
-                                                                                   "1"));
-            records.append(record);
-        }
-    }
-    detail.SetCustomSARecords(records);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const
-{
-    QVector<quint32> records;
-    const QDomNodeList nodeList = domElement.childNodes();
-    for (qint32 i = 0; i < nodeList.size(); ++i)
-    {
-        const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull())
-        {
-            const quint32 path = GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
-            if (path > NULL_ID)
-            {
-                records.append(path);
-            }
-        }
-    }
-    detail.SetInternalPaths(records);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VPattern::ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const
 {
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 49da3ab46..31cff3136 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -120,8 +120,6 @@ private:
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
-    void           ParsePieceCSARecords(const QDomElement &domElement, VPiece &detail) const;
-    void           ParsePieceInternalPaths(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePiecePatternInfo(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceGrainline(const QDomElement &domElement, VPiece &detail) const;
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index 5f04dfa3e..ed68e62a0 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -109,6 +109,10 @@ const QString VAbstractPattern::AttrArrows          = QStringLiteral("arrows");
 const QString VAbstractPattern::AttrNodeReverse     = QStringLiteral("reverse");
 const QString VAbstractPattern::AttrSABefore        = QStringLiteral("before");
 const QString VAbstractPattern::AttrSAAfter         = QStringLiteral("after");
+const QString VAbstractPattern::AttrStart           = QStringLiteral("start");
+const QString VAbstractPattern::AttrPath            = QStringLiteral("path");
+const QString VAbstractPattern::AttrEnd             = QStringLiteral("end");
+const QString VAbstractPattern::AttrIncludeAs       = QStringLiteral("includeAs");
 
 const QString VAbstractPattern::AttrAll             = QStringLiteral("all");
 
@@ -575,6 +579,50 @@ VPiecePath VAbstractPattern::ParsePieceNodes(const QDomElement &domElement)
     return path;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<CustomSARecord> VAbstractPattern::ParsePieceCSARecords(const QDomElement &domElement)
+{
+    QVector<CustomSARecord> records;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull())
+        {
+            CustomSARecord record;
+            record.startPoint = GetParametrUInt(element, VAbstractPattern::AttrStart, NULL_ID_STR);
+            record.path = GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
+            record.endPoint = GetParametrUInt(element, VAbstractPattern::AttrEnd, NULL_ID_STR);
+            record.reverse = GetParametrBool(element, VAbstractPattern::AttrNodeReverse, falseStr);
+            record.includeType = static_cast<PiecePathIncludeType>(GetParametrUInt(element,
+                                                                                   VAbstractPattern::AttrIncludeAs,
+                                                                                   "1"));
+            records.append(record);
+        }
+    }
+    return records;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> VAbstractPattern::ParsePieceInternalPaths(const QDomElement &domElement)
+{
+    QVector<quint32> records;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull())
+        {
+            const quint32 path = GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
+            if (path > NULL_ID)
+            {
+                records.append(path);
+            }
+        }
+    }
+    return records;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
 {
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index a8d6052e6..83961b81e 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -95,7 +95,9 @@ public:
     static VDataTool* getTool(const quint32 &id);
     static void       AddTool(const quint32 &id, VDataTool *tool);
 
-    static VPiecePath ParsePieceNodes(const QDomElement &domElement);
+    static VPiecePath              ParsePieceNodes(const QDomElement &domElement);
+    static QVector<CustomSARecord> ParsePieceCSARecords(const QDomElement &domElement);
+    static QVector<quint32>        ParsePieceInternalPaths(const QDomElement &domElement);
 
     void           AddToolOnRemove(VDataTool *tool);
 
@@ -215,6 +217,10 @@ public:
     static const QString AttrNodeReverse;
     static const QString AttrSABefore;
     static const QString AttrSAAfter;
+    static const QString AttrStart;
+    static const QString AttrPath;
+    static const QString AttrEnd;
+    static const QString AttrIncludeAs;
 
     static const QString AttrAll;
 
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index 053748e9f..d1f806fb7 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -157,26 +157,6 @@ void VToolPiecePath::decrementReferens()
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VToolPiecePath::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
-{
-    domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolPiecePath::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path)
-{
-    if (path.CountNodes() > 0)
-    {
-        QDomElement nodesElement = doc->createElement(VAbstractPattern::TagNodes);
-        for (int i = 0; i < path.CountNodes(); ++i)
-        {
-            AddNode(doc, nodesElement, path.at(i));
-        }
-        domElement.appendChild(nodesElement);
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VToolPiecePath::AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiecePath &path)
 {
@@ -225,31 +205,34 @@ void VToolPiecePath::AddToFile()
 
     AddToModeling(domElement);
 
-    VPiece oldDet = VAbstractTool::data.GetPiece(m_pieceId);
-    VPiece newDet = oldDet;
-
-    if (path.GetType() == PiecePathType::InternalPath)
+    if (m_pieceId > NULL_ID)
     {
-        QVector<quint32> iPaths = newDet.GetInternalPaths();
-        iPaths.append(id);
-        newDet.SetInternalPaths(iPaths);
+        const VPiece oldDet = VAbstractTool::data.GetPiece(m_pieceId);
+        VPiece newDet = oldDet;
+
+        if (path.GetType() == PiecePathType::InternalPath)
+        {
+            QVector<quint32> iPaths = newDet.GetInternalPaths();
+            iPaths.append(id);
+            newDet.SetInternalPaths(iPaths);
+        }
+        else if (path.GetType() == PiecePathType::CustomSeamAllowance)
+        {
+            CustomSARecord record;
+            record.path = id;
+
+            QVector<CustomSARecord> records = newDet.GetCustomSARecords();
+            records.append(record);
+            newDet.SetCustomSARecords(records);
+        }
+
+        SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
+        qApp->getUndoStack()->push(saveCommand);// First push then make a connect
+        VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
+        connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
+
+        qApp->getUndoStack()->endMacro();
     }
-    else if (path.GetType() == PiecePathType::CustomSeamAllowance)
-    {
-        CustomSARecord record;
-        record.path = id;
-
-        QVector<CustomSARecord> records = newDet.GetCustomSARecords();
-        records.append(record);
-        newDet.SetCustomSARecords(records);
-    }
-
-    SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
-    qApp->getUndoStack()->push(saveCommand);// First push then make a connect
-    VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
-    connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-
-    qApp->getUndoStack()->endMacro();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
index edc8e2273..6360e4b3f 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
@@ -53,8 +53,6 @@ public:
     virtual void incrementReferens() Q_DECL_OVERRIDE;
     virtual void decrementReferens() Q_DECL_OVERRIDE;
 
-    static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
-    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path);
     static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiecePath &path);
 public slots:
     virtual void FullUpdateFromFile () Q_DECL_OVERRIDE;
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index ac2441d5e..ec513ae87 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -415,6 +415,26 @@ void VAbstractTool::AddRecord(const quint32 id, const Tool &toolType, VAbstractP
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractTool::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path)
+{
+    if (path.CountNodes() > 0)
+    {
+        QDomElement nodesElement = doc->createElement(VAbstractPattern::TagNodes);
+        for (int i = 0; i < path.CountNodes(); ++i)
+        {
+            AddNode(doc, nodesElement, path.at(i));
+        }
+        domElement.appendChild(nodesElement);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractTool::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
+{
+    AddNodes(doc, domElement, piece.GetPath());
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief RefreshLine refresh line to label on scene.
@@ -507,3 +527,9 @@ QDomElement VAbstractTool::AddSANode(VAbstractPattern *doc, const QString &tagNa
 
     return nod;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractTool::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
+{
+    domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
+}
diff --git a/src/libs/vtools/tools/vabstracttool.h b/src/libs/vtools/tools/vabstracttool.h
index f78c71227..9387e6df5 100644
--- a/src/libs/vtools/tools/vabstracttool.h
+++ b/src/libs/vtools/tools/vabstracttool.h
@@ -81,7 +81,9 @@ public:
     static const QStringList      Colors();
     static QMap<QString, QString> ColorsList();
 
-    static void             AddRecord(const quint32 id, const Tool &toolType, VAbstractPattern *doc);
+    static void AddRecord(const quint32 id, const Tool &toolType, VAbstractPattern *doc);
+    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path);
+    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
 
     const VContainer        *getData() const;
 
@@ -151,6 +153,7 @@ protected:
                             QGraphicsLineItem *lineName, const qreal radius);
 
     static QDomElement AddSANode(VAbstractPattern *doc, const QString &tagName, const VPieceNode &node);
+    static void        AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
 private:
     Q_DISABLE_COPY(VAbstractTool)
 };
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index a8fd22f23..ee48d5312 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -73,10 +73,6 @@ const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllow
 const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
 const QString VToolSeamAllowance::AttrHeight         = QStringLiteral("height");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
-const QString VToolSeamAllowance::AttrStart          = QStringLiteral("start");
-const QString VToolSeamAllowance::AttrPath           = QStringLiteral("path");
-const QString VToolSeamAllowance::AttrEnd            = QStringLiteral("end");
-const QString VToolSeamAllowance::AttrIncludeAs      = QStringLiteral("includeAs");
 const QString VToolSeamAllowance::AttrFont           = QStringLiteral("fontSize");
 const QString VToolSeamAllowance::AttrRotation       = QStringLiteral("rotation");
 
@@ -214,26 +210,6 @@ void VToolSeamAllowance::Remove(bool ask)
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VToolSeamAllowance::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node)
-{
-    domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolSeamAllowance::AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
-{
-    if (piece.GetPath().CountNodes() > 0)
-    {
-        QDomElement nodesElement = doc->createElement(VAbstractPattern::TagNodes);
-        for (int i = 0; i < piece.GetPath().CountNodes(); ++i)
-        {
-            AddNode(doc, nodesElement, piece.GetPath().at(i));
-        }
-        domElement.appendChild(nodesElement);
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece)
 {
@@ -256,11 +232,11 @@ void VToolSeamAllowance::AddCSARecord(VAbstractPattern *doc, QDomElement &domEle
 {
     QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord);
 
-    doc->SetAttribute(recordNode, AttrStart, record.startPoint);
-    doc->SetAttribute(recordNode, AttrPath, record.path);
-    doc->SetAttribute(recordNode, AttrEnd, record.endPoint);
+    doc->SetAttribute(recordNode, VAbstractPattern::AttrStart, record.startPoint);
+    doc->SetAttribute(recordNode, VAbstractPattern::AttrPath, record.path);
+    doc->SetAttribute(recordNode, VAbstractPattern::AttrEnd, record.endPoint);
     doc->SetAttribute(recordNode, VAbstractPattern::AttrNodeReverse, record.reverse);
-    doc->SetAttribute(recordNode, AttrIncludeAs, static_cast<unsigned int>(record.includeType));
+    doc->SetAttribute(recordNode, VAbstractPattern::AttrIncludeAs, static_cast<unsigned int>(record.includeType));
 
     domElement.appendChild(recordNode);
 }
@@ -289,7 +265,7 @@ void VToolSeamAllowance::AddInternalPaths(VAbstractPattern *doc, QDomElement &do
         for (int i = 0; i < paths.size(); ++i)
         {
             QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord);
-            doc->SetAttribute(recordNode, AttrPath, paths.at(i));
+            doc->SetAttribute(recordNode, VAbstractPattern::AttrPath, paths.at(i));
             iPathsElement.appendChild(recordNode);
         }
         domElement.appendChild(iPathsElement);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 286ec4d59..4b25acc00 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -67,17 +67,11 @@ public:
     static const QString AttrWidth;
     static const QString AttrHeight;
     static const QString AttrUnited;
-    static const QString AttrStart;
-    static const QString AttrPath;
-    static const QString AttrEnd;
-    static const QString AttrIncludeAs;
     static const QString AttrFont;
     static const QString AttrRotation;
 
     void Remove(bool ask);
 
-    static void AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
-    static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
     static void AddAttributes(VAbstractPattern *doc, QDomElement &domElement, quint32 id, const VPiece &piece);
     static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record);
     static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector<CustomSARecord> &records);
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index a7ad91eff..7a2ec2d05 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -66,6 +66,7 @@
 #include "nodeDetails/vnodepoint.h"
 #include "nodeDetails/vnodespline.h"
 #include "nodeDetails/vnodesplinepath.h"
+#include "nodeDetails/vtoolpiecepath.h"
 #include "vdatatool.h"
 #include "vnodedetail.h"
 #include "vtoolseamallowance.h"
@@ -97,7 +98,7 @@ QT_WARNING_POP
 namespace
 {
 //---------------------------------------------------------------------------------------------------------------------
-VPiecePath GetPieceMainPath(int piece, VAbstractPattern *doc, quint32 id)
+VPiecePath GetPiecePath(int piece, VAbstractPattern *doc, quint32 id)
 {
     const QDomElement tool = doc->elementById(id);
     if (tool.isNull())
@@ -116,9 +117,7 @@ VPiecePath GetPieceMainPath(int piece, VAbstractPattern *doc, quint32 id)
             for (qint32 j = 0; j < detList.size(); ++j)
             {
                 const QDomElement element = detList.at(j).toElement();
-                if (not element.isNull()
-                        && element.tagName() == VAbstractPattern::TagNodes
-                        && j+1 == piece)
+                if (not element.isNull() && element.tagName() == VAbstractPattern::TagNodes && j+1 == piece)
                 {
                     return VAbstractPattern::ParsePieceNodes(element);
                 }
@@ -132,13 +131,99 @@ VPiecePath GetPieceMainPath(int piece, VAbstractPattern *doc, quint32 id)
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath GetPiece1MainPath(VAbstractPattern *doc, quint32 id)
 {
-    return GetPieceMainPath(1, doc, id);
+    return GetPiecePath(1, doc, id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath GetPiece2MainPath(VAbstractPattern *doc, quint32 id)
 {
-    return GetPieceMainPath(2, doc, id);
+    return GetPiecePath(2, doc, id);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<CustomSARecord> GetPieceCSAList(int piece, VAbstractPattern *doc, quint32 id)
+{
+    const QDomElement tool = doc->elementById(id);
+    if (tool.isNull())
+    {
+        VException e(QString("Can't get tool by id='%1'.").arg(id));
+        throw e;
+    }
+
+    const QDomNodeList nodesList = tool.childNodes();
+    for (qint32 i = 0; i < nodesList.size(); ++i)
+    {
+        const QDomElement element = nodesList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        {
+            const QDomNodeList detList = element.childNodes();
+            for (qint32 j = 0; j < detList.size(); ++j)
+            {
+                const QDomElement element = detList.at(j).toElement();
+                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagCSA && j+1 == piece)
+                {
+                    return VAbstractPattern::ParsePieceCSARecords(element);
+                }
+            }
+        }
+    }
+
+    return QVector<CustomSARecord>();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<CustomSARecord> GetPiece1CSAPaths(VAbstractPattern *doc, quint32 id)
+{
+    return GetPieceCSAList(1, doc, id);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<CustomSARecord> GetPiece2CSAPaths(VAbstractPattern *doc, quint32 id)
+{
+    return GetPieceCSAList(2, doc, id);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetPieceInternalPathList(int piece, VAbstractPattern *doc, quint32 id)
+{
+    const QDomElement tool = doc->elementById(id);
+    if (tool.isNull())
+    {
+        VException e(QString("Can't get tool by id='%1'.").arg(id));
+        throw e;
+    }
+
+    const QDomNodeList nodesList = tool.childNodes();
+    for (qint32 i = 0; i < nodesList.size(); ++i)
+    {
+        const QDomElement element = nodesList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        {
+            const QDomNodeList detList = element.childNodes();
+            for (qint32 j = 0; j < detList.size(); ++j)
+            {
+                const QDomElement element = detList.at(j).toElement();
+                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagIPaths && j+1 == piece)
+                {
+                    return VAbstractPattern::ParsePieceInternalPaths(element);
+                }
+            }
+        }
+    }
+
+    return QVector<quint32>();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetPiece1InternalPaths(VAbstractPattern *doc, quint32 id)
+{
+    return GetPieceInternalPathList(1, doc, id);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetPiece2InternalPaths(VAbstractPattern *doc, quint32 id)
+{
+    return GetPieceInternalPathList(2, doc, id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -218,7 +303,7 @@ QString DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id)
  * @param pRotate point rotation.
  * @param angle angle rotation.
  */
-void BiasRotatePoint(VPointF *point, const qreal &dx, const qreal &dy, const QPointF &pRotate, const qreal &angle)
+void BiasRotatePoint(VPointF *point, qreal dx, qreal dy, const QPointF &pRotate, qreal angle)
 {
     point->setX(point->x()+dx);
     point->setY(point->y()+dy);
@@ -483,15 +568,14 @@ quint32 AddNodeSplinePath(const VPieceNode &node, const VToolUnionDetailsInitDat
 /**
  * @brief AddToNewDetail create united detail adding one node per time.
  */
-void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDetail, const VPiecePath &det, int i,
-                        quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx = 0, qreal dy = 0,
-                        quint32 pRotate = NULL_ID, qreal angle = 0);
+void AddNodeToNewPath(const VToolUnionDetailsInitData &initData, VPiecePath &newPath, const VPieceNode &node,
+                      quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx = 0, qreal dy = 0,
+                      quint32 pRotate = NULL_ID, qreal angle = 0);
 
-void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDetail, const VPiecePath &det, int i,
-                        quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
-                        quint32 pRotate, qreal angle)
+void AddNodeToNewPath(const VToolUnionDetailsInitData &initData, VPiecePath &newPath, const VPieceNode &node,
+                      quint32 idTool, QVector<quint32> &children, const QString &drawName, qreal dx, qreal dy,
+                      quint32 pRotate, qreal angle)
 {
-    const VPieceNode &node = det.at(i);
     quint32 id = 0;
     switch (node.GetTypeTool())
     {
@@ -505,7 +589,7 @@ void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDe
             id = AddNodeElArc(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
             break;
         case (Tool::NodeSpline):
-            id = AddNodeSplinePath(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
+            id = AddNodeSpline(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
             break;
         case (Tool::NodeSplinePath):
             id = AddNodeSplinePath(node, initData, idTool, children, drawName, dx, dy, pRotate, angle);
@@ -514,7 +598,7 @@ void AddNodeToNewDetail(const VToolUnionDetailsInitData &initData, VPiece &newDe
             qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
             break;
     }
-    newDetail.GetPath().Append(VPieceNode(id, node.GetTypeTool(), node.GetReverse()));
+    newPath.Append(VPieceNode(id, node.GetTypeTool(), node.GetReverse()));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -540,30 +624,59 @@ void FindIndexJ(qint32 pointsD2, const VPiecePath &d2Path, quint32 indexD2, qint
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void SaveNodesChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
+QDomElement GetTagChildren(VAbstractPattern *doc, quint32 id)
 {
     QDomElement toolUnion = doc->elementById(id);
     if (toolUnion.isNull())
     {
-        return;
+        VException e(QString("Can't get tool by id='%1'.").arg(id));
+        throw e;
     }
 
-    QDomElement tagChildren = doc->createElement(VToolUnionDetails::TagChildren);
-    QDomElement tagNodes = doc->createElement(VAbstractPattern::TagNodes);
+    QDomElement tagChildren = toolUnion.firstChildElement(VToolUnionDetails::TagChildren);
 
+    if (tagChildren.isNull())
+    {
+        tagChildren = doc->createElement(VToolUnionDetails::TagChildren);
+        toolUnion.appendChild(tagChildren);
+    }
+
+    return tagChildren;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SaveChildren(VAbstractPattern *doc, quint32 id, QDomElement section, const QVector<quint32> &children)
+{
     for (int i=0; i<children.size(); ++i)
     {
         QDomElement tagChild = doc->createElement(VToolUnionDetails::TagChild);
         tagChild.appendChild(doc->createTextNode(QString().setNum(children.at(i))));
-        tagNodes.appendChild(tagChild);
+        section.appendChild(tagChild);
     }
 
-    tagChildren.appendChild(tagNodes);
-    toolUnion.appendChild(tagChildren);
+    GetTagChildren(doc, id).appendChild(section);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> GetNodesChildren(VAbstractPattern *doc, quint32 id)
+void SaveNodesChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
+{
+    SaveChildren(doc, id, doc->createElement(VAbstractPattern::TagNodes), children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SaveCSAChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
+{
+    SaveChildren(doc, id, doc->createElement(VToolSeamAllowance::TagCSA), children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void SaveInternalPathsChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
+{
+    SaveChildren(doc, id, doc->createElement(VToolSeamAllowance::TagIPaths), children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetChildren(VAbstractPattern *doc, quint32 id, const QString &tagName)
 {
     const QDomElement toolUnion = doc->elementById(id);
     if (toolUnion.isNull())
@@ -577,7 +690,7 @@ QVector<quint32> GetNodesChildren(VAbstractPattern *doc, quint32 id)
         return QVector<quint32>();
     }
 
-    const QDomElement tagNodes = tagChildren.firstChildElement(VAbstractPattern::TagNodes);
+    const QDomElement tagNodes = tagChildren.firstChildElement(tagName);
     if (tagNodes.isNull())
     {
         return QVector<quint32>();
@@ -596,6 +709,24 @@ QVector<quint32> GetNodesChildren(VAbstractPattern *doc, quint32 id)
     return childrenId;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetNodesChildren(VAbstractPattern *doc, quint32 id)
+{
+    return GetChildren(doc, id, VAbstractPattern::TagNodes);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetCSAChildren(VAbstractPattern *doc, quint32 id)
+{
+    return GetChildren(doc, id, VToolSeamAllowance::TagCSA);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<quint32> GetInternalPathsChildren(VAbstractPattern *doc, quint32 id)
+{
+    return GetChildren(doc, id, VToolSeamAllowance::TagIPaths);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 TakeNextId(QVector<quint32> &children)
 {
@@ -779,12 +910,11 @@ void UpdateNodeSplinePath(VContainer *data, const VPieceNode &node, QVector<quin
  * @param pRotate point rotation.
  * @param angle angle rotation.
  */
-void UpdateNodes(VContainer *data, const VPiecePath &det, int i, QVector<quint32> &children,
+void UpdatePathNode(VContainer *data, const VPieceNode &node, QVector<quint32> &children,
                  qreal dx = 0, qreal dy = 0, quint32 pRotate = NULL_ID, qreal angle = 0);
-void UpdateNodes(VContainer *data, const VPiecePath &det, int i, QVector<quint32> &children, qreal dx, qreal dy,
+void UpdatePathNode(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
                  quint32 pRotate, qreal angle)
 {
-    const VPieceNode &node = det.at(i);
     switch (node.GetTypeTool())
     {
         case (Tool::NodePoint):
@@ -809,28 +939,23 @@ void UpdateNodes(VContainer *data, const VPiecePath &det, int i, QVector<quint32
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void CreateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsInitData &initData,
-                        const VPieceNode &det1p1, qreal dx, qreal dy, qreal angle)
+void CreateUnitedNodes(VPiece &newDetail, const VPiece &d1, const VPiece &d2, quint32 id, const QString &drawName,
+                       const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
 {
-    const QString drawName = DrawName(initData.doc, initData.d1id, initData.d2id);
-    SCASSERT(not drawName.isEmpty())
-
-    const VPiece d1 = initData.data->GetPiece(initData.d1id);
     const VPiecePath d1Path = d1.GetPath().RemoveEdge(initData.indexD1);
-
-    const VPiece d2 = initData.data->GetPiece(initData.d2id);
     const VPiecePath d2Path = d2.GetPath().RemoveEdge(initData.indexD2);
 
     const qint32 countNodeD1 = d1Path.CountNodes();
     const qint32 countNodeD2 = d2Path.CountNodes();
 
+    qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
     qint32 i = 0;
-    VPiece newDetail;
     QVector<quint32> children;
-    const int det1P1Index = d1.GetPath().indexOfNode(det1p1.GetId());
+    VPiecePath newPath;
+    const int det1P1Index = d1.GetPath().indexOfNode(pRotate);
     do
     {
-        AddNodeToNewDetail(initData, newDetail, d1Path, i, id, children, drawName);
+        AddNodeToNewPath(initData, newPath, d1Path.at(i), id, children, drawName);
         ++i;
         if (i > det1P1Index && pointsD2 < countNodeD2-1)
         {
@@ -842,16 +967,226 @@ void CreateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsIni
                 {
                     j=0;
                 }
-                AddNodeToNewDetail(initData, newDetail, d2Path, j, id, children, drawName, dx, dy, det1p1.GetId(),
-                                   angle);
+                AddNodeToNewPath(initData, newPath, d2Path.at(j), id, children, drawName, dx, dy, pRotate, angle);
                 ++pointsD2;
                 ++j;
             } while (pointsD2 < countNodeD2-1);
         }
     } while (i < countNodeD1);
 
+    newDetail.SetPath(newPath);
+
     SCASSERT(not children.isEmpty())
     SaveNodesChildren(initData.doc, id, children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedDetailCSA(VPiece &newDetail, const VPiece &d, QVector<quint32> &children, quint32 id,
+                           const QString &drawName, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
+                           quint32 pRotate, qreal angle)
+{
+    QVector<CustomSARecord> newList = newDetail.GetCustomSARecords();
+    const QVector<CustomSARecord> oldList = d.GetCustomSARecords();
+    for(int i=0; i < oldList.size(); ++i)
+    {
+        CustomSARecord record = oldList.at(i);
+        const VPiecePath path = initData.data->GetPiecePath(record.path);
+        VPiecePath newPath = path;
+        newPath.Clear();//Clear nodes
+        for (int i=0; i < path.CountNodes(); ++i)
+        {
+            AddNodeToNewPath(initData, newPath, path.at(i), id, children, drawName, dx, dy, pRotate, angle);
+        }
+        VToolPiecePath *pathTool = VToolPiecePath::Create(0, newPath, NULL_ID, initData.scene, initData.doc,
+                                                          initData.data, initData.parse, Source::FromTool, drawName,
+                                                          id);
+        record.path = pathTool->getId();
+        newList.append(record);
+    }
+    newDetail.SetCustomSARecords(newList);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedCSA(VPiece &newDetail, const VPiece &d1, const VPiece &d2, quint32 id, const QString &drawName,
+                     const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
+{
+    QVector<quint32> children;
+    CreateUnitedDetailCSA(newDetail, d1, children, id, drawName, initData, dx, dy, pRotate, angle);
+    CreateUnitedDetailCSA(newDetail, d2, children, id, drawName, initData, dx, dy, pRotate, angle);
+
+    SCASSERT(not children.isEmpty())
+    SaveCSAChildren(initData.doc, id, children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedDetailInternalPaths(VPiece &newDetail, const VPiece &d, QVector<quint32> &children, quint32 id,
+                                     const QString &drawName, const VToolUnionDetailsInitData &initData, qreal dx,
+                                     qreal dy, quint32 pRotate, qreal angle)
+{
+    QVector<quint32> newList = newDetail.GetInternalPaths();
+    const QVector<quint32> oldList = d.GetInternalPaths();
+    for(int i=0; i < oldList.size(); ++i)
+    {
+        const VPiecePath path = initData.data->GetPiecePath(oldList.at(i));
+        VPiecePath newPath = path;
+        newPath.Clear();//Clear nodes
+
+        for (int i=0; i < path.CountNodes(); ++i)
+        {
+            AddNodeToNewPath(initData, newPath, path.at(i), id, children, drawName, dx, dy, pRotate, angle);
+        }
+        VToolPiecePath *pathTool = VToolPiecePath::Create(0, newPath, NULL_ID, initData.scene, initData.doc,
+                                                          initData.data, initData.parse, Source::FromTool, drawName,
+                                                          id);
+        newList.append(pathTool->getId());
+    }
+    newDetail.SetInternalPaths(newList);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedInternalPaths(VPiece &newDetail, const VPiece &d1, const VPiece &d2, quint32 id,
+                               const QString &drawName, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
+                               quint32 pRotate, qreal angle)
+{
+    QVector<quint32> children;
+    CreateUnitedDetailInternalPaths(newDetail, d1, children, id, drawName, initData, dx, dy, pRotate, angle);
+    CreateUnitedDetailInternalPaths(newDetail, d2, children, id, drawName, initData, dx, dy, pRotate, angle);
+
+    SCASSERT(not children.isEmpty())
+    SaveInternalPathsChildren(initData.doc, id, children);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedNodes(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                       qreal angle)
+{
+    const VPiecePath d1Path = GetPiece1MainPath(initData.doc, initData.d1id);
+    const VPiecePath d1REPath = d1Path.RemoveEdge(initData.indexD1);
+
+    const VPiecePath d2Path = GetPiece2MainPath(initData.doc, initData.d2id);
+    const VPiecePath d2REPath = d2Path.RemoveEdge(initData.indexD2);
+
+    const qint32 countNodeD1 = d1REPath.CountNodes();
+    const qint32 countNodeD2 = d2REPath.CountNodes();
+
+    QVector<quint32> children = GetNodesChildren(initData.doc, id);
+    if (not children.isEmpty())
+    {
+        // This check need for backward compatibility
+        // Remove check and "else" part if min version is 0.3.2
+        Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
+                          "Time to refactor the code.");
+        if (children.size() == countNodeD1 + countNodeD2-1)
+        {
+            qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
+            qint32 i = 0;
+            const int indexOfNode = d1Path.indexOfNode(pRotate);
+            do
+            {
+                UpdatePathNode(initData.data, d1REPath.at(i), children);
+                ++i;
+                if (i > indexOfNode && pointsD2 < countNodeD2-1)
+                {
+                    qint32 j = 0;
+                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
+                    do
+                    {
+                        if (j >= countNodeD2)
+                        {
+                            j=0;
+                        }
+                        UpdatePathNode(initData.data, d2REPath.at(j), children, dx, dy, pRotate, angle);
+                        ++pointsD2;
+                        ++j;
+                    } while (pointsD2 < countNodeD2-1);
+                }
+            } while (i<countNodeD1);
+        }
+        else // remove if min version is 0.3.2
+        {
+            qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
+            qint32 i = 0;
+            const int indexOfNode = d1Path.indexOfNode(pRotate);
+            do
+            {
+                ++i;
+                if (i > indexOfNode)
+                {
+                    const int childrenCount = children.size();
+                    qint32 j = 0;
+                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
+                    do
+                    {
+                        if (j >= countNodeD2)
+                        {
+                            j=0;
+                        }
+                        UpdatePathNode(initData.data, d2REPath.at(j), children, dx, dy, pRotate, angle);
+                        ++pointsD2;
+                        ++j;
+                    } while (pointsD2 < childrenCount);
+                    break;
+                }
+            } while (i<countNodeD1);
+        }
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedDetailCSA(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                           qreal angle, const QVector<CustomSARecord> &records)
+{
+    QVector<quint32> children = GetCSAChildren(initData.doc, id);
+    for (int i=0; i < records.size(); ++i)
+    {
+        VPiecePath path = initData.data->GetPiecePath(records.at(i).path);
+        UpdatePathNode(initData.data, path.at(i), children, dx, dy, pRotate, angle);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedCSA(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                     qreal angle)
+{
+    UpdateUnitedDetailCSA(id, initData, dx, dy, pRotate, angle, GetPiece1CSAPaths(initData.doc, id));
+    UpdateUnitedDetailCSA(id, initData, dx, dy, pRotate, angle, GetPiece2CSAPaths(initData.doc, id));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedDetailInternalPaths(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
+                                     quint32 pRotate, qreal angle, const QVector<quint32> &records)
+{
+    QVector<quint32> children = GetInternalPathsChildren(initData.doc, id);
+    for (int i=0; i < records.size(); ++i)
+    {
+        VPiecePath path = initData.data->GetPiecePath(records.at(i));
+        UpdatePathNode(initData.data, path.at(i), children, dx, dy, pRotate, angle);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void UpdateUnitedInternalPaths(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
+                               quint32 pRotate, qreal angle)
+{
+    UpdateUnitedDetailInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece1InternalPaths(initData.doc, id));
+    UpdateUnitedDetailInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece2InternalPaths(initData.doc, id));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void CreateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                        qreal angle)
+{
+    const QString drawName = DrawName(initData.doc, initData.d1id, initData.d2id);
+    SCASSERT(not drawName.isEmpty())
+
+    const VPiece d1 = initData.data->GetPiece(initData.d1id);
+    const VPiece d2 = initData.data->GetPiece(initData.d2id);
+
+    VPiece newDetail;
+
+    CreateUnitedNodes(newDetail, d1, d2, id, drawName, initData, dx, dy, pRotate, angle);
+    CreateUnitedCSA(newDetail, d1, d2, id, drawName, initData, dx, dy, pRotate, angle);
+    CreateUnitedInternalPaths(newDetail, d1, d2, id, drawName, initData, dx, dy, pRotate, angle);
 
     newDetail.SetName(QObject::tr("United detail"));
     newDetail.SetSAWidth(d1.GetSAWidth());
@@ -876,77 +1211,12 @@ void CreateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsIni
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void UpdateUnitedDetail(qint32 &pointsD2, quint32 id, const VToolUnionDetailsInitData &initData,
-                        const VPieceNode &det1p1, qreal dx, qreal dy, qreal angle)
+void UpdateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                        qreal angle)
 {
-    const VPiecePath d1Path = GetPiece1MainPath(initData.doc, initData.d1id);
-    const VPiecePath d1REPath = d1Path.RemoveEdge(initData.indexD1);
-
-    const VPiecePath d2Path = GetPiece2MainPath(initData.doc, initData.d2id);
-    const VPiecePath d2REPath = d2Path.RemoveEdge(initData.indexD2);
-
-    const qint32 countNodeD1 = d1REPath.CountNodes();
-    const qint32 countNodeD2 = d2REPath.CountNodes();
-
-    QVector<quint32> children = GetNodesChildren(initData.doc, id);
-    if (not children.isEmpty())
-    {
-        // This check need for backward compatibility
-        // Remove check and "else" part if min version is 0.3.2
-        Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
-                          "Time to refactor the code.");
-        if (children.size() == countNodeD1 + countNodeD2-1)
-        {
-            qint32 i = 0;
-            const int indexOfNode = d1Path.indexOfNode(det1p1.GetId());
-            do
-            {
-                UpdateNodes(initData.data, d1REPath, i, children);
-                ++i;
-                if (i > indexOfNode && pointsD2 < countNodeD2-1)
-                {
-                    qint32 j = 0;
-                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
-                    do
-                    {
-                        if (j >= countNodeD2)
-                        {
-                            j=0;
-                        }
-                        UpdateNodes(initData.data, d2REPath, j, children, dx, dy, det1p1.GetId(), angle);
-                        ++pointsD2;
-                        ++j;
-                    } while (pointsD2 < countNodeD2-1);
-                }
-            } while (i<countNodeD1);
-        }
-        else // remove if min version is 0.3.2
-        {
-            qint32 i = 0;
-            const int indexOfNode = d1Path.indexOfNode(det1p1.GetId());
-            do
-            {
-                ++i;
-                if (i > indexOfNode)
-                {
-                    const int childrenCount = children.size();
-                    qint32 j = 0;
-                    FindIndexJ(pointsD2, d2Path, initData.indexD2, j);
-                    do
-                    {
-                        if (j >= countNodeD2)
-                        {
-                            j=0;
-                        }
-                        UpdateNodes(initData.data, d2REPath, j, children, dx, dy, det1p1.GetId(), angle);
-                        ++pointsD2;
-                        ++j;
-                    } while (pointsD2 < childrenCount);
-                    break;
-                }
-            } while (i<countNodeD1);
-        }
-    }
+    UpdateUnitedNodes(id, initData, dx, dy, pRotate, angle);
+    UpdateUnitedCSA(id, initData, dx, dy, pRotate, angle);
+    UpdateUnitedInternalPaths(id, initData, dx, dy, pRotate, angle);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -958,15 +1228,13 @@ void UniteDetails(quint32 id, const VToolUnionDetailsInitData &initData)
     qreal angle = 0;
     UnionInitParameters(initData, det1p1, dx, dy, angle);
 
-    qint32 pointsD2 = 0; //Keeps number points the second detail, what we have already added.
-
     if (initData.typeCreation == Source::FromGui)
     {
-        CreateUnitedDetail(pointsD2, id, initData, det1p1, dx, dy, angle);
+        CreateUnitedDetail(id, initData,  dx, dy, det1p1.GetId(), angle);
     }
     else
     {
-        UpdateUnitedDetail(pointsD2, id, initData, det1p1, dx, dy, angle);
+        UpdateUnitedDetail(id, initData, dx, dy, det1p1.GetId(), angle);
     }
 }
 } // static functions
@@ -1230,7 +1498,7 @@ QVector<quint32> VToolUnionDetails::GetReferenceObjects() const
                         case 1://VToolSeamAllowance::TagCSA
                         case 2://VToolSeamAllowance::TagIPaths
                         {
-                            const quint32 id = doc->GetParametrUInt(element, VToolSeamAllowance::AttrPath, NULL_ID_STR);
+                            const quint32 id = doc->GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
                             if (id > NULL_ID)
                             {
                                 list.append(id);

From 7aebc22d88825474a4c98ed8e96e8c357b5d544d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 17 Jan 2017 12:26:25 +0200
Subject: [PATCH 165/208] Use MessageHandler to show better error message when
 load xsd schema.

--HG--
branch : feature
---
 src/libs/ifc/xml/vdomdocument.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp
index f8efed3e9..e5a590f11 100644
--- a/src/libs/ifc/xml/vdomdocument.cpp
+++ b/src/libs/ifc/xml/vdomdocument.cpp
@@ -495,8 +495,9 @@ void VDomDocument::ValidateXML(const QString &schema, const QString &fileName)
     {
         pattern.close();
         fileSchema.close();
-        const QString errorMsg(tr("Could not load schema file '%1'.").arg(fileSchema.fileName()));
-        throw VException(errorMsg);
+        VException e(messageHandler.statusMessage());
+        e.AddMoreInformation(tr("Could not load schema file '%1'.").arg(fileSchema.fileName()));
+        throw e;
     }
     qCDebug(vXML, "Schema loaded.");
 

From bfd76b4e60b9b324da34d43504350532560d4f8e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 17 Jan 2017 13:49:21 +0200
Subject: [PATCH 166/208] Code style.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index 0d43f14be..aeeacb164 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -256,9 +256,9 @@ template <typename T>
 const QSharedPointer<T> VContainer::GeometricObject(const quint32 &id) const
 {
     QSharedPointer<VGObject> gObj = QSharedPointer<VGObject>();
-   if (d->gObjects.contains(id))
-   {
-       gObj = d->gObjects.value(id);
+    if (d->gObjects.contains(id))
+    {
+        gObj = d->gObjects.value(id);
     }
     else
     {
@@ -269,11 +269,11 @@ const QSharedPointer<T> VContainer::GeometricObject(const quint32 &id) const
         QSharedPointer<T> obj = qSharedPointerDynamicCast<T>(gObj);
         SCASSERT(obj.isNull() == false)
         return obj;
-     }
-     catch (const std::bad_alloc &)
-     {
+    }
+    catch (const std::bad_alloc &)
+    {
         throw VExceptionBadId(tr("Can't cast object"), id);
-     }
+    }
 }
 
 

From 7490200806784450da604d5ded7b6dc1a65bcd69 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Tue, 17 Jan 2017 13:49:55 +0200
Subject: [PATCH 167/208] Fix tool Union Details's dialog.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecepath.cpp            | 110 ++++++++++++++++++
 src/libs/vpatterndb/vpiecepath.h              |   4 +
 .../dialogs/tools/dialoguniondetails.cpp      |  17 +--
 3 files changed, 123 insertions(+), 8 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index e0ed91595..9d3e6216d 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -387,6 +387,96 @@ void VPiecePath::NodeOnEdge(quint32 index, VPieceNode &p1, VPieceNode &p2) const
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VPiecePath::Contains(quint32 id) const
+{
+    for (int i = 0; i < d->m_nodes.size(); ++i)
+    {
+        if (d->m_nodes.at(i).GetId() == id)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief OnEdge checks if two poins located on the edge. Edge is line between two points. If between two points
+ * located arcs or splines ignore this.
+ * @param p1 id first point.
+ * @param p2 id second point.
+ * @return true - on edge, false - no.
+ */
+bool VPiecePath::OnEdge(quint32 p1, quint32 p2) const
+{
+    const QVector<VPieceNode> list = ListNodePoint();
+    if (list.size() < 2)
+    {
+        qDebug()<<"Not enough points.";
+        return false;
+    }
+    int i = indexOfNode(list, p1);
+    int j1 = 0, j2 = 0;
+
+    if (i == list.size() - 1)
+    {
+        j1 = i-1;
+        j2 = 0;
+    }
+    else if (i == 0)
+    {
+        j1 = list.size() - 1;
+        j2 = i + 1;
+    }
+    else
+    {
+        j1 = i - 1;
+        j2 = i + 1;
+    }
+
+    if (list.at(j1).GetId() == p2 || list.at(j2).GetId() == p2)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Edge return edge index in detail. Edge is line between two points. If between two points
+ * located arcs or splines ignore this.
+ * @param p1 id first point.
+ * @param p2 id second point.
+ * @return edge index or -1 if points don't located on edge
+ */
+int VPiecePath::Edge(quint32 p1, quint32 p2) const
+{
+    if (OnEdge(p1, p2) == false)
+    {
+        qDebug()<<"Points don't on edge.";
+        return -1;
+    }
+
+    const QVector<VPieceNode> list = ListNodePoint();
+    int i = indexOfNode(list, p1);
+    int j = indexOfNode(list, p2);
+
+    int min = qMin(i, j);
+
+    if (min == 0 && (i == list.size() - 1 || j == list.size() - 1))
+    {
+        return list.size() - 1;
+    }
+    else
+    {
+        return min;
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief listNodePoint return list nodes only with points.
@@ -679,3 +769,23 @@ VSAPoint VPiecePath::CurvePoint(const VSAPoint &candidate, const VContainer *dat
     }
     return point;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief indexOfNode return index in list node using id object.
+ * @param list list nodes detail.
+ * @param id object (arc, point, spline, splinePath) id.
+ * @return index in list or -1 id can't find.
+ */
+int VPiecePath::indexOfNode(const QVector<VPieceNode> &list, quint32 id)
+{
+    for (int i = 0; i < list.size(); ++i)
+    {
+        if (list.at(i).GetId() == id)
+        {
+            return i;
+        }
+    }
+    qDebug()<<"Can't find node.";
+    return -1;
+}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 557d8541d..9f80b1293 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -81,6 +81,9 @@ public:
 
     int  indexOfNode(quint32 id) const;
     void NodeOnEdge(quint32 index, VPieceNode &p1, VPieceNode &p2) const;
+    bool Contains(quint32 id) const;
+    bool OnEdge(quint32 p1, quint32 p2) const;
+    int  Edge(quint32 p1, quint32 p2) const;
 
     QVector<VPieceNode> ListNodePoint() const;
 
@@ -106,6 +109,7 @@ private:
 
     static VSAPoint CurvePoint(const VSAPoint &candidate, const VContainer *data, const VPieceNode &node,
                                const QSharedPointer<VAbstractCurve> &curve);
+    static int      indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };
 
 Q_DECLARE_TYPEINFO(VPiecePath, Q_MOVABLE_TYPE);
diff --git a/src/libs/vtools/dialogs/tools/dialoguniondetails.cpp b/src/libs/vtools/dialogs/tools/dialoguniondetails.cpp
index 0078616b1..8c54a9dee 100644
--- a/src/libs/vtools/dialogs/tools/dialoguniondetails.cpp
+++ b/src/libs/vtools/dialogs/tools/dialoguniondetails.cpp
@@ -33,7 +33,8 @@
 
 #include "../ifc/ifcdef.h"
 #include "../vpatterndb/vcontainer.h"
-#include "../vpatterndb/vdetail.h"
+#include "../vpatterndb/vpiece.h"
+#include "../vpatterndb/vpiecenode.h"
 #include "dialogtool.h"
 #include "ui_dialoguniondetails.h"
 
@@ -96,8 +97,8 @@ bool DialogUnionDetails::CheckObject(const quint32 &id, const quint32 &idDetail)
     {
         return false;
     }
-    const VDetail det = data->GetDetail(idDetail);
-    return det.Containes(id);
+    const VPiece det = data->GetPiece(idDetail);
+    return det.GetPath().Contains(id);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -107,8 +108,8 @@ bool DialogUnionDetails::CheckDetail(const quint32 &idDetail) const
     {
         return false;
     }
-    const VDetail det = data->GetDetail(idDetail);
-    if (det.CountNode() >= 3 && det.listNodePoint().size() >= 2)
+    const VPiece det = data->GetPiece(idDetail);
+    if (det.GetPath().CountNodes() >= 3 && det.GetPath().ListNodePoint().size() >= 2)
     {
         return true;
     }
@@ -166,11 +167,11 @@ void DialogUnionDetails::ChoosedDetail(const quint32 &id, const SceneObject &typ
                 emit ToolTip(tr("Select a unique point"));
                 return;
             }
-            VDetail d = data->GetDetail(idDetail);
-            if (d.OnEdge(p1, id))
+            VPiece d = data->GetPiece(idDetail);
+            if (d.GetPath().OnEdge(p1, id))
             {
                 p2 = id;
-                index = d.Edge(p1, p2);
+                index = d.GetPath().Edge(p1, p2);
                 ++numberD;
                 if (numberD > 1)
                 {

From 8b839c7002841bcb24d3e41cdff80b1fd0c79c60 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 10:15:51 +0200
Subject: [PATCH 168/208] List of pieces should also be cleared.

--HG--
branch : feature
---
 src/libs/vpatterndb/vcontainer.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index d8404befc..db7efea75 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -305,6 +305,8 @@ void VContainer::Clear()
     _id = NULL_ID;
 
     d->details->clear();
+    d->pieces->clear();
+    d->piecePaths->clear();
     ClearVariables();
     ClearGObjects();
     ClearUniqueNames();

From d2ff75dedceed2033669f08c71f2537dbc6d355a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 10:17:18 +0200
Subject: [PATCH 169/208] Tool Union Details now works.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiece.cpp                |  12 ++
 src/libs/vpatterndb/vpiece.h                  |   2 +
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  33 ++-
 .../vtools/tools/nodeDetails/vtoolpiecepath.h |   1 +
 src/libs/vtools/tools/vabstracttool.cpp       |  93 ++++++++-
 src/libs/vtools/tools/vabstracttool.h         |   5 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  | 106 ++--------
 src/libs/vtools/tools/vtoolseamallowance.h    |   4 +-
 src/libs/vtools/tools/vtooluniondetails.cpp   | 192 +++++++++---------
 src/libs/vtools/tools/vtooluniondetails.h     |   2 +-
 10 files changed, 247 insertions(+), 203 deletions(-)

diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 398866c27..9fc8a2a10 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -281,6 +281,12 @@ void VPiece::SetInternalPaths(const QVector<quint32> &iPaths)
     d->m_internalPaths = iPaths;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::AppendInternalPath(quint32 path)
+{
+    d->m_internalPaths.append(path);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<CustomSARecord> VPiece::GetCustomSARecords() const
 {
@@ -293,6 +299,12 @@ void VPiece::SetCustomSARecords(const QVector<CustomSARecord> &records)
     d->m_customSARecords = records;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::AppendCustomSARecord(const CustomSARecord &record)
+{
+    d->m_customSARecords.append(record);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief MissingNodes find missing nodes in detail. When we deleted object in detail and return this detail need
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 47bc31f05..fcd2c9948 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -81,9 +81,11 @@ public:
 
     QVector<quint32> GetInternalPaths() const;
     void             SetInternalPaths(const QVector<quint32> &iPaths);
+    void             AppendInternalPath(quint32 path);
 
     QVector<CustomSARecord> GetCustomSARecords() const;
     void                    SetCustomSARecords(const QVector<CustomSARecord> &records);
+    void                    AppendCustomSARecord(const CustomSARecord &record);
 
     QVector<quint32> MissingNodes(const VPiece &det) const;
     QVector<quint32> MissingCSAPath(const VPiece &det) const;
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index d1f806fb7..0a3cb028c 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -40,8 +40,10 @@ VToolPiecePath *VToolPiecePath::Create(DialogTool *dialog, VMainGraphicsScene *s
     SCASSERT(dialog != nullptr);
     DialogPiecePath *dialogTool = qobject_cast<DialogPiecePath*>(dialog);
     SCASSERT(dialogTool != nullptr);
-    const VPiecePath path = dialogTool->GetPiecePath();
+    VPiecePath path = dialogTool->GetPiecePath();
     const quint32 pieceId = dialogTool->GetPieceId();
+    qApp->getUndoStack()->beginMacro("add path");
+    path.SetNodes(PrepareNodes(path, scene, doc, data));
 
     VToolPiecePath *pathTool = Create(0, path, pieceId, scene, doc, data, Document::FullParse, Source::FromGui);
     return pathTool;
@@ -90,7 +92,6 @@ VToolPiecePath *VToolPiecePath::Create(quint32 _id, const VPiecePath &path, quin
                 SCASSERT(saTool != nullptr);
                 pathTool->setParentItem(saTool);
                 pathTool->SetParentType(ParentType::Item);
-                doc->IncrementReferens(id);
             }
             else
             {
@@ -201,8 +202,6 @@ void VToolPiecePath::AddToFile()
 
     AddNodes(doc, domElement, path);
 
-    qApp->getUndoStack()->beginMacro(tr("new path"));
-
     AddToModeling(domElement);
 
     if (m_pieceId > NULL_ID)
@@ -230,8 +229,6 @@ void VToolPiecePath::AddToFile()
         qApp->getUndoStack()->push(saveCommand);// First push then make a connect
         VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
         connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-
-        qApp->getUndoStack()->endMacro();
     }
 }
 
@@ -263,6 +260,23 @@ void VToolPiecePath::HideNode()
     hide();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VToolPiecePath::ToolCreation(const Source &typeCreation)
+{
+    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
+    {
+        AddToFile();
+        if (typeCreation != Source::FromTool)
+        {
+            qApp->getUndoStack()->endMacro();
+        }
+    }
+    else
+    {
+        RefreshDataInFile();
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VToolPiecePath::VToolPiecePath(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 pieceId,
                                const Source &typeCreation, const QString &drawName, const quint32 &idTool,
@@ -271,6 +285,7 @@ VToolPiecePath::VToolPiecePath(VAbstractPattern *doc, VContainer *data, quint32
       QGraphicsPathItem(parent),
       m_pieceId(pieceId)
 {
+    IncrementNodes(VAbstractTool::data.GetPiecePath(id));
     RefreshGeometry();
     ToolCreation(typeCreation);
 }
@@ -296,8 +311,7 @@ void VToolPiecePath::IncrementNodes(const VPiecePath &path) const
 {
     for (int i = 0; i < path.CountNodes(); ++i)
     {
-        const QSharedPointer<VGObject> node = VAbstractTool::data.GetGObject(path.at(i).GetId());
-        doc->IncrementReferens(node->getIdTool());
+        doc->IncrementReferens(VAbstractTool::data.GetGObject(path.at(i).GetId())->getIdTool());
     }
 }
 
@@ -306,7 +320,6 @@ void VToolPiecePath::DecrementNodes(const VPiecePath &path) const
 {
     for (int i = 0; i < path.CountNodes(); ++i)
     {
-        const QSharedPointer<VGObject> node = VAbstractTool::data.GetGObject(path.at(i).GetId());
-        doc->DecrementReferens(node->getIdTool());
+        doc->DecrementReferens(VAbstractTool::data.GetGObject(path.at(i).GetId())->getIdTool());
     }
 }
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
index 6360e4b3f..2b1f4fca8 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.h
@@ -63,6 +63,7 @@ protected:
     virtual void RefreshDataInFile() Q_DECL_OVERRIDE;
     virtual void ShowNode() Q_DECL_OVERRIDE;
     virtual void HideNode() Q_DECL_OVERRIDE;
+    virtual void ToolCreation(const Source &typeCreation) Q_DECL_OVERRIDE;
 private:
     Q_DISABLE_COPY(VToolPiecePath)
 
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index ec513ae87..1198a0683 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -62,12 +62,17 @@
 #include "../vgeometry/../ifc/ifcdef.h"
 #include "../vgeometry/vgeometrydef.h"
 #include "../vgeometry/vgobject.h"
+#include "../vgeometry/vcubicbezier.h"
+#include "../vgeometry/vcubicbezierpath.h"
+#include "../vgeometry/vsplinepath.h"
+#include "../vgeometry/varc.h"
+#include "../vgeometry/vellipticalarc.h"
 #include "../vmisc/vcommonsettings.h"
 #include "../vmisc/logging.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vpatterndb/vpiecenode.h"
 #include "../vwidgets/vgraphicssimpletextitem.h"
-#include "vdatatool.h"
+#include "nodeDetails/nodedetails.h"
 
 class QGraphicsEllipseItem;
 class QGraphicsLineItem;
@@ -75,6 +80,51 @@ template <class T> class QSharedPointer;
 
 const QString VAbstractTool::AttrInUse = QStringLiteral("inUse");
 
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+template<typename T>
+/**
+ * @brief CreateNode create new node for detail.
+ * @param data container.
+ * @param id id parent object.
+ * @return id for new object.
+ */
+quint32 CreateNode(VContainer *data, quint32 id)
+{
+    //We can't use exist object. Need create new.
+    T *node = new T(*data->GeometricObject<T>(id).data());
+    node->setMode(Draw::Modeling);
+    return data->AddGObject(node);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 CreateNodeSpline(VContainer *data, quint32 id)
+{
+    if (data->GetGObject(id)->getType() == GOType::Spline)
+    {
+        return CreateNode<VSpline>(data, id);
+    }
+    else
+    {
+        return CreateNode<VCubicBezier>(data, id);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+quint32 CreateNodeSplinePath(VContainer *data, quint32 id)
+{
+    if (data->GetGObject(id)->getType() == GOType::SplinePath)
+    {
+        return CreateNode<VSplinePath>(data, id);
+    }
+    else
+    {
+        return CreateNode<VCubicBezierPath>(data, id);
+    }
+}
+}//static functions
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief VAbstractTool container.
@@ -533,3 +583,44 @@ void VAbstractTool::AddNode(VAbstractPattern *doc, QDomElement &domElement, cons
 {
     domElement.appendChild(AddSANode(doc, VAbstractPattern::TagNode, node));
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VPieceNode> VAbstractTool::PrepareNodes(const VPiecePath &path, VMainGraphicsScene *scene,
+                                                VAbstractPattern *doc, VContainer *data)
+{
+    QVector<VPieceNode> nodes;
+    for (int i = 0; i< path.CountNodes(); ++i)
+    {
+        quint32 id = 0;
+        VPieceNode nodeD = path.at(i);
+        switch (nodeD.GetTypeTool())
+        {
+            case (Tool::NodePoint):
+                id = CreateNode<VPointF>(data, nodeD.GetId());
+                VNodePoint::Create(doc, data, scene, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+                break;
+            case (Tool::NodeArc):
+                id = CreateNode<VArc>(data, nodeD.GetId());
+                VNodeArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+                break;
+            case (Tool::NodeElArc):
+                id = CreateNode<VEllipticalArc>(data, nodeD.GetId());
+                VNodeEllipticalArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+                break;
+            case (Tool::NodeSpline):
+                id = CreateNodeSpline(data, nodeD.GetId());
+                VNodeSpline::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+                break;
+            case (Tool::NodeSplinePath):
+                id = CreateNodeSplinePath(data, nodeD.GetId());
+                VNodeSplinePath::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
+                break;
+            default:
+                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
+                break;
+        }
+        nodeD.SetId(id);
+        nodes.append(nodeD);
+    }
+    return nodes;
+}
diff --git a/src/libs/vtools/tools/vabstracttool.h b/src/libs/vtools/tools/vabstracttool.h
index 9387e6df5..1b24d6d39 100644
--- a/src/libs/vtools/tools/vabstracttool.h
+++ b/src/libs/vtools/tools/vabstracttool.h
@@ -147,13 +147,16 @@ protected:
     void AddVisualization();
 
     virtual void SetVisualization()=0;
-    void ToolCreation(const Source &typeCreation);
+    virtual void ToolCreation(const Source &typeCreation);
 
     static void RefreshLine(QGraphicsEllipseItem *point, VGraphicsSimpleTextItem *namePoint,
                             QGraphicsLineItem *lineName, const qreal radius);
 
     static QDomElement AddSANode(VAbstractPattern *doc, const QString &tagName, const VPieceNode &node);
     static void        AddNode(VAbstractPattern *doc, QDomElement &domElement, const VPieceNode &node);
+
+    static QVector<VPieceNode> PrepareNodes(const VPiecePath &path, VMainGraphicsScene *scene, VAbstractPattern *doc,
+                                            VContainer *data);
 private:
     Q_DISABLE_COPY(VAbstractTool)
 };
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index ee48d5312..be6b1c712 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -90,69 +90,8 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
     DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(dialog);
     SCASSERT(dialogTool != nullptr);
     VPiece detail = dialogTool->GetPiece();
-    QVector<VPieceNode> nodes;
     qApp->getUndoStack()->beginMacro("add detail");
-    for (int i = 0; i< detail.GetPath().CountNodes(); ++i)
-    {
-        quint32 id = 0;
-        VPieceNode nodeD = detail.GetPath().at(i);
-        switch (nodeD.GetTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                id = CreateNode<VPointF>(data, nodeD.GetId());
-                VNodePoint::Create(doc, data, scene, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeArc):
-            {
-                id = CreateNode<VArc>(data, nodeD.GetId());
-                VNodeArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeElArc):
-            {
-                id = CreateNode<VEllipticalArc>(data, nodeD.GetId());
-                VNodeEllipticalArc::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeSpline):
-            {
-                const auto obj = data->GetGObject(nodeD.GetId());
-                if (obj->getType() == GOType::Spline)
-                {
-                    id = CreateNode<VSpline>(data, nodeD.GetId());
-                }
-                else
-                {
-                    id = CreateNode<VCubicBezier>(data, nodeD.GetId());
-                }
-                VNodeSpline::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            case (Tool::NodeSplinePath):
-            {
-                const auto obj = data->GetGObject(nodeD.GetId());
-                if (obj->getType() == GOType::SplinePath)
-                {
-                    id = CreateNode<VSplinePath>(data, nodeD.GetId());
-                }
-                else
-                {
-                    id = CreateNode<VCubicBezierPath>(data, nodeD.GetId());
-                }
-                VNodeSplinePath::Create(doc, data, id, nodeD.GetId(), Document::FullParse, Source::FromGui);
-            }
-            break;
-            default:
-                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-                break;
-        }
-        nodeD.SetId(id);
-        nodes.append(nodeD);
-    }
-
-    detail.GetPath().SetNodes(nodes);
+    detail.GetPath().SetNodes(PrepareNodes(detail.GetPath(), scene, doc, data));
 
     VToolSeamAllowance *piece = Create(0, detail, scene, doc, data, Document::FullParse, Source::FromGui);
 
@@ -1068,19 +1007,8 @@ VToolSeamAllowance::VToolSeamAllowance(VAbstractPattern *doc, VContainer *data,
     this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
 
     connect(scene, &VMainGraphicsScene::EnableToolMove, this, &VToolSeamAllowance::EnableToolMove);
-    //connect(scene, &VMainGraphicsScene::ItemClicked, this, &VToolSeamAllowance::ResetChildren);
-    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
-    {
-        AddToFile();
-        if (typeCreation != Source::FromTool)
-        {
-            qApp->getUndoStack()->endMacro();
-        }
-    }
-    else
-    {
-        RefreshDataInFile();
-    }
+    connect(scene, &VMainGraphicsScene::ItemClicked, this, &VToolSeamAllowance::ResetChildren);
+    ToolCreation(typeCreation);
     setAcceptHoverEvents(true);
 
     connect(m_dataLabel, &VTextGraphicsItem::SignalMoved, this, &VToolSeamAllowance::SaveMoveDetail);
@@ -1165,7 +1093,7 @@ void VToolSeamAllowance::InitNodes(const VPiece &detail, VMainGraphicsScene *sce
             case (Tool::NodeElArc):
             case (Tool::NodeSpline):
             case (Tool::NodeSplinePath):
-                doc->IncrementReferens(detail.GetPath().at(i).GetId());
+                doc->IncrementReferens(VAbstractTool::data.GetGObject(detail.GetPath().at(i).GetId())->getIdTool());
                 break;
             default:
                 qDebug()<<"Get wrong tool type. Ignore.";
@@ -1194,6 +1122,7 @@ void VToolSeamAllowance::InitInternalPaths(const VPiece &detail)
         SCASSERT(tool != nullptr);
         tool->setParentItem(this);
         tool->SetParentType(ParentType::Item);
+        tool->show();
         doc->IncrementReferens(records.at(i));
     }
 }
@@ -1219,19 +1148,20 @@ void VToolSeamAllowance::DeleteTool(bool ask)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-template<typename T>
-/**
- * @brief CreateNode create new node for detail.
- * @param data container.
- * @param id id parent object.
- * @return id for new object.
- */
-quint32 VToolSeamAllowance::CreateNode(VContainer *data, const quint32 &id)
+void VToolSeamAllowance::ToolCreation(const Source &typeCreation)
 {
-    //We can't use exist object. Need create new.
-    T *node = new T(*data->GeometricObject<T>(id).data());
-    node->setMode(Draw::Modeling);
-    return data->AddGObject(node);
+    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
+    {
+        AddToFile();
+        if (typeCreation != Source::FromTool)
+        {
+            qApp->getUndoStack()->endMacro();
+        }
+    }
+    else
+    {
+        RefreshDataInFile();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 4b25acc00..1c8b1a2e3 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -125,6 +125,7 @@ protected:
     virtual void       keyReleaseEvent(QKeyEvent * event) Q_DECL_OVERRIDE;
     virtual void       SetVisualization() Q_DECL_OVERRIDE {}
     virtual void       DeleteTool(bool ask = true) Q_DECL_OVERRIDE;
+    virtual void       ToolCreation(const Source &typeCreation) Q_DECL_OVERRIDE;
 
 private:
     Q_DISABLE_COPY(VToolSeamAllowance)
@@ -143,9 +144,6 @@ private:
 
     void SetDialog();
 
-    template<typename T>
-    static quint32 CreateNode(VContainer *data, const quint32 &id);
-
     VToolSeamAllowance(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation,
                        VMainGraphicsScene *scene, const QString &m_drawName, QGraphicsItem * parent = nullptr);
 
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index 7a2ec2d05..9cd040617 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -111,13 +111,13 @@ VPiecePath GetPiecePath(int piece, VAbstractPattern *doc, quint32 id)
     for (qint32 i = 0; i < nodesList.size(); ++i)
     {
         const QDomElement element = nodesList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail && i+1 == piece)
         {
             const QDomNodeList detList = element.childNodes();
             for (qint32 j = 0; j < detList.size(); ++j)
             {
                 const QDomElement element = detList.at(j).toElement();
-                if (not element.isNull() && element.tagName() == VAbstractPattern::TagNodes && j+1 == piece)
+                if (not element.isNull() && element.tagName() == VAbstractPattern::TagNodes)
                 {
                     return VAbstractPattern::ParsePieceNodes(element);
                 }
@@ -141,7 +141,7 @@ VPiecePath GetPiece2MainPath(VAbstractPattern *doc, quint32 id)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<CustomSARecord> GetPieceCSAList(int piece, VAbstractPattern *doc, quint32 id)
+QVector<CustomSARecord> GetPiece2CSAPaths(VAbstractPattern *doc, quint32 id)
 {
     const QDomElement tool = doc->elementById(id);
     if (tool.isNull())
@@ -154,13 +154,13 @@ QVector<CustomSARecord> GetPieceCSAList(int piece, VAbstractPattern *doc, quint3
     for (qint32 i = 0; i < nodesList.size(); ++i)
     {
         const QDomElement element = nodesList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail && i+1 == 2)
         {
             const QDomNodeList detList = element.childNodes();
             for (qint32 j = 0; j < detList.size(); ++j)
             {
                 const QDomElement element = detList.at(j).toElement();
-                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagCSA && j+1 == piece)
+                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagCSA)
                 {
                     return VAbstractPattern::ParsePieceCSARecords(element);
                 }
@@ -172,19 +172,7 @@ QVector<CustomSARecord> GetPieceCSAList(int piece, VAbstractPattern *doc, quint3
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<CustomSARecord> GetPiece1CSAPaths(VAbstractPattern *doc, quint32 id)
-{
-    return GetPieceCSAList(1, doc, id);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<CustomSARecord> GetPiece2CSAPaths(VAbstractPattern *doc, quint32 id)
-{
-    return GetPieceCSAList(2, doc, id);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> GetPieceInternalPathList(int piece, VAbstractPattern *doc, quint32 id)
+QVector<quint32> GetPiece2InternalPaths(VAbstractPattern *doc, quint32 id)
 {
     const QDomElement tool = doc->elementById(id);
     if (tool.isNull())
@@ -197,13 +185,13 @@ QVector<quint32> GetPieceInternalPathList(int piece, VAbstractPattern *doc, quin
     for (qint32 i = 0; i < nodesList.size(); ++i)
     {
         const QDomElement element = nodesList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail)
+        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagDetail && i+1 == 2)
         {
             const QDomNodeList detList = element.childNodes();
             for (qint32 j = 0; j < detList.size(); ++j)
             {
                 const QDomElement element = detList.at(j).toElement();
-                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagIPaths && j+1 == piece)
+                if (not element.isNull() && element.tagName() == VToolSeamAllowance::TagIPaths)
                 {
                     return VAbstractPattern::ParsePieceInternalPaths(element);
                 }
@@ -214,18 +202,6 @@ QVector<quint32> GetPieceInternalPathList(int piece, VAbstractPattern *doc, quin
     return QVector<quint32>();
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> GetPiece1InternalPaths(VAbstractPattern *doc, quint32 id)
-{
-    return GetPieceInternalPathList(1, doc, id);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> GetPiece2InternalPaths(VAbstractPattern *doc, quint32 id)
-{
-    return GetPieceInternalPathList(2, doc, id);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 QString DrawName(VAbstractPattern *doc, quint32 d1id, quint32 d2id)
 {
@@ -314,32 +290,30 @@ void BiasRotatePoint(VPointF *point, qreal dx, qreal dy, const QPointF &pRotate,
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void PointsOnEdge(const VPiece &d, quint32 index, VPointF &p1, VPointF &p2, VContainer *data)
+void PointsOnEdge(const VPiecePath &path, quint32 index, VPointF &p1, VPointF &p2, VContainer *data)
 {
     VPieceNode det2p1;
     VPieceNode det2p2;
-    d.GetPath().NodeOnEdge(index, det2p1, det2p2);
+    path.NodeOnEdge(index, det2p1, det2p2);
     p1 = VPointF(*data->GeometricObject<VPointF>(det2p1.GetId()));
     p2 = VPointF(*data->GeometricObject<VPointF>(det2p2.GetId()));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void UnionInitParameters(const VToolUnionDetailsInitData &initData, VPieceNode &det1p1, qreal &dx, qreal &dy,
-                         qreal &angle)
+void UnionInitParameters(const VToolUnionDetailsInitData &initData, const VPiecePath &d1Path, const VPiecePath &d2Path,
+                         VPieceNode &det1p1, qreal &dx, qreal &dy, qreal &angle)
 {
-    const VPiece d1 = initData.data->GetPiece(initData.d1id);
     VPieceNode det1p2;
-    d1.GetPath().NodeOnEdge(initData.indexD1, det1p1, det1p2);
+    d1Path.NodeOnEdge(initData.indexD1, det1p1, det1p2);
     Q_UNUSED(det1p2)
 
     VPointF point1;
     VPointF point2;
-    PointsOnEdge(d1, initData.indexD1, point1, point2, initData.data);
+    PointsOnEdge(d1Path, initData.indexD1, point1, point2, initData.data);
 
     VPointF point3;
     VPointF point4;
-    const VPiece d2 = initData.data->GetPiece(initData.d2id);
-    PointsOnEdge(d2, initData.indexD2, point3, point4, initData.data);
+    PointsOnEdge(d2Path, initData.indexD2, point3, point4, initData.data);
 
     dx = point1.x() - point4.x();
     dy = point1.y() - point4.y();
@@ -987,6 +961,7 @@ void CreateUnitedDetailCSA(VPiece &newDetail, const VPiece &d, QVector<quint32>
 {
     QVector<CustomSARecord> newList = newDetail.GetCustomSARecords();
     const QVector<CustomSARecord> oldList = d.GetCustomSARecords();
+    QVector<quint32> nodeChildren;
     for(int i=0; i < oldList.size(); ++i)
     {
         CustomSARecord record = oldList.at(i);
@@ -995,14 +970,16 @@ void CreateUnitedDetailCSA(VPiece &newDetail, const VPiece &d, QVector<quint32>
         newPath.Clear();//Clear nodes
         for (int i=0; i < path.CountNodes(); ++i)
         {
-            AddNodeToNewPath(initData, newPath, path.at(i), id, children, drawName, dx, dy, pRotate, angle);
+            AddNodeToNewPath(initData, newPath, path.at(i), id, nodeChildren, drawName, dx, dy, pRotate, angle);
         }
-        VToolPiecePath *pathTool = VToolPiecePath::Create(0, newPath, NULL_ID, initData.scene, initData.doc,
-                                                          initData.data, initData.parse, Source::FromTool, drawName,
-                                                          id);
-        record.path = pathTool->getId();
+        const quint32 idPath = initData.data->AddPiecePath(newPath);
+        VToolPiecePath::Create(idPath, newPath, NULL_ID, initData.scene, initData.doc, initData.data, initData.parse,
+                               Source::FromTool, drawName, id);
+        record.path = idPath;
         newList.append(record);
+        nodeChildren.prepend(idPath);
     }
+    children += nodeChildren;
     newDetail.SetCustomSARecords(newList);
 }
 
@@ -1010,8 +987,13 @@ void CreateUnitedDetailCSA(VPiece &newDetail, const VPiece &d, QVector<quint32>
 void CreateUnitedCSA(VPiece &newDetail, const VPiece &d1, const VPiece &d2, quint32 id, const QString &drawName,
                      const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
 {
+    const QVector<CustomSARecord> d1Records = d1.GetCustomSARecords();
+    for (int i = 0; i < d1Records.size(); ++i)
+    {
+        newDetail.AppendCustomSARecord(d1Records.at(i));
+    }
+
     QVector<quint32> children;
-    CreateUnitedDetailCSA(newDetail, d1, children, id, drawName, initData, dx, dy, pRotate, angle);
     CreateUnitedDetailCSA(newDetail, d2, children, id, drawName, initData, dx, dy, pRotate, angle);
 
     SCASSERT(not children.isEmpty())
@@ -1025,6 +1007,7 @@ void CreateUnitedDetailInternalPaths(VPiece &newDetail, const VPiece &d, QVector
 {
     QVector<quint32> newList = newDetail.GetInternalPaths();
     const QVector<quint32> oldList = d.GetInternalPaths();
+    QVector<quint32> nodeChildren;
     for(int i=0; i < oldList.size(); ++i)
     {
         const VPiecePath path = initData.data->GetPiecePath(oldList.at(i));
@@ -1033,13 +1016,15 @@ void CreateUnitedDetailInternalPaths(VPiece &newDetail, const VPiece &d, QVector
 
         for (int i=0; i < path.CountNodes(); ++i)
         {
-            AddNodeToNewPath(initData, newPath, path.at(i), id, children, drawName, dx, dy, pRotate, angle);
+            AddNodeToNewPath(initData, newPath, path.at(i), id, nodeChildren, drawName, dx, dy, pRotate, angle);
         }
-        VToolPiecePath *pathTool = VToolPiecePath::Create(0, newPath, NULL_ID, initData.scene, initData.doc,
-                                                          initData.data, initData.parse, Source::FromTool, drawName,
-                                                          id);
-        newList.append(pathTool->getId());
+        const quint32 idPath = initData.data->AddPiecePath(newPath);
+        VToolPiecePath::Create(idPath, newPath, NULL_ID, initData.scene, initData.doc, initData.data, initData.parse,
+                               Source::FromTool, drawName, id);
+        newList.append(idPath);
+        nodeChildren.prepend(idPath);
     }
+    children += nodeChildren;
     newDetail.SetInternalPaths(newList);
 }
 
@@ -1048,8 +1033,13 @@ void CreateUnitedInternalPaths(VPiece &newDetail, const VPiece &d1, const VPiece
                                const QString &drawName, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
                                quint32 pRotate, qreal angle)
 {
+    const QVector<quint32> d1Internal = d1.GetInternalPaths();
+    for (int i = 0; i < d1Internal.size(); ++i)
+    {
+        newDetail.AppendInternalPath(d1Internal.at(i));
+    }
+
     QVector<quint32> children;
-    CreateUnitedDetailInternalPaths(newDetail, d1, children, id, drawName, initData, dx, dy, pRotate, angle);
     CreateUnitedDetailInternalPaths(newDetail, d2, children, id, drawName, initData, dx, dy, pRotate, angle);
 
     SCASSERT(not children.isEmpty())
@@ -1060,10 +1050,10 @@ void CreateUnitedInternalPaths(VPiece &newDetail, const VPiece &d1, const VPiece
 void UpdateUnitedNodes(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
                        qreal angle)
 {
-    const VPiecePath d1Path = GetPiece1MainPath(initData.doc, initData.d1id);
+    const VPiecePath d1Path = GetPiece1MainPath(initData.doc, id);
     const VPiecePath d1REPath = d1Path.RemoveEdge(initData.indexD1);
 
-    const VPiecePath d2Path = GetPiece2MainPath(initData.doc, initData.d2id);
+    const VPiecePath d2Path = GetPiece2MainPath(initData.doc, id);
     const VPiecePath d2REPath = d2Path.RemoveEdge(initData.indexD2);
 
     const qint32 countNodeD1 = d1REPath.CountNodes();
@@ -1133,43 +1123,46 @@ void UpdateUnitedNodes(quint32 id, const VToolUnionDetailsInitData &initData, qr
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void UpdateUnitedDetailCSA(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
-                           qreal angle, const QVector<CustomSARecord> &records)
+void UpdateUnitedDetailPaths(const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                             qreal angle, const QVector<quint32> &records, QVector<quint32> children)
 {
-    QVector<quint32> children = GetCSAChildren(initData.doc, id);
     for (int i=0; i < records.size(); ++i)
     {
-        VPiecePath path = initData.data->GetPiecePath(records.at(i).path);
-        UpdatePathNode(initData.data, path.at(i), children, dx, dy, pRotate, angle);
+        const VPiecePath path = initData.data->GetPiecePath(records.at(i));
+        const quint32 updatedId = TakeNextId(children);
+
+        VPiecePath updatedPath(path);
+        updatedPath.Clear();
+
+        for (int j=0; j < path.CountNodes(); ++j)
+        {
+            const VPieceNode &node = path.at(j);
+            const quint32 id = TakeNextId(children);
+            updatedPath.Append(VPieceNode(id, node.GetTypeTool(), node.GetReverse()));
+            QVector<quint32> nodeChildren = {id};
+            UpdatePathNode(initData.data, path.at(j), nodeChildren, dx, dy, pRotate, angle);
+        }
+        initData.data->UpdatePiecePath(updatedId, updatedPath);
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void UpdateUnitedCSA(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
-                     qreal angle)
+void UpdateUnitedDetailCSA(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy, quint32 pRotate,
+                           qreal angle, const QVector<CustomSARecord> &records)
 {
-    UpdateUnitedDetailCSA(id, initData, dx, dy, pRotate, angle, GetPiece1CSAPaths(initData.doc, id));
-    UpdateUnitedDetailCSA(id, initData, dx, dy, pRotate, angle, GetPiece2CSAPaths(initData.doc, id));
+    QVector<quint32> idRecords;
+    for (int i = 0; i < records.size(); ++i)
+    {
+        idRecords.append(records.at(i).path);
+    }
+    UpdateUnitedDetailPaths(initData, dx, dy, pRotate, angle, idRecords, GetCSAChildren(initData.doc, id));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void UpdateUnitedDetailInternalPaths(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
                                      quint32 pRotate, qreal angle, const QVector<quint32> &records)
 {
-    QVector<quint32> children = GetInternalPathsChildren(initData.doc, id);
-    for (int i=0; i < records.size(); ++i)
-    {
-        VPiecePath path = initData.data->GetPiecePath(records.at(i));
-        UpdatePathNode(initData.data, path.at(i), children, dx, dy, pRotate, angle);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void UpdateUnitedInternalPaths(quint32 id, const VToolUnionDetailsInitData &initData, qreal dx, qreal dy,
-                               quint32 pRotate, qreal angle)
-{
-    UpdateUnitedDetailInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece1InternalPaths(initData.doc, id));
-    UpdateUnitedDetailInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece2InternalPaths(initData.doc, id));
+    UpdateUnitedDetailPaths(initData, dx, dy, pRotate, angle, records, GetInternalPathsChildren(initData.doc, id));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1215,8 +1208,8 @@ void UpdateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, q
                         qreal angle)
 {
     UpdateUnitedNodes(id, initData, dx, dy, pRotate, angle);
-    UpdateUnitedCSA(id, initData, dx, dy, pRotate, angle);
-    UpdateUnitedInternalPaths(id, initData, dx, dy, pRotate, angle);
+    UpdateUnitedDetailCSA(id, initData, dx, dy, pRotate, angle, GetPiece2CSAPaths(initData.doc, id));
+    UpdateUnitedDetailInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece2InternalPaths(initData.doc, id));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1226,14 +1219,19 @@ void UniteDetails(quint32 id, const VToolUnionDetailsInitData &initData)
     qreal dx = 0;
     qreal dy = 0;
     qreal angle = 0;
-    UnionInitParameters(initData, det1p1, dx, dy, angle);
 
     if (initData.typeCreation == Source::FromGui)
     {
-        CreateUnitedDetail(id, initData,  dx, dy, det1p1.GetId(), angle);
+        const VPiece d1 = initData.data->GetPiece(initData.d1id);
+        const VPiece d2 = initData.data->GetPiece(initData.d2id);
+        UnionInitParameters(initData, d1.GetPath(), d2.GetPath(), det1p1, dx, dy, angle);
+        CreateUnitedDetail(id, initData, dx, dy, det1p1.GetId(), angle);
     }
     else
     {
+        const VPiecePath d1Path = GetPiece1MainPath(initData.doc, id);
+        const VPiecePath d2Path = GetPiece2MainPath(initData.doc, id);
+        UnionInitParameters(initData, d1Path, d2Path, det1p1, dx, dy, angle);
         UpdateUnitedDetail(id, initData, dx, dy, det1p1.GetId(), angle);
     }
 }
@@ -1493,18 +1491,13 @@ QVector<quint32> VToolUnionDetails::GetReferenceObjects() const
                     switch (parts.indexOf(element.tagName()))
                     {
                         case 0://VAbstractPattern::TagNodes
-                            list += NodesReferenceObjects(element);
+                            list += ReferenceObjects(element, TagNode, AttrIdObject);
                             break;
                         case 1://VToolSeamAllowance::TagCSA
                         case 2://VToolSeamAllowance::TagIPaths
-                        {
-                            const quint32 id = doc->GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
-                            if (id > NULL_ID)
-                            {
-                                list.append(id);
-                            }
+                            list += ReferenceObjects(element, VToolSeamAllowance::TagRecord,
+                                                     VAbstractPattern::AttrPath);
                             break;
-                        }
                         default:
                             break;
                     }
@@ -1516,23 +1509,24 @@ QVector<quint32> VToolUnionDetails::GetReferenceObjects() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<quint32> VToolUnionDetails::NodesReferenceObjects(const QDomElement &nodes) const
+QVector<quint32> VToolUnionDetails::ReferenceObjects(const QDomElement &root, const QString &tag,
+                                                     const QString &attribute) const
 {
-    QVector<quint32> list;
+    QVector<quint32> objects;
 
-    const QDomNodeList nodeList = nodes.childNodes();
-    for (qint32 i = 0; i < nodeList.size(); ++i)
+    const QDomNodeList list = root.childNodes();
+    for (qint32 i = 0; i < list.size(); ++i)
     {
-        const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VToolUnionDetails::TagNode)
+        const QDomElement element = list.at(i).toElement();
+        if (not element.isNull() && element.tagName() == tag)
         {
-            const quint32 id = doc->GetParametrUInt(element, AttrIdObject, NULL_ID_STR);
+            const quint32 id = doc->GetParametrUInt(element, attribute, NULL_ID_STR);
             if (id > NULL_ID)
             {
-                list.append(id);
+                objects.append(id);
             }
         }
     }
 
-    return list;
+    return objects;
 }
diff --git a/src/libs/vtools/tools/vtooluniondetails.h b/src/libs/vtools/tools/vtooluniondetails.h
index 2265a0677..b8c3c5649 100644
--- a/src/libs/vtools/tools/vtooluniondetails.h
+++ b/src/libs/vtools/tools/vtooluniondetails.h
@@ -143,7 +143,7 @@ private:
     void             AddDetail(QDomElement &domElement, const VPiece &d) const;
     void             AddToModeling(const QDomElement &domElement);
     QVector<quint32> GetReferenceObjects() const;
-    QVector<quint32> NodesReferenceObjects(const QDomElement &nodes) const;
+    QVector<quint32> ReferenceObjects(const QDomElement &root, const QString &tag, const QString &attribute) const;
 };
 
 #endif // VTOOLUNIONDETAILS_H

From ccc8da800fb54474dd366e72ff4692b262f628f3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 12:22:02 +0200
Subject: [PATCH 170/208] Pieces should disappear from the list when deleted.

--HG--
branch : feature
---
 src/libs/ifc/xml/vabstractpattern.cpp        | 10 ++++++++--
 src/libs/ifc/xml/vabstractpattern.h          |  5 +++--
 src/libs/vpatterndb/vcontainer.cpp           |  6 ++++++
 src/libs/vpatterndb/vcontainer.h             |  1 +
 src/libs/vtools/tools/vtoolseamallowance.cpp | 17 +++++++++++++++++
 src/libs/vtools/tools/vtooluniondetails.cpp  |  3 +++
 6 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index ed68e62a0..f51ea8eaf 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -544,7 +544,7 @@ void VAbstractPattern::setCursor(const quint32 &value)
  * @param id tool id.
  * @return tool.
  */
-VDataTool *VAbstractPattern::getTool(const quint32 &id)
+VDataTool *VAbstractPattern::getTool(quint32 id)
 {
     ToolExists(id);
     return tools.value(id);
@@ -556,13 +556,19 @@ VDataTool *VAbstractPattern::getTool(const quint32 &id)
  * @param id tool id.
  * @param tool tool.
  */
-void VAbstractPattern::AddTool(const quint32 &id, VDataTool *tool)
+void VAbstractPattern::AddTool(quint32 id, VDataTool *tool)
 {
     Q_ASSERT_X(id != 0, Q_FUNC_INFO, "id == 0");
     SCASSERT(tool != nullptr)
             tools.insert(id, tool);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VAbstractPattern::RemoveTool(quint32 id)
+{
+    tools.remove(id);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath VAbstractPattern::ParsePieceNodes(const QDomElement &domElement)
 {
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index 83961b81e..e0237101d 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -92,8 +92,9 @@ public:
 
     virtual void   UpdateToolData(const quint32 &id, VContainer *data)=0;
 
-    static VDataTool* getTool(const quint32 &id);
-    static void       AddTool(const quint32 &id, VDataTool *tool);
+    static VDataTool* getTool(quint32 id);
+    static void       AddTool(quint32 id, VDataTool *tool);
+    static void       RemoveTool(quint32 id);
 
     static VPiecePath              ParsePieceNodes(const QDomElement &domElement);
     static QVector<CustomSARecord> ParsePieceCSARecords(const QDomElement &domElement);
diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index db7efea75..5cc5a26ef 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -519,6 +519,12 @@ void VContainer::RemoveVariable(const QString &name)
     d->variables.remove(name);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void VContainer::RemovePiece(quint32 id)
+{
+    d->pieces->remove(id);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief AddObject add object to container
diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index aeeacb164..070ef4434 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -168,6 +168,7 @@ public:
     template <typename T>
     void               AddVariable(const QString& name, T *var);
     void               RemoveVariable(const QString& name);
+    void               RemovePiece(quint32 id);
 
     void               UpdateGObject(quint32 id, VGObject* obj);
     void               UpdateDetail(quint32 id, const VDetail &detail);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index be6b1c712..6fa1fbb01 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -1140,6 +1140,23 @@ void VToolSeamAllowance::DeleteTool(bool ask)
         /* If UnionDetails tool delete detail no need emit FullParsing.*/
         connect(delDet, &DeletePiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
     }
+
+    // If UnionDetails tool delete the detail this object will be deleted only after full parse.
+    // Deleting inside UnionDetails cause crash.
+    // Because this object should be inactive from no one we disconnect all signals that may cause a crash
+    // KEEP THIS LIST ACTUALL!!!
+    disconnect(doc, 0, this, 0);
+    if (QGraphicsScene *toolScene = scene())
+    {
+        disconnect(toolScene, 0, this, 0);
+    }
+    disconnect(m_dataLabel, 0, this, 0);
+    disconnect(m_patternInfo, 0, this, 0);
+    disconnect(m_grainLine, 0, this, 0);
+    disconnect(m_sceneDetails, 0, this, 0);
+
+    hide();// User shouldn't see this object
+
     qApp->getUndoStack()->push(delDet);
 
     // Throw exception, this will help prevent case when we forget to immediately quit function.
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index 9cd040617..b5768ab8c 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -1194,6 +1194,9 @@ void CreateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, q
         SCASSERT(toolDet != nullptr);
         bool ask = false;
         toolDet->Remove(ask);
+        // We do not call full parse, so will need more to do more cleaning than usually
+        initData.doc->RemoveTool(id);
+        initData.data->RemovePiece(id);
     };
 
     if (not initData.retainPieces)

From 004c83a11f91cd20e0dcb7b4bd63e70518844569 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 14:01:51 +0200
Subject: [PATCH 171/208] After each reset label or grainline need to repaint
 piece image.

--HG--
branch : feature
---
 src/libs/vtools/tools/vgrainlineitem.cpp     | 5 +++++
 src/libs/vtools/tools/vtextgraphicsitem.cpp  | 5 +++++
 src/libs/vtools/tools/vtoolseamallowance.cpp | 6 ++++--
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/libs/vtools/tools/vgrainlineitem.cpp b/src/libs/vtools/tools/vgrainlineitem.cpp
index 4fea3b503..dfe1c5ff9 100644
--- a/src/libs/vtools/tools/vgrainlineitem.cpp
+++ b/src/libs/vtools/tools/vgrainlineitem.cpp
@@ -32,6 +32,7 @@
 #include <QGraphicsSceneMouseEvent>
 #include <QStyleOptionGraphicsItem>
 #include <QDebug>
+#include <QGraphicsScene>
 
 #include "../vmisc/def.h"
 #include "../vmisc/vmath.h"
@@ -230,6 +231,10 @@ QRectF VGrainlineItem::boundingRect() const
  */
 void VGrainlineItem::Reset()
 {
+    if (QGraphicsScene *toolScene = scene())
+    {
+        toolScene->clearSelection();
+    }
     m_bReleased = false;
     m_eMode = mNormal;
     setZValue(INACTIVE_Z);
diff --git a/src/libs/vtools/tools/vtextgraphicsitem.cpp b/src/libs/vtools/tools/vtextgraphicsitem.cpp
index d9b815266..63d1f834c 100644
--- a/src/libs/vtools/tools/vtextgraphicsitem.cpp
+++ b/src/libs/vtools/tools/vtextgraphicsitem.cpp
@@ -37,6 +37,7 @@
 #include <QPoint>
 #include <QStyleOptionGraphicsItem>
 #include <Qt>
+#include <QGraphicsScene>
 
 #include "../vmisc/def.h"
 #include "../vmisc/vmath.h"
@@ -201,6 +202,10 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
  */
 void VTextGraphicsItem::Reset()
 {
+    if (QGraphicsScene *toolScene = scene())
+    {
+        toolScene->clearSelection();
+    }
     m_eMode = mNormal;
     m_bReleased = false;
     Update();
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 6fa1fbb01..3800846ac 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -334,7 +334,7 @@ void VToolSeamAllowance::AllowSelecting(bool enabled)
 void VToolSeamAllowance::ResetChildren(QGraphicsItem *pItem)
 {
     const VPiece detail = VAbstractTool::data.GetPiece(id);
-    VTextGraphicsItem* pVGI = dynamic_cast<VTextGraphicsItem*>(pItem);
+    VTextGraphicsItem* pVGI = qgraphicsitem_cast<VTextGraphicsItem*>(pItem);
     if (pVGI != m_dataLabel)
     {
         if (detail.GetPatternPieceData().IsVisible())
@@ -349,7 +349,7 @@ void VToolSeamAllowance::ResetChildren(QGraphicsItem *pItem)
             m_patternInfo->Reset();
         }
     }
-    VGrainlineItem* pGLI = dynamic_cast<VGrainlineItem*>(pItem);
+    VGrainlineItem* pGLI = qgraphicsitem_cast<VGrainlineItem*>(pItem);
     if (pGLI != m_grainLine)
     {
         if (detail.GetGrainlineGeometry().IsVisible())
@@ -357,6 +357,8 @@ void VToolSeamAllowance::ResetChildren(QGraphicsItem *pItem)
             m_grainLine->Reset();
         }
     }
+
+    update();
 }
 
 //---------------------------------------------------------------------------------------------------------------------

From ac58338fc489111e968586281a710776cbcece0d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 15:17:16 +0200
Subject: [PATCH 172/208] Convert old tool union to format version 0.4.0.

--HG--
branch : feature
---
 src/libs/ifc/schema/pattern/v0.4.0.xsd |  76 ++++++++++++++---
 src/libs/ifc/xml/vpatternconverter.cpp | 114 ++++++++++++++++++++++++-
 src/libs/ifc/xml/vpatternconverter.h   |   3 +
 3 files changed, 178 insertions(+), 15 deletions(-)

diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index d8b2f8066..397e7b1eb 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -362,23 +362,75 @@
                                                                                    <xs:element name="det" minOccurs="2" maxOccurs="2">
                                                                                          <xs:complexType>
                                                                                                <xs:sequence>
-                                                                                                     <xs:element name="node" maxOccurs="unbounded">
-                                                                                                           <xs:complexType>
-                                                                                                                 <xs:attribute name="nodeType" type="xs:string"></xs:attribute>
-                                                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                                                 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
-                                                                                                           </xs:complexType>
-                                                                                                     </xs:element>
+																								     <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																												   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+																														   <xs:complexType>
+																																 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
+																																 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
+																																 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
+																																 <xs:attribute name="before" type="xs:double"></xs:attribute>
+																																 <xs:attribute name="after" type="xs:double"></xs:attribute>
+																																 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
+																														   </xs:complexType>
+																													 </xs:element>
+																												 </xs:sequence>
+																											 </xs:complexType>
+																										</xs:element>
+																										<xs:element name="csa" minOccurs="0" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																												   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+																														   <xs:complexType>
+																																 <xs:attribute name="start" type="xs:unsignedInt"></xs:attribute>
+																																 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
+																																 <xs:attribute name="end" type="xs:unsignedInt"></xs:attribute>
+																																 <xs:attribute name="reverse" type="xs:boolean"></xs:attribute>
+																																 <xs:attribute name="includeAs" type="piecePathIncludeType"></xs:attribute>
+																														   </xs:complexType>
+																													 </xs:element>
+																												 </xs:sequence>
+																											 </xs:complexType>
+																										</xs:element>
+																										<xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																												   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+																														   <xs:complexType>
+																																 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
+																														   </xs:complexType>
+																													 </xs:element>
+																												 </xs:sequence>
+																											 </xs:complexType>
+																										</xs:element>
                                                                                                </xs:sequence>
                                                                                          </xs:complexType>
                                                                                    </xs:element>
-                                                                                   <xs:element name="children" minOccurs="0" maxOccurs="1">
+                                                                                   <xs:element name="children" minOccurs="1" maxOccurs="1">
                                                                                          <xs:complexType>
                                                                                                <xs:sequence>
-                                                                                                     <xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
+																								     <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
+                                                                                                                </xs:sequence>
+																											 </xs:complexType>
+																									 </xs:element>
+																									 <xs:element name="csa" minOccurs="0" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
+                                                                                                                </xs:sequence>
+																											 </xs:complexType>
+																									 </xs:element>
+																									 <xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+																											<xs:complexType>
+																												<xs:sequence>
+																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
+                                                                                                                </xs:sequence>
+																											 </xs:complexType>
+																									 </xs:element>
                                                                                                </xs:sequence>
                                                                                          </xs:complexType>
                                                                                    </xs:element>
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index f17998f76..f9d936502 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -130,7 +130,8 @@ const QString strMy                        = QStringLiteral("my");
 const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
 const QString strInLayout                  = QStringLiteral("inLayout");
 const QString strSeamAllowance             = QStringLiteral("seamAllowance");
-const QString strTypeObject                = QStringLiteral("typeObject");
+const QString strNodeType                  = QStringLiteral("nodeType");
+const QString strDet                       = QStringLiteral("det");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)
@@ -590,6 +591,7 @@ void VPatternConverter::ToV0_4_0()
     SetVersion(QStringLiteral("0.4.0"));
     TagRemoveAttributeTypeObjectInV0_4_0();
     TagDetailToV0_4_0();
+    TagUnionDetailsToV0_4_0();
     Save();
 }
 
@@ -1714,9 +1716,9 @@ void VPatternConverter::TagRemoveAttributeTypeObjectInV0_4_0()
                 QDomElement domElement = domNode.toElement();
                 if (not domElement.isNull())
                 {
-                    if (domElement.hasAttribute(strTypeObject))
+                    if (domElement.hasAttribute(strNodeType))
                     {
-                        domElement.removeAttribute(strTypeObject);
+                        domElement.removeAttribute(strNodeType);
                     }
                 }
                 domNode = domNode.nextSibling();
@@ -1810,3 +1812,109 @@ void VPatternConverter::TagDetailToV0_4_0()
         }
     }
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VPatternConverter::GetUnionDetailNodesV0_4_0(const QDomElement &detail)
+{
+    QDomElement tagNodes = createElement(strNodes);
+
+    if (not detail.isNull())
+    {
+        const QDomNodeList childList = detail.childNodes();
+        for (qint32 i = 0; i < childList.size(); ++i)
+        {
+            const QDomElement node = childList.at(i).toElement();
+            if (not node.isNull())
+            {
+                QDomElement tagNode = createElement(strNode);
+
+                tagNode.setAttribute(strIdObject, node.attribute(strIdObject, NULL_ID_STR));
+
+                if (node.hasAttribute(strReverse))
+                {
+                    tagNode.setAttribute(strReverse, node.attribute(strReverse, "0"));
+                }
+
+                tagNode.setAttribute(strType, node.attribute(strType, ""));
+
+                tagNodes.appendChild(tagNode);
+            }
+        }
+    }
+
+    return tagNodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QDomElement VPatternConverter::GetUnionChildrenNodesV0_4_0(const QDomElement &detail)
+{
+    QDomElement tagNodes = createElement(strNodes);
+
+    if (not detail.isNull())
+    {
+        const QDomNodeList childList = detail.childNodes();
+        for (qint32 i = 0; i < childList.size(); ++i)
+        {
+            const QDomElement node = childList.at(i).toElement();
+            if (not node.isNull())
+            {
+                QDomElement tagNode = node.cloneNode().toElement();
+                tagNodes.appendChild(tagNode);
+            }
+        }
+    }
+
+    return tagNodes;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternConverter::TagUnionDetailsToV0_4_0()
+{
+    // TODO. Delete if minimal supported version is 0.4.0
+    Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
+                      "Time to refactor the code.");
+
+    const QDomNodeList list = elementsByTagName(strTools);
+    for (int i=0; i < list.size(); ++i)
+    {
+        // Tag 'tools' used only for union details, so no need to check any additional attributes
+        QDomElement toolDOM = list.at(i).toElement();
+        if (not toolDOM.isNull())
+        {
+            const QStringList tags = QStringList() << strDet << strChildren;
+
+            QVector<QDomElement> nodes;
+            QDomElement tagChildrenNodes = createElement(strChildren);
+
+            const QDomNodeList childList = toolDOM.childNodes();
+            for (qint32 i = 0; i < childList.size(); ++i)
+            {
+                const QDomElement element = childList.at(i).toElement();
+                if (not element.isNull())
+                {
+                    switch (tags.indexOf(element.tagName()))
+                    {
+                        case 0://strDet
+                            nodes.append(GetUnionDetailNodesV0_4_0(element));
+                            break;
+                        case 1://strChildren
+                            tagChildrenNodes.appendChild(GetUnionChildrenNodesV0_4_0(element));
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            RemoveAllChildren(toolDOM);
+
+            for (int i = 0; i < nodes.size(); ++i)
+            {
+                QDomElement tagDet = createElement(strDet);
+                tagDet.appendChild(nodes.at(i));
+                toolDOM.appendChild(tagDet);
+            }
+            toolDOM.appendChild(tagChildrenNodes);
+        }
+    }
+}
diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h
index 8b51c0d4a..3341fecaf 100644
--- a/src/libs/ifc/xml/vpatternconverter.h
+++ b/src/libs/ifc/xml/vpatternconverter.h
@@ -137,6 +137,9 @@ private:
 
     void TagRemoveAttributeTypeObjectInV0_4_0();
     void TagDetailToV0_4_0();
+    void TagUnionDetailsToV0_4_0();
+    QDomElement GetUnionDetailNodesV0_4_0(const QDomElement &detail);
+    QDomElement GetUnionChildrenNodesV0_4_0(const QDomElement &detail);
 };
 
 //---------------------------------------------------------------------------------------------------------------------

From 6ee0c42d53890610121b2c384d96d2b42e3382cd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 18 Jan 2017 15:20:42 +0200
Subject: [PATCH 173/208] Used command "xmllint --format" to format files.

--HG--
branch : feature
---
 .../schema/individual_measurements/v0.3.3.xsd |  138 +-
 src/libs/ifc/schema/pattern/v0.4.0.xsd        | 1606 +++++++++--------
 .../schema/standard_measurements/v0.4.3.xsd   |  314 ++--
 3 files changed, 1040 insertions(+), 1018 deletions(-)

diff --git a/src/libs/ifc/schema/individual_measurements/v0.3.3.xsd b/src/libs/ifc/schema/individual_measurements/v0.3.3.xsd
index 489ebd973..044a44471 100644
--- a/src/libs/ifc/schema/individual_measurements/v0.3.3.xsd
+++ b/src/libs/ifc/schema/individual_measurements/v0.3.3.xsd
@@ -1,72 +1,72 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
-	<xs:element name="vit">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element name="version" type="formatVersion"></xs:element>
-				<xs:element name="read-only" type="xs:boolean"></xs:element>
-				<xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-				<xs:element name="unit" type="units"></xs:element>
-				<xs:element name="pm_system" type="psCode"></xs:element>
-				<xs:element name="personal">
-					<xs:complexType>
-						<xs:sequence>
-							<xs:element name="family-name" type="xs:string"></xs:element>
-							<xs:element name="given-name" type="xs:string"></xs:element>
-							<xs:element name="birth-date" type="xs:date"></xs:element>
-							<xs:element name="gender" type="gender"></xs:element>
-							<xs:element name="email" type="xs:string"></xs:element>
-					   </xs:sequence>
-					</xs:complexType>
-				</xs:element>
-				<xs:element name="body-measurements">
-					<xs:complexType>
-						<xs:sequence>
-							<xs:element name="m" minOccurs="0" maxOccurs="unbounded">
-								<xs:complexType>
-									<xs:attribute name="name" type="shortName" use="required"></xs:attribute>
-									<xs:attribute name="value" type="xs:string" use="required"></xs:attribute>
-									<xs:attribute name="full_name" type="xs:string"></xs:attribute>
-									<xs:attribute name="description" type="xs:string"></xs:attribute>
-								</xs:complexType>
-							</xs:element>
-						</xs:sequence>
-					</xs:complexType>
-				</xs:element>
-			</xs:sequence>
-		</xs:complexType>
-		<xs:unique name="measurementName">
-			<xs:selector xpath="body-measurements/m"/>
-			<xs:field xpath="@name"/>
-		</xs:unique>
-	</xs:element>
-	<xs:simpleType name="shortName">
-		<xs:restriction base="xs:string">   
-			<xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
-		</xs:restriction>
-	</xs:simpleType>
-	<xs:simpleType name="formatVersion">
-		<xs:restriction base="xs:string">
-			<xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
-		</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="gender">
-		<xs:restriction base="xs:string">
-			<xs:enumeration value="unknown"/>
-			<xs:enumeration value="male"/>
-			<xs:enumeration value="female"/>
-		</xs:restriction>
-	</xs:simpleType>
-	<xs:simpleType name="psCode">
-		<xs:restriction base="xs:string">
-			<xs:pattern value="^^(([0-9]|[1-4][0-9]|5[0-4])|998)$"/>
-		</xs:restriction>
-	</xs:simpleType>
+  <xs:element name="vit">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="version" type="formatVersion"/>
+        <xs:element name="read-only" type="xs:boolean"/>
+        <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="unit" type="units"/>
+        <xs:element name="pm_system" type="psCode"/>
+        <xs:element name="personal">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="family-name" type="xs:string"/>
+              <xs:element name="given-name" type="xs:string"/>
+              <xs:element name="birth-date" type="xs:date"/>
+              <xs:element name="gender" type="gender"/>
+              <xs:element name="email" type="xs:string"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="body-measurements">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="m" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="name" type="shortName" use="required"/>
+                  <xs:attribute name="value" type="xs:string" use="required"/>
+                  <xs:attribute name="full_name" type="xs:string"/>
+                  <xs:attribute name="description" type="xs:string"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+    </xs:complexType>
+    <xs:unique name="measurementName">
+      <xs:selector xpath="body-measurements/m"/>
+      <xs:field xpath="@name"/>
+    </xs:unique>
+  </xs:element>
+  <xs:simpleType name="shortName">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="formatVersion">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
+    </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="gender">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="unknown"/>
+      <xs:enumeration value="male"/>
+      <xs:enumeration value="female"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="psCode">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^^(([0-9]|[1-4][0-9]|5[0-4])|998)$"/>
+    </xs:restriction>
+  </xs:simpleType>
 </xs:schema>
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index 397e7b1eb..fd1f4d635 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -1,795 +1,817 @@
 <?xml version="1.0" encoding="UTF-8"?>
-   <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
-         <!-- XML Schema Generated from XML Document-->
-         <xs:element name="pattern">
-               <xs:complexType>
-                     <xs:sequence minOccurs="1" maxOccurs="unbounded">
-                            <xs:element name="version" type="formatVersion"></xs:element>
-                            <xs:element name="unit" type="units"></xs:element>
-                            <xs:element name="image" minOccurs="0" maxOccurs="1">
-                                <xs:complexType>
-                                 <xs:simpleContent>
-                                    <xs:extension base="xs:string">
-                                       <xs:attribute name="extension" type="imageExtension"></xs:attribute>
-                                    </xs:extension>
-                                 </xs:simpleContent>
-                                </xs:complexType>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+  <!-- XML Schema Generated from XML Document-->
+  <xs:element name="pattern">
+    <xs:complexType>
+      <xs:sequence minOccurs="1" maxOccurs="unbounded">
+        <xs:element name="version" type="formatVersion"/>
+        <xs:element name="unit" type="units"/>
+        <xs:element name="image" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:simpleContent>
+              <xs:extension base="xs:string">
+                <xs:attribute name="extension" type="imageExtension"/>
+              </xs:extension>
+            </xs:simpleContent>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="author" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="gradation" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="heights">
+                <xs:complexType>
+                  <xs:attribute name="all" type="xs:boolean" use="required"/>
+                  <xs:attribute name="h50" type="xs:boolean"/>
+                  <xs:attribute name="h56" type="xs:boolean"/>
+                  <xs:attribute name="h62" type="xs:boolean"/>
+                  <xs:attribute name="h68" type="xs:boolean"/>
+                  <xs:attribute name="h74" type="xs:boolean"/>
+                  <xs:attribute name="h80" type="xs:boolean"/>
+                  <xs:attribute name="h86" type="xs:boolean"/>
+                  <xs:attribute name="h92" type="xs:boolean"/>
+                  <xs:attribute name="h98" type="xs:boolean"/>
+                  <xs:attribute name="h104" type="xs:boolean"/>
+                  <xs:attribute name="h110" type="xs:boolean"/>
+                  <xs:attribute name="h116" type="xs:boolean"/>
+                  <xs:attribute name="h122" type="xs:boolean"/>
+                  <xs:attribute name="h128" type="xs:boolean"/>
+                  <xs:attribute name="h134" type="xs:boolean"/>
+                  <xs:attribute name="h140" type="xs:boolean"/>
+                  <xs:attribute name="h146" type="xs:boolean"/>
+                  <xs:attribute name="h152" type="xs:boolean"/>
+                  <xs:attribute name="h158" type="xs:boolean"/>
+                  <xs:attribute name="h164" type="xs:boolean"/>
+                  <xs:attribute name="h170" type="xs:boolean"/>
+                  <xs:attribute name="h176" type="xs:boolean"/>
+                  <xs:attribute name="h182" type="xs:boolean"/>
+                  <xs:attribute name="h188" type="xs:boolean"/>
+                  <xs:attribute name="h194" type="xs:boolean"/>
+                </xs:complexType>
+              </xs:element>
+              <xs:element name="sizes">
+                <xs:complexType>
+                  <xs:attribute name="all" type="xs:boolean" use="required"/>
+                  <xs:attribute name="s22" type="xs:boolean"/>
+                  <xs:attribute name="s24" type="xs:boolean"/>
+                  <xs:attribute name="s26" type="xs:boolean"/>
+                  <xs:attribute name="s28" type="xs:boolean"/>
+                  <xs:attribute name="s30" type="xs:boolean"/>
+                  <xs:attribute name="s32" type="xs:boolean"/>
+                  <xs:attribute name="s34" type="xs:boolean"/>
+                  <xs:attribute name="s36" type="xs:boolean"/>
+                  <xs:attribute name="s38" type="xs:boolean"/>
+                  <xs:attribute name="s40" type="xs:boolean"/>
+                  <xs:attribute name="s42" type="xs:boolean"/>
+                  <xs:attribute name="s44" type="xs:boolean"/>
+                  <xs:attribute name="s46" type="xs:boolean"/>
+                  <xs:attribute name="s48" type="xs:boolean"/>
+                  <xs:attribute name="s50" type="xs:boolean"/>
+                  <xs:attribute name="s52" type="xs:boolean"/>
+                  <xs:attribute name="s54" type="xs:boolean"/>
+                  <xs:attribute name="s56" type="xs:boolean"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+            <xs:attribute name="custom" type="xs:boolean"/>
+            <xs:attribute name="defHeight" type="baseHeight"/>
+            <xs:attribute name="defSize" type="baseSize"/>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="patternName" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="patternNumber" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="company" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="customer" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="size" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="showDate" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="showMeasurements" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="measurements" type="xs:string"/>
+        <xs:element name="increments" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence minOccurs="0" maxOccurs="unbounded">
+              <xs:element name="increment" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="description" type="xs:string" use="required"/>
+                  <xs:attribute name="name" type="shortName" use="required"/>
+                  <xs:attribute name="formula" type="xs:string" use="required"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+          <xs:unique name="incrementName">
+            <xs:selector xpath="increment"/>
+            <xs:field xpath="@name"/>
+          </xs:unique>
+        </xs:element>
+        <xs:element name="draw" minOccurs="1" maxOccurs="unbounded">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="calculation" minOccurs="1" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                      <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="x" type="xs:double"/>
+                          <xs:attribute name="y" type="xs:double"/>
+                          <xs:attribute name="mx" type="xs:double"/>
+                          <xs:attribute name="my" type="xs:double"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="name" type="shortName"/>
+                          <xs:attribute name="firstPoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="secondPoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="thirdPoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="basePoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="pShoulder" type="xs:unsignedInt"/>
+                          <xs:attribute name="p1Line" type="xs:unsignedInt"/>
+                          <xs:attribute name="p2Line" type="xs:unsignedInt"/>
+                          <xs:attribute name="length" type="xs:string"/>
+                          <xs:attribute name="angle" type="xs:string"/>
+                          <xs:attribute name="typeLine" type="xs:string"/>
+                          <xs:attribute name="splinePath" type="xs:unsignedInt"/>
+                          <xs:attribute name="spline" type="xs:unsignedInt"/>
+                          <xs:attribute name="p1Line1" type="xs:unsignedInt"/>
+                          <xs:attribute name="p1Line2" type="xs:unsignedInt"/>
+                          <xs:attribute name="p2Line1" type="xs:unsignedInt"/>
+                          <xs:attribute name="p2Line2" type="xs:unsignedInt"/>
+                          <xs:attribute name="center" type="xs:unsignedInt"/>
+                          <xs:attribute name="radius" type="xs:string"/>
+                          <xs:attribute name="axisP1" type="xs:unsignedInt"/>
+                          <xs:attribute name="axisP2" type="xs:unsignedInt"/>
+                          <xs:attribute name="arc" type="xs:unsignedInt"/>
+                          <xs:attribute name="elArc" type="xs:unsignedInt"/>
+                          <xs:attribute name="curve" type="xs:unsignedInt"/>
+                          <xs:attribute name="curve1" type="xs:unsignedInt"/>
+                          <xs:attribute name="curve2" type="xs:unsignedInt"/>
+                          <xs:attribute name="lineColor" type="colors"/>
+                          <xs:attribute name="color" type="colors"/>
+                          <xs:attribute name="firstArc" type="xs:unsignedInt"/>
+                          <xs:attribute name="secondArc" type="xs:unsignedInt"/>
+                          <xs:attribute name="crossPoint" type="crossType"/>
+                          <xs:attribute name="vCrossPoint" type="crossType"/>
+                          <xs:attribute name="hCrossPoint" type="crossType"/>
+                          <xs:attribute name="c1Center" type="xs:unsignedInt"/>
+                          <xs:attribute name="c2Center" type="xs:unsignedInt"/>
+                          <xs:attribute name="c1Radius" type="xs:string"/>
+                          <xs:attribute name="c2Radius" type="xs:string"/>
+                          <xs:attribute name="cRadius" type="xs:string"/>
+                          <xs:attribute name="tangent" type="xs:unsignedInt"/>
+                          <xs:attribute name="cCenter" type="xs:unsignedInt"/>
+                          <xs:attribute name="name1" type="shortName"/>
+                          <xs:attribute name="mx1" type="xs:double"/>
+                          <xs:attribute name="my1" type="xs:double"/>
+                          <xs:attribute name="name2" type="shortName"/>
+                          <xs:attribute name="mx2" type="xs:double"/>
+                          <xs:attribute name="my2" type="xs:double"/>
+                          <xs:attribute name="point1" type="xs:unsignedInt"/>
+                          <xs:attribute name="point2" type="xs:unsignedInt"/>
+                          <xs:attribute name="dartP1" type="xs:unsignedInt"/>
+                          <xs:attribute name="dartP2" type="xs:unsignedInt"/>
+                          <xs:attribute name="dartP3" type="xs:unsignedInt"/>
+                          <xs:attribute name="baseLineP1" type="xs:unsignedInt"/>
+                          <xs:attribute name="baseLineP2" type="xs:unsignedInt"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="line" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="firstPoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="secondPoint" type="xs:unsignedInt"/>
+                          <xs:attribute name="typeLine" type="xs:string"/>
+                          <xs:attribute name="lineColor" type="colors"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="operation" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:sequence>
+                            <xs:element name="source" minOccurs="1" maxOccurs="1">
+                              <xs:complexType>
+                                <xs:sequence>
+                                  <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
+                                    <xs:complexType>
+                                      <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
+                                    </xs:complexType>
+                                  </xs:element>
+                                </xs:sequence>
+                              </xs:complexType>
                             </xs:element>
-                            <xs:element name="author" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="gradation" minOccurs="0" maxOccurs="1">
-                                <xs:complexType>
-                                       <xs:sequence>
-                                             <xs:element name="heights">
-                                                   <xs:complexType>
-                                                         <xs:attribute name="all" type="xs:boolean" use="required"></xs:attribute>
-                                                         <xs:attribute name="h50" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h56" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h62" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h68" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h74" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h80" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h86" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h92" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h98" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h104" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h110" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h116" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h122" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h128" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h134" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h140" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h146" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h152" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h158" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h164" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h170" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h176" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h182" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h188" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="h194" type="xs:boolean"></xs:attribute>       
-                                                   </xs:complexType>
-                                             </xs:element>
-                                             <xs:element name="sizes">
-                                                   <xs:complexType>
-                                                         <xs:attribute name="all" type="xs:boolean" use="required"></xs:attribute>
-                                                         <xs:attribute name="s22" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s24" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s26" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s28" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s30" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s32" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s34" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s36" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s38" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s40" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s42" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s44" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s46" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s48" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s50" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s52" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s54" type="xs:boolean"></xs:attribute>
-                                                         <xs:attribute name="s56" type="xs:boolean"></xs:attribute>    
-                                                   </xs:complexType>
-                                             </xs:element>
-                                       </xs:sequence>
-                                       <xs:attribute name="custom" type="xs:boolean"></xs:attribute>
-                                       <xs:attribute name="defHeight" type="baseHeight"></xs:attribute>
-                                       <xs:attribute name="defSize" type="baseSize"></xs:attribute>
-                                 </xs:complexType>
+                            <xs:element name="destination" minOccurs="1" maxOccurs="1">
+                              <xs:complexType>
+                                <xs:sequence>
+                                  <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
+                                    <xs:complexType>
+                                      <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
+                                      <xs:attribute name="mx" type="xs:double"/>
+                                      <xs:attribute name="my" type="xs:double"/>
+                                    </xs:complexType>
+                                  </xs:element>
+                                </xs:sequence>
+                              </xs:complexType>
                             </xs:element>
-                            <xs:element name="patternName" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="patternNumber" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="company" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="customer" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="size" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="showDate" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
-                            <xs:element name="showMeasurements" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
-                           <xs:element name="measurements" type="xs:string"></xs:element>
-                           <xs:element name="increments" minOccurs="0" maxOccurs="1">
-                                 <xs:complexType>
-                                       <xs:sequence minOccurs="0" maxOccurs="unbounded">
-                                             <xs:element name="increment" minOccurs="0" maxOccurs="unbounded">
-                                                   <xs:complexType>
-                                                         <xs:attribute name="description" type="xs:string" use="required"></xs:attribute>
-                                                         <xs:attribute name="name" type="shortName" use="required"></xs:attribute>
-                                                         <xs:attribute name="formula" type="xs:string" use="required"></xs:attribute>      
-                                                   </xs:complexType>
-                                             </xs:element>
-                                       </xs:sequence>
-                                 </xs:complexType>
-                                 <xs:unique name="incrementName">
-                                    <xs:selector xpath="increment"/>
-                                    <xs:field xpath="@name"/>
-                                 </xs:unique>
-                           </xs:element>
-                           <xs:element name="draw" minOccurs="1" maxOccurs="unbounded">
-                                 <xs:complexType>
-                                       <xs:sequence>
-                                             <xs:element name="calculation" minOccurs="1" maxOccurs="unbounded">
-                                                   <xs:complexType>
-                                                         <xs:sequence>
-                                                               <xs:choice minOccurs="0" maxOccurs="unbounded">   
-                                                                     <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="x" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="y" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="name" type="shortName"></xs:attribute>
-                                                                                 <xs:attribute name="firstPoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="secondPoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="thirdPoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="basePoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="pShoulder" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p1Line" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p2Line" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="angle" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="splinePath" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="spline" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p1Line1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p1Line2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p2Line1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p2Line2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="radius" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="axisP1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="axisP2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="arc" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="elArc" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="curve" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="curve1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="curve2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="lineColor" type="colors"></xs:attribute>
-                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
-                                                                                 <xs:attribute name="firstArc" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="secondArc" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="crossPoint" type="crossType"></xs:attribute>
-                                                                                 <xs:attribute name="vCrossPoint" type="crossType"></xs:attribute>
-                                                                                 <xs:attribute name="hCrossPoint" type="crossType"></xs:attribute>
-                                                                                 <xs:attribute name="c1Center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="c2Center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="c1Radius" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="c2Radius" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="cRadius" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="tangent" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="cCenter" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="name1" type="shortName"></xs:attribute>
-                                                                                 <xs:attribute name="mx1" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="my1" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="name2" type="shortName"></xs:attribute>
-                                                                                 <xs:attribute name="mx2" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="my2" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="point1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="point2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="dartP1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="dartP2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="dartP3" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="baseLineP1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="baseLineP2" type="xs:unsignedInt"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>                                                              
-                                                                     <xs:element name="line" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="firstPoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="secondPoint" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="lineColor" type="colors"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element> 
-                                                                     <xs:element name="operation" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-																			     <xs:sequence>
-                                                                                       <xs:element name="source" minOccurs="1" maxOccurs="1">
-                                                                                             <xs:complexType>
-																								   <xs:sequence>
-																									   <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
-																											 <xs:complexType>
-																												<xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
-																											 </xs:complexType>
-																									   </xs:element>
-																								   </xs:sequence>	   
-                                                                                             </xs:complexType>
-                                                                                       </xs:element>
-                                                                                       <xs:element name="destination" minOccurs="1" maxOccurs="1">
-                                                                                             <xs:complexType>
-																								   <xs:sequence>
-																									   <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
-																											 <xs:complexType>
-																												<xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                                                <xs:attribute name="mx" type="xs:double"></xs:attribute>
-																								                <xs:attribute name="my" type="xs:double"></xs:attribute>
-																											 </xs:complexType>
-																									   </xs:element>
-																								   </xs:sequence>
-                                                                                             </xs:complexType>
-                                                                                       </xs:element>
-                                                                                 </xs:sequence>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="angle" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="suffix" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="p1Line" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="p2Line" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="axisType" type="axisType"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element> 
-                                                                     <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="angle1" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="angle2" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="radius" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
-                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="elArc" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="angle1" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="angle2" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="rotationAngle" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="radius1" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="radius2" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="center" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
-                                                                                 <xs:attribute name="length" type="xs:string"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:sequence>
-                                                                                       <xs:element name="pathPoint" minOccurs="0" maxOccurs="unbounded">
-                                                                                             <xs:complexType>
-                                                                                                   <xs:attribute name="kAsm2" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="pSpline" type="xs:unsignedInt"></xs:attribute>
-                                                                                                   <xs:attribute name="angle" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="angle1" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="angle2" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="length1" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="length2" type="xs:string"></xs:attribute>
-                                                                                                   <xs:attribute name="kAsm1" type="xs:string"></xs:attribute>
-                                                                                             </xs:complexType>
-                                                                                       </xs:element>
-                                                                                 </xs:sequence>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="kCurve" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="kAsm1" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="kAsm2" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="angle1" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="angle2" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="length1" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="length2" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="point1" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="point2" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="point3" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="point4" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="color" type="colors"></xs:attribute>
-                                                                                 <xs:attribute name="duplicate" type="xs:unsignedInt"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                               </xs:choice>
-                                                         </xs:sequence>
-                                                   </xs:complexType>
-                                             </xs:element>
-                                             <xs:element name="modeling" minOccurs="1" maxOccurs="unbounded">
-                                                   <xs:complexType>
-                                                         <xs:sequence>
-                                                               <xs:choice minOccurs="0" maxOccurs="unbounded">
-                                                                     <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="elArc" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="idObject" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="path" minOccurs="0" maxOccurs="unbounded">
-                                                                           <xs:complexType>
-																			   <xs:sequence>
-																				<xs:element name="nodes" minOccurs="1" maxOccurs="1">
-																					<xs:complexType>
-																						<xs:sequence>
-																						   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
-																								   <xs:complexType>
-																										 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
-																										 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
-																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
-																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
-																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
-																										 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
-																								   </xs:complexType>
-																							 </xs:element>
-																						 </xs:sequence>
-																					 </xs:complexType>
-																				</xs:element>
-																				</xs:sequence>
-                                                                                 <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                                 <xs:attribute name="type" type="piecePathType"></xs:attribute>
-                                                                                 <xs:attribute name="idTool" type="xs:unsignedInt"></xs:attribute>
-                                                                                 <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                                 <xs:attribute name="name" type="xs:string"></xs:attribute>
-                                                                                 <xs:attribute name="typeLine" type="xs:string"></xs:attribute>
-                                                                           </xs:complexType>
-                                                                     </xs:element>
-                                                                     <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">
-                                                                       <xs:complexType>
-                                                                             <xs:sequence>
-                                                                                   <xs:element name="det" minOccurs="2" maxOccurs="2">
-                                                                                         <xs:complexType>
-                                                                                               <xs:sequence>
-																								     <xs:element name="nodes" minOccurs="1" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																												   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
-																														   <xs:complexType>
-																																 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
-																																 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
-																																 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
-																																 <xs:attribute name="before" type="xs:double"></xs:attribute>
-																																 <xs:attribute name="after" type="xs:double"></xs:attribute>
-																																 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
-																														   </xs:complexType>
-																													 </xs:element>
-																												 </xs:sequence>
-																											 </xs:complexType>
-																										</xs:element>
-																										<xs:element name="csa" minOccurs="0" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																												   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
-																														   <xs:complexType>
-																																 <xs:attribute name="start" type="xs:unsignedInt"></xs:attribute>
-																																 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
-																																 <xs:attribute name="end" type="xs:unsignedInt"></xs:attribute>
-																																 <xs:attribute name="reverse" type="xs:boolean"></xs:attribute>
-																																 <xs:attribute name="includeAs" type="piecePathIncludeType"></xs:attribute>
-																														   </xs:complexType>
-																													 </xs:element>
-																												 </xs:sequence>
-																											 </xs:complexType>
-																										</xs:element>
-																										<xs:element name="iPaths" minOccurs="0" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																												   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
-																														   <xs:complexType>
-																																 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
-																														   </xs:complexType>
-																													 </xs:element>
-																												 </xs:sequence>
-																											 </xs:complexType>
-																										</xs:element>
-                                                                                               </xs:sequence>
-                                                                                         </xs:complexType>
-                                                                                   </xs:element>
-                                                                                   <xs:element name="children" minOccurs="1" maxOccurs="1">
-                                                                                         <xs:complexType>
-                                                                                               <xs:sequence>
-																								     <xs:element name="nodes" minOccurs="1" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
-                                                                                                                </xs:sequence>
-																											 </xs:complexType>
-																									 </xs:element>
-																									 <xs:element name="csa" minOccurs="0" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
-                                                                                                                </xs:sequence>
-																											 </xs:complexType>
-																									 </xs:element>
-																									 <xs:element name="iPaths" minOccurs="0" maxOccurs="1">
-																											<xs:complexType>
-																												<xs:sequence>
-																													<xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"></xs:element>
-                                                                                                                </xs:sequence>
-																											 </xs:complexType>
-																									 </xs:element>
-                                                                                               </xs:sequence>
-                                                                                         </xs:complexType>
-                                                                                   </xs:element>
-                                                                             </xs:sequence>
-                                                                             <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                             <xs:attribute name="type" type="xs:string"></xs:attribute>
-                                                                             <xs:attribute name="indexD1" type="xs:unsignedInt"></xs:attribute>
-                                                                             <xs:attribute name="indexD2" type="xs:unsignedInt"></xs:attribute>
-                                                                             <xs:attribute name="inUse" type="xs:boolean"></xs:attribute>
-                                                                       </xs:complexType>
-                                                                    </xs:element>
-                                                               </xs:choice>           
-                                                         </xs:sequence>
-                                                   </xs:complexType>
-                                             </xs:element>
-                                             <xs:element name="details" minOccurs="1" maxOccurs="unbounded">
-                                                   <xs:complexType>
-                                                         <xs:sequence>
-                                                               <xs:element name="detail" minOccurs="0" maxOccurs="unbounded">
-                                                                     <xs:complexType>
-                                                                           <xs:sequence>
-                                                                               <xs:element name="data" minOccurs="0" maxOccurs="1">
-                                                                                   <xs:complexType>
-                                                                                       <xs:sequence>
-                                                                                           <xs:element name="mcp" minOccurs="0" maxOccurs="unbounded">
-                                                                                               <xs:complexType>
-                                                                                                   <xs:attribute name="cutNumber" type="xs:unsignedInt"/>
-                                                                                                   <xs:attribute name="userDef" type="xs:string"/>
-                                                                                                   <xs:attribute name="material" type="materialType"/>
-                                                                                                   <xs:attribute name="placement" type="placementType"/>
-                                                                                               </xs:complexType>
-                                                                                           </xs:element>
-                                                                                       </xs:sequence>
-                                                                                       <xs:attribute name="letter" type="xs:string"></xs:attribute>
-                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
-                                                                                       <xs:attribute name="fontSize" type="xs:unsignedInt"></xs:attribute>
-                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="width" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="height" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="rotation" type="xs:double"></xs:attribute>
-                                                                                   </xs:complexType>
-                                                                               </xs:element>
-                                                                               <xs:element name="patternInfo" minOccurs="0" maxOccurs="1">
-                                                                                   <xs:complexType>
-                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
-                                                                                       <xs:attribute name="fontSize" type="xs:unsignedInt"></xs:attribute>
-                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="width" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="height" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="rotation" type="xs:double"></xs:attribute>
-                                                                                   </xs:complexType>
-                                                                               </xs:element>
-                                                                               <xs:element name="grainline" minOccurs="0" maxOccurs="1">
-                                                                                   <xs:complexType>
-                                                                                       <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
-                                                                                       <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                                       <xs:attribute name="length" type="xs:string"></xs:attribute>
-                                                                                       <xs:attribute name="rotation" type="xs:string"></xs:attribute>
-                                                                                       <xs:attribute name="arrows" type="arrowType"></xs:attribute>
-                                                                                    </xs:complexType>
-                                                                               </xs:element>
-                                                                               <xs:element name="nodes" minOccurs="1" maxOccurs="1">
-																					<xs:complexType>
-																						<xs:sequence>
-																						   <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
-																								   <xs:complexType>
-																										 <xs:attribute name="type" type="xs:string" use="required"></xs:attribute>
-																										 <xs:attribute name="idObject" type="xs:unsignedInt" use="required"></xs:attribute>
-																										 <xs:attribute name="reverse" type="xs:unsignedInt"></xs:attribute>
-																										 <xs:attribute name="before" type="xs:double"></xs:attribute>
-																										 <xs:attribute name="after" type="xs:double"></xs:attribute>
-																										 <xs:attribute name="angle" type="nodeAngle"></xs:attribute>
-																										 <xs:attribute name="mx" type="xs:double"></xs:attribute>
-																										 <xs:attribute name="my" type="xs:double"></xs:attribute>
-																								   </xs:complexType>
-																							 </xs:element>
-																						 </xs:sequence>
-																					 </xs:complexType>
-																				</xs:element>
-																				<xs:element name="csa" minOccurs="0" maxOccurs="1">
-																					<xs:complexType>
-																						<xs:sequence>
-																						   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
-																								   <xs:complexType>
-																										 <xs:attribute name="start" type="xs:unsignedInt"></xs:attribute>
-																										 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
-																										 <xs:attribute name="end" type="xs:unsignedInt"></xs:attribute>
-																										 <xs:attribute name="reverse" type="xs:boolean"></xs:attribute>
-																										 <xs:attribute name="includeAs" type="piecePathIncludeType"></xs:attribute>
-																								   </xs:complexType>
-																							 </xs:element>
-																						 </xs:sequence>
-																					 </xs:complexType>
-																				</xs:element>
-																				<xs:element name="iPaths" minOccurs="0" maxOccurs="1">
-																					<xs:complexType>
-																						<xs:sequence>
-																						   <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
-																								   <xs:complexType>
-																										 <xs:attribute name="path" type="xs:unsignedInt" use="required"></xs:attribute>
-																								   </xs:complexType>
-																							 </xs:element>
-																						 </xs:sequence>
-																					 </xs:complexType>
-																				</xs:element>
-                                                                           </xs:sequence>
-                                                                           <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                           <xs:attribute name="version" type="pieceVersion"></xs:attribute>
-                                                                           <xs:attribute name="mx" type="xs:double"></xs:attribute>
-                                                                           <xs:attribute name="my" type="xs:double"></xs:attribute>
-                                                                           <xs:attribute name="name" type="xs:string"></xs:attribute>
-                                                                           <xs:attribute name="inLayout" type="xs:boolean"></xs:attribute>
-                                                                           <xs:attribute name="forbidFlipping" type="xs:boolean"></xs:attribute>
-                                                                           <xs:attribute name="width" type="xs:double"></xs:attribute>
-                                                                           <xs:attribute name="seamAllowance" type="xs:boolean"></xs:attribute>
-                                                                           <xs:attribute name="united" type="xs:boolean"></xs:attribute>
-                                                                           <xs:attribute name="closed" type="xs:unsignedInt"></xs:attribute>
-                                                                     </xs:complexType>
-                                                               </xs:element>
-                                                         </xs:sequence>
-                                                   </xs:complexType>
-                                             </xs:element>
-                                             <xs:element name="groups" minOccurs="0" maxOccurs="1">
-                                                   <xs:complexType>
-                                                         <xs:sequence>
-                                                               <xs:element name="group" minOccurs="0" maxOccurs="unbounded">
-                                                                     <xs:complexType>
-                                                                           <xs:sequence>
-                                                                                 <xs:element name="item" maxOccurs="unbounded">
-                                                                                       <xs:complexType>
-                                                                                             <xs:attribute name="object" type="xs:unsignedInt"></xs:attribute>
-                                                                                             <xs:attribute name="tool" type="xs:unsignedInt"></xs:attribute>
-                                                                                       </xs:complexType>
-                                                                                 </xs:element>
-                                                                           </xs:sequence>
-                                                                           <xs:attribute name="id" type="xs:unsignedInt" use="required"></xs:attribute>
-                                                                           <xs:attribute name="name" type="xs:string"></xs:attribute>
-                                                                           <xs:attribute name="visible" type="xs:boolean"></xs:attribute>
-                                                                     </xs:complexType>
-                                                               </xs:element>
-                                                         </xs:sequence>
-                                                   </xs:complexType>
-                                             </xs:element>
-                                       </xs:sequence>
-                                       <xs:attribute name="name" type="xs:string"></xs:attribute>
-                                 </xs:complexType>
-                           </xs:element>
-                     </xs:sequence>
-					 <xs:attribute name="readOnly" type="xs:boolean"></xs:attribute>
-               </xs:complexType>
-         </xs:element>
-    <xs:simpleType name="shortName">
-        <xs:restriction base="xs:string">   
-            <xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
-        </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="measurementsTypes">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="standard"/>
-            <xs:enumeration value="individual"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="formatVersion">
-        <xs:restriction base="xs:string">
-            <xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
-        </xs:restriction>
-    </xs:simpleType>
-     <xs:simpleType name="imageExtension">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="PNG"/>
-            <xs:enumeration value="JPG"/>
-            <xs:enumeration value="BMP"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="colors">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="black"/>
-            <xs:enumeration value="green"/>
-            <xs:enumeration value="blue"/>
-            <xs:enumeration value="darkRed"/>
-            <xs:enumeration value="darkGreen"/>
-            <xs:enumeration value="darkBlue"/>
-            <xs:enumeration value="yellow"/>
-            <xs:enumeration value="lightsalmon"/>
-            <xs:enumeration value="goldenrod"/>
-            <xs:enumeration value="orange"/>
-            <xs:enumeration value="deeppink"/>
-            <xs:enumeration value="violet"/>
-            <xs:enumeration value="darkviolet"/>
-            <xs:enumeration value="mediumseagreen"/>
-            <xs:enumeration value="lime"/>
-            <xs:enumeration value="deepskyblue"/>
-            <xs:enumeration value="cornflowerblue"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="baseHeight">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="50"/>
-            <xs:enumeration value="56"/>
-            <xs:enumeration value="62"/>
-            <xs:enumeration value="68"/>
-            <xs:enumeration value="74"/>
-            <xs:enumeration value="80"/>
-            <xs:enumeration value="86"/>
-            <xs:enumeration value="92"/>
-            <xs:enumeration value="98"/>
-            <xs:enumeration value="104"/>
-            <xs:enumeration value="110"/>
-            <xs:enumeration value="116"/>
-            <xs:enumeration value="122"/>
-            <xs:enumeration value="128"/>
-            <xs:enumeration value="134"/>
-            <xs:enumeration value="140"/>
-            <xs:enumeration value="146"/>
-            <xs:enumeration value="152"/>
-            <xs:enumeration value="158"/>
-            <xs:enumeration value="164"/>
-            <xs:enumeration value="170"/>
-            <xs:enumeration value="176"/>
-            <xs:enumeration value="182"/>
-            <xs:enumeration value="188"/>
-            <xs:enumeration value="194"/>
-            <xs:enumeration value="500"/>
-            <xs:enumeration value="560"/>
-            <xs:enumeration value="620"/>
-            <xs:enumeration value="680"/>
-            <xs:enumeration value="740"/>
-            <xs:enumeration value="800"/>
-            <xs:enumeration value="860"/>
-            <xs:enumeration value="920"/>
-            <xs:enumeration value="980"/>
-            <xs:enumeration value="1040"/>
-            <xs:enumeration value="1100"/>
-            <xs:enumeration value="1160"/>
-            <xs:enumeration value="1220"/>
-            <xs:enumeration value="1280"/>
-            <xs:enumeration value="1340"/>
-            <xs:enumeration value="1400"/>
-            <xs:enumeration value="1460"/>
-            <xs:enumeration value="1520"/>
-            <xs:enumeration value="1580"/>
-            <xs:enumeration value="1640"/>
-            <xs:enumeration value="1700"/>
-            <xs:enumeration value="1760"/>
-            <xs:enumeration value="1820"/>
-            <xs:enumeration value="1880"/>
-            <xs:enumeration value="1940"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="baseSize">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="22"/>
-            <xs:enumeration value="24"/>
-            <xs:enumeration value="26"/>
-            <xs:enumeration value="28"/>
-            <xs:enumeration value="30"/>
-            <xs:enumeration value="32"/>
-            <xs:enumeration value="34"/>
-            <xs:enumeration value="36"/>
-            <xs:enumeration value="38"/>
-            <xs:enumeration value="40"/>
-            <xs:enumeration value="42"/>
-            <xs:enumeration value="44"/>
-            <xs:enumeration value="46"/>
-            <xs:enumeration value="48"/>
-            <xs:enumeration value="50"/>
-            <xs:enumeration value="52"/>
-            <xs:enumeration value="54"/>
-            <xs:enumeration value="56"/>
-            <xs:enumeration value="220"/>
-            <xs:enumeration value="240"/>
-            <xs:enumeration value="260"/>
-            <xs:enumeration value="280"/>
-            <xs:enumeration value="300"/>
-            <xs:enumeration value="320"/>
-            <xs:enumeration value="340"/>
-            <xs:enumeration value="360"/>
-            <xs:enumeration value="380"/>
-            <xs:enumeration value="400"/>
-            <xs:enumeration value="420"/>
-            <xs:enumeration value="440"/>
-            <xs:enumeration value="460"/>
-            <xs:enumeration value="480"/>
-            <xs:enumeration value="500"/>
-            <xs:enumeration value="520"/>
-            <xs:enumeration value="540"/>
-            <xs:enumeration value="560"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="crossType">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="1"/>
-            <xs:enumeration value="2"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="axisType">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="1"/>
-            <xs:enumeration value="2"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="materialType">
-       <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="0"/><!--Fabric-->
-            <xs:enumeration value="1"/><!--Lining-->
-            <xs:enumeration value="2"/><!--Interfacing-->
-            <xs:enumeration value="3"/><!--Interlining-->
-            <xs:enumeration value="4"/><!--UserDefined-->
-       </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="placementType">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="0"/><!--No placement-->
-       <xs:enumeration value="1"/><!--Cut on Fold-->
-     </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="arrowType">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="0"/><!--Both-->
-       <xs:enumeration value="1"/><!--Front-->
-       <xs:enumeration value="2"/><!--Rear-->
-     </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="pieceVersion">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="1"/><!--Old version-->
-       <xs:enumeration value="2"/><!--New version-->
-     </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="nodeAngle">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="0"/><!--by length-->
-       <xs:enumeration value="1"/><!--by points intersections-->
-       <xs:enumeration value="2"/><!--by second edge symmetry-->
-       <xs:enumeration value="3"/><!--by first edge symmetry-->
-       <xs:enumeration value="4"/><!--by first edge right angle-->
-       <xs:enumeration value="5"/><!--by first edge right angle-->
-     </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="piecePathType">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="1"/><!--custom seam allowance-->
-       <xs:enumeration value="2"/><!--internal path-->
-     </xs:restriction>
-   </xs:simpleType>
-   <xs:simpleType name="piecePathIncludeType">
-     <xs:restriction base="xs:unsignedInt">
-       <xs:enumeration value="0"/><!--as main path-->
-       <xs:enumeration value="1"/><!--as custom seam allowance-->
-     </xs:restriction>
-   </xs:simpleType>
-   </xs:schema>
+                          </xs:sequence>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="center" type="xs:unsignedInt"/>
+                          <xs:attribute name="angle" type="xs:string"/>
+                          <xs:attribute name="length" type="xs:string"/>
+                          <xs:attribute name="suffix" type="xs:string"/>
+                          <xs:attribute name="type" type="xs:string" use="required"/>
+                          <xs:attribute name="p1Line" type="xs:unsignedInt"/>
+                          <xs:attribute name="p2Line" type="xs:unsignedInt"/>
+                          <xs:attribute name="axisType" type="axisType"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="angle1" type="xs:string"/>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="angle2" type="xs:string"/>
+                          <xs:attribute name="radius" type="xs:string"/>
+                          <xs:attribute name="center" type="xs:unsignedInt"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="color" type="colors"/>
+                          <xs:attribute name="length" type="xs:string"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="elArc" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="angle1" type="xs:string"/>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="angle2" type="xs:string"/>
+                          <xs:attribute name="rotationAngle" type="xs:string"/>
+                          <xs:attribute name="radius1" type="xs:string"/>
+                          <xs:attribute name="radius2" type="xs:string"/>
+                          <xs:attribute name="center" type="xs:unsignedInt"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="color" type="colors"/>
+                          <xs:attribute name="length" type="xs:string"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:sequence>
+                            <xs:element name="pathPoint" minOccurs="0" maxOccurs="unbounded">
+                              <xs:complexType>
+                                <xs:attribute name="kAsm2" type="xs:string"/>
+                                <xs:attribute name="pSpline" type="xs:unsignedInt"/>
+                                <xs:attribute name="angle" type="xs:string"/>
+                                <xs:attribute name="angle1" type="xs:string"/>
+                                <xs:attribute name="angle2" type="xs:string"/>
+                                <xs:attribute name="length1" type="xs:string"/>
+                                <xs:attribute name="length2" type="xs:string"/>
+                                <xs:attribute name="kAsm1" type="xs:string"/>
+                              </xs:complexType>
+                            </xs:element>
+                          </xs:sequence>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="kCurve" type="xs:double"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="kAsm1" type="xs:double"/>
+                          <xs:attribute name="kAsm2" type="xs:double"/>
+                          <xs:attribute name="angle1" type="xs:string"/>
+                          <xs:attribute name="angle2" type="xs:string"/>
+                          <xs:attribute name="length1" type="xs:string"/>
+                          <xs:attribute name="length2" type="xs:string"/>
+                          <xs:attribute name="point1" type="xs:unsignedInt"/>
+                          <xs:attribute name="point2" type="xs:unsignedInt"/>
+                          <xs:attribute name="point3" type="xs:unsignedInt"/>
+                          <xs:attribute name="point4" type="xs:unsignedInt"/>
+                          <xs:attribute name="color" type="colors"/>
+                          <xs:attribute name="duplicate" type="xs:unsignedInt"/>
+                        </xs:complexType>
+                      </xs:element>
+                    </xs:choice>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:element name="modeling" minOccurs="1" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                      <xs:element name="point" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="idObject" type="xs:unsignedInt"/>
+                          <xs:attribute name="mx" type="xs:double"/>
+                          <xs:attribute name="my" type="xs:double"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="idTool" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="arc" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="idObject" type="xs:unsignedInt"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="idTool" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="elArc" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="idObject" type="xs:unsignedInt"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="idTool" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="spline" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="idObject" type="xs:unsignedInt"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="idTool" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="path" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:sequence>
+                            <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+                              <xs:complexType>
+                                <xs:sequence>
+                                  <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+                                    <xs:complexType>
+                                      <xs:attribute name="type" type="xs:string" use="required"/>
+                                      <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
+                                      <xs:attribute name="reverse" type="xs:unsignedInt"/>
+                                      <xs:attribute name="before" type="xs:double"/>
+                                      <xs:attribute name="after" type="xs:double"/>
+                                      <xs:attribute name="angle" type="nodeAngle"/>
+                                    </xs:complexType>
+                                  </xs:element>
+                                </xs:sequence>
+                              </xs:complexType>
+                            </xs:element>
+                          </xs:sequence>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="type" type="piecePathType"/>
+                          <xs:attribute name="idTool" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                          <xs:attribute name="name" type="xs:string"/>
+                          <xs:attribute name="typeLine" type="xs:string"/>
+                        </xs:complexType>
+                      </xs:element>
+                      <xs:element name="tools" minOccurs="0" maxOccurs="unbounded">
+                        <xs:complexType>
+                          <xs:sequence>
+                            <xs:element name="det" minOccurs="2" maxOccurs="2">
+                              <xs:complexType>
+                                <xs:sequence>
+                                  <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+                                          <xs:complexType>
+                                            <xs:attribute name="type" type="xs:string" use="required"/>
+                                            <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
+                                            <xs:attribute name="reverse" type="xs:unsignedInt"/>
+                                            <xs:attribute name="before" type="xs:double"/>
+                                            <xs:attribute name="after" type="xs:double"/>
+                                            <xs:attribute name="angle" type="nodeAngle"/>
+                                          </xs:complexType>
+                                        </xs:element>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                  <xs:element name="csa" minOccurs="0" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+                                          <xs:complexType>
+                                            <xs:attribute name="start" type="xs:unsignedInt"/>
+                                            <xs:attribute name="path" type="xs:unsignedInt" use="required"/>
+                                            <xs:attribute name="end" type="xs:unsignedInt"/>
+                                            <xs:attribute name="reverse" type="xs:boolean"/>
+                                            <xs:attribute name="includeAs" type="piecePathIncludeType"/>
+                                          </xs:complexType>
+                                        </xs:element>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                  <xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+                                          <xs:complexType>
+                                            <xs:attribute name="path" type="xs:unsignedInt" use="required"/>
+                                          </xs:complexType>
+                                        </xs:element>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                </xs:sequence>
+                              </xs:complexType>
+                            </xs:element>
+                            <xs:element name="children" minOccurs="1" maxOccurs="1">
+                              <xs:complexType>
+                                <xs:sequence>
+                                  <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"/>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                  <xs:element name="csa" minOccurs="0" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"/>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                  <xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+                                    <xs:complexType>
+                                      <xs:sequence>
+                                        <xs:element name="child" type="xs:unsignedInt" minOccurs="1" maxOccurs="unbounded"/>
+                                      </xs:sequence>
+                                    </xs:complexType>
+                                  </xs:element>
+                                </xs:sequence>
+                              </xs:complexType>
+                            </xs:element>
+                          </xs:sequence>
+                          <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                          <xs:attribute name="type" type="xs:string"/>
+                          <xs:attribute name="indexD1" type="xs:unsignedInt"/>
+                          <xs:attribute name="indexD2" type="xs:unsignedInt"/>
+                          <xs:attribute name="inUse" type="xs:boolean"/>
+                        </xs:complexType>
+                      </xs:element>
+                    </xs:choice>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:element name="details" minOccurs="1" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="detail" minOccurs="0" maxOccurs="unbounded">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="data" minOccurs="0" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="mcp" minOccurs="0" maxOccurs="unbounded">
+                                  <xs:complexType>
+                                    <xs:attribute name="cutNumber" type="xs:unsignedInt"/>
+                                    <xs:attribute name="userDef" type="xs:string"/>
+                                    <xs:attribute name="material" type="materialType"/>
+                                    <xs:attribute name="placement" type="placementType"/>
+                                  </xs:complexType>
+                                </xs:element>
+                              </xs:sequence>
+                              <xs:attribute name="letter" type="xs:string"/>
+                              <xs:attribute name="visible" type="xs:boolean"/>
+                              <xs:attribute name="fontSize" type="xs:unsignedInt"/>
+                              <xs:attribute name="mx" type="xs:double"/>
+                              <xs:attribute name="my" type="xs:double"/>
+                              <xs:attribute name="width" type="xs:double"/>
+                              <xs:attribute name="height" type="xs:double"/>
+                              <xs:attribute name="rotation" type="xs:double"/>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:element name="patternInfo" minOccurs="0" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:attribute name="visible" type="xs:boolean"/>
+                              <xs:attribute name="fontSize" type="xs:unsignedInt"/>
+                              <xs:attribute name="mx" type="xs:double"/>
+                              <xs:attribute name="my" type="xs:double"/>
+                              <xs:attribute name="width" type="xs:double"/>
+                              <xs:attribute name="height" type="xs:double"/>
+                              <xs:attribute name="rotation" type="xs:double"/>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:element name="grainline" minOccurs="0" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:attribute name="visible" type="xs:boolean"/>
+                              <xs:attribute name="mx" type="xs:double"/>
+                              <xs:attribute name="my" type="xs:double"/>
+                              <xs:attribute name="length" type="xs:string"/>
+                              <xs:attribute name="rotation" type="xs:string"/>
+                              <xs:attribute name="arrows" type="arrowType"/>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:element name="nodes" minOccurs="1" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="node" minOccurs="1" maxOccurs="unbounded">
+                                  <xs:complexType>
+                                    <xs:attribute name="type" type="xs:string" use="required"/>
+                                    <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
+                                    <xs:attribute name="reverse" type="xs:unsignedInt"/>
+                                    <xs:attribute name="before" type="xs:double"/>
+                                    <xs:attribute name="after" type="xs:double"/>
+                                    <xs:attribute name="angle" type="nodeAngle"/>
+                                    <xs:attribute name="mx" type="xs:double"/>
+                                    <xs:attribute name="my" type="xs:double"/>
+                                  </xs:complexType>
+                                </xs:element>
+                              </xs:sequence>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:element name="csa" minOccurs="0" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+                                  <xs:complexType>
+                                    <xs:attribute name="start" type="xs:unsignedInt"/>
+                                    <xs:attribute name="path" type="xs:unsignedInt" use="required"/>
+                                    <xs:attribute name="end" type="xs:unsignedInt"/>
+                                    <xs:attribute name="reverse" type="xs:boolean"/>
+                                    <xs:attribute name="includeAs" type="piecePathIncludeType"/>
+                                  </xs:complexType>
+                                </xs:element>
+                              </xs:sequence>
+                            </xs:complexType>
+                          </xs:element>
+                          <xs:element name="iPaths" minOccurs="0" maxOccurs="1">
+                            <xs:complexType>
+                              <xs:sequence>
+                                <xs:element name="record" minOccurs="1" maxOccurs="unbounded">
+                                  <xs:complexType>
+                                    <xs:attribute name="path" type="xs:unsignedInt" use="required"/>
+                                  </xs:complexType>
+                                </xs:element>
+                              </xs:sequence>
+                            </xs:complexType>
+                          </xs:element>
+                        </xs:sequence>
+                        <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                        <xs:attribute name="version" type="pieceVersion"/>
+                        <xs:attribute name="mx" type="xs:double"/>
+                        <xs:attribute name="my" type="xs:double"/>
+                        <xs:attribute name="name" type="xs:string"/>
+                        <xs:attribute name="inLayout" type="xs:boolean"/>
+                        <xs:attribute name="forbidFlipping" type="xs:boolean"/>
+                        <xs:attribute name="width" type="xs:double"/>
+                        <xs:attribute name="seamAllowance" type="xs:boolean"/>
+                        <xs:attribute name="united" type="xs:boolean"/>
+                        <xs:attribute name="closed" type="xs:unsignedInt"/>
+                      </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:element name="groups" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="group" minOccurs="0" maxOccurs="unbounded">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="item" maxOccurs="unbounded">
+                            <xs:complexType>
+                              <xs:attribute name="object" type="xs:unsignedInt"/>
+                              <xs:attribute name="tool" type="xs:unsignedInt"/>
+                            </xs:complexType>
+                          </xs:element>
+                        </xs:sequence>
+                        <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+                        <xs:attribute name="name" type="xs:string"/>
+                        <xs:attribute name="visible" type="xs:boolean"/>
+                      </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+            <xs:attribute name="name" type="xs:string"/>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+      <xs:attribute name="readOnly" type="xs:boolean"/>
+    </xs:complexType>
+  </xs:element>
+  <xs:simpleType name="shortName">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
+    </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="measurementsTypes">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="standard"/>
+      <xs:enumeration value="individual"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="formatVersion">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="imageExtension">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="PNG"/>
+      <xs:enumeration value="JPG"/>
+      <xs:enumeration value="BMP"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="colors">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="black"/>
+      <xs:enumeration value="green"/>
+      <xs:enumeration value="blue"/>
+      <xs:enumeration value="darkRed"/>
+      <xs:enumeration value="darkGreen"/>
+      <xs:enumeration value="darkBlue"/>
+      <xs:enumeration value="yellow"/>
+      <xs:enumeration value="lightsalmon"/>
+      <xs:enumeration value="goldenrod"/>
+      <xs:enumeration value="orange"/>
+      <xs:enumeration value="deeppink"/>
+      <xs:enumeration value="violet"/>
+      <xs:enumeration value="darkviolet"/>
+      <xs:enumeration value="mediumseagreen"/>
+      <xs:enumeration value="lime"/>
+      <xs:enumeration value="deepskyblue"/>
+      <xs:enumeration value="cornflowerblue"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="baseHeight">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="50"/>
+      <xs:enumeration value="56"/>
+      <xs:enumeration value="62"/>
+      <xs:enumeration value="68"/>
+      <xs:enumeration value="74"/>
+      <xs:enumeration value="80"/>
+      <xs:enumeration value="86"/>
+      <xs:enumeration value="92"/>
+      <xs:enumeration value="98"/>
+      <xs:enumeration value="104"/>
+      <xs:enumeration value="110"/>
+      <xs:enumeration value="116"/>
+      <xs:enumeration value="122"/>
+      <xs:enumeration value="128"/>
+      <xs:enumeration value="134"/>
+      <xs:enumeration value="140"/>
+      <xs:enumeration value="146"/>
+      <xs:enumeration value="152"/>
+      <xs:enumeration value="158"/>
+      <xs:enumeration value="164"/>
+      <xs:enumeration value="170"/>
+      <xs:enumeration value="176"/>
+      <xs:enumeration value="182"/>
+      <xs:enumeration value="188"/>
+      <xs:enumeration value="194"/>
+      <xs:enumeration value="500"/>
+      <xs:enumeration value="560"/>
+      <xs:enumeration value="620"/>
+      <xs:enumeration value="680"/>
+      <xs:enumeration value="740"/>
+      <xs:enumeration value="800"/>
+      <xs:enumeration value="860"/>
+      <xs:enumeration value="920"/>
+      <xs:enumeration value="980"/>
+      <xs:enumeration value="1040"/>
+      <xs:enumeration value="1100"/>
+      <xs:enumeration value="1160"/>
+      <xs:enumeration value="1220"/>
+      <xs:enumeration value="1280"/>
+      <xs:enumeration value="1340"/>
+      <xs:enumeration value="1400"/>
+      <xs:enumeration value="1460"/>
+      <xs:enumeration value="1520"/>
+      <xs:enumeration value="1580"/>
+      <xs:enumeration value="1640"/>
+      <xs:enumeration value="1700"/>
+      <xs:enumeration value="1760"/>
+      <xs:enumeration value="1820"/>
+      <xs:enumeration value="1880"/>
+      <xs:enumeration value="1940"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="baseSize">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="22"/>
+      <xs:enumeration value="24"/>
+      <xs:enumeration value="26"/>
+      <xs:enumeration value="28"/>
+      <xs:enumeration value="30"/>
+      <xs:enumeration value="32"/>
+      <xs:enumeration value="34"/>
+      <xs:enumeration value="36"/>
+      <xs:enumeration value="38"/>
+      <xs:enumeration value="40"/>
+      <xs:enumeration value="42"/>
+      <xs:enumeration value="44"/>
+      <xs:enumeration value="46"/>
+      <xs:enumeration value="48"/>
+      <xs:enumeration value="50"/>
+      <xs:enumeration value="52"/>
+      <xs:enumeration value="54"/>
+      <xs:enumeration value="56"/>
+      <xs:enumeration value="220"/>
+      <xs:enumeration value="240"/>
+      <xs:enumeration value="260"/>
+      <xs:enumeration value="280"/>
+      <xs:enumeration value="300"/>
+      <xs:enumeration value="320"/>
+      <xs:enumeration value="340"/>
+      <xs:enumeration value="360"/>
+      <xs:enumeration value="380"/>
+      <xs:enumeration value="400"/>
+      <xs:enumeration value="420"/>
+      <xs:enumeration value="440"/>
+      <xs:enumeration value="460"/>
+      <xs:enumeration value="480"/>
+      <xs:enumeration value="500"/>
+      <xs:enumeration value="520"/>
+      <xs:enumeration value="540"/>
+      <xs:enumeration value="560"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="crossType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="1"/>
+      <xs:enumeration value="2"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="axisType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="1"/>
+      <xs:enumeration value="2"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="materialType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="0"/>
+      <!--Fabric-->
+      <xs:enumeration value="1"/>
+      <!--Lining-->
+      <xs:enumeration value="2"/>
+      <!--Interfacing-->
+      <xs:enumeration value="3"/>
+      <!--Interlining-->
+      <xs:enumeration value="4"/>
+      <!--UserDefined-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="placementType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="0"/>
+      <!--No placement-->
+      <xs:enumeration value="1"/>
+      <!--Cut on Fold-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="arrowType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="0"/>
+      <!--Both-->
+      <xs:enumeration value="1"/>
+      <!--Front-->
+      <xs:enumeration value="2"/>
+      <!--Rear-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="pieceVersion">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="1"/>
+      <!--Old version-->
+      <xs:enumeration value="2"/>
+      <!--New version-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="nodeAngle">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="0"/>
+      <!--by length-->
+      <xs:enumeration value="1"/>
+      <!--by points intersections-->
+      <xs:enumeration value="2"/>
+      <!--by second edge symmetry-->
+      <xs:enumeration value="3"/>
+      <!--by first edge symmetry-->
+      <xs:enumeration value="4"/>
+      <!--by first edge right angle-->
+      <xs:enumeration value="5"/>
+      <!--by first edge right angle-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="piecePathType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="1"/>
+      <!--custom seam allowance-->
+      <xs:enumeration value="2"/>
+      <!--internal path-->
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="piecePathIncludeType">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="0"/>
+      <!--as main path-->
+      <xs:enumeration value="1"/>
+      <!--as custom seam allowance-->
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>
diff --git a/src/libs/ifc/schema/standard_measurements/v0.4.3.xsd b/src/libs/ifc/schema/standard_measurements/v0.4.3.xsd
index dc72b8300..4b246e839 100644
--- a/src/libs/ifc/schema/standard_measurements/v0.4.3.xsd
+++ b/src/libs/ifc/schema/standard_measurements/v0.4.3.xsd
@@ -1,160 +1,160 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
-	<xs:element name="vst">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element name="version" type="formatVersion"></xs:element>
-				<xs:element name="read-only" type="xs:boolean"></xs:element>
-				<xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
-				<xs:element name="unit" type="units"></xs:element>
-				<xs:element name="pm_system" type="psCode"></xs:element>
-				<xs:element name="size">
-					<xs:complexType>
-						<xs:attribute name="base" type="baseSize" use="required"></xs:attribute>
-					</xs:complexType>
-				</xs:element>
-				<xs:element name="height">
-					<xs:complexType>
-						<xs:attribute name="base" type="baseHeight" use="required"></xs:attribute>
-					</xs:complexType>
-				</xs:element>
-				<xs:element name="body-measurements">
-					<xs:complexType>
-						<xs:sequence>
-							<xs:element name="m" minOccurs="0" maxOccurs="unbounded">
-								<xs:complexType>
-									<xs:attribute name="name" type="shortName" use="required"></xs:attribute>
-									<xs:attribute name="base" type="xs:double" use="required"></xs:attribute>
-									<xs:attribute name="height_increase" type="xs:double" use="required"></xs:attribute>
-									<xs:attribute name="size_increase" type="xs:double" use="required"></xs:attribute>
-									<xs:attribute name="full_name" type="xs:string"></xs:attribute>
-									<xs:attribute name="description" type="xs:string"></xs:attribute>
-								</xs:complexType>
-							</xs:element>
-						</xs:sequence>
-					</xs:complexType>
-				</xs:element>
-			</xs:sequence>
-		 </xs:complexType>
-		<xs:unique name="measurementName">
-			<xs:selector xpath="body-measurements/m"/>
-			<xs:field xpath="@name"/>
-		</xs:unique>
-	  </xs:element>
-	<xs:simpleType name="shortName">
-		<xs:restriction base="xs:string">   
-			<xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
-		</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="formatVersion">
-		<xs:restriction base="xs:string">
-			<xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
-		</xs:restriction>
-	</xs:simpleType>
-	<xs:simpleType name="psCode">
-		<xs:restriction base="xs:string">
-			<xs:pattern value="^^(([0-9]|[1-4][0-9]|5[0-4])|998)$"/>
-		</xs:restriction>
-	</xs:simpleType>
-    <xs:simpleType name="baseHeight">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="50"/>
-            <xs:enumeration value="56"/>
-            <xs:enumeration value="62"/>
-            <xs:enumeration value="68"/>
-            <xs:enumeration value="74"/>
-            <xs:enumeration value="80"/>
-            <xs:enumeration value="86"/>
-            <xs:enumeration value="92"/>
-            <xs:enumeration value="98"/>
-            <xs:enumeration value="104"/>
-            <xs:enumeration value="110"/>
-            <xs:enumeration value="116"/>
-            <xs:enumeration value="122"/>
-            <xs:enumeration value="128"/>
-            <xs:enumeration value="134"/>
-            <xs:enumeration value="140"/>
-            <xs:enumeration value="146"/>
-            <xs:enumeration value="152"/>
-            <xs:enumeration value="158"/>
-            <xs:enumeration value="164"/>
-            <xs:enumeration value="170"/>
-            <xs:enumeration value="176"/>
-            <xs:enumeration value="182"/>
-            <xs:enumeration value="188"/>
-            <xs:enumeration value="194"/>
-            <xs:enumeration value="500"/>
-            <xs:enumeration value="560"/>
-            <xs:enumeration value="620"/>
-            <xs:enumeration value="680"/>
-            <xs:enumeration value="740"/>
-            <xs:enumeration value="800"/>
-            <xs:enumeration value="860"/>
-            <xs:enumeration value="920"/>
-            <xs:enumeration value="980"/>
-            <xs:enumeration value="1040"/>
-            <xs:enumeration value="1100"/>
-            <xs:enumeration value="1160"/>
-            <xs:enumeration value="1220"/>
-            <xs:enumeration value="1280"/>
-            <xs:enumeration value="1340"/>
-            <xs:enumeration value="1400"/>
-            <xs:enumeration value="1460"/>
-            <xs:enumeration value="1520"/>
-            <xs:enumeration value="1580"/>
-            <xs:enumeration value="1640"/>
-            <xs:enumeration value="1700"/>
-            <xs:enumeration value="1760"/>
-            <xs:enumeration value="1820"/>
-            <xs:enumeration value="1880"/>
-            <xs:enumeration value="1940"/>
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="baseSize">
-        <xs:restriction base="xs:unsignedInt">
-            <xs:enumeration value="22"/>
-            <xs:enumeration value="24"/>
-            <xs:enumeration value="26"/>
-            <xs:enumeration value="28"/>
-            <xs:enumeration value="30"/>
-            <xs:enumeration value="32"/>
-            <xs:enumeration value="34"/>
-            <xs:enumeration value="36"/>
-            <xs:enumeration value="38"/>
-            <xs:enumeration value="40"/>
-            <xs:enumeration value="42"/>
-            <xs:enumeration value="44"/>
-            <xs:enumeration value="46"/>
-            <xs:enumeration value="48"/>
-            <xs:enumeration value="50"/>
-            <xs:enumeration value="52"/>
-            <xs:enumeration value="54"/>
-            <xs:enumeration value="56"/>
-            <xs:enumeration value="220"/>
-            <xs:enumeration value="240"/>
-            <xs:enumeration value="260"/>
-            <xs:enumeration value="280"/>
-            <xs:enumeration value="300"/>
-            <xs:enumeration value="320"/>
-            <xs:enumeration value="340"/>
-            <xs:enumeration value="360"/>
-            <xs:enumeration value="380"/>
-            <xs:enumeration value="400"/>
-            <xs:enumeration value="420"/>
-            <xs:enumeration value="440"/>
-            <xs:enumeration value="460"/>
-            <xs:enumeration value="480"/>
-            <xs:enumeration value="500"/>
-            <xs:enumeration value="520"/>
-            <xs:enumeration value="540"/>
-            <xs:enumeration value="560"/>
-        </xs:restriction>
-    </xs:simpleType>
+  <xs:element name="vst">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="version" type="formatVersion"/>
+        <xs:element name="read-only" type="xs:boolean"/>
+        <xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1"/>
+        <xs:element name="unit" type="units"/>
+        <xs:element name="pm_system" type="psCode"/>
+        <xs:element name="size">
+          <xs:complexType>
+            <xs:attribute name="base" type="baseSize" use="required"/>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="height">
+          <xs:complexType>
+            <xs:attribute name="base" type="baseHeight" use="required"/>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="body-measurements">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="m" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:attribute name="name" type="shortName" use="required"/>
+                  <xs:attribute name="base" type="xs:double" use="required"/>
+                  <xs:attribute name="height_increase" type="xs:double" use="required"/>
+                  <xs:attribute name="size_increase" type="xs:double" use="required"/>
+                  <xs:attribute name="full_name" type="xs:string"/>
+                  <xs:attribute name="description" type="xs:string"/>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+    </xs:complexType>
+    <xs:unique name="measurementName">
+      <xs:selector xpath="body-measurements/m"/>
+      <xs:field xpath="@name"/>
+    </xs:unique>
+  </xs:element>
+  <xs:simpleType name="shortName">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^([^\p{Nd}\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;'\&quot;]){1,1}([^\p{Zs}*/&amp;|!&lt;&gt;^\-()–+−=?:;\&quot;]){0,}$"/>
+    </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="formatVersion">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))\.(0|([1-9][0-9]*))$"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="psCode">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="^^(([0-9]|[1-4][0-9]|5[0-4])|998)$"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="baseHeight">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="50"/>
+      <xs:enumeration value="56"/>
+      <xs:enumeration value="62"/>
+      <xs:enumeration value="68"/>
+      <xs:enumeration value="74"/>
+      <xs:enumeration value="80"/>
+      <xs:enumeration value="86"/>
+      <xs:enumeration value="92"/>
+      <xs:enumeration value="98"/>
+      <xs:enumeration value="104"/>
+      <xs:enumeration value="110"/>
+      <xs:enumeration value="116"/>
+      <xs:enumeration value="122"/>
+      <xs:enumeration value="128"/>
+      <xs:enumeration value="134"/>
+      <xs:enumeration value="140"/>
+      <xs:enumeration value="146"/>
+      <xs:enumeration value="152"/>
+      <xs:enumeration value="158"/>
+      <xs:enumeration value="164"/>
+      <xs:enumeration value="170"/>
+      <xs:enumeration value="176"/>
+      <xs:enumeration value="182"/>
+      <xs:enumeration value="188"/>
+      <xs:enumeration value="194"/>
+      <xs:enumeration value="500"/>
+      <xs:enumeration value="560"/>
+      <xs:enumeration value="620"/>
+      <xs:enumeration value="680"/>
+      <xs:enumeration value="740"/>
+      <xs:enumeration value="800"/>
+      <xs:enumeration value="860"/>
+      <xs:enumeration value="920"/>
+      <xs:enumeration value="980"/>
+      <xs:enumeration value="1040"/>
+      <xs:enumeration value="1100"/>
+      <xs:enumeration value="1160"/>
+      <xs:enumeration value="1220"/>
+      <xs:enumeration value="1280"/>
+      <xs:enumeration value="1340"/>
+      <xs:enumeration value="1400"/>
+      <xs:enumeration value="1460"/>
+      <xs:enumeration value="1520"/>
+      <xs:enumeration value="1580"/>
+      <xs:enumeration value="1640"/>
+      <xs:enumeration value="1700"/>
+      <xs:enumeration value="1760"/>
+      <xs:enumeration value="1820"/>
+      <xs:enumeration value="1880"/>
+      <xs:enumeration value="1940"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="baseSize">
+    <xs:restriction base="xs:unsignedInt">
+      <xs:enumeration value="22"/>
+      <xs:enumeration value="24"/>
+      <xs:enumeration value="26"/>
+      <xs:enumeration value="28"/>
+      <xs:enumeration value="30"/>
+      <xs:enumeration value="32"/>
+      <xs:enumeration value="34"/>
+      <xs:enumeration value="36"/>
+      <xs:enumeration value="38"/>
+      <xs:enumeration value="40"/>
+      <xs:enumeration value="42"/>
+      <xs:enumeration value="44"/>
+      <xs:enumeration value="46"/>
+      <xs:enumeration value="48"/>
+      <xs:enumeration value="50"/>
+      <xs:enumeration value="52"/>
+      <xs:enumeration value="54"/>
+      <xs:enumeration value="56"/>
+      <xs:enumeration value="220"/>
+      <xs:enumeration value="240"/>
+      <xs:enumeration value="260"/>
+      <xs:enumeration value="280"/>
+      <xs:enumeration value="300"/>
+      <xs:enumeration value="320"/>
+      <xs:enumeration value="340"/>
+      <xs:enumeration value="360"/>
+      <xs:enumeration value="380"/>
+      <xs:enumeration value="400"/>
+      <xs:enumeration value="420"/>
+      <xs:enumeration value="440"/>
+      <xs:enumeration value="460"/>
+      <xs:enumeration value="480"/>
+      <xs:enumeration value="500"/>
+      <xs:enumeration value="520"/>
+      <xs:enumeration value="540"/>
+      <xs:enumeration value="560"/>
+    </xs:restriction>
+  </xs:simpleType>
 </xs:schema>

From 84b285cbe4f368634804aafb923dd49ce8ffe581 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 19 Jan 2017 12:07:26 +0200
Subject: [PATCH 174/208] Refactoring. Grainline and label have common parent.

--HG--
branch : feature
---
 src/libs/vtools/tools/tools.pri             |   6 +-
 src/libs/vtools/tools/vgrainlineitem.cpp    |  89 ++--------
 src/libs/vtools/tools/vgrainlineitem.h      |  85 ++++-----
 src/libs/vtools/tools/vpieceitem.cpp        | 108 +++++++++++
 src/libs/vtools/tools/vpieceitem.h          |  73 ++++++++
 src/libs/vtools/tools/vtextgraphicsitem.cpp | 187 +++++++-------------
 src/libs/vtools/tools/vtextgraphicsitem.h   |  81 ++++-----
 7 files changed, 324 insertions(+), 305 deletions(-)
 create mode 100644 src/libs/vtools/tools/vpieceitem.cpp
 create mode 100644 src/libs/vtools/tools/vpieceitem.h

diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri
index 6a43ce9da..ee9c190a6 100644
--- a/src/libs/vtools/tools/tools.pri
+++ b/src/libs/vtools/tools/tools.pri
@@ -61,7 +61,8 @@ HEADERS += \
     $$PWD/drawTools/toolcurve/vtoolellipticalarc.h \
     $$PWD/nodeDetails/vnodeellipticalarc.h \
     $$PWD/vtoolseamallowance.h \
-    $$PWD/nodeDetails/vtoolpiecepath.h
+    $$PWD/nodeDetails/vtoolpiecepath.h \
+    $$PWD/vpieceitem.h
 
 SOURCES += \
     $$PWD/vtooldetail.cpp \
@@ -120,4 +121,5 @@ SOURCES += \
     $$PWD/drawTools/toolcurve/vtoolellipticalarc.cpp \
     $$PWD/nodeDetails/vnodeellipticalarc.cpp \
     $$PWD/vtoolseamallowance.cpp \
-    $$PWD/nodeDetails/vtoolpiecepath.cpp
+    $$PWD/nodeDetails/vtoolpiecepath.cpp \
+    $$PWD/vpieceitem.cpp
diff --git a/src/libs/vtools/tools/vgrainlineitem.cpp b/src/libs/vtools/tools/vgrainlineitem.cpp
index dfe1c5ff9..954216651 100644
--- a/src/libs/vtools/tools/vgrainlineitem.cpp
+++ b/src/libs/vtools/tools/vgrainlineitem.cpp
@@ -32,7 +32,6 @@
 #include <QGraphicsSceneMouseEvent>
 #include <QStyleOptionGraphicsItem>
 #include <QDebug>
-#include <QGraphicsScene>
 
 #include "../vmisc/def.h"
 #include "../vmisc/vmath.h"
@@ -45,7 +44,6 @@
 #define RESIZE_RECT_SIZE                10
 #define ROTATE_CIRC_R                   7
 #define ACTIVE_Z                        10
-#define INACTIVE_Z                      5
 
 //---------------------------------------------------------------------------------------------------------------------
 /**
@@ -53,13 +51,10 @@
  * @param pParent pointer to the parent item
  */
 VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent)
-    : QGraphicsObject(pParent),
-      m_eMode(VGrainlineItem::mNormal),
-      m_bReleased(false),
+    : VPieceItem(pParent),
       m_dRotation(0),
       m_dStartRotation(0),
       m_dLength(0),
-      m_rectBoundingBox(),
       m_polyBound(),
       m_ptStartPos(),
       m_ptStartMove(),
@@ -69,12 +64,10 @@ VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent)
       m_ptStart(),
       m_ptFinish(),
       m_ptCenter(),
-      m_ptRotCenter(),
       m_dAngle(0),
       m_eArrowType(VGrainlineGeometry::atBoth)
 {
-    m_rectBoundingBox.setTopLeft(QPointF(0, 0));
-    setAcceptHoverEvents(true);
+    m_inactiveZ = 5;
     Reset();
     UpdateRectangle();
 }
@@ -212,43 +205,7 @@ void VGrainlineItem::UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal
     m_eArrowType = eAT;
 
     UpdateRectangle();
-    UpdateBox();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VGrainlineItem::boundingRect returns the bounding rect around the grainline
- * @return bounding rect
- */
-QRectF VGrainlineItem::boundingRect() const
-{
-    return m_rectBoundingBox;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VGrainlineItem::Reset resets the item parameters.
- */
-void VGrainlineItem::Reset()
-{
-    if (QGraphicsScene *toolScene = scene())
-    {
-        toolScene->clearSelection();
-    }
-    m_bReleased = false;
-    m_eMode = mNormal;
-    setZValue(INACTIVE_Z);
-    UpdateBox();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VGrainlineItem::IsIdle returns the idle flag.
- * @return true, if item mode is normal and false otherwise.
- */
-bool VGrainlineItem::IsIdle() const
-{
-    return m_eMode == mNormal;
+    Update();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -323,7 +280,7 @@ void VGrainlineItem::SetScale(qreal dScale)
 {
     m_dScale = dScale;
     UpdateRectangle();
-    UpdateBox();
+    Update();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -360,7 +317,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME)
             SetOverrideCursor(cursorArrowCloseHand, 1, 1);
         }
         setZValue(ACTIVE_Z);
-        UpdateBox();
+        Update();
     }
 }
 
@@ -383,7 +340,7 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
             pt.setY(pt.y() + dY);
         }
         setPos(pt);
-        UpdateBox();
+        Update();
     }
     else if (m_eMode == mResize)
     {
@@ -400,7 +357,7 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
             m_dLength = dPrevLen;
         }
         UpdateRectangle();
-        UpdateBox();
+        Update();
     }
     else if (m_eMode == mRotate)
     {
@@ -424,7 +381,7 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME)
             setPos(ptNewPos);
             m_dRotation = m_dStartRotation + dAng;
             UpdateRectangle();
-            UpdateBox();
+            Update();
         }
     }
 }
@@ -459,7 +416,7 @@ void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
                 if (m_bReleased == true)
                 {
                     m_eMode = mRotate;
-                    UpdateBox();
+                    Update();
                 }
             }
             else
@@ -472,7 +429,7 @@ void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
                 {
                     emit SignalResized(m_dLength);
                 }
-                UpdateBox();
+                Update();
             }
         }
         else
@@ -485,7 +442,7 @@ void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
             {
                 emit SignalRotated(m_dRotation, m_ptStart);
             }
-            UpdateBox();
+            Update();
         }
         m_bReleased = true;
     }
@@ -495,7 +452,7 @@ void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
 /**
  * @brief VGrainlineItem::UpdateBox updates the item
  */
-void VGrainlineItem::UpdateBox()
+void VGrainlineItem::Update()
 {
     update(m_rectBoundingBox);
 }
@@ -554,28 +511,6 @@ void VGrainlineItem::UpdateRectangle()
     prepareGeometryChange();
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VGrainlineItem::GetAngle calculates the angle between the line, which goes from
- * rotation center to pt and x axis
- * @param pt point of interest
- * @return the angle between line from rotation center and point of interest and x axis
- */
-qreal VGrainlineItem::GetAngle(const QPointF& pt) const
-{
-    double dX = pt.x() - m_ptRotCenter.x();
-    double dY = pt.y() - m_ptRotCenter.y();
-
-    if (fabs(dX) < 1 && fabs(dY) < 1)
-    {
-        return 0;
-    }
-    else
-    {
-        return qAtan2(-dY, dX);
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief VGrainlineItem::Rotate rotates point pt around ptCenter by angle dAng [rad]
diff --git a/src/libs/vtools/tools/vgrainlineitem.h b/src/libs/vtools/tools/vgrainlineitem.h
index 41ea59eb5..7f4217d54 100644
--- a/src/libs/vtools/tools/vgrainlineitem.h
+++ b/src/libs/vtools/tools/vgrainlineitem.h
@@ -29,8 +29,7 @@
 #ifndef VGRAINLINEITEM_H
 #define VGRAINLINEITEM_H
 
-#include <QGraphicsObject>
-
+#include "vpieceitem.h"
 #include "../vpatterndb/vgrainlinegeometry.h"
 
 class QGraphicsObject;
@@ -38,66 +37,50 @@ class QPainter;
 class QStyleOptionGraphicsItem;
 class QWidget;
 
-class VGrainlineItem : public QGraphicsObject
+class VGrainlineItem : public VPieceItem
 {
     Q_OBJECT
-
-    enum Mode {
-        mNormal,
-        mMove,
-        mResize,
-        mRotate
-    };
-
 public:
     explicit VGrainlineItem(QGraphicsItem* pParent = nullptr);
     virtual ~VGrainlineItem();
 
-    void                    paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget);
-    void                    UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength,
-                                           VGrainlineGeometry::ArrowType eAT);
+    virtual void paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget) Q_DECL_OVERRIDE;
+    void         UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength,
+                                VGrainlineGeometry::ArrowType eAT);
 
-    QRectF                  boundingRect() const;
-    void                    Reset();
-    bool                    IsIdle() const;
-    bool                    IsContained(const QPointF &pt, qreal dRot, qreal &dX, qreal &dY) const;
-    void                    SetScale(qreal dScale);
-
-protected:
-    void                    mousePressEvent(QGraphicsSceneMouseEvent* pME);
-    void                    mouseMoveEvent(QGraphicsSceneMouseEvent* pME);
-    void                    mouseReleaseEvent(QGraphicsSceneMouseEvent* pME);
-    void                    UpdateBox();
-    void                    UpdateRectangle();
-
-    qreal                   GetAngle(const QPointF& pt) const;
-    QPointF                 Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const;
-    QPointF                 GetInsideCorner(int i, qreal dDist) const;
+    bool IsContained(const QPointF &pt, qreal dRot, qreal &dX, qreal &dY) const;
+    void SetScale(qreal dScale);
 
 signals:
-    void                    SignalMoved(const QPointF& ptPos);
-    void                    SignalResized(qreal dLength);
-    void                    SignalRotated(qreal dRot, const QPointF& ptNewPos);
+    void SignalResized(qreal dLength);
+    void SignalRotated(qreal dRot, const QPointF& ptNewPos);
+
+protected:
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void Update() Q_DECL_OVERRIDE;
+    void         UpdateRectangle();
+
+    QPointF Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const;
+    QPointF GetInsideCorner(int i, qreal dDist) const;
 
 private:
-    Mode                            m_eMode;
-    bool                            m_bReleased;
-    qreal                           m_dRotation;
-    qreal                           m_dStartRotation;
-    qreal                           m_dLength;
-    QRectF                          m_rectBoundingBox;
-    QPolygonF                       m_polyBound;
-    QPointF                         m_ptStartPos;
-    QPointF                         m_ptStartMove;
-    qreal                           m_dScale;
-    QPolygonF                       m_polyResize;
-    qreal                           m_dStartLength;
-    QPointF                         m_ptStart;
-    QPointF                         m_ptFinish;
-    QPointF                         m_ptCenter;
-    QPointF                         m_ptRotCenter;
-    qreal                           m_dAngle;
-    VGrainlineGeometry::ArrowType   m_eArrowType;
+    Q_DISABLE_COPY(VGrainlineItem)
+    qreal                         m_dRotation;
+    qreal                         m_dStartRotation;
+    qreal                         m_dLength;
+    QPolygonF                     m_polyBound;
+    QPointF                       m_ptStartPos;
+    QPointF                       m_ptStartMove;
+    qreal                         m_dScale;
+    QPolygonF                     m_polyResize;
+    qreal                         m_dStartLength;
+    QPointF                       m_ptStart;
+    QPointF                       m_ptFinish;
+    QPointF                       m_ptCenter;
+    qreal                         m_dAngle;
+    VGrainlineGeometry::ArrowType m_eArrowType;
 };
 
 #endif // VGRAINLINEITEM_H
diff --git a/src/libs/vtools/tools/vpieceitem.cpp b/src/libs/vtools/tools/vpieceitem.cpp
new file mode 100644
index 000000000..f7f969fed
--- /dev/null
+++ b/src/libs/vtools/tools/vpieceitem.cpp
@@ -0,0 +1,108 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   18 1, 2017
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2017 Valentina project
+ **  <https://bitbucket.org/dismine/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 "vpieceitem.h"
+#include "../vmisc/vmath.h"
+
+#include <QGraphicsScene>
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceItem::VPieceItem(QGraphicsItem *pParent)
+    : QGraphicsObject(pParent),
+      m_rectBoundingBox(),
+      m_eMode(VPieceItem::mNormal),
+      m_bReleased(false),
+      m_ptRotCenter(),
+      m_inactiveZ(1)
+{
+    m_rectBoundingBox.setTopLeft(QPointF(0, 0));
+    setAcceptHoverEvents(true);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VPieceItem::~VPieceItem()
+{
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief boundingRect returns the item bounding box
+ * @return item bounding box
+ */
+QRectF VPieceItem::boundingRect() const
+{
+    return m_rectBoundingBox;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief Reset resets the item, putting the mode and z coordinate to normal and redraws it
+ */
+void VPieceItem::Reset()
+{
+    if (QGraphicsScene *toolScene = scene())
+    {
+        toolScene->clearSelection();
+    }
+    m_eMode = mNormal;
+    m_bReleased = false;
+    Update();
+    setZValue(m_inactiveZ);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief IsIdle returns the idle flag.
+ * @return true, if item mode is normal and false otherwise.
+ */
+bool VPieceItem::IsIdle() const
+{
+    return m_eMode == mNormal;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief GetAngle calculates the angle between the line, which goes from rotation center to pt and x axis
+ * @param pt point of interest
+ * @return the angle between line from rotation center and point of interest and x axis
+ */
+double VPieceItem::GetAngle(const QPointF &pt) const
+{
+    const double dX = pt.x() - m_ptRotCenter.x();
+    const double dY = pt.y() - m_ptRotCenter.y();
+
+    if (fabs(dX) < 1 && fabs(dY) < 1)
+    {
+        return 0;
+    }
+    else
+    {
+        return qAtan2(dY, dX);
+    }
+}
+
diff --git a/src/libs/vtools/tools/vpieceitem.h b/src/libs/vtools/tools/vpieceitem.h
new file mode 100644
index 000000000..7b3306044
--- /dev/null
+++ b/src/libs/vtools/tools/vpieceitem.h
@@ -0,0 +1,73 @@
+/************************************************************************
+ **
+ **  @file
+ **  @author Roman Telezhynskyi <dismine(at)gmail.com>
+ **  @date   18 1, 2017
+ **
+ **  @brief
+ **  @copyright
+ **  This source code is part of the Valentine project, a pattern making
+ **  program, whose allow create and modeling patterns of clothing.
+ **  Copyright (C) 2017 Valentina project
+ **  <https://bitbucket.org/dismine/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 VPIECEITEM_H
+#define VPIECEITEM_H
+
+#include <QtCore/qglobal.h>
+#include <QGraphicsObject>
+
+class VPieceItem : public QGraphicsObject
+{
+    Q_OBJECT
+public:
+    explicit VPieceItem(QGraphicsItem* pParent = nullptr);
+    virtual ~VPieceItem();
+
+    virtual QRectF boundingRect() const Q_DECL_OVERRIDE;
+
+    virtual void Update() =0;
+
+    void Reset();
+    bool IsIdle() const;
+
+    double GetAngle(const QPointF &pt) const;
+
+signals:
+    void SignalMoved(const QPointF &ptPos);
+
+protected:
+    enum Mode
+    {
+        mNormal,
+        mMove,
+        mResize,
+        mRotate
+    };
+    QRectF  m_rectBoundingBox;
+    Mode    m_eMode;
+    bool    m_bReleased;
+    QPointF m_ptRotCenter;
+
+    qreal m_inactiveZ;
+
+private:
+    Q_DISABLE_COPY(VPieceItem)
+};
+
+#endif // VPIECEITEM_H
diff --git a/src/libs/vtools/tools/vtextgraphicsitem.cpp b/src/libs/vtools/tools/vtextgraphicsitem.cpp
index 63d1f834c..c423a04b8 100644
--- a/src/libs/vtools/tools/vtextgraphicsitem.cpp
+++ b/src/libs/vtools/tools/vtextgraphicsitem.cpp
@@ -37,7 +37,6 @@
 #include <QPoint>
 #include <QStyleOptionGraphicsItem>
 #include <Qt>
-#include <QGraphicsScene>
 
 #include "../vmisc/def.h"
 #include "../vmisc/vmath.h"
@@ -56,32 +55,85 @@ const qreal rotateCircle = (2./*mm*/ / 25.4) * PrintDPI;
 #define ROTATE_ARC                  50
 const qreal minW = (4./*mm*/ / 25.4) * PrintDPI + resizeSquare;
 const qreal minH = (4./*mm*/ / 25.4) * PrintDPI + resizeSquare;
-#define INACTIVE_Z                  2
 #define ACTIVE_Z                    10
 
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief GetBoundingRect calculates the bounding box around rectBB rectangle, rotated around its center by dRot degrees
+ * @param rectBB rectangle of interest
+ * @param dRot rectangle rotation
+ * @return bounding box around rectBB rotated by dRot
+ */
+QRectF GetBoundingRect(QRectF rectBB, qreal dRot)
+{
+    QPointF apt[4] = { rectBB.topLeft(), rectBB.topRight(), rectBB.bottomLeft(), rectBB.bottomRight() };
+    QPointF ptCenter = rectBB.center();
+
+    qreal dX1 = 0;
+    qreal dX2 = 0;
+    qreal dY1 = 0;
+    qreal dY2 = 0;
+
+    double dAng = qDegreesToRadians(dRot);
+    for (int i = 0; i < 4; ++i)
+    {
+        QPointF pt = apt[i] - ptCenter;
+        qreal dX = pt.x()*cos(dAng) + pt.y()*sin(dAng);
+        qreal dY = -pt.x()*sin(dAng) + pt.y()*cos(dAng);
+
+        if (i == 0)
+        {
+            dX1 = dX2 = dX;
+            dY1 = dY2 = dY;
+        }
+        else
+        {
+            if (dX < dX1)
+            {
+                dX1 = dX;
+            }
+            else if (dX > dX2)
+            {
+                dX2 = dX;
+            }
+            if (dY < dY1)
+            {
+                dY1 = dY;
+            }
+            else if (dY > dY2)
+            {
+                dY2 = dY;
+            }
+        }
+    }
+    QRectF rect;
+    rect.setTopLeft(ptCenter + QPointF(dX1, dY1));
+    rect.setWidth(dX2 - dX1);
+    rect.setHeight(dY2 - dY1);
+    return rect;
+}
+}//static functions
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief VTextGraphicsItem::VTextGraphicsItem constructor
  * @param pParent pointer to the parent item
  */
 VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent)
-    : QGraphicsObject(pParent),
-      m_eMode(VTextGraphicsItem::mNormal),
-      m_bReleased(false),
+    : VPieceItem(pParent),
       m_ptStartPos(),
       m_ptStart(),
-      m_ptRotCenter(),
       m_szStart(),
       m_dRotation(0),
       m_dAngle(0),
       m_rectResize(),
-      m_rectBoundingBox(),
       m_tm()
 {
-    m_rectBoundingBox.setTopLeft(QPointF(0, 0));
+    m_inactiveZ = 2;
     SetSize(minW, minH);
-    setZValue(INACTIVE_Z);
-    setAcceptHoverEvents(true);
+    setZValue(m_inactiveZ);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -196,32 +248,6 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VTextGraphicsItem::Reset resets the item, putting the mode and z coordinate to normal and redraws it
- */
-void VTextGraphicsItem::Reset()
-{
-    if (QGraphicsScene *toolScene = scene())
-    {
-        toolScene->clearSelection();
-    }
-    m_eMode = mNormal;
-    m_bReleased = false;
-    Update();
-    setZValue(INACTIVE_Z);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VTextGraphicsItem::IsIdle checks if the item is in normal mode.
- * @return true, if item is in normal mode and false otherwise.
- */
-bool VTextGraphicsItem::IsIdle() const
-{
-    return m_eMode == mNormal;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief VTextGraphicsItem::AddLine adds a line of text to the label list.
@@ -374,16 +400,6 @@ int VTextGraphicsItem::GetFontSize() const
     return m_tm.GetFont().pixelSize();
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VTextGraphicsItem::boundingRect returns the label bounding box
- * @return label bounding box
- */
-QRectF VTextGraphicsItem::boundingRect() const
-{
-    return m_rectBoundingBox;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief VTextGraphicsItem::mousePressEvent handles left button mouse press events
@@ -617,82 +633,3 @@ void VTextGraphicsItem::CorrectLabel()
     m_tm.FitFontSize(m_rectBoundingBox.width(), m_rectBoundingBox.height());
     UpdateBox();
 }
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VTextGraphicsItem::GetAngle calculates the angle between the line, which goes from
- * rotation center to pt and x axis
- * @param pt point of interest
- * @return the angle between line from rotation center and point of interest and x axis
- */
-double VTextGraphicsItem::GetAngle(QPointF pt) const
-{
-    double dX = pt.x() - m_ptRotCenter.x();
-    double dY = pt.y() - m_ptRotCenter.y();
-
-    if (fabs(dX) < 1 && fabs(dY) < 1)
-    {
-        return 0;
-    }
-    else
-    {
-        return qAtan2(dY, dX);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VTextGraphicsItem::GetBoundingRect calculates the bounding box
- *  around rectBB rectangle, rotated around its center by dRot degrees
- * @param rectBB rectangle of interest
- * @param dRot rectangle rotation
- * @return bounding box around rectBB rotated by dRot
- */
-QRectF VTextGraphicsItem::GetBoundingRect(QRectF rectBB, qreal dRot) const
-{
-    QPointF apt[4] = { rectBB.topLeft(), rectBB.topRight(), rectBB.bottomLeft(), rectBB.bottomRight() };
-    QPointF ptCenter = rectBB.center();
-
-    qreal dX1 = 0;
-    qreal dX2 = 0;
-    qreal dY1 = 0;
-    qreal dY2 = 0;
-
-    double dAng = qDegreesToRadians(dRot);
-    for (int i = 0; i < 4; ++i)
-    {
-        QPointF pt = apt[i] - ptCenter;
-        qreal dX = pt.x()*cos(dAng) + pt.y()*sin(dAng);
-        qreal dY = -pt.x()*sin(dAng) + pt.y()*cos(dAng);
-
-        if (i == 0)
-        {
-            dX1 = dX2 = dX;
-            dY1 = dY2 = dY;
-        }
-        else
-        {
-            if (dX < dX1)
-            {
-                dX1 = dX;
-            }
-            else if (dX > dX2)
-            {
-                dX2 = dX;
-            }
-            if (dY < dY1)
-            {
-                dY1 = dY;
-            }
-            else if (dY > dY2)
-            {
-                dY2 = dY;
-            }
-        }
-    }
-    QRectF rect;
-    rect.setTopLeft(ptCenter + QPointF(dX1, dY1));
-    rect.setWidth(dX2 - dX1);
-    rect.setHeight(dY2 - dY1);
-    return rect;
-}
diff --git a/src/libs/vtools/tools/vtextgraphicsitem.h b/src/libs/vtools/tools/vtextgraphicsitem.h
index 923b91ac2..1748ddc9c 100644
--- a/src/libs/vtools/tools/vtextgraphicsitem.h
+++ b/src/libs/vtools/tools/vtextgraphicsitem.h
@@ -40,6 +40,7 @@
 #include <QString>
 #include <QtGlobal>
 
+#include "vpieceitem.h"
 #include "../vlayout/vtextmanager.h"
 
 class QFont;
@@ -59,70 +60,50 @@ class VPatternPieceData;
  * which can be dragged around, resized and rotated within the parent item. The text font
  * size will be automatically updated, so that the entire text will fit into the item.
  */
-class VTextGraphicsItem : public QGraphicsObject
+class VTextGraphicsItem : public VPieceItem
 {
     Q_OBJECT
-
-    enum Mode {
-        mNormal,
-        mMove,
-        mResize,
-        mRotate
-    };
-
 public:
     explicit VTextGraphicsItem(QGraphicsItem* pParent = nullptr);
     virtual ~VTextGraphicsItem();
 
-    void                SetFont(const QFont& fnt);
-    virtual void        paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-                              QWidget *widget) Q_DECL_OVERRIDE;
+    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) Q_DECL_OVERRIDE;
+    virtual void Update() Q_DECL_OVERRIDE;
 
-    void                Reset();
-    bool                IsIdle() const;
-
-    int                 GetFontSize() const;
-    virtual QRectF      boundingRect() const Q_DECL_OVERRIDE;
-    void                AddLine(const TextLine& tl);
-    void                Clear();
-    void                SetSize(qreal fW, qreal fH);
-    void                Update();
-    bool                IsContained(QRectF rectBB, qreal dRot, qreal& dX, qreal& dY) const;
-    void                UpdateData(const QString& qsName, const VPatternPieceData& data);
-    void                UpdateData(const VAbstractPattern* pDoc, qreal dSize, qreal dHeight);
-    int                 GetTextLines() const;
+    void SetFont(const QFont& fnt);
+    int  GetFontSize() const;
+    void AddLine(const TextLine& tl);
+    void Clear();
+    void SetSize(qreal fW, qreal fH);
+    bool IsContained(QRectF rectBB, qreal dRot, qreal& dX, qreal& dY) const;
+    void UpdateData(const QString& qsName, const VPatternPieceData& data);
+    void UpdateData(const VAbstractPattern* pDoc, qreal dSize, qreal dHeight);
+    int  GetTextLines() const;
 
 protected:
-    virtual void        mousePressEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
-    virtual void        mouseMoveEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
-    virtual void        mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
-    virtual void        hoverMoveEvent(QGraphicsSceneHoverEvent* pHE) Q_DECL_OVERRIDE;
-    virtual void        hoverLeaveEvent(QGraphicsSceneHoverEvent* pHE) Q_DECL_OVERRIDE;
-    void                UpdateBox();
-    void                CorrectLabel();
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) Q_DECL_OVERRIDE;
+    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* pHE) Q_DECL_OVERRIDE;
+    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* pHE) Q_DECL_OVERRIDE;
 
-    double              GetAngle(QPointF pt) const;
+    void UpdateBox();
+    void CorrectLabel();
 
 signals:
-    void                SignalMoved(const QPointF& ptPos);
-    void                SignalResized(qreal iTW, int iFontSize);
-    void                SignalRotated(qreal dAng);
-    void                SignalShrink();
+    void SignalResized(qreal iTW, int iFontSize);
+    void SignalRotated(qreal dAng);
+    void SignalShrink();
 
 private:
-    Mode                m_eMode;
-    bool                m_bReleased;
-    QPointF             m_ptStartPos;
-    QPointF             m_ptStart;
-    QPointF             m_ptRotCenter;
-    QSizeF              m_szStart;
-    double              m_dRotation;
-    double              m_dAngle;
-    QRectF              m_rectResize;
-    QRectF              m_rectBoundingBox;
-    VTextManager        m_tm;
-
-    QRectF              GetBoundingRect(QRectF rectBB, qreal dRot) const;
+    Q_DISABLE_COPY(VTextGraphicsItem)
+    QPointF      m_ptStartPos;
+    QPointF      m_ptStart;
+    QSizeF       m_szStart;
+    double       m_dRotation;
+    double       m_dAngle;
+    QRectF       m_rectResize;
+    VTextManager m_tm;
 };
 
 #endif // VTEXTGRAPHICSITEM_H

From 121f003e7c5a8d018b842ef5cba3d0bcdb861e89 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Thu, 19 Jan 2017 12:23:42 +0200
Subject: [PATCH 175/208] Refactoring. Move grainline and lable to library
 VWidgets.

--HG--
branch : feature
---
 src/libs/vtools/tools/tools.pri                        | 10 ++--------
 src/libs/vtools/tools/vtoolseamallowance.cpp           |  1 +
 src/libs/vtools/tools/vtoolseamallowance.h             |  6 +++---
 src/libs/{vtools/tools => vwidgets}/vgrainlineitem.cpp |  0
 src/libs/{vtools/tools => vwidgets}/vgrainlineitem.h   |  0
 src/libs/{vtools/tools => vwidgets}/vpieceitem.cpp     |  0
 src/libs/{vtools/tools => vwidgets}/vpieceitem.h       |  0
 .../{vtools/tools => vwidgets}/vtextgraphicsitem.cpp   |  0
 .../{vtools/tools => vwidgets}/vtextgraphicsitem.h     |  0
 src/libs/vwidgets/vwidgets.pri                         | 10 ++++++++--
 10 files changed, 14 insertions(+), 13 deletions(-)
 rename src/libs/{vtools/tools => vwidgets}/vgrainlineitem.cpp (100%)
 rename src/libs/{vtools/tools => vwidgets}/vgrainlineitem.h (100%)
 rename src/libs/{vtools/tools => vwidgets}/vpieceitem.cpp (100%)
 rename src/libs/{vtools/tools => vwidgets}/vpieceitem.h (100%)
 rename src/libs/{vtools/tools => vwidgets}/vtextgraphicsitem.cpp (100%)
 rename src/libs/{vtools/tools => vwidgets}/vtextgraphicsitem.h (100%)

diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri
index ee9c190a6..99d8e4bcb 100644
--- a/src/libs/vtools/tools/tools.pri
+++ b/src/libs/vtools/tools/tools.pri
@@ -51,8 +51,6 @@ HEADERS += \
     $$PWD/drawTools/toolcurve/vtoolcubicbezier.h \
     $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.h \
     $$PWD/drawTools/operation/vtoolrotation.h \
-    $$PWD/vtextgraphicsitem.h \
-    $$PWD/vgrainlineitem.h \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyline.h \
     $$PWD/drawTools/operation/vabstractoperation.h \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.h \
@@ -61,8 +59,7 @@ HEADERS += \
     $$PWD/drawTools/toolcurve/vtoolellipticalarc.h \
     $$PWD/nodeDetails/vnodeellipticalarc.h \
     $$PWD/vtoolseamallowance.h \
-    $$PWD/nodeDetails/vtoolpiecepath.h \
-    $$PWD/vpieceitem.h
+    $$PWD/nodeDetails/vtoolpiecepath.h
 
 SOURCES += \
     $$PWD/vtooldetail.cpp \
@@ -111,8 +108,6 @@ SOURCES += \
     $$PWD/drawTools/toolcurve/vtoolcubicbezier.cpp \
     $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.cpp \
     $$PWD/drawTools/operation/vtoolrotation.cpp \
-    $$PWD/vtextgraphicsitem.cpp \
-    $$PWD/vgrainlineitem.cpp \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyline.cpp \
     $$PWD/drawTools/operation/vabstractoperation.cpp \
     $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.cpp \
@@ -121,5 +116,4 @@ SOURCES += \
     $$PWD/drawTools/toolcurve/vtoolellipticalarc.cpp \
     $$PWD/nodeDetails/vnodeellipticalarc.cpp \
     $$PWD/vtoolseamallowance.cpp \
-    $$PWD/nodeDetails/vtoolpiecepath.cpp \
-    $$PWD/vpieceitem.cpp
+    $$PWD/nodeDetails/vtoolpiecepath.cpp
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 3800846ac..9fcc89f9d 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -53,6 +53,7 @@
 #include "../undocommands/savepieceoptions.h"
 #include "../undocommands/togglepieceinlayout.h"
 #include "../vwidgets/vmaingraphicsview.h"
+#include "../vwidgets/vnobrushscalepathitem.h"
 
 #include <QGraphicsSceneMouseEvent>
 #include <QGraphicsView>
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 1c8b1a2e3..f3f0f8111 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -34,14 +34,14 @@
 #include <QObject>
 #include <QGraphicsPathItem>
 
-#include "../vwidgets/vnobrushscalepathitem.h"
 #include "vabstracttool.h"
-#include "vtextgraphicsitem.h"
-#include "vgrainlineitem.h"
+#include "../vwidgets/vtextgraphicsitem.h"
+#include "../vwidgets/vgrainlineitem.h"
 
 class VMainGraphicsScene;
 class DialogTool;
 class VPiece;
+class VNoBrushScalePathItem;
 
 class VToolSeamAllowance : public VAbstractTool, public QGraphicsPathItem
 {
diff --git a/src/libs/vtools/tools/vgrainlineitem.cpp b/src/libs/vwidgets/vgrainlineitem.cpp
similarity index 100%
rename from src/libs/vtools/tools/vgrainlineitem.cpp
rename to src/libs/vwidgets/vgrainlineitem.cpp
diff --git a/src/libs/vtools/tools/vgrainlineitem.h b/src/libs/vwidgets/vgrainlineitem.h
similarity index 100%
rename from src/libs/vtools/tools/vgrainlineitem.h
rename to src/libs/vwidgets/vgrainlineitem.h
diff --git a/src/libs/vtools/tools/vpieceitem.cpp b/src/libs/vwidgets/vpieceitem.cpp
similarity index 100%
rename from src/libs/vtools/tools/vpieceitem.cpp
rename to src/libs/vwidgets/vpieceitem.cpp
diff --git a/src/libs/vtools/tools/vpieceitem.h b/src/libs/vwidgets/vpieceitem.h
similarity index 100%
rename from src/libs/vtools/tools/vpieceitem.h
rename to src/libs/vwidgets/vpieceitem.h
diff --git a/src/libs/vtools/tools/vtextgraphicsitem.cpp b/src/libs/vwidgets/vtextgraphicsitem.cpp
similarity index 100%
rename from src/libs/vtools/tools/vtextgraphicsitem.cpp
rename to src/libs/vwidgets/vtextgraphicsitem.cpp
diff --git a/src/libs/vtools/tools/vtextgraphicsitem.h b/src/libs/vwidgets/vtextgraphicsitem.h
similarity index 100%
rename from src/libs/vtools/tools/vtextgraphicsitem.h
rename to src/libs/vwidgets/vtextgraphicsitem.h
diff --git a/src/libs/vwidgets/vwidgets.pri b/src/libs/vwidgets/vwidgets.pri
index 042607eb2..1f3219b8f 100644
--- a/src/libs/vwidgets/vwidgets.pri
+++ b/src/libs/vwidgets/vwidgets.pri
@@ -11,7 +11,10 @@ SOURCES += \
     $$PWD/vabstractsimple.cpp \
     $$PWD/vnobrushscalepathitem.cpp \
     $$PWD/vsimplecurve.cpp \
-    $$PWD/vabstractmainwindow.cpp
+    $$PWD/vabstractmainwindow.cpp \
+    $$PWD/vtextgraphicsitem.cpp \
+    $$PWD/vgrainlineitem.cpp \
+    $$PWD/vpieceitem.cpp
 
 win32-msvc*:SOURCES += $$PWD/stable.cpp
 
@@ -26,4 +29,7 @@ HEADERS += \
     $$PWD/vabstractsimple.h \
     $$PWD/vnobrushscalepathitem.h \
     $$PWD/vsimplecurve.h \
-    $$PWD/vabstractmainwindow.h
+    $$PWD/vabstractmainwindow.h \
+    $$PWD/vtextgraphicsitem.h \
+    $$PWD/vgrainlineitem.h \
+    $$PWD/vpieceitem.h

From 25a2717682403878966c4d32089ba4440eeb970f Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Fri, 20 Jan 2017 15:58:35 +0200
Subject: [PATCH 176/208] Added new local variable "CurrentSeamAllowance".

--HG--
branch : feature
---
 src/libs/ifc/ifcdef.cpp                       | 48 ++++++++++---------
 src/libs/ifc/ifcdef.h                         |  1 +
 src/libs/vpatterndb/vtranslatevars.cpp        |  2 +
 .../TranslationsTest/tst_buitinregexp.cpp     |  1 +
 4 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp
index 99a936f47..eb5565f02 100644
--- a/src/libs/ifc/ifcdef.cpp
+++ b/src/libs/ifc/ifcdef.cpp
@@ -167,29 +167,30 @@ const QString ColorDeepSkyBlue      = QStringLiteral("deepskyblue");
 const QString ColorCornFlowerBlue   = QStringLiteral("cornflowerblue");
 
 //variables
-const QString line_           = QStringLiteral("Line_");
-const QString angleLine_      = QStringLiteral("AngleLine_");
-const QString spl_            = QStringLiteral(SPL_);
-const QString arc_            = QStringLiteral(ARC_);
-const QString splPath         = QStringLiteral("SplPath");
-const QString radius_V        = QStringLiteral("Radius");
-const QString radiusArc_      = radius_V + arc_;
-const QString angle1_V        = QStringLiteral("Angle1");
-const QString angle2_V        = QStringLiteral("Angle2");
-const QString c1Length_V      = QStringLiteral("C1Length");
-const QString c2Length_V      = QStringLiteral("C2Length");
-const QString c1LengthSpl_    = c1Length_V + spl_;
-const QString c2LengthSpl_    = c2Length_V + spl_;
-const QString c1LengthSplPath = c1Length_V + splPath;
-const QString c2LengthSplPath = c2Length_V + splPath;
-const QString angle1Arc_      = angle1_V + arc_;
-const QString angle2Arc_      = angle2_V + arc_;
-const QString angle1Spl_      = angle1_V + spl_;
-const QString angle2Spl_      = angle2_V + spl_;
-const QString angle1SplPath   = angle1_V + splPath;
-const QString angle2SplPath   = angle2_V + splPath;
-const QString seg_            = QStringLiteral("Seg_");
-const QString currentLength   = QStringLiteral("CurrentLength");
+const QString line_                = QStringLiteral("Line_");
+const QString angleLine_           = QStringLiteral("AngleLine_");
+const QString spl_                 = QStringLiteral(SPL_);
+const QString arc_                 = QStringLiteral(ARC_);
+const QString splPath              = QStringLiteral("SplPath");
+const QString radius_V             = QStringLiteral("Radius");
+const QString radiusArc_           = radius_V + arc_;
+const QString angle1_V             = QStringLiteral("Angle1");
+const QString angle2_V             = QStringLiteral("Angle2");
+const QString c1Length_V           = QStringLiteral("C1Length");
+const QString c2Length_V           = QStringLiteral("C2Length");
+const QString c1LengthSpl_         = c1Length_V + spl_;
+const QString c2LengthSpl_         = c2Length_V + spl_;
+const QString c1LengthSplPath      = c1Length_V + splPath;
+const QString c2LengthSplPath      = c2Length_V + splPath;
+const QString angle1Arc_           = angle1_V + arc_;
+const QString angle2Arc_           = angle2_V + arc_;
+const QString angle1Spl_           = angle1_V + spl_;
+const QString angle2Spl_           = angle2_V + spl_;
+const QString angle1SplPath        = angle1_V + splPath;
+const QString angle2SplPath        = angle2_V + splPath;
+const QString seg_                 = QStringLiteral("Seg_");
+const QString currentLength        = QStringLiteral("CurrentLength");
+const QString currentSeamAllowance = QStringLiteral("CurrentSeamAllowance");
 
 const QStringList builInVariables = QStringList() << line_
                                                   << angleLine_
@@ -205,6 +206,7 @@ const QStringList builInVariables = QStringList() << line_
                                                   << angle2SplPath
                                                   << seg_
                                                   << currentLength
+                                                  << currentSeamAllowance
                                                   << c1LengthSpl_
                                                   << c2LengthSpl_
                                                   << c1LengthSplPath
diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h
index eddb84df5..143fee251 100644
--- a/src/libs/ifc/ifcdef.h
+++ b/src/libs/ifc/ifcdef.h
@@ -197,6 +197,7 @@ extern const QString angle1SplPath;
 extern const QString angle2SplPath;
 extern const QString seg_;
 extern const QString currentLength;
+extern const QString currentSeamAllowance;
 
 extern const QStringList builInVariables;
 
diff --git a/src/libs/vpatterndb/vtranslatevars.cpp b/src/libs/vpatterndb/vtranslatevars.cpp
index e3b51c091..2fce248c3 100644
--- a/src/libs/vpatterndb/vtranslatevars.cpp
+++ b/src/libs/vpatterndb/vtranslatevars.cpp
@@ -388,6 +388,8 @@ void VTranslateVars::InitVariables()
                                               "Do not add symbol _ to the end of the name"));
     variables.insert(seg_, translate("VTranslateVars", "Seg_", "Segment. Left symbol _ in the name"));
     variables.insert(currentLength, translate("VTranslateVars", "CurrentLength", "Do not add space between words"));
+    variables.insert(currentSeamAllowance, translate("VTranslateVars", "CurrentSeamAllowance",
+                                                     "Do not add space between words"));
     variables.insert(c1LengthSpl_, translate("VTranslateVars", "C1LengthSpl_", "Left symbol _ in the name"));
     variables.insert(c2LengthSpl_, translate("VTranslateVars", "C2LengthSpl_", "Left symbol _ in the name"));
     variables.insert(c1LengthSplPath, translate("VTranslateVars", "C1LengthSplPath",
diff --git a/src/test/TranslationsTest/tst_buitinregexp.cpp b/src/test/TranslationsTest/tst_buitinregexp.cpp
index 60a2b30e3..1ae953068 100644
--- a/src/test/TranslationsTest/tst_buitinregexp.cpp
+++ b/src/test/TranslationsTest/tst_buitinregexp.cpp
@@ -138,6 +138,7 @@ void TST_BuitInRegExp::TestCheckUnderlineExists_data()
     data.insert(angle2SplPath, false);
     data.insert(seg_, true);
     data.insert(currentLength, false);
+    data.insert(currentSeamAllowance, false);
     data.insert(c1LengthSpl_, true);
     data.insert(c2LengthSpl_, true);
     data.insert(c1LengthSplPath, false);

From 0ef10c01b0a8f8d6f1efb675f7f6abf0f5c82320 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 15:24:40 +0200
Subject: [PATCH 177/208] A piece seam allowance can be controlled by formula.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp            |  19 +-
 src/app/valentina/xml/vpattern.h              |   2 +-
 src/libs/ifc/schema/pattern/v0.4.0.xsd        |  10 +-
 src/libs/ifc/xml/vabstractpattern.cpp         |  10 +-
 src/libs/vpatterndb/vnodedetail.cpp           |  16 +-
 src/libs/vpatterndb/vpiece.cpp                |  14 +
 src/libs/vpatterndb/vpiece.h                  |   3 +
 src/libs/vpatterndb/vpiece_p.h                |   8 +-
 src/libs/vpatterndb/vpiecenode.cpp            |  69 +-
 src/libs/vpatterndb/vpiecenode.h              |  19 +-
 src/libs/vpatterndb/vpiecenode_p.h            |   9 +
 src/libs/vpatterndb/vpiecepath.cpp            |   8 +-
 .../support/dialogeditwrongformula.cpp        |  11 +-
 .../dialogs/support/dialogeditwrongformula.h  |   2 +
 .../vtools/dialogs/tools/dialogpiecepath.cpp  | 418 ++++++++---
 .../vtools/dialogs/tools/dialogpiecepath.h    |  44 +-
 .../vtools/dialogs/tools/dialogpiecepath.ui   | 680 +++++++++++++++---
 .../dialogs/tools/dialogseamallowance.cpp     | 365 ++++++++--
 .../dialogs/tools/dialogseamallowance.h       |  40 +-
 .../dialogs/tools/dialogseamallowance.ui      | 673 ++++++++++++++---
 src/libs/vtools/dialogs/tools/dialogtool.cpp  |  15 +-
 src/libs/vtools/dialogs/tools/dialogtool.h    |   2 +-
 src/libs/vtools/tools/drawTools/vdrawtool.cpp |  95 ---
 src/libs/vtools/tools/drawTools/vdrawtool.h   |   1 -
 src/libs/vtools/tools/vabstracttool.cpp       | 105 ++-
 src/libs/vtools/tools/vabstracttool.h         |   2 +
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  24 +-
 src/libs/vtools/tools/vtoolseamallowance.h    |   2 +-
 src/libs/vtools/tools/vtooluniondetails.cpp   |   7 +-
 29 files changed, 2144 insertions(+), 529 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 5c1479232..6bee26a2b 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -296,8 +296,9 @@ void VPattern::setCurrentData()
 
                 const VDataTool *vTool = tools.value(id);
                 *data = vTool->getData();
-                //Delete special variable if exist
+                //Delete special variables if exist
                 data->RemoveVariable(currentLength);
+                data->RemoveVariable(currentSeamAllowance);
                 qCDebug(vXML, "Data successfully updated.");
             }
             else
@@ -690,7 +691,7 @@ void VPattern::ParseDrawMode(const QDomNode &node, const Document &parse, const
  * @param domElement tag in xml tree.
  * @param parse parser file mode.
  */
-void VPattern::ParseDetailElement(const QDomElement &domElement, const Document &parse)
+void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse)
 {
     Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
     try
@@ -701,12 +702,13 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
         detail.SetMx(qApp->toPixel(GetParametrDouble(domElement, AttrMx, "0.0")));
         detail.SetMy(qApp->toPixel(GetParametrDouble(domElement, AttrMy, "0.0")));
         detail.SetSeamAllowance(GetParametrBool(domElement, VToolSeamAllowance::AttrSeamAllowance, falseStr));
-        detail.SetSAWidth(GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0.0"));
         detail.SetForbidFlipping(GetParametrBool(domElement, VToolSeamAllowance::AttrForbidFlipping,
                                            QString().setNum(qApp->ValentinaSettings()->GetForbidWorkpieceFlipping())));
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
         detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
+        const QString width = GetParametrString(domElement, VToolSeamAllowance::AttrWidth, "0.0");
+        QString w = width;//need for saving fixed formula;
         const uint version = GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
 
         const QStringList tags = QStringList() << TagNodes
@@ -757,7 +759,14 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
                 }
             }
         }
-        VToolSeamAllowance::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile);
+        VToolSeamAllowance::Create(id, detail, w, sceneDetail, this, data, parse, Source::FromFile);
+        //Rewrite attribute formula. Need for situation when we have wrong formula.
+        if (w != width)
+        {
+            SetAttribute(domElement, VToolSeamAllowance::AttrWidth, w);
+            modified = true;
+            haveLiteChange();
+        }
     }
     catch (const VExceptionBadId &e)
     {
@@ -877,7 +886,7 @@ void VPattern::ParseDetails(const QDomElement &domElement, const Document &parse
     {
         if (domNode.isElement())
         {
-            const QDomElement domElement = domNode.toElement();
+            QDomElement domElement = domNode.toElement();
             if (domElement.isNull() == false)
             {
                 if (domElement.tagName() == TagDetail)
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 31cff3136..19a3010a7 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -118,7 +118,7 @@ private:
 
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
-    void           ParseDetailElement(const QDomElement &domElement, const Document &parse);
+    void           ParseDetailElement(QDomElement &domElement, const Document &parse);
     void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
     void           ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePiecePatternInfo(const QDomElement &domElement, VPiece &detail) const;
diff --git a/src/libs/ifc/schema/pattern/v0.4.0.xsd b/src/libs/ifc/schema/pattern/v0.4.0.xsd
index fd1f4d635..bcb5da26f 100644
--- a/src/libs/ifc/schema/pattern/v0.4.0.xsd
+++ b/src/libs/ifc/schema/pattern/v0.4.0.xsd
@@ -370,8 +370,8 @@
                                             <xs:attribute name="type" type="xs:string" use="required"/>
                                             <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
                                             <xs:attribute name="reverse" type="xs:unsignedInt"/>
-                                            <xs:attribute name="before" type="xs:double"/>
-                                            <xs:attribute name="after" type="xs:double"/>
+                                            <xs:attribute name="before" type="xs:string"/>
+                                            <xs:attribute name="after" type="xs:string"/>
                                             <xs:attribute name="angle" type="nodeAngle"/>
                                           </xs:complexType>
                                         </xs:element>
@@ -503,8 +503,8 @@
                                     <xs:attribute name="type" type="xs:string" use="required"/>
                                     <xs:attribute name="idObject" type="xs:unsignedInt" use="required"/>
                                     <xs:attribute name="reverse" type="xs:unsignedInt"/>
-                                    <xs:attribute name="before" type="xs:double"/>
-                                    <xs:attribute name="after" type="xs:double"/>
+                                    <xs:attribute name="before" type="xs:string"/>
+                                    <xs:attribute name="after" type="xs:string"/>
                                     <xs:attribute name="angle" type="nodeAngle"/>
                                     <xs:attribute name="mx" type="xs:double"/>
                                     <xs:attribute name="my" type="xs:double"/>
@@ -547,7 +547,7 @@
                         <xs:attribute name="name" type="xs:string"/>
                         <xs:attribute name="inLayout" type="xs:boolean"/>
                         <xs:attribute name="forbidFlipping" type="xs:boolean"/>
-                        <xs:attribute name="width" type="xs:double"/>
+                        <xs:attribute name="width" type="xs:string"/>
                         <xs:attribute name="seamAllowance" type="xs:boolean"/>
                         <xs:attribute name="united" type="xs:boolean"/>
                         <xs:attribute name="closed" type="xs:unsignedInt"/>
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index f51ea8eaf..87755a387 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -634,8 +634,10 @@ VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
 {
     const quint32 id = VDomDocument::GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
     const bool reverse = VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
-    const qreal saBefore = VDomDocument::GetParametrDouble(domElement, VAbstractPattern::AttrSABefore, "-1");
-    const qreal saAfter = VDomDocument::GetParametrDouble(domElement, VAbstractPattern::AttrSAAfter, "-1");
+    const QString saBefore = VDomDocument::GetParametrString(domElement, VAbstractPattern::AttrSABefore,
+                                                             currentSeamAllowance);
+    const QString saAfter = VDomDocument::GetParametrString(domElement, VAbstractPattern::AttrSAAfter,
+                                                            currentSeamAllowance);
     const PieceNodeAngle angle = static_cast<PieceNodeAngle>(VDomDocument::GetParametrUInt(domElement, AttrAngle, "0"));
 
     const QString t = VDomDocument::GetParametrString(domElement, AttrType, VAbstractPattern::NodePoint);
@@ -669,8 +671,8 @@ VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
             throw e;
     }
     VPieceNode node(id, tool, reverse);
-    node.SetSABefore(saBefore);
-    node.SetSAAfter(saAfter);
+    node.SetFormulaSABefore(saBefore);
+    node.SetFormulaSAAfter(saAfter);
     node.SetAngleType(angle);
 
     return node;
diff --git a/src/libs/vpatterndb/vnodedetail.cpp b/src/libs/vpatterndb/vnodedetail.cpp
index a26b86887..b7fcf60ba 100644
--- a/src/libs/vpatterndb/vnodedetail.cpp
+++ b/src/libs/vpatterndb/vnodedetail.cpp
@@ -199,29 +199,29 @@ QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<V
 
                     if (IsSABefore(QLineF(point, previosPoint), QLineF(point, xPoint)))
                     {
-                        path[i].SetSABefore(LocalWidth(node.getMx()));
+                        path[i].SetFormulaSABefore(QString().setNum(LocalWidth(node.getMx())));
 
                         if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
                         {
-                            path[i].SetSAAfter(LocalWidth(node.getMy()));
+                            path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMy())));
                         }
                     }
                     else if (IsSABefore(QLineF(point, previosPoint), QLineF(point, yPoint)))
                     {
-                        path[i].SetSABefore(LocalWidth(node.getMy()));
+                        path[i].SetFormulaSABefore(QString().setNum(LocalWidth(node.getMy())));
 
                         if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
                         {
-                            path[i].SetSAAfter(LocalWidth(node.getMx()));
+                            path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMx())));
                         }
                     }
                     else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
                     {
-                        path[i].SetSAAfter(LocalWidth(node.getMx()));
+                        path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMx())));
                     }
                     else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
                     {
-                        path[i].SetSAAfter(LocalWidth(node.getMy()));
+                        path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMy())));
                     }
                 }
             }
@@ -230,8 +230,8 @@ QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<V
 
     if (not closed && path.CountNodes() > 1)
     {
-        path[0].SetSABefore(0);
-        path[path.CountNodes()-1].SetSAAfter(0);
+        path[0].SetFormulaSABefore("0");
+        path[path.CountNodes()-1].SetFormulaSAAfter("0");
     }
 
     return path.GetNodes();
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 9fc8a2a10..85200418d 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -269,6 +269,20 @@ void VPiece::SetUnited(bool united)
     d->m_united = united;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QString VPiece::GetFormulaSAWidth() const
+{
+    return d->m_formulaWidth;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPiece::SetFormulaSAWidth(const QString &formula, qreal value)
+{
+    SetSAWidth(value);
+    const qreal width = GetSAWidth();
+    width >= 0 ? d->m_formulaWidth = formula : d->m_formulaWidth = QLatin1String("0");
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<quint32> VPiece::GetInternalPaths() const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index fcd2c9948..0ea0180e4 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -79,6 +79,9 @@ public:
     bool IsUnited() const;
     void SetUnited(bool united);
 
+    QString GetFormulaSAWidth() const;
+    void    SetFormulaSAWidth(const QString &formula, qreal value);
+
     QVector<quint32> GetInternalPaths() const;
     void             SetInternalPaths(const QVector<quint32> &iPaths);
     void             AppendInternalPath(quint32 path);
diff --git a/src/libs/vpatterndb/vpiece_p.h b/src/libs/vpatterndb/vpiece_p.h
index 53791ae3b..f937e8488 100644
--- a/src/libs/vpatterndb/vpiece_p.h
+++ b/src/libs/vpatterndb/vpiece_p.h
@@ -56,7 +56,8 @@ public:
           m_internalPaths(),
           m_ppData(),
           m_piPatternInfo(),
-          m_glGrainline()
+          m_glGrainline(),
+          m_formulaWidth("0")
     {}
 
     VPieceData(const VPieceData &detail)
@@ -70,7 +71,8 @@ public:
           m_internalPaths(detail.m_internalPaths),
           m_ppData(detail.m_ppData),
           m_piPatternInfo(detail.m_piPatternInfo),
-          m_glGrainline(detail.m_glGrainline)
+          m_glGrainline(detail.m_glGrainline),
+          m_formulaWidth(detail.m_formulaWidth)
     {}
 
     ~VPieceData();
@@ -96,6 +98,8 @@ public:
     /** @brief m_glGrainline grainline geometry object*/
     VGrainlineGeometry m_glGrainline;
 
+    QString m_formulaWidth;
+
 private:
     VPieceData &operator=(const VPieceData &) Q_DECL_EQ_DELETE;
 };
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index 1401121eb..a03d7e476 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -28,8 +28,11 @@
 
 #include "vpiecenode.h"
 #include "vpiecenode_p.h"
+#include "vcontainer.h"
+#include "calculator.h"
 
 #include <QDataStream>
+#include <QtNumeric>
 
 //---------------------------------------------------------------------------------------------------------------------
 VPieceNode::VPieceNode()
@@ -101,15 +104,15 @@ void VPieceNode::SetReverse(bool reverse)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VPieceNode::GetSABefore() const
+qreal VPieceNode::GetSABefore(const VContainer *data) const
 {
-    return d->m_saBefore;
+    return EvalFormula(data, d->m_formulaWidthBefore);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VPieceNode::GetSABefore(Unit unit) const
+qreal VPieceNode::GetSABefore(const VContainer *data, Unit unit) const
 {
-    qreal value = d->m_saBefore;
+    qreal value = EvalFormula(data, d->m_formulaWidthBefore);
     if (value >= 0)
     {
         value = ToPixel(value, unit);
@@ -118,24 +121,30 @@ qreal VPieceNode::GetSABefore(Unit unit) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPieceNode::SetSABefore(qreal value)
+QString VPieceNode::GetFormulaSABefore() const
+{
+    return d->m_formulaWidthBefore;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetFormulaSABefore(const QString &formula)
 {
     if (d->m_typeTool == Tool::NodePoint)
     {
-        value < 0 ? d->m_saBefore = -1: d->m_saBefore = value;
+        d->m_formulaWidthBefore = formula;
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VPieceNode::GetSAAfter() const
+qreal VPieceNode::GetSAAfter(const VContainer *data) const
 {
-    return d->m_saAfter;
+    return EvalFormula(data, d->m_formulaWidthAfter);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VPieceNode::GetSAAfter(Unit unit) const
+qreal VPieceNode::GetSAAfter(const VContainer *data, Unit unit) const
 {
-    qreal value = d->m_saAfter;
+    qreal value = EvalFormula(data, d->m_formulaWidthAfter);
     if (value >= 0)
     {
         value = ToPixel(value, unit);
@@ -144,11 +153,17 @@ qreal VPieceNode::GetSAAfter(Unit unit) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPieceNode::SetSAAfter(qreal value)
+QString VPieceNode::GetFormulaSAAfter() const
+{
+    return d->m_formulaWidthAfter;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VPieceNode::SetFormulaSAAfter(const QString &formula)
 {
     if (d->m_typeTool == Tool::NodePoint)
     {
-        value < 0 ? d->m_saAfter = -1: d->m_saAfter = value;
+        d->m_formulaWidthAfter = formula;
     }
 }
 
@@ -167,6 +182,36 @@ void VPieceNode::SetAngleType(PieceNodeAngle type)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+qreal VPieceNode::EvalFormula(const VContainer *data, QString formula) const
+{
+    if (formula.isEmpty())
+    {
+        return -1;
+    }
+    else
+    {
+        try
+        {
+            // Replace line return character with spaces for calc if exist
+            formula.replace("\n", " ");
+            QScopedPointer<Calculator> cal(new Calculator());
+            const qreal result = cal->EvalFormula(data->PlainVariables(), formula);
+
+            if (qIsInf(result) || qIsNaN(result))
+            {
+                return -1;
+            }
+            return result;
+        }
+        catch (qmu::QmuParserError &e)
+        {
+            Q_UNUSED(e)
+            return -1;
+        }
+    }
+}
+
 // Friend functions
 //---------------------------------------------------------------------------------------------------------------------
 QDataStream& operator<<(QDataStream& out, const VPieceNode& p)
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 89c212cb2..9114b6c33 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -37,6 +37,7 @@
 
 class VPieceNodeData;
 class QDataStream;
+class VContainer;
 
 class VPieceNode
 {
@@ -59,18 +60,24 @@ public:
     bool GetReverse() const;
     void SetReverse(bool reverse);
 
-    qreal GetSABefore() const;
-    qreal GetSABefore(Unit unit) const;
-    void  SetSABefore(qreal value);
+    qreal GetSABefore(const VContainer *data) const;
+    qreal GetSABefore(const VContainer *data, Unit unit) const;
 
-    qreal GetSAAfter() const;
-    qreal GetSAAfter(Unit unit) const;
-    void  SetSAAfter(qreal value);
+    QString GetFormulaSABefore() const;
+    void    SetFormulaSABefore(const QString &formula);
+
+    qreal GetSAAfter(const VContainer *data) const;
+    qreal GetSAAfter(const VContainer *data, Unit unit) const;
+
+    QString GetFormulaSAAfter() const;
+    void    SetFormulaSAAfter(const QString &formula);
 
     PieceNodeAngle GetAngleType() const;
     void           SetAngleType(PieceNodeAngle type);
 private:
     QSharedDataPointer<VPieceNodeData> d;
+
+    qreal EvalFormula(const VContainer *data, QString formula) const;
 };
 
 Q_DECLARE_METATYPE(VPieceNode)
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index 25a1c0bad..98c6c6797 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -45,6 +45,8 @@ public:
           m_reverse(false),
           m_saBefore(-1),
           m_saAfter(-1),
+          m_formulaWidthBefore("-1"),
+          m_formulaWidthAfter("-1"),
           m_angleType(PieceNodeAngle::ByLength)
     {}
 
@@ -54,6 +56,8 @@ public:
           m_reverse(reverse),
           m_saBefore(-1),
           m_saAfter(-1),
+          m_formulaWidthBefore("-1"),
+          m_formulaWidthAfter("-1"),
           m_angleType(PieceNodeAngle::ByLength)
     {
         if (m_typeTool == Tool::NodePoint)
@@ -69,6 +73,8 @@ public:
           m_reverse(node.m_reverse),
           m_saBefore(node.m_saBefore),
           m_saAfter(node.m_saAfter),
+          m_formulaWidthBefore(node.m_formulaWidthBefore),
+          m_formulaWidthAfter(node.m_formulaWidthAfter),
           m_angleType(node.m_angleType)
     {}
 
@@ -86,6 +92,9 @@ public:
     qreal m_saBefore;
     qreal m_saAfter;
 
+    QString m_formulaWidthBefore;
+    QString m_formulaWidthAfter;
+
     PieceNodeAngle m_angleType;
 
 private:
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 9d3e6216d..2a35473e4 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -656,8 +656,8 @@ VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *d
     const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
     VSAPoint p(point->toQPointF());
 
-    p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-    p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+    p.SetSAAfter(node.GetSAAfter(data, *data->GetPatternUnit()));
+    p.SetSABefore(node.GetSABefore(data, *data->GetPatternUnit()));
     p.SetAngleType(node.GetAngleType());
 
     return p;
@@ -762,8 +762,8 @@ VSAPoint VPiecePath::CurvePoint(const VSAPoint &candidate, const VContainer *dat
         if (curve->IsPointOnCurve(p))
         {
             point = VSAPoint(p);
-            point.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
-            point.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
+            point.SetSAAfter(node.GetSAAfter(data, *data->GetPatternUnit()));
+            point.SetSABefore(node.GetSABefore(data, *data->GetPatternUnit()));
             point.SetAngleType(node.GetAngleType());
         }
     }
diff --git a/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp b/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp
index 731b3d2ab..db8590590 100644
--- a/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp
+++ b/src/libs/vtools/dialogs/support/dialogeditwrongformula.cpp
@@ -77,7 +77,7 @@ enum {ColumnName = 0, ColumnFullName};
 //---------------------------------------------------------------------------------------------------------------------
 DialogEditWrongFormula::DialogEditWrongFormula(const VContainer *data, const quint32 &toolId, QWidget *parent)
     :DialogTool(data, toolId, parent), ui(new Ui::DialogEditWrongFormula), formula(QString()), formulaBaseHeight(0),
-      checkZero(false), postfix(QString()), restoreCursor(false)
+      checkZero(false), checkLessThanZero(false), postfix(QString()), restoreCursor(false)
 {
     ui->setupUi(this);
     InitVariables();
@@ -156,7 +156,8 @@ void DialogEditWrongFormula::EvalFormula()
 {
     SCASSERT(plainTextEditFormula != nullptr)
     SCASSERT(labelResultCalculation != nullptr)
-    Eval(plainTextEditFormula->toPlainText(), flagFormula, labelResultCalculation, postfix, checkZero);
+    Eval(plainTextEditFormula->toPlainText(), flagFormula, labelResultCalculation, postfix, checkZero,
+         checkLessThanZero);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -383,6 +384,12 @@ void DialogEditWrongFormula::setCheckZero(bool value)
     checkZero = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogEditWrongFormula::setCheckLessThanZero(bool value)
+{
+
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogEditWrongFormula::setPostfix(const QString &value)
 {
diff --git a/src/libs/vtools/dialogs/support/dialogeditwrongformula.h b/src/libs/vtools/dialogs/support/dialogeditwrongformula.h
index 247aeb33c..41b623bdd 100644
--- a/src/libs/vtools/dialogs/support/dialogeditwrongformula.h
+++ b/src/libs/vtools/dialogs/support/dialogeditwrongformula.h
@@ -70,6 +70,7 @@ public:
     QString      GetFormula() const;
     void         SetFormula(const QString &value);
     void         setCheckZero(bool value);
+    void         setCheckLessThanZero(bool value);
     void         setPostfix(const QString &value);
 public slots:
     virtual void DialogAccepted() Q_DECL_OVERRIDE;
@@ -109,6 +110,7 @@ private:
     int formulaBaseHeight;
 
     bool checkZero;
+    bool checkLessThanZero;
     QString postfix;
     bool restoreCursor;
 
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index d9d017a80..9e71a3a27 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -32,72 +32,34 @@
 #include "visualization/path/vistoolpiecepath.h"
 #include "../../tools/vabstracttool.h"
 #include "../../tools/vtoolseamallowance.h"
+#include "../support/dialogeditwrongformula.h"
 
 #include <QMenu>
+#include <QTimer>
 
 //---------------------------------------------------------------------------------------------------------------------
 DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
     : DialogTool(data, toolId, parent),
-    ui(new Ui::DialogPiecePath),
-    m_showMode(false)
+      ui(new Ui::DialogPiecePath),
+      m_showMode(false),
+      m_saWidth(0),
+      m_timerWidth(nullptr),
+      m_timerWidthBefore(nullptr),
+      m_timerWidthAfter(nullptr),
+      m_formulaBaseWidth(0),
+      m_formulaBaseWidthBefore(0),
+      m_formulaBaseWidthAfter(0)
 {
     ui->setupUi(this);
     InitOkCancel(ui);
 
-#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
-    ui->lineEditName->setClearButtonEnabled(true);
-#endif
-
-    FillComboBoxTypeLine(ui->comboBoxPenType, VAbstractTool::LineStylesPics());
-
-    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
-
-    InitPathTypes();
-    connect(ui->comboBoxType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
-            [this]()
-    {
-        ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath);
-        ValidObjects(PathIsValid());
-    });
+    InitPathTab();
+    InitSeamAllowanceTab();
 
     flagName = true;//We have default name of piece.
     flagError = PathIsValid();
     CheckState();
 
-    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
-    ui->doubleSpinBoxSeams->setSuffix(suffix);
-    ui->doubleSpinBoxSABefore->setSuffix(suffix);
-    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
-
-    if(qApp->patternUnit() == Unit::Inch)
-    {
-        ui->doubleSpinBoxSeams->setDecimals(5);
-        ui->doubleSpinBoxSABefore->setDecimals(5);
-        ui->doubleSpinBoxSAAfter->setDecimals(5);
-    }
-
-    InitNodesList();
-    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogPiecePath::NodeChanged);
-
-    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefBefore);
-    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefAfter);
-
-    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
-
-    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogPiecePath::ChangedSABefore);
-    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogPiecePath::ChangedSAAfter);
-
-    InitNodeAngles(ui->comboBoxAngle);
-    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
-            &DialogPiecePath::NodeAngleChanged);
-
-    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogPiecePath::ShowContextMenu);
-
     vis = new VisToolPiecePath(data);
 
     ui->tabWidget->removeTab(1);
@@ -314,14 +276,18 @@ void DialogPiecePath::NameChanged()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::NodeChanged(int index)
 {
-    ui->doubleSpinBoxSABefore->setDisabled(true);
-    ui->doubleSpinBoxSAAfter->setDisabled(true);
+    ui->plainTextEditFormulaWidthBefore->setDisabled(true);
+    ui->toolButtonExprBefore->setDisabled(true);
     ui->pushButtonDefBefore->setDisabled(true);
+
+    ui->plainTextEditFormulaWidthAfter->setDisabled(true);
+    ui->toolButtonExprAfter->setDisabled(true);
     ui->pushButtonDefAfter->setDisabled(true);
+
     ui->comboBoxAngle->setDisabled(true);
 
-    ui->doubleSpinBoxSABefore->blockSignals(true);
-    ui->doubleSpinBoxSAAfter->blockSignals(true);
+    ui->plainTextEditFormulaWidthBefore->blockSignals(true);
+    ui->plainTextEditFormulaWidthAfter->blockSignals(true);
     ui->comboBoxAngle->blockSignals(true);
 
     if (index != -1)
@@ -337,32 +303,42 @@ void DialogPiecePath::NodeChanged(int index)
         {
             const VPieceNode &node = path.at(nodeIndex);
 
-            ui->doubleSpinBoxSABefore->setEnabled(true);
-            ui->doubleSpinBoxSAAfter->setEnabled(true);
-            ui->comboBoxAngle->setEnabled(true);
+            // Seam alowance before
+            ui->plainTextEditFormulaWidthBefore->setEnabled(true);
+            ui->toolButtonExprBefore->setEnabled(true);
 
-            qreal w1 = node.GetSABefore();
-            if (w1 < 0)
-            {
-                w1 = ui->doubleSpinBoxSeams->value();
-            }
-            else
+            QString w1Formula = node.GetFormulaSABefore();
+            if (w1Formula != currentSeamAllowance)
             {
                 ui->pushButtonDefBefore->setEnabled(true);
             }
-            ui->doubleSpinBoxSABefore->setValue(w1);
-
-            qreal w2 = node.GetSAAfter();
-            if (w2 < 0)
+            if (w1Formula.length() > 80)// increase height if needed.
             {
-                w2 = ui->doubleSpinBoxSeams->value();
+                this->DeployWidthBeforeFormulaTextEdit();
             }
-            else
-            {
-                ui->pushButtonDefAfter->setEnabled(true);
-            }
-            ui->doubleSpinBoxSAAfter->setValue(w2);
+            w1Formula = qApp->TrVars()->FormulaToUser(w1Formula, qApp->Settings()->GetOsSeparator());
+            ui->plainTextEditFormulaWidthBefore->setPlainText(w1Formula);
+            MoveCursorToEnd(ui->plainTextEditFormulaWidthBefore);
 
+            // Seam alowance after
+            ui->plainTextEditFormulaWidthAfter->setEnabled(true);
+            ui->toolButtonExprAfter->setEnabled(true);
+
+            QString w2Formula = node.GetFormulaSAAfter();
+            if (w2Formula != currentSeamAllowance)
+            {
+                ui->pushButtonDefBefore->setEnabled(true);
+            }
+            if (w2Formula.length() > 80)// increase height if needed.
+            {
+                this->DeployWidthAfterFormulaTextEdit();
+            }
+            w2Formula = qApp->TrVars()->FormulaToUser(w2Formula, qApp->Settings()->GetOsSeparator());
+            ui->plainTextEditFormulaWidthAfter->setPlainText(w2Formula);
+            MoveCursorToEnd(ui->plainTextEditFormulaWidthAfter);
+
+            // Angle type
+            ui->comboBoxAngle->setEnabled(true);
             const int index = ui->comboBoxAngle->findData(static_cast<unsigned char>(node.GetAngleType()));
             if (index != -1)
             {
@@ -372,38 +348,238 @@ void DialogPiecePath::NodeChanged(int index)
     }
     else
     {
-        ui->doubleSpinBoxSABefore->setValue(0);
-        ui->doubleSpinBoxSAAfter->setValue(0);
+        ui->plainTextEditFormulaWidthBefore->setPlainText("");
+        ui->plainTextEditFormulaWidthAfter->setPlainText("");
         ui->comboBoxAngle->setCurrentIndex(-1);
     }
 
-    ui->doubleSpinBoxSABefore->blockSignals(false);
-    ui->doubleSpinBoxSAAfter->blockSignals(false);
+    ui->plainTextEditFormulaWidthBefore->blockSignals(false);
+    ui->plainTextEditFormulaWidthAfter->blockSignals(false);
     ui->comboBoxAngle->blockSignals(false);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::ReturnDefBefore()
 {
-    SetCurrentSABefore(-1);
+    ui->plainTextEditFormulaWidthBefore->setPlainText(currentSeamAllowance);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogPiecePath::ReturnDefAfter()
 {
-    SetCurrentSAAfter(-1);
+    ui->plainTextEditFormulaWidthAfter->setPlainText(currentSeamAllowance);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::ChangedSABefore(double d)
+void DialogPiecePath::EvalWidth()
 {
-    SetCurrentSABefore(d);
+    labelEditFormula = ui->labelEditWidth;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidth->toPlainText();
+    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, true, true);
+
+    if (m_saWidth >= 0)
+    {
+        VContainer *locData = const_cast<VContainer *> (data);
+        locData->AddVariable(currentSeamAllowance, new VIncrement(locData, currentSeamAllowance, 0, m_saWidth,
+                                                                  QString().setNum(m_saWidth), true,
+                                                                  tr("Current seam aloowance")));
+
+        EvalWidthBefore();
+        EvalWidthAfter();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::ChangedSAAfter(double d)
+void DialogPiecePath::EvalWidthBefore()
 {
-    SetCurrentSAAfter(d);
+    labelEditFormula = ui->labelEditBefore;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidthBefore->toPlainText();
+    bool flagFormula = false; // fake flag
+    Eval(formula, flagFormula, ui->labelResultBefore, postfix, true, true);
+
+    UpdateNodeSABefore(GetFormulaSAWidthBefore());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::EvalWidthAfter()
+{
+    labelEditFormula = ui->labelEditAfter;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidthAfter->toPlainText();
+    bool flagFormula = false; // fake flag
+    Eval(formula, flagFormula, ui->labelResultAfter, postfix, true, true);
+
+    UpdateNodeSABefore(GetFormulaSAWidthAfter());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::FXWidth()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width"));
+    dialog->SetFormula(GetFormulaSAWidth());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetFormulaSAWidth(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::FXWidthBefore()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width before"));
+    dialog->SetFormula(GetFormulaSAWidthBefore());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetCurrentSABefore(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::FXWidthAfter()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width after"));
+    dialog->SetFormula(GetFormulaSAWidthAfter());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetCurrentSAAfter(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::WidthChanged()
+{
+    labelEditFormula = ui->labelEditWidth;
+    labelResultCalculation = ui->labelResultWidth;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidth, m_timerWidth, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::WidthBeforeChanged()
+{
+    labelEditFormula = ui->labelEditBefore;
+    labelResultCalculation = ui->labelResultBefore;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    bool flagFormula = false;
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidthBefore, m_timerWidthBefore, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::WidthAfterChanged()
+{
+    labelEditFormula = ui->labelEditAfter;
+    labelResultCalculation = ui->labelResultAfter;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    bool flagFormula = false;
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidthAfter, m_timerWidthAfter, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::DeployWidthFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidth, ui->pushButtonGrowWidth, m_formulaBaseWidth);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::DeployWidthBeforeFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidthBefore, ui->pushButtonGrowWidthBefore, m_formulaBaseWidthBefore);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::DeployWidthAfterFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidthAfter, ui->pushButtonGrowWidthAfter, m_formulaBaseWidthAfter);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::InitPathTab()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+    ui->lineEditName->setClearButtonEnabled(true);
+#endif
+
+    FillComboBoxTypeLine(ui->comboBoxPenType, VAbstractTool::LineStylesPics());
+
+    connect(ui->lineEditName, &QLineEdit::textChanged, this, &DialogPiecePath::NameChanged);
+
+    InitPathTypes();
+    connect(ui->comboBoxType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+            [this]()
+    {
+        ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath);
+        ValidObjects(PathIsValid());
+    });
+
+    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->listWidget, &QListWidget::customContextMenuRequested, this, &DialogPiecePath::ShowContextMenu);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::InitSeamAllowanceTab()
+{
+    plainTextEditFormula = ui->plainTextEditFormulaWidth;
+    this->m_formulaBaseWidth = ui->plainTextEditFormulaWidth->height();
+    this->m_formulaBaseWidthBefore = ui->plainTextEditFormulaWidthBefore->height();
+    this->m_formulaBaseWidthAfter = ui->plainTextEditFormulaWidthAfter->height();
+
+    ui->plainTextEditFormulaWidth->installEventFilter(this);
+    ui->plainTextEditFormulaWidthBefore->installEventFilter(this);
+    ui->plainTextEditFormulaWidthAfter->installEventFilter(this);
+
+    m_timerWidth = new QTimer(this);
+    connect(m_timerWidth, &QTimer::timeout, this, &DialogPiecePath::EvalWidth);
+
+    m_timerWidthBefore = new QTimer(this);
+    connect(m_timerWidthBefore, &QTimer::timeout, this, &DialogPiecePath::EvalWidthBefore);
+
+    m_timerWidthAfter = new QTimer(this);
+    connect(m_timerWidthAfter, &QTimer::timeout, this, &DialogPiecePath::EvalWidthAfter);
+
+    // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
+    m_saWidth = UnitConvertor(1, Unit::Cm, qApp->patternUnit());
+    ui->plainTextEditFormulaWidth->setPlainText(qApp->LocaleToString(m_saWidth));
+
+    InitNodesList();
+    connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogPiecePath::NodeChanged);
+
+    connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefBefore);
+    connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogPiecePath::ReturnDefAfter);
+
+    InitNodeAngles(ui->comboBoxAngle);
+    connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
+            &DialogPiecePath::NodeAngleChanged);
+
+    connect(ui->toolButtonExprWidth, &QPushButton::clicked, this, &DialogPiecePath::FXWidth);
+    connect(ui->toolButtonExprBefore, &QPushButton::clicked, this, &DialogPiecePath::FXWidthBefore);
+    connect(ui->toolButtonExprAfter, &QPushButton::clicked, this, &DialogPiecePath::FXWidthAfter);
+
+    connect(ui->plainTextEditFormulaWidth, &QPlainTextEdit::textChanged, this, &DialogPiecePath::WidthChanged);
+    connect(ui->plainTextEditFormulaWidthBefore, &QPlainTextEdit::textChanged, this,
+            &DialogPiecePath::WidthBeforeChanged);
+    connect(ui->plainTextEditFormulaWidthAfter, &QPlainTextEdit::textChanged, this,
+            &DialogPiecePath::WidthAfterChanged);
+
+    connect(ui->pushButtonGrowWidth, &QPushButton::clicked, this, &DialogPiecePath::DeployWidthFormulaTextEdit);
+    connect(ui->pushButtonGrowWidthBefore, &QPushButton::clicked,
+            this, &DialogPiecePath::DeployWidthBeforeFormulaTextEdit);
+    connect(ui->pushButtonGrowWidthAfter, &QPushButton::clicked, this,
+            &DialogPiecePath::DeployWidthAfterFormulaTextEdit);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -582,7 +758,21 @@ quint32 DialogPiecePath::GetLastId() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::SetCurrentSABefore(qreal value)
+void DialogPiecePath::SetCurrentSABefore(const QString &formula)
+{
+    UpdateNodeSABefore(formula);
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetCurrentSAAfter(const QString &formula)
+{
+    UpdateNodeSAAfter(formula);
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::UpdateNodeSABefore(const QString &formula)
 {
     const int index = ui->comboBoxNodes->currentIndex();
     if (index != -1)
@@ -597,16 +787,14 @@ void DialogPiecePath::SetCurrentSABefore(qreal value)
         if (rowItem)
         {
             VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
-            rowNode.SetSABefore(value);
+            rowNode.SetFormulaSABefore(formula);
             rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
-
-            ListChanged();
         }
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::SetCurrentSAAfter(qreal value)
+void DialogPiecePath::UpdateNodeSAAfter(const QString &formula)
 {
     const int index = ui->comboBoxNodes->currentIndex();
     if (index != -1)
@@ -621,14 +809,30 @@ void DialogPiecePath::SetCurrentSAAfter(qreal value)
         if (rowItem)
         {
             VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
-            rowNode.SetSAAfter(value);
+            rowNode.SetFormulaSAAfter(formula);
             rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
-
-            ListChanged();
         }
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogPiecePath::SetFormulaSAWidth(const QString &formula)
+{
+    const QString width = qApp->TrVars()->FormulaToUser(formula, qApp->Settings()->GetOsSeparator());
+    // increase height if needed.
+    if (width.length() > 80)
+    {
+        this->DeployWidthFormulaTextEdit();
+    }
+    ui->plainTextEditFormulaWidth->setPlainText(width);
+
+    VisToolPiecePath *path = qobject_cast<VisToolPiecePath *>(vis);
+    SCASSERT(path != nullptr)
+    path->SetPath(CreatePath());
+
+    MoveCursorToEnd(ui->plainTextEditFormulaWidth);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 DialogPiecePath::GetPieceId() const
 {
@@ -667,17 +871,11 @@ void DialogPiecePath::SetPieceId(quint32 id)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogPiecePath::SetSAWidth(qreal width)
+QString DialogPiecePath::GetFormulaSAWidth() const
 {
-    if (width >=0)
-    {
-        ui->tabWidget->addTab(ui->tabSeamAllowance, tr("Seam allowance"));
-        ui->doubleSpinBoxSeams->setValue(width);
-    }
-    else
-    {
-        ui->tabWidget->removeTab(1);
-    }
+    QString width = ui->plainTextEditFormulaWidth->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -758,3 +956,19 @@ void DialogPiecePath::NewItem(const VPieceNode &node)
 {
     NewNodeItem(ui->listWidget, node);
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogPiecePath::GetFormulaSAWidthBefore() const
+{
+    QString width = ui->plainTextEditFormulaWidthBefore->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogPiecePath::GetFormulaSAWidthAfter() const
+{
+    QString width = ui->plainTextEditFormulaWidthAfter->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
+}
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.h b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
index c1f06c163..4739d8ea3 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.h
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.h
@@ -51,7 +51,8 @@ public:
     quint32 GetPieceId() const;
     void    SetPieceId(quint32 id);
 
-    void SetSAWidth(qreal width);
+    QString GetFormulaSAWidth() const;
+    void    SetFormulaSAWidth(const QString &formula);
 
     virtual void SetPiecesList(const QVector<quint32> &list) Q_DECL_OVERRIDE;
 
@@ -72,14 +73,39 @@ private slots:
     void NodeChanged(int index);
     void ReturnDefBefore();
     void ReturnDefAfter();
-    void ChangedSABefore(double d);
-    void ChangedSAAfter(double d);
+
+    void EvalWidth();
+    void EvalWidthBefore();
+    void EvalWidthAfter();
+
+    void FXWidth();
+    void FXWidthBefore();
+    void FXWidthAfter();
+
+    void WidthChanged();
+    void WidthBeforeChanged();
+    void WidthAfterChanged();
+
+    void DeployWidthFormulaTextEdit();
+    void DeployWidthBeforeFormulaTextEdit();
+    void DeployWidthAfterFormulaTextEdit();
 
 private:
     Q_DISABLE_COPY(DialogPiecePath)
     Ui::DialogPiecePath *ui;
-    bool m_showMode;
+    bool  m_showMode;
+    qreal m_saWidth;
 
+    QTimer *m_timerWidth;
+    QTimer *m_timerWidthBefore;
+    QTimer *m_timerWidthAfter;
+
+    int m_formulaBaseWidth;
+    int m_formulaBaseWidthBefore;
+    int m_formulaBaseWidthAfter;
+
+    void InitPathTab();
+    void InitSeamAllowanceTab();
     void InitPathTypes();
     void InitListPieces();
     void InitNodesList();
@@ -101,8 +127,14 @@ private:
 
     quint32 GetLastId() const;
 
-    void SetCurrentSABefore(qreal value);
-    void SetCurrentSAAfter(qreal value);
+    void SetCurrentSABefore(const QString &formula);
+    void SetCurrentSAAfter(const QString &formula);
+
+    void UpdateNodeSABefore(const QString &formula);
+    void UpdateNodeSAAfter(const QString &formula);
+
+    QString GetFormulaSAWidthBefore() const;
+    QString GetFormulaSAWidthAfter() const;
 };
 
 #endif // DIALOGPIECEPATH_H
diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
index 6ee68ac25..10d360ffd 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>480</width>
-    <height>409</height>
+    <height>437</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -121,19 +121,53 @@
       <attribute name="title">
        <string>Seam allowance</string>
       </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_3">
+      <layout class="QVBoxLayout" name="verticalLayout_4">
        <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_2">
-         <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item alignment="Qt::AlignLeft">
           <widget class="QLabel" name="labelEditWidth">
            <property name="sizePolicy">
-            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
              <horstretch>0</horstretch>
              <verstretch>0</verstretch>
             </sizepolicy>
            </property>
-           <property name="locale">
-            <locale language="English" country="UnitedStates"/>
+           <property name="palette">
+            <palette>
+             <active>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </active>
+             <inactive>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>255</red>
+                 <green>0</green>
+                 <blue>0</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </inactive>
+             <disabled>
+              <colorrole role="WindowText">
+               <brush brushstyle="SolidPattern">
+                <color alpha="255">
+                 <red>159</red>
+                 <green>158</green>
+                 <blue>158</blue>
+                </color>
+               </brush>
+              </colorrole>
+             </disabled>
+            </palette>
            </property>
            <property name="text">
             <string>Width:</string>
@@ -141,29 +175,7 @@
           </widget>
          </item>
          <item>
-          <widget class="QDoubleSpinBox" name="doubleSpinBoxSeams">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="readOnly">
-            <bool>true</bool>
-           </property>
-           <property name="maximum">
-            <double>900.990000000000009</double>
-           </property>
-           <property name="singleStep">
-            <double>0.100000000000000</double>
-           </property>
-           <property name="value">
-            <double>0.000000000000000</double>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <spacer name="horizontalSpacer">
+          <spacer name="horizontalSpacer_2">
            <property name="orientation">
             <enum>Qt::Horizontal</enum>
            </property>
@@ -175,6 +187,125 @@
            </property>
           </spacer>
          </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QToolButton" name="toolButtonExprWidth">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="toolTip">
+            <string>Formula wizard</string>
+           </property>
+           <property name="text">
+            <string notr="true">...</string>
+           </property>
+           <property name="icon">
+            <iconset resource="../../../vmisc/share/resources/icon.qrc">
+             <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>24</width>
+             <height>24</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string/>
+           </property>
+           <property name="pixmap">
+            <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item alignment="Qt::AlignRight">
+          <widget class="QLabel" name="labelResultWidth">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>87</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Value</string>
+           </property>
+           <property name="text">
+            <string notr="true">_</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_6">
+         <item>
+          <widget class="QPlainTextEdit" name="plainTextEditFormulaWidth">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>28</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>Calculation</string>
+           </property>
+           <property name="tabChangesFocus">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pushButtonGrowWidth">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>18</width>
+             <height>18</height>
+            </size>
+           </property>
+           <property name="sizeIncrement">
+            <size>
+             <width>0</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="toolTip">
+            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+           <property name="text">
+            <string notr="true"/>
+           </property>
+           <property name="icon">
+            <iconset theme="go-down">
+             <normaloff>.</normaloff>.</iconset>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>16</width>
+             <height>16</height>
+            </size>
+           </property>
+           <property name="flat">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
         </layout>
        </item>
        <item>
@@ -182,44 +313,108 @@
          <property name="title">
           <string>Nodes</string>
          </property>
-         <layout class="QFormLayout" name="formLayout_2">
-          <property name="fieldGrowthPolicy">
-           <enum>QFormLayout::ExpandingFieldsGrow</enum>
-          </property>
-          <item row="0" column="0">
-           <widget class="QLabel" name="labelNode">
-            <property name="text">
-             <string>Node:</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="QComboBox" name="comboBoxNodes"/>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="labelSABefore">
-            <property name="toolTip">
-             <string>Seam allowance before node</string>
-            </property>
-            <property name="text">
-             <string>Before:</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <layout class="QHBoxLayout" name="horizontalLayout">
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_5">
             <item>
-             <widget class="QDoubleSpinBox" name="doubleSpinBoxSABefore">
-              <property name="maximum">
-               <double>900.990000000000009</double>
-              </property>
-              <property name="singleStep">
-               <double>0.100000000000000</double>
+             <widget class="QLabel" name="labelNode">
+              <property name="text">
+               <string>Node:</string>
               </property>
              </widget>
             </item>
+            <item>
+             <widget class="QComboBox" name="comboBoxNodes">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_9">
+            <item alignment="Qt::AlignLeft">
+             <widget class="QLabel" name="labelEditBefore">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>159</red>
+                    <green>158</green>
+                    <blue>158</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
+              </property>
+              <property name="text">
+               <string>Before:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_3">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
             <item>
              <widget class="QPushButton" name="pushButtonDefBefore">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
               <property name="toolTip">
                <string>Return to default width</string>
               </property>
@@ -228,32 +423,197 @@
               </property>
              </widget>
             </item>
-           </layout>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="labelSAAfter">
-            <property name="toolTip">
-             <string>Seam allowance after node</string>
-            </property>
-            <property name="text">
-             <string>After:</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <layout class="QHBoxLayout" name="horizontalLayout_3">
-            <item>
-             <widget class="QDoubleSpinBox" name="doubleSpinBoxSAAfter">
-              <property name="maximum">
-               <double>900.990000000000009</double>
+            <item alignment="Qt::AlignRight">
+             <widget class="QToolButton" name="toolButtonExprBefore">
+              <property name="enabled">
+               <bool>false</bool>
               </property>
-              <property name="singleStep">
-               <double>0.100000000000000</double>
+              <property name="toolTip">
+               <string>Formula wizard</string>
+              </property>
+              <property name="text">
+               <string notr="true">...</string>
+              </property>
+              <property name="icon">
+               <iconset resource="../../../vmisc/share/resources/icon.qrc">
+                <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>24</width>
+                <height>24</height>
+               </size>
               </property>
              </widget>
             </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="label_6">
+              <property name="text">
+               <string/>
+              </property>
+              <property name="pixmap">
+               <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="labelResultBefore">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>87</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Value</string>
+              </property>
+              <property name="text">
+               <string notr="true">_</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <item>
+             <widget class="QPlainTextEdit" name="plainTextEditFormulaWidthBefore">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>28</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Calculation</string>
+              </property>
+              <property name="tabChangesFocus">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonGrowWidthBefore">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>18</width>
+                <height>18</height>
+               </size>
+              </property>
+              <property name="sizeIncrement">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="text">
+               <string notr="true"/>
+              </property>
+              <property name="icon">
+               <iconset theme="go-down">
+                <normaloff>.</normaloff>.</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>16</width>
+                <height>16</height>
+               </size>
+              </property>
+              <property name="flat">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_16">
+            <item alignment="Qt::AlignLeft">
+             <widget class="QLabel" name="labelEditAfter">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>159</red>
+                    <green>158</green>
+                    <blue>158</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
+              </property>
+              <property name="text">
+               <string>After:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_6">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
             <item>
              <widget class="QPushButton" name="pushButtonDefAfter">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
               <property name="toolTip">
                <string>Return to default width</string>
               </property>
@@ -262,17 +622,157 @@
               </property>
              </widget>
             </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QToolButton" name="toolButtonExprAfter">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="toolTip">
+               <string>Formula wizard</string>
+              </property>
+              <property name="text">
+               <string notr="true">...</string>
+              </property>
+              <property name="icon">
+               <iconset resource="../../../vmisc/share/resources/icon.qrc">
+                <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>24</width>
+                <height>24</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="label_10">
+              <property name="text">
+               <string/>
+              </property>
+              <property name="pixmap">
+               <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="labelResultAfter">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>87</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Value</string>
+              </property>
+              <property name="text">
+               <string notr="true">_</string>
+              </property>
+             </widget>
+            </item>
            </layout>
           </item>
-          <item row="3" column="0">
-           <widget class="QLabel" name="labelAngle">
-            <property name="text">
-             <string>Angle:</string>
-            </property>
-           </widget>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_17">
+            <item>
+             <widget class="QPlainTextEdit" name="plainTextEditFormulaWidthAfter">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>28</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Calculation</string>
+              </property>
+              <property name="tabChangesFocus">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonGrowWidthAfter">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>18</width>
+                <height>18</height>
+               </size>
+              </property>
+              <property name="sizeIncrement">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="text">
+               <string notr="true"/>
+              </property>
+              <property name="icon">
+               <iconset theme="go-down">
+                <normaloff>.</normaloff>.</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>16</width>
+                <height>16</height>
+               </size>
+              </property>
+              <property name="flat">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
           </item>
-          <item row="3" column="1">
-           <widget class="QComboBox" name="comboBoxAngle"/>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <item>
+             <widget class="QLabel" name="labelAngle">
+              <property name="text">
+               <string>Angle:</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="comboBoxAngle">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
           </item>
          </layout>
         </widget>
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 9be77474d..a9d1b5a44 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -37,6 +37,7 @@
 #include "../support/dialogeditwrongformula.h"
 
 #include <QMenu>
+#include <QTimer>
 #include <QtNumeric>
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -55,7 +56,14 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
       m_oldGeom(),
       m_oldGrainline(),
       m_iRotBaseHeight(0),
-      m_iLenBaseHeight(0)
+      m_iLenBaseHeight(0),
+      m_formulaBaseWidth(0),
+      m_formulaBaseWidthBefore(0),
+      m_formulaBaseWidthAfter(0),
+      m_timerWidth(nullptr),
+      m_timerWidthBefore(nullptr),
+      m_timerWidthAfter(nullptr),
+      m_saWidth(0)
 {
     ui->setupUi(this);
 
@@ -84,6 +92,9 @@ DialogSeamAllowance::DialogSeamAllowance(const VContainer *data, const quint32 &
 //---------------------------------------------------------------------------------------------------------------------
 DialogSeamAllowance::~DialogSeamAllowance()
 {
+    VContainer *locData = const_cast<VContainer *> (data);
+    locData->RemoveVariable(currentSeamAllowance);
+
     delete ui;
 }
 
@@ -141,10 +152,12 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
     CustomSAChanged(0);
 
     ui->checkBoxForbidFlipping->setChecked(piece.IsForbidFlipping());
-    ui->doubleSpinBoxSeams->setValue(piece.GetSAWidth());
     ui->checkBoxSeams->setChecked(piece.IsSeamAllowance());
     ui->lineEditName->setText(piece.GetName());
 
+    ui->plainTextEditFormulaWidth->setPlainText(piece.GetFormulaSAWidth());
+    m_saWidth = piece.GetSAWidth();
+
     m_mx = piece.GetMx();
     m_my = piece.GetMy();
 
@@ -283,7 +296,7 @@ void DialogSeamAllowance::SaveData()
 void DialogSeamAllowance::CheckState()
 {
     SCASSERT(bOk != nullptr);
-    bOk->setEnabled(flagName && flagError);
+    bOk->setEnabled(flagName && flagError && flagFormula);
     // In case dialog hasn't apply button
     if ( bApply != nullptr && applyAllowed)
     {
@@ -506,7 +519,7 @@ void DialogSeamAllowance::ShowCustomSAContextMenu(const QPoint &pos)
         dialog->SetPieceId(toolId);
         if (record.includeType == PiecePathIncludeType::AsMainPath)
         {
-            dialog->SetSAWidth(ui->doubleSpinBoxSeams->value());
+            dialog->SetFormulaSAWidth(GetFormulaSAWidth());
         }
         dialog->EnbleShowMode(true);
         m_dialog = dialog;
@@ -580,14 +593,18 @@ void DialogSeamAllowance::EnableSeamAllowance(bool enable)
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::NodeChanged(int index)
 {
-    ui->doubleSpinBoxSABefore->setDisabled(true);
-    ui->doubleSpinBoxSAAfter->setDisabled(true);
+    ui->plainTextEditFormulaWidthBefore->setDisabled(true);
+    ui->toolButtonExprBefore->setDisabled(true);
     ui->pushButtonDefBefore->setDisabled(true);
+
+    ui->plainTextEditFormulaWidthAfter->setDisabled(true);
+    ui->toolButtonExprAfter->setDisabled(true);
     ui->pushButtonDefAfter->setDisabled(true);
+
     ui->comboBoxAngle->setDisabled(true);
 
-    ui->doubleSpinBoxSABefore->blockSignals(true);
-    ui->doubleSpinBoxSAAfter->blockSignals(true);
+    ui->plainTextEditFormulaWidthBefore->blockSignals(true);
+    ui->plainTextEditFormulaWidthAfter->blockSignals(true);
     ui->comboBoxAngle->blockSignals(true);
 
     if (index != -1)
@@ -603,32 +620,42 @@ void DialogSeamAllowance::NodeChanged(int index)
         {
             const VPieceNode &node = piece.GetPath().at(nodeIndex);
 
-            ui->doubleSpinBoxSABefore->setEnabled(true);
-            ui->doubleSpinBoxSAAfter->setEnabled(true);
-            ui->comboBoxAngle->setEnabled(true);
+            // Seam alowance before
+            ui->plainTextEditFormulaWidthBefore->setEnabled(true);
+            ui->toolButtonExprBefore->setEnabled(true);
 
-            qreal w1 = node.GetSABefore();
-            if (w1 < 0)
-            {
-                w1 = piece.GetSAWidth();
-            }
-            else
+            QString w1Formula = node.GetFormulaSABefore();
+            if (w1Formula != currentSeamAllowance)
             {
                 ui->pushButtonDefBefore->setEnabled(true);
             }
-            ui->doubleSpinBoxSABefore->setValue(w1);
-
-            qreal w2 = node.GetSAAfter();
-            if (w2 < 0)
+            if (w1Formula.length() > 80)// increase height if needed.
             {
-                w2 = piece.GetSAWidth();
+                this->DeployWidthBeforeFormulaTextEdit();
             }
-            else
+            w1Formula = qApp->TrVars()->FormulaToUser(w1Formula, qApp->Settings()->GetOsSeparator());
+            ui->plainTextEditFormulaWidthBefore->setPlainText(w1Formula);
+            MoveCursorToEnd(ui->plainTextEditFormulaWidthBefore);
+
+            // Seam alowance after
+            ui->plainTextEditFormulaWidthAfter->setEnabled(true);
+            ui->toolButtonExprAfter->setEnabled(true);
+
+            QString w2Formula = node.GetFormulaSAAfter();
+            if (w2Formula != currentSeamAllowance)
             {
                 ui->pushButtonDefAfter->setEnabled(true);
             }
-            ui->doubleSpinBoxSAAfter->setValue(w2);
+            if (w2Formula.length() > 80)// increase height if needed.
+            {
+                this->DeployWidthAfterFormulaTextEdit();
+            }
+            w2Formula = qApp->TrVars()->FormulaToUser(w2Formula, qApp->Settings()->GetOsSeparator());
+            ui->plainTextEditFormulaWidthAfter->setPlainText(w2Formula);
+            MoveCursorToEnd(ui->plainTextEditFormulaWidthAfter);
 
+            // Angle type
+            ui->comboBoxAngle->setEnabled(true);
             const int index = ui->comboBoxAngle->findData(static_cast<unsigned char>(node.GetAngleType()));
             if (index != -1)
             {
@@ -638,13 +665,13 @@ void DialogSeamAllowance::NodeChanged(int index)
     }
     else
     {
-        ui->doubleSpinBoxSABefore->setValue(0);
-        ui->doubleSpinBoxSAAfter->setValue(0);
+        ui->plainTextEditFormulaWidthBefore->setPlainText("");
+        ui->plainTextEditFormulaWidthAfter->setPlainText("");
         ui->comboBoxAngle->setCurrentIndex(-1);
     }
 
-    ui->doubleSpinBoxSABefore->blockSignals(false);
-    ui->doubleSpinBoxSAAfter->blockSignals(false);
+    ui->plainTextEditFormulaWidthBefore->blockSignals(false);
+    ui->plainTextEditFormulaWidthAfter->blockSignals(false);
     ui->comboBoxAngle->blockSignals(false);
 }
 
@@ -752,25 +779,13 @@ void DialogSeamAllowance::NodeAngleChanged(int index)
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ReturnDefBefore()
 {
-    SetCurrentSABefore(-1);
+    ui->plainTextEditFormulaWidthBefore->setPlainText(currentSeamAllowance);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::ReturnDefAfter()
 {
-    SetCurrentSAAfter(-1);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::ChangedSABefore(double d)
-{
-    SetCurrentSABefore(d);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::ChangedSAAfter(double d)
-{
-    SetCurrentSAAfter(d);
+    ui->plainTextEditFormulaWidthAfter->setPlainText(currentSeamAllowance);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1061,6 +1076,142 @@ void DialogSeamAllowance::ResetWarning()
     ui->tabWidget->setTabIcon(ui->tabWidget->indexOf(ui->tabGrainline), icon);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EvalWidth()
+{
+    labelEditFormula = ui->labelEditWidth;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidth->toPlainText();
+    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, true, true);
+
+    if (m_saWidth >= 0)
+    {
+        VContainer *locData = const_cast<VContainer *> (data);
+        locData->AddVariable(currentSeamAllowance, new VIncrement(locData, currentSeamAllowance, 0, m_saWidth,
+                                                                  QString().setNum(m_saWidth), true,
+                                                                  tr("Current seam allowance")));
+
+        EvalWidthBefore();
+        EvalWidthAfter();
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EvalWidthBefore()
+{
+    labelEditFormula = ui->labelEditBefore;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidthBefore->toPlainText();
+    bool flagFormula = false; // fake flag
+    Eval(formula, flagFormula, ui->labelResultBefore, postfix, true, true);
+
+    UpdateNodeSABefore(GetFormulaSAWidthBefore());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::EvalWidthAfter()
+{
+    labelEditFormula = ui->labelEditAfter;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    const QString formula = ui->plainTextEditFormulaWidthAfter->toPlainText();
+    bool flagFormula = false; // fake flag
+    Eval(formula, flagFormula, ui->labelResultAfter, postfix, true, true);
+
+    UpdateNodeSAAfter(GetFormulaSAWidthAfter());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::FXWidth()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width"));
+    dialog->SetFormula(GetFormulaSAWidth());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetFormulaSAWidth(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::FXWidthBefore()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width before"));
+    dialog->SetFormula(GetFormulaSAWidthBefore());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetCurrentSABefore(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::FXWidthAfter()
+{
+    DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
+    dialog->setWindowTitle(tr("Edit seam allowance width after"));
+    dialog->SetFormula(GetFormulaSAWidthAfter());
+    dialog->setCheckLessThanZero(true);
+    dialog->setPostfix(VDomDocument::UnitsToStr(qApp->patternUnit(), true));
+    if (dialog->exec() == QDialog::Accepted)
+    {
+        SetCurrentSAAfter(dialog->GetFormula());
+    }
+    delete dialog;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::WidthChanged()
+{
+    labelEditFormula = ui->labelEditWidth;
+    labelResultCalculation = ui->labelResultWidth;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidth, m_timerWidth, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::WidthBeforeChanged()
+{
+    labelEditFormula = ui->labelEditBefore;
+    labelResultCalculation = ui->labelResultBefore;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    bool flagFormula = false;
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidthBefore, m_timerWidthBefore, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::WidthAfterChanged()
+{
+    labelEditFormula = ui->labelEditAfter;
+    labelResultCalculation = ui->labelResultAfter;
+    const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
+    bool flagFormula = false;
+    ValFormulaChanged(flagFormula, ui->plainTextEditFormulaWidthAfter, m_timerWidthAfter, postfix);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::DeployWidthFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidth, ui->pushButtonGrowWidth, m_formulaBaseWidth);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::DeployWidthBeforeFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidthBefore, ui->pushButtonGrowWidthBefore, m_formulaBaseWidthBefore);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::DeployWidthAfterFormulaTextEdit()
+{
+    DeployFormula(ui->plainTextEditFormulaWidthAfter, ui->pushButtonGrowWidthAfter, m_formulaBaseWidthAfter);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiece DialogSeamAllowance::CreatePiece() const
 {
@@ -1089,11 +1240,14 @@ VPiece DialogSeamAllowance::CreatePiece() const
 
     piece.SetForbidFlipping(ui->checkBoxForbidFlipping->isChecked());
     piece.SetSeamAllowance(ui->checkBoxSeams->isChecked());
-    piece.SetSAWidth(ui->doubleSpinBoxSeams->value());
     piece.SetName(ui->lineEditName->text());
     piece.SetMx(m_mx);
     piece.SetMy(m_my);
 
+    QString width = ui->plainTextEditFormulaWidth->toPlainText();
+    width.replace("\n", " ");
+    piece.SetFormulaSAWidth(width, m_saWidth);
+
     piece.GetPatternPieceData().SetLetter(ui->lineEditLetter->text());
 
     for (int i = 0; i < m_conMCP.count(); ++i)
@@ -1306,7 +1460,21 @@ quint32 DialogSeamAllowance::GetLastId() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::SetCurrentSABefore(qreal value)
+void DialogSeamAllowance::SetCurrentSABefore(const QString &formula)
+{
+    UpdateNodeSABefore(formula);
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetCurrentSAAfter(const QString &formula)
+{
+    UpdateNodeSAAfter(formula);
+    ListChanged();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::UpdateNodeSABefore(const QString &formula)
 {
     const int index = ui->comboBoxNodes->currentIndex();
     if (index != -1)
@@ -1321,16 +1489,14 @@ void DialogSeamAllowance::SetCurrentSABefore(qreal value)
         if (rowItem)
         {
             VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
-            rowNode.SetSABefore(value);
+            rowNode.SetFormulaSABefore(formula);
             rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
-
-            ListChanged();
         }
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void DialogSeamAllowance::SetCurrentSAAfter(qreal value)
+void DialogSeamAllowance::UpdateNodeSAAfter(const QString &formula)
 {
     const int index = ui->comboBoxNodes->currentIndex();
     if (index != -1)
@@ -1345,10 +1511,8 @@ void DialogSeamAllowance::SetCurrentSAAfter(qreal value)
         if (rowItem)
         {
             VPieceNode rowNode = qvariant_cast<VPieceNode>(rowItem->data(Qt::UserRole));
-            rowNode.SetSAAfter(value);
+            rowNode.SetFormulaSAAfter(formula);
             rowItem->setData(Qt::UserRole, QVariant::fromValue(rowNode));
-
-            ListChanged();
         }
     }
 }
@@ -1367,21 +1531,29 @@ void DialogSeamAllowance::InitMainPathTab()
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::InitSeamAllowanceTab()
 {
+    plainTextEditFormula = ui->plainTextEditFormulaWidth;
+    this->m_formulaBaseWidth = ui->plainTextEditFormulaWidth->height();
+    this->m_formulaBaseWidthBefore = ui->plainTextEditFormulaWidthBefore->height();
+    this->m_formulaBaseWidthAfter = ui->plainTextEditFormulaWidthAfter->height();
+
+    ui->plainTextEditFormulaWidth->installEventFilter(this);
+    ui->plainTextEditFormulaWidthBefore->installEventFilter(this);
+    ui->plainTextEditFormulaWidthAfter->installEventFilter(this);
+
+    m_timerWidth = new QTimer(this);
+    connect(m_timerWidth, &QTimer::timeout, this, &DialogSeamAllowance::EvalWidth);
+
+    m_timerWidthBefore = new QTimer(this);
+    connect(m_timerWidthBefore, &QTimer::timeout, this, &DialogSeamAllowance::EvalWidthBefore);
+
+    m_timerWidthAfter = new QTimer(this);
+    connect(m_timerWidthAfter, &QTimer::timeout, this, &DialogSeamAllowance::EvalWidthAfter);
+
     connect(ui->checkBoxSeams, &QCheckBox::toggled, this, &DialogSeamAllowance::EnableSeamAllowance);
 
-    const QString suffix = QLatin1String(" ") + VDomDocument::UnitsToStr(qApp->patternUnit(), true);
-    ui->doubleSpinBoxSeams->setSuffix(suffix);
-    ui->doubleSpinBoxSABefore->setSuffix(suffix);
-    ui->doubleSpinBoxSAAfter->setSuffix(suffix);
-
-    if(qApp->patternUnit() == Unit::Inch)
-    {
-        ui->doubleSpinBoxSeams->setDecimals(5);
-        ui->doubleSpinBoxSABefore->setDecimals(5);
-        ui->doubleSpinBoxSAAfter->setDecimals(5);
-    }
     // Default value for seam allowence is 1 cm. But pattern have different units, so just set 1 in dialog not enough.
-    ui->doubleSpinBoxSeams->setValue(UnitConvertor(1, Unit::Cm, qApp->patternUnit()));
+    m_saWidth = UnitConvertor(1, Unit::Cm, qApp->patternUnit());
+    ui->plainTextEditFormulaWidth->setPlainText(qApp->LocaleToString(m_saWidth));
 
     InitNodesList();
     connect(ui->comboBoxNodes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
@@ -1390,14 +1562,6 @@ void DialogSeamAllowance::InitSeamAllowanceTab()
     connect(ui->pushButtonDefBefore, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefBefore);
     connect(ui->pushButtonDefAfter, &QPushButton::clicked, this, &DialogSeamAllowance::ReturnDefAfter);
 
-    connect(ui->doubleSpinBoxSeams, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            [this](){NodeChanged(ui->comboBoxNodes->currentIndex());});
-
-    connect(ui->doubleSpinBoxSABefore, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogSeamAllowance::ChangedSABefore);
-    connect(ui->doubleSpinBoxSAAfter, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
-            this, &DialogSeamAllowance::ChangedSAAfter);
-
     InitNodeAngles(ui->comboBoxAngle);
     connect(ui->comboBoxAngle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::NodeAngleChanged);
@@ -1412,6 +1576,22 @@ void DialogSeamAllowance::InitSeamAllowanceTab()
             &DialogSeamAllowance::CSAEndPointChanged);
     connect(ui->comboBoxIncludeType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
             &DialogSeamAllowance::CSAIncludeTypeChanged);
+
+    connect(ui->toolButtonExprWidth, &QPushButton::clicked, this, &DialogSeamAllowance::FXWidth);
+    connect(ui->toolButtonExprBefore, &QPushButton::clicked, this, &DialogSeamAllowance::FXWidthBefore);
+    connect(ui->toolButtonExprAfter, &QPushButton::clicked, this, &DialogSeamAllowance::FXWidthAfter);
+
+    connect(ui->plainTextEditFormulaWidth, &QPlainTextEdit::textChanged, this, &DialogSeamAllowance::WidthChanged);
+    connect(ui->plainTextEditFormulaWidthBefore, &QPlainTextEdit::textChanged, this,
+            &DialogSeamAllowance::WidthBeforeChanged);
+    connect(ui->plainTextEditFormulaWidthAfter, &QPlainTextEdit::textChanged, this,
+            &DialogSeamAllowance::WidthAfterChanged);
+
+    connect(ui->pushButtonGrowWidth, &QPushButton::clicked, this, &DialogSeamAllowance::DeployWidthFormulaTextEdit);
+    connect(ui->pushButtonGrowWidthBefore, &QPushButton::clicked,
+            this, &DialogSeamAllowance::DeployWidthBeforeFormulaTextEdit);
+    connect(ui->pushButtonGrowWidthAfter, &QPushButton::clicked, this,
+            &DialogSeamAllowance::DeployWidthAfterFormulaTextEdit);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1513,6 +1693,49 @@ void DialogSeamAllowance::InitGrainlineTab()
     m_iLenBaseHeight = ui->lineEditLenFormula->height();
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetFormulaSAWidth() const
+{
+    QString width = ui->plainTextEditFormulaWidth->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void DialogSeamAllowance::SetFormulaSAWidth(const QString &formula)
+{
+    const QString width = qApp->TrVars()->FormulaToUser(formula, qApp->Settings()->GetOsSeparator());
+    // increase height if needed.
+    if (width.length() > 80)
+    {
+        this->DeployWidthFormulaTextEdit();
+    }
+    ui->plainTextEditFormulaWidth->setPlainText(width);
+
+    VisToolPiece *path = qobject_cast<VisToolPiece *>(vis);
+    SCASSERT(path != nullptr)
+    const VPiece p = CreatePiece();
+    path->SetPiece(p);
+
+    MoveCursorToEnd(ui->plainTextEditFormulaWidth);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetFormulaSAWidthBefore() const
+{
+    QString width = ui->plainTextEditFormulaWidthBefore->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString DialogSeamAllowance::GetFormulaSAWidthAfter() const
+{
+    QString width = ui->plainTextEditFormulaWidthAfter->toPlainText();
+    width.replace("\n", " ");
+    return qApp->TrVars()->TryFormulaFromUser(width, qApp->Settings()->GetOsSeparator());
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 void DialogSeamAllowance::UpdateCurrentCustomSARecord()
 {
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.h b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
index 4e7f659a8..ece3aff7a 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.h
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.h
@@ -53,6 +53,8 @@ public:
     VPiece GetPiece() const;
     void   SetPiece(const VPiece &m_piece);
 
+    QString GetFormulaSAWidth() const;
+
 public slots:
     virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
     virtual void ShowDialog(bool click) Q_DECL_OVERRIDE;
@@ -84,8 +86,6 @@ private slots:
     void NodeAngleChanged(int index);
     void ReturnDefBefore();
     void ReturnDefAfter();
-    void ChangedSABefore(double d);
-    void ChangedSAAfter(double d);
     void CustomSAChanged(int row);
     void PathDialogClosed(int result);
 
@@ -98,6 +98,22 @@ private slots:
     void DeployLength();
     void ResetWarning();
 
+    void EvalWidth();
+    void EvalWidthBefore();
+    void EvalWidthAfter();
+
+    void FXWidth();
+    void FXWidthBefore();
+    void FXWidthAfter();
+
+    void WidthChanged();
+    void WidthBeforeChanged();
+    void WidthAfterChanged();
+
+    void DeployWidthFormulaTextEdit();
+    void DeployWidthBeforeFormulaTextEdit();
+    void DeployWidthAfterFormulaTextEdit();
+
 private:
     Q_DISABLE_COPY(DialogSeamAllowance)
 
@@ -119,6 +135,14 @@ private:
     VGrainlineGeometry   m_oldGrainline;
     int                  m_iRotBaseHeight;
     int                  m_iLenBaseHeight;
+    int                  m_formulaBaseWidth;
+    int                  m_formulaBaseWidthBefore;
+    int                  m_formulaBaseWidthAfter;
+
+    QTimer *m_timerWidth;
+    QTimer *m_timerWidthBefore;
+    QTimer *m_timerWidthAfter;
+    qreal   m_saWidth;
 
     VPiece CreatePiece() const;
 
@@ -137,8 +161,11 @@ private:
 
     quint32 GetLastId() const;
 
-    void SetCurrentSABefore(qreal value);
-    void SetCurrentSAAfter(qreal value);
+    void SetCurrentSABefore(const QString &formula);
+    void SetCurrentSAAfter(const QString &formula);
+
+    void UpdateNodeSABefore(const QString &formula);
+    void UpdateNodeSAAfter(const QString &formula);
 
     void InitMainPathTab();
     void InitSeamAllowanceTab();
@@ -148,6 +175,11 @@ private:
     void InitInternalPathsTab();
     void InitPatternPieceDataTab();
     void InitGrainlineTab();
+
+    void SetFormulaSAWidth(const QString &formula);
+
+    QString GetFormulaSAWidthBefore() const;
+    QString GetFormulaSAWidthAfter() const;
 };
 
 #endif // DIALOGSEAMALLOWANCE_H
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
index ff18f4b2d..315098dc5 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>521</width>
-    <height>493</height>
+    <height>611</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -21,7 +21,7 @@
    <item>
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>4</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tabMainPath">
       <attribute name="title">
@@ -94,7 +94,7 @@
       <attribute name="title">
        <string>Seam allowance</string>
       </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_5">
+      <layout class="QVBoxLayout" name="verticalLayout_11">
        <item>
         <widget class="QCheckBox" name="checkBoxSeams">
          <property name="text">
@@ -119,50 +119,62 @@
          <property name="checkable">
           <bool>false</bool>
          </property>
-         <layout class="QVBoxLayout" name="verticalLayout_3">
-          <property name="topMargin">
-           <number>9</number>
-          </property>
+         <layout class="QVBoxLayout" name="verticalLayout_5">
           <property name="bottomMargin">
            <number>0</number>
           </property>
           <item>
            <layout class="QHBoxLayout" name="horizontalLayout_2">
-            <item>
+            <item alignment="Qt::AlignLeft">
              <widget class="QLabel" name="labelEditWidth">
               <property name="sizePolicy">
-               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
                 <horstretch>0</horstretch>
                 <verstretch>0</verstretch>
                </sizepolicy>
               </property>
-              <property name="locale">
-               <locale language="English" country="UnitedStates"/>
+              <property name="palette">
+               <palette>
+                <active>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </active>
+                <inactive>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>255</red>
+                    <green>0</green>
+                    <blue>0</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </inactive>
+                <disabled>
+                 <colorrole role="WindowText">
+                  <brush brushstyle="SolidPattern">
+                   <color alpha="255">
+                    <red>159</red>
+                    <green>158</green>
+                    <blue>158</blue>
+                   </color>
+                  </brush>
+                 </colorrole>
+                </disabled>
+               </palette>
               </property>
               <property name="text">
                <string>Width:</string>
               </property>
              </widget>
             </item>
-            <item>
-             <widget class="QDoubleSpinBox" name="doubleSpinBoxSeams">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="maximum">
-               <double>900.990000000000009</double>
-              </property>
-              <property name="singleStep">
-               <double>0.100000000000000</double>
-              </property>
-              <property name="value">
-               <double>1.000000000000000</double>
-              </property>
-             </widget>
-            </item>
             <item>
              <spacer name="horizontalSpacer">
               <property name="orientation">
@@ -176,6 +188,119 @@
               </property>
              </spacer>
             </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QToolButton" name="toolButtonExprWidth">
+              <property name="toolTip">
+               <string>Formula wizard</string>
+              </property>
+              <property name="text">
+               <string notr="true">...</string>
+              </property>
+              <property name="icon">
+               <iconset resource="../../../vmisc/share/resources/icon.qrc">
+                <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>24</width>
+                <height>24</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="label_2">
+              <property name="text">
+               <string/>
+              </property>
+              <property name="pixmap">
+               <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+              </property>
+             </widget>
+            </item>
+            <item alignment="Qt::AlignRight">
+             <widget class="QLabel" name="labelResultWidth">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>87</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Value</string>
+              </property>
+              <property name="text">
+               <string notr="true">_</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_6">
+            <item>
+             <widget class="QPlainTextEdit" name="plainTextEditFormulaWidth">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>28</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>Calculation</string>
+              </property>
+              <property name="tabChangesFocus">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonGrowWidth">
+              <property name="maximumSize">
+               <size>
+                <width>18</width>
+                <height>18</height>
+               </size>
+              </property>
+              <property name="sizeIncrement">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="text">
+               <string notr="true"/>
+              </property>
+              <property name="icon">
+               <iconset theme="go-down">
+                <normaloff>.</normaloff>.</iconset>
+              </property>
+              <property name="iconSize">
+               <size>
+                <width>16</width>
+                <height>16</height>
+               </size>
+              </property>
+              <property name="flat">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
            </layout>
           </item>
           <item>
@@ -183,42 +308,115 @@
             <property name="title">
              <string>Nodes</string>
             </property>
-            <layout class="QFormLayout" name="formLayout">
-             <property name="fieldGrowthPolicy">
-              <enum>QFormLayout::ExpandingFieldsGrow</enum>
+            <layout class="QVBoxLayout" name="verticalLayout_3">
+             <property name="bottomMargin">
+              <number>0</number>
              </property>
-             <item row="0" column="0">
-              <widget class="QLabel" name="labelNode">
-               <property name="text">
-                <string>Node:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="0" column="1">
-              <widget class="QComboBox" name="comboBoxNodes"/>
-             </item>
-             <item row="1" column="0">
-              <widget class="QLabel" name="labelSABefore">
-               <property name="toolTip">
-                <string>Seam allowance before node</string>
-               </property>
-               <property name="text">
-                <string>Before:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="1" column="1">
-              <layout class="QHBoxLayout" name="horizontalLayout">
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_10">
                <item>
-                <widget class="QDoubleSpinBox" name="doubleSpinBoxSABefore">
-                 <property name="maximum">
-                  <double>900.990000000000009</double>
+                <widget class="QLabel" name="labelNode">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
                  </property>
-                 <property name="singleStep">
-                  <double>0.100000000000000</double>
+                 <property name="text">
+                  <string>Node:</string>
                  </property>
                 </widget>
                </item>
+               <item>
+                <widget class="QComboBox" name="comboBoxNodes">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_7">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_9">
+               <item alignment="Qt::AlignLeft">
+                <widget class="QLabel" name="labelEditBefore">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="palette">
+                  <palette>
+                   <active>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </active>
+                   <inactive>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </inactive>
+                   <disabled>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>159</red>
+                       <green>158</green>
+                       <blue>158</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </disabled>
+                  </palette>
+                 </property>
+                 <property name="text">
+                  <string>Before:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_3">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
                <item>
                 <widget class="QPushButton" name="pushButtonDefBefore">
                  <property name="toolTip">
@@ -229,30 +427,186 @@
                  </property>
                 </widget>
                </item>
-              </layout>
-             </item>
-             <item row="2" column="0">
-              <widget class="QLabel" name="labelSAAfter">
-               <property name="toolTip">
-                <string>Seam allowance after node</string>
-               </property>
-               <property name="text">
-                <string>After:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="2" column="1">
-              <layout class="QHBoxLayout" name="horizontalLayout_3">
-               <item>
-                <widget class="QDoubleSpinBox" name="doubleSpinBoxSAAfter">
-                 <property name="maximum">
-                  <double>900.990000000000009</double>
+               <item alignment="Qt::AlignRight">
+                <widget class="QToolButton" name="toolButtonExprBefore">
+                 <property name="toolTip">
+                  <string>Formula wizard</string>
                  </property>
-                 <property name="singleStep">
-                  <double>0.100000000000000</double>
+                 <property name="text">
+                  <string notr="true">...</string>
+                 </property>
+                 <property name="icon">
+                  <iconset resource="../../../vmisc/share/resources/icon.qrc">
+                   <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+                 </property>
+                 <property name="iconSize">
+                  <size>
+                   <width>24</width>
+                   <height>24</height>
+                  </size>
                  </property>
                 </widget>
                </item>
+               <item alignment="Qt::AlignRight">
+                <widget class="QLabel" name="label_6">
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="pixmap">
+                  <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+                 </property>
+                </widget>
+               </item>
+               <item alignment="Qt::AlignRight">
+                <widget class="QLabel" name="labelResultBefore">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>87</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Value</string>
+                 </property>
+                 <property name="text">
+                  <string notr="true">_</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_7">
+               <item>
+                <widget class="QPlainTextEdit" name="plainTextEditFormulaWidthBefore">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>28</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Calculation</string>
+                 </property>
+                 <property name="tabChangesFocus">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButtonGrowWidthBefore">
+                 <property name="maximumSize">
+                  <size>
+                   <width>18</width>
+                   <height>18</height>
+                  </size>
+                 </property>
+                 <property name="sizeIncrement">
+                  <size>
+                   <width>0</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string notr="true"/>
+                 </property>
+                 <property name="icon">
+                  <iconset theme="go-down">
+                   <normaloff>.</normaloff>.</iconset>
+                 </property>
+                 <property name="iconSize">
+                  <size>
+                   <width>16</width>
+                   <height>16</height>
+                  </size>
+                 </property>
+                 <property name="flat">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_16">
+               <item alignment="Qt::AlignLeft">
+                <widget class="QLabel" name="labelEditAfter">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="palette">
+                  <palette>
+                   <active>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </active>
+                   <inactive>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>255</red>
+                       <green>0</green>
+                       <blue>0</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </inactive>
+                   <disabled>
+                    <colorrole role="WindowText">
+                     <brush brushstyle="SolidPattern">
+                      <color alpha="255">
+                       <red>159</red>
+                       <green>158</green>
+                       <blue>158</blue>
+                      </color>
+                     </brush>
+                    </colorrole>
+                   </disabled>
+                  </palette>
+                 </property>
+                 <property name="text">
+                  <string>After:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_6">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
                <item>
                 <widget class="QPushButton" name="pushButtonDefAfter">
                  <property name="toolTip">
@@ -263,17 +617,154 @@
                  </property>
                 </widget>
                </item>
+               <item alignment="Qt::AlignRight">
+                <widget class="QToolButton" name="toolButtonExprAfter">
+                 <property name="toolTip">
+                  <string>Formula wizard</string>
+                 </property>
+                 <property name="text">
+                  <string notr="true">...</string>
+                 </property>
+                 <property name="icon">
+                  <iconset resource="../../../vmisc/share/resources/icon.qrc">
+                   <normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
+                 </property>
+                 <property name="iconSize">
+                  <size>
+                   <width>24</width>
+                   <height>24</height>
+                  </size>
+                 </property>
+                </widget>
+               </item>
+               <item alignment="Qt::AlignRight">
+                <widget class="QLabel" name="label_10">
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="pixmap">
+                  <pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
+                 </property>
+                </widget>
+               </item>
+               <item alignment="Qt::AlignRight">
+                <widget class="QLabel" name="labelResultAfter">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>87</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Value</string>
+                 </property>
+                 <property name="text">
+                  <string notr="true">_</string>
+                 </property>
+                </widget>
+               </item>
               </layout>
              </item>
-             <item row="3" column="0">
-              <widget class="QLabel" name="labelAngle">
-               <property name="text">
-                <string>Angle:</string>
-               </property>
-              </widget>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_17">
+               <item>
+                <widget class="QPlainTextEdit" name="plainTextEditFormulaWidthAfter">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>28</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>Calculation</string>
+                 </property>
+                 <property name="tabChangesFocus">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButtonGrowWidthAfter">
+                 <property name="maximumSize">
+                  <size>
+                   <width>18</width>
+                   <height>18</height>
+                  </size>
+                 </property>
+                 <property name="sizeIncrement">
+                  <size>
+                   <width>0</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string notr="true"/>
+                 </property>
+                 <property name="icon">
+                  <iconset theme="go-down">
+                   <normaloff>.</normaloff>.</iconset>
+                 </property>
+                 <property name="iconSize">
+                  <size>
+                   <width>16</width>
+                   <height>16</height>
+                  </size>
+                 </property>
+                 <property name="flat">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+              </layout>
              </item>
-             <item row="3" column="1">
-              <widget class="QComboBox" name="comboBoxAngle"/>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout_15">
+               <item>
+                <widget class="QLabel" name="labelAngle">
+                 <property name="text">
+                  <string>Angle:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QComboBox" name="comboBoxAngle">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_8">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
              </item>
             </layout>
            </widget>
@@ -293,6 +784,12 @@
           <bool>false</bool>
          </property>
          <layout class="QVBoxLayout" name="verticalLayout_4">
+          <property name="spacing">
+           <number>6</number>
+          </property>
+          <property name="topMargin">
+           <number>9</number>
+          </property>
           <property name="bottomMargin">
            <number>0</number>
           </property>
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp
index 7791854c6..b0d71b549 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp
@@ -582,7 +582,7 @@ void DialogTool::ValFormulaChanged(bool &flag, QPlainTextEdit *edit, QTimer *tim
         return;
     }
     timer->setSingleShot(true);
-    timer->start(1000);
+    timer->start(300);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -594,13 +594,11 @@ void DialogTool::ValFormulaChanged(bool &flag, QPlainTextEdit *edit, QTimer *tim
  * @param postfix unit name
  * @param checkZero true - if formula can't be equal zero
  */
-qreal DialogTool::Eval(const QString &text, bool &flag, QLabel *label, const QString& postfix, bool checkZero)
+qreal DialogTool::Eval(const QString &text, bool &flag, QLabel *label, const QString& postfix, bool checkZero,
+                       bool checkLessThanZero)
 {
-    qDebug() << "Eval started";
     SCASSERT(label != nullptr)
-    qDebug() << "Label ok";
     SCASSERT(labelEditFormula != nullptr)
-    qDebug() << "lef ok";
 
     qreal result = INT_MIN;//Value can be 0, so use max imposible value
 
@@ -640,6 +638,13 @@ qreal DialogTool::Eval(const QString &text, bool &flag, QLabel *label, const QSt
                     label->setText(tr("Error") + " (" + postfix + ")");
                     label->setToolTip(tr("Value can't be 0"));
                 }
+                else if (checkLessThanZero && result < 0)
+                {
+                    flag = false;
+                    ChangeColor(labelEditFormula, Qt::red);
+                    label->setText(tr("Error") + " (" + postfix + ")");
+                    label->setToolTip(tr("Value can't be lass than 0"));
+                }
                 else
                 {
                     label->setText(qApp->LocaleToString(result) + " " +postfix);
diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h
index e437aaad3..460a28d18 100644
--- a/src/libs/vtools/dialogs/tools/dialogtool.h
+++ b/src/libs/vtools/dialogs/tools/dialogtool.h
@@ -231,7 +231,7 @@ protected:
     void             ValFormulaChanged(bool &flag, QPlainTextEdit *edit, QTimer * timer,
                                        const QString &postfix = QString());
     qreal            Eval(const QString &text, bool &flag, QLabel *label, const QString &postfix,
-                          bool checkZero = true);
+                          bool checkZero = true, bool checkLessThanZero = false);
 
     void             setCurrentPointId(QComboBox *box, const quint32 &value,
                                        FillComboBox rule = FillComboBox::NoChildren,
diff --git a/src/libs/vtools/tools/drawTools/vdrawtool.cpp b/src/libs/vtools/tools/drawTools/vdrawtool.cpp
index 4de01fb70..db85d3d0a 100644
--- a/src/libs/vtools/tools/drawTools/vdrawtool.cpp
+++ b/src/libs/vtools/tools/drawTools/vdrawtool.cpp
@@ -28,7 +28,6 @@
 
 #include "vdrawtool.h"
 
-#include <qnumeric.h>
 #include <QDialog>
 #include <QDomNode>
 #include <QMessageLogger>
@@ -41,10 +40,6 @@
 #include "../ifc/ifcdef.h"
 #include "../ifc/xml/vdomdocument.h"
 #include "../ifc/xml/vabstractpattern.h"
-#include "../ifc/exception/vexceptionundo.h"
-#include "../vpatterndb/calculator.h"
-#include "../../dialogs/support/dialogeditwrongformula.h"
-#include "../../dialogs/support/dialogundo.h"
 #include "../../undocommands/addtocalc.h"
 #include "../../undocommands/savetooloptions.h"
 #include "../qmuparser/qmuparsererror.h"
@@ -292,96 +287,6 @@ void VDrawTool::DetailsMode(bool mode)
     // Do nothing.
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CheckFormula check formula.
- *
- * Try calculate formula. If find error show dialog that allow user try fix formula. If user can't throw exception. In
- * successes case return result calculation and fixed formula string. If formula ok don't touch formula.
- *
- * @param toolId [in] tool's id.
- * @param formula [in|out] string with formula.
- * @param data [in] container with variables. Need for math parser.
- * @throw QmuParserError.
- * @return result of calculation formula.
- */
-qreal VDrawTool::CheckFormula(const quint32 &toolId, QString &formula, VContainer *data)
-{
-    SCASSERT(data != nullptr)
-    qreal result = 0;
-    try
-    {
-        QScopedPointer<Calculator> cal(new Calculator());
-        result = cal->EvalFormula(data->PlainVariables(), formula);
-
-        if (qIsInf(result) || qIsNaN(result))
-        {
-            qDebug() << "Invalid the formula value";
-            return 0;
-        }
-    }
-    catch (qmu::QmuParserError &e)
-    {
-        qDebug() << "\nMath parser error:\n"
-                 << "--------------------------------------\n"
-                 << "Message:     " << e.GetMsg()  << "\n"
-                 << "Expression:  " << e.GetExpr() << "\n"
-                 << "--------------------------------------";
-
-        if (qApp->IsAppInGUIMode())
-        {
-            QScopedPointer<DialogUndo> dialogUndo(new DialogUndo(qApp->getMainWindow()));
-            forever
-            {
-                if (dialogUndo->exec() == QDialog::Accepted)
-                {
-                    const UndoButton resultUndo = dialogUndo->Result();
-                    if (resultUndo == UndoButton::Fix)
-                    {
-                        auto *dialog = new DialogEditWrongFormula(data, toolId, qApp->getMainWindow());
-                        dialog->setWindowTitle(tr("Edit wrong formula"));
-                        dialog->SetFormula(formula);
-                        if (dialog->exec() == QDialog::Accepted)
-                        {
-                            formula = dialog->GetFormula();
-                            /* Need delete dialog here because parser in dialog don't allow use correct separator for
-                             * parsing here. */
-                            delete dialog;
-                            QScopedPointer<Calculator> cal1(new Calculator());
-                            result = cal1->EvalFormula(data->PlainVariables(), formula);
-
-                            if (qIsInf(result) || qIsNaN(result))
-                            {
-                                qDebug() << "Invalid the formula value";
-                                return 0;
-                            }
-
-                            break;
-                        }
-                        else
-                        {
-                            delete dialog;
-                        }
-                    }
-                    else
-                    {
-                        throw VExceptionUndo(QString("Undo wrong formula %1").arg(formula));
-                    }
-                }
-                else
-                {
-                    throw;
-                }
-            }
-        }
-        else
-        {
-            throw;
-        }
-    }
-    return result;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief AddToCalculation add tool to calculation tag in pattern file.
diff --git a/src/libs/vtools/tools/drawTools/vdrawtool.h b/src/libs/vtools/tools/drawTools/vdrawtool.h
index cbb1281aa..105e212e6 100644
--- a/src/libs/vtools/tools/drawTools/vdrawtool.h
+++ b/src/libs/vtools/tools/drawTools/vdrawtool.h
@@ -75,7 +75,6 @@ public:
     /** @brief setDialog set dialog when user want change tool option. */
     virtual void setDialog() {}
     virtual void DialogLinkDestroy();
-    static qreal CheckFormula(const quint32 &toolId, QString &formula, VContainer *data);
 
     QString      getLineType() const;
     virtual void SetTypeLine(const QString &value);
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index 1198a0683..7cd873b5f 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -52,11 +52,13 @@
 #include <QUndoStack>
 #include <QVector>
 #include <new>
+#include <qnumeric.h>
 
 #include "../vgeometry/vpointf.h"
 #include "../vpropertyexplorer/checkablemessagebox.h"
 #include "../vwidgets/vmaingraphicsview.h"
 #include "../ifc/exception/vexception.h"
+#include "../ifc/exception/vexceptionundo.h"
 #include "../ifc/xml/vtoolrecord.h"
 #include "../undocommands/deltool.h"
 #include "../vgeometry/../ifc/ifcdef.h"
@@ -71,8 +73,11 @@
 #include "../vmisc/logging.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/calculator.h"
 #include "../vwidgets/vgraphicssimpletextitem.h"
 #include "nodeDetails/nodedetails.h"
+#include "../dialogs/support/dialogundo.h"
+#include "../dialogs/support/dialogeditwrongformula.h"
 
 class QGraphicsEllipseItem;
 class QGraphicsLineItem;
@@ -152,6 +157,96 @@ VAbstractTool::~VAbstractTool()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief CheckFormula check formula.
+ *
+ * Try calculate formula. If find error show dialog that allow user try fix formula. If user can't throw exception. In
+ * successes case return result calculation and fixed formula string. If formula ok don't touch formula.
+ *
+ * @param toolId [in] tool's id.
+ * @param formula [in|out] string with formula.
+ * @param data [in] container with variables. Need for math parser.
+ * @throw QmuParserError.
+ * @return result of calculation formula.
+ */
+qreal VAbstractTool::CheckFormula(const quint32 &toolId, QString &formula, VContainer *data)
+{
+    SCASSERT(data != nullptr)
+    qreal result = 0;
+    try
+    {
+        QScopedPointer<Calculator> cal(new Calculator());
+        result = cal->EvalFormula(data->PlainVariables(), formula);
+
+        if (qIsInf(result) || qIsNaN(result))
+        {
+            qDebug() << "Invalid the formula value";
+            return 0;
+        }
+    }
+    catch (qmu::QmuParserError &e)
+    {
+        qDebug() << "\nMath parser error:\n"
+                 << "--------------------------------------\n"
+                 << "Message:     " << e.GetMsg()  << "\n"
+                 << "Expression:  " << e.GetExpr() << "\n"
+                 << "--------------------------------------";
+
+        if (qApp->IsAppInGUIMode())
+        {
+            QScopedPointer<DialogUndo> dialogUndo(new DialogUndo(qApp->getMainWindow()));
+            forever
+            {
+                if (dialogUndo->exec() == QDialog::Accepted)
+                {
+                    const UndoButton resultUndo = dialogUndo->Result();
+                    if (resultUndo == UndoButton::Fix)
+                    {
+                        auto *dialog = new DialogEditWrongFormula(data, toolId, qApp->getMainWindow());
+                        dialog->setWindowTitle(tr("Edit wrong formula"));
+                        dialog->SetFormula(formula);
+                        if (dialog->exec() == QDialog::Accepted)
+                        {
+                            formula = dialog->GetFormula();
+                            /* Need delete dialog here because parser in dialog don't allow use correct separator for
+                             * parsing here. */
+                            delete dialog;
+                            QScopedPointer<Calculator> cal1(new Calculator());
+                            result = cal1->EvalFormula(data->PlainVariables(), formula);
+
+                            if (qIsInf(result) || qIsNaN(result))
+                            {
+                                qDebug() << "Invalid the formula value";
+                                return 0;
+                            }
+
+                            break;
+                        }
+                        else
+                        {
+                            delete dialog;
+                        }
+                    }
+                    else
+                    {
+                        throw VExceptionUndo(QString("Undo wrong formula %1").arg(formula));
+                    }
+                }
+                else
+                {
+                    throw;
+                }
+            }
+        }
+        else
+        {
+            throw;
+        }
+    }
+    return result;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief DeleteTool full delete object form scene and file.
@@ -536,16 +631,14 @@ QDomElement VAbstractTool::AddSANode(VAbstractPattern *doc, const QString &tagNa
     }
     else
     {
-        const qreal w1 = node.GetSABefore();
-        if (w1 >= 0)
+        if (node.GetFormulaSABefore() != currentSeamAllowance)
         {
-            doc->SetAttribute(nod, VAbstractPattern::AttrSABefore, w1);
+            doc->SetAttribute(nod, VAbstractPattern::AttrSABefore, node.GetFormulaSABefore());
         }
 
-        const qreal w2 = node.GetSAAfter();
-        if (w2 >= 0)
+        if (node.GetFormulaSAAfter() != currentSeamAllowance)
         {
-            doc->SetAttribute(nod, VAbstractPattern::AttrSAAfter, w2);
+            doc->SetAttribute(nod, VAbstractPattern::AttrSAAfter, node.GetFormulaSAAfter());
         }
     }
 
diff --git a/src/libs/vtools/tools/vabstracttool.h b/src/libs/vtools/tools/vabstracttool.h
index 1b24d6d39..e4bec6a15 100644
--- a/src/libs/vtools/tools/vabstracttool.h
+++ b/src/libs/vtools/tools/vabstracttool.h
@@ -73,6 +73,8 @@ public:
 
     static const QString AttrInUse;
 
+    static qreal CheckFormula(const quint32 &toolId, QString &formula, VContainer *data);
+
     static const QStringList    StylesList();
     static Qt::PenStyle         LineStyleToPenStyle(const QString &typeLine);
     static QString              PenStyleToLineStyle(Qt::PenStyle penStyle);
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 9fcc89f9d..35382ced9 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -91,10 +91,11 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
     DialogSeamAllowance *dialogTool = qobject_cast<DialogSeamAllowance*>(dialog);
     SCASSERT(dialogTool != nullptr);
     VPiece detail = dialogTool->GetPiece();
+    QString width = detail.GetFormulaSAWidth();
     qApp->getUndoStack()->beginMacro("add detail");
     detail.GetPath().SetNodes(PrepareNodes(detail.GetPath(), scene, doc, data));
 
-    VToolSeamAllowance *piece = Create(0, detail, scene, doc, data, Document::FullParse, Source::FromGui);
+    VToolSeamAllowance *piece = Create(0, detail, width, scene, doc, data, Document::FullParse, Source::FromGui);
 
     if (piece != nullptr)
     {
@@ -104,16 +105,24 @@ VToolSeamAllowance *VToolSeamAllowance::Create(DialogTool *dialog, VMainGraphics
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, const VPiece &newPiece, VMainGraphicsScene *scene,
+VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, VPiece newPiece, QString &width, VMainGraphicsScene *scene,
                                                VAbstractPattern *doc, VContainer *data, const Document &parse,
                                                const Source &typeCreation, const QString &drawName)
 {
     if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
     {
+        data->AddVariable(currentSeamAllowance, new VIncrement(data, currentSeamAllowance, 0, newPiece.GetSAWidth(),
+                                                               width, true, tr("Current seam allowance")));
         id = data->AddPiece(newPiece);
     }
     else
     {
+        const qreal calcWidth = CheckFormula(id, width, data);
+        newPiece.SetFormulaSAWidth(width, calcWidth);
+
+        data->AddVariable(currentSeamAllowance, new VIncrement(data, currentSeamAllowance, 0, calcWidth,
+                                                               width, true, tr("Current seam allowance")));
+
         data->UpdatePiece(id, newPiece);
         if (parse != Document::FullParse)
         {
@@ -121,19 +130,20 @@ VToolSeamAllowance *VToolSeamAllowance::Create(quint32 id, const VPiece &newPiec
         }
     }
     VAbstractTool::AddRecord(id, Tool::Piece, doc);
+    VToolSeamAllowance *piece = nullptr;
     if (parse == Document::FullParse)
     {
-        VToolSeamAllowance *piece = new VToolSeamAllowance(doc, data, id, typeCreation, scene, drawName);
+        piece = new VToolSeamAllowance(doc, data, id, typeCreation, scene, drawName);
         scene->addItem(piece);
         connect(piece, &VToolSeamAllowance::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
         connect(scene, &VMainGraphicsScene::EnableDetailItemHover, piece, &VToolSeamAllowance::AllowHover);
         connect(scene, &VMainGraphicsScene::EnableDetailItemSelection, piece, &VToolSeamAllowance::AllowSelecting);
         connect(scene, &VMainGraphicsScene::HighlightDetail, piece, &VToolSeamAllowance::Highlight);
         doc->AddTool(id, piece);
-
-        return piece;
     }
-    return nullptr;
+    //Very important to delete it. Only this tool need this special variable.
+    data->RemoveVariable(currentLength);
+    return piece;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -163,7 +173,7 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrInLayout, piece.IsInLayout());
     doc->SetAttribute(domElement, AttrForbidFlipping, piece.IsForbidFlipping());
     doc->SetAttribute(domElement, AttrSeamAllowance, piece.IsSeamAllowance());
-    doc->SetAttribute(domElement, AttrWidth, piece.GetSAWidth());
+    doc->SetAttribute(domElement, AttrWidth, piece.GetFormulaSAWidth());
     doc->SetAttribute(domElement, AttrUnited, piece.IsUnited());
 }
 
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index f3f0f8111..742b42979 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -51,7 +51,7 @@ public:
 
     static VToolSeamAllowance* Create(DialogTool *m_dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
                                       VContainer *data);
-    static VToolSeamAllowance* Create(quint32 id, const VPiece &newPiece, VMainGraphicsScene *scene,
+    static VToolSeamAllowance* Create(quint32 id, VPiece newPiece, QString &width, VMainGraphicsScene *scene,
                                       VAbstractPattern *doc, VContainer *data, const Document &parse,
                                       const Source &typeCreation, const QString &m_drawName = QString());
 
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index b5768ab8c..f3b116ad6 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -1182,11 +1182,12 @@ void CreateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, q
     CreateUnitedInternalPaths(newDetail, d1, d2, id, drawName, initData, dx, dy, pRotate, angle);
 
     newDetail.SetName(QObject::tr("United detail"));
-    newDetail.SetSAWidth(d1.GetSAWidth());
+    QString formulaSAWidth = d1.GetFormulaSAWidth();
+    newDetail.SetFormulaSAWidth(formulaSAWidth, d1.GetSAWidth());
     newDetail.SetMx(d1.GetMx());
     newDetail.SetMy(d1.GetMy());
-    VToolSeamAllowance::Create(0, newDetail, initData.scene, initData.doc, initData.data, initData.parse,
-                               Source::FromTool, drawName);
+    VToolSeamAllowance::Create(0, newDetail, formulaSAWidth, initData.scene, initData.doc, initData.data,
+                               initData.parse, Source::FromTool, drawName);
 
     auto RemoveDetail = [initData](quint32 id)
     {

From 24d5aa0f53cf55d0ac4a860a16d309ed11a53d30 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 15:49:43 +0200
Subject: [PATCH 178/208] The error message should display the translated
 measurement name.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 412f16af2..8823c0370 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -401,14 +401,17 @@ QSharedPointer<VMeasurements> MainWindow::OpenMeasurementFile(const QString &pat
             throw e;
         }
 
-        const QStringList mList = m->ListAll();
-        const QStringList pList = doc->ListMeasurements();
-
-        const QSet<QString> match = pList.toSet().subtract(mList.toSet());
+        const QSet<QString> match = doc->ListMeasurements().toSet().subtract(m->ListAll().toSet());
         if (not match.isEmpty())
         {
+            QList<QString> list = match.toList();
+            for (int i = 0; i < list.size(); ++i)
+            {
+                list[i] = qApp->TrVars()->MToUser(list.at(i));
+            }
+
             VException e(tr("Measurement file doesn't include all required measurements."));
-            e.AddMoreInformation(tr("Please, additionaly provide: %1").arg(QStringList(match.toList()).join(", ")));
+            e.AddMoreInformation(tr("Please, additionaly provide: %1").arg(QStringList(list).join(", ")));
             throw e;
         }
 

From e15d4d9c0541b4952341f521ec2598fa4cb05bb1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 15:50:17 +0200
Subject: [PATCH 179/208] Fix possible memory leak.

--HG--
branch : feature
---
 src/app/tape/tmainwindow.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp
index e0be0b916..d6e4f6e63 100644
--- a/src/app/tape/tmainwindow.cpp
+++ b/src/app/tape/tmainwindow.cpp
@@ -1258,10 +1258,9 @@ void TMainWindow::ImportFromPattern()
         converter.Convert();
 
         VDomDocument::ValidateXML(VPatternConverter::CurrentSchema, mPath);
-        VLitePattern *doc = new VLitePattern();
+        QScopedPointer<VLitePattern> doc(new VLitePattern());
         doc->setXMLContent(mPath);
         measurements = doc->ListMeasurements();
-        delete doc; // close a pattern
     }
     catch (VException &e)
     {

From 669d295804b35bf59f612375641bbb7abf39e05a Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 16:30:14 +0200
Subject: [PATCH 180/208] Class VToolDetail removed.

--HG--
branch : feature
---
 .../core/vtooloptionspropertybrowser.cpp      |    6 +-
 src/app/valentina/dialogs/dialoghistory.cpp   |    3 +-
 src/app/valentina/mainwindow.cpp              |   31 +-
 src/app/valentina/mainwindow.h                |    1 -
 src/app/valentina/xml/vpattern.cpp            |   22 +-
 src/libs/ifc/xml/vabstractpattern.cpp         |   12 +-
 src/libs/vmisc/def.h                          |    1 -
 src/libs/vtools/tools/tools.pri               |    2 -
 src/libs/vtools/tools/vtooldetail.cpp         | 1327 -----------------
 src/libs/vtools/tools/vtooldetail.h           |  164 --
 src/libs/vtools/undocommands/adddet.cpp       |  120 --
 src/libs/vtools/undocommands/adddet.h         |   66 -
 src/libs/vtools/undocommands/deletedetail.cpp |  111 --
 src/libs/vtools/undocommands/deletedetail.h   |   62 -
 .../vtools/undocommands/savedetailoptions.cpp |  216 ---
 .../vtools/undocommands/savedetailoptions.h   |   83 --
 src/libs/vtools/undocommands/undocommands.pri |    6 -
 17 files changed, 24 insertions(+), 2209 deletions(-)
 delete mode 100644 src/libs/vtools/tools/vtooldetail.cpp
 delete mode 100644 src/libs/vtools/tools/vtooldetail.h
 delete mode 100644 src/libs/vtools/undocommands/adddet.cpp
 delete mode 100644 src/libs/vtools/undocommands/adddet.h
 delete mode 100644 src/libs/vtools/undocommands/deletedetail.cpp
 delete mode 100644 src/libs/vtools/undocommands/deletedetail.h
 delete mode 100644 src/libs/vtools/undocommands/savedetailoptions.cpp
 delete mode 100644 src/libs/vtools/undocommands/savedetailoptions.h

diff --git a/src/app/valentina/core/vtooloptionspropertybrowser.cpp b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
index 8e0e356bd..09e22849e 100644
--- a/src/app/valentina/core/vtooloptionspropertybrowser.cpp
+++ b/src/app/valentina/core/vtooloptionspropertybrowser.cpp
@@ -76,7 +76,7 @@ void VToolOptionsPropertyBrowser::ClearPropertyBrowser()
 void VToolOptionsPropertyBrowser::ShowItemOptions(QGraphicsItem *item)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were used in switch.");
 
     switch (item->type())
     {
@@ -203,7 +203,7 @@ void VToolOptionsPropertyBrowser::UpdateOptions()
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were used in switch.");
 
     switch (currentItem->type())
     {
@@ -348,7 +348,7 @@ void VToolOptionsPropertyBrowser::userChangedData(VPE::VProperty *property)
     }
 
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were used in switch.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were used in switch.");
 
     switch (currentItem->type())
     {
diff --git a/src/app/valentina/dialogs/dialoghistory.cpp b/src/app/valentina/dialogs/dialoghistory.cpp
index ae3f66b62..a168827b8 100644
--- a/src/app/valentina/dialogs/dialoghistory.cpp
+++ b/src/app/valentina/dialogs/dialoghistory.cpp
@@ -212,7 +212,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QString DialogHistory::Record(const VToolRecord &tool)
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were used in history.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were used in history.");
 
     const QDomElement domElem = doc->elementById(tool.getId());
     if (domElem.isElement() == false)
@@ -392,7 +392,6 @@ QString DialogHistory::Record(const VToolRecord &tool)
             }
             //Because "history" not only show history of pattern, but help restore current data for each pattern's
             //piece, we need add record about details and nodes, but don't show them.
-            case Tool::Detail:
             case Tool::Piece:
             case Tool::UnionDetails:
             case Tool::NodeArc:
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 8823c0370..e15949234 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -51,7 +51,6 @@
 #include "../vwidgets/vmaingraphicsscene.h"
 #include "tools/drawTools/drawtools.h"
 #include "../vtools/dialogs/tooldialogs.h"
-#include "tools/vtooldetail.h"
 #include "tools/vtoolseamallowance.h"
 #include "tools/nodeDetails/vtoolpiecepath.h"
 #include "tools/vtooluniondetails.h"
@@ -990,21 +989,6 @@ void MainWindow::ToolPiecePath(bool checked)
                                    &MainWindow::ClosedDialogPiecePath);
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ClosedDialogDetail actions after closing DialogDetail.
- * @param result result of dialog working.
- */
-void MainWindow::ClosedDialogDetail(int result)
-{
-    if (result == QDialog::Accepted)
-    {
-        VToolDetail::Create(dialogTool, sceneDetails, doc, pattern);
-    }
-    ArrowTool();
-    doc->LiteParseTree(Document::LiteParse);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ToolHeight handler tool height.
@@ -1772,7 +1756,7 @@ void MainWindow::InitToolButtons()
     }
 
     // This check helps to find missed tools
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Check if all tools were connected.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Check if all tools were connected.");
 
     connect(ui->toolButtonEndLine, &QToolButton::clicked, this, &MainWindow::ToolEndLine);
     connect(ui->toolButtonLine, &QToolButton::clicked, this, &MainWindow::ToolLine);
@@ -1845,7 +1829,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::CancelTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled.");
 
     qCDebug(vMainWindow, "Canceling tool.");
     delete dialogTool;
@@ -1929,9 +1913,6 @@ void MainWindow::CancelTool()
         case Tool::PointOfContact:
             ui->toolButtonPointOfContact->setChecked(false);
             break;
-        case Tool::Detail:
-            ui->toolButtonNewDetail->setChecked(false);
-            break;
         case Tool::Piece:
             ui->toolButtonNewDetail->setChecked(false);
             break;
@@ -3055,7 +3036,7 @@ void MainWindow::SetEnableTool(bool enable)
     }
 
     // This check helps to find missed tools
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled.");
 
     //Drawing Tools
     ui->toolButtonEndLine->setEnabled(drawTools);
@@ -3377,7 +3358,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 void MainWindow::LastUsedTool()
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were handled.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled.");
 
     if (currentTool == lastUsedTool)
     {
@@ -3464,10 +3445,6 @@ void MainWindow::LastUsedTool()
             ui->toolButtonPointOfContact->setChecked(true);
             ToolPointOfContact(true);
             break;
-        case Tool::Detail:
-            ui->toolButtonNewDetail->setChecked(true);
-            ToolDetail(true);
-            break;
         case Tool::Piece:
             ui->toolButtonNewDetail->setChecked(true);
             ToolDetail(true);
diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h
index fed8ae7e0..7b6277533 100644
--- a/src/app/valentina/mainwindow.h
+++ b/src/app/valentina/mainwindow.h
@@ -168,7 +168,6 @@ private slots:
     bool Save();
     void Open();
 
-    void ClosedDialogDetail(int result);
     void ClosedDialogUnionDetails(int result);
     void ClosedDialogGroup(int result);
     void ClosedDialogPiecePath(int result);
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 6bee26a2b..3b2855a4e 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -29,7 +29,6 @@
 #include "vpattern.h"
 #include "../vwidgets/vabstractmainwindow.h"
 #include "../vtools/tools/vdatatool.h"
-#include "../vtools/tools/vtooldetail.h"
 #include "../vtools/tools/vtoolseamallowance.h"
 #include "../vtools/tools/vtooluniondetails.h"
 #include "../vtools/tools/drawTools/drawtools.h"
@@ -812,13 +811,13 @@ void VPattern::ParsePieceDataTag(const QDomElement &domElement, VPiece &detail)
     ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
     ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
     detail.GetPatternPieceData().SetPos(ptPos);
-    qreal dLW = GetParametrDouble(domElement, VToolDetail::AttrWidth, "0");
+    qreal dLW = GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0");
     detail.GetPatternPieceData().SetLabelWidth(dLW);
-    qreal dLH = GetParametrDouble(domElement, VToolDetail::AttrHeight, "0");
+    qreal dLH = GetParametrDouble(domElement, VToolSeamAllowance::AttrHeight, "0");
     detail.GetPatternPieceData().SetLabelHeight(dLH);
-    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolDetail::AttrFont, "0"));
+    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolSeamAllowance::AttrFont, "0"));
     detail.GetPatternPieceData().SetFontSize(iFS);
-    qreal dRot = GetParametrDouble(domElement, VToolDetail::AttrRotation, "0");
+    qreal dRot = GetParametrDouble(domElement, VToolSeamAllowance::AttrRotation, "0");
     detail.GetPatternPieceData().SetRotation(dRot);
 
     QDomNodeList nodeListMCP = domElement.childNodes();
@@ -845,13 +844,13 @@ void VPattern::ParsePiecePatternInfo(const QDomElement &domElement, VPiece &deta
     ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
     ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
     detail.GetPatternInfo().SetPos(ptPos);
-    qreal dLW = GetParametrDouble(domElement, VToolDetail::AttrWidth, "0");
+    qreal dLW = GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0");
     detail.GetPatternInfo().SetLabelWidth(dLW);
-    qreal dLH = GetParametrDouble(domElement, VToolDetail::AttrHeight, "0");
+    qreal dLH = GetParametrDouble(domElement, VToolSeamAllowance::AttrHeight, "0");
     detail.GetPatternInfo().SetLabelHeight(dLH);
-    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolDetail::AttrFont, "0"));
+    int iFS = static_cast<int>(GetParametrUInt(domElement, VToolSeamAllowance::AttrFont, "0"));
     detail.GetPatternInfo().SetFontSize(iFS);
-    qreal dRot = GetParametrDouble(domElement, VToolDetail::AttrRotation, "0");
+    qreal dRot = GetParametrDouble(domElement, VToolSeamAllowance::AttrRotation, "0");
     detail.GetPatternInfo().SetRotation(dRot);
 }
 
@@ -865,7 +864,7 @@ void VPattern::ParsePieceGrainline(const QDomElement &domElement, VPiece &detail
     detail.GetGrainlineGeometry().SetPos(ptPos);
     QString qsLength = GetParametrString(domElement, AttrLength, "0");
     detail.GetGrainlineGeometry().SetLength(qsLength);
-    QString qsRot = GetParametrString(domElement, VToolDetail::AttrRotation, "90");
+    QString qsRot = GetParametrString(domElement, VToolSeamAllowance::AttrRotation, "90");
     detail.GetGrainlineGeometry().SetRotation(qsRot);
     VGrainlineGeometry::ArrowType eAT =
             VGrainlineGeometry::ArrowType(GetParametrUInt(domElement, AttrArrows, "0"));
@@ -3737,7 +3736,7 @@ QT_WARNING_DISABLE_GCC("-Wswitch-default")
 QRectF VPattern::ActiveDrawBoundingRect() const
 {
     // This check helps to find missed tools in the switch
-    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52, "Not all tools were used.");
+    Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were used.");
 
     QRectF rec;
 
@@ -3862,7 +3861,6 @@ QRectF VPattern::ActiveDrawBoundingRect() const
                     rec = ToolBoundingRect<VToolEllipticalArc>(rec, tool.getId());
                     break;
                 //These tools are not accesseble in Draw mode, but still 'history' contains them.
-                case Tool::Detail:
                 case Tool::Piece:
                 case Tool::UnionDetails:
                 case Tool::NodeArc:
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index 87755a387..c344bc12e 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -774,7 +774,7 @@ quint32 VAbstractPattern::SiblingNodeId(const quint32 &nodeId) const
                     const VToolRecord tool = history.at(j-1);
                     switch ( tool.getTypeTool() )
                     {
-                        case Tool::Detail:
+                        case Tool::Piece:
                         case Tool::UnionDetails:
                         case Tool::NodeArc:
                         case Tool::NodeElArc:
@@ -1566,7 +1566,7 @@ QStringList VAbstractPattern::ListPointExpressions() const
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment a number.
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagPoint);
@@ -1638,7 +1638,7 @@ QStringList VAbstractPattern::ListArcExpressions() const
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number.
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagArc);
@@ -1692,7 +1692,7 @@ QStringList VAbstractPattern::ListElArcExpressions() const
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number.
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagElArc);
@@ -1763,7 +1763,7 @@ QStringList VAbstractPattern::ListPathPointExpressions() const
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number.
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(AttrPathPoint);
@@ -1830,7 +1830,7 @@ QStringList VAbstractPattern::ListOperationExpressions() const
     // Check if new tool doesn't bring new attribute with a formula.
     // If no just increment number.
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
-    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 52);
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
 
     QStringList expressions;
     const QDomNodeList list = elementsByTagName(TagOperation);
diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h
index 8ef847585..15a5ef7aa 100644
--- a/src/libs/vmisc/def.h
+++ b/src/libs/vmisc/def.h
@@ -120,7 +120,6 @@ enum class Tool : ToolVisHolderType
     CubicBezierPath,
     CutSplinePath,
     PointOfContact,
-    Detail,
     Piece,
     PiecePath,
     NodePoint,
diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri
index 99d8e4bcb..2b755c117 100644
--- a/src/libs/vtools/tools/tools.pri
+++ b/src/libs/vtools/tools/tools.pri
@@ -2,7 +2,6 @@
 # This need for corect working file translations.pro
 
 HEADERS += \
-    $$PWD/vtooldetail.h \
     $$PWD/vdatatool.h \
     $$PWD/vabstracttool.h \
     $$PWD/tools.h \
@@ -62,7 +61,6 @@ HEADERS += \
     $$PWD/nodeDetails/vtoolpiecepath.h
 
 SOURCES += \
-    $$PWD/vtooldetail.cpp \
     $$PWD/vdatatool.cpp \
     $$PWD/vabstracttool.cpp \
     $$PWD/drawTools/toolpoint/toolsinglepoint/vtooltriangle.cpp \
diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp
deleted file mode 100644
index 5a4abc1b0..000000000
--- a/src/libs/vtools/tools/vtooldetail.cpp
+++ /dev/null
@@ -1,1327 +0,0 @@
-/************************************************************************
- **
- **  @file   vtooldetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "vtooldetail.h"
-
-#include <QAction>
-#include <QBrush>
-#include <QDialog>
-#include <QDomElement>
-#include <QEvent>
-#include <QFlags>
-#include <QFont>
-#include <QGraphicsItem>
-#include <QGraphicsScene>
-#include <QGraphicsSceneContextMenuEvent>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsView>
-#include <QHash>
-#include <QIcon>
-#include <QKeyEvent>
-#include <QList>
-#include <QMenu>
-#include <QMessageBox>
-#include <QMessageLogger>
-#include <QPainter>
-#include <QPainterPath>
-#include <QPen>
-#include <QPoint>
-#include <QPointF>
-#include <QPolygonF>
-#include <QRectF>
-#include <QSharedPointer>
-#include <QStaticStringData>
-#include <QString>
-#include <QStringData>
-#include <QStringDataPtr>
-#include <QStringList>
-#include <QUndoStack>
-#include <QVariant>
-#include <Qt>
-#include <QtDebug>
-#include <new>
-
-#include "../dialogs/tools/dialogtool.h"
-#include "../ifc/exception/vexception.h"
-#include "../ifc/xml/vdomdocument.h"
-#include "../ifc/xml/vabstractpattern.h"
-#include "../ifc/ifcdef.h"
-#include "../undocommands/adddet.h"
-#include "../undocommands/deletedetail.h"
-#include "../undocommands/movepiece.h"
-#include "../undocommands/savedetailoptions.h"
-#include "../undocommands/togglepieceinlayout.h"
-#include "../vgeometry/varc.h"
-#include "../vgeometry/vellipticalarc.h"
-#include "../vgeometry/vcubicbezier.h"
-#include "../vgeometry/vcubicbezierpath.h"
-#include "../vgeometry/vgeometrydef.h"
-#include "../vgeometry/vgobject.h"
-#include "../vgeometry/vpointf.h"
-#include "../vgeometry/vspline.h"
-#include "../vgeometry/vsplinepath.h"
-#include "../vmisc/vabstractapplication.h"
-#include "../vpatterndb/vcontainer.h"
-#include "../vpatterndb/vdetail.h"
-#include "../vpatterndb/vpatterninfogeometry.h"
-#include "../vpatterndb/vpatternpiecedata.h"
-#include "../vpatterndb/calculator.h"
-#include "../vmisc/def.h"
-#include "../vwidgets/vmaingraphicsscene.h"
-#include "../vwidgets/vmaingraphicsview.h"
-#include "../vwidgets/vnobrushscalepathitem.h"
-#include "../tools/vtooldetail.h"
-#include "vabstracttool.h"
-#include "nodeDetails/vabstractnode.h"
-#include "nodeDetails/vnodearc.h"
-#include "nodeDetails/vnodeellipticalarc.h"
-#include "nodeDetails/vnodepoint.h"
-#include "nodeDetails/vnodespline.h"
-#include "nodeDetails/vnodesplinepath.h"
-#include "vtextgraphicsitem.h"
-#include "vnodedetail.h"
-
-class QDomElement;
-class QGraphicsSceneContextMenuEvent;
-class QGraphicsSceneHoverEvent;
-class QGraphicsSceneMouseEvent;
-class QKeyEvent;
-class QStyleOptionGraphicsItem;
-class QWidget;
-class VDataTool;
-
-const QString VToolDetail::TagNode            = QStringLiteral("node");
-
-const QString VToolDetail::AttrSupplement     = QStringLiteral("supplement");
-const QString VToolDetail::AttrClosed         = QStringLiteral("closed");
-const QString VToolDetail::AttrForbidFlipping = QStringLiteral("forbidFlipping");
-const QString VToolDetail::AttrWidth          = QStringLiteral("width");
-const QString VToolDetail::AttrHeight         = QStringLiteral("height");
-const QString VToolDetail::AttrNodeType       = QStringLiteral("nodeType");
-const QString VToolDetail::AttrReverse        = QStringLiteral("reverse");
-const QString VToolDetail::AttrFont           = QStringLiteral("fontSize");
-const QString VToolDetail::AttrRotation       = QStringLiteral("rotation");
-
-const QString VToolDetail::NodeTypeContour    = QStringLiteral("Contour");
-const QString VToolDetail::NodeTypeModeling   = QStringLiteral("Modeling");
-
-const QString VToolDetail::NodeArc            = QStringLiteral("NodeArc");
-const QString VToolDetail::NodeElArc          = QStringLiteral("NodeElArc");
-const QString VToolDetail::NodePoint          = QStringLiteral("NodePoint");
-const QString VToolDetail::NodeSpline         = QStringLiteral("NodeSpline");
-const QString VToolDetail::NodeSplinePath     = QStringLiteral("NodeSplinePath");
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VToolDetail constructor.
- * @param doc dom document container
- * @param data container with variables
- * @param id object id in container
- * @param typeCreation way we create this tool.
- * @param scene pointer to scene.
- * @param parent parent object
- */
-VToolDetail::VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation,
-                         VMainGraphicsScene *scene, const QString &drawName, QGraphicsItem *parent)
-    :VAbstractTool(doc, data, id), VNoBrushScalePathItem(parent), dialog(nullptr), sceneDetails(scene),
-      drawName(drawName), seamAllowance(new VNoBrushScalePathItem(this)), dataLabel(new VTextGraphicsItem(this)),
-      patternInfo(new VTextGraphicsItem(this)), grainLine(new VGrainlineItem(this))
-{
-    VDetail detail = data->GetDetail(id);
-    for (int i = 0; i< detail.CountNode(); ++i)
-    {
-        switch (detail.at(i).getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                VNodePoint *tool = InitTool<VNodePoint>(scene, detail.at(i));
-                connect(tool, &VNodePoint::ShowContextMenu, this, &VToolDetail::contextMenuEvent);
-                break;
-            }
-            case (Tool::NodeArc):
-            case (Tool::NodeElArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-                doc->IncrementReferens(detail.at(i).getId());
-                break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore.";
-                break;
-        }
-    }
-    this->setFlag(QGraphicsItem::ItemIsMovable, true);
-    this->setFlag(QGraphicsItem::ItemIsSelectable, true);
-    RefreshGeometry();
-
-    this->setBrush(QBrush(Qt::Dense7Pattern));
-    seamAllowance->setBrush(QBrush(Qt::FDiagPattern));
-
-    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
-    this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
-
-    connect(scene, &VMainGraphicsScene::EnableToolMove, this, &VToolDetail::EnableToolMove);
-    connect(scene, &VMainGraphicsScene::ItemClicked, this, &VToolDetail::ResetChildren);
-    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
-    {
-        AddToFile();
-        if (typeCreation != Source::FromTool)
-        {
-            qApp->getUndoStack()->endMacro();
-        }
-    }
-    setAcceptHoverEvents(true);
-
-    connect(dataLabel, &VTextGraphicsItem::SignalMoved, this, &VToolDetail::SaveMoveDetail);
-    connect(dataLabel, &VTextGraphicsItem::SignalResized, this, &VToolDetail::SaveResizeDetail);
-    connect(dataLabel, &VTextGraphicsItem::SignalRotated, this, &VToolDetail::SaveRotationDetail);
-
-    connect(patternInfo, &VTextGraphicsItem::SignalMoved, this, &VToolDetail::SaveMovePattern);
-    connect(patternInfo, &VTextGraphicsItem::SignalResized, this, &VToolDetail::SaveResizePattern);
-    connect(patternInfo, &VTextGraphicsItem::SignalRotated, this, &VToolDetail::SaveRotationPattern);
-
-    connect(grainLine, &VGrainlineItem::SignalMoved, this, &VToolDetail::SaveMoveGrainline);
-    connect(grainLine, &VGrainlineItem::SignalResized, this, &VToolDetail::SaveResizeGrainline);
-    connect(grainLine, &VGrainlineItem::SignalRotated, this, &VToolDetail::SaveRotateGrainline);
-
-    connect(doc, &VAbstractPattern::patternChanged, this, &VToolDetail::UpdatePatternInfo);
-    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdateLabel);
-    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdatePatternInfo);
-    connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdateGrainline);
-
-    connect(sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolDetail::UpdateLabel);
-    connect(sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolDetail::UpdatePatternInfo);
-    connect(sceneDetails, &VMainGraphicsScene::LanguageChanged, this, &VToolDetail::retranslateUi);
-
-    UpdateLabel();
-    UpdatePatternInfo();
-    UpdateGrainline();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-VToolDetail::~VToolDetail()
-{
-    delete dialog;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setDialog set dialog when user want change tool option.
- */
-void VToolDetail::setDialog()
-{
-    SCASSERT(dialog != nullptr)
-//    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-//    SCASSERT(dialogTool != nullptr)
-//    dialogTool->setDetail(VAbstractTool::data.GetDetail(id));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Create help create tool from GUI.
- * @param dialog dialog.
- * @param scene pointer to scene.
- * @param doc dom document container.
- * @param data container with variables.
- */
-void VToolDetail::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data)
-{
-    SCASSERT(dialog != nullptr)
-//    DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-//    SCASSERT(dialogTool != nullptr)
-//    VDetail detail = dialogTool->getDetail();
-//    VDetail det;
-//    qApp->getUndoStack()->beginMacro("add detail");
-//    for (int i = 0; i< detail.CountNode(); ++i)
-//    {
-//        quint32 id = 0;
-//        const VNodeDetail &nodeD = detail.at(i);
-//        switch (nodeD.getTypeTool())
-//        {
-//            case (Tool::NodePoint):
-//            {
-//                id = CreateNode<VPointF>(data, nodeD.getId());
-//                VNodePoint::Create(doc, data, scene, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-//            }
-//            break;
-//            case (Tool::NodeArc):
-//            {
-//                id = CreateNode<VArc>(data, nodeD.getId());
-//                VNodeArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-//            }
-//            break;
-//            case (Tool::NodeElArc):
-//            {
-//                id = CreateNode<VEllipticalArc>(data, nodeD.getId());
-//                VNodeEllipticalArc::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-//            }
-//            break;
-//            case (Tool::NodeSpline):
-//            {
-//                const auto obj = data->GetGObject(nodeD.getId());
-//                if (obj->getType() == GOType::Spline)
-//                {
-//                    id = CreateNode<VSpline>(data, nodeD.getId());
-//                }
-//                else
-//                {
-//                    id = CreateNode<VCubicBezier>(data, nodeD.getId());
-//                }
-//                VNodeSpline::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-//            }
-//            break;
-//            case (Tool::NodeSplinePath):
-//            {
-//                const auto obj = data->GetGObject(nodeD.getId());
-//                if (obj->getType() == GOType::SplinePath)
-//                {
-//                    id = CreateNode<VSplinePath>(data, nodeD.getId());
-//                }
-//                else
-//                {
-//                    id = CreateNode<VCubicBezierPath>(data, nodeD.getId());
-//                }
-//                VNodeSplinePath::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
-//            }
-//            break;
-//            default:
-//                qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-//                break;
-//        }
-//        VNodeDetail node(id, nodeD.getTypeTool(), NodeDetail::Contour, nodeD.getMx(), nodeD.getMy(),
-//                         nodeD.getReverse());
-//        det.append(node);
-//    }
-//    det.setName(detail.getName());
-//    det.setWidth(detail.getWidth());
-//    det.setClosed(detail.getClosed());
-//    det.setSeamAllowance(detail.getSeamAllowance());
-//    det.setForbidFlipping(detail.getForbidFlipping());
-//    det.SetPatternPieceData(detail.GetPatternPieceData());
-//    det.SetPatternInfo(detail.GetPatternInfo());
-//    Create(0, det, scene, doc, data, Document::FullParse, Source::FromGui);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Create help create tool.
- * @param _id tool id, 0 if tool doesn't exist yet.
- * @param newDetail detail what we want show.
- * @param scene pointer to scene.
- * @param doc dom document container.
- * @param data container with variables.
- * @param parse parser file mode.
- * @param typeCreation way we create this tool.
- */
-void VToolDetail::Create(const quint32 &_id, const VDetail &newDetail, VMainGraphicsScene *scene, VAbstractPattern *doc,
-                         VContainer *data, const Document &parse, const Source &typeCreation, const QString &drawName)
-{
-    quint32 id = _id;
-    if (typeCreation == Source::FromGui || typeCreation == Source::FromTool)
-    {
-        id = data->AddDetail(newDetail);
-    }
-    else
-    {
-        data->UpdateDetail(id, newDetail);
-        if (parse != Document::FullParse)
-        {
-            doc->UpdateToolData(id, data);
-        }
-    }
-    VAbstractTool::AddRecord(id, Tool::Detail, doc);
-    if (parse == Document::FullParse)
-    {
-        VToolDetail *detail = new VToolDetail(doc, data, id, typeCreation, scene, drawName);
-        scene->addItem(detail);
-        connect(detail, &VToolDetail::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
-        connect(scene, &VMainGraphicsScene::EnableDetailItemHover, detail, &VToolDetail::AllowHover);
-        connect(scene, &VMainGraphicsScene::EnableDetailItemSelection, detail, &VToolDetail::AllowSelecting);
-        connect(scene, &VMainGraphicsScene::HighlightDetail, detail, &VToolDetail::Highlight);
-        doc->AddTool(id, detail);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Remove full delete detail.
- */
-void VToolDetail::Remove(bool ask)
-{
-    try
-    {
-        DeleteTool(ask);
-    }
-    catch(const VExceptionToolWasDeleted &e)
-    {
-        Q_UNUSED(e)
-        return;//Leave this method immediately!!!
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief FullUpdateFromFile update tool data form file.
- */
-void VToolDetail::FullUpdateFromFile()
-{
-    RefreshGeometry();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief FullUpdateFromGuiOk refresh tool data after change in options.
- * @param result keep result working dialog.
- */
-void VToolDetail::FullUpdateFromGuiOk(int result)
-{
-    if (result == QDialog::Accepted)
-    {
-        SCASSERT(dialog != nullptr)
-//        DialogDetail *dialogTool = qobject_cast<DialogDetail*>(dialog);
-//        SCASSERT(dialogTool != nullptr)
-//        const VDetail newDet = dialogTool->getDetail();
-//        const VDetail oldDet = VAbstractTool::data.GetDetail(id);
-
-//        qDebug() << "VToolDetail Position" << newDet.GetPatternPieceData().GetPos();
-//        SaveDetailOptions *saveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-//        connect(saveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-//        qApp->getUndoStack()->push(saveCommand);
-//        UpdateLabel();
-    }
-    delete dialog;
-    dialog = nullptr;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VToolDetail::paint draws a bounding box around detail, if one of its text or grainline items is not idle.
- */
-void VToolDetail::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
-    if (scene()->views().count() > 0)
-    {
-        const QPoint pt0 = scene()->views().at(0)->mapFromScene(0, 0);
-        const QPoint pt = scene()->views().at(0)->mapFromScene(0, 100);
-
-        const QPoint p = pt - pt0;
-
-#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
-        const qreal dScale = qSqrt(QPoint::dotProduct(p, p));
-#else
-        const qreal dScale = qSqrt(p.x() * p.x() + p.y() * p.y());
-#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
-        grainLine->SetScale(100/dScale);
-        //qDebug() << "SCALE" << dScale << 10/dScale;
-    }
-
-    if (dataLabel->IsIdle() == false || patternInfo->IsIdle() == false || grainLine->IsIdle() == false)
-    {
-        painter->save();
-        painter->setPen(QPen(Qt::black, 3, Qt::DashLine));
-        painter->drawRect(boundingRect().adjusted(1, 1, -1, -1));
-        painter->restore();
-    }
-    VNoBrushScalePathItem::paint(painter, option, widget);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddToFile add tag with informations about tool into file.
- */
-void VToolDetail::AddToFile()
-{
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    QDomElement domElement = doc->createElement(getTagName());
-
-    doc->SetAttribute(domElement, VDomDocument::AttrId, id);
-    doc->SetAttribute(domElement, AttrName, detail.getName());
-    doc->SetAttribute(domElement, AttrMx, qApp->fromPixel(detail.getMx()));
-    doc->SetAttribute(domElement, AttrMy, qApp->fromPixel(detail.getMy()));
-    doc->SetAttribute(domElement, AttrSupplement, static_cast<quint8>(detail.getSeamAllowance()));
-    doc->SetAttribute(domElement, AttrClosed, static_cast<quint8>(detail.getClosed()));
-    doc->SetAttribute(domElement, AttrWidth, detail.getWidth());
-    doc->SetAttribute(domElement, AttrForbidFlipping, static_cast<quint8>(detail.getForbidFlipping()));
-
-    // detail data
-    QDomElement domData = doc->createElement(VAbstractPattern::TagData);
-    const VPatternPieceData& data = detail.GetPatternPieceData();
-    doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter());
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, data.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, data.GetPos().y());
-    doc->SetAttribute(domData, AttrWidth, data.GetLabelWidth());
-    doc->SetAttribute(domData, AttrHeight, data.GetLabelHeight());
-    doc->SetAttribute(domData, AttrFont, data.GetFontSize());
-    doc->SetAttribute(domData, AttrRotation, data.GetRotation());
-
-    for (int i = 0; i < data.GetMCPCount(); ++i)
-    {
-        MaterialCutPlacement mcp = data.GetMCP(i);
-        QDomElement domMCP = doc->createElement(VAbstractPattern::TagMCP);
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrMaterial, int(mcp.m_eMaterial));
-        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-        {
-            doc->SetAttribute(domMCP, VAbstractPattern::AttrUserDefined, mcp.m_qsMaterialUserDef);
-        }
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrCutNumber, mcp.m_iCutNumber);
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrPlacement, int(mcp.m_ePlacement));
-        domData.appendChild(domMCP);
-    }
-    domElement.appendChild(domData);
-
-    // pattern info
-    domData = doc->createElement(VAbstractPattern::TagPatternInfo);
-    const VPatternInfoGeometry& geom = detail.GetPatternInfo();
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, geom.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, geom.GetPos().y());
-    doc->SetAttribute(domData, AttrWidth, geom.GetLabelWidth());
-    doc->SetAttribute(domData, AttrHeight, geom.GetLabelHeight());
-    doc->SetAttribute(domData, AttrFont, geom.GetFontSize());
-    doc->SetAttribute(domData, AttrRotation, geom.GetRotation());
-    domElement.appendChild(domData);
-
-    // grainline
-    domData = doc->createElement(VAbstractPattern::TagGrainline);
-    const VGrainlineGeometry& glGeom = detail.GetGrainlineGeometry();
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y());
-    doc->SetAttribute(domData, AttrLength, glGeom.GetLength());
-    doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation());
-    doc->SetAttribute(domData, VAbstractPattern::AttrArrows, int(glGeom.GetArrowType()));
-    qDebug() << "XML ROTATION" << glGeom.GetRotation();
-
-    // nodes
-    for (int i = 0; i < detail.CountNode(); ++i)
-    {
-       AddNode(doc, domElement, detail.at(i));
-    }
-
-    AddDet *addDet = new AddDet(domElement, doc, detail, drawName);
-    connect(addDet, &AddDet::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
-    qApp->getUndoStack()->push(addDet);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief RefreshDataInFile refresh attributes in file. If attributes don't exist create them.
- */
-void VToolDetail::RefreshDataInFile()
-{
-    QDomElement domElement = doc->elementById(id);
-    if (domElement.isElement())
-    {
-        VDetail det = VAbstractTool::data.GetDetail(id);
-        doc->SetAttribute(domElement, AttrName, det.getName());
-        doc->SetAttribute(domElement, AttrSupplement, QString().setNum(static_cast<quint8>(det.getSeamAllowance())));
-        doc->SetAttribute(domElement, AttrClosed, QString().setNum(static_cast<quint8>(det.getClosed())));
-        doc->SetAttribute(domElement, AttrWidth, QString().setNum(det.getWidth()));
-        doc->RemoveAllChildren(domElement);
-
-        // detail data
-        QDomElement domData = doc->createElement(VAbstractPattern::TagData);
-        const VPatternPieceData& data = det.GetPatternPieceData();
-        doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter());
-        doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
-        doc->SetAttribute(domData, AttrMx, data.GetPos().x());
-        doc->SetAttribute(domData, AttrMy, data.GetPos().y());
-        doc->SetAttribute(domData, AttrWidth, data.GetLabelWidth());
-        doc->SetAttribute(domData, AttrHeight, data.GetLabelHeight());
-        doc->SetAttribute(domData, AttrFont, data.GetFontSize());
-        doc->SetAttribute(domData, AttrRotation, data.GetRotation());
-
-        for (int i = 0; i < data.GetMCPCount(); ++i)
-        {
-            MaterialCutPlacement mcp = data.GetMCP(i);
-            QDomElement domMCP = doc->createElement(VAbstractPattern::TagMCP);
-            doc->SetAttribute(domMCP, VAbstractPattern::AttrMaterial, int(mcp.m_eMaterial));
-            if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-            {
-                doc->SetAttribute(domMCP, VAbstractPattern::AttrUserDefined, mcp.m_qsMaterialUserDef);
-            }
-            else
-            {
-                domMCP.removeAttribute(VAbstractPattern::AttrUserDefined);
-            }
-            doc->SetAttribute(domMCP, VAbstractPattern::AttrCutNumber, mcp.m_iCutNumber);
-            doc->SetAttribute(domMCP, VAbstractPattern::AttrPlacement, int(mcp.m_ePlacement));
-            domData.appendChild(domMCP);
-        }
-        domElement.appendChild(domData);
-
-        // pattern info
-        domData = doc->createElement(VAbstractPattern::TagPatternInfo);
-        const VPatternInfoGeometry& geom = det.GetPatternInfo();
-        doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true? trueStr : falseStr);
-        doc->SetAttribute(domData, AttrMx, geom.GetPos().x());
-        doc->SetAttribute(domData, AttrMy, geom.GetPos().y());
-        doc->SetAttribute(domData, AttrWidth, geom.GetLabelWidth());
-        doc->SetAttribute(domData, AttrHeight, geom.GetLabelHeight());
-        doc->SetAttribute(domData, AttrFont, geom.GetFontSize());
-        doc->SetAttribute(domData, AttrRotation, geom.GetRotation());
-
-        // grainline
-        domData = doc->createElement(VAbstractPattern::TagGrainline);
-        const VGrainlineGeometry& glGeom = det.GetGrainlineGeometry();
-        doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr);
-        doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x());
-        doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y());
-        doc->SetAttribute(domData, AttrLength, glGeom.GetLength());
-        doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation());
-        doc->SetAttribute(domData, VAbstractPattern::AttrArrows, int(glGeom.GetArrowType()));
-
-        // nodes
-        for (int i = 0; i < det.CountNode(); ++i)
-        {
-           AddNode(doc, domElement, det.at(i));
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief itemChange handle detail change.
- * @param change change
- * @param value value
- * @return new value.
- */
-QVariant VToolDetail::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
-{
-    if (change == ItemPositionChange && scene())
-    {
-            // Each time we move something we call recalculation scene rect. In some cases this can cause moving
-            // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move.
-            static bool changeFinished = true;
-            if (changeFinished)
-            {
-               changeFinished = false;
-
-               // value - this is new position.
-               const QPointF newPos = value.toPointF();
-
-               MovePiece *moveDet = new MovePiece(doc, newPos.x(), newPos.y(), id, scene());
-               connect(moveDet, &MovePiece::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-               qApp->getUndoStack()->push(moveDet);
-
-               const QList<QGraphicsView *> viewList = scene()->views();
-               if (not viewList.isEmpty())
-               {
-                   if (QGraphicsView *view = viewList.at(0))
-                   {
-                       const int xmargin = 50;
-                       const int ymargin = 50;
-
-                       const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view);
-                       const QRectF itemRect = mapToScene(boundingRect()|childrenBoundingRect()).boundingRect();
-
-                       // If item's rect is bigger than view's rect ensureVisible works very unstable.
-                       if (itemRect.height() + 2*ymargin < viewRect.height() &&
-                           itemRect.width() + 2*xmargin < viewRect.width())
-                       {
-                            view->ensureVisible(itemRect, xmargin, ymargin);
-                       }
-                       else
-                       {
-                           // Ensure visible only small rect around a cursor
-                           VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
-                           SCASSERT(currentScene)
-                           const QPointF cursorPosition = currentScene->getScenePos();
-                           view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
-                       }
-                   }
-               }
-               // Don't forget to update geometry, because first change never call full parse
-               RefreshGeometry();
-               changeFinished = true;
-        }
-    }
-
-    if (change == QGraphicsItem::ItemSelectedChange)
-    {
-        if (value == true)
-        {
-            // do stuff if selected
-            this->setFocus();
-        }
-        else
-        {
-            // do stuff if not selected
-        }
-    }
-
-    return VNoBrushScalePathItem::itemChange(change, value);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief keyReleaseEvent handle key release events.
- * @param event key release event.
- */
-void VToolDetail::keyReleaseEvent(QKeyEvent *event)
-{
-    switch (event->key())
-    {
-        case Qt::Key_Delete:
-            try
-            {
-                DeleteTool();
-            }
-            catch(const VExceptionToolWasDeleted &e)
-            {
-                Q_UNUSED(e)
-                return;//Leave this method immediately!!!
-            }
-            break;
-        default:
-            break;
-    }
-    VNoBrushScalePathItem::keyReleaseEvent ( event );
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
-    // Special for not selectable item first need to call standard mousePressEvent then accept event
-    VNoBrushScalePathItem::mousePressEvent(event);
-
-    // Somehow clicking on notselectable object do not clean previous selections.
-    if (not (flags() & ItemIsSelectable) && scene())
-    {
-        scene()->clearSelection();
-    }
-
-    if (flags() & QGraphicsItem::ItemIsMovable)
-    {
-        if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
-        {
-            SetOverrideCursor(cursorArrowCloseHand, 1, 1);
-        }
-    }
-
-    if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
-    {
-        doc->SelectedDetail(id);
-        emit ChoosedTool(id, SceneObject::Detail);
-    }
-
-    event->accept();// Special for not selectable item first need to call standard mousePressEvent then accept event
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief mouseReleaseEvent handle mouse release events.
- * @param event mouse release event.
- */
-void VToolDetail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
-{
-    if (event->button() == Qt::LeftButton)
-    {
-        //Disable cursor-arrow-closehand
-        RestoreOverrideCursor(cursorArrowCloseHand);
-    }
-    VNoBrushScalePathItem::mouseReleaseEvent(event);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
-{
-    Q_UNUSED(event)
-    if (flags() & QGraphicsItem::ItemIsMovable)
-    {
-        SetOverrideCursor(cursorArrowOpenHand, 1, 1);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
-{
-    Q_UNUSED(event)
-    if (flags() & QGraphicsItem::ItemIsMovable)
-    {
-        SetOverrideCursor(cursorArrowOpenHand, 1, 1);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
-{
-    Q_UNUSED(event)
-    //Disable cursor-arrow-openhand
-    if (flags() & QGraphicsItem::ItemIsMovable)
-    {
-        RestoreOverrideCursor(cursorArrowOpenHand);
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief contextMenuEvent handle context menu events.
- * @param event context menu event.
- */
-void VToolDetail::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
-{
-    QMenu menu;
-    QAction *actionOption = menu.addAction(QIcon::fromTheme("preferences-other"), tr("Options"));
-
-    QAction *inLayoutOption = menu.addAction(tr("In layout"));
-    inLayoutOption->setCheckable(true);
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    inLayoutOption->setChecked(detail.IsInLayout());
-
-    QAction *actionRemove = menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
-    _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
-
-    QAction *selectedAction = menu.exec(event->screenPos());
-    if (selectedAction == actionOption)
-    {
-//        dialog = new DialogDetail(getData(), id, qApp->getMainWindow());
-//        dialog->setModal(true);
-//        connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
-//                dialog, &DialogTool::ChosenObject);
-//        connect(dialog, &DialogTool::DialogClosed, this, &VToolDetail::FullUpdateFromGuiOk);
-//        setDialog();
-//        dialog->show();
-    }
-    else if (selectedAction == inLayoutOption)
-    {
-        TogglePieceInLayout *togglePrint = new TogglePieceInLayout(id, selectedAction->isChecked(),
-                                                                     &(VAbstractTool::data), doc);
-        connect(togglePrint, &TogglePieceInLayout::UpdateList, doc, &VAbstractPattern::CheckInLayoutList);
-        qApp->getUndoStack()->push(togglePrint);
-    }
-    else if (selectedAction == actionRemove)
-    {
-        try
-        {
-            DeleteTool();
-        }
-        catch(const VExceptionToolWasDeleted &e)
-        {
-            Q_UNUSED(e)
-            return;//Leave this method immediately!!!
-        }
-        return; //Leave this method immediately after call!!!
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UpdateLabel updates the text label, making it just big enough for the text to fit it
- */
-void VToolDetail::UpdateLabel()
-{
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    const VPatternPieceData& data = detail.GetPatternPieceData();
-
-    if (data.IsVisible() == true)
-    {
-        QFont fnt = qApp->font();
-        {
-            const int iFS = data.GetFontSize();
-            iFS < MIN_FONT_SIZE ? fnt.setPixelSize(MIN_FONT_SIZE) : fnt.setPixelSize(iFS);
-        }
-        dataLabel->SetFont(fnt);
-        dataLabel->SetSize(data.GetLabelWidth(), data.GetLabelHeight());
-        dataLabel->UpdateData(detail.getName(), data);
-        QPointF pt = data.GetPos();
-        QRectF rectBB;
-        rectBB.setTopLeft(pt);
-        rectBB.setWidth(dataLabel->boundingRect().width());
-        rectBB.setHeight(dataLabel->boundingRect().height());
-        qreal dX;
-        qreal dY;
-        if (dataLabel->IsContained(rectBB, data.GetRotation(), dX, dY) == false)
-        {
-            pt.setX(pt.x() + dX);
-            pt.setY(pt.y() + dY);
-        }
-
-        dataLabel->setPos(pt);
-        dataLabel->setRotation(data.GetRotation());
-        dataLabel->Update();
-        dataLabel->show();
-    }
-    else
-    {
-        dataLabel->hide();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UpdatePatternInfo updates the pattern info label
- */
-void VToolDetail::UpdatePatternInfo()
-{
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    const VPatternInfoGeometry& geom = detail.GetPatternInfo();
-
-    if (geom.IsVisible() == true)
-    {
-        QFont fnt = qApp->font();
-        int iFS = geom.GetFontSize();
-        if (iFS < MIN_FONT_SIZE)
-        {
-            iFS = MIN_FONT_SIZE;
-        }
-        fnt.setPixelSize(iFS);
-        patternInfo->SetFont(fnt);
-        patternInfo->SetSize(geom.GetLabelWidth(), geom.GetLabelHeight());
-        patternInfo->UpdateData(doc, getData()->size(), getData()->height());
-
-        QPointF pt = geom.GetPos();
-        QRectF rectBB;
-        rectBB.setTopLeft(pt);
-        rectBB.setWidth(patternInfo->boundingRect().width());
-        rectBB.setHeight(patternInfo->boundingRect().height());
-        qreal dX;
-        qreal dY;
-        if (patternInfo->IsContained(rectBB, geom.GetRotation(), dX, dY) == false)
-        {
-            pt.setX(pt.x() + dX);
-            pt.setY(pt.y() + dY);
-        }
-
-        patternInfo->setPos(pt);
-        patternInfo->setRotation(geom.GetRotation());
-        patternInfo->Update();
-        if (patternInfo->GetTextLines() > 0)
-        {
-            patternInfo->show();
-        }
-        else
-        {
-            patternInfo->hide();
-        }
-    }
-    else
-    {
-        patternInfo->hide();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VToolDetail::UpdateGrainline updates the grain line item
- */
-void VToolDetail::UpdateGrainline()
-{
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    const VGrainlineGeometry& geom = detail.GetGrainlineGeometry();
-
-    if (geom.IsVisible() == true)
-    {
-        qreal dRotation;
-        qreal dLength;
-        try
-        {
-            QString qsFormula;
-            qsFormula = geom.GetRotation().replace("\n", " ");
-            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
-
-            Calculator cal1;
-            dRotation = cal1.EvalFormula(VDataTool::data.PlainVariables(), qsFormula);
-
-            qsFormula = geom.GetLength().replace("\n", " ");
-            qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator());
-            Calculator cal2;
-            dLength = cal2.EvalFormula(VDataTool::data.PlainVariables(), qsFormula);
-        }
-        catch(...)
-        {
-            grainLine->hide();
-            return;
-        }
-
-        grainLine->UpdateGeometry(geom.GetPos(), dRotation, ToPixel(dLength, *VDataTool::data.GetPatternUnit()),
-                                  geom.GetArrowType());
-        grainLine->show();
-    }
-    else
-    {
-        grainLine->hide();
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief SaveMoveDetail saves the move detail operation to the undo stack
- */
-void VToolDetail::SaveMoveDetail(const QPointF& ptPos)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternPieceData().SetPos(ptPos);
-    newDet.GetPatternPieceData().SetLabelWidth(dataLabel->boundingRect().width());
-    newDet.GetPatternPieceData().SetLabelHeight(dataLabel->boundingRect().height());
-    newDet.GetPatternPieceData().SetFontSize(dataLabel->GetFontSize());
-    newDet.GetPatternPieceData().SetRotation(dataLabel->rotation());
-
-    SaveDetailOptions* moveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    moveCommand->setText(tr("move pattern piece label"));
-    connect(moveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(moveCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief SaveResizeDetail saves the resize detail label operation to the undo stack
- */
-void VToolDetail::SaveResizeDetail(qreal dLabelW, int iFontSize)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternPieceData().SetLabelWidth(dLabelW);
-    newDet.GetPatternPieceData().SetLabelHeight(dataLabel->boundingRect().height());
-    newDet.GetPatternPieceData().SetFontSize(iFontSize);
-    newDet.GetPatternPieceData().SetRotation(dataLabel->rotation());
-    SaveDetailOptions* resizeCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    resizeCommand->setText(tr("resize pattern piece label"));
-    connect(resizeCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(resizeCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief SaveRotationDetail saves the rotation detail label operation to the undo stack
- */
-void VToolDetail::SaveRotationDetail(qreal dRot)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternPieceData().SetPos(dataLabel->pos());
-    newDet.GetPatternPieceData().SetLabelWidth(dataLabel->boundingRect().width());
-    newDet.GetPatternPieceData().SetLabelHeight(dataLabel->boundingRect().height());
-    newDet.GetPatternPieceData().SetFontSize(dataLabel->GetFontSize());
-    newDet.GetPatternPieceData().SetRotation(dRot);
-
-    SaveDetailOptions* rotateCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    rotateCommand->setText(tr("rotate pattern piece label"));
-    connect(rotateCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(rotateCommand);
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief SaveMovePattern saves the pattern label position
- */
-void VToolDetail::SaveMovePattern(const QPointF &ptPos)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternInfo().SetPos(ptPos);
-    newDet.GetPatternInfo().SetLabelWidth(patternInfo->boundingRect().width());
-    newDet.GetPatternInfo().SetLabelHeight(patternInfo->boundingRect().height());
-    newDet.GetPatternInfo().SetFontSize(patternInfo->GetFontSize());
-    newDet.GetPatternInfo().SetRotation(patternInfo->rotation());
-
-    SaveDetailOptions* moveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    moveCommand->setText(tr("move pattern info label"));
-    connect(moveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(moveCommand);
-
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief: SaveResizePattern saves the pattern label width and font size
- */
-void VToolDetail::SaveResizePattern(qreal dLabelW, int iFontSize)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternInfo().SetLabelWidth(dLabelW);
-    newDet.GetPatternInfo().SetLabelHeight(patternInfo->boundingRect().height());
-    newDet.GetPatternInfo().SetFontSize(iFontSize);
-    newDet.GetPatternInfo().SetRotation(patternInfo->rotation());
-    SaveDetailOptions* resizeCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    resizeCommand->setText(tr("resize pattern info label"));
-    connect(resizeCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(resizeCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::SaveRotationPattern(qreal dRot)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetPatternInfo().SetPos(patternInfo->pos());
-    newDet.GetPatternInfo().SetLabelWidth(patternInfo->boundingRect().width());
-    newDet.GetPatternInfo().SetLabelHeight(patternInfo->boundingRect().height());
-    newDet.GetPatternInfo().SetFontSize(patternInfo->GetFontSize());
-    newDet.GetPatternInfo().SetRotation(dRot);
-
-    SaveDetailOptions* rotateCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    rotateCommand->setText(tr("rotate pattern info label"));
-    connect(rotateCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(rotateCommand);
-}
-
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::SaveMoveGrainline(const QPointF& ptPos)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-    newDet.GetGrainlineGeometry().SetPos(ptPos);
-    qDebug() << "******* new grainline pos" << ptPos;
-
-    SaveDetailOptions* moveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    moveCommand->setText(tr("move grainline"));
-    connect(moveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(moveCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::SaveResizeGrainline(qreal dLength)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-
-    dLength = FromPixel(dLength, *VDataTool::data.GetPatternUnit());
-    newDet.GetGrainlineGeometry().SetLength(qApp->LocaleToString(dLength));
-    SaveDetailOptions* resizeCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    resizeCommand->setText(tr("resize grainline"));
-    connect(resizeCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(resizeCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::SaveRotateGrainline(qreal dRot, const QPointF& ptPos)
-{
-    VDetail oldDet = VAbstractTool::data.GetDetail(id);
-    VDetail newDet = oldDet;
-
-    dRot = qRadiansToDegrees(dRot);
-    newDet.GetGrainlineGeometry().SetRotation(qApp->LocaleToString(dRot));
-    newDet.GetGrainlineGeometry().SetPos(ptPos);
-    SaveDetailOptions* rotateCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene());
-    rotateCommand->setText(tr("rotate grainline"));
-    connect(rotateCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
-    qApp->getUndoStack()->push(rotateCommand);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddNode add node to the file.
- * @param domElement tag in xml tree.
- * @param node node of detail.
- */
-void VToolDetail::AddNode(VAbstractPattern *doc, QDomElement &domElement, const VNodeDetail &node)
-{
-    QDomElement nod = doc->createElement(TagNode);
-
-    doc->SetAttribute(nod, AttrIdObject, node.getId());
-    doc->SetAttribute(nod, AttrMx, qApp->fromPixel(node.getMx()));
-    doc->SetAttribute(nod, AttrMy, qApp->fromPixel(node.getMy()));
-
-    if (node.getTypeTool() != Tool::NodePoint)
-    {
-        doc->SetAttribute(nod, AttrReverse, static_cast<quint8>(node.getReverse()));
-    }
-
-    if (node.getTypeNode() == NodeDetail::Contour)
-    {
-        doc->SetAttribute(nod, AttrNodeType, NodeTypeContour);
-    }
-    else
-    {
-        doc->SetAttribute(nod, AttrNodeType, NodeTypeModeling);
-    }
-    switch (node.getTypeTool())
-    {
-        case (Tool::NodeArc):
-            doc->SetAttribute(nod, AttrType, NodeArc);
-            break;
-        case (Tool::NodeElArc):
-            doc->SetAttribute(nod, AttrType, NodeElArc);
-            break;
-        case (Tool::NodePoint):
-            doc->SetAttribute(nod, AttrType, NodePoint);
-            break;
-        case (Tool::NodeSpline):
-            doc->SetAttribute(nod, AttrType, NodeSpline);
-            break;
-        case (Tool::NodeSplinePath):
-            doc->SetAttribute(nod, AttrType, NodeSplinePath);
-            break;
-        default:
-            qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
-            break;
-    }
-    domElement.appendChild(nod);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QString VToolDetail::getTagName() const
-{
-    return VAbstractPattern::TagDetail;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::ShowVisualization(bool show)
-{
-    Q_UNUSED(show)
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::GroupVisibility(quint32 object, bool visible)
-{
-    Q_UNUSED(object)
-    Q_UNUSED(visible)
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief RefreshGeometry refresh item on scene.
- */
-void VToolDetail::RefreshGeometry()
-{
-    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
-
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    QPainterPath mainPath = detail.ContourPath(this->getData());
-    this->setPath(mainPath);
-    this->setPos(detail.getMx(), detail.getMy());
-
-    if (detail.getSeamAllowance())
-    {
-        mainPath.addPath(detail.SeamAllowancePath(this->getData()));
-        mainPath.setFillRule(Qt::OddEvenFill);
-        seamAllowance->setPath(mainPath);
-    }
-    else
-    {
-        seamAllowance->setPath(QPainterPath());
-    }
-
-    this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::DeleteTool(bool ask)
-{
-    QScopedPointer<DeleteDetail> delDet(new DeleteDetail(doc, id, VAbstractTool::data.GetDetail(id)));
-    if (ask)
-    {
-        if (ConfirmDeletion() == QMessageBox::No)
-        {
-            return;
-        }
-        /* If UnionDetails tool delete detail no need emit FullParsing.*/
-        connect(delDet.data(), &DeleteDetail::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
-    }
-    qApp->getUndoStack()->push(delDet.take());
-
-    // Throw exception, this will help prevent case when we forget to immediately quit function.
-    VExceptionToolWasDeleted e("Tool was used after deleting.");
-    throw e;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-template <typename Tool>
-//cppcheck-suppress unusedFunction
-Tool* VToolDetail::InitTool(VMainGraphicsScene *scene, const VNodeDetail &node)
-{
-    Tool *tool = qobject_cast<Tool*>(doc->getTool(node.getId()));
-    SCASSERT(tool != nullptr)
-    connect(tool, &Tool::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
-    tool->setParentItem(this);
-    tool->SetParentType(ParentType::Item);
-    doc->IncrementReferens(node.getId());
-    return tool;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::EnableToolMove(bool move)
-{
-    setFlag(QGraphicsItem::ItemIsMovable, move);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::AllowHover(bool enabled)
-{
-    setAcceptHoverEvents(enabled);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::AllowSelecting(bool enabled)
-{
-    setFlag(QGraphicsItem::ItemIsSelectable, enabled);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::ResetChildren(QGraphicsItem *pItem)
-{
-    const VDetail detail = VAbstractTool::data.GetDetail(id);
-    VTextGraphicsItem* pVGI = dynamic_cast<VTextGraphicsItem*>(pItem);
-    if (pVGI != dataLabel)
-    {
-        if (detail.GetPatternPieceData().IsVisible())
-        {
-            dataLabel->Reset();
-        }
-    }
-    if (pVGI != patternInfo)
-    {
-        if (detail.GetPatternInfo().IsVisible())
-        {
-            patternInfo->Reset();
-        }
-    }
-    VGrainlineItem* pGLI = dynamic_cast<VGrainlineItem*>(pItem);
-    if (pGLI != grainLine)
-    {
-        if (detail.GetGrainlineGeometry().IsVisible())
-        {
-            grainLine->Reset();
-        }
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::UpdateAll()
-{
-    sceneDetails->update();
-    update();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::retranslateUi()
-{
-    UpdateLabel();
-    UpdatePatternInfo();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VToolDetail::Highlight(quint32 id)
-{
-    setSelected(this->id == id);
-}
diff --git a/src/libs/vtools/tools/vtooldetail.h b/src/libs/vtools/tools/vtooldetail.h
deleted file mode 100644
index d46b144e6..000000000
--- a/src/libs/vtools/tools/vtooldetail.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/************************************************************************
- **
- **  @file   vtooldetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 VTOOLDETAIL_H
-#define VTOOLDETAIL_H
-
-#include <qcompilerdetection.h>
-#include <QObject>
-#include <QtGlobal>
-
-#include "../vwidgets/vnobrushscalepathitem.h"
-#include "vabstracttool.h"
-#include "vtextgraphicsitem.h"
-#include "vgrainlineitem.h"
-
-class VMainGraphicsScene;
-class DialogTool;
-
-/**
- * @brief The VToolDetail class for working with detail.
- */
-class VToolDetail: public VAbstractTool, public VNoBrushScalePathItem
-{
-    Q_OBJECT
-public:
-    ~VToolDetail();
-
-    virtual void       setDialog();
-    template<typename T>
-    /**
-     * @brief CreateNode create new node for detail.
-     * @param data container.
-     * @param id id parent object.
-     * @return id for new object.
-     */
-    static quint32 CreateNode(VContainer *data, const quint32 &id)
-    {
-        //We can't use exist object. Need create new.
-        T *node = new T(*data->GeometricObject<T>(id).data());
-        node->setMode(Draw::Modeling);
-        return data->AddGObject(node);
-    }
-
-    static void        Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data);
-    static void        Create(const quint32 &_id, const VDetail &newDetail, VMainGraphicsScene  *scene,
-                              VAbstractPattern *doc, VContainer *data, const Document &parse,
-                              const Source &typeCreation, const QString &drawName = QString());
-    static const QString TagNode;
-    static const QString AttrSupplement;
-    static const QString AttrClosed;
-    static const QString AttrForbidFlipping;
-    static const QString AttrWidth;
-    static const QString AttrHeight;
-    static const QString AttrNodeType;
-    static const QString AttrReverse;
-    static const QString AttrFont;
-    static const QString AttrRotation;
-    static const QString NodeTypeContour;
-    static const QString NodeTypeModeling;
-    static const QString NodeArc;
-    static const QString NodeElArc;
-    static const QString NodePoint;
-    static const QString NodeSpline;
-    static const QString NodeSplinePath;
-    void               Remove(bool ask);
-    static void        AddNode(VAbstractPattern *doc, QDomElement &domElement, const VNodeDetail &node);
-    virtual int        type() const Q_DECL_OVERRIDE {return Type;}
-    enum { Type = UserType + static_cast<int>(Tool::Detail)};
-    virtual QString    getTagName() const Q_DECL_OVERRIDE;
-    virtual void       ShowVisualization(bool show) Q_DECL_OVERRIDE;
-    virtual void       GroupVisibility(quint32 object, bool visible) Q_DECL_OVERRIDE;
-public slots:
-    virtual void       FullUpdateFromFile () Q_DECL_OVERRIDE;
-    virtual void       FullUpdateFromGuiOk(int result);
-    void               EnableToolMove(bool move);
-    virtual void       AllowHover(bool enabled) Q_DECL_OVERRIDE;
-    virtual void       AllowSelecting(bool enabled) Q_DECL_OVERRIDE;
-    virtual void       ResetChildren(QGraphicsItem* pItem);
-    virtual void       UpdateAll();
-    virtual void       retranslateUi();
-    void               Highlight(quint32 id);
-protected:
-    virtual void       paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-                             QWidget *widget) Q_DECL_OVERRIDE;
-    virtual void       AddToFile () Q_DECL_OVERRIDE;
-    virtual void       RefreshDataInFile() Q_DECL_OVERRIDE;
-    virtual QVariant   itemChange ( GraphicsItemChange change, const QVariant &value ) Q_DECL_OVERRIDE;
-    virtual void       mousePressEvent( QGraphicsSceneMouseEvent * event) Q_DECL_OVERRIDE;
-    virtual void       mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE;
-    virtual void       hoverMoveEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
-    virtual void       hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
-    virtual void       hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE;
-    virtual void       contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE;
-    virtual void       keyReleaseEvent(QKeyEvent * event) Q_DECL_OVERRIDE;
-    virtual void       SetVisualization() Q_DECL_OVERRIDE {}
-
-protected slots:
-    virtual void       UpdateLabel();
-    virtual void       UpdatePatternInfo();
-    virtual void       UpdateGrainline();
-    virtual void       SaveMoveDetail(const QPointF &ptPos);
-    virtual void       SaveResizeDetail(qreal dLabelW, int iFontSize);
-    virtual void       SaveRotationDetail(qreal dRot);
-    virtual void       SaveMovePattern(const QPointF& ptPos);
-    virtual void       SaveResizePattern(qreal dLabelW, int iFontSize);
-    virtual void       SaveRotationPattern(qreal dRot);
-    virtual void       SaveMoveGrainline(const QPointF& ptPos);
-    virtual void       SaveResizeGrainline(qreal dLength);
-    virtual void       SaveRotateGrainline(qreal dRot, const QPointF& ptPos);
-
-private:
-    Q_DISABLE_COPY(VToolDetail)
-    /** @brief dialog dialog options. */
-    DialogTool                  *dialog;
-
-    /** @brief sceneDetails pointer to the scene. */
-    VMainGraphicsScene          *sceneDetails;
-    QString                      drawName;
-
-    VNoBrushScalePathItem       *seamAllowance;
-    VTextGraphicsItem           *dataLabel;
-    VTextGraphicsItem           *patternInfo;
-    VGrainlineItem              *grainLine;
-
-    VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation,
-                VMainGraphicsScene *scene, const QString &drawName, QGraphicsItem * parent = nullptr);
-
-    void               RefreshGeometry ();
-    template <typename Tool>
-    /**
-     * @brief InitTool initial node item on scene
-     * @param scene pointer to scene.
-     * @param node node of detail.
-     */
-    Tool*              InitTool(VMainGraphicsScene *scene, const VNodeDetail &node);
-    virtual void       DeleteTool(bool ask = true) Q_DECL_OVERRIDE;
-};
-
-#endif // VTOOLDETAIL_H
diff --git a/src/libs/vtools/undocommands/adddet.cpp b/src/libs/vtools/undocommands/adddet.cpp
deleted file mode 100644
index c2b9d4efe..000000000
--- a/src/libs/vtools/undocommands/adddet.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/************************************************************************
- **
- **  @file   adddet.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   15 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "adddet.h"
-
-#include <QByteArray>
-#include <QDomNode>
-
-#include "../ifc/xml/vabstractpattern.h"
-#include "../vmisc/logging.h"
-#include "vundocommand.h"
-
-class QDomElement;
-class QUndoCommand;
-
-//---------------------------------------------------------------------------------------------------------------------
-AddDet::AddDet(const QDomElement &xml, VAbstractPattern *doc, const VDetail &detail, const QString &drawName,
-               QUndoCommand *parent)
-    : VUndoCommand(xml, doc, parent), detail(detail), drawName(drawName)
-{
-    setText(tr("add detail"));
-    nodeId = doc->GetParametrId(xml);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-AddDet::~AddDet()
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-// cppcheck-suppress unusedFunction
-void AddDet::undo()
-{
-    qCDebug(vUndo, "Undo.");
-
-    QDomElement details = GetDetailsSection();
-    if (not details.isNull())
-    {
-        QDomElement domElement = doc->elementById(nodeId);
-        if (domElement.isElement())
-        {
-            if (details.removeChild(domElement).isNull())
-            {
-                qCDebug(vUndo, "Can't delete node");
-                return;
-            }
-
-            DecrementReferences(detail.getNodes());
-        }
-        else
-        {
-            qCDebug(vUndo, "Can't get node by id = %u.", nodeId);
-            return;
-        }
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagDetails));
-        return;
-    }
-    emit NeedFullParsing();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-// cppcheck-suppress unusedFunction
-void AddDet::redo()
-{
-    qCDebug(vUndo, "Redo.");
-
-    QDomElement details = GetDetailsSection();
-    if (not details.isNull())
-    {
-        details.appendChild(xml);
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagDetails));
-        return;
-    }
-    RedoFullParsing();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QDomElement AddDet::GetDetailsSection() const
-{
-    QDomElement details;
-    if (drawName.isEmpty())
-    {
-        doc->GetActivNodeElement(VAbstractPattern::TagDetails, details);
-    }
-    else
-    {
-        details = doc->GetDraw(drawName).firstChildElement(VAbstractPattern::TagDetails);
-    }
-    return details;
-}
diff --git a/src/libs/vtools/undocommands/adddet.h b/src/libs/vtools/undocommands/adddet.h
deleted file mode 100644
index a6583cf6e..000000000
--- a/src/libs/vtools/undocommands/adddet.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/************************************************************************
- **
- **  @file   adddet.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   15 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 ADDDET_H
-#define ADDDET_H
-
-#include <qcompilerdetection.h>
-#include <QDomElement>
-#include <QMetaObject>
-#include <QObject>
-#include <QString>
-#include <QtGlobal>
-
-#include "../tools/vtooldetail.h"
-#include "vdetail.h"
-#include "vundocommand.h"
-
-class QDomElement;
-class QUndoCommand;
-class VAbstractPattern;
-
-class AddDet : public VUndoCommand
-{
-    Q_OBJECT
-public:
-    AddDet(const QDomElement &xml, VAbstractPattern *doc, const VDetail &detail, const QString &drawName = QString(),
-           QUndoCommand *parent = 0);
-    virtual ~AddDet() Q_DECL_OVERRIDE;
-    // cppcheck-suppress unusedFunction
-    virtual void undo() Q_DECL_OVERRIDE;
-    // cppcheck-suppress unusedFunction
-    virtual void redo() Q_DECL_OVERRIDE;
-private:
-    Q_DISABLE_COPY(AddDet)
-    VDetail detail;
-    QString drawName;
-
-    QDomElement GetDetailsSection() const;
-};
-
-#endif // ADDDET_H
diff --git a/src/libs/vtools/undocommands/deletedetail.cpp b/src/libs/vtools/undocommands/deletedetail.cpp
deleted file mode 100644
index b663df944..000000000
--- a/src/libs/vtools/undocommands/deletedetail.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/************************************************************************
- **
- **  @file   deletedetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   16 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "deletedetail.h"
-
-#include <QDomElement>
-#include <QHash>
-
-#include "../tools/vtooldetail.h"
-#include "../ifc/ifcdef.h"
-#include "../ifc/xml/vabstractpattern.h"
-#include "../ifc/xml/vdomdocument.h"
-#include "../vmisc/logging.h"
-#include "../vmisc/def.h"
-#include "../tools/vdatatool.h"
-#include "vundocommand.h"
-
-class QUndoCommand;
-
-//---------------------------------------------------------------------------------------------------------------------
-DeleteDetail::DeleteDetail(VAbstractPattern *doc, quint32 id, const VDetail &detail, QUndoCommand *parent)
-    : VUndoCommand(QDomElement(), doc, parent), parentNode(QDomNode()), siblingId(NULL_ID), detail(detail)
-{
-    setText(tr("delete tool"));
-    nodeId = id;
-    QDomElement domElement = doc->elementById(id);
-    if (domElement.isElement())
-    {
-        xml = domElement.cloneNode().toElement();
-        parentNode = domElement.parentNode();
-        QDomNode previousDetail = domElement.previousSibling();
-        if (previousDetail.isNull())
-        {
-            siblingId = NULL_ID;
-        }
-        else
-        {
-            // Better save id of previous detail instead of reference to node.
-            siblingId = doc->GetParametrUInt(previousDetail.toElement(), VAbstractPattern::AttrId, NULL_ID_STR);
-        }
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't get detail by id = %u.", nodeId);
-        return;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-DeleteDetail::~DeleteDetail()
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DeleteDetail::undo()
-{
-    qCDebug(vUndo, "Undo.");
-
-    UndoDeleteAfterSibling(parentNode, siblingId);
-    emit NeedFullParsing();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void DeleteDetail::redo()
-{
-    qCDebug(vUndo, "Redo.");
-
-    QDomElement domElement = doc->elementById(nodeId);
-    if (domElement.isElement())
-    {
-        parentNode.removeChild(domElement);
-
-        // UnionDetails delete two old details and create one new.
-        // So when UnionDetail delete detail we can't use FullParsing. So we hide detail on scene directly.
-        VToolDetail *toolDet = qobject_cast<VToolDetail*>(doc->getTool(nodeId));
-        SCASSERT(toolDet != nullptr)
-        toolDet->hide();
-
-        DecrementReferences(detail.getNodes());
-        emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't get detail by id = %u.", nodeId);
-        return;
-    }
-}
diff --git a/src/libs/vtools/undocommands/deletedetail.h b/src/libs/vtools/undocommands/deletedetail.h
deleted file mode 100644
index abbe30b7e..000000000
--- a/src/libs/vtools/undocommands/deletedetail.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/************************************************************************
- **
- **  @file   deletedetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   16 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 DELETEDETAIL_H
-#define DELETEDETAIL_H
-
-#include <qcompilerdetection.h>
-#include <QDomNode>
-#include <QMetaObject>
-#include <QObject>
-#include <QString>
-#include <QtGlobal>
-
-#include "../tools/vtooldetail.h"
-#include "vdetail.h"
-#include "vundocommand.h"
-
-class QGraphicsItem;
-class QUndoCommand;
-class VAbstractPattern;
-
-class DeleteDetail : public VUndoCommand
-{
-    Q_OBJECT
-public:
-    DeleteDetail(VAbstractPattern *doc, quint32 id, const VDetail &detail, QUndoCommand *parent = 0);
-    virtual ~DeleteDetail() Q_DECL_OVERRIDE;
-    virtual void undo() Q_DECL_OVERRIDE;
-    virtual void redo() Q_DECL_OVERRIDE;
-private:
-    Q_DISABLE_COPY(DeleteDetail)
-    QDomNode parentNode;
-    quint32 siblingId;
-    VDetail detail;
-};
-
-#endif // DELETEDETAIL_H
diff --git a/src/libs/vtools/undocommands/savedetailoptions.cpp b/src/libs/vtools/undocommands/savedetailoptions.cpp
deleted file mode 100644
index fa8ae38e9..000000000
--- a/src/libs/vtools/undocommands/savedetailoptions.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/************************************************************************
- **
- **  @file   savedetailoptions.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   12 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "savedetailoptions.h"
-
-#include <QDomElement>
-#include <QPointF>
-#include <QUndoCommand>
-#include <QDebug>
-
-#include "../ifc/xml/vabstractpattern.h"
-#include "../ifc/ifcdef.h"
-#include "../vmisc/logging.h"
-#include "../vmisc/def.h"
-#include "../vpatterndb/vpatterninfogeometry.h"
-#include "../vpatterndb/vpatternpiecedata.h"
-#include "../vpatterndb/vgrainlinegeometry.h"
-#include "../tools/vtooldetail.h"
-#include "vundocommand.h"
-
-class QDomElement;
-class QUndoCommand;
-
-//---------------------------------------------------------------------------------------------------------------------
-SaveDetailOptions::SaveDetailOptions(const VDetail &oldDet, const VDetail &newDet, VAbstractPattern *doc,
-                                     const quint32 &id, QGraphicsScene *scene, QUndoCommand *parent)
-    : VUndoCommand(QDomElement(), doc, parent), oldDet(oldDet), newDet(newDet), scene(scene)
-{
-    setText(tr("save detail option"));
-    nodeId = id;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-SaveDetailOptions::~SaveDetailOptions()
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::undo()
-{
-    qCDebug(vUndo, "Undo.");
-
-    QDomElement domElement = doc->elementById(nodeId);
-    if (domElement.isElement())
-    {
-        SaveDet(domElement, oldDet);
-        doc->RemoveAllChildren(domElement);
-        SavePatternPieceData(domElement, oldDet);
-        SavePatternInfo(domElement, oldDet);
-        SaveGrainline(domElement, oldDet);
-
-        for (int i = 0; i < oldDet.CountNode(); ++i)
-        {
-           VToolDetail::AddNode(doc, domElement, oldDet.at(i));
-        }
-        IncrementReferences(oldDet.Missing(newDet));
-        emit NeedLiteParsing(Document::LiteParse);
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't find detail with id = %u.", nodeId);
-        return;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::redo()
-{
-    qCDebug(vUndo, "Redo.");
-
-    QDomElement domElement = doc->elementById(nodeId);
-    if (domElement.isElement())
-    {
-        SaveDet(domElement, newDet);
-        doc->RemoveAllChildren(domElement);
-        SavePatternPieceData(domElement, newDet);
-        SavePatternInfo(domElement, newDet);
-        SaveGrainline(domElement, newDet);
-
-        for (int i = 0; i < newDet.CountNode(); ++i)
-        {
-           VToolDetail::AddNode(doc, domElement, newDet.at(i));
-        }
-
-        DecrementReferences(oldDet.Missing(newDet));
-        emit NeedLiteParsing(Document::LiteParse);
-    }
-    else
-    {
-        qCDebug(vUndo, "Can't find detail with id = %u.", nodeId);
-        return;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool SaveDetailOptions::mergeWith(const QUndoCommand *command)
-{
-    const SaveDetailOptions *saveCommand = static_cast<const SaveDetailOptions *>(command);
-    SCASSERT(saveCommand != nullptr)
-    const quint32 id = saveCommand->getDetId();
-
-    if (id != nodeId || text() != command->text())
-    {
-        return false;
-    }
-
-    newDet = saveCommand->getNewDet();
-    return true;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-int SaveDetailOptions::id() const
-{
-    return static_cast<int>(UndoCommand::SaveDetailOptions);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::SaveDet(QDomElement &domElement, const VDetail &det)
-{
-    doc->SetAttribute(domElement, AttrName, det.getName());
-    doc->SetAttribute(domElement, VToolDetail::AttrSupplement, QString().setNum(det.getSeamAllowance()));
-    doc->SetAttribute(domElement, VToolDetail::AttrClosed, QString().setNum(det.getClosed()));
-    doc->SetAttribute(domElement, VToolDetail::AttrWidth, QString().setNum(det.getWidth()));
-    doc->SetAttribute(domElement, VToolDetail::AttrForbidFlipping, QString().setNum(det.getForbidFlipping()));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::SavePatternPieceData(QDomElement &domElement, const VDetail &det)
-{
-    QDomElement domData = doc->createElement(VAbstractPattern::TagData);
-    const VPatternPieceData& data = det.GetPatternPieceData();
-    doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter());
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, data.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, data.GetPos().y());
-    doc->SetAttribute(domData, VToolDetail::AttrWidth, data.GetLabelWidth());
-    doc->SetAttribute(domData, VToolDetail::AttrHeight, data.GetLabelHeight());
-    doc->SetAttribute(domData, VToolDetail::AttrFont, data.GetFontSize());
-    doc->SetAttribute(domData, VToolDetail::AttrRotation, data.GetRotation());
-
-    for (int i = 0; i < data.GetMCPCount(); ++i)
-    {
-        MaterialCutPlacement mcp = data.GetMCP(i);
-        QDomElement domMCP = doc->createElement(VAbstractPattern::TagMCP);
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrMaterial, int(mcp.m_eMaterial));
-        if (mcp.m_eMaterial == MaterialType::mtUserDefined)
-        {
-            qDebug() << "USER DEFINED MATERIAL";
-            doc->SetAttribute(domMCP, VAbstractPattern::AttrUserDefined, mcp.m_qsMaterialUserDef);
-        }
-        else
-        {
-            qDebug() << "PREDEFINED MATERIAL";
-            domMCP.removeAttribute(VAbstractPattern::AttrUserDefined);
-        }
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrCutNumber, mcp.m_iCutNumber);
-        doc->SetAttribute(domMCP, VAbstractPattern::AttrPlacement, int(mcp.m_ePlacement));
-        domData.appendChild(domMCP);
-    }
-    domElement.appendChild(domData);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::SavePatternInfo(QDomElement &domElement, const VDetail &det)
-{
-    QDomElement domData = doc->createElement(VAbstractPattern::TagPatternInfo);
-    const VPatternInfoGeometry& data = det.GetPatternInfo();
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, data.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, data.GetPos().y());
-    doc->SetAttribute(domData, VToolDetail::AttrWidth, data.GetLabelWidth());
-    doc->SetAttribute(domData, VToolDetail::AttrHeight, data.GetLabelHeight());
-    doc->SetAttribute(domData, VToolDetail::AttrFont, data.GetFontSize());
-    doc->SetAttribute(domData, VToolDetail::AttrRotation, data.GetRotation());
-
-    domElement.appendChild(domData);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void SaveDetailOptions::SaveGrainline(QDomElement &domElement, const VDetail &det)
-{
-    QDomElement domData = doc->createElement(VAbstractPattern::TagGrainline);
-    const VGrainlineGeometry& glGeom = det.GetGrainlineGeometry();
-    doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr);
-    doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x());
-    doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y());
-    doc->SetAttribute(domData, AttrLength, glGeom.GetLength());
-    doc->SetAttribute(domData, VToolDetail::AttrRotation, glGeom.GetRotation());
-    doc->SetAttribute(domData, VAbstractPattern::AttrArrows, int(glGeom.GetArrowType()));
-
-    domElement.appendChild(domData);
-}
diff --git a/src/libs/vtools/undocommands/savedetailoptions.h b/src/libs/vtools/undocommands/savedetailoptions.h
deleted file mode 100644
index 5b4cbc058..000000000
--- a/src/libs/vtools/undocommands/savedetailoptions.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/************************************************************************
- **
- **  @file   savedetailoptions.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   12 6, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 SAVEDETAILOPTIONS_H
-#define SAVEDETAILOPTIONS_H
-
-#include <qcompilerdetection.h>
-#include <QMetaObject>
-#include <QObject>
-#include <QString>
-#include <QtGlobal>
-
-#include "../tools/vtooldetail.h"
-#include "vdetail.h"
-#include "vundocommand.h"
-
-class QDomElement;
-class QGraphicsScene;
-class QUndoCommand;
-class VAbstractPattern;
-
-class SaveDetailOptions : public VUndoCommand
-{
-    Q_OBJECT
-public:
-    SaveDetailOptions(const VDetail &oldDet, const VDetail &newDet, VAbstractPattern *doc, const quint32 &id,
-                      QGraphicsScene *scene, QUndoCommand *parent = 0);
-    virtual ~SaveDetailOptions() Q_DECL_OVERRIDE;
-    virtual void undo() Q_DECL_OVERRIDE;
-    virtual void redo() Q_DECL_OVERRIDE;
-    virtual bool mergeWith(const QUndoCommand *command) Q_DECL_OVERRIDE;
-    virtual int  id() const Q_DECL_OVERRIDE;
-    quint32      getDetId() const;
-    VDetail      getNewDet() const;
-private:
-    Q_DISABLE_COPY(SaveDetailOptions)
-    const VDetail oldDet;
-    VDetail       newDet;
-    QGraphicsScene *scene;
-    void         SaveDet(QDomElement &domElement, const VDetail &det);
-    void         SavePatternPieceData(QDomElement &domElement, const VDetail &det);
-    void         SavePatternInfo(QDomElement &domElement, const VDetail &det);
-    void         SaveGrainline(QDomElement &domElement, const VDetail &det);
-};
-
-//---------------------------------------------------------------------------------------------------------------------
-inline quint32 SaveDetailOptions::getDetId() const
-{
-    return nodeId;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-inline VDetail SaveDetailOptions::getNewDet() const
-{
-    return newDet;
-}
-
-#endif // SAVEDETAILOPTIONS_H
diff --git a/src/libs/vtools/undocommands/undocommands.pri b/src/libs/vtools/undocommands/undocommands.pri
index a682f0e26..b77b22ae9 100644
--- a/src/libs/vtools/undocommands/undocommands.pri
+++ b/src/libs/vtools/undocommands/undocommands.pri
@@ -8,12 +8,9 @@ HEADERS += \
     $$PWD/movespline.h \
     $$PWD/movesplinepath.h \
     $$PWD/savetooloptions.h \
-    $$PWD/savedetailoptions.h \
     $$PWD/deltool.h \
     $$PWD/deletepatternpiece.h \
     $$PWD/adddetnode.h \
-    $$PWD/adddet.h \
-    $$PWD/deletedetail.h \
     $$PWD/vundocommand.h \
     $$PWD/renamepp.h \
     $$PWD/label/movelabel.h \
@@ -36,12 +33,9 @@ SOURCES += \
     $$PWD/movespline.cpp \
     $$PWD/movesplinepath.cpp \
     $$PWD/savetooloptions.cpp \
-    $$PWD/savedetailoptions.cpp \
     $$PWD/deltool.cpp \
     $$PWD/deletepatternpiece.cpp \
     $$PWD/adddetnode.cpp \
-    $$PWD/adddet.cpp \
-    $$PWD/deletedetail.cpp \
     $$PWD/vundocommand.cpp \
     $$PWD/renamepp.cpp \
     $$PWD/label/movelabel.cpp \

From ef9411cf5a5791bfc24e0f742133f5cff540ce62 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 16:37:37 +0200
Subject: [PATCH 181/208] Actually we check measurements in two palces. Forgot
 about this.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp | 48 ++++++++++++++------------------
 src/app/valentina/mainwindow.h   |  1 +
 2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index e15949234..9ed9b9aba 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -400,19 +400,7 @@ QSharedPointer<VMeasurements> MainWindow::OpenMeasurementFile(const QString &pat
             throw e;
         }
 
-        const QSet<QString> match = doc->ListMeasurements().toSet().subtract(m->ListAll().toSet());
-        if (not match.isEmpty())
-        {
-            QList<QString> list = match.toList();
-            for (int i = 0; i < list.size(); ++i)
-            {
-                list[i] = qApp->TrVars()->MToUser(list.at(i));
-            }
-
-            VException e(tr("Measurement file doesn't include all required measurements."));
-            e.AddMoreInformation(tr("Please, additionaly provide: %1").arg(QStringList(list).join(", ")));
-            throw e;
-        }
+        CheckRequiredMeasurements(m.data());
 
         if (m->Type() == MeasurementsType::Standard)
         {
@@ -529,6 +517,24 @@ bool MainWindow::UpdateMeasurements(const QString &path, int size, int height)
     return true;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::CheckRequiredMeasurements(const VMeasurements *m)
+{
+    const QSet<QString> match = doc->ListMeasurements().toSet().subtract(m->ListAll().toSet());
+    if (not match.isEmpty())
+    {
+        QList<QString> list = match.toList();
+        for (int i = 0; i < list.size(); ++i)
+        {
+            list[i] = qApp->TrVars()->MToUser(list.at(i));
+        }
+
+        VException e(tr("Measurement file doesn't include all required measurements."));
+        e.AddMoreInformation(tr("Please, additionaly provide: %1").arg(QStringList(list).join(", ")));
+        throw e;
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief SetToolButton set tool and show dialog.
@@ -4279,7 +4285,7 @@ QString MainWindow::CheckPathToMeasurements(const QString &patternPath, const QS
                 }
                 else
                 {
-                    VMeasurements *m = new VMeasurements(pattern);
+                    QScopedPointer<VMeasurements> m(new VMeasurements(pattern));
                     m->setXMLContent(mPath);
 
                     patternType = m->Type();
@@ -4313,19 +4319,7 @@ QString MainWindow::CheckPathToMeasurements(const QString &patternPath, const QS
                         throw e;
                     }
 
-                    const QStringList mList = m->ListAll();
-                    const QStringList pList = doc->ListMeasurements();
-
-                    delete m;
-
-                    const QSet<QString> match = pList.toSet().subtract(mList.toSet());
-                    if (not match.isEmpty())
-                    {
-                        VException e(tr("Measurement file doesn't include all required measurements."));
-                        e.AddMoreInformation(tr("Please, additionaly provide: %1")
-                                             .arg(QStringList(match.toList()).join(", ")));
-                        throw e;
-                    }
+                    CheckRequiredMeasurements(m.data());
 
                     doc->SetPath(RelativeMPath(patternPath, mPath));
                     PatternChangesWereSaved(false);
diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h
index 7b6277533..61e5999f1 100644
--- a/src/app/valentina/mainwindow.h
+++ b/src/app/valentina/mainwindow.h
@@ -339,6 +339,7 @@ private:
     QSharedPointer<VMeasurements> OpenMeasurementFile(const QString &path);
     bool               LoadMeasurements(const QString &path);
     bool               UpdateMeasurements(const QString &path, int size, int height);
+    void               CheckRequiredMeasurements(const VMeasurements *m);
 
     void               ReopenFilesAfterCrash(QStringList &args);
     void               DoExport(const VCommandLinePtr& expParams);

From 8b1e9e24d4677f652bd3eca63ac59c00781fd96c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 17:32:08 +0200
Subject: [PATCH 182/208] Tool path and piece now bring formulas, should cover
 this fact.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp           |  30 ++---
 src/app/valentina/xml/vpattern.h             |   1 -
 src/libs/ifc/xml/vabstractpattern.cpp        | 128 +++++++++++++++++++
 src/libs/ifc/xml/vabstractpattern.h          |   7 +
 src/libs/vtools/tools/vtoolseamallowance.cpp |  14 +-
 src/libs/vtools/tools/vtoolseamallowance.h   |   2 -
 6 files changed, 149 insertions(+), 33 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 3b2855a4e..f3c77d225 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -706,7 +706,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
         detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
         detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
 
-        const QString width = GetParametrString(domElement, VToolSeamAllowance::AttrWidth, "0.0");
+        const QString width = GetParametrString(domElement, AttrWidth, "0.0");
         QString w = width;//need for saving fixed formula;
         const uint version = GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
 
@@ -762,7 +762,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
         //Rewrite attribute formula. Need for situation when we have wrong formula.
         if (w != width)
         {
-            SetAttribute(domElement, VToolSeamAllowance::AttrWidth, w);
+            SetAttribute(domElement, AttrWidth, w);
             modified = true;
             haveLiteChange();
         }
@@ -811,13 +811,13 @@ void VPattern::ParsePieceDataTag(const QDomElement &domElement, VPiece &detail)
     ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
     ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
     detail.GetPatternPieceData().SetPos(ptPos);
-    qreal dLW = GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0");
+    qreal dLW = GetParametrDouble(domElement, AttrWidth, "0");
     detail.GetPatternPieceData().SetLabelWidth(dLW);
     qreal dLH = GetParametrDouble(domElement, VToolSeamAllowance::AttrHeight, "0");
     detail.GetPatternPieceData().SetLabelHeight(dLH);
     int iFS = static_cast<int>(GetParametrUInt(domElement, VToolSeamAllowance::AttrFont, "0"));
     detail.GetPatternPieceData().SetFontSize(iFS);
-    qreal dRot = GetParametrDouble(domElement, VToolSeamAllowance::AttrRotation, "0");
+    qreal dRot = GetParametrDouble(domElement, AttrRotation, "0");
     detail.GetPatternPieceData().SetRotation(dRot);
 
     QDomNodeList nodeListMCP = domElement.childNodes();
@@ -844,13 +844,13 @@ void VPattern::ParsePiecePatternInfo(const QDomElement &domElement, VPiece &deta
     ptPos.setX(GetParametrDouble(domElement, AttrMx, "0"));
     ptPos.setY(GetParametrDouble(domElement, AttrMy, "0"));
     detail.GetPatternInfo().SetPos(ptPos);
-    qreal dLW = GetParametrDouble(domElement, VToolSeamAllowance::AttrWidth, "0");
+    qreal dLW = GetParametrDouble(domElement, AttrWidth, "0");
     detail.GetPatternInfo().SetLabelWidth(dLW);
     qreal dLH = GetParametrDouble(domElement, VToolSeamAllowance::AttrHeight, "0");
     detail.GetPatternInfo().SetLabelHeight(dLH);
     int iFS = static_cast<int>(GetParametrUInt(domElement, VToolSeamAllowance::AttrFont, "0"));
     detail.GetPatternInfo().SetFontSize(iFS);
-    qreal dRot = GetParametrDouble(domElement, VToolSeamAllowance::AttrRotation, "0");
+    qreal dRot = GetParametrDouble(domElement, AttrRotation, "0");
     detail.GetPatternInfo().SetRotation(dRot);
 }
 
@@ -864,7 +864,7 @@ void VPattern::ParsePieceGrainline(const QDomElement &domElement, VPiece &detail
     detail.GetGrainlineGeometry().SetPos(ptPos);
     QString qsLength = GetParametrString(domElement, AttrLength, "0");
     detail.GetGrainlineGeometry().SetLength(qsLength);
-    QString qsRot = GetParametrString(domElement, VToolSeamAllowance::AttrRotation, "90");
+    QString qsRot = GetParametrString(domElement, AttrRotation, "90");
     detail.GetGrainlineGeometry().SetRotation(qsRot);
     VGrainlineGeometry::ArrowType eAT =
             VGrainlineGeometry::ArrowType(GetParametrUInt(domElement, AttrArrows, "0"));
@@ -3205,7 +3205,7 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
         const QDomElement element = domElement.firstChildElement(VAbstractPattern::TagNodes);
         if (not element.isNull())
         {
-            ParsePathNodes(element, path);
+            path = ParsePathNodes(element);
         }
 
         path.SetType(type);
@@ -3222,20 +3222,6 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParsePathNodes(const QDomElement &domElement, VPiecePath &path) const
-{
-    const QDomNodeList nodeList = domElement.childNodes();
-    for (qint32 i = 0; i < nodeList.size(); ++i)
-    {
-        const QDomElement element = nodeList.at(i).toElement();
-        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
-        {
-            path.Append(ParseSANode(element));
-        }
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief ParseIncrementsElement parse increments tag.
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 19a3010a7..b70f4af87 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -141,7 +141,6 @@ private:
                                          const QString& type);
 
     void           ParsePathElement(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse);
-    void           ParsePathNodes(const QDomElement &domElement, VPiecePath &path) const;
 
     void           ParseIncrementsElement(const QDomNode& node);
     void           PrepareForParse(const Document &parse);
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index c344bc12e..122428173 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -113,6 +113,8 @@ const QString VAbstractPattern::AttrStart           = QStringLiteral("start");
 const QString VAbstractPattern::AttrPath            = QStringLiteral("path");
 const QString VAbstractPattern::AttrEnd             = QStringLiteral("end");
 const QString VAbstractPattern::AttrIncludeAs       = QStringLiteral("includeAs");
+const QString VAbstractPattern::AttrWidth           = QStringLiteral("width");
+const QString VAbstractPattern::AttrRotation        = QStringLiteral("rotation");
 
 const QString VAbstractPattern::AttrAll             = QStringLiteral("all");
 
@@ -1402,6 +1404,22 @@ void VAbstractPattern::ToolExists(const quint32 &id)
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+VPiecePath VAbstractPattern::ParsePathNodes(const QDomElement &domElement)
+{
+    VPiecePath path;
+    const QDomNodeList nodeList = domElement.childNodes();
+    for (qint32 i = 0; i < nodeList.size(); ++i)
+    {
+        const QDomElement element = nodeList.at(i).toElement();
+        if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
+        {
+            path.Append(ParseSANode(element));
+        }
+    }
+    return path;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief SetActivPP set current pattern piece.
@@ -1550,12 +1568,16 @@ QStringList VAbstractPattern::ListExpressions() const
     QStringList list;
 
     // If new tool bring absolutely new type and has formula(s) create new method to cover it.
+    // Note. Tool Union Details also contains formulas, but we don't use them for union and keep only to simplifying
+    // working with nodes. Same code for saving reading.
     list << ListPointExpressions();
     list << ListArcExpressions();
     list << ListElArcExpressions();
     list << ListSplineExpressions();
     list << ListIncrementExpressions();
     list << ListOperationExpressions();
+    list << ListPathExpressions();
+    list << ListPieceExpressions();
 
     return list;
 }
@@ -1861,6 +1883,112 @@ QStringList VAbstractPattern::ListOperationExpressions() const
     return expressions;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QStringList VAbstractPattern::ListNodesExpressions(const QDomElement &nodes) const
+{
+    QStringList expressions;
+    VPiecePath path;
+    if (not nodes.isNull())
+    {
+        path = ParsePathNodes(nodes);
+    }
+
+    for(int i = 0; i < path.CountNodes(); ++i)
+    {
+        expressions.append(path.at(i).GetFormulaSABefore());
+        expressions.append(path.at(i).GetFormulaSAAfter());
+    }
+    return expressions;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QStringList VAbstractPattern::ListPathExpressions() const
+{
+    // Check if new tool doesn't bring new attribute with a formula.
+    // If no just increment number.
+    // If new tool bring absolutely new type and has formula(s) create new method to cover it.
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
+
+    QStringList expressions;
+    const QDomNodeList list = elementsByTagName(TagPath);
+    for (int i=0; i < list.size(); ++i)
+    {
+        const QDomElement dom = list.at(i).toElement();
+        if (dom.isNull())
+        {
+            continue;
+        }
+
+        expressions << ListNodesExpressions(dom.firstChildElement(TagNodes));
+    }
+
+    return expressions;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QStringList VAbstractPattern::ListGrainlineExpressions(const QDomElement &element) const
+{
+    QStringList expressions;
+    if (not element.isNull())
+    {
+        // Each tag can contains several attributes.
+        try
+        {
+            expressions.append(GetParametrString(element, AttrRotation));
+        }
+        catch (VExceptionEmptyParameter &e)
+        {
+            Q_UNUSED(e)
+        }
+
+        try
+        {
+            expressions.append(GetParametrString(element, AttrLength));
+        }
+        catch (VExceptionEmptyParameter &e)
+        {
+            Q_UNUSED(e)
+        }
+    }
+
+    return expressions;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QStringList VAbstractPattern::ListPieceExpressions() const
+{
+    // Check if new tool doesn't bring new attribute with a formula.
+    // If no just increment number.
+    // If new tool bring absolutely new type and has formula(s) create new method to cover it.
+    Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 51);
+
+    QStringList expressions;
+    const QDomNodeList list = elementsByTagName(TagDetail);
+    for (int i=0; i < list.size(); ++i)
+    {
+        const QDomElement dom = list.at(i).toElement();
+        if (dom.isNull())
+        {
+            continue;
+        }
+
+        // Each tag can contains several attributes.
+        try
+        {
+            expressions.append(GetParametrString(dom, AttrWidth));
+        }
+        catch (VExceptionEmptyParameter &e)
+        {
+            Q_UNUSED(e)
+        }
+
+        expressions << ListNodesExpressions(dom.firstChildElement(TagNodes));
+        expressions << ListGrainlineExpressions(dom.firstChildElement(TagGrainline));
+    }
+
+    return expressions;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool VAbstractPattern::IsVariable(const QString &token) const
 {
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index e0237101d..2e590c9a1 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -222,6 +222,8 @@ public:
     static const QString AttrPath;
     static const QString AttrEnd;
     static const QString AttrIncludeAs;
+    static const QString AttrWidth;
+    static const QString AttrRotation;
 
     static const QString AttrAll;
 
@@ -356,6 +358,7 @@ protected:
     static QHash<quint32, VDataTool*> tools;
 
     static void       ToolExists(const quint32 &id);
+    static VPiecePath ParsePathNodes(const QDomElement &domElement);
     static VPieceNode ParseSANode(const QDomElement &domElement);
 
     void           SetActivPP(const QString& name);
@@ -379,6 +382,10 @@ private:
     QStringList ListPathPointExpressions() const;
     QStringList ListIncrementExpressions() const;
     QStringList ListOperationExpressions() const;
+    QStringList ListNodesExpressions(const QDomElement &nodes) const;
+    QStringList ListPathExpressions() const;
+    QStringList ListGrainlineExpressions(const QDomElement &element) const;
+    QStringList ListPieceExpressions() const;
 
     bool IsVariable(const QString& token) const;
     bool IsPostfixOperator(const QString& token) const;
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index 35382ced9..7a13ae281 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -71,11 +71,9 @@ const QString VToolSeamAllowance::TagIPaths  = QStringLiteral("iPaths");
 const QString VToolSeamAllowance::AttrVersion        = QStringLiteral("version");
 const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
 const QString VToolSeamAllowance::AttrSeamAllowance  = QStringLiteral("seamAllowance");
-const QString VToolSeamAllowance::AttrWidth          = QStringLiteral("width");
 const QString VToolSeamAllowance::AttrHeight         = QStringLiteral("height");
 const QString VToolSeamAllowance::AttrUnited         = QStringLiteral("united");
 const QString VToolSeamAllowance::AttrFont           = QStringLiteral("fontSize");
-const QString VToolSeamAllowance::AttrRotation       = QStringLiteral("rotation");
 
 //---------------------------------------------------------------------------------------------------------------------
 VToolSeamAllowance::~VToolSeamAllowance()
@@ -173,7 +171,7 @@ void VToolSeamAllowance::AddAttributes(VAbstractPattern *doc, QDomElement &domEl
     doc->SetAttribute(domElement, AttrInLayout, piece.IsInLayout());
     doc->SetAttribute(domElement, AttrForbidFlipping, piece.IsForbidFlipping());
     doc->SetAttribute(domElement, AttrSeamAllowance, piece.IsSeamAllowance());
-    doc->SetAttribute(domElement, AttrWidth, piece.GetFormulaSAWidth());
+    doc->SetAttribute(domElement, VAbstractPattern::AttrWidth, piece.GetFormulaSAWidth());
     doc->SetAttribute(domElement, AttrUnited, piece.IsUnited());
 }
 
@@ -231,10 +229,10 @@ void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement
     doc->SetAttribute(domData, VAbstractPattern::AttrVisible, data.IsVisible() == true? trueStr : falseStr);
     doc->SetAttribute(domData, AttrMx, data.GetPos().x());
     doc->SetAttribute(domData, AttrMy, data.GetPos().y());
-    doc->SetAttribute(domData, AttrWidth, data.GetLabelWidth());
+    doc->SetAttribute(domData, VAbstractPattern::AttrWidth, data.GetLabelWidth());
     doc->SetAttribute(domData, AttrHeight, data.GetLabelHeight());
     doc->SetAttribute(domData, AttrFont, data.GetFontSize());
-    doc->SetAttribute(domData, AttrRotation, data.GetRotation());
+    doc->SetAttribute(domData, VAbstractPattern::AttrRotation, data.GetRotation());
 
     for (int i = 0; i < data.GetMCPCount(); ++i)
     {
@@ -260,10 +258,10 @@ void VToolSeamAllowance::AddPatternInfo(VAbstractPattern *doc, QDomElement &domE
     doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true ? trueStr : falseStr);
     doc->SetAttribute(domData, AttrMx, geom.GetPos().x());
     doc->SetAttribute(domData, AttrMy, geom.GetPos().y());
-    doc->SetAttribute(domData, AttrWidth, geom.GetLabelWidth());
+    doc->SetAttribute(domData, VAbstractPattern::AttrWidth, geom.GetLabelWidth());
     doc->SetAttribute(domData, AttrHeight, geom.GetLabelHeight());
     doc->SetAttribute(domData, AttrFont, geom.GetFontSize());
-    doc->SetAttribute(domData, AttrRotation, geom.GetRotation());
+    doc->SetAttribute(domData, VAbstractPattern::AttrRotation, geom.GetRotation());
     domElement.appendChild(domData);
 }
 
@@ -277,7 +275,7 @@ void VToolSeamAllowance::AddGrainline(VAbstractPattern *doc, QDomElement &domEle
     doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x());
     doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y());
     doc->SetAttribute(domData, AttrLength, glGeom.GetLength());
-    doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation());
+    doc->SetAttribute(domData, VAbstractPattern::AttrRotation, glGeom.GetRotation());
     doc->SetAttribute(domData, VAbstractPattern::AttrArrows, int(glGeom.GetArrowType()));
     domElement.appendChild(domData);
 }
diff --git a/src/libs/vtools/tools/vtoolseamallowance.h b/src/libs/vtools/tools/vtoolseamallowance.h
index 742b42979..304936fd3 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.h
+++ b/src/libs/vtools/tools/vtoolseamallowance.h
@@ -64,11 +64,9 @@ public:
     static const QString AttrVersion;
     static const QString AttrForbidFlipping;
     static const QString AttrSeamAllowance;
-    static const QString AttrWidth;
     static const QString AttrHeight;
     static const QString AttrUnited;
     static const QString AttrFont;
-    static const QString AttrRotation;
 
     void Remove(bool ask);
 

From ded6a9e76c001ab73b045f40293229c018bef419 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 17:47:53 +0200
Subject: [PATCH 183/208] Clean using class VNodeDetail.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtooluniondetails.h     |  1 -
 src/libs/vtools/undocommands/vundocommand.cpp | 18 ------------------
 src/libs/vtools/undocommands/vundocommand.h   |  4 ----
 3 files changed, 23 deletions(-)

diff --git a/src/libs/vtools/tools/vtooluniondetails.h b/src/libs/vtools/tools/vtooluniondetails.h
index b8c3c5649..a0d652bbe 100644
--- a/src/libs/vtools/tools/vtooluniondetails.h
+++ b/src/libs/vtools/tools/vtooluniondetails.h
@@ -51,7 +51,6 @@ class QDomNode;
 class QPointF;
 class VContainer;
 class VMainGraphicsScene;
-class VNodeDetail;
 class VPointF;
 
 struct VToolUnionDetailsInitData
diff --git a/src/libs/vtools/undocommands/vundocommand.cpp b/src/libs/vtools/undocommands/vundocommand.cpp
index 2dfde0c6d..cd430d377 100644
--- a/src/libs/vtools/undocommands/vundocommand.cpp
+++ b/src/libs/vtools/undocommands/vundocommand.cpp
@@ -76,24 +76,6 @@ void VUndoCommand::UndoDeleteAfterSibling(QDomNode &parentNode, const quint32 &s
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-void VUndoCommand::IncrementReferences(const QVector<VNodeDetail> &nodes) const
-{
-    for (qint32 i = 0; i < nodes.size(); ++i)
-    {
-        doc->IncrementReferens(nodes.at(i).getId());
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VUndoCommand::DecrementReferences(const QVector<VNodeDetail> &nodes) const
-{
-    for (qint32 i = 0; i < nodes.size(); ++i)
-    {
-        doc->DecrementReferens(nodes.at(i).getId());
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VUndoCommand::IncrementReferences(const QVector<quint32> &nodes) const
 {
diff --git a/src/libs/vtools/undocommands/vundocommand.h b/src/libs/vtools/undocommands/vundocommand.h
index b6211a239..58f5c1d32 100644
--- a/src/libs/vtools/undocommands/vundocommand.h
+++ b/src/libs/vtools/undocommands/vundocommand.h
@@ -66,7 +66,6 @@ enum class UndoCommand: char { AddPatternPiece,
                                TogglePieceInLayout
                              };
 
-class VNodeDetail;
 class VPieceNode;
 class VPattern;
 
@@ -88,9 +87,6 @@ protected:
     virtual void RedoFullParsing();
     void         UndoDeleteAfterSibling(QDomNode &parentNode, const quint32 &siblingId) const;
 
-    void         IncrementReferences(const QVector<VNodeDetail> &nodes) const;
-    void         DecrementReferences(const QVector<VNodeDetail> &nodes) const;
-
     void         IncrementReferences(const QVector<quint32> &nodes) const;
     void         DecrementReferences(const QVector<quint32> &nodes) const;
 

From 26c76bbc71dd8b6108f9c64e302c5e886135111e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 21 Jan 2017 19:12:57 +0200
Subject: [PATCH 184/208] Replace VDetail by VPiece.

--HG--
branch : feature
---
 src/app/valentina/mainwindow.cpp       |  10 +-
 src/app/valentina/mainwindowsnogui.cpp |  18 +-
 src/app/valentina/mainwindowsnogui.h   |   3 +-
 src/app/valentina/xml/vpattern.cpp     |   1 +
 src/app/valentina/xml/vpattern.h       |   1 +
 src/libs/vpatterndb/vcontainer.cpp     |  63 --
 src/libs/vpatterndb/vcontainer.h       |  13 +-
 src/libs/vpatterndb/vdetail.cpp        | 814 -------------------------
 src/libs/vpatterndb/vdetail.h          | 125 ----
 src/libs/vpatterndb/vdetail_p.h        |  91 ---
 src/libs/vpatterndb/vpatterndb.pri     |   3 -
 src/test/ValentinaTest/tst_vdetail.cpp |  23 +-
 12 files changed, 32 insertions(+), 1133 deletions(-)
 delete mode 100644 src/libs/vpatterndb/vdetail.cpp
 delete mode 100644 src/libs/vpatterndb/vdetail.h
 delete mode 100644 src/libs/vpatterndb/vdetail_p.h

diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 9ed9b9aba..801df66a2 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -2268,10 +2268,10 @@ void MainWindow::ActionLayout(bool checked)
         ui->actionDetails->setChecked(false);
         ui->actionLayout->setChecked(true);
 
-        QHash<quint32, VDetail> details;
+        QHash<quint32, VPiece> details;
         if(not qApp->getOpeningPattern())
         {
-            const QHash<quint32, VDetail> *allDetails = pattern->DataDetails();
+            const QHash<quint32, VPiece> *allDetails = pattern->DataPieces();
             if (allDetails->count() == 0)
             {
                 QMessageBox::information(this, tr("Layout mode"), tr("You can't use now the Layout mode. "
@@ -2282,7 +2282,7 @@ void MainWindow::ActionLayout(bool checked)
             }
             else
             {
-                QHash<quint32, VDetail>::const_iterator i = allDetails->constBegin();
+                QHash<quint32, VPiece>::const_iterator i = allDetails->constBegin();
                 while (i != allDetails->constEnd())
                 {
                     if (i.value().IsInLayout())
@@ -4388,7 +4388,7 @@ void MainWindow::ZoomFirstShow()
     VMainGraphicsView::NewSceneRect(sceneDraw, ui->view);
     VMainGraphicsView::NewSceneRect(sceneDetails, ui->view);
 
-    if (pattern->DataDetails()->size() > 0)
+    if (pattern->DataPieces()->size() > 0)
     {
         ActionDetails(true);
         ui->view->ZoomFitBest();
@@ -4405,7 +4405,7 @@ void MainWindow::DoExport(const VCommandLinePtr &expParams)
 {
     auto settings = expParams->DefaultGenerator();
 
-    const QHash<quint32, VDetail> *details = pattern->DataDetails();
+    const QHash<quint32, VPiece> *details = pattern->DataPieces();
     if(not qApp->getOpeningPattern())
     {
         if (details->count() == 0)
diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp
index b2c369fd4..30630d0c3 100644
--- a/src/app/valentina/mainwindowsnogui.cpp
+++ b/src/app/valentina/mainwindowsnogui.cpp
@@ -463,7 +463,7 @@ void MainWindowsNoGUI::PrintTiled()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VDetail> *details)
+void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VPiece> *details)
 {
     listDetails.clear();
     SCASSERT(details != nullptr)
@@ -472,18 +472,18 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VDetail> *de
         return;
     }
 
-    QHash<quint32, VDetail>::const_iterator i = details->constBegin();
+    QHash<quint32, VPiece>::const_iterator i = details->constBegin();
     while (i != details->constEnd())
     {
         VLayoutDetail det = VLayoutDetail();
-        const VDetail d = i.value();
-        det.SetCountourPoints(d.ContourPoints(pattern));
-        det.SetSeamAllowencePoints(d.SeamAllowancePoints(pattern), d.getSeamAllowance(), d.getClosed());
-        det.setName(d.getName());
+        const VPiece d = i.value();
+        det.SetCountourPoints(d.MainPathPoints(pattern));
+        det.SetSeamAllowencePoints(d.SeamAllowancePoints(pattern), d.IsSeamAllowance(), false);
+        det.setName(d.GetName());
         const VPatternPieceData& data = d.GetPatternPieceData();
         if (data.IsVisible() == true)
         {
-            det.SetDetail(d.getName(), data, qApp->font());
+            det.SetDetail(d.GetName(), data, qApp->font());
         }
         const VPatternInfoGeometry& geom = d.GetPatternInfo();
         if (geom.IsVisible() == true)
@@ -501,9 +501,9 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VDetail> *de
         {
             det.SetGrainline(grainlineGeom, *pattern);
         }
-        det.setWidth(qApp->toPixel(d.getWidth()));
+        det.setWidth(qApp->toPixel(d.GetSAWidth()));
         det.CreateTextItems();
-        det.setForbidFlipping(d.getForbidFlipping());
+        det.setForbidFlipping(d.IsForbidFlipping());
 
         listDetails.append(det);
         ++i;
diff --git a/src/app/valentina/mainwindowsnogui.h b/src/app/valentina/mainwindowsnogui.h
index 6febda374..6b5cfc26f 100644
--- a/src/app/valentina/mainwindowsnogui.h
+++ b/src/app/valentina/mainwindowsnogui.h
@@ -32,7 +32,6 @@
 #include <QMainWindow>
 #include <QPrinter>
 
-#include "../vpatterndb/vdetail.h"
 #include "../vlayout/vlayoutdetail.h"
 #include "xml/vpattern.h"
 #include "dialogs/dialogsavelayout.h"
@@ -90,7 +89,7 @@ protected:
     QMarginsF margins;
     QSizeF paperSize;
 
-    void PrepareDetailsForLayout(const QHash<quint32, VDetail> *details);
+    void PrepareDetailsForLayout(const QHash<quint32, VPiece> *details);
     void ExportLayout(const DialogSaveLayout &dialog);
 
     void InitTempLayoutScene();
diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index f3c77d225..117437147 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -55,6 +55,7 @@
 #include "../vpatterndb/vpatterninfogeometry.h"
 #include "../vpatterndb/vgrainlinegeometry.h"
 #include "../vpatterndb/vpiecepath.h"
+#include "../vpatterndb/vnodedetail.h"
 
 #include <QMessageBox>
 #include <QUndoStack>
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index b70f4af87..20f0e8a3a 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -36,6 +36,7 @@
 
 class VDataTool;
 class VMainGraphicsScene;
+class VNodeDetail;
 
 /**
  * @brief The VPattern class working with pattern file.
diff --git a/src/libs/vpatterndb/vcontainer.cpp b/src/libs/vpatterndb/vcontainer.cpp
index 5cc5a26ef..2034fbc3d 100644
--- a/src/libs/vpatterndb/vcontainer.cpp
+++ b/src/libs/vpatterndb/vcontainer.cpp
@@ -150,24 +150,6 @@ const val VContainer::GetObject(const QHash<key, val> &obj, key id) const
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief GetDetail return detail by id
- * @param id id of detail
- * @return detail
- */
-const VDetail VContainer::GetDetail(quint32 id) const
-{
-    if (d->details->contains(id))
-    {
-        return d->details->value(id);
-    }
-    else
-    {
-        throw VExceptionBadId(tr("Can't find object"), id);
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 VPiece VContainer::GetPiece(quint32 id) const
 {
@@ -208,19 +190,6 @@ quint32 VContainer::AddGObject(VGObject *obj)
     return AddObject(d->gObjects, pointer);
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief AddDetail add new detail to container
- * @param detail new detail
- * @return return id of new detail in container
- */
-quint32 VContainer::AddDetail(const VDetail &detail)
-{
-    const quint32 id = getNextId();
-    d->details->insert(id, detail);
-    return id;
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VContainer::AddPiece(const VPiece &detail)
 {
@@ -304,7 +273,6 @@ void VContainer::Clear()
     qCDebug(vCon, "Clearing container data.");
     _id = NULL_ID;
 
-    d->details->clear();
     d->pieces->clear();
     d->piecePaths->clear();
     ClearVariables();
@@ -318,7 +286,6 @@ void VContainer::ClearForFullParse()
     qCDebug(vCon, "Clearing container data for full parse.");
     _id = NULL_ID;
 
-    d->details->clear();
     d->pieces->clear();
     d->piecePaths->clear();
     ClearVariables(VarType::Increment);
@@ -556,19 +523,6 @@ void VContainer::UpdateGObject(quint32 id, VGObject* obj)
     uniqueNames.insert(obj->name());
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UpdateDetail update detail by id
- * @param id id of existing detail
- * @param detail detail
- */
-void VContainer::UpdateDetail(quint32 id, const VDetail &detail)
-{
-    Q_ASSERT_X(id != NULL_ID, Q_FUNC_INFO, "id == 0"); //-V654 //-V712
-    d->details->insert(id, detail);
-    UpdateId(id);
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VContainer::UpdatePiece(quint32 id, const VPiece &detail)
 {
@@ -734,13 +688,6 @@ const QMap<QString, QSharedPointer<T> > VContainer::DataVar(const VarType &type)
     return map;
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-// cppcheck-suppress unusedFunction
-void VContainer::ClearDetails()
-{
-    d->details->clear();
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 void VContainer::ClearUniqueNames()
 {
@@ -809,16 +756,6 @@ const QHash<quint32, QSharedPointer<VGObject> > *VContainer::DataGObjects() cons
     return &d->gObjects;
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief data container with dataDetails return container of details
- * @return pointer on container of details
- */
-const QHash<quint32, VDetail> *VContainer::DataDetails() const
-{
-    return d->details.data();
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 const QHash<quint32, VPiece> *VContainer::DataPieces() const
 {
diff --git a/src/libs/vpatterndb/vcontainer.h b/src/libs/vpatterndb/vcontainer.h
index 070ef4434..562cc8330 100644
--- a/src/libs/vpatterndb/vcontainer.h
+++ b/src/libs/vpatterndb/vcontainer.h
@@ -53,7 +53,6 @@
 #include "../vmisc/diagnostic.h"
 #include "variables.h"
 #include "variables/vinternalvariable.h"
-#include "vdetail.h"
 #include "vpiece.h"
 #include "vpiecepath.h"
 #include "vtranslatevars.h"
@@ -83,7 +82,6 @@ public:
     VContainerData(const VTranslateVars *trVars, const Unit *patternUnit)
         : gObjects(QHash<quint32, QSharedPointer<VGObject> >()),
           variables(QHash<QString, QSharedPointer<VInternalVariable> > ()),
-          details(QSharedPointer<QHash<quint32, VDetail>>(new QHash<quint32, VDetail>())),
           pieces(QSharedPointer<QHash<quint32, VPiece>>(new QHash<quint32, VPiece>())),
           piecePaths(QSharedPointer<QHash<quint32, VPiecePath>>(new QHash<quint32, VPiecePath>())),
           trVars(trVars),
@@ -94,7 +92,6 @@ public:
         : QSharedData(data),
           gObjects(data.gObjects),
           variables(data.variables),
-          details(data.details),
           pieces(data.pieces),
           piecePaths(data.piecePaths),
           trVars(data.trVars),
@@ -112,10 +109,7 @@ public:
      * @brief variables container for measurements, increments, lines lengths, lines angles, arcs lengths, curve lengths
      */
     QHash<QString, QSharedPointer<VInternalVariable>> variables;
-    /**
-     * @brief details container of details
-     */
-    QSharedPointer<QHash<quint32, VDetail>> details;
+
     QSharedPointer<QHash<quint32, VPiece>> pieces;
     QSharedPointer<QHash<quint32, VPiecePath>> piecePaths;
 
@@ -144,7 +138,6 @@ public:
     const QSharedPointer<T> GeometricObject(const quint32 &id) const;
     const QSharedPointer<VGObject> GetGObject(quint32 id) const;
     static const QSharedPointer<VGObject> GetFakeGObject(quint32 id);
-    const VDetail      GetDetail(quint32 id) const;
     VPiece             GetPiece(quint32 id) const;
     VPiecePath         GetPiecePath(quint32 id) const;
     qreal              GetTableValue(const QString& name, MeasurementsType patternType) const;
@@ -155,7 +148,6 @@ public:
     static void        UpdateId(quint32 newId);
 
     quint32            AddGObject(VGObject *obj);
-    quint32            AddDetail(const VDetail &detail);
     quint32            AddPiece(const VPiece &detail);
     quint32            AddPiecePath(const VPiecePath &path);
     void               AddLine(const quint32 &firstPointId, const quint32 &secondPointId);
@@ -171,7 +163,6 @@ public:
     void               RemovePiece(quint32 id);
 
     void               UpdateGObject(quint32 id, VGObject* obj);
-    void               UpdateDetail(quint32 id, const VDetail &detail);
     void               UpdatePiece(quint32 id, const VPiece &detail);
     void               UpdatePiecePath(quint32 id, const VPiecePath &path);
 
@@ -180,7 +171,6 @@ public:
     void               ClearGObjects();
     void               ClearCalculationGObjects();
     void               ClearVariables(const VarType &type = VarType::Unknown);
-    void               ClearDetails();
     static void        ClearUniqueNames();
 
     static void        SetSize(qreal size);
@@ -195,7 +185,6 @@ public:
     void               RemoveIncrement(const QString& name);
 
     const QHash<quint32, QSharedPointer<VGObject> >         *DataGObjects() const;
-    const QHash<quint32, VDetail>                           *DataDetails() const;
     const QHash<quint32, VPiece>                            *DataPieces() const;
     const QHash<QString, QSharedPointer<VInternalVariable>> *DataVariables() const;
 
diff --git a/src/libs/vpatterndb/vdetail.cpp b/src/libs/vpatterndb/vdetail.cpp
deleted file mode 100644
index 665f3fd9b..000000000
--- a/src/libs/vpatterndb/vdetail.cpp
+++ /dev/null
@@ -1,814 +0,0 @@
-/************************************************************************
- **
- **  @file   vdetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "vdetail.h"
-
-#include <QList>
-#include <QMessageLogger>
-#include <QPainterPath>
-#include <QSet>
-#include <QSharedPointer>
-#include <QString>
-#include <Qt>
-#include <QtDebug>
-#include <new>
-
-#include "../vmisc/def.h"
-#include "../vgeometry/vabstractcurve.h"
-#include "../vgeometry/vgobject.h"
-#include "../vgeometry/vpointf.h"
-#include "../vlayout/vlayoutdef.h"
-#include "vcontainer.h"
-#include "vdetail_p.h"
-#include "vnodedetail.h"
-#include "vpatternpiecedata.h"
-#include "vgrainlinegeometry.h"
-
-class QPointF;
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VDetail default contructor. Create empty detail.
- */
-VDetail::VDetail()
-    :VAbstractDetail(), d(new VDetailData)
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VDetail constructor.
- * @param name detail name.
- * @param nodes list of nodes.
- */
-VDetail::VDetail(const QString &name, const QVector<VNodeDetail> &nodes)
-    :VAbstractDetail(name), d(new VDetailData(nodes))
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VDetail copy constructor.
- * @param detail detail.
- */
-VDetail::VDetail(const VDetail &detail)
-    :VAbstractDetail(detail), d (detail.d)
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief operator = assignment operator.
- * @param detail detail.
- * @return new detail.
- */
-VDetail &VDetail::operator =(const VDetail &detail)
-{
-    if ( &detail == this )
-    {
-        return *this;
-    }
-    VAbstractDetail::operator=(detail);
-    d = detail.d;
-    return *this;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-VDetail::~VDetail()
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Clear detail full clear.
- */
-void VDetail::Clear()
-{
-    d->nodes.clear();
-    d->mx = 0;
-    d->my = 0;
-    GetPatternPieceData().Clear();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ClearNodes clear list of nodes.
- */
-void VDetail::ClearNodes()
-{
-    d->nodes.clear();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Containes check if detail containe this id.
- * @param id object id.
- * @return true if containe.
- */
-bool VDetail::Containes(const quint32 &id) const
-{
-    for (int i = 0; i < d->nodes.size(); ++i)
-    {
-        VNodeDetail node = d->nodes.at(i);
-        if (node.getId() == id)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief operator [] find node by index in list.
- * @param indx index node in list.
- * @return node
- */
-VNodeDetail &VDetail::operator [](int indx)
-{
-    return d->nodes[indx];
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief at find node by index in list.
- * @param indx index node in list.
- * @return const node.
- */
-const VNodeDetail &VDetail::at(int indx) const
-{
-    return d->nodes.at(indx);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief indexOfNode return index in list node using id object.
- * @param id object (arc, point, spline, splinePath) id.
- * @return index in list or -1 id can't find.
- */
-int VDetail::indexOfNode(const quint32 &id) const
-{
-    return indexOfNode(d->nodes, id);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief id return id detail in list data.
- * @return id.
- */
-quint32 VDetail::id() const
-{
-    return d->_id;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setId set id detail in list data.
- * @param id detail id.
- */
-void VDetail::setId(const quint32 &id)
-{
-    d->_id = id;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VDetail::IsInLayout() const
-{
-    return d->inLayout;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VDetail::SetInLayout(bool inLayout)
-{
-    d->inLayout = inLayout;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief OnEdge checks if two poins located on the edge. Edge is line between two points. If between two points
- * located arcs or splines ignore this.
- * @param p1 id first point.
- * @param p2 id second point.
- * @return true - on edge, false - no.
- */
-bool VDetail::OnEdge(const quint32 &p1, const quint32 &p2) const
-{
-    QVector<VNodeDetail> list = listNodePoint();
-    if (list.size() < 2)
-    {
-        qDebug()<<"Not enough points.";
-        return false;
-    }
-    int i = indexOfNode(list, p1);
-    int j1 = 0, j2 = 0;
-
-    if (i == list.size() - 1)
-    {
-        j1 = i-1;
-        j2 = 0;
-    }
-    else if (i == 0)
-    {
-        j1 = list.size() - 1;
-        j2 = i + 1;
-    }
-    else
-    {
-        j1 = i - 1;
-        j2 = i + 1;
-    }
-
-    if (list.at(j1).getId() == p2 || list.at(j2).getId() == p2)
-    {
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Edge return edge index in detail. Edge is line between two points. If between two points
- * located arcs or splines ignore this.
- * @param p1 id first point.
- * @param p2 id second point.
- * @return edge index or -1 if points don't located on edge
- */
-int VDetail::Edge(const quint32 &p1, const quint32 &p2) const
-{
-    if (OnEdge(p1, p2) == false)
-    {
-        qDebug()<<"Points don't on edge.";
-        return -1;
-    }
-
-    QVector<VNodeDetail> list = listNodePoint();
-    int i = indexOfNode(list, p1);
-    int j = indexOfNode(list, p2);
-
-    int min = qMin(i, j);
-
-    if (min == 0 && (i == list.size() - 1 || j == list.size() - 1))
-    {
-        return list.size() - 1;
-    }
-    else
-    {
-        return min;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief NodeOnEdge return nodes located on edge with index.
- * @param index index of edge.
- * @param p1 first node.
- * @param p2 second node.
- */
-void VDetail::NodeOnEdge(const quint32 &index, VNodeDetail &p1, VNodeDetail &p2) const
-{
-    QVector<VNodeDetail> list = listNodePoint();
-    if (index > static_cast<quint32>(list.size()))
-    {
-        qDebug()<<"Wrong edge index index ="<<index;
-        return;
-    }
-    p1 = list.at(static_cast<int>(index));
-    if (index + 1 > static_cast<quint32>(list.size()) - 1)
-    {
-        p2 = list.at(0);
-    }
-    else
-    {
-        p2 = list.at(static_cast<int>(index+1));
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief RemoveEdge return detail without edge with index.
- * @param index idex of edge.
- * @return detail without edge with index.
- */
-VDetail VDetail::RemoveEdge(const quint32 &index) const
-{
-    VDetail det(*this);
-    det.ClearNodes();
-
-    // Edge can be only segment. We ignore all curves inside segments.
-    const quint32 edges = static_cast<quint32>(listNodePoint().size());
-    quint32 k = 0;
-    for (quint32 i=0; i<edges; ++i)
-    {
-        if (i == index)
-        {
-            det.append(this->at(static_cast<int>(k)));
-            ++k;
-        }
-        else
-        {
-            VNodeDetail p1;
-            VNodeDetail p2;
-            this->NodeOnEdge(i, p1, p2);
-            const int j1 = this->indexOfNode(p1.getId());
-            int j2 = this->indexOfNode(p2.getId());
-            if (j2 == 0)
-            {
-                j2 = this->CountNode();
-            }
-            for (int j=j1; j<j2; ++j)
-            {// Add "segment" except last point. Inside can be curves too.
-                det.append(this->at(j));
-                ++k;
-            }
-        }
-    }
-    return det;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Missing find missing nodes in detail. When we deleted object in detail and return this detail need
- * understand, what nodes need make invisible.
- * @param det changed detail.
- * @return  list with missing nodes.
- */
-QVector<VNodeDetail> VDetail::Missing(const VDetail &det) const
-{
-    if (d->nodes.size() == det.CountNode()) //-V807
-    {
-        return QVector<VNodeDetail>();
-    }
-
-    QSet<quint32> set1;
-    for (qint32 i = 0; i < d->nodes.size(); ++i)
-    {
-        set1.insert(d->nodes.at(i).getId());
-    }
-
-    QSet<quint32> set2;
-    for (qint32 j = 0; j < det.CountNode(); ++j)
-    {
-        set2.insert(det.at(j).getId());
-    }
-
-    const QList<quint32> set3 = set1.subtract(set2).toList();
-    QVector<VNodeDetail> nodes;
-    for (qint32 i = 0; i < set3.size(); ++i)
-    {
-        const int index = indexOfNode(d->nodes, set3.at(i));
-        if (index != -1)
-        {
-            nodes.append(d->nodes.at(index));
-        }
-    }
-
-    return nodes;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VDetail::ContourPoints(const VContainer *data) const
-{
-    QVector<QPointF> points;
-    for (int i = 0; i< CountNode(); ++i)
-    {
-        switch (at(i).getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).getId());
-                points.append(*point);
-            }
-            break;
-            case (Tool::NodeArc):
-            case (Tool::NodeElArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-            {
-                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).getId());
-
-                const QPointF begin = StartSegment(data, i, at(i).getReverse());
-                const QPointF end = EndSegment(data, i, at(i).getReverse());
-
-                points << curve->GetSegmentPoints(begin, end, at(i).getReverse());
-            }
-            break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).getTypeTool());
-                break;
-        }
-    }
-
-    points = CheckLoops(CorrectEquidistantPoints(points));//A path can contains loops
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VDetail::SeamAllowancePoints(const VContainer *data) const
-{
-    QVector<QPointF> pointsEkv;
-    if (getSeamAllowance() == false)
-    {
-        return pointsEkv;
-    }
-
-    for (int i = 0; i< CountNode(); ++i)
-    {
-        switch (at(i).getTypeTool())
-        {
-            case (Tool::NodePoint):
-            {
-                const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(at(i).getId());
-                QPointF pEkv = *point;
-                pEkv.setX(pEkv.x()+at(i).getMx());
-                pEkv.setY(pEkv.y()+at(i).getMy());
-                pointsEkv.append(pEkv);
-            }
-            break;
-            case (Tool::NodeArc):
-            case (Tool::NodeElArc):
-            case (Tool::NodeSpline):
-            case (Tool::NodeSplinePath):
-            {
-                const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).getId());
-
-                const QPointF begin = StartSegment(data, i, at(i).getReverse());
-                const QPointF end = EndSegment(data, i, at(i).getReverse());
-
-                const QVector<QPointF> nodePoints = curve->GetSegmentPoints(begin, end, at(i).getReverse());
-                pointsEkv << biasPoints(nodePoints, at(i).getMx(), at(i).getMy());
-            }
-            break;
-            default:
-                qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(at(i).getTypeTool());
-                break;
-        }
-    }
-
-    pointsEkv = CheckLoops(CorrectEquidistantPoints(pointsEkv));//A path can contains loops
-
-    if (getClosed() == true)
-    {
-        pointsEkv = Equidistant(pointsEkv, EquidistantType::CloseEquidistant, ToPixel(getWidth(),
-                                                                                      *data->GetPatternUnit()));
-    }
-    else
-    {
-        pointsEkv = Equidistant(pointsEkv, EquidistantType::OpenEquidistant, ToPixel(getWidth(),
-                                                                                     *data->GetPatternUnit()));
-    }
-    return pointsEkv;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QPainterPath VDetail::ContourPath(const VContainer *data) const
-{
-    const QVector<QPointF> points = ContourPoints(data);
-    QPainterPath path;
-
-    // contour
-    path.moveTo(points[0]);
-    for (qint32 i = 1; i < points.count(); ++i)
-    {
-        path.lineTo(points.at(i));
-    }
-    path.lineTo(points.at(0));
-    path.setFillRule(Qt::WindingFill);
-
-    return path;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QPainterPath VDetail::SeamAllowancePath(const VContainer *data) const
-{
-    const QVector<QPointF> pointsEkv = SeamAllowancePoints(data);
-    QPainterPath ekv;
-
-    // seam allowence
-    if (getSeamAllowance())
-    {
-        if (not pointsEkv.isEmpty())
-        {
-            ekv.moveTo(pointsEkv.at(0));
-            for (qint32 i = 1; i < pointsEkv.count(); ++i)
-            {
-                ekv.lineTo(pointsEkv.at(i));
-            }
-
-            ekv.setFillRule(Qt::WindingFill);
-        }
-    }
-
-    return ekv;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief listNodePoint return list nodes only with points.
- * @return list points node.
- */
-QVector<VNodeDetail> VDetail::listNodePoint() const
-{
-    QVector<VNodeDetail> list;
-    for (int i = 0; i < d->nodes.size(); ++i) //-V807
-    {
-        if (d->nodes.at(i).getTypeTool() == Tool::NodePoint)
-        {
-            list.append(d->nodes.at(i));
-        }
-    }
-    return list;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VDetail::SetPatternPieceData(const VPatternPieceData &data)
-{
-    d->m_ppData = data;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Returns full access to the pattern piece data object
- * @return pattern piece data object
- */
-VPatternPieceData& VDetail::GetPatternPieceData()
-{
-    return d->m_ppData;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Returns the read only reference to the pattern piece data object
- * @return pattern piece data object
- */
-const VPatternPieceData& VDetail::GetPatternPieceData() const
-{
-    return d->m_ppData;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VDetail::SetPatternInfo(const VPatternInfoGeometry &info)
-{
-    d->m_piPatternInfo = info;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Returns full access to the pattern info geometry object
- * @return pattern info geometry object
- */
-VPatternInfoGeometry& VDetail::GetPatternInfo()
-{
-    return d->m_piPatternInfo;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Returns the read only reference to the pattern info geometry object
- * @return pattern info geometry object
- */
-const VPatternInfoGeometry& VDetail::GetPatternInfo() const
-{
-    return d->m_piPatternInfo;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-
-/**
- * @brief VDetail::GetGrainlineGeometry full access to the grainline geometry object
- * @return reference to grainline geometry object
- */
-VGrainlineGeometry& VDetail::GetGrainlineGeometry()
-{
-    return d->m_glGrainline;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-
-/**
- * @brief VDetail::GetGrainlineGeometry returns the read-only reference to the grainline geometry object
- * @return reference to grainline geometry object
- */
-const VGrainlineGeometry& VDetail::GetGrainlineGeometry() const
-{
-    return d->m_glGrainline;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief indexOfNode return index in list node using id object.
- * @param list list nodes detail.
- * @param id object (arc, point, spline, splinePath) id.
- * @return index in list or -1 id can't find.
- */
-int VDetail::indexOfNode(const QVector<VNodeDetail> &list, const quint32 &id)
-{
-    for (int i = 0; i < list.size(); ++i)
-    {
-        if (list.at(i).getId() == id)
-        {
-            return i;
-        }
-    }
-    qDebug()<<"Can't find node.";
-    return -1;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QPointF VDetail::StartSegment(const VContainer *data, const int &i, bool reverse) const
-{
-    if (i < 0 && i > CountNode()-1)
-    {
-        return QPointF();
-    }
-
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).getId());
-
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
-    {
-        points = VGObject::GetReversePoints(points);
-    }
-
-    QPointF begin = points.first();
-    if (CountNode() > 1)
-    {
-        if (i == 0)
-        {
-            if (at(CountNode()-1).getTypeTool() == Tool::NodePoint)
-            {
-                begin = *data->GeometricObject<VPointF>(at(CountNode()-1).getId());
-            }
-        }
-        else
-        {
-            if (at(i-1).getTypeTool() == Tool::NodePoint)
-            {
-                begin = *data->GeometricObject<VPointF>(at(i-1).getId());
-            }
-        }
-    }
-    return begin;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QPointF VDetail::EndSegment(const VContainer *data, const int &i, bool reverse) const
-{
-    if (i < 0 && i > CountNode()-1)
-    {
-        return QPointF();
-    }
-
-    const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).getId());
-
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
-    {
-        points = VGObject::GetReversePoints(points);
-    }
-
-    QPointF end = points.last();
-    if (CountNode() > 2)
-    {
-        if (i == CountNode() - 1)
-        {
-            if (at(0).getTypeTool() == Tool::NodePoint)
-            {
-                end = *data->GeometricObject<VPointF>(at(0).getId());
-            }
-        }
-        else
-        {
-            if (at(i+1).getTypeTool() == Tool::NodePoint)
-            {
-                end = *data->GeometricObject<VPointF>(at(i+1).getId());
-            }
-        }
-    }
-    return end;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief biasPoints bias point.
- * @param points vector of points.
- * @param mx offset respect to x.
- * @param my offset respect to y.
- * @return new vector biased points.
- */
-QVector<QPointF> VDetail::biasPoints(const QVector<QPointF> &points, const qreal &mx, const qreal &my)
-{
-    QVector<QPointF> p;
-    for (qint32 i = 0; i < points.size(); ++i)
-    {
-        QPointF point = points.at(i);
-        point.setX(point.x() + mx);
-        point.setY(point.y() + my);
-        p.append(point);
-    }
-    return p;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief append append in the end of list node.
- * @param node new node.
- */
-void VDetail::append(const VNodeDetail &node)
-{
-    d->nodes.append(node);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CountNode return count nodes.
- * @return count.
- */
-qint32 VDetail::CountNode() const
-{
-    return d->nodes.size();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getMx return bias for X axis.
- * @return x bias.
- */
-qreal VDetail::getMx() const
-{
-    return d->mx;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setMx set bias for X axis.
- * @param value new x bias.
- */
-void VDetail::setMx(const qreal &value)
-{
-    d->mx = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getMy get bias for y axis.
- * @return y axis.
- */
-qreal VDetail::getMy() const
-{
-    return d->my;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setMy set bias for y axis.
- * @param value new y bias.
- */
-void VDetail::setMy(const qreal &value)
-{
-    d->my = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getNodes return list of nodes.
- * @return list of nodes.
- */
-QVector<VNodeDetail> VDetail::getNodes() const
-{
-    return d->nodes;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setNodes set list of nodes
- * @param value list of nodes
- */
-// cppcheck-suppress unusedFunction
-void VDetail::setNodes(const QVector<VNodeDetail> &value)
-{
-    d->nodes = value;
-}
diff --git a/src/libs/vpatterndb/vdetail.h b/src/libs/vpatterndb/vdetail.h
deleted file mode 100644
index 54eb0c958..000000000
--- a/src/libs/vpatterndb/vdetail.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/************************************************************************
- **
- **  @file   vdetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   November 15, 2013
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 VDETAIL_H
-#define VDETAIL_H
-
-#include <qcompilerdetection.h>
-#include <QPointF>
-#include <QSharedDataPointer>
-#include <QString>
-#include <QTypeInfo>
-#include <QVector>
-#include <QtGlobal>
-
-#include "../vlayout/vabstractdetail.h"
-#include "vnodedetail.h"
-
-class QPainterPath;
-class QPointF;
-class VContainer;
-class VDetailData;
-class VNodeDetail;
-class VPatternInfoGeometry;
-class VPatternPieceData;
-class VGrainlineGeometry;
-
-/**
- * @brief The VDetail class for path of object (points, arcs, splines).
- */
-class VDetail :public VAbstractDetail
-{
-public:
-    VDetail();
-    VDetail(const QString &name, const QVector<VNodeDetail> &nodes);
-    VDetail(const VDetail &detail);
-    VDetail &operator=(const VDetail &detail);
-    virtual ~VDetail() Q_DECL_OVERRIDE;
-
-    void           append(const VNodeDetail &node);
-    void           Clear();
-    void           ClearNodes();
-    qint32         CountNode() const;
-    bool           Containes(const quint32 &id)const;
-    VNodeDetail &  operator[](int indx);
-    const VNodeDetail & at ( int indx ) const;
-
-    qreal getMx() const;
-    void  setMx(const qreal &value);
-
-    qreal getMy() const;
-    void  setMy(const qreal &value);
-
-    quint32 id() const;
-    void    setId(const quint32 &id);
-
-    bool IsInLayout() const;
-    void SetInLayout(bool inLayout);
-
-    QVector<VNodeDetail> getNodes() const;
-    void setNodes(const QVector<VNodeDetail> &value);
-
-    int  indexOfNode(const quint32 &id) const;
-    bool OnEdge(const quint32 &p1, const quint32 &p2)const;
-    int  Edge(const quint32 &p1, const quint32 &p2)const;
-    void NodeOnEdge(const quint32 &index, VNodeDetail &p1, VNodeDetail &p2)const;
-    VDetail RemoveEdge(const quint32 &index) const;
-
-    QVector<VNodeDetail> Missing(const VDetail &det) const;
-
-    QVector<QPointF> ContourPoints(const VContainer *data) const;
-    QVector<QPointF> SeamAllowancePoints(const VContainer *data) const;
-
-    QPainterPath ContourPath(const VContainer *data) const;
-    QPainterPath SeamAllowancePath(const VContainer *data) const;
-    QVector<VNodeDetail> listNodePoint()const;
-
-    void                     SetPatternPieceData(const VPatternPieceData &data);
-    VPatternPieceData&       GetPatternPieceData();
-    const VPatternPieceData& GetPatternPieceData() const;
-
-    void                        SetPatternInfo(const VPatternInfoGeometry &info);
-    VPatternInfoGeometry&       GetPatternInfo();
-    const VPatternInfoGeometry& GetPatternInfo() const;
-    VGrainlineGeometry& GetGrainlineGeometry();
-    const VGrainlineGeometry& GetGrainlineGeometry() const;
-
-private:
-    QSharedDataPointer<VDetailData> d;
-
-    static int indexOfNode(const QVector<VNodeDetail> &list, const quint32 &id);
-
-    QPointF StartSegment(const VContainer *data, const int &i, bool reverse) const;
-    QPointF EndSegment(const VContainer *data, const int &i, bool reverse) const;
-
-    static QVector<QPointF> biasPoints(const QVector<QPointF> &points, const qreal &mx, const qreal &my);
-};
-
-Q_DECLARE_TYPEINFO(VDetail, Q_MOVABLE_TYPE);
-
-#endif // VDETAIL_H
diff --git a/src/libs/vpatterndb/vdetail_p.h b/src/libs/vpatterndb/vdetail_p.h
deleted file mode 100644
index d3692ca24..000000000
--- a/src/libs/vpatterndb/vdetail_p.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/************************************************************************
- **
- **  @file   vdetail_p.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   20 8, 2014
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 VDETAIL_P_H
-#define VDETAIL_P_H
-
-#include <QSharedData>
-#include "vnodedetail.h"
-#include "vpatternpiecedata.h"
-#include "vpatterninfogeometry.h"
-#include "vgrainlinegeometry.h"
-#include "../ifc/ifcdef.h"
-#include "../vmisc/diagnostic.h"
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC("-Weffc++")
-
-class VDetailData : public QSharedData
-{
-public:
-    VDetailData()
-        :_id(NULL_ID), nodes(QVector<VNodeDetail>()), mx(0), my(0), inLayout(true)
-    {}
-
-    explicit VDetailData(const QVector<VNodeDetail> &nodes)
-        :_id(NULL_ID), nodes(nodes), mx(0), my(0), inLayout(true)
-    {}
-
-    VDetailData(const VDetailData &detail)
-        :QSharedData(detail), _id(NULL_ID), nodes(detail.nodes), mx(detail.mx), my(detail.my),
-          m_ppData(detail.m_ppData), m_piPatternInfo(detail.m_piPatternInfo),
-          m_glGrainline(detail.m_glGrainline), inLayout(detail.inLayout)
-    {}
-
-    ~VDetailData() {}
-
-    /** @brief _id id detail. */
-    quint32        _id;
-
-    /** @brief nodes list detail nodes. */
-    QVector<VNodeDetail> nodes;
-
-    /** @brief mx bias x axis. */
-    qreal          mx;
-
-    /** @brief my bias y axis. */
-    qreal          my;
-
-    /** @brief Pattern piece data */
-    VPatternPieceData m_ppData;
-    /** @brief Pattern info coordinates */
-    VPatternInfoGeometry m_piPatternInfo;
-    /**
-     * @brief m_glGrainline grainline geometry object
-     */
-    VGrainlineGeometry m_glGrainline;
-
-    bool           inLayout;
-
-private:
-    VDetailData &operator=(const VDetailData &) Q_DECL_EQ_DELETE;
-};
-
-QT_WARNING_POP
-
-#endif // VDETAIL_P_H
diff --git a/src/libs/vpatterndb/vpatterndb.pri b/src/libs/vpatterndb/vpatterndb.pri
index b35c843ba..5a94d2ff8 100644
--- a/src/libs/vpatterndb/vpatterndb.pri
+++ b/src/libs/vpatterndb/vpatterndb.pri
@@ -4,7 +4,6 @@
 SOURCES += \
     $$PWD/vcontainer.cpp \
     $$PWD/calculator.cpp \
-    $$PWD/vdetail.cpp \
     $$PWD/vnodedetail.cpp \
     $$PWD/vtranslatevars.cpp \
     $$PWD/variables/varcradius.cpp \
@@ -34,8 +33,6 @@ HEADERS += \
     $$PWD/stable.h \
     $$PWD/calculator.h \
     $$PWD/variables.h \
-    $$PWD/vdetail.h \
-    $$PWD/vdetail_p.h \
     $$PWD/vnodedetail.h \
     $$PWD/vnodedetail_p.h \
     $$PWD/vtranslatevars.h \
diff --git a/src/test/ValentinaTest/tst_vdetail.cpp b/src/test/ValentinaTest/tst_vdetail.cpp
index 486ec5ea5..d835b449c 100644
--- a/src/test/ValentinaTest/tst_vdetail.cpp
+++ b/src/test/ValentinaTest/tst_vdetail.cpp
@@ -28,6 +28,9 @@
 
 #include "tst_vdetail.h"
 #include "../vpatterndb/vcontainer.h"
+#include "../vpatterndb/vpiece.h"
+#include "../vpatterndb/vpiecenode.h"
+#include "../vpatterndb/vpiecepath.h"
 #include "../vgeometry/vsplinepath.h"
 
 #include <QtTest>
@@ -86,15 +89,17 @@ void TST_VDetail::ClearLoop()
     data->UpdateGObject(310, new VPointF(802.08718110236236, 1653.9337322834645, "Н5", 5.0000125984251973,
                                          9.9999874015748045));
 
-    VDetail detail;
-    detail.setSeamAllowance(true);
-    detail.setWidth(7);
-    detail.setClosed(false);
-    detail.append(VNodeDetail(304, Tool::NodePoint, NodeDetail::Contour));
-    detail.append(VNodeDetail(307, Tool::NodePoint, NodeDetail::Contour));
-    detail.append(VNodeDetail(308, Tool::NodeSplinePath, NodeDetail::Contour));
-    detail.append(VNodeDetail(309, Tool::NodePoint, NodeDetail::Contour));
-    detail.append(VNodeDetail(310, Tool::NodePoint, NodeDetail::Contour));
+    VPiece detail;
+    detail.SetSeamAllowance(true);
+    detail.SetSAWidth(7);
+    detail.GetPath().Append(VPieceNode(304, Tool::NodePoint));
+    detail.GetPath().Append(VPieceNode(307, Tool::NodePoint));
+    detail.GetPath().Append(VPieceNode(308, Tool::NodeSplinePath));
+    detail.GetPath().Append(VPieceNode(309, Tool::NodePoint));
+    detail.GetPath().Append(VPieceNode(310, Tool::NodePoint));
+    // Closed
+    detail.GetPath()[0].SetFormulaSABefore("0");
+    detail.GetPath()[detail.GetPath().CountNodes()-1].SetFormulaSAAfter("0");
 
     const QVector<QPointF> pointsEkv = detail.SeamAllowancePoints(data);
 

From 8fb6c9c508f72370fd47b91a40fb9fbf0dbf6a8c Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 10:32:01 +0200
Subject: [PATCH 185/208] Code that converts VPiece to VLayoutDetail moved to
 static function.

--HG--
branch : feature
---
 src/app/valentina/mainwindowsnogui.cpp | 32 +----------------------
 src/libs/vlayout/vlayoutdetail.cpp     | 35 ++++++++++++++++++++++++++
 src/libs/vlayout/vlayoutdetail.h       |  2 ++
 3 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp
index 30630d0c3..c996b5427 100644
--- a/src/app/valentina/mainwindowsnogui.cpp
+++ b/src/app/valentina/mainwindowsnogui.cpp
@@ -475,37 +475,7 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VPiece> *det
     QHash<quint32, VPiece>::const_iterator i = details->constBegin();
     while (i != details->constEnd())
     {
-        VLayoutDetail det = VLayoutDetail();
-        const VPiece d = i.value();
-        det.SetCountourPoints(d.MainPathPoints(pattern));
-        det.SetSeamAllowencePoints(d.SeamAllowancePoints(pattern), d.IsSeamAllowance(), false);
-        det.setName(d.GetName());
-        const VPatternPieceData& data = d.GetPatternPieceData();
-        if (data.IsVisible() == true)
-        {
-            det.SetDetail(d.GetName(), data, qApp->font());
-        }
-        const VPatternInfoGeometry& geom = d.GetPatternInfo();
-        if (geom.IsVisible() == true)
-        {
-            VAbstractPattern* pDoc = qApp->getCurrentDocument();
-            QDate date;
-            if (pDoc->IsDateVisible() == true)
-            {
-                date = QDate::currentDate();
-            }
-            det.SetPatternInfo(pDoc, geom, qApp->font(), pattern->size(), pattern->height());
-        }
-        const VGrainlineGeometry& grainlineGeom = d.GetGrainlineGeometry();
-        if (grainlineGeom.IsVisible() == true)
-        {
-            det.SetGrainline(grainlineGeom, *pattern);
-        }
-        det.setWidth(qApp->toPixel(d.GetSAWidth()));
-        det.CreateTextItems();
-        det.setForbidFlipping(d.IsForbidFlipping());
-
-        listDetails.append(det);
+        listDetails.append(VLayoutDetail::Create(i.value(), pattern));
         ++i;
     }
 }
diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp
index 08e6ea135..c2042aa33 100644
--- a/src/libs/vlayout/vlayoutdetail.cpp
+++ b/src/libs/vlayout/vlayoutdetail.cpp
@@ -83,6 +83,41 @@ VLayoutDetail &VLayoutDetail::operator=(const VLayoutDetail &detail)
 VLayoutDetail::~VLayoutDetail()
 {}
 
+//---------------------------------------------------------------------------------------------------------------------
+VLayoutDetail VLayoutDetail::Create(const VPiece &piece, const VContainer *pattern)
+{
+    VLayoutDetail det = VLayoutDetail();
+    det.SetCountourPoints(piece.MainPathPoints(pattern));
+    det.SetSeamAllowencePoints(piece.SeamAllowancePoints(pattern), piece.IsSeamAllowance(), false);
+    det.setName(piece.GetName());
+    const VPatternPieceData& data = piece.GetPatternPieceData();
+    if (data.IsVisible() == true)
+    {
+        det.SetDetail(piece.GetName(), data, qApp->font());
+    }
+    const VPatternInfoGeometry& geom = piece.GetPatternInfo();
+    if (geom.IsVisible() == true)
+    {
+        VAbstractPattern* pDoc = qApp->getCurrentDocument();
+        QDate date;
+        if (pDoc->IsDateVisible() == true)
+        {
+            date = QDate::currentDate();
+        }
+        det.SetPatternInfo(pDoc, geom, qApp->font(), pattern->size(), pattern->height());
+    }
+    const VGrainlineGeometry& grainlineGeom = piece.GetGrainlineGeometry();
+    if (grainlineGeom.IsVisible() == true)
+    {
+        det.SetGrainline(grainlineGeom, *pattern);
+    }
+    det.setWidth(qApp->toPixel(piece.GetSAWidth()));
+    det.CreateTextItems();
+    det.setForbidFlipping(piece.IsForbidFlipping());
+
+    return det;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 // cppcheck-suppress unusedFunction
 QVector<QPointF> VLayoutDetail::GetContourPoints() const
diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h
index e23924dcf..f72e67473 100644
--- a/src/libs/vlayout/vlayoutdetail.h
+++ b/src/libs/vlayout/vlayoutdetail.h
@@ -68,6 +68,8 @@ public:
     VLayoutDetail &operator=(const VLayoutDetail &detail);
     virtual ~VLayoutDetail() Q_DECL_OVERRIDE;
 
+    static VLayoutDetail Create(const VPiece &piece, const VContainer *pattern);
+
     QVector<QPointF> GetContourPoints() const;
     void SetCountourPoints(const QVector<QPointF> &points);
 

From c6f529992bfba34f331c06ccfeee9cbbd96430dd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 10:50:23 +0200
Subject: [PATCH 186/208] Switch parent for class VLayoutDetail to
 VAbstractPiece.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractpiece.h  |  2 ++
 src/libs/vlayout/vlayoutdetail.cpp | 51 ++++++++++++++++++------------
 src/libs/vlayout/vlayoutdetail.h   |  7 ++--
 src/libs/vlayout/vlayoutpaper.cpp  |  2 +-
 src/libs/vlayout/vposition.cpp     |  2 +-
 5 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index fd618fe37..a6b0a8dc5 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -203,6 +203,8 @@ private:
     static qreal            AngleBetweenBisectors(const QLineF &b1, const QLineF &b2);
 };
 
+Q_DECLARE_TYPEINFO(VAbstractPiece, Q_MOVABLE_TYPE);
+
 //---------------------------------------------------------------------------------------------------------------------
 /**
  * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp
index c2042aa33..da6ff54a0 100644
--- a/src/libs/vlayout/vlayoutdetail.cpp
+++ b/src/libs/vlayout/vlayoutdetail.cpp
@@ -59,12 +59,12 @@ class VAbstractPattern;
 
 //---------------------------------------------------------------------------------------------------------------------
 VLayoutDetail::VLayoutDetail()
-    :VAbstractDetail(), d(new VLayoutDetailData)
+    :VAbstractPiece(), d(new VLayoutDetailData)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
 VLayoutDetail::VLayoutDetail(const VLayoutDetail &detail)
-    :VAbstractDetail(detail), d(detail.d)
+    :VAbstractPiece(detail), d(detail.d)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -74,7 +74,7 @@ VLayoutDetail &VLayoutDetail::operator=(const VLayoutDetail &detail)
     {
         return *this;
     }
-    VAbstractDetail::operator=(detail);
+    VAbstractPiece::operator=(detail);
     d = detail.d;
     return *this;
 }
@@ -88,8 +88,8 @@ VLayoutDetail VLayoutDetail::Create(const VPiece &piece, const VContainer *patte
 {
     VLayoutDetail det = VLayoutDetail();
     det.SetCountourPoints(piece.MainPathPoints(pattern));
-    det.SetSeamAllowencePoints(piece.SeamAllowancePoints(pattern), piece.IsSeamAllowance(), false);
-    det.setName(piece.GetName());
+    det.SetSeamAllowencePoints(piece.SeamAllowancePoints(pattern), piece.IsSeamAllowance());
+    det.SetName(piece.GetName());
     const VPatternPieceData& data = piece.GetPatternPieceData();
     if (data.IsVisible() == true)
     {
@@ -111,9 +111,9 @@ VLayoutDetail VLayoutDetail::Create(const VPiece &piece, const VContainer *patte
     {
         det.SetGrainline(grainlineGeom, *pattern);
     }
-    det.setWidth(qApp->toPixel(piece.GetSAWidth()));
+    det.SetSAWidth(qApp->toPixel(piece.GetSAWidth()));
     det.CreateTextItems();
-    det.setForbidFlipping(piece.IsForbidFlipping());
+    det.SetForbidFlipping(piece.IsForbidFlipping());
 
     return det;
 }
@@ -139,12 +139,11 @@ QVector<QPointF> VLayoutDetail::GetSeamAllowencePoints() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence, bool closed)
+void VLayoutDetail::SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence)
 {
     if (seamAllowence)
     {
-        setSeamAllowance(seamAllowence);
-        setClosed(closed);
+        SetSeamAllowance(seamAllowence);
         d->seamAllowence = points;
         if (not d->seamAllowence.isEmpty())
         {
@@ -153,7 +152,7 @@ void VLayoutDetail::SetSeamAllowencePoints(const QVector<QPointF> &points, bool
         else
         {
             qWarning()<<"Seam allowence is empty.";
-            setSeamAllowance(false);
+            SetSeamAllowance(false);
         }
     }
 }
@@ -401,7 +400,7 @@ int VLayoutDetail::LayoutEdgeByPoint(const QPointF &p1) const
 QRectF VLayoutDetail::DetailBoundingRect() const
 {
     QVector<QPointF> points;
-    if (getSeamAllowance())
+    if (IsSeamAllowance())
     {
         points = GetSeamAllowencePoints();
     }
@@ -434,7 +433,7 @@ bool VLayoutDetail::isNull() const
 {
     if (d->contour.isEmpty() == false && d->layoutWidth > 0)
     {
-        if (getSeamAllowance() && d->seamAllowence.isEmpty() == false)
+        if (IsSeamAllowance() && d->seamAllowence.isEmpty() == false)
         {
             return false;
         }
@@ -468,10 +467,9 @@ void VLayoutDetail::SetLayoutAllowencePoints()
 {
     if (d->layoutWidth > 0)
     {
-        if (getSeamAllowance())
+        if (IsSeamAllowance())
         {
-            d->layoutAllowence = Equidistant(GetSeamAllowencePoints(), EquidistantType::CloseEquidistant,
-                                             d->layoutWidth);
+            d->layoutAllowence = Equidistant(PrepareAllowance(GetSeamAllowencePoints()), d->layoutWidth);
             if (d->layoutAllowence.isEmpty() == false)
             {
                 #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
@@ -483,7 +481,7 @@ void VLayoutDetail::SetLayoutAllowencePoints()
         }
         else
         {
-            d->layoutAllowence = Equidistant(GetContourPoints(), EquidistantType::CloseEquidistant, d->layoutWidth);
+            d->layoutAllowence = Equidistant(PrepareAllowance(GetContourPoints()), d->layoutWidth);
             if (d->layoutAllowence.isEmpty() == false)
             {
             #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
@@ -547,13 +545,13 @@ QPainterPath VLayoutDetail::ContourPath() const
     path.lineTo(points.at(0));
 
     // seam allowence
-    if (getSeamAllowance() == true)
+    if (IsSeamAllowance() == true)
     {
         points = GetSeamAllowencePoints();
 
-        if (getClosed() == true)
+        if (points.last().toPoint() != points.first().toPoint())
         {
-            points.append(points.at(0));
+            points.append(points.at(0));// Should be always closed
         }
 
         QPainterPath ekv;
@@ -799,7 +797,7 @@ QGraphicsItem* VLayoutDetail::GetGrainlineItem() const
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VLayoutDetail::DetailPath() const
 {
-    if (getSeamAllowance())
+    if (IsSeamAllowance())
     {
         return d->seamAllowence;
     }
@@ -809,6 +807,17 @@ QVector<QPointF> VLayoutDetail::DetailPath() const
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<VSAPoint> VLayoutDetail::PrepareAllowance(const QVector<QPointF> &points)
+{
+    QVector<VSAPoint> allowancePoints;
+    for(int i = 0; i < points.size(); +i)
+    {
+        allowancePoints.append(VSAPoint(points.at(i)));
+    }
+    return allowancePoints;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool VLayoutDetail::IsMirror() const
 {
diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h
index f72e67473..138f65184 100644
--- a/src/libs/vlayout/vlayoutdetail.h
+++ b/src/libs/vlayout/vlayoutdetail.h
@@ -45,7 +45,7 @@
 #include "../vpatterndb/vpatterninfogeometry.h"
 #include "../vpatterndb/vpatternpiecedata.h"
 #include "../vpatterndb/vcontainer.h"
-#include "vabstractdetail.h"
+#include "vabstractpiece.h"
 
 class QFont;
 class QGraphicsItem;
@@ -60,7 +60,7 @@ class VPatternInfoGeometry;
 class VPatternPieceData;
 class VGrainlineGeometry;
 
-class VLayoutDetail :public VAbstractDetail
+class VLayoutDetail :public VAbstractPiece
 {
 public:
     VLayoutDetail();
@@ -74,7 +74,7 @@ public:
     void SetCountourPoints(const QVector<QPointF> &points);
 
     QVector<QPointF> GetSeamAllowencePoints() const;
-    void SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence = true, bool closed = true);
+    void SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence = true);
 
     QVector<QPointF> GetLayoutAllowencePoints() const;
     void SetLayoutAllowencePoints();
@@ -128,6 +128,7 @@ private:
 
     QVector<QPointF> DetailPath() const;
 
+    static QVector<VSAPoint> PrepareAllowance(const QVector<QPointF> &points);
     QVector<QPointF> Map(const QVector<QPointF> &points) const;
     static QVector<QPointF> RoundPoints(const QVector<QPointF> &points);
 
diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp
index 3cd1b4b15..6422faeea 100644
--- a/src/libs/vlayout/vlayoutpaper.cpp
+++ b/src/libs/vlayout/vlayoutpaper.cpp
@@ -198,7 +198,7 @@ bool VLayoutPaper::ArrangeDetail(const VLayoutDetail &detail, volatile bool &sto
         return false;//Not enough edges
     }
 
-    if (detail.getForbidFlipping() && not d->globalRotate)
+    if (detail.IsForbidFlipping() && not d->globalRotate)
     { // Compensate forbidden flipping by rotating. 180 degree will be enough.
         d->localRotate = true;
         d->localRotationIncrease = 180;
diff --git a/src/libs/vlayout/vposition.cpp b/src/libs/vlayout/vposition.cpp
index 9308536f2..6524dddb6 100644
--- a/src/libs/vlayout/vposition.cpp
+++ b/src/libs/vlayout/vposition.cpp
@@ -294,7 +294,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
             break;
     }
 
-    if (flagMirror && not detail.getForbidFlipping())
+    if (flagMirror && not detail.IsForbidFlipping())
     {
         #ifdef LAYOUT_DEBUG
             #ifdef SHOW_MIRROR

From 10a13a499dff4791d02eb5482c18d1e7e018c09e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 11:02:02 +0200
Subject: [PATCH 187/208] Rename class VLayoutDetail.

--HG--
branch : feature
---
 src/app/valentina/mainwindowsnogui.cpp        |   4 +-
 src/app/valentina/mainwindowsnogui.h          |   4 +-
 src/libs/vlayout/vbank.cpp                    |  10 +-
 src/libs/vlayout/vbank.h                      |   8 +-
 src/libs/vlayout/vcontour.cpp                 |   6 +-
 src/libs/vlayout/vcontour.h                   |   6 +-
 src/libs/vlayout/vlayout.pri                  |  10 +-
 src/libs/vlayout/vlayoutgenerator.cpp         |  16 +--
 src/libs/vlayout/vlayoutgenerator.h           |   8 +-
 src/libs/vlayout/vlayoutpaper.cpp             |  14 +--
 src/libs/vlayout/vlayoutpaper.h               |  12 +-
 src/libs/vlayout/vlayoutpaper_p.h             |   8 +-
 .../{vlayoutdetail.cpp => vlayoutpiece.cpp}   | 110 +++++++++---------
 .../{vlayoutdetail.h => vlayoutpiece.h}       |  18 +--
 .../{vlayoutdetail_p.h => vlayoutpiece_p.h}   |  10 +-
 src/libs/vlayout/vposition.cpp                |  28 ++---
 src/libs/vlayout/vposition.h                  |  28 ++---
 src/test/ValentinaTest/tst_vlayoutdetail.cpp  |   8 +-
 18 files changed, 154 insertions(+), 154 deletions(-)
 rename src/libs/vlayout/{vlayoutdetail.cpp => vlayoutpiece.cpp} (89%)
 rename src/libs/vlayout/{vlayoutdetail.h => vlayoutpiece.h} (91%)
 rename src/libs/vlayout/{vlayoutdetail_p.h => vlayoutpiece_p.h} (94%)

diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp
index c996b5427..9ba89c342 100644
--- a/src/app/valentina/mainwindowsnogui.cpp
+++ b/src/app/valentina/mainwindowsnogui.cpp
@@ -60,7 +60,7 @@
 
 //---------------------------------------------------------------------------------------------------------------------
 MainWindowsNoGUI::MainWindowsNoGUI(QWidget *parent)
-    : VAbstractMainWindow(parent), listDetails(QVector<VLayoutDetail>()), currentScene(nullptr), tempSceneLayout(nullptr),
+    : VAbstractMainWindow(parent), listDetails(QVector<VLayoutPiece>()), currentScene(nullptr), tempSceneLayout(nullptr),
       pattern(new VContainer(qApp->TrVars(), qApp->patternUnitP())), doc(nullptr), papers(QList<QGraphicsItem *>()),
       shadows(QList<QGraphicsItem *>()), scenes(QList<QGraphicsScene *>()), details(QList<QList<QGraphicsItem *> >()),
       undoAction(nullptr), redoAction(nullptr), actionDockWidgetToolOptions(nullptr), actionDockWidgetGroups(nullptr),
@@ -475,7 +475,7 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VPiece> *det
     QHash<quint32, VPiece>::const_iterator i = details->constBegin();
     while (i != details->constEnd())
     {
-        listDetails.append(VLayoutDetail::Create(i.value(), pattern));
+        listDetails.append(VLayoutPiece::Create(i.value(), pattern));
         ++i;
     }
 }
diff --git a/src/app/valentina/mainwindowsnogui.h b/src/app/valentina/mainwindowsnogui.h
index 6b5cfc26f..17f715dfb 100644
--- a/src/app/valentina/mainwindowsnogui.h
+++ b/src/app/valentina/mainwindowsnogui.h
@@ -32,7 +32,7 @@
 #include <QMainWindow>
 #include <QPrinter>
 
-#include "../vlayout/vlayoutdetail.h"
+#include "../vlayout/vlayoutpiece.h"
 #include "xml/vpattern.h"
 #include "dialogs/dialogsavelayout.h"
 #include "../vlayout/vlayoutgenerator.h"
@@ -58,7 +58,7 @@ public slots:
     void PrintOrigin();
     void PrintTiled();
 protected:
-    QVector<VLayoutDetail> listDetails;
+    QVector<VLayoutPiece> listDetails;
 
     /** @brief currentScene pointer to current scene. */
     QGraphicsScene *currentScene;
diff --git a/src/libs/vlayout/vbank.cpp b/src/libs/vlayout/vbank.cpp
index f28787391..17b8eb7cf 100644
--- a/src/libs/vlayout/vbank.cpp
+++ b/src/libs/vlayout/vbank.cpp
@@ -32,7 +32,7 @@
 
 #include "../vmisc/diagnostic.h"
 #include "../vmisc/logging.h"
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes")
@@ -52,7 +52,7 @@ QT_WARNING_POP
 
 //---------------------------------------------------------------------------------------------------------------------
 VBank::VBank()
-    :details(QVector<VLayoutDetail>()), unsorted(QHash<int, qint64>()), big(QHash<int, qint64>()),
+    :details(QVector<VLayoutPiece>()), unsorted(QHash<int, qint64>()), big(QHash<int, qint64>()),
       middle(QHash<int, qint64>()), small(QHash<int, qint64>()), layoutWidth(0), caseType(Cases::CaseDesc),
       prepare(false), diagonal(0)
 {}
@@ -71,7 +71,7 @@ void VBank::SetLayoutWidth(const qreal &value)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VBank::SetDetails(const QVector<VLayoutDetail> &details)
+void VBank::SetDetails(const QVector<VLayoutPiece> &details)
 {
     this->details = details;
     Reset();
@@ -111,7 +111,7 @@ int VBank::GetTiket()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail VBank::GetDetail(int i) const
+VLayoutPiece VBank::GetDetail(int i) const
 {
     if (i >= 0 && i < details.size())
     {
@@ -119,7 +119,7 @@ VLayoutDetail VBank::GetDetail(int i) const
     }
     else
     {
-        return VLayoutDetail();
+        return VLayoutPiece();
     }
 }
 
diff --git a/src/libs/vlayout/vbank.h b/src/libs/vlayout/vbank.h
index 51cd7e312..340f034d2 100644
--- a/src/libs/vlayout/vbank.h
+++ b/src/libs/vlayout/vbank.h
@@ -43,7 +43,7 @@
 #endif
 
 class QPointF;
-class VLayoutDetail;
+class VLayoutPiece;
 
 enum class Cases : char { CaseThreeGroup = 0, CaseTwoGroup, CaseDesc, UnknownCase};
 
@@ -55,9 +55,9 @@ public:
     qreal GetLayoutWidth() const;
     void SetLayoutWidth(const qreal &value);
 
-    void SetDetails(const QVector<VLayoutDetail> &details);
+    void SetDetails(const QVector<VLayoutPiece> &details);
     int  GetTiket();
-    VLayoutDetail GetDetail(int i) const;
+    VLayoutPiece GetDetail(int i) const;
 
     void Arranged(int i);
     void NotArranged(int i);
@@ -74,7 +74,7 @@ public:
 
 private:
     Q_DISABLE_COPY(VBank)
-    QVector<VLayoutDetail> details;
+    QVector<VLayoutPiece> details;
     QHash<int, qint64> unsorted;
 
     QHash<int, qint64> big;
diff --git a/src/libs/vlayout/vcontour.cpp b/src/libs/vlayout/vcontour.cpp
index 03ae18dee..da72142cb 100644
--- a/src/libs/vlayout/vcontour.cpp
+++ b/src/libs/vlayout/vcontour.cpp
@@ -37,7 +37,7 @@
 #include <Qt>
 
 #include "vcontour_p.h"
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 #include "../vmisc/vmath.h"
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -125,7 +125,7 @@ QSizeF VContour::GetSize() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VContour::UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ, BestFrom type) const
+QVector<QPointF> VContour::UniteWithContour(const VLayoutPiece &detail, int globalI, int detJ, BestFrom type) const
 {
     QVector<QPointF> newContour;
     if (d->globalContour.isEmpty()) //-V807
@@ -333,7 +333,7 @@ QPainterPath VContour::ContourPath() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VContour::AppendWhole(QVector<QPointF> &contour, const VLayoutDetail &detail, int detJ) const
+void VContour::AppendWhole(QVector<QPointF> &contour, const VLayoutPiece &detail, int detJ) const
 {
     int processedEdges = 0;
     const int nD = detail.LayoutEdgesCount();
diff --git a/src/libs/vlayout/vcontour.h b/src/libs/vlayout/vcontour.h
index baa64f963..cfa622da4 100644
--- a/src/libs/vlayout/vcontour.h
+++ b/src/libs/vlayout/vcontour.h
@@ -43,7 +43,7 @@ class QPointF;
 class QRectF;
 class QSizeF;
 class VContourData;
-class VLayoutDetail;
+class VLayoutPiece;
 
 class VContour
 {
@@ -68,7 +68,7 @@ public:
 
     QSizeF GetSize() const;
 
-    QVector<QPointF> UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ, BestFrom type) const;
+    QVector<QPointF> UniteWithContour(const VLayoutPiece &detail, int globalI, int detJ, BestFrom type) const;
 
     QLineF EmptySheetEdge() const;
     int    GlobalEdgesCount() const;
@@ -85,7 +85,7 @@ public:
 private:
     QSharedDataPointer<VContourData> d;
 
-    void AppendWhole(QVector<QPointF> &contour, const VLayoutDetail &detail, int detJ) const;
+    void AppendWhole(QVector<QPointF> &contour, const VLayoutPiece &detail, int detJ) const;
 };
 
 Q_DECLARE_TYPEINFO(VContour, Q_MOVABLE_TYPE);
diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri
index 29ef87f7c..1ed0558d0 100644
--- a/src/libs/vlayout/vlayout.pri
+++ b/src/libs/vlayout/vlayout.pri
@@ -4,10 +4,8 @@
 HEADERS += \
     $$PWD/stable.h \
     $$PWD/vlayoutgenerator.h \
-    $$PWD/vlayoutdetail.h \
     $$PWD/vabstractdetail.h \
     $$PWD/vabstractdetail_p.h \
-    $$PWD/vlayoutdetail_p.h \
     $$PWD/vlayoutdef.h \
     $$PWD/vlayoutpaper.h \
     $$PWD/vlayoutpaper_p.h \
@@ -20,11 +18,12 @@ HEADERS += \
     $$PWD/vposter.h \
     $$PWD/vgraphicsfillitem.h \
     $$PWD/vabstractpiece.h \
-    $$PWD/vabstractpiece_p.h
+    $$PWD/vabstractpiece_p.h \
+    $$PWD/vlayoutpiece.h \
+    $$PWD/vlayoutpiece_p.h
 
 SOURCES += \
     $$PWD/vlayoutgenerator.cpp \
-    $$PWD/vlayoutdetail.cpp \
     $$PWD/vabstractdetail.cpp \
     $$PWD/vlayoutpaper.cpp \
     $$PWD/vbank.cpp \
@@ -34,6 +33,7 @@ SOURCES += \
     $$PWD/vtextmanager.cpp \
     $$PWD/vposter.cpp \
     $$PWD/vgraphicsfillitem.cpp \
-    $$PWD/vabstractpiece.cpp
+    $$PWD/vabstractpiece.cpp \
+    $$PWD/vlayoutpiece.cpp
 
 win32-msvc*:SOURCES += $$PWD/stable.cpp
diff --git a/src/libs/vlayout/vlayoutgenerator.cpp b/src/libs/vlayout/vlayoutgenerator.cpp
index cc374eed7..0117f04ee 100644
--- a/src/libs/vlayout/vlayoutgenerator.cpp
+++ b/src/libs/vlayout/vlayoutgenerator.cpp
@@ -34,7 +34,7 @@
 
 #include "../vmisc/def.h"
 #include "../vmisc/vmath.h"
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 #include "vlayoutpaper.h"
 
 class QMarginsF;
@@ -54,7 +54,7 @@ VLayoutGenerator::~VLayoutGenerator()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutGenerator::SetDetails(const QVector<VLayoutDetail> &details)
+void VLayoutGenerator::SetDetails(const QVector<VLayoutPiece> &details)
 {
     bank->SetDetails(details);
 }
@@ -273,7 +273,7 @@ void VLayoutGenerator::GatherPages()
         return;
     }
 
-    QList<QList<VLayoutDetail>> nDetails;
+    QList<QList<VLayoutPiece>> nDetails;
     qreal length = 0;
     int j = 0; // papers count
 
@@ -328,7 +328,7 @@ void VLayoutGenerator::UnitePages()
     }
 
     QList<qreal> papersLength;
-    QList<QList<VLayoutDetail> > nDetails;
+    QList<QList<VLayoutPiece> > nDetails;
     qreal length = 0;
     int j = 0; // papers count
 
@@ -385,7 +385,7 @@ void VLayoutGenerator::UnitePages()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutGenerator::UniteDetails(int j, QList<QList<VLayoutDetail> > &nDetails, qreal length, int i)
+void VLayoutGenerator::UniteDetails(int j, QList<QList<VLayoutPiece> > &nDetails, qreal length, int i)
 {
     if ((j == 0 && nDetails.isEmpty()) || j >= nDetails.size())
     {//First or new details in paper
@@ -411,17 +411,17 @@ void VLayoutGenerator::UnitePapers(int j, QList<qreal> &papersLength, qreal leng
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QList<VLayoutDetail> VLayoutGenerator::MoveDetails(qreal length, const QVector<VLayoutDetail> &details)
+QList<VLayoutPiece> VLayoutGenerator::MoveDetails(qreal length, const QVector<VLayoutPiece> &details)
 {
     if (qFuzzyIsNull(length))
     {
         return details.toList();
     }
 
-    QList<VLayoutDetail> newDetails;
+    QList<VLayoutPiece> newDetails;
     for (int i = 0; i < details.size(); ++i)
     {
-        VLayoutDetail d = details.at(i);
+        VLayoutPiece d = details.at(i);
         d.Translate(0, length);
         newDetails.append(d);
     }
diff --git a/src/libs/vlayout/vlayoutgenerator.h b/src/libs/vlayout/vlayoutgenerator.h
index 90caa59bd..822e35658 100644
--- a/src/libs/vlayout/vlayoutgenerator.h
+++ b/src/libs/vlayout/vlayoutgenerator.h
@@ -50,7 +50,7 @@ class QMarginsF;
 #endif
 
 class QGraphicsItem;
-class VLayoutDetail;
+class VLayoutPiece;
 class VLayoutPaper;
 
 class VLayoutGenerator :public QObject
@@ -60,7 +60,7 @@ public:
     explicit VLayoutGenerator(QObject *parent = nullptr);
     virtual ~VLayoutGenerator() Q_DECL_OVERRIDE;
 
-    void SetDetails(const QVector<VLayoutDetail> &details);
+    void SetDetails(const QVector<VLayoutPiece> &details);
     void SetLayoutWidth(qreal width);
     void SetCaseType(Cases caseType);
     int DetailsCount();
@@ -140,9 +140,9 @@ private:
 
     void GatherPages();
     void UnitePages();
-    void UniteDetails(int j, QList<QList<VLayoutDetail> > &nDetails, qreal length, int i);
+    void UniteDetails(int j, QList<QList<VLayoutPiece> > &nDetails, qreal length, int i);
     void UnitePapers(int j, QList<qreal> &papersLength, qreal length);
-    QList<VLayoutDetail> MoveDetails(qreal length, const QVector<VLayoutDetail> &details);
+    QList<VLayoutPiece> MoveDetails(qreal length, const QVector<VLayoutPiece> &details);
 };
 
 typedef std::shared_ptr<VLayoutGenerator> VLayoutGeneratorPtr;
diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp
index 6422faeea..890c6dea4 100644
--- a/src/libs/vlayout/vlayoutpaper.cpp
+++ b/src/libs/vlayout/vlayoutpaper.cpp
@@ -45,7 +45,7 @@
 
 #include "vbestsquare.h"
 #include "vcontour.h"
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 #include "vlayoutpaper_p.h"
 #include "vposition.h"
 
@@ -185,7 +185,7 @@ void VLayoutPaper::SetPaperIndex(quint32 index)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VLayoutPaper::ArrangeDetail(const VLayoutDetail &detail, volatile bool &stop)
+bool VLayoutPaper::ArrangeDetail(const VLayoutPiece &detail, volatile bool &stop)
 {
     // First need set size of paper
     if (d->globalContour.GetHeight() <= 0 || d->globalContour.GetWidth() <= 0)
@@ -221,7 +221,7 @@ int VLayoutPaper::Count() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VLayoutPaper::AddToSheet(const VLayoutDetail &detail, volatile bool &stop)
+bool VLayoutPaper::AddToSheet(const VLayoutPiece &detail, volatile bool &stop)
 {
     VBestSquare bestResult(d->globalContour.GetSize(), d->saveLength);
     QThreadPool *thread_pool = QThreadPool::globalInstance();
@@ -289,11 +289,11 @@ bool VLayoutPaper::AddToSheet(const VLayoutDetail &detail, volatile bool &stop)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutDetail &detail)
+bool VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail)
 {
     if (bestResult.ValidResult())
     {
-        VLayoutDetail workDetail = detail;
+        VLayoutPiece workDetail = detail;
         workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix
         workDetail.SetMirror(bestResult.Mirror());
         const QVector<QPointF> newGContour = d->globalContour.UniteWithContour(workDetail, bestResult.GContourEdge(),
@@ -369,13 +369,13 @@ QList<QGraphicsItem *> VLayoutPaper::GetItemDetails() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<VLayoutDetail> VLayoutPaper::GetDetails() const
+QVector<VLayoutPiece> VLayoutPaper::GetDetails() const
 {
     return d->details;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutPaper::SetDetails(const QList<VLayoutDetail> &details)
+void VLayoutPaper::SetDetails(const QList<VLayoutPiece> &details)
 {
     d->details = details.toVector();
 }
diff --git a/src/libs/vlayout/vlayoutpaper.h b/src/libs/vlayout/vlayoutpaper.h
index 8c48a076d..7a28b8d74 100644
--- a/src/libs/vlayout/vlayoutpaper.h
+++ b/src/libs/vlayout/vlayoutpaper.h
@@ -40,7 +40,7 @@ class QGraphicsItem;
 class QGraphicsRectItem;
 class QRectF;
 class VBestSquare;
-class VLayoutDetail;
+class VLayoutPiece;
 class VLayoutPaperData;
 template <typename T> class QList;
 template <typename T> class QVector;
@@ -77,22 +77,22 @@ public:
 
     void SetPaperIndex(quint32 index);
 
-    bool ArrangeDetail(const VLayoutDetail &detail, volatile bool &stop);
+    bool ArrangeDetail(const VLayoutPiece &detail, volatile bool &stop);
     int  Count() const;
     QGraphicsRectItem *GetPaperItem(bool autoCrop) const Q_REQUIRED_RESULT;
     QList<QGraphicsItem *> GetItemDetails() const Q_REQUIRED_RESULT;
 
-    QVector<VLayoutDetail> GetDetails() const;
-    void                   SetDetails(const QList<VLayoutDetail>& details);
+    QVector<VLayoutPiece> GetDetails() const;
+    void                   SetDetails(const QList<VLayoutPiece>& details);
 
     QRectF DetailsBoundingRect() const;
 
 private:
     QSharedDataPointer<VLayoutPaperData> d;
 
-    bool AddToSheet(const VLayoutDetail &detail, volatile bool &stop);
+    bool AddToSheet(const VLayoutPiece &detail, volatile bool &stop);
 
-    bool SaveResult(const VBestSquare &bestResult, const VLayoutDetail &detail);
+    bool SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail);
 
 };
 
diff --git a/src/libs/vlayout/vlayoutpaper_p.h b/src/libs/vlayout/vlayoutpaper_p.h
index 34ec699bf..81acb7a45 100644
--- a/src/libs/vlayout/vlayoutpaper_p.h
+++ b/src/libs/vlayout/vlayoutpaper_p.h
@@ -33,7 +33,7 @@
 #include <QVector>
 #include <QPointF>
 
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 #include "vcontour.h"
 
 QT_WARNING_PUSH
@@ -43,7 +43,7 @@ class VLayoutPaperData : public QSharedData
 {
 public:
     VLayoutPaperData()
-        : details(QVector<VLayoutDetail>()),
+        : details(QVector<VLayoutPiece>()),
           globalContour(VContour()),
           paperIndex(0),
           frame(0),
@@ -57,7 +57,7 @@ public:
 
     VLayoutPaperData(int height,
                      int width)
-        : details(QVector<VLayoutDetail>()),
+        : details(QVector<VLayoutPiece>()),
           globalContour(VContour(height, width)),
           paperIndex(0),
           frame(0),
@@ -86,7 +86,7 @@ public:
     ~VLayoutPaperData() {}
 
     /** @brief details list of arranged details. */
-    QVector<VLayoutDetail> details;
+    QVector<VLayoutPiece> details;
 
     /** @brief globalContour list of global points contour. */
     VContour globalContour;
diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutpiece.cpp
similarity index 89%
rename from src/libs/vlayout/vlayoutdetail.cpp
rename to src/libs/vlayout/vlayoutpiece.cpp
index da6ff54a0..29c1235e2 100644
--- a/src/libs/vlayout/vlayoutdetail.cpp
+++ b/src/libs/vlayout/vlayoutpiece.cpp
@@ -26,7 +26,7 @@
  **
  *************************************************************************/
 
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 
 #include <QBrush>
 #include <QFlags>
@@ -49,7 +49,7 @@
 #include "../vmisc/vabstractapplication.h"
 #include "../vpatterndb/calculator.h"
 #include "vlayoutdef.h"
-#include "vlayoutdetail_p.h"
+#include "vlayoutpiece_p.h"
 #include "vtextmanager.h"
 #include "vgraphicsfillitem.h"
 
@@ -58,17 +58,17 @@ class QLineF;
 class VAbstractPattern;
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail::VLayoutDetail()
-    :VAbstractPiece(), d(new VLayoutDetailData)
+VLayoutPiece::VLayoutPiece()
+    :VAbstractPiece(), d(new VLayoutPieceData)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail::VLayoutDetail(const VLayoutDetail &detail)
+VLayoutPiece::VLayoutPiece(const VLayoutPiece &detail)
     :VAbstractPiece(detail), d(detail.d)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail &VLayoutDetail::operator=(const VLayoutDetail &detail)
+VLayoutPiece &VLayoutPiece::operator=(const VLayoutPiece &detail)
 {
     if ( &detail == this )
     {
@@ -80,13 +80,13 @@ VLayoutDetail &VLayoutDetail::operator=(const VLayoutDetail &detail)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail::~VLayoutDetail()
+VLayoutPiece::~VLayoutPiece()
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
-VLayoutDetail VLayoutDetail::Create(const VPiece &piece, const VContainer *pattern)
+VLayoutPiece VLayoutPiece::Create(const VPiece &piece, const VContainer *pattern)
 {
-    VLayoutDetail det = VLayoutDetail();
+    VLayoutPiece det = VLayoutPiece();
     det.SetCountourPoints(piece.MainPathPoints(pattern));
     det.SetSeamAllowencePoints(piece.SeamAllowancePoints(pattern), piece.IsSeamAllowance());
     det.SetName(piece.GetName());
@@ -120,26 +120,26 @@ VLayoutDetail VLayoutDetail::Create(const VPiece &piece, const VContainer *patte
 
 //---------------------------------------------------------------------------------------------------------------------
 // cppcheck-suppress unusedFunction
-QVector<QPointF> VLayoutDetail::GetContourPoints() const
+QVector<QPointF> VLayoutPiece::GetContourPoints() const
 {
     return Map(d->contour);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetCountourPoints(const QVector<QPointF> &points)
+void VLayoutPiece::SetCountourPoints(const QVector<QPointF> &points)
 {
     d->contour = RemoveDublicates(RoundPoints(points));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 // cppcheck-suppress unusedFunction
-QVector<QPointF> VLayoutDetail::GetSeamAllowencePoints() const
+QVector<QPointF> VLayoutPiece::GetSeamAllowencePoints() const
 {
     return Map(d->seamAllowence);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence)
+void VLayoutPiece::SetSeamAllowencePoints(const QVector<QPointF> &points, bool seamAllowence)
 {
     if (seamAllowence)
     {
@@ -158,13 +158,13 @@ void VLayoutDetail::SetSeamAllowencePoints(const QVector<QPointF> &points, bool
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VLayoutDetail::GetLayoutAllowencePoints() const
+QVector<QPointF> VLayoutPiece::GetLayoutAllowencePoints() const
 {
     return Map(d->layoutAllowence);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetDetail(const QString& qsName, const VPatternPieceData& data, const QFont &font)
+void VLayoutPiece::SetDetail(const QString& qsName, const VPatternPieceData& data, const QFont &font)
 {
     d->detailData = data;
     qreal dAng = qDegreesToRadians(data.GetRotation());
@@ -190,7 +190,7 @@ void VLayoutDetail::SetDetail(const QString& qsName, const VPatternPieceData& da
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetPatternInfo(const VAbstractPattern* pDoc, const VPatternInfoGeometry& geom, const QFont &font,
+void VLayoutPiece::SetPatternInfo(const VAbstractPattern* pDoc, const VPatternInfoGeometry& geom, const QFont &font,
                                    qreal dSize, qreal dHeight)
 {
     d->patternGeom = geom;
@@ -219,7 +219,7 @@ void VLayoutDetail::SetPatternInfo(const VAbstractPattern* pDoc, const VPatternI
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetGrainline(const VGrainlineGeometry& geom, const VContainer& rPattern)
+void VLayoutPiece::SetGrainline(const VGrainlineGeometry& geom, const VContainer& rPattern)
 {
     d->grainlineGeom = geom;
     qreal dAng;
@@ -286,31 +286,31 @@ void VLayoutDetail::SetGrainline(const VGrainlineGeometry& geom, const VContaine
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QTransform VLayoutDetail::GetMatrix() const
+QTransform VLayoutPiece::GetMatrix() const
 {
     return d->matrix;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetMatrix(const QTransform &matrix)
+void VLayoutPiece::SetMatrix(const QTransform &matrix)
 {
     d->matrix = matrix;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VLayoutDetail::GetLayoutWidth() const
+qreal VLayoutPiece::GetLayoutWidth() const
 {
     return d->layoutWidth;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetLayoutWidth(const qreal &value)
+void VLayoutPiece::SetLayoutWidth(const qreal &value)
 {
     d->layoutWidth = value;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::Translate(qreal dx, qreal dy)
+void VLayoutPiece::Translate(qreal dx, qreal dy)
 {
     QTransform m;
     m.translate(dx, dy);
@@ -318,7 +318,7 @@ void VLayoutDetail::Translate(qreal dx, qreal dy)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::Rotate(const QPointF &originPoint, qreal degrees)
+void VLayoutPiece::Rotate(const QPointF &originPoint, qreal degrees)
 {
     QTransform m;
     m.translate(originPoint.x(), originPoint.y());
@@ -328,7 +328,7 @@ void VLayoutDetail::Rotate(const QPointF &originPoint, qreal degrees)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::Mirror(const QLineF &edge)
+void VLayoutPiece::Mirror(const QLineF &edge)
 {
     if (edge.isNull())
     {
@@ -361,43 +361,43 @@ void VLayoutDetail::Mirror(const QLineF &edge)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::DetailEdgesCount() const
+int VLayoutPiece::DetailEdgesCount() const
 {
     return DetailPath().count();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::LayoutEdgesCount() const
+int VLayoutPiece::LayoutEdgesCount() const
 {
     return d->layoutAllowence.count();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QLineF VLayoutDetail::DetailEdge(int i) const
+QLineF VLayoutPiece::DetailEdge(int i) const
 {
     return Edge(DetailPath(), i);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QLineF VLayoutDetail::LayoutEdge(int i) const
+QLineF VLayoutPiece::LayoutEdge(int i) const
 {
     return Edge(d->layoutAllowence, i);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::DetailEdgeByPoint(const QPointF &p1) const
+int VLayoutPiece::DetailEdgeByPoint(const QPointF &p1) const
 {
     return EdgeByPoint(DetailPath(), p1);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::LayoutEdgeByPoint(const QPointF &p1) const
+int VLayoutPiece::LayoutEdgeByPoint(const QPointF &p1) const
 {
     return EdgeByPoint(d->layoutAllowence, p1);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QRectF VLayoutDetail::DetailBoundingRect() const
+QRectF VLayoutPiece::DetailBoundingRect() const
 {
     QVector<QPointF> points;
     if (IsSeamAllowance())
@@ -414,7 +414,7 @@ QRectF VLayoutDetail::DetailBoundingRect() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QRectF VLayoutDetail::LayoutBoundingRect() const
+QRectF VLayoutPiece::LayoutBoundingRect() const
 {
     QVector<QPointF> points = GetLayoutAllowencePoints();
     points.append(points.first());
@@ -422,14 +422,14 @@ QRectF VLayoutDetail::LayoutBoundingRect() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qreal VLayoutDetail::Diagonal() const
+qreal VLayoutPiece::Diagonal() const
 {
     const QRectF rec = LayoutBoundingRect();
     return qSqrt(pow(rec.height(), 2) + pow(rec.width(), 2));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VLayoutDetail::isNull() const
+bool VLayoutPiece::isNull() const
 {
     if (d->contour.isEmpty() == false && d->layoutWidth > 0)
     {
@@ -449,7 +449,7 @@ bool VLayoutDetail::isNull() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-qint64 VLayoutDetail::Square() const
+qint64 VLayoutPiece::Square() const
 {
     if (d->layoutAllowence.isEmpty()) //-V807
     {
@@ -463,7 +463,7 @@ qint64 VLayoutDetail::Square() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetLayoutAllowencePoints()
+void VLayoutPiece::SetLayoutAllowencePoints()
 {
     if (d->layoutWidth > 0)
     {
@@ -499,7 +499,7 @@ void VLayoutDetail::SetLayoutAllowencePoints()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VLayoutDetail::Map(const QVector<QPointF> &points) const
+QVector<QPointF> VLayoutPiece::Map(const QVector<QPointF> &points) const
 {
     QVector<QPointF> p;
     for (int i = 0; i < points.size(); ++i)
@@ -520,7 +520,7 @@ QVector<QPointF> VLayoutDetail::Map(const QVector<QPointF> &points) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VLayoutDetail::RoundPoints(const QVector<QPointF> &points)
+QVector<QPointF> VLayoutPiece::RoundPoints(const QVector<QPointF> &points)
 {
     QVector<QPointF> p;
     for (int i=0; i < points.size(); ++i)
@@ -531,7 +531,7 @@ QVector<QPointF> VLayoutDetail::RoundPoints(const QVector<QPointF> &points)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPainterPath VLayoutDetail::ContourPath() const
+QPainterPath VLayoutPiece::ContourPath() const
 {
     QPainterPath path;
 
@@ -569,13 +569,13 @@ QPainterPath VLayoutDetail::ContourPath() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::ClearTextItems()
+void VLayoutPiece::ClearTextItems()
 {
     d->m_liPP.clear();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::CreateTextItems()
+void VLayoutPiece::CreateTextItems()
 {
     ClearTextItems();
     // first add detail texts
@@ -696,7 +696,7 @@ void VLayoutDetail::CreateTextItems()
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::GetTextItemsCount() const
+int VLayoutPiece::GetTextItemsCount() const
 {
     return d->m_liPP.count();
 }
@@ -707,7 +707,7 @@ int VLayoutDetail::GetTextItemsCount() const
  * @param i index of the requested item
  * @return pointer to the newly created item. The caller is responsible to delete it.
  */
-QGraphicsItem* VLayoutDetail::GetTextItem(int i) const
+QGraphicsItem* VLayoutPiece::GetTextItem(int i) const
 {
     QGraphicsPathItem* item = new QGraphicsPathItem();
     QTransform transform = d->matrix;
@@ -751,7 +751,7 @@ QGraphicsItem* VLayoutDetail::GetTextItem(int i) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPainterPath VLayoutDetail::LayoutAllowencePath() const
+QPainterPath VLayoutPiece::LayoutAllowencePath() const
 {
     QPainterPath path;
     path.setFillRule(Qt::WindingFill);
@@ -768,7 +768,7 @@ QPainterPath VLayoutDetail::LayoutAllowencePath() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QGraphicsItem *VLayoutDetail::GetItem() const
+QGraphicsItem *VLayoutPiece::GetItem() const
 {
     QGraphicsPathItem *item = new QGraphicsPathItem();
     item->setPath(ContourPath());
@@ -776,7 +776,7 @@ QGraphicsItem *VLayoutDetail::GetItem() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QGraphicsItem* VLayoutDetail::GetGrainlineItem() const
+QGraphicsItem* VLayoutPiece::GetGrainlineItem() const
 {
     if (d->grainlinePoints.count() < 2)
     {
@@ -795,7 +795,7 @@ QGraphicsItem* VLayoutDetail::GetGrainlineItem() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VLayoutDetail::DetailPath() const
+QVector<QPointF> VLayoutPiece::DetailPath() const
 {
     if (IsSeamAllowance())
     {
@@ -808,7 +808,7 @@ QVector<QPointF> VLayoutDetail::DetailPath() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<VSAPoint> VLayoutDetail::PrepareAllowance(const QVector<QPointF> &points)
+QVector<VSAPoint> VLayoutPiece::PrepareAllowance(const QVector<QPointF> &points)
 {
     QVector<VSAPoint> allowancePoints;
     for(int i = 0; i < points.size(); +i)
@@ -819,13 +819,13 @@ QVector<VSAPoint> VLayoutDetail::PrepareAllowance(const QVector<QPointF> &points
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VLayoutDetail::IsMirror() const
+bool VLayoutPiece::IsMirror() const
 {
     return d->mirror;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VLayoutDetail::SetMirror(bool value)
+void VLayoutPiece::SetMirror(bool value)
 {
     d->mirror = value;
 }
@@ -838,7 +838,7 @@ void VLayoutDetail::SetMirror(bool value)
  * @param dAng angle of rotation
  * @return position of point pt after rotating it around the center for dAng radians
  */
-QPointF VLayoutDetail::RotatePoint(const QPointF &ptCenter, const QPointF& pt, qreal dAng)
+QPointF VLayoutPiece::RotatePoint(const QPointF &ptCenter, const QPointF& pt, qreal dAng)
 {
     QPointF ptDest;
     QPointF ptRel = pt - ptCenter;
@@ -855,7 +855,7 @@ QPointF VLayoutDetail::RotatePoint(const QPointF &ptCenter, const QPointF& pt, q
  * @param points list of 4 label vertices
  * @return list of flipped points
  */
-QVector<QPointF> VLayoutDetail::Mirror(const QVector<QPointF> &points) const
+QVector<QPointF> VLayoutPiece::Mirror(const QVector<QPointF> &points) const
 {
     // should only call this method with rectangular shapes
     Q_ASSERT(points.count() == 4);
@@ -880,7 +880,7 @@ QVector<QPointF> VLayoutDetail::Mirror(const QVector<QPointF> &points) const
  * @param pt2 second point
  * @return Euclidian distance between the two points
  */
-qreal VLayoutDetail::GetDistance(const QPointF &pt1, const QPointF &pt2)
+qreal VLayoutPiece::GetDistance(const QPointF &pt1, const QPointF &pt2)
 {
     const qreal dX = pt1.x() - pt2.x();
     const qreal dY = pt1.y() - pt2.y();
@@ -889,7 +889,7 @@ qreal VLayoutDetail::GetDistance(const QPointF &pt1, const QPointF &pt2)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QLineF VLayoutDetail::Edge(const QVector<QPointF> &path, int i) const
+QLineF VLayoutPiece::Edge(const QVector<QPointF> &path, int i) const
 {
     if (i < 1 || i > path.count())
     { // Doesn't exist such edge
@@ -923,7 +923,7 @@ QLineF VLayoutDetail::Edge(const QVector<QPointF> &path, int i) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-int VLayoutDetail::EdgeByPoint(const QVector<QPointF> &path, const QPointF &p1) const
+int VLayoutPiece::EdgeByPoint(const QVector<QPointF> &path, const QPointF &p1) const
 {
     if (p1.isNull())
     {
diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutpiece.h
similarity index 91%
rename from src/libs/vlayout/vlayoutdetail.h
rename to src/libs/vlayout/vlayoutpiece.h
index 138f65184..63a46a9db 100644
--- a/src/libs/vlayout/vlayoutdetail.h
+++ b/src/libs/vlayout/vlayoutpiece.h
@@ -55,20 +55,20 @@ class QPointF;
 class QRectF;
 class QTransform;
 class VAbstractPattern;
-class VLayoutDetailData;
+class VLayoutPieceData;
 class VPatternInfoGeometry;
 class VPatternPieceData;
 class VGrainlineGeometry;
 
-class VLayoutDetail :public VAbstractPiece
+class VLayoutPiece :public VAbstractPiece
 {
 public:
-    VLayoutDetail();
-    VLayoutDetail(const VLayoutDetail &detail);
-    VLayoutDetail &operator=(const VLayoutDetail &detail);
-    virtual ~VLayoutDetail() Q_DECL_OVERRIDE;
+    VLayoutPiece();
+    VLayoutPiece(const VLayoutPiece &detail);
+    VLayoutPiece &operator=(const VLayoutPiece &detail);
+    virtual ~VLayoutPiece() Q_DECL_OVERRIDE;
 
-    static VLayoutDetail Create(const VPiece &piece, const VContainer *pattern);
+    static VLayoutPiece Create(const VPiece &piece, const VContainer *pattern);
 
     QVector<QPointF> GetContourPoints() const;
     void SetCountourPoints(const QVector<QPointF> &points);
@@ -124,7 +124,7 @@ public:
     QGraphicsItem* GetGrainlineItem() const Q_REQUIRED_RESULT;
 
 private:
-    QSharedDataPointer<VLayoutDetailData>   d;
+    QSharedDataPointer<VLayoutPieceData>   d;
 
     QVector<QPointF> DetailPath() const;
 
@@ -140,6 +140,6 @@ private:
     int    EdgeByPoint(const QVector<QPointF> &path, const QPointF &p1) const;
 };
 
-Q_DECLARE_TYPEINFO(VLayoutDetail, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(VLayoutPiece, Q_MOVABLE_TYPE);
 
 #endif // VLAYOUTDETAIL_H
diff --git a/src/libs/vlayout/vlayoutdetail_p.h b/src/libs/vlayout/vlayoutpiece_p.h
similarity index 94%
rename from src/libs/vlayout/vlayoutdetail_p.h
rename to src/libs/vlayout/vlayoutpiece_p.h
index 289af3275..76a5b1cff 100644
--- a/src/libs/vlayout/vlayoutdetail_p.h
+++ b/src/libs/vlayout/vlayoutpiece_p.h
@@ -43,17 +43,17 @@
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_GCC("-Weffc++")
 
-class VLayoutDetailData : public QSharedData
+class VLayoutPieceData : public QSharedData
 {
 public:
-    VLayoutDetailData()
+    VLayoutPieceData()
         :contour(QVector<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()),
           matrix(QMatrix()), layoutWidth(0), mirror(false), detailLabel(QVector<QPointF>()),
           patternInfo(QVector<QPointF>()), grainlinePoints(QVector<QPointF>()), detailData(), patternGeom(),
           grainlineGeom(), m_tmDetail(), m_tmPattern(), m_liPP(QList<QPainterPath>())
     {}
 
-    VLayoutDetailData(const VLayoutDetailData &detail)
+    VLayoutPieceData(const VLayoutPieceData &detail)
         :QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence),
           layoutAllowence(detail.layoutAllowence), matrix(detail.matrix),
           layoutWidth(detail.layoutWidth), mirror(detail.mirror), detailLabel(detail.detailLabel),
@@ -62,7 +62,7 @@ public:
           m_tmPattern(detail.m_tmPattern), m_liPP(detail.m_liPP)
     {}
 
-    ~VLayoutDetailData() {}
+    ~VLayoutPieceData() {}
 
     /** @brief contour list of contour points. */
     QVector<QPointF>                        contour;
@@ -101,7 +101,7 @@ public:
     QList<QPainterPath>                     m_liPP;
 
 private:
-    VLayoutDetailData &operator=(const VLayoutDetailData &) Q_DECL_EQ_DELETE;
+    VLayoutPieceData &operator=(const VLayoutPieceData &) Q_DECL_EQ_DELETE;
 };
 
 QT_WARNING_POP
diff --git a/src/libs/vlayout/vposition.cpp b/src/libs/vlayout/vposition.cpp
index 6524dddb6..cbe25ef01 100644
--- a/src/libs/vlayout/vposition.cpp
+++ b/src/libs/vlayout/vposition.cpp
@@ -50,10 +50,10 @@
 #include "../vmisc/vmath.h"
 
 //---------------------------------------------------------------------------------------------------------------------
-VPosition::VPosition(const VContour &gContour, int j, const VLayoutDetail &detail, int i, volatile bool *stop,
+VPosition::VPosition(const VContour &gContour, int j, const VLayoutPiece &detail, int i, volatile bool *stop,
                      bool rotate, int rotationIncrease, bool saveLength)
     :QRunnable(), bestResult(VBestSquare(gContour.GetSize(), saveLength)), gContour(gContour), detail(detail), i(i),
-      j(j), paperIndex(0), frame(0), detailsCount(0), details(QVector<VLayoutDetail>()), stop(stop), rotate(rotate),
+      j(j), paperIndex(0), frame(0), detailsCount(0), details(QVector<VLayoutPiece>()), stop(stop), rotate(rotate),
       rotationIncrease(rotationIncrease), angle_between(0)
 {
     if ((rotationIncrease >= 1 && rotationIncrease <= 180 && 360 % rotationIncrease == 0) == false)
@@ -71,7 +71,7 @@ void VPosition::run()
     }
 
     // We should use copy of the detail.
-    VLayoutDetail workDetail = detail;
+    VLayoutPiece workDetail = detail;
 
     int dEdge = i;// For mirror detail edge will be different
     if (CheckCombineEdges(workDetail, j, dEdge))
@@ -139,7 +139,7 @@ void VPosition::setDetailsCount(const quint32 &value)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPosition::setDetails(const QVector<VLayoutDetail> &details)
+void VPosition::setDetails(const QVector<VLayoutPiece> &details)
 {
     this->details = details;
 }
@@ -151,8 +151,8 @@ VBestSquare VPosition::getBestResult() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPosition::DrawDebug(const VContour &contour, const VLayoutDetail &detail, int frame, quint32 paperIndex,
-                          int detailsCount, const QVector<VLayoutDetail> &details)
+void VPosition::DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex,
+                          int detailsCount, const QVector<VLayoutPiece> &details)
 {
     const int biasWidth = Bias(contour.GetWidth(), QIMAGE_MAX);
     const int biasHeight = Bias(contour.GetHeight(), QIMAGE_MAX);
@@ -242,7 +242,7 @@ int VPosition::Bias(int length, int maxLength)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutDetail &detail, int globalI, int detJ,
+void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ,
                               BestFrom type)
 {
     QVector<QPointF> newGContour = gContour.UniteWithContour(detail, globalI, detJ, type);
@@ -252,7 +252,7 @@ void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutDetail &deta
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
+bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
 {
     const QLineF globalEdge = gContour.GlobalEdge(j);
     bool flagMirror = false;
@@ -340,7 +340,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const
+bool VPosition::CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, int angle) const
 {
     const QLineF globalEdge = gContour.GlobalEdge(j);
     bool flagSquare = false;
@@ -376,7 +376,7 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-VPosition::CrossingType VPosition::Crossing(const VLayoutDetail &detail) const
+VPosition::CrossingType VPosition::Crossing(const VLayoutPiece &detail) const
 {
     const QRectF gRect = gContour.BoundingRect();
     if (not gRect.intersects(detail.LayoutBoundingRect()) && not gRect.contains(detail.DetailBoundingRect()))
@@ -404,7 +404,7 @@ bool VPosition::SheetContains(const QRectF &rect) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPosition::CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge)
+void VPosition::CombineEdges(VLayoutPiece &detail, const QLineF &globalEdge, const int &dEdge)
 {
     QLineF detailEdge;
     if (gContour.GetContour().isEmpty())
@@ -433,7 +433,7 @@ void VPosition::CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, co
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPosition::RotateEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge, int angle) const
+void VPosition::RotateEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge, int angle) const
 {
     QLineF detailEdge;
     if (gContour.GetContour().isEmpty())
@@ -472,7 +472,7 @@ void VPosition::Rotate(int increase)
         }
 
         // We should use copy of the detail.
-        VLayoutDetail workDetail = detail;
+        VLayoutPiece workDetail = detail;
 
         if (CheckRotationEdges(workDetail, j, i, angle))
         {
@@ -549,7 +549,7 @@ QPainterPath VPosition::DrawContour(const QVector<QPointF> &points)
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QPainterPath VPosition::DrawDetails(const QVector<VLayoutDetail> &details)
+QPainterPath VPosition::DrawDetails(const QVector<VLayoutPiece> &details)
 {
     QPainterPath path;
     path.setFillRule(Qt::WindingFill);
diff --git a/src/libs/vlayout/vposition.h b/src/libs/vlayout/vposition.h
index 692d05d42..c607d4777 100644
--- a/src/libs/vlayout/vposition.h
+++ b/src/libs/vlayout/vposition.h
@@ -37,7 +37,7 @@
 #include "vbestsquare.h"
 #include "vcontour.h"
 #include "vlayoutdef.h"
-#include "vlayoutdetail.h"
+#include "vlayoutpiece.h"
 
 class QLineF;
 class QPainterPath;
@@ -48,7 +48,7 @@ class QRectF;
 class VPosition : public QRunnable
 {
 public:
-    VPosition(const VContour &gContour, int j, const VLayoutDetail &detail, int i, volatile bool *stop, bool rotate,
+    VPosition(const VContour &gContour, int j, const VLayoutPiece &detail, int i, volatile bool *stop, bool rotate,
               int rotationIncrease, bool saveLength);
     virtual ~VPosition() Q_DECL_OVERRIDE{}
 
@@ -61,12 +61,12 @@ public:
     quint32 getDetailsCount() const;
     void setDetailsCount(const quint32 &value);
 
-    void setDetails(const QVector<VLayoutDetail> &details);
+    void setDetails(const QVector<VLayoutPiece> &details);
 
     VBestSquare getBestResult() const;
 
-    static void DrawDebug(const VContour &contour, const VLayoutDetail &detail, int frame, quint32 paperIndex,
-                          int detailsCount, const QVector<VLayoutDetail> &details = QVector<VLayoutDetail>());
+    static void DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex,
+                          int detailsCount, const QVector<VLayoutPiece> &details = QVector<VLayoutPiece>());
 
     static int Bias(int length, int maxLength);
 
@@ -74,13 +74,13 @@ private:
     Q_DISABLE_COPY(VPosition)
     VBestSquare bestResult;
     const VContour gContour;
-    const VLayoutDetail detail;
+    const VLayoutPiece detail;
     int i;
     int j;
     quint32 paperIndex;
     quint32 frame;
     quint32 detailsCount;
-    QVector<VLayoutDetail> details;
+    QVector<VLayoutPiece> details;
     volatile bool *stop;
     bool rotate;
     int rotationIncrease;
@@ -105,20 +105,20 @@ private:
 
     virtual void run() Q_DECL_OVERRIDE;
 
-    void SaveCandidate(VBestSquare &bestResult, const VLayoutDetail &detail, int globalI, int detJ, BestFrom type);
+    void SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ, BestFrom type);
 
-    bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge);
-    bool CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const;
+    bool CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge);
+    bool CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, int angle) const;
 
-    CrossingType Crossing(const VLayoutDetail &detail) const;
+    CrossingType Crossing(const VLayoutPiece &detail) const;
     bool         SheetContains(const QRectF &rect) const;
 
-    void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge);
-    void RotateEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge, int angle) const;
+    void CombineEdges(VLayoutPiece &detail, const QLineF &globalEdge, const int &dEdge);
+    void RotateEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge, int angle) const;
 
     static QPainterPath ShowDirection(const QLineF &edge);
     static QPainterPath DrawContour(const QVector<QPointF> &points);
-    static QPainterPath DrawDetails(const QVector<VLayoutDetail> &details);
+    static QPainterPath DrawDetails(const QVector<VLayoutPiece> &details);
 
     void Rotate(int increase);
 };
diff --git a/src/test/ValentinaTest/tst_vlayoutdetail.cpp b/src/test/ValentinaTest/tst_vlayoutdetail.cpp
index cf29172ef..f440e813a 100644
--- a/src/test/ValentinaTest/tst_vlayoutdetail.cpp
+++ b/src/test/ValentinaTest/tst_vlayoutdetail.cpp
@@ -27,7 +27,7 @@
  *************************************************************************/
 
 #include "tst_vlayoutdetail.h"
-#include "../vlayout/vlayoutdetail.h"
+#include "../vlayout/vlayoutpiece.h"
 
 #include <QtDebug>
 
@@ -56,7 +56,7 @@ void TST_VLayoutDetail::Case1() const
     // See issue #304. Layout appears different than my pattern.
     // https://bitbucket.org/dismine/valentina/issue/304/layout-appears-different-than-my-pattern
 
-    VLayoutDetail det = VLayoutDetail();
+    VLayoutPiece det = VLayoutPiece();
     det.SetCountourPoints(InputPointsCase1());
 
     // Begin comparison
@@ -118,7 +118,7 @@ QVector<QPointF> TST_VLayoutDetail::OutputPointsCase1() const //-V524
 //---------------------------------------------------------------------------------------------------------------------
 void TST_VLayoutDetail::Case2() const
 {
-    VLayoutDetail det = VLayoutDetail();
+    VLayoutPiece det = VLayoutPiece();
     det.SetCountourPoints(InputPointsCase2());
 
     // Begin comparison
@@ -159,7 +159,7 @@ QVector<QPointF> TST_VLayoutDetail::OutputPointsCase2() const
 //---------------------------------------------------------------------------------------------------------------------
 void TST_VLayoutDetail::Case3() const
 {
-    VLayoutDetail det = VLayoutDetail();
+    VLayoutPiece det = VLayoutPiece();
     det.SetCountourPoints(InputPointsCase3());
 
     // Begin comparison

From fb86e6c51f78f565c3663cc5f7580f7f066f1a9e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 11:20:33 +0200
Subject: [PATCH 188/208] Remove class VAbstractDetail.

--HG--
branch : feature
---
 src/libs/vlayout/vabstractdetail.cpp          |  855 ----------
 src/libs/vlayout/vabstractdetail.h            |   98 --
 src/libs/vlayout/vabstractdetail_p.h          |   75 -
 src/libs/vlayout/vlayout.pri                  |    3 -
 src/test/ValentinaTest/ValentinaTest.pro      |    2 -
 src/test/ValentinaTest/qttestmainlambda.cpp   |    2 -
 .../ValentinaTest/tst_vabstractdetail.cpp     | 1386 -----------------
 src/test/ValentinaTest/tst_vabstractdetail.h  |   87 --
 src/test/ValentinaTest/tst_vabstractpiece.cpp | 1311 ++++++++++++++++
 src/test/ValentinaTest/tst_vabstractpiece.h   |   39 +
 src/test/ValentinaTest/tst_varc.cpp           |    4 +-
 src/test/ValentinaTest/tst_vellipticalarc.cpp |    4 +-
 12 files changed, 1354 insertions(+), 2512 deletions(-)
 delete mode 100644 src/libs/vlayout/vabstractdetail.cpp
 delete mode 100644 src/libs/vlayout/vabstractdetail.h
 delete mode 100644 src/libs/vlayout/vabstractdetail_p.h
 delete mode 100644 src/test/ValentinaTest/tst_vabstractdetail.cpp
 delete mode 100644 src/test/ValentinaTest/tst_vabstractdetail.h

diff --git a/src/libs/vlayout/vabstractdetail.cpp b/src/libs/vlayout/vabstractdetail.cpp
deleted file mode 100644
index 00372a5c2..000000000
--- a/src/libs/vlayout/vabstractdetail.cpp
+++ /dev/null
@@ -1,855 +0,0 @@
-/************************************************************************
- **
- **  @file   vabstractdetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   2 1, 2015
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "vabstractdetail.h"
-
-#include <QLine>
-#include <QLineF>
-#include <QMessageLogger>
-#include <QPainterPath>
-#include <QPoint>
-#include <QPointF>
-#include <QString>
-#include <QVector>
-#include <QtDebug>
-
-#include "../vgeometry/vgobject.h"
-#include "vabstractdetail_p.h"
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VAbstractDetail default contructor. Create empty detail.
- */
-VAbstractDetail::VAbstractDetail()
-    :d(new VAbstractDetailData)
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VAbstractDetail constructor.
- * @param name detail name.
- */
-VAbstractDetail::VAbstractDetail(const QString &name)
-    :d(new VAbstractDetailData(name))
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief VAbstractDetail copy constructor.
- * @param detail detail.
- */
-VAbstractDetail::VAbstractDetail(const VAbstractDetail &detail)
-    :d (detail.d)
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief operator = assignment operator.
- * @param detail detail.
- * @return new detail.
- */
-VAbstractDetail &VAbstractDetail::operator=(const VAbstractDetail &detail)
-{
-    if ( &detail == this )
-    {
-        return *this;
-    }
-    d = detail.d;
-    return *this;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-VAbstractDetail::~VAbstractDetail()
-{}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief Clear detail full clear.
- */
-void VAbstractDetail::Clear()
-{
-    d->name.clear();
-    d->seamAllowance = false;
-    d->closed = true;
-    d->width = 0;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getName return detail name.
- * @return name.
- */
-QString VAbstractDetail::getName() const
-{
-    return d->name;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setName set detail name.
- * @param value new name.
- */
-void VAbstractDetail::setName(const QString &value)
-{
-    d->name = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getSeamAllowance keep status for seam allowance detail.
- * @return true - need seam allowance, false - no need seam allowance.
- */
-bool VAbstractDetail::getSeamAllowance() const
-{
-    return d->seamAllowance;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setSeamAllowance set status for seam allowance detail.
- * @param value true - need seam allowance, false - no need seam allowance.
- */
-void VAbstractDetail::setSeamAllowance(bool value)
-{
-    d->seamAllowance = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getClosed keep close status for detail equdistant.
- * @return true - close equdistant, false - don't close equdistant.
- */
-bool VAbstractDetail::getClosed() const
-{
-    return d->closed;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setClosed set close status for detail equdistant.
- * @param value true - close equdistant, false - don't close equdistant.
- */
-void VAbstractDetail::setClosed(bool value)
-{
-    d->closed = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief getWidth return value detail seam allowance.
- * @return value in mm.
- */
-qreal VAbstractDetail::getWidth() const
-{
-    return d->width;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief setWidth set value detail seam allowance.
- * @param value width in mm.
- */
-void VAbstractDetail::setWidth(const qreal &value)
-{
-    d->width = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VAbstractDetail::getForbidFlipping() const
-{
-    return d->forbidFlipping;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void VAbstractDetail::setForbidFlipping(bool value)
-{
-    d->forbidFlipping = value;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VAbstractDetail::Equidistant(const QVector<QPointF> &points, const EquidistantType &eqv, qreal width)
-{
-    QVector<QPointF> ekvPoints;
-
-    if (width <= 0)
-    {
-        qDebug()<<"Width <= 0.";
-        return QVector<QPointF>();
-    }
-
-    QVector<QPointF> p = CorrectEquidistantPoints(points);
-    if ( p.size() < 3 )
-    {
-        qDebug()<<"Not enough points for building the equidistant.";
-        return QVector<QPointF>();
-    }
-
-    if (eqv == EquidistantType::CloseEquidistant)
-    {
-        p.append(p.at(0));
-    }
-    for (qint32 i = 0; i < p.size(); ++i )
-    {
-        if ( i == 0 && eqv == EquidistantType::CloseEquidistant)
-        {//first point, polyline closed
-            ekvPoints<<EkvPoint(QLineF(p.at(p.size()-2), p.at(p.size()-1)), QLineF(p.at(1), p.at(0)), width);
-            continue;
-        }
-        else if (i == 0 && eqv == EquidistantType::OpenEquidistant)
-        {//first point, polyline doesn't closed
-            ekvPoints.append(UnclosedEkvPoint(QLineF(p.at(0), p.at(1)), QLineF(p.at(0), p.at(p.size()-1)), width));
-            continue;
-        }
-        if (i == p.size()-1 && eqv == EquidistantType::CloseEquidistant)
-        {//last point, polyline closed
-            if (not ekvPoints.isEmpty())
-            {
-                ekvPoints.append(ekvPoints.at(0));
-            }
-            continue;
-        }
-        else if (i == p.size()-1 && eqv == EquidistantType::OpenEquidistant)
-        {//last point, polyline doesn't closed
-            ekvPoints.append(UnclosedEkvPoint(QLineF(p.at(p.size()-2), p.at(p.size()-1)),
-                                              QLineF(p.at(0), p.at(p.size()-1)), width));
-            continue;
-        }
-        //points in the middle of polyline
-        ekvPoints<<EkvPoint(QLineF(p.at(i-1), p.at(i)), QLineF(p.at(i+1), p.at(i)), width);
-    }
-
-    bool removeFirstAndLast = true;
-    if (eqv == EquidistantType::CloseEquidistant)
-    {
-        removeFirstAndLast = false;
-    }
-
-    ekvPoints = CheckLoops(CorrectEquidistantPoints(ekvPoints, removeFirstAndLast));//Result path can contain loops
-    return ekvPoints;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VAbstractDetail::RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast)
-{
-    QVector<QPointF> p = points;
-
-    if (removeFirstAndLast)
-    {
-        if (not p.isEmpty() && p.size() > 1)
-        {
-            // Path can't be closed
-            if (p.first() == p.last())
-            {
-            #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-                p.remove(p.size() - 1);
-            #else
-                p.removeLast();
-            #endif
-            }
-        }
-    }
-
-    for (int i = 0; i < p.size()-1; ++i)
-    {
-        if (p.at(i) == p.at(i+1))
-        {
-            if (not removeFirstAndLast && (i == p.size()-1))
-            {
-                continue;
-            }
-
-            p.erase(p.begin() + i + 1);
-            --i;
-            continue;
-        }
-    }
-
-    return p;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VAbstractDetail::CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
-                                        const QPointF &crossPoint)
-{
-    QVector<QPointF> sub1 = SubPath(points, iNext, j);
-    sub1.append(crossPoint);
-    sub1 = CheckLoops(CorrectEquidistantPoints(sub1, false));
-    const qreal sub1Sum = SumTrapezoids(sub1);
-
-    QVector<QPointF> sub2 = SubPath(points, jNext, i);
-    sub2.append(crossPoint);
-    sub2 = CheckLoops(CorrectEquidistantPoints(sub2, false));
-    const qreal sub2Sum = SumTrapezoids(sub2);
-
-    if (sub1Sum < 0 && sub2Sum < 0)
-    {
-        if (Crossing(sub1, sub2))
-        {
-            return true;
-        }
-    }
-    else
-    {
-        if (not Crossing(sub1, sub2))
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VAbstractDetail::ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point)
-{
-    const bool l1p1el2p1 = (line1.p1() == line2.p1());
-    const bool l1p2el2p2 = (line1.p2() == line2.p2());
-    const bool l1p1el2p2 = (line1.p1() == line2.p2());
-    const bool l1p2el2p1 = (line1.p2() == line2.p1());
-
-    if (l1p2el2p2 || l1p2el2p1)
-    {
-        point = line1.p2();
-        return true;
-    }
-    else if (l1p1el2p1 || l1p1el2p2)
-    {
-        point = line1.p1();
-        return true;
-    }
-    else
-    {
-        point = QPointF();
-        return false;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VAbstractDetail::Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2)
-{
-    if (sub1.isEmpty() || sub2.isEmpty())
-    {
-        return false;
-    }
-
-    const QRectF sub1Rect = QPolygonF(sub1).boundingRect();
-    const QRectF sub2Rect = QPolygonF(sub2).boundingRect();
-    if (not sub1Rect.intersects(sub2Rect))
-    {
-        return false;
-    }
-
-    QPainterPath sub1Path;
-    sub1Path.setFillRule(Qt::WindingFill);
-    sub1Path.moveTo(sub1.at(0));
-    for (qint32 i = 1; i < sub1.count(); ++i)
-    {
-        sub1Path.lineTo(sub1.at(i));
-    }
-    sub1Path.lineTo(sub1.at(0));
-
-    QPainterPath sub2Path;
-    sub2Path.setFillRule(Qt::WindingFill);
-    sub2Path.moveTo(sub2.at(0));
-    for (qint32 i = 1; i < sub2.count(); ++i)
-    {
-        sub2Path.lineTo(sub2.at(i));
-    }
-    sub2Path.lineTo(sub2.at(0));
-
-    if (not sub1Path.intersects(sub2Path))
-    {
-        return false;
-    }
-    else
-    {
-        return true;
-    }
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> VAbstractDetail::SubPath(const QVector<QPointF> &path, int startIndex, int endIndex)
-{
-    if (path.isEmpty()
-       || startIndex < 0 || startIndex >= path.size()
-       || endIndex < 0 || endIndex >= path.size()
-       || startIndex == endIndex)
-    {
-        return path;
-    }
-
-    QVector<QPointF> subPath;
-    int i = startIndex - 1;
-    do
-    {
-        ++i;
-        if (i >= path.size())
-        {
-            i = 0;
-        }
-        subPath.append(path.at(i));
-    } while (i != endIndex);
-
-    return subPath;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
- * @param points list of points equdistant.
- * @return corrected list.
- */
-QVector<QPointF> VAbstractDetail::CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast)
-{
-    if (points.size()<4)//Better don't check if only three points. We can destroy equidistant.
-    {
-        qDebug()<<"Only three points.";
-        return points;
-    }
-
-    //Clear equivalent points
-    QVector<QPointF> buf1 = RemoveDublicates(points, removeFirstAndLast);
-
-    if (buf1.size()<3)
-    {
-        return buf1;
-    }
-
-    QVector<QPointF> buf2;
-    //Remove point on line
-    for (qint32 i = 0; i < buf1.size(); ++i)
-    {// In this case we alwayse will have bounded intersection, so all is need is to check if point i is on line.
-     // Unfortunatelly QLineF::intersect can't be used in this case because of the floating-point accuraccy problem.
-        int prev = i-1;
-        int next = i+1;
-        if (i == 0)
-        {
-            prev = buf1.size() - 1;
-        }
-        else if (i == buf1.size() - 1)
-        {
-            next = 0;
-        }
-
-        const QPointF &iPoint = buf1.at(i);
-        const QPointF &prevPoint = buf1.at(prev);
-        const QPointF &nextPoint = buf1.at(next);
-
-        if (not VGObject::IsPointOnLineviaPDP(buf1.at(i), buf1.at(prev), buf1.at(next))
-                && prevPoint != nextPoint) // not zigzag
-        {
-            buf2.append(buf1.at(i));
-        }
-        else if ((i == 0 || i == buf1.size() - 1) && (iPoint == prevPoint || iPoint == nextPoint))
-        {
-            // If RemoveDublicates does not remove these points it is a valid case.
-            // Case where last point equal first point
-            buf2.append(buf1.at(i));
-        }
-    }
-
-    buf2 = RemoveDublicates(buf2, false);
-
-    return buf2;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief CheckLoops seek and delete loops in equidistant.
- * @param points vector of points of equidistant.
- * @return vector of points of equidistant.
- */
-QVector<QPointF> VAbstractDetail::CheckLoops(const QVector<QPointF> &points)
-{
-    int count = points.size();
-    /*If we got less than 4 points no need seek loops.*/
-    if (count < 4)
-    {
-        return points;
-    }
-
-    const bool pathClosed = (points.first() == points.last());
-
-    QVector<QPointF> ekvPoints;
-
-    qint32 i, j, jNext = 0;
-    for (i = 0; i < count; ++i)
-    {
-        /*Last three points no need check.*/
-        /*Triangle has not contain loops*/
-        if (i > count-3)
-        {
-            ekvPoints.append(points.at(i));
-            continue;
-        }
-
-        enum LoopIntersectType { NoIntersection, BoundedIntersection, ParallelIntersection };
-
-        QPointF crosPoint;
-        LoopIntersectType status = NoIntersection;
-        const QLineF line1(points.at(i), points.at(i+1));
-        // Because a path can contains several loops we will seek the last and only then remove the loop(s)
-        // That's why we parse from the end
-        for (j = count-1; j >= i+2; --j)
-        {
-            j == count-1 ? jNext = 0 : jNext = j+1;
-            QLineF line2(points.at(j), points.at(jNext));
-
-            if(qFuzzyIsNull(line2.length()))
-            {//If a path is closed the edge (count-1;0) length will be 0
-                continue;
-            }
-
-            QSet<qint32> uniqueVertices;
-            uniqueVertices << i << i+1 << j;
-
-            // For closed path last point is equal to first. Using index of the first.
-            pathClosed && jNext == count-1 ? uniqueVertices << 0 : uniqueVertices << jNext;
-
-            const QLineF::IntersectType intersect = line1.intersect(line2, &crosPoint);
-            if (intersect == QLineF::NoIntersection)
-            { // According to the documentation QLineF::NoIntersection indicates that the lines do not intersect;
-              // i.e. they are parallel. But parallel also mean they can be on the same line.
-              // Method IsPointOnLineviaPDP will check it.
-                if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1))
-                    // Lines are not neighbors
-                    && uniqueVertices.size() == 4)
-                {
-                    // Left to catch case where segments are on the same line, but do not have real intersections.
-                    QLineF tmpLine1 = line1;
-                    QLineF tmpLine2 = line2;
-
-                    tmpLine1.setAngle(tmpLine1.angle()+90);
-
-                    QPointF tmpCrosPoint;
-                    const QLineF::IntersectType tmpIntrs1 = tmpLine1.intersect(tmpLine2, &tmpCrosPoint);
-
-                    tmpLine1 = line1;
-                    tmpLine2.setAngle(tmpLine2.angle()+90);
-
-                    const QLineF::IntersectType tmpIntrs2 = tmpLine1.intersect(tmpLine2, &tmpCrosPoint);
-
-                    if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection)
-                    { // Now we really sure that lines are on the same line and have real intersections.
-                        QPointF cPoint;
-                        const bool caseFlag = ParallelCrossPoint(line1, line2, cPoint);
-                        if (not caseFlag || CheckIntersection(points, i, i+1, j, jNext, cPoint))
-                        {
-                            status = ParallelIntersection;
-                            break;
-                        }
-                    }
-                }
-            }
-            else if (intersect == QLineF::BoundedIntersection)
-            {
-                if (uniqueVertices.size() == 4)
-                { // Break, but not if lines are neighbors
-                    if ((line1.p1() != crosPoint
-                        && line1.p2() != crosPoint
-                        && line2.p1() != crosPoint
-                        && line2.p2() != crosPoint) || CheckIntersection(points, i, i+1, j, jNext, crosPoint))
-                    {
-                        status = BoundedIntersection;
-                        break;
-                    }
-                }
-            }
-            status = NoIntersection;
-        }
-
-        switch (status)
-        {
-            case ParallelIntersection:
-                /*We have found a loop.*/
-                ekvPoints.append(points.at(i));
-                ekvPoints.append(points.at(jNext));
-                jNext > j ? i = jNext : i = j; // Skip a loop
-                break;
-            case BoundedIntersection:
-                ekvPoints.append(points.at(i));
-                ekvPoints.append(crosPoint);
-                i = j;
-                break;
-            case NoIntersection:
-                /*We have not found loop.*/
-                ekvPoints.append(points.at(i));
-                break;
-            default:
-                break;
-        }
-    }
-    return ekvPoints;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal.
- * @param line1 first line.
- * @param line2 second line.
- * @param width width of equidistant.
- * @return vector of points.
- */
-QVector<QPointF> VAbstractDetail::EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width)
-{
-    if (width <= 0)
-    {
-        return QVector<QPointF>();
-    }
-    QVector<QPointF> points;
-    if (line1.p2() != line2.p2())
-    {
-        qDebug()<<"Last points of two lines must be equal.";
-        return QVector<QPointF>();
-    }
-    QPointF CrosPoint;
-    const QLineF bigLine1 = ParallelLine(line1, width );
-    const QLineF bigLine2 = ParallelLine(QLineF(line2.p2(), line2.p1()), width );
-    QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint );
-    switch (type)
-    {
-        case (QLineF::BoundedIntersection):
-            points.append(CrosPoint);
-            return points;
-            break;
-        case (QLineF::UnboundedIntersection):
-        {
-            QLineF line( line1.p2(), CrosPoint );
-
-            const int angle1 = BisectorAngle(line1.p1(), line1.p2(), line2.p1());
-            const int angle2 = BisectorAngle(bigLine1.p1(), CrosPoint, bigLine2.p2());
-
-            if (angle1 == angle2)
-            {//Regular equdistant case
-                const qreal length = line.length();
-                if (length > width*2.4)
-                { // Cutting too long a cut angle
-                    line.setLength(width); // Not sure about width value here
-                    QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular
-                    cutLine.setLength(length); // Decided take this length
-
-                    // We do not check intersection type because intersection must alwayse exist
-                    QPointF px;
-                    cutLine.setAngle(cutLine.angle()+90);
-                    QLineF::IntersectType type = bigLine1.intersect( cutLine, &px );
-                    if (type == QLineF::NoIntersection)
-                    {
-                        qDebug()<<"Couldn't find intersection with cut line.";
-                    }
-                    points.append(px);
-
-                    cutLine.setAngle(cutLine.angle()-180);
-                    type = bigLine2.intersect( cutLine, &px );
-                    if (type == QLineF::NoIntersection)
-                    {
-                        qDebug()<<"Couldn't find intersection with cut line.";
-                    }
-                    points.append(px);
-                }
-                else
-                {
-                    points.append(CrosPoint);
-                    return points;
-                }
-            }
-            else
-            {// Dart. Create a loop.
-                points.append(bigLine1.p2());
-                points.append(bigLine2.p1());
-                return points;
-            }
-            break;
-        }
-        case (QLineF::NoIntersection):
-            /*If we have correct lines this means lines lie on a line.*/
-            points.append(bigLine1.p2());
-            return points;
-            break;
-        default:
-            break;
-    }
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief UnclosedEkvPoint helps find point of an unclosed seam allowance. One side of two lines should be equal.
- *
- * In case of the first seam allowance point equal should be the first point of the two lines. In case the last point -
- * the last point of the two lines.
- *
- * @param line line of a seam allowance
- * @param helpLine help line of the main path that cut unclosed seam allowance
- * @param width seam allowance width
- * @return seam allowance point
- */
-QPointF VAbstractDetail::UnclosedEkvPoint(const QLineF &line, const QLineF &helpLine, const qreal &width)
-{
-    if (width <= 0)
-    {
-        return QPointF();
-    }
-
-    const bool firstPoint = line.p1() == helpLine.p1();
-    if (not (line.p2() == helpLine.p2() || firstPoint))
-    {
-        qDebug()<<"Two points of two lines must be equal.";
-        return QPointF();
-    }
-
-    QPointF CrosPoint;
-    const QLineF bigLine = ParallelLine(line, width );
-    QLineF::IntersectType type = bigLine.intersect( helpLine, &CrosPoint );
-    switch (type)
-    {
-        case (QLineF::BoundedIntersection):
-            return CrosPoint;
-            break;
-        case (QLineF::UnboundedIntersection):
-        {
-            // This case is very tricky.
-            // User can create very wrong path that will create crospoint far from main path.
-            // Such an annomaly we try to catch and fix.
-            // If don't do this the program will crash.
-            QLineF test;
-            firstPoint ? test = QLineF(line.p1(), CrosPoint) : test = QLineF(line.p2(), CrosPoint);
-            const qreal length = test.length();
-            if (length > width*2.4)
-            {
-                test.setLength(width);
-                return test.p2();
-            }
-            else
-            {
-                return CrosPoint;
-            }
-            break;
-        }
-        case (QLineF::NoIntersection):
-            /*If we have correct lines this means lines lie on a line.*/
-            if (firstPoint)
-            {
-                return bigLine.p1();
-            }
-            else
-            {
-                return bigLine.p2();
-            }
-            break;
-        default:
-            break;
-    }
-    return QPointF();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief ParallelLine create parallel line.
- * @param line starting line.
- * @param width width to parallel line.
- * @return parallel line.
- */
-QLineF VAbstractDetail::ParallelLine(const QLineF &line, qreal width)
-{
-    QLineF paralel = QLineF (SingleParallelPoint(line, 90, width), SingleParallelPoint(QLineF(line.p2(), line.p1()),
-                                                                                       -90, width));
-    return paralel;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief SingleParallelPoint return point of parallel line.
- * @param line starting line.
- * @param angle angle in degree.
- * @param width width to parallel line.
- * @return point of parallel line.
- */
-QPointF VAbstractDetail::SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width)
-{
-    QLineF pLine = line;
-    pLine.setAngle( pLine.angle() + angle );
-    pLine.setLength( width );
-    return pLine.p2();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-int VAbstractDetail::BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3)
-{
-    QLineF line1(p2, p1);
-    QLineF line2(p2, p3);
-    QLineF bLine;
-
-    const qreal angle1 = line1.angleTo(line2);
-    const qreal angle2 = line2.angleTo(line1);
-
-    if (angle1 <= angle2)
-    {
-        bLine = line1;
-        bLine.setAngle(bLine.angle() + angle1/2.0);
-    }
-    else
-    {
-        bLine = line2;
-        bLine.setAngle(bLine.angle() + angle2/2.0);
-    }
-
-    return qRound(bLine.angle());
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-qreal VAbstractDetail::SumTrapezoids(const QVector<QPointF> &points)
-{
-    // Calculation a polygon area through the sum of the areas of trapezoids
-    qreal s, res = 0;
-    const int n = points.size();
-
-    if(n > 2)
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (i == 0)
-            {
-                s = points.at(i).x()*(points.at(n-1).y() - points.at(i+1).y()); //if i == 0, then y[i-1] replace on y[n-1]
-                res += s;
-            }
-            else
-            {
-                if (i == n-1)
-                {
-                    s = points.at(i).x()*(points.at(i-1).y() - points.at(0).y()); // if i == n-1, then y[i+1] replace on y[0]
-                    res += s;
-                }
-                else
-                {
-                    s = points.at(i).x()*(points.at(i-1).y() - points.at(i+1).y());
-                    res += s;
-                }
-            }
-        }
-    }
-    return res;
-}
diff --git a/src/libs/vlayout/vabstractdetail.h b/src/libs/vlayout/vabstractdetail.h
deleted file mode 100644
index 902b15dd2..000000000
--- a/src/libs/vlayout/vabstractdetail.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/************************************************************************
- **
- **  @file   vabstractdetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   2 1, 2015
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 VABSTRACTDETAIL_H
-#define VABSTRACTDETAIL_H
-
-#include <QSharedDataPointer>
-#include <QTypeInfo>
-#include <QtGlobal>
-
-#include "vlayoutdef.h"
-
-class QLineF;
-class QPointF;
-class QString;
-class VAbstractDetailData;
-template <typename T> class QVector;
-
-/**
- * @brief The VAbstractDetail class abstract class for all details.
- */
-class VAbstractDetail
-{
-public:
-    VAbstractDetail();
-    explicit VAbstractDetail(const QString &name);
-    VAbstractDetail(const VAbstractDetail &detail);
-    VAbstractDetail &operator=(const VAbstractDetail &detail);
-    virtual ~VAbstractDetail();
-
-    void    Clear();
-
-    QString getName() const;
-    void    setName(const QString &value);
-
-    bool    getSeamAllowance() const;
-    void    setSeamAllowance(bool value);
-
-    bool    getClosed() const;
-    void    setClosed(bool value);
-
-    qreal   getWidth() const;
-    void    setWidth(const qreal &value);
-
-    bool    getForbidFlipping() const;
-    void    setForbidFlipping(bool value);
-
-    static QVector<QPointF> Equidistant(const QVector<QPointF> &points, const EquidistantType &eqv, qreal width);
-    static qreal            SumTrapezoids(const QVector<QPointF> &points);
-    static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
-    static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points, bool removeFirstAndLast = true);
-
-protected:
-    static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points, bool removeFirstAndLast = true);
-
-private:
-    QSharedDataPointer<VAbstractDetailData> d;
-
-    static bool             CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
-                                              const QPointF &crossPoint);
-    static bool             ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point);
-    static bool             Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2);
-    static QVector<QPointF> SubPath(const QVector<QPointF> &path, int startIndex, int endIndex);
-    static QVector<QPointF> EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width);
-    static QPointF          UnclosedEkvPoint(const QLineF &line, const QLineF &helpLine, const qreal &width);
-    static QLineF           ParallelLine(const QLineF &line, qreal width );
-    static QPointF          SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width);
-    static int              BisectorAngle(const QPointF &p1, const QPointF &p2, const QPointF &p3);
-};
-
-Q_DECLARE_TYPEINFO(VAbstractDetail, Q_MOVABLE_TYPE);
-
-#endif // VABSTRACTDETAIL_H
diff --git a/src/libs/vlayout/vabstractdetail_p.h b/src/libs/vlayout/vabstractdetail_p.h
deleted file mode 100644
index 54fded0b3..000000000
--- a/src/libs/vlayout/vabstractdetail_p.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/************************************************************************
- **
- **  @file   vabstractdetail_p.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   2 1, 2015
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2013-2015 Valentina project
- **  <https://bitbucket.org/dismine/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 VABSTRACTDETAIL_P_H
-#define VABSTRACTDETAIL_P_H
-
-#include <QSharedData>
-#include <QString>
-
-#include "../vmisc/diagnostic.h"
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_GCC("-Weffc++")
-
-class VAbstractDetailData : public QSharedData
-{
-public:
-    VAbstractDetailData()
-        :name(QString()), seamAllowance(false), closed(true), width(0), forbidFlipping(false)
-    {}
-
-    explicit VAbstractDetailData(const QString &name)
-        :name(name), seamAllowance(false), closed(true), width(0), forbidFlipping(false)
-    {}
-
-    VAbstractDetailData(const VAbstractDetailData &detail)
-        :QSharedData(detail), name(detail.name), seamAllowance(detail.seamAllowance), closed(detail.closed),
-          width(detail.width), forbidFlipping(detail.forbidFlipping)
-    {}
-
-    ~VAbstractDetailData() {}
-
-    /** @brief name detail name. */
-    QString        name;
-    /** @brief seamAllowance status seamAllowance detail. */
-    bool           seamAllowance;
-    /** @brief closed status equdistant detail. */
-    bool           closed;
-    /** @brief width value seamAllowance in mm. */
-    qreal          width;
-    /** @brief forbidFlipping forbid piece be mirrored in a layout. */
-    bool           forbidFlipping;
-
-private:
-    VAbstractDetailData &operator=(const VAbstractDetailData &) Q_DECL_EQ_DELETE;
-};
-
-QT_WARNING_POP
-
-#endif // VABSTRACTDETAIL_P_H
diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri
index 1ed0558d0..11a46ad9c 100644
--- a/src/libs/vlayout/vlayout.pri
+++ b/src/libs/vlayout/vlayout.pri
@@ -4,8 +4,6 @@
 HEADERS += \
     $$PWD/stable.h \
     $$PWD/vlayoutgenerator.h \
-    $$PWD/vabstractdetail.h \
-    $$PWD/vabstractdetail_p.h \
     $$PWD/vlayoutdef.h \
     $$PWD/vlayoutpaper.h \
     $$PWD/vlayoutpaper_p.h \
@@ -24,7 +22,6 @@ HEADERS += \
 
 SOURCES += \
     $$PWD/vlayoutgenerator.cpp \
-    $$PWD/vabstractdetail.cpp \
     $$PWD/vlayoutpaper.cpp \
     $$PWD/vbank.cpp \
     $$PWD/vcontour.cpp \
diff --git a/src/test/ValentinaTest/ValentinaTest.pro b/src/test/ValentinaTest/ValentinaTest.pro
index 3d31c6c76..a421d5acf 100644
--- a/src/test/ValentinaTest/ValentinaTest.pro
+++ b/src/test/ValentinaTest/ValentinaTest.pro
@@ -36,7 +36,6 @@ DEFINES += SRCDIR=\\\"$$PWD/\\\"
 SOURCES += \
     qttestmainlambda.cpp \
     tst_vposter.cpp \
-    tst_vabstractdetail.cpp \
     tst_vspline.cpp \
     tst_nameregexp.cpp \
     tst_vlayoutdetail.cpp \
@@ -62,7 +61,6 @@ win32-msvc*:SOURCES += stable.cpp
 
 HEADERS += \
     tst_vposter.h \
-    tst_vabstractdetail.h \
     tst_vspline.h \
     tst_nameregexp.h \
     tst_vlayoutdetail.h \
diff --git a/src/test/ValentinaTest/qttestmainlambda.cpp b/src/test/ValentinaTest/qttestmainlambda.cpp
index 00c0ded7a..6bbf8113c 100644
--- a/src/test/ValentinaTest/qttestmainlambda.cpp
+++ b/src/test/ValentinaTest/qttestmainlambda.cpp
@@ -29,7 +29,6 @@
 #include <QtTest>
 
 #include "tst_vposter.h"
-#include "tst_vabstractdetail.h"
 #include "tst_vabstractpiece.h"
 #include "tst_vspline.h"
 #include "tst_nameregexp.h"
@@ -70,7 +69,6 @@ int main(int argc, char** argv)
     ASSERT_TEST(new TST_FindPoint());
     ASSERT_TEST(new TST_VDetail());
     ASSERT_TEST(new TST_VPoster());
-    //ASSERT_TEST(new TST_VAbstractDetail());
     ASSERT_TEST(new TST_VAbstractPiece());
     ASSERT_TEST(new TST_VSpline());
     ASSERT_TEST(new TST_VSplinePath());
diff --git a/src/test/ValentinaTest/tst_vabstractdetail.cpp b/src/test/ValentinaTest/tst_vabstractdetail.cpp
deleted file mode 100644
index 9a900dc89..000000000
--- a/src/test/ValentinaTest/tst_vabstractdetail.cpp
+++ /dev/null
@@ -1,1386 +0,0 @@
-/************************************************************************
- **
- **  @file   tst_vabstractdetail.cpp
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   16 4, 2015
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2015 Valentina project
- **  <https://bitbucket.org/dismine/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 "tst_vabstractdetail.h"
-#include "../vlayout/vabstractdetail.h"
-
-#include <QPointF>
-#include <QVector>
-
-#include <QtTest>
-
-//---------------------------------------------------------------------------------------------------------------------
-TST_VAbstractDetail::TST_VAbstractDetail(QObject *parent)
-    :AbstractTest(parent)
-{
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::EquidistantRemoveLoop_data()
-{
-    QTest::addColumn<QVector<QPointF>>("points");
-    QTest::addColumn<int>("eqv");
-    QTest::addColumn<qreal>("width");
-    QTest::addColumn<QVector<QPointF>>("ekvOrig");
-
-    // These are two real cases where equdistant has loop.
-    // See issue #298. Segmented Curve isn't selected in Seam Allowance tool.
-    // https://bitbucket.org/dismine/valentina/issue/298/segmented-curve-isnt-selected-in-seam
-    // Code should clean loops in path.
-    QTest::newRow("Issue 298. Case1") << InputPointsIssue298Case1()
-                                      << static_cast<int>(EquidistantType::CloseEquidistant)
-                                      << 75.5906 // seam allowance width
-                                      << OutputPointsIssue298Case1();
-
-    QTest::newRow("Issue 298. Case2") << InputPointsIssue298Case2()
-                                      << static_cast<int>(EquidistantType::CloseEquidistant)
-                                      << 37.7953 // seam allowance width
-                                      << OutputPointsIssue298Case2();
-
-    // See issue #548. Bug Detail tool. Case when seam allowance is wrong.
-    // https://bitbucket.org/dismine/valentina/issues/548/bug-detail-tool-case-when-seam-allowance
-    // Files: Steampunk_trousers.val and marie.vit
-    // Actually buggy detail see in file src/app/share/collection/bugs/Steampunk_trousers_issue_#548.val
-    // Code should clean loops in path.
-    QTest::newRow("Issue 548. Case1") << InputPointsIssue548Case1()
-                                      << static_cast<int>(EquidistantType::CloseEquidistant)
-                                      << 11.338582677165354 // seam allowance width (0.3 cm)
-                                      << OutputPointsIssue548Case1();
-
-    QTest::newRow("Issue 548. Case2") << InputPointsIssue548Case2()
-                                      << static_cast<int>(EquidistantType::CloseEquidistant)
-                                      << 37.795275590551185 // seam allowance width (1.0 cm)
-                                      << OutputPointsIssue548Case2();
-
-    QTest::newRow("Issue 548. Case3") << InputPointsIssue548Case3()
-                                      << static_cast<int>(EquidistantType::CloseEquidistant)
-                                      << 75.59055118110237 // seam allowance width (2.0 cm)
-                                      << OutputPointsIssue548Case3();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-// cppcheck-suppress unusedFunction
-void TST_VAbstractDetail::EquidistantRemoveLoop() const
-{
-    QFETCH(QVector<QPointF>, points);
-    QFETCH(int, eqv);
-    QFETCH(qreal, width);
-    QFETCH(QVector<QPointF>, ekvOrig);
-
-    const QVector<QPointF> ekv = VAbstractDetail::Equidistant(points, static_cast<EquidistantType>(eqv), width);
-
-    // Begin comparison
-    Comparison(ekv, ekvOrig);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::SumTrapezoids() const
-{
-    // Case3 checks that the method 'SumTrapezoids' returns negative value for three clockwise allocated points
-    // Case4 checks that the method 'SumTrapezoids' returns positive value for three counterclock-wise allocated points
-    // Case5 checks that the method 'SumTrapezoids' returns 0 for one point
-    Case3();
-    Case4();
-    Case5();
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PathRemoveLoop_data() const
-{
-    QTest::addColumn<QVector<QPointF>>("path");
-    QTest::addColumn<QVector<QPointF>>("expect");
-
-    QVector<QPointF> path;
-    path << QPointF(10, 10);
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 20);
-    path << QPointF(10, 10);
-    QTest::newRow("Correct closed a path (four unique points)") << path << path;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-#else
-    path.removeLast();
-#endif
-    QTest::newRow("Correct unclosed a path (four unique points)") << path << path;
-
-    path.clear();
-    path << QPointF(0, 10);
-    path << QPointF(10, 10);
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-    QTest::newRow("Correct closed a path (six unique points)") << path << path;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-#else
-    path.removeLast();
-#endif
-    QTest::newRow("Correct unclosed a path (six unique points)") << path << path;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 10);
-    path << QPointF(10, 20);
-    path << QPointF(20, 10);
-
-    QVector<QPointF> res;
-    res << QPointF(20, 10);
-    res << QPointF(20, 20);
-    res << QPointF(15, 15);
-    res << QPointF(20, 10);
-    QTest::newRow("One loop, closed a path (four unique points)") << path << res;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-    res.remove(res.size() - 1);
-#else
-    path.removeLast();
-    res.removeLast();
-#endif
-    QTest::newRow("One loop, unclosed a path (four unique points)") << path << res;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 10);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-    path << QPointF(10, 20);
-    path << QPointF(20, 10);
-
-    res.clear();
-    res << QPointF(20, 10);
-    res << QPointF(20, 20);
-    res << QPointF(15, 15);
-    res << QPointF(20, 10);
-    QTest::newRow("Two loops, closed a path (six unique points)") << path << res;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-    res.remove(res.size() - 1);
-#else
-    path.removeLast();
-    res.removeLast();
-#endif
-    QTest::newRow("Two loops, unclosed a path (six unique points)") << path << res;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 10);
-    path << QPointF(0, 10);
-    path << QPointF(0, 20);
-    path << QPointF(10, 20);
-    path << QPointF(20, 10);
-
-    res.clear();
-    res << QPointF(20, 10);
-    res << QPointF(20, 20);
-    res << QPointF(15, 15);
-    res << QPointF(20, 10);
-    QTest::newRow("One loop, the first loop, closed a path (six unique points)") << path << res;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-    res.remove(res.size() - 1);
-#else
-    path.removeLast();
-    res.removeLast();
-#endif
-    QTest::newRow("One loop, the first loop, unclosed a path (six unique points)") << path << res;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 20);
-    path << QPointF(0, 10);
-    path << QPointF(0, 20);
-    path << QPointF(10, 10);
-    path << QPointF(20, 10);
-
-    res.clear();
-    res << QPointF(20, 10);
-    res << QPointF(20, 20);
-    res << QPointF(10, 20);
-    res << QPointF(5, 15);
-    res << QPointF(10, 10);
-    res << QPointF(20, 10);
-    QTest::newRow("One loop, the second loop, closed a path (six unique points)") << path << res;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-    res.remove(res.size() - 1);
-#else
-    path.removeLast();
-    res.removeLast();
-#endif
-    QTest::newRow("One loop, the second loop, unclosed a path (six unique points)") << path << res;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(20, 20);
-    path << QPointF(10, 20);
-    path << QPointF(20, 15);
-    path << QPointF(10, 10);
-    path << QPointF(20, 10);
-    QTest::newRow("Correct closed a path, point on line (four unique points)") << path << path;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-#else
-    path.removeLast();
-#endif
-    QTest::newRow("Corect unclosed a path, point on line (four unique points)") << path << path;
-
-    path.clear();
-    path << QPointF(20, 10);
-    path << QPointF(10, 15);
-    path << QPointF(20, 20);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(10, 15);
-    path << QPointF(0, 10);
-    path << QPointF(10, 10);
-    path << QPointF(20, 10);
-
-    QTest::newRow("Correct closed a path, point on line (six unique points)") << path << path;
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
-    path.remove(path.size() - 1);
-#else
-    path.removeLast();
-#endif
-    QTest::newRow("Corect unclosed a path, point on line (six unique points)") << path << path;
-
-    path.clear();
-    path << QPointF(100.96979100571033, 1797.6153764073072);
-    path << QPointF(168.3888427659865, 1807.2395034187866);
-    path << QPointF(206.78076137364403, 1812.2910842036706);
-    path << QPointF(239.1630793382262, 1815.951361623424);
-    path << QPointF(267.5320085054171, 1818.4827543754482);
-    path << QPointF(293.9502505847841, 1820.144031725603);
-    path << QPointF(320.48133946750147, 1821.175819320443);
-    path << QPointF(364.5960626489172, 1822.0507669842166);
-    path << QPointF(400.66867742260206, 1822.488188976378);
-    path << QPointF(623.3126833308274, 1822.488188976378);
-    path << QPointF(653.5489038032683, 2162.6456692913384);
-    path << QPointF(570.545584385708, 2162.6456692913384);
-    path << QPointF(600.7818048581489, 1822.488188976378);
-    path << QPointF(1001.3385826771654, 1822.488188976378);
-    path << QPointF(1001.3385826771654, 2680.44094488189);
-    path << QPointF(-22.11646613738226, 2680.44094488189);
-    path << QPointF(100.96979100571033, 1797.6153764073072);
-
-    res.clear();
-    res << QPointF(100.96979100571033, 1797.6153764073072);
-    res << QPointF(168.3888427659865, 1807.2395034187866);
-    res << QPointF(206.78076137364403, 1812.2910842036706);
-    res << QPointF(239.1630793382262, 1815.951361623424);
-    res << QPointF(267.5320085054171, 1818.4827543754482);
-    res << QPointF(293.9502505847841, 1820.144031725603);
-    res << QPointF(320.48133946750147, 1821.175819320443);
-    res << QPointF(364.5960626489172, 1822.0507669842166);
-    res << QPointF(400.66867742260206, 1822.488188976378);
-    res << QPointF(1001.3385826771654, 1822.488188976378);
-    res << QPointF(1001.3385826771654, 2680.44094488189);
-    res << QPointF(-22.11646613738226, 2680.44094488189);
-    res << QPointF(100.96979100571033, 1797.6153764073072);
-
-    // See the file "collection/bugs/Issue_#493.val"
-    QTest::newRow("Test case issue #493") << path << res;
-
-    path.clear();
-    path << QPointF(-685.2149804319953, -3568.7982439212556);
-    path << QPointF(-700.7415523087261, -3623.900571239949);
-    path << QPointF(-675.4694480627154, -3639.3631430823175);
-    path << QPointF(-684.7497934439581, -3631.3546395862268);
-    path << QPointF(-683.1356602239256, -3633.2868478418427);
-    path << QPointF(-686.8764821039574, -3627.927414863926);
-    path << QPointF(-684.7670104817863, -3631.587853202178);
-    path << QPointF(-682.2386030572435, -3636.8469922361573);
-    path << QPointF(-676.4708011186385, -3650.307478525872);
-    path << QPointF(-666.3050989871189, -3676.5286567894937);
-    path << QPointF(-654.0449409043066, -3710.198553447806);
-    path << QPointF(-640.1333287371614, -3750.0101920374505);
-    path << QPointF(-617.0729873733014, -3818.3303697354913);
-    path << QPointF(-583.8128392515604, -3920.9726624886944);
-    path << QPointF(-550.5307668482033, -4027.6970214479597);
-    path << QPointF(-527.4164674104215, -4104.7034088569535);
-    path << QPointF(-513.4302533332675, -4152.73879565781);
-    path << QPointF(-501.0373006826446, -4196.767296675345);
-    path << QPointF(-490.59311078227046, -4235.660899517831);
-    path << QPointF(-477.25724163384456, -4288.293444470835);
-    path << QPointF(-405.3839593893572, -4272.013803282615);
-    path << QPointF(-545.9786893428341, -3568.830152982464);
-    path << QPointF(-685.2149804319953, -3568.7982439212556);
-
-    res.clear();
-    res << QPointF(-685.2149804319953, -3568.7982439212556);
-    res << QPointF(-700.7415523087261, -3623.900571239949);
-    res << QPointF(-683.3457668881176, -3634.5440688767967);
-    res << QPointF(-682.2386030572435, -3636.8469922361573);
-    res << QPointF(-676.4708011186385, -3650.307478525872);
-    res << QPointF(-666.3050989871189, -3676.5286567894937);
-    res << QPointF(-654.0449409043066, -3710.198553447806);
-    res << QPointF(-640.1333287371614, -3750.0101920374505);
-    res << QPointF(-617.0729873733014, -3818.3303697354913);
-    res << QPointF(-583.8128392515604, -3920.9726624886944);
-    res << QPointF(-550.5307668482033, -4027.6970214479597);
-    res << QPointF(-527.4164674104215, -4104.7034088569535);
-    res << QPointF(-513.4302533332675, -4152.73879565781);
-    res << QPointF(-501.0373006826446, -4196.767296675345);
-    res << QPointF(-490.59311078227046, -4235.660899517831);
-    res << QPointF(-477.25724163384456, -4288.293444470835);
-    res << QPointF(-405.3839593893572, -4272.013803282615);
-    res << QPointF(-545.9786893428341, -3568.830152982464);
-    res << QPointF(-685.2149804319953, -3568.7982439212556);
-
-    // See the file "collection/bugs/Issue_#515.val"
-    // Check a seam allowance path.
-    // The curve that causes the issue is the first in the list.
-    QTest::newRow("Test case issue #515. Big loop in seam allowance path.") << path << res;
-
-    path.clear();
-    path << QPointF(-449.6699112298347, -4243.2921010175705);
-    path << QPointF(-576.966638263205, -3606.6183279948636);
-    path << QPointF(-656.9465284876832, -3606.6183279948636);
-    path << QPointF(-656.5996104603414, -3606.6000783462687);
-    path << QPointF(-655.7439133016985, -3607.1236310612317);
-    path << QPointF(-654.129780081666, -3609.0558393168476);
-    path << QPointF(-651.3154902471701, -3613.939306009108);
-    path << QPointF(-647.8207651830382, -3621.2084054506768);
-    path << QPointF(-641.4701586077349, -3636.0289997859454);
-    path << QPointF(-630.9244502073004, -3663.23035747934);
-    path << QPointF(-618.4465305467888, -3697.4982896415795);
-    path << QPointF(-604.3873016966293, -3737.732371148936);
-    path << QPointF(-581.1891087215608, -3806.460957656939);
-    path << QPointF(-547.7936207285052, -3909.520915257629);
-    path << QPointF(-514.3891332445846, -4016.6378180116963);
-    path << QPointF(-491.17181635142833, -4093.9874129706236);
-    path << QPointF(-477.094588519539, -4142.335384784734);
-    path << QPointF(-464.5941701318652, -4186.745679830414);
-    path << QPointF(-454.0214632588362, -4226.117872983938);
-
-    res.clear();
-    res << QPointF(-449.6699112298347, -4243.2921010175705);
-    res << QPointF(-576.966638263205, -3606.6183279948636);
-    res << QPointF(-656.5697831440032, -3606.6183279948636);
-    res << QPointF(-655.7439133016985, -3607.1236310612317);
-    res << QPointF(-654.129780081666, -3609.0558393168476);
-    res << QPointF(-651.3154902471701, -3613.939306009108);
-    res << QPointF(-647.8207651830382, -3621.2084054506768);
-    res << QPointF(-641.4701586077349, -3636.0289997859454);
-    res << QPointF(-630.9244502073004, -3663.23035747934);
-    res << QPointF(-618.4465305467888, -3697.4982896415795);
-    res << QPointF(-604.3873016966293, -3737.732371148936);
-    res << QPointF(-581.1891087215608, -3806.460957656939);
-    res << QPointF(-547.7936207285052, -3909.520915257629);
-    res << QPointF(-514.3891332445846, -4016.6378180116963);
-    res << QPointF(-491.17181635142833, -4093.9874129706236);
-    res << QPointF(-477.094588519539, -4142.335384784734);
-    res << QPointF(-464.5941701318652, -4186.745679830414);
-    res << QPointF(-454.0214632588362, -4226.117872983938);
-
-    // See the file "collection/bugs/Issue_#515.val"
-    // Check a seam allowance path.
-    // The curve that causes the issue is the last in the list.
-    QTest::newRow("Test case issue #515. Small loop in seam allowance path.") << path << res;
-
-    path.clear();
-    path << QPointF(1229.6503937007876, 937.6667716535435);
-    path << QPointF(203.08931117793543, 937.6667716535435);
-    path << QPointF(459.7677349767701, -2166.704563141019);
-    path << QPointF(1229.6503937007876, -1990.077167189857);
-    path << QPointF(1229.6503937007876, -555.2466141732282);
-    path << QPointF(920.1053824527112, -555.2466141732282);
-    path << QPointF(887.034516310979, -63.90803149606281);
-    path << QPointF(816.3607592795726, -63.908031496062826);
-    path << QPointF(780.7580397937137, -592.8627210002539);
-    path << QPointF(816.0241340748559, -1202.917917917055);
-    path << QPointF(887.3711415156957, -1202.917917917055);
-    path << QPointF(920.4420076574283, -630.8371653543306);
-    path << QPointF(1229.6503937007876, -630.8371653543306);
-    path << QPointF(1229.6503937007876, 937.6667716535435);
-
-    res.clear();
-    res << QPointF(1229.6503937007876, 937.6667716535435);
-    res << QPointF(203.08931117793543, 937.6667716535435);
-    res << QPointF(459.7677349767702, -2166.704563141019);
-    res << QPointF(1229.6503937007876, -1990.077167189857);
-    res << QPointF(1229.6503937007876, 937.6667716535435);
-
-    // See the file "collection/bugs/Issue_#603.val"
-    // Point H1 is first in the list
-    QTest::newRow("Test issue 603.") << path << res;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PathRemoveLoop() const
-{
-    QFETCH(QVector<QPointF>, path);
-    QFETCH(QVector<QPointF>, expect);
-
-    QVector<QPointF> res = VAbstractDetail::CheckLoops(path);
-    Comparison(res, expect);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PathLoopsCase_data() const
-{
-    QTest::addColumn<QVector<QPointF>>("path");
-    QTest::addColumn<QVector<QPointF>>("expect");
-
-    QVector<QPointF> path;
-    path << QPointF(61.86670866141733, 446.92270866141735);
-    path << QPointF(650.6504606788366, 473.2192016666484);
-    path << QPointF(649.4426552757304, 480.5376973511262);
-    path << QPointF(646.5769170924987, 501.9977838630714);
-    path << QPointF(644.6382908004568, 523.6358081043691);
-    path << QPointF(643.4592698551749, 551.9888717674471);
-    path << QPointF(642.9134698671897, 584.1776423714557);
-    path << QPointF(643.1914832622404, 613.2382010061506);
-    path << QPointF(644.2199668178571, 639.3780275889782);
-    path << QPointF(645.9255773115714, 662.8046020373845);
-    path << QPointF(648.2349715209137, 683.7254042688159);
-    path << QPointF(651.0748062234152, 702.3479142007185);
-    path << QPointF(654.3717381966065, 718.8796117505387);
-    path << QPointF(658.0524242180187, 733.5279768357226);
-    path << QPointF(662.0435210651824, 746.5004893737165);
-    path << QPointF(666.2716855156286, 758.0046292819667);
-    path << QPointF(670.6635743468883, 768.2478764779191);
-    path << QPointF(677.400406718071, 781.7952098705392);
-    path << QPointF(691.6740007010135, 806.2608114022295);
-    path << QPointF(694.5877745571677, 810.2150054671212);
-    path << QPointF(699.9560352035193, 816.1706553153153);
-    path << QPointF(708.9007628091615, 824.0594196166176);
-    path << QPointF(719.3794725391945, 831.7499791040799);
-    path << QPointF(730.9568541500198, 839.0942359684872);
-    path << QPointF(743.1975973980386, 845.9440924006244);
-    path << QPointF(755.6663920396528, 852.1514505912763);
-    path << QPointF(767.9279278312633, 857.568212731228);
-    path << QPointF(779.5468945292718, 862.046281011264);
-    path << QPointF(790.0879818900794, 865.4375576221694);
-    path << QPointF(799.115879670088, 867.5939447547289);
-    path << QPointF(804.5608128209333, 868.2650594004886);
-    path << QPointF(807.5317661719646, 868.2782441618697);
-    path << QPointF(809.8795601157717, 867.8994015359809);
-    path << QPointF(811.5497808719051, 867.1100192966705);
-    path << QPointF(812.4880146599148, 865.8915852177861);
-    path << QPointF(812.6398476993509, 864.2255870731761);
-    path << QPointF(811.9508662097637, 862.0935126366886);
-    path << QPointF(810.3666564107034, 859.4768496821717);
-    path << QPointF(806.3216663321919, 854.66911491981);
-    path << QPointF(802.0871811023624, 850.6707401574804);
-    path << QPointF(799.4598981526765, 850.6707401574804);
-    path << QPointF(802.0871811023624, 1653.9337322834645);
-    path << QPointF(61.86670866141733, 1653.9337322834645);
-
-    QVector<QPointF> res;
-    res << QPointF(61.86670866141733, 446.92270866141735);
-    res << QPointF(650.6504606788366, 473.2192016666484);
-    res << QPointF(649.4426552757304, 480.5376973511262);
-    res << QPointF(646.5769170924987, 501.9977838630714);
-    res << QPointF(644.6382908004568, 523.6358081043691);
-    res << QPointF(643.4592698551749, 551.9888717674471);
-    res << QPointF(642.9134698671897, 584.1776423714557);
-    res << QPointF(643.1914832622404, 613.2382010061506);
-    res << QPointF(644.2199668178571, 639.3780275889782);
-    res << QPointF(645.9255773115714, 662.8046020373845);
-    res << QPointF(648.2349715209137, 683.7254042688159);
-    res << QPointF(651.0748062234152, 702.3479142007185);
-    res << QPointF(654.3717381966065, 718.8796117505387);
-    res << QPointF(658.0524242180187, 733.5279768357226);
-    res << QPointF(662.0435210651824, 746.5004893737165);
-    res << QPointF(666.2716855156286, 758.0046292819667);
-    res << QPointF(670.6635743468883, 768.2478764779191);
-    res << QPointF(677.400406718071, 781.7952098705392);
-    res << QPointF(691.6740007010135, 806.2608114022295);
-    res << QPointF(694.5877745571677, 810.2150054671212);
-    res << QPointF(699.9560352035193, 816.1706553153153);
-    res << QPointF(708.9007628091615, 824.0594196166176);
-    res << QPointF(719.3794725391945, 831.7499791040799);
-    res << QPointF(730.9568541500198, 839.0942359684872);
-    res << QPointF(743.1975973980386, 845.9440924006244);
-    res << QPointF(755.6663920396528, 852.1514505912763);
-    res << QPointF(767.9279278312633, 857.568212731228);
-    res << QPointF(779.5468945292718, 862.046281011264);
-    res << QPointF(790.0879818900794, 865.4375576221694);
-    res << QPointF(799.115879670088, 867.5939447547289);
-    res << QPointF(799.5154110117976, 867.6431889469776);
-    res << QPointF(802.0871811023624, 1653.9337322834645);
-    res << QPointF(61.86670866141733, 1653.9337322834645);
-
-    // See file "collection/bugs/Issue_#609_case1.val"
-    // Clear a main path. Bound intersection. External loop. Outside a loop. Start point Ф1.
-    QTest::newRow("Issue 609. Case1a") << path << res;
-
-    path.clear();
-    path << QPointF(-365.68188649000314, -2143.126579528016);
-    path << QPointF(-195.75487873249062, -2116.7935769656237);
-    path << QPointF(-195.75487873249062, -1836.0319480765759);
-    path << QPointF(-233.39027086052477, -1838.4849618976993);
-    path << QPointF(-231.15080237392075, -1855.5915146519483);
-    path << QPointF(-225.84473077299972, -1889.4811404382626);
-    path << QPointF(-219.39861487985402, -1922.986407729537);
-    path << QPointF(-211.6695159016421, -1955.9990283342697);
-    path << QPointF(-204.87723909172885, -1980.439660924953);
-    path << QPointF(-199.87970909142098, -1996.6270828437923);
-    path << QPointF(-194.48099536000245, -2012.6451713592935);
-    path << QPointF(-188.65032933731845, -2028.5246588116781);
-    path << QPointF(-182.36812965707693, -2044.2602109802488);
-    path << QPointF(-175.61499879935675, -2059.8462252736344);
-    path << QPointF(-168.3717693169516, -2075.2768492268588);
-    path << QPointF(-160.6424572210866, -2090.5008865466684);
-    path << QPointF(-150.22847685877994, -2109.7385074212525);
-    path << QPointF(194.23861004296444, -2056.3576305273214);
-    path << QPointF(302.4787663409577, -1301.003761061316);
-    path << QPointF(279.86810151275455, -1288.330749878147);
-    path << QPointF(-641.7062267185897, -2051.118466118487);
-    path << QPointF(-365.68188649000314, -2143.126579528016);
-
-    res.clear();
-    res << QPointF(-365.68188649000314, -2143.126579528016);
-    res << QPointF(-195.75487873249062, -2116.7935769656237);
-    res << QPointF(-195.75487873249062, -2008.8655346469059);
-    res << QPointF(-194.48099536000245, -2012.6451713592935);
-    res << QPointF(-188.65032933731845, -2028.5246588116781);
-    res << QPointF(-182.36812965707693, -2044.2602109802488);
-    res << QPointF(-175.61499879935675, -2059.8462252736344);
-    res << QPointF(-168.3717693169516, -2075.2768492268588);
-    res << QPointF(-160.6424572210866, -2090.5008865466684);
-    res << QPointF(-150.22847685877994, -2109.7385074212525);
-    res << QPointF(194.23861004296444, -2056.3576305273214);
-    res << QPointF(302.4787663409577, -1301.003761061316);
-    res << QPointF(279.86810151275455, -1288.330749878147);
-    res << QPointF(-641.7062267185897, -2051.118466118487);
-    res << QPointF(-365.68188649000314, -2143.126579528016);
-
-    // See file "collection/bugs/Issue_#609_case2.val"
-    // Clear an equdistant. Bound intersection. Internal loop. Outside a loop. Start point А2.
-    QTest::newRow("Issue 609. Case2b") << path << res;
-
-    path.clear();
-    path << QPointF(0, 10);
-    path << QPointF(5, 10);
-    path << QPointF(2.5, 15);
-    path << QPointF(7.5, 15);
-    path << QPointF(5, 10);
-    path << QPointF(10, 10);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-
-    QTest::newRow("Internal loop. Valid case.") << path << path;
-
-    path.clear();
-    path << QPointF(0, 10);
-    path << QPointF(5, 10);
-    path << QPointF(7.5, 15);
-    path << QPointF(2.5, 15);
-    path << QPointF(5, 10);
-    path << QPointF(10, 10);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-
-    res.clear();
-    res << QPointF(0, 10);
-    res << QPointF(10, 10);
-    res << QPointF(10, 20);
-    res << QPointF(0, 20);
-    res << QPointF(0, 10);
-
-    QTest::newRow("Internal loop. Invalid case.") << path << res;
-
-    path.clear();
-    path << QPointF(0, 10);
-    path << QPointF(5, 10);
-    path << QPointF(0, 0);
-    path << QPointF(10, 0);
-    path << QPointF(5, 10);
-    path << QPointF(10, 10);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-
-    QTest::newRow("External loop. Valid case.") << path << path;
-
-    path.clear();
-    path << QPointF(0, 10);
-    path << QPointF(5, 10);
-    path << QPointF(10, 0);
-    path << QPointF(0, 0);
-    path << QPointF(5, 10);
-    path << QPointF(10, 10);
-    path << QPointF(10, 20);
-    path << QPointF(0, 20);
-    path << QPointF(0, 10);
-
-    res.clear();
-    res << QPointF(0, 10);
-    res << QPointF(10, 10);
-    res << QPointF(10, 20);
-    res << QPointF(0, 20);
-    res << QPointF(0, 10);
-
-    QTest::newRow("External loop. Invalid case.") << path << res;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PathLoopsCase() const
-{
-    QFETCH(QVector<QPointF>, path);
-    QFETCH(QVector<QPointF>, expect);
-
-    const QVector<QPointF> res = VAbstractDetail::CheckLoops(path);
-    Comparison(res, expect);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::BrokenDetailEquidistant_data() const
-{
-    QTest::addColumn<QVector<QPointF>>("points");
-    QTest::addColumn<int>("eqv");
-    QTest::addColumn<qreal>("width");
-    QTest::addColumn<QVector<QPointF>>("ekvOrig");
-
-    // For more details see the file "collection/bugs/GAVAUDAN Laure - corsage - figure 4.val".
-    // We will test only one detail. The second require too accurate data that we cannot get from debuger.
-    // The test check an open equdistant of correct detail.
-    QVector<QPointF> points;// Input points.
-    points.append(QPointF(787.5835464566929, 1701.3138897637796));
-    points.append(QPointF(938.7646488188976, 1701.3138897637796));
-    points.append(QPointF(928.6149958683911, 1732.4440719866434));
-    points.append(QPointF(910.0209091217698, 1792.3369853889722));
-    points.append(QPointF(893.3643262819251, 1849.7845131987456));
-    points.append(QPointF(878.5244039283091, 1905.2261617043234));
-    points.append(QPointF(865.3802986403739, 1959.101437194065));
-    points.append(QPointF(863.9366982685195, 1965.6834024491068));
-    points.append(QPointF(852.8936778444679, 1919.6965437838999));
-    points.append(QPointF(837.0628180560684, 1860.2846653184251));
-    points.append(QPointF(819.0677656132684, 1798.6758641921479));
-    points.append(QPointF(798.7585839758027, 1734.54810216256));
-    points.append(QPointF(787.5835464566929, 1701.3138897637796));
-
-    EquidistantType eqv = EquidistantType::OpenEquidistant; // Open path
-    qreal width = 37.795275590551185; // seam allowance width
-
-    QVector<QPointF> ekvOrig;
-    ekvOrig.append(QPointF(774.8748468280837, 1663.5186141732283));
-    ekvOrig.append(QPointF(990.8407795072413, 1663.5186141732283));
-    ekvOrig.append(QPointF(964.6314912875667, 1743.9055911653147));
-    ekvOrig.append(QPointF(946.2221157804494, 1803.203536155223));
-    ekvOrig.append(QPointF(929.7733291125676, 1859.9343877726233));
-    ekvOrig.append(QPointF(915.1430746962241, 1914.5927211230298));
-    ekvOrig.append(QPointF(902.2033544443959, 1967.630259856634));
-    ekvOrig.append(QPointF(894.4064781634931, 2003.1794116713015));
-    ekvOrig.append(QPointF(834.213891302752, 2003.7742535883901));
-    ekvOrig.append(QPointF(816.2523103379473, 1928.9761772004185));
-    ekvOrig.append(QPointF(800.6574884611877, 1870.4501290629887));
-    ekvOrig.append(QPointF(782.9077417718742, 1809.6811695225983));
-    ekvOrig.append(QPointF(786.7126382487066, 1698.723835966227));
-
-    QTest::newRow("GAVAUDAN Laure.") << points << static_cast<int>(eqv) << width << ekvOrig;
-
-    points.clear();
-    points.append(QPointF(97.33089106412862, -223.03306117556497));
-    points.append(QPointF(990.7494050554426, 2.819093995045));
-    points.append(QPointF(908.3966357321774, 379.5839357215547));
-    points.append(QPointF(-135.41154226686143, 697.6417881399819));
-
-    eqv = EquidistantType::OpenEquidistant;
-    width = 11.338582677165354;
-
-    ekvOrig.clear();
-    ekvOrig.append(QPointF(100.10981413873267, -234.02583351343978));
-    ekvOrig.append(QPointF(1004.1704360325447, -5.483401649771952));
-    ekvOrig.append(QPointF(918.0553412376563, 388.4941212347381));
-    ekvOrig.append(QPointF(-138.65807550610091, 710.4843173601864));
-
-    // See the file "collection/bugs/Issue_#604.val" (since 0.5.0)
-    QTest::newRow("Issue #604.") << points << static_cast<int>(eqv) << width << ekvOrig;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::BrokenDetailEquidistant() const
-{
-    QFETCH(QVector<QPointF>, points);
-    QFETCH(int, eqv);
-    QFETCH(qreal, width);
-    QFETCH(QVector<QPointF>, ekvOrig);
-
-    const QVector<QPointF> ekv = VAbstractDetail::Equidistant(points, static_cast<EquidistantType>(eqv),
-                                                              width);// Take result
-
-    // Begin comparison
-    Comparison(ekv, ekvOrig);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::CorrectEquidistantPoints_data() const
-{
-    // See file zigzag.val
-    QTest::addColumn<QVector<QPointF>>("points");
-    QTest::addColumn<QVector<QPointF>>("expect");
-    QTest::addColumn<bool>("removeFirstAndLast");
-
-    QVector<QPointF> points;
-    points.append(QPointF(-741.7894588053705, 1065.7336503858917));
-    points.append(QPointF(-759.696551643576, -115.81420543069257));
-    points.append(QPointF(-278.17249953019325, -217.1037453126913));
-    points.append(QPointF(-244.64654130659474, 1077.9548221866635));
-    points.append(QPointF(-741.7894588053705, 1065.7336503858917));
-
-    QVector<QPointF> expect;
-    expect.append(QPointF(-741.7894588053705, 1065.7336503858917));
-    expect.append(QPointF(-759.696551643576, -115.81420543069257));
-    expect.append(QPointF(-278.17249953019325, -217.1037453126913));
-    expect.append(QPointF(-244.64654130659474, 1077.9548221866635));
-    expect.append(QPointF(-741.7894588053705, 1065.7336503858917));
-
-    QTest::newRow("Closed seam allowance. Last point equal first.") << points << expect << false;
-
-    points.clear();
-    points.append(QPointF(-704.5489521643801, 1028.8424328418016));
-    points.append(QPointF(-721.4335720065426, -85.24049234531904));
-    points.append(QPointF(-707.7852899705758, 755.7064514429209));
-    points.append(QPointF(-721.4335720065426, -85.24049234531904));
-    points.append(QPointF(-314.78124296268265, -170.7806167067443));
-    points.append(QPointF(-283.4579031023758, 1039.1940357173805));
-
-    expect.clear();
-    expect.append(QPointF(-704.5489521643801, 1028.8424328418016));
-    expect.append(QPointF(-721.4335720065426, -85.24049234531904));
-    expect.append(QPointF(-314.78124296268265, -170.7806167067443));
-    expect.append(QPointF(-283.4579031023758, 1039.1940357173805));
-
-    QTest::newRow("Clearing bad main path.") << points << expect << true;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::CorrectEquidistantPoints() const
-{
-    QFETCH(QVector<QPointF>, points);
-    QFETCH(QVector<QPointF>, expect);
-    QFETCH(bool, removeFirstAndLast);
-
-    const QVector<QPointF> res = VAbstractDetail::CorrectEquidistantPoints(points, removeFirstAndLast);
-
-    // Begin comparison
-    Comparison(res, expect);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::TestCorrectEquidistantPoints_data()
-{
-    QTest::addColumn<QVector<QPointF>>("before");
-    QTest::addColumn<QVector<QPointF>>("expect");
-
-    QVector<QPointF> before;
-    before << QPointF(30.0, 39.999874015748034);
-    before << QPointF(785.9055118110236, 39.999874015748034);
-    before << QPointF(785.9055118110236, 3819.527433070866);
-    before << QPointF(483.54330708661416, 3819.527433070866);
-    before << QPointF(483.54330708661416, 1929.763653543307);
-    before << QPointF(407.9527559055629, 984.8817637795973);
-    before << QPointF(407.9527559055118, 1929.763653543307);
-    before << QPointF(407.9527559055118, 3819.527433070866);
-    before << QPointF(30.0, 3819.527433070866);
-
-    QVector<QPointF> expect;
-    expect << QPointF(30.0, 39.999874015748034);
-    expect << QPointF(785.9055118110236, 39.999874015748034);
-    expect << QPointF(785.9055118110236, 3819.527433070866);
-    expect << QPointF(483.54330708661416, 3819.527433070866);
-    expect << QPointF(483.54330708661416, 1929.763653543307);
-    expect << QPointF(407.9527559055629, 984.8817637795973);
-    expect << QPointF(407.9527559055118, 3819.527433070866);
-    expect << QPointF(30.0, 3819.527433070866);
-
-    QTest::newRow("Test case issue #548") << before << expect;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::TestCorrectEquidistantPoints() const
-{
-    QFETCH(QVector<QPointF>, before);
-    QFETCH(QVector<QPointF>, expect);
-
-    QVector<QPointF> after = VAbstractDetail::CorrectEquidistantPoints(before);
-    Comparison(after, expect);
-}
-
-#ifndef Q_OS_WIN
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PossibleInfiniteClearLoops_data() const
-{
-    QTest::addColumn<QVector<QPointF>>("path");
-    QTest::addColumn<QVector<QPointF>>("expect");
-
-    QVector<QPointF> path;
-    path << QPointF(-670.6449010946802, 4046.36220472441);
-    path << QPointF(-1025.9051277126944, 4046.36220472441);
-    path << QPointF(-1026.4460203880594, 4010.5247429150854);
-    path << QPointF(-1027.2972172274538, 3924.202328582098);
-    path << QPointF(-1028.1383921346433, 3768.5948526129496);
-    path << QPointF(-1028.5065585022217, 3521.575730066707);
-    path << QPointF(-1028.2712136539103, 3252.2436039362233);
-    path << QPointF(-1027.2910122410117, 2850.1024469719814);
-    path << QPointF(-1025.9446023682538, 2439.350819630564);
-    path << QPointF(-1025.8983315247287, 2338.629525677473);
-    path << QPointF(-1025.3536572186458, 2309.970015878699);
-    path << QPointF(-1024.2100836932389, 2281.714612342931);
-    path << QPointF(-1022.5102766116828, 2253.846781520112);
-    path << QPointF(-1020.2969016371525, 2226.349989860186);
-    path << QPointF(-1017.6126244328227, 2199.207703813094);
-    path << QPointF(-1014.5001106618688, 2172.403389828782);
-    path << QPointF(-1011.0020259874652, 2145.9205143571917);
-    path << QPointF(-1005.1601480132764, 2106.7277181407126);
-    path << QPointF(-996.3625412018714, 2055.4921956731814);
-    path << QPointF(-986.7906327138169, 2005.2448233555149);
-    path << QPointF(-976.785747854512, 1955.8533327872588);
-    path << QPointF(-961.6606968634906, 1883.0158867454916);
-    path << QPointF(-947.5864881030896, 1811.4914675744105);
-    path << QPointF(-939.2629508127773, 1764.2008199992524);
-    path << QPointF(-933.8852659113251, 1728.8707137815559);
-    path << QPointF(-930.742733377741, 1705.3464944792456);
-    path << QPointF(-928.0252775410311, 1681.829576238578);
-    path << QPointF(-925.7755640643697, 1658.3034255094963);
-    path << QPointF(-924.036258610932, 1634.7515087419433);
-    path << QPointF(-922.850026843893, 1611.1572923858625);
-    path << QPointF(-922.2595344264276, 1587.504242891197);
-    path << QPointF(-922.3074470217107, 1563.7758267078902);
-    path << QPointF(-922.613405031688, 1551.8740157480315);
-    path << QPointF(-960.4086806222392, 841.3228346456693);
-    path << QPointF(-954.9336313684444, 841.5464781141166);
-    path << QPointF(-944.0363771538431, 841.3102753632543);
-    path << QPointF(-933.2160856340209, 840.291423017261);
-    path << QPointF(-922.4878118569704, 838.5316299985567);
-    path << QPointF(-911.8666108706839, 836.0726052295611);
-    path << QPointF(-901.3675377231535, 832.9560576326933);
-    path << QPointF(-891.005647462372, 829.2236961303737);
-    path << QPointF(-880.7959951363317, 824.9172296450213);
-    path << QPointF(-870.7536357930251, 820.0783670990559);
-    path << QPointF(-860.893624480444, 814.7488174148973);
-    path << QPointF(-851.2310162465817, 808.9702895149649);
-    path << QPointF(-841.7808661394299, 802.7844923216785);
-    path << QPointF(-832.5582292069812, 796.2331347574575);
-    path << QPointF(-823.578160497228, 789.3579257447218);
-    path << QPointF(-810.5607800373014, 778.5565764202543);
-    path << QPointF(-794.2367125298769, 763.3635567727296);
-    path << QPointF(-779.1539087770976, 747.6258919346988);
-    path << QPointF(-765.4328091629026, 731.6772532855191);
-    path << QPointF(-753.193854071231, 715.8513122045474);
-    path << QPointF(-742.557483886022, 700.4817400711408);
-    path << QPointF(-733.644138991215, 685.9022082646563);
-    path << QPointF(-726.5742597707488, 672.446388164451);
-    path << QPointF(-721.4682866085625, 660.447951149882);
-    path << QPointF(-718.6229063234249, 651.1532303788147);
-    path << QPointF(-716.6036430255488, 642.9038041285014);
-    path << QPointF(-714.137568179324, 630.1235656609365);
-    path << QPointF(-711.8605525364693, 612.2344502588126);
-    path << QPointF(-710.4560555432737, 593.4222205889721);
-    path << QPointF(-709.4234847119759, 563.5940176156308);
-    path << QPointF(-708.952111561728, 520.4666582691573);
-    path << QPointF(-708.4401766852314, 497.3858267716535);
-    path << QPointF(-400.92922424489655, 469.03937007874015);
-    path << QPointF(-708.4401766852314, 440.6929133858268);
-    path << QPointF(-708.7078446526739, 341.66122584661264);
-    path << QPointF(-709.3427685457568, 299.60322373665383);
-    path << QPointF(-710.6909230403871, 257.048095841136);
-    path << QPointF(-713.0251717477311, 214.57984397612822);
-    path << QPointF(-715.632864794307, 183.1716335401434);
-    path << QPointF(-717.7953694429818, 162.55016633308693);
-    path << QPointF(-720.3578834261159, 142.27891915519677);
-    path << QPointF(-723.3545146951046, 122.43089223348173);
-    path << QPointF(-725.0465030138121, 112.71059563115871);
-    path << QPointF(-219.59055118110237, -35.52755905511811);
-    path << QPointF(-218.99352387527398, -33.21125072212394);
-    path << QPointF(-217.35724543521775, -28.699086141666157);
-    path << QPointF(-215.20035586903225, -24.33136255454731);
-    path << QPointF(-212.53403014110648, -20.10796717265881);
-    path << QPointF(-209.36944321582945, -16.02878720789205);
-    path << QPointF(-205.71777005759026, -12.093709872138447);
-    path << QPointF(-201.59018563077785, -8.302622377289406);
-    path << QPointF(-196.99786489978123, -4.65541193523633);
-    path << QPointF(-189.3170483291933, 0.5638303631539586);
-    path << QPointF(-177.47808861476295, 6.996342387787443);
-    path << QPointF(-163.981333042598, 12.855376387191757);
-    path << QPointF(-148.91618132781048, 18.141834666235646);
-    path << QPointF(-132.37203318551252, 22.856619529787864);
-    path << QPointF(-114.43828833081622, 27.00063328271716);
-    path << QPointF(-95.20434647883366, 30.574778229892296);
-    path << QPointF(-74.75960734467688, 33.57995667618201);
-    path << QPointF(-53.193470643458, 36.01707092645505);
-    path << QPointF(-30.595336090289106, 37.887023285580185);
-    path << QPointF(-7.0546034002822875, 39.19071605842615);
-    path << QPointF(17.339327711450373, 39.929051549861704);
-    path << QPointF(29.858267716535437, 40.06299212598426);
-    path << QPointF(-45.73228346456693, 1589.6692913385828);
-    path << QPointF(-45.73228346456693, 4046.36220472441);
-    path << QPointF(-297.70078740157487, 4046.36220472441);
-    path << QPointF(-297.70078740157487, 2118.8031496062995);
-    path << QPointF(-222.1102362204725, 1589.6692913385828);
-    path << QPointF(-297.70078740157487, 1060.535433070866);
-    path << QPointF(-373.2913385826772, 1589.6692913385828);
-    path << QPointF(-297.70078740157487, 2118.8031496062995);
-    path << QPointF(-297.70078740157487, 4046.36220472441);
-    path << QPointF(-670.6449010946802, 4046.36220472441);
-    path << QPointF(-670.6449010946802, 2024.3149606299214);
-    path << QPointF(-622.7555214134819, 1570.7716535433071);
-    path << QPointF(-670.6449010946802, 1117.2283464566929);
-    path << QPointF(-718.5342807758785, 1570.7716535433071);
-    path << QPointF(-670.6449010946802, 2024.3149606299214);
-
-    QVector<QPointF> expect;
-    expect << QPointF(-670.6449010946802, 4046.36220472441);
-    expect << QPointF(-670.6449010946802, 4046.36220472441);
-    expect << QPointF(-670.6449010946802, 2024.3149606299214);
-    expect << QPointF(-670.6449010946802, 2024.3149606299214);
-    expect << QPointF(-670.6449010946802, 2024.3149606299214);
-
-    // See the file "collection/bugs/possible_inf_loop.val"
-    QTest::newRow("Possible infinite loop") << path << expect;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::PossibleInfiniteClearLoops() const
-{
-    QFETCH(QVector<QPointF>, path);
-    QFETCH(QVector<QPointF>, expect);
-
-    QVector<QPointF> res = VAbstractDetail::CheckLoops(path);
-    Comparison(res, expect);
-}
-#endif //#ifndef Q_OS_WIN
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::Case3() const
-{
-    const QVector<QPointF> points = InputPointsCase3(); // Input points.
-
-    const qreal result = VAbstractDetail::SumTrapezoids(points);
-    QVERIFY(result < 0);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::Case4() const
-{
-    const QVector<QPointF> points = InputPointsCase4(); // Input points.
-
-    const qreal result = VAbstractDetail::SumTrapezoids(points);
-    QVERIFY(result > 0);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-void TST_VAbstractDetail::Case5() const
-{
-    const QVector<QPointF> points = InputPointsCase5(); // Input points.
-
-    const qreal result = VAbstractDetail::SumTrapezoids(points);
-    QVERIFY(qFuzzyIsNull(result));
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsIssue298Case1() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(35, 39.9999);
-    points += QPointF(412.953, 39.9999);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(408.797, 405.589);
-    points += QPointF(390.909, 377.669);
-    points += QPointF(362.315, 330.86);
-    points += QPointF(323.075, 264.247);
-    points += QPointF(286.15, 201.448);
-    points += QPointF(262.477, 162.745);
-    points += QPointF(249.22, 142.455);
-    points += QPointF(241.092, 131.261);
-    points += QPointF(236.545, 125.75);
-    points += QPointF(232.808, 122.058);
-    points += QPointF(230.6, 120.629);
-    points += QPointF(229.393, 120.277);
-    points += QPointF(228.421, 120.456);
-    points += QPointF(227.69, 121.185);
-    points += QPointF(227.033, 123.272);
-    points += QPointF(227.112, 128.232);
-    points += QPointF(228.29, 135.699);
-    points += QPointF(230.625, 145.81);
-    points += QPointF(234.173, 158.703);
-    points += QPointF(241.73, 183.168);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(251.528, 212.406);
-    points += QPointF(255.482, 227.075);
-    points += QPointF(257.717, 239.591);
-    points += QPointF(258.279, 247.554);
-    points += QPointF(258.203, 252.278);
-    points += QPointF(257.756, 256.51);
-    points += QPointF(256.949, 260.264);
-    points += QPointF(255.795, 263.547);
-    points += QPointF(254.308, 266.372);
-    points += QPointF(252.501, 268.749);
-    points += QPointF(250.385, 270.688);
-    points += QPointF(247.974, 272.201);
-    points += QPointF(245.281, 273.296);
-    points += QPointF(242.319, 273.986);
-    points += QPointF(239.1, 274.28);
-    points += QPointF(233.846, 274.05);
-    points += QPointF(226.022, 272.393);
-    points += QPointF(217.402, 269.345);
-    points += QPointF(208.09, 264.991);
-    points += QPointF(198.186, 259.414);
-    points += QPointF(187.795, 252.7);
-    points += QPointF(177.019, 244.933);
-    points += QPointF(165.96, 236.197);
-    points += QPointF(154.721, 226.576);
-    points += QPointF(143.405, 216.157);
-    points += QPointF(132.113, 205.022);
-    points += QPointF(120.95, 193.257);
-    points += QPointF(110.017, 180.946);
-    points += QPointF(99.4167, 168.174);
-    points += QPointF(89.2522, 155.024);
-    points += QPointF(79.626, 141.582);
-    points += QPointF(70.6405, 127.933);
-    points += QPointF(62.3985, 114.16);
-    points += QPointF(55.0025, 100.348);
-    points += QPointF(48.5551, 86.5823);
-    points += QPointF(43.159, 72.9466);
-    points += QPointF(38.9167, 59.5258);
-    points += QPointF(35.9309, 46.4042);
-    points += QPointF(35, 39.9999);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::OutputPointsIssue298Case1() const
-{
-    QVector<QPointF> points;
-    points += QPointF(-52.3724798442221, -35.5907);
-    points += QPointF(487.7117748779425, -35.5907);
-    points += QPointF(493.3432017362585, 473.32371517914754);
-    points += QPointF(385.98559977345093, 506.8445742667132);
-    points += QPointF(345.64704646524604, 447.1446764706891);
-    points += QPointF(326.82411403464874, 417.76541252489994);
-    points += QPointF(297.4844355409708, 369.73572061014266);
-    points += QPointF(280.35686644039447, 340.63425704493835);
-    points += QPointF(268.2336759982877, 345.56366422433183);
-    points += QPointF(254.38869069377708, 348.78886336684104);
-    points += QPointF(240.8928242225697, 350.0214774527481);
-    points += QPointF(224.29748398011193, 349.2949970081793);
-    points += QPointF(205.50330859478322, 345.31468660256957);
-    points += QPointF(188.72568121178054, 339.38217984347546);
-    points += QPointF(173.487571907339, 332.2573164509149);
-    points += QPointF(159.09346043909582, 324.15190856941325);
-    points += QPointF(145.1562378134811, 315.1465661857729);
-    points += QPointF(131.46917217609203, 305.28136213922494);
-    points += QPointF(117.9345600633141, 294.589765121662);
-    points += QPointF(104.5254725457231, 283.11108988305153);
-    points += QPointF(91.25156649455745, 270.88938370179534);
-    points += QPointF(78.14294517511125, 257.9630200468154);
-    points += QPointF(65.25722328495372, 244.3823949426573);
-    points += QPointF(52.65759889494496, 230.19470850111355);
-    points += QPointF(40.412239584772514, 215.4406233233806);
-    points += QPointF(28.600027181043494, 200.15894757848054);
-    points += QPointF(17.304913602921047, 184.38648111018338);
-    points += QPointF(6.6105681133211736, 168.14173996194046);
-    points += QPointF(-3.3897319816688407, 151.43048866270516);
-    points += QPointF(-12.592267484961765, 134.24479093805914);
-    points += QPointF(-20.880547263016442, 116.54866956498358);
-    points += QPointF(-28.111192294561146, 98.27715746242171);
-    points += QPointF(-34.098213657706594, 79.33681465062016);
-    points += QPointF(-38.441724866417594, 60.24852451858777);
-    points += QPointF(-52.3724798442221, -35.5907);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsIssue298Case2() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(35, 39.9999);
-    points += QPointF(35, 39.9999);
-    points += QPointF(35.9309, 46.4042);
-    points += QPointF(38.9167, 59.5258);
-    points += QPointF(43.159, 72.9466);
-    points += QPointF(48.5551, 86.5823);
-    points += QPointF(55.0025, 100.348);
-    points += QPointF(62.3985, 114.16);
-    points += QPointF(70.6405, 127.933);
-    points += QPointF(79.626, 141.582);
-    points += QPointF(89.2522, 155.024);
-    points += QPointF(99.4167, 168.174);
-    points += QPointF(110.017, 180.946);
-    points += QPointF(120.95, 193.257);
-    points += QPointF(132.113, 205.022);
-    points += QPointF(143.405, 216.157);
-    points += QPointF(154.721, 226.576);
-    points += QPointF(165.96, 236.197);
-    points += QPointF(177.019, 244.933);
-    points += QPointF(187.795, 252.7);
-    points += QPointF(198.186, 259.414);
-    points += QPointF(208.09, 264.991);
-    points += QPointF(217.402, 269.345);
-    points += QPointF(226.022, 272.393);
-    points += QPointF(233.846, 274.05);
-    points += QPointF(239.1, 274.28);
-    points += QPointF(242.319, 273.986);
-    points += QPointF(245.281, 273.296);
-    points += QPointF(247.974, 272.201);
-    points += QPointF(250.385, 270.688);
-    points += QPointF(252.501, 268.749);
-    points += QPointF(254.308, 266.372);
-    points += QPointF(255.795, 263.547);
-    points += QPointF(256.949, 260.264);
-    points += QPointF(257.756, 256.51);
-    points += QPointF(258.203, 252.278);
-    points += QPointF(258.279, 247.554);
-    points += QPointF(257.717, 239.591);
-    points += QPointF(255.482, 227.075);
-    points += QPointF(251.528, 212.406);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(241.73, 183.168);
-    points += QPointF(234.173, 158.703);
-    points += QPointF(230.625, 145.81);
-    points += QPointF(228.29, 135.699);
-    points += QPointF(227.112, 128.232);
-    points += QPointF(227.033, 123.272);
-    points += QPointF(227.69, 121.185);
-    points += QPointF(228.421, 120.456);
-    points += QPointF(229.393, 120.277);
-    points += QPointF(230.6, 120.629);
-    points += QPointF(232.808, 122.058);
-    points += QPointF(236.545, 125.75);
-    points += QPointF(241.092, 131.261);
-    points += QPointF(249.22, 142.455);
-    points += QPointF(262.477, 162.745);
-    points += QPointF(286.15, 201.448);
-    points += QPointF(323.075, 264.247);
-    points += QPointF(362.315, 330.86);
-    points += QPointF(390.909, 377.669);
-    points += QPointF(408.797, 405.589);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(35, 417.953);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::OutputPointsIssue298Case2() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(-2.7952999999999975, 4.8384699505981095);
-    points += QPointF(67.34448942068963, -0.23248582689164274);
-    points += QPointF(73.11721243320879, 39.48203774070609);
-    points += QPointF(75.42415682885321, 49.62029267468959);
-    points += QPointF(78.79409614728041, 60.281321268788744);
-    points += QPointF(83.27292363150828, 71.59911521750833);
-    points += QPointF(88.79988374248082, 83.39960453097031);
-    points += QPointF(95.2926159908344, 95.5247556686474);
-    points += QPointF(102.65546594334339, 107.82863001903641);
-    points += QPointF(110.78654319853989, 120.17975944490887);
-    points += QPointF(119.5782864094781, 132.4565262107595);
-    points += QPointF(128.91893020761376, 144.54068833830968);
-    points += QPointF(138.69670055252752, 156.3216457494432);
-    points += QPointF(148.79638835752286, 167.69430252867102);
-    points += QPointF(159.09802741244354, 178.55148997659143);
-    points += QPointF(169.48171675272164, 188.79080814910267);
-    points += QPointF(179.81876372713828, 198.30845505847407);
-    points += QPointF(189.9727199683426, 207.00061743916868);
-    points += QPointF(199.7939139119543, 214.75881893038778);
-    points += QPointF(209.1143810932559, 221.476716907111);
-    points += QPointF(216.03386663545683, 225.9476461661168);
-    points += QPointF(215.3306509043856, 223.3387762725701);
-    points += QPointF(205.75073516810195, 194.75155680967347);
-    points += QPointF(197.88802785264718, 169.29686123304236);
-    points += QPointF(193.97579117825833, 155.08026950731082);
-    points += QPointF(191.1640933645057, 142.90507610480435);
-    points += QPointF(189.3638602852325, 131.49392126360493);
-    points += QPointF(189.14507682295456, 117.75764312564759);
-    points += QPointF(194.42693552963567, 100.97950138920423);
-    points += QPointF(210.03879336533757, 85.41035725481989);
-    points += QPointF(231.36634627769158, 81.48275234606332);
-    points += QPointF(246.4916615881645, 85.89378050620131);
-    points += QPointF(256.60614755001956, 92.43979519799973);
-    points += QPointF(264.4750900046005, 100.21398185636762);
-    points += QPointF(270.9888544453203, 108.1087159300009);
-    points += QPointF(280.35077918473866, 121.00209505562212);
-    points += QPointF(294.42535276480356, 142.5434013797918);
-    points += QPointF(318.5597512322288, 182.00074197391842);
-    points += QPointF(394.73028222951507, 311.42213969492946);
-    points += QPointF(422.9514429826756, 357.62079373755);
-    points += QPointF(440.37197676737753, 384.8111617646563);
-    points += QPointF(488.2841719585649, 455.71983154868764);
-    points += QPointF(-2.795300000000013, 455.7506738094777);
-    points += QPointF(-2.7952999999999975, 4.8384699505981095);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsIssue548Case1() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(236.97989607468364, 65.89325192030674);
-    points += QPointF(198.93409106041895, 172.04876297154925);
-    points += QPointF(260.32251114299453, 75.38027418944861);
-    points += QPointF(324.54110236213444, 101.48031496062993);
-    points += QPointF(29.858267716535437, 300.85039370078744);
-    points += QPointF(99.86433649395013, 10.166060970128015);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::OutputPointsIssue548Case1() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(251.32210577118798, 59.48301432799721);
-    points += QPointF(243.9841262159756, 79.95746530820585);
-    points += QPointF(255.82424817748586, 61.31279754390509);
-    points += QPointF(348.48337789725855, 98.9717841021069);
-    points += QPointF(29.780382054543473, 314.59289909613994);
-    points += QPointF(17.01672179602679, 305.7450049304056);
-    points += QPointF(91.92616539550944, -5.299480329501037);
-    points += QPointF(251.32210577118798, 59.48301432799721);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsIssue548Case2() const
-{
-    QVector<QPointF> points;
-    points << QPointF(99.86433649395013, 10.166060970128015);
-    points << QPointF(236.97989607468364, 65.89325192030674);
-    points << QPointF(198.93409106041895, 172.04876297154925);
-    points << QPointF(260.32251114299453, 75.38027418944861);
-    points << QPointF(324.54110236213444, 101.48031496062993);
-    points << QPointF(29.858267716535437, 300.85039370078744);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::OutputPointsIssue548Case2() const
-{
-    QVector<QPointF> points;
-    points << QPointF(73.40376616581447, -41.38574336196901);
-    points << QPointF(245.32830125796568, 28.488685370970344);
-    points << QPointF(245.32830125796573, 28.488685370970277);
-    points << QPointF(404.3486874792147, 93.11854543221973);
-    points << QPointF(29.598648843228922, 346.6587450186291);
-    points << QPointF(-12.946885351826726, 317.1657644661815);
-    points << QPointF(73.40376616581447, -41.38574336196901);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsIssue548Case3() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(99.86433649395013, 10.166060970128015);
-    points += QPointF(236.97989607468364, 65.89325192030674);
-    points += QPointF(198.93409106041895, 172.04876297154925);
-    points += QPointF(260.32251114299453, 75.38027418944861);
-    points += QPointF(324.54110236213444, 101.48031496062993);
-    points += QPointF(29.858267716535437, 300.85039370078744);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::OutputPointsIssue548Case3() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(46.94319583767885, -92.9375476940661);
-#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
-    points += QPointF(234.2633962639462, -16.805935717278903);
-#else
-    points += QPointF(238.798634936, -14.9627013515);
-#endif
-    points += QPointF(484.15627259629446, 84.75677590380938);
-    points += QPointF(29.339029969922702, 392.46709633647066);
-    points += QPointF(-55.75203842018885, 333.48113523157537);
-    points += QPointF(46.94319583767885, -92.9375476940661);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsCase3() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(35, 35);
-    points += QPointF(50, 50);
-    points += QPointF(15, 50);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsCase4() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(15, 15);
-    points += QPointF(15, 50);
-    points += QPointF(50, 50);
-
-    return points;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractDetail::InputPointsCase5() const
-{
-    QVector<QPointF> points;
-
-    points += QPointF(35, 35);
-
-    return points;
-}
diff --git a/src/test/ValentinaTest/tst_vabstractdetail.h b/src/test/ValentinaTest/tst_vabstractdetail.h
deleted file mode 100644
index 3ae4094dd..000000000
--- a/src/test/ValentinaTest/tst_vabstractdetail.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/************************************************************************
- **
- **  @file   tst_vabstractdetail.h
- **  @author Roman Telezhynskyi <dismine(at)gmail.com>
- **  @date   16 4, 2015
- **
- **  @brief
- **  @copyright
- **  This source code is part of the Valentine project, a pattern making
- **  program, whose allow create and modeling patterns of clothing.
- **  Copyright (C) 2015 Valentina project
- **  <https://bitbucket.org/dismine/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 TST_VABSTRACTDETAIL_H
-#define TST_VABSTRACTDETAIL_H
-
-#include "../vmisc/abstracttest.h"
-
-class TST_VAbstractDetail : public AbstractTest
-{
-    Q_OBJECT
-public:
-    explicit TST_VAbstractDetail(QObject *parent = nullptr);
-
-signals:
-
-private slots:
-    void EquidistantRemoveLoop_data();
-    void EquidistantRemoveLoop() const;
-    void SumTrapezoids() const;
-    void PathRemoveLoop_data() const;
-    void PathRemoveLoop() const;
-    void PathLoopsCase_data() const;
-    void PathLoopsCase() const;
-    void BrokenDetailEquidistant_data() const;
-    void BrokenDetailEquidistant() const;
-    void CorrectEquidistantPoints_data() const;
-    void CorrectEquidistantPoints() const;
-    void TestCorrectEquidistantPoints_data();
-    void TestCorrectEquidistantPoints() const;
-#ifndef Q_OS_WIN
-    void PossibleInfiniteClearLoops_data() const;
-    void PossibleInfiniteClearLoops() const;
-#endif
-
-private:
-    void Case3() const;
-    void Case4() const;
-    void Case5() const;
-
-    QVector<QPointF> InputPointsIssue298Case1() const;
-    QVector<QPointF> OutputPointsIssue298Case1() const;
-
-    QVector<QPointF> InputPointsIssue298Case2() const;
-    QVector<QPointF> OutputPointsIssue298Case2() const;
-
-    QVector<QPointF> InputPointsIssue548Case1() const;
-    QVector<QPointF> OutputPointsIssue548Case1() const;
-
-    QVector<QPointF> InputPointsIssue548Case2() const;
-    QVector<QPointF> OutputPointsIssue548Case2() const;
-
-    QVector<QPointF> InputPointsIssue548Case3() const;
-    QVector<QPointF> OutputPointsIssue548Case3() const;
-
-    QVector<QPointF> InputPointsCase3() const;
-    QVector<QPointF> InputPointsCase4() const;
-    QVector<QPointF> InputPointsCase5() const;
-
-};
-
-#endif // TST_VABSTRACTDETAIL_H
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp
index fc8f67453..553771c60 100644
--- a/src/test/ValentinaTest/tst_vabstractpiece.cpp
+++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp
@@ -60,6 +60,35 @@ void TST_VAbstractPiece::EquidistantRemoveLoop_data()
     QTest::newRow("Seam test 3") << InputPointsCase3()
                                  << 37.795275590551185 // seam allowance width
                                  << OutputPointsCase3();
+
+    // These are two real cases where equdistant has loop.
+    // See issue #298. Segmented Curve isn't selected in Seam Allowance tool.
+    // https://bitbucket.org/dismine/valentina/issue/298/segmented-curve-isnt-selected-in-seam
+    // Code should clean loops in path.
+    QTest::newRow("Issue 298. Case1") << InputPointsIssue298Case1()
+                                      << 75.5906 // seam allowance width
+                                      << OutputPointsIssue298Case1();
+
+    QTest::newRow("Issue 298. Case2") << InputPointsIssue298Case2()
+                                      << 37.7953 // seam allowance width
+                                      << OutputPointsIssue298Case2();
+
+    // See issue #548. Bug Detail tool. Case when seam allowance is wrong.
+    // https://bitbucket.org/dismine/valentina/issues/548/bug-detail-tool-case-when-seam-allowance
+    // Files: Steampunk_trousers.val and marie.vit
+    // Actually buggy detail see in file src/app/share/collection/bugs/Steampunk_trousers_issue_#548.val
+    // Code should clean loops in path.
+    QTest::newRow("Issue 548. Case1") << InputPointsIssue548Case1()
+                                      << 11.338582677165354 // seam allowance width (0.3 cm)
+                                      << OutputPointsIssue548Case1();
+
+    QTest::newRow("Issue 548. Case2") << InputPointsIssue548Case2()
+                                      << 37.795275590551185 // seam allowance width (1.0 cm)
+                                      << OutputPointsIssue548Case2();
+
+    QTest::newRow("Issue 548. Case3") << InputPointsIssue548Case3()
+                                      << 75.59055118110237 // seam allowance width (2.0 cm)
+                                      << OutputPointsIssue548Case3();
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1663,3 +1692,1285 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsCase3() const
 
     return points;
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::SumTrapezoids() const
+{
+    // Case3 checks that the method 'SumTrapezoids' returns negative value for three clockwise allocated points
+    // Case4 checks that the method 'SumTrapezoids' returns positive value for three counterclock-wise allocated points
+    // Case5 checks that the method 'SumTrapezoids' returns 0 for one point
+    Case3();
+    Case4();
+    Case5();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PathRemoveLoop_data() const
+{
+    QTest::addColumn<QVector<QPointF>>("path");
+    QTest::addColumn<QVector<QPointF>>("expect");
+
+    QVector<QPointF> path;
+    path << QPointF(10, 10);
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 20);
+    path << QPointF(10, 10);
+    QTest::newRow("Correct closed a path (four unique points)") << path << path;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+#else
+    path.removeLast();
+#endif
+    QTest::newRow("Correct unclosed a path (four unique points)") << path << path;
+
+    path.clear();
+    path << QPointF(0, 10);
+    path << QPointF(10, 10);
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+    QTest::newRow("Correct closed a path (six unique points)") << path << path;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+#else
+    path.removeLast();
+#endif
+    QTest::newRow("Correct unclosed a path (six unique points)") << path << path;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 10);
+    path << QPointF(10, 20);
+    path << QPointF(20, 10);
+
+    QVector<QPointF> res;
+    res << QPointF(20, 10);
+    res << QPointF(20, 20);
+    res << QPointF(15, 15);
+    res << QPointF(20, 10);
+    QTest::newRow("One loop, closed a path (four unique points)") << path << res;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+    res.remove(res.size() - 1);
+#else
+    path.removeLast();
+    res.removeLast();
+#endif
+    QTest::newRow("One loop, unclosed a path (four unique points)") << path << res;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 10);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+    path << QPointF(10, 20);
+    path << QPointF(20, 10);
+
+    res.clear();
+    res << QPointF(20, 10);
+    res << QPointF(20, 20);
+    res << QPointF(15, 15);
+    res << QPointF(20, 10);
+    QTest::newRow("Two loops, closed a path (six unique points)") << path << res;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+    res.remove(res.size() - 1);
+#else
+    path.removeLast();
+    res.removeLast();
+#endif
+    QTest::newRow("Two loops, unclosed a path (six unique points)") << path << res;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 10);
+    path << QPointF(0, 10);
+    path << QPointF(0, 20);
+    path << QPointF(10, 20);
+    path << QPointF(20, 10);
+
+    res.clear();
+    res << QPointF(20, 10);
+    res << QPointF(20, 20);
+    res << QPointF(15, 15);
+    res << QPointF(20, 10);
+    QTest::newRow("One loop, the first loop, closed a path (six unique points)") << path << res;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+    res.remove(res.size() - 1);
+#else
+    path.removeLast();
+    res.removeLast();
+#endif
+    QTest::newRow("One loop, the first loop, unclosed a path (six unique points)") << path << res;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 20);
+    path << QPointF(0, 10);
+    path << QPointF(0, 20);
+    path << QPointF(10, 10);
+    path << QPointF(20, 10);
+
+    res.clear();
+    res << QPointF(20, 10);
+    res << QPointF(20, 20);
+    res << QPointF(10, 20);
+    res << QPointF(5, 15);
+    res << QPointF(10, 10);
+    res << QPointF(20, 10);
+    QTest::newRow("One loop, the second loop, closed a path (six unique points)") << path << res;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+    res.remove(res.size() - 1);
+#else
+    path.removeLast();
+    res.removeLast();
+#endif
+    QTest::newRow("One loop, the second loop, unclosed a path (six unique points)") << path << res;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(20, 20);
+    path << QPointF(10, 20);
+    path << QPointF(20, 15);
+    path << QPointF(10, 10);
+    path << QPointF(20, 10);
+    QTest::newRow("Correct closed a path, point on line (four unique points)") << path << path;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+#else
+    path.removeLast();
+#endif
+    QTest::newRow("Corect unclosed a path, point on line (four unique points)") << path << path;
+
+    path.clear();
+    path << QPointF(20, 10);
+    path << QPointF(10, 15);
+    path << QPointF(20, 20);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(10, 15);
+    path << QPointF(0, 10);
+    path << QPointF(10, 10);
+    path << QPointF(20, 10);
+
+    QTest::newRow("Correct closed a path, point on line (six unique points)") << path << path;
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+    path.remove(path.size() - 1);
+#else
+    path.removeLast();
+#endif
+    QTest::newRow("Corect unclosed a path, point on line (six unique points)") << path << path;
+
+    path.clear();
+    path << QPointF(100.96979100571033, 1797.6153764073072);
+    path << QPointF(168.3888427659865, 1807.2395034187866);
+    path << QPointF(206.78076137364403, 1812.2910842036706);
+    path << QPointF(239.1630793382262, 1815.951361623424);
+    path << QPointF(267.5320085054171, 1818.4827543754482);
+    path << QPointF(293.9502505847841, 1820.144031725603);
+    path << QPointF(320.48133946750147, 1821.175819320443);
+    path << QPointF(364.5960626489172, 1822.0507669842166);
+    path << QPointF(400.66867742260206, 1822.488188976378);
+    path << QPointF(623.3126833308274, 1822.488188976378);
+    path << QPointF(653.5489038032683, 2162.6456692913384);
+    path << QPointF(570.545584385708, 2162.6456692913384);
+    path << QPointF(600.7818048581489, 1822.488188976378);
+    path << QPointF(1001.3385826771654, 1822.488188976378);
+    path << QPointF(1001.3385826771654, 2680.44094488189);
+    path << QPointF(-22.11646613738226, 2680.44094488189);
+    path << QPointF(100.96979100571033, 1797.6153764073072);
+
+    res.clear();
+    res << QPointF(100.96979100571033, 1797.6153764073072);
+    res << QPointF(168.3888427659865, 1807.2395034187866);
+    res << QPointF(206.78076137364403, 1812.2910842036706);
+    res << QPointF(239.1630793382262, 1815.951361623424);
+    res << QPointF(267.5320085054171, 1818.4827543754482);
+    res << QPointF(293.9502505847841, 1820.144031725603);
+    res << QPointF(320.48133946750147, 1821.175819320443);
+    res << QPointF(364.5960626489172, 1822.0507669842166);
+    res << QPointF(400.66867742260206, 1822.488188976378);
+    res << QPointF(1001.3385826771654, 1822.488188976378);
+    res << QPointF(1001.3385826771654, 2680.44094488189);
+    res << QPointF(-22.11646613738226, 2680.44094488189);
+    res << QPointF(100.96979100571033, 1797.6153764073072);
+
+    // See the file "collection/bugs/Issue_#493.val"
+    QTest::newRow("Test case issue #493") << path << res;
+
+    path.clear();
+    path << QPointF(-685.2149804319953, -3568.7982439212556);
+    path << QPointF(-700.7415523087261, -3623.900571239949);
+    path << QPointF(-675.4694480627154, -3639.3631430823175);
+    path << QPointF(-684.7497934439581, -3631.3546395862268);
+    path << QPointF(-683.1356602239256, -3633.2868478418427);
+    path << QPointF(-686.8764821039574, -3627.927414863926);
+    path << QPointF(-684.7670104817863, -3631.587853202178);
+    path << QPointF(-682.2386030572435, -3636.8469922361573);
+    path << QPointF(-676.4708011186385, -3650.307478525872);
+    path << QPointF(-666.3050989871189, -3676.5286567894937);
+    path << QPointF(-654.0449409043066, -3710.198553447806);
+    path << QPointF(-640.1333287371614, -3750.0101920374505);
+    path << QPointF(-617.0729873733014, -3818.3303697354913);
+    path << QPointF(-583.8128392515604, -3920.9726624886944);
+    path << QPointF(-550.5307668482033, -4027.6970214479597);
+    path << QPointF(-527.4164674104215, -4104.7034088569535);
+    path << QPointF(-513.4302533332675, -4152.73879565781);
+    path << QPointF(-501.0373006826446, -4196.767296675345);
+    path << QPointF(-490.59311078227046, -4235.660899517831);
+    path << QPointF(-477.25724163384456, -4288.293444470835);
+    path << QPointF(-405.3839593893572, -4272.013803282615);
+    path << QPointF(-545.9786893428341, -3568.830152982464);
+    path << QPointF(-685.2149804319953, -3568.7982439212556);
+
+    res.clear();
+    res << QPointF(-685.2149804319953, -3568.7982439212556);
+    res << QPointF(-700.7415523087261, -3623.900571239949);
+    res << QPointF(-683.3457668881176, -3634.5440688767967);
+    res << QPointF(-682.2386030572435, -3636.8469922361573);
+    res << QPointF(-676.4708011186385, -3650.307478525872);
+    res << QPointF(-666.3050989871189, -3676.5286567894937);
+    res << QPointF(-654.0449409043066, -3710.198553447806);
+    res << QPointF(-640.1333287371614, -3750.0101920374505);
+    res << QPointF(-617.0729873733014, -3818.3303697354913);
+    res << QPointF(-583.8128392515604, -3920.9726624886944);
+    res << QPointF(-550.5307668482033, -4027.6970214479597);
+    res << QPointF(-527.4164674104215, -4104.7034088569535);
+    res << QPointF(-513.4302533332675, -4152.73879565781);
+    res << QPointF(-501.0373006826446, -4196.767296675345);
+    res << QPointF(-490.59311078227046, -4235.660899517831);
+    res << QPointF(-477.25724163384456, -4288.293444470835);
+    res << QPointF(-405.3839593893572, -4272.013803282615);
+    res << QPointF(-545.9786893428341, -3568.830152982464);
+    res << QPointF(-685.2149804319953, -3568.7982439212556);
+
+    // See the file "collection/bugs/Issue_#515.val"
+    // Check a seam allowance path.
+    // The curve that causes the issue is the first in the list.
+    QTest::newRow("Test case issue #515. Big loop in seam allowance path.") << path << res;
+
+    path.clear();
+    path << QPointF(-449.6699112298347, -4243.2921010175705);
+    path << QPointF(-576.966638263205, -3606.6183279948636);
+    path << QPointF(-656.9465284876832, -3606.6183279948636);
+    path << QPointF(-656.5996104603414, -3606.6000783462687);
+    path << QPointF(-655.7439133016985, -3607.1236310612317);
+    path << QPointF(-654.129780081666, -3609.0558393168476);
+    path << QPointF(-651.3154902471701, -3613.939306009108);
+    path << QPointF(-647.8207651830382, -3621.2084054506768);
+    path << QPointF(-641.4701586077349, -3636.0289997859454);
+    path << QPointF(-630.9244502073004, -3663.23035747934);
+    path << QPointF(-618.4465305467888, -3697.4982896415795);
+    path << QPointF(-604.3873016966293, -3737.732371148936);
+    path << QPointF(-581.1891087215608, -3806.460957656939);
+    path << QPointF(-547.7936207285052, -3909.520915257629);
+    path << QPointF(-514.3891332445846, -4016.6378180116963);
+    path << QPointF(-491.17181635142833, -4093.9874129706236);
+    path << QPointF(-477.094588519539, -4142.335384784734);
+    path << QPointF(-464.5941701318652, -4186.745679830414);
+    path << QPointF(-454.0214632588362, -4226.117872983938);
+
+    res.clear();
+    res << QPointF(-449.6699112298347, -4243.2921010175705);
+    res << QPointF(-576.966638263205, -3606.6183279948636);
+    res << QPointF(-656.5697831440032, -3606.6183279948636);
+    res << QPointF(-655.7439133016985, -3607.1236310612317);
+    res << QPointF(-654.129780081666, -3609.0558393168476);
+    res << QPointF(-651.3154902471701, -3613.939306009108);
+    res << QPointF(-647.8207651830382, -3621.2084054506768);
+    res << QPointF(-641.4701586077349, -3636.0289997859454);
+    res << QPointF(-630.9244502073004, -3663.23035747934);
+    res << QPointF(-618.4465305467888, -3697.4982896415795);
+    res << QPointF(-604.3873016966293, -3737.732371148936);
+    res << QPointF(-581.1891087215608, -3806.460957656939);
+    res << QPointF(-547.7936207285052, -3909.520915257629);
+    res << QPointF(-514.3891332445846, -4016.6378180116963);
+    res << QPointF(-491.17181635142833, -4093.9874129706236);
+    res << QPointF(-477.094588519539, -4142.335384784734);
+    res << QPointF(-464.5941701318652, -4186.745679830414);
+    res << QPointF(-454.0214632588362, -4226.117872983938);
+
+    // See the file "collection/bugs/Issue_#515.val"
+    // Check a seam allowance path.
+    // The curve that causes the issue is the last in the list.
+    QTest::newRow("Test case issue #515. Small loop in seam allowance path.") << path << res;
+
+    path.clear();
+    path << QPointF(1229.6503937007876, 937.6667716535435);
+    path << QPointF(203.08931117793543, 937.6667716535435);
+    path << QPointF(459.7677349767701, -2166.704563141019);
+    path << QPointF(1229.6503937007876, -1990.077167189857);
+    path << QPointF(1229.6503937007876, -555.2466141732282);
+    path << QPointF(920.1053824527112, -555.2466141732282);
+    path << QPointF(887.034516310979, -63.90803149606281);
+    path << QPointF(816.3607592795726, -63.908031496062826);
+    path << QPointF(780.7580397937137, -592.8627210002539);
+    path << QPointF(816.0241340748559, -1202.917917917055);
+    path << QPointF(887.3711415156957, -1202.917917917055);
+    path << QPointF(920.4420076574283, -630.8371653543306);
+    path << QPointF(1229.6503937007876, -630.8371653543306);
+    path << QPointF(1229.6503937007876, 937.6667716535435);
+
+    res.clear();
+    res << QPointF(1229.6503937007876, 937.6667716535435);
+    res << QPointF(203.08931117793543, 937.6667716535435);
+    res << QPointF(459.7677349767702, -2166.704563141019);
+    res << QPointF(1229.6503937007876, -1990.077167189857);
+    res << QPointF(1229.6503937007876, 937.6667716535435);
+
+    // See the file "collection/bugs/Issue_#603.val"
+    // Point H1 is first in the list
+    QTest::newRow("Test issue 603.") << path << res;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PathRemoveLoop() const
+{
+    QFETCH(QVector<QPointF>, path);
+    QFETCH(QVector<QPointF>, expect);
+
+    QVector<QPointF> res = VAbstractPiece::CheckLoops(path);
+    Comparison(res, expect);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PathLoopsCase_data() const
+{
+    QTest::addColumn<QVector<QPointF>>("path");
+    QTest::addColumn<QVector<QPointF>>("expect");
+
+    QVector<QPointF> path;
+    path << QPointF(61.86670866141733, 446.92270866141735);
+    path << QPointF(650.6504606788366, 473.2192016666484);
+    path << QPointF(649.4426552757304, 480.5376973511262);
+    path << QPointF(646.5769170924987, 501.9977838630714);
+    path << QPointF(644.6382908004568, 523.6358081043691);
+    path << QPointF(643.4592698551749, 551.9888717674471);
+    path << QPointF(642.9134698671897, 584.1776423714557);
+    path << QPointF(643.1914832622404, 613.2382010061506);
+    path << QPointF(644.2199668178571, 639.3780275889782);
+    path << QPointF(645.9255773115714, 662.8046020373845);
+    path << QPointF(648.2349715209137, 683.7254042688159);
+    path << QPointF(651.0748062234152, 702.3479142007185);
+    path << QPointF(654.3717381966065, 718.8796117505387);
+    path << QPointF(658.0524242180187, 733.5279768357226);
+    path << QPointF(662.0435210651824, 746.5004893737165);
+    path << QPointF(666.2716855156286, 758.0046292819667);
+    path << QPointF(670.6635743468883, 768.2478764779191);
+    path << QPointF(677.400406718071, 781.7952098705392);
+    path << QPointF(691.6740007010135, 806.2608114022295);
+    path << QPointF(694.5877745571677, 810.2150054671212);
+    path << QPointF(699.9560352035193, 816.1706553153153);
+    path << QPointF(708.9007628091615, 824.0594196166176);
+    path << QPointF(719.3794725391945, 831.7499791040799);
+    path << QPointF(730.9568541500198, 839.0942359684872);
+    path << QPointF(743.1975973980386, 845.9440924006244);
+    path << QPointF(755.6663920396528, 852.1514505912763);
+    path << QPointF(767.9279278312633, 857.568212731228);
+    path << QPointF(779.5468945292718, 862.046281011264);
+    path << QPointF(790.0879818900794, 865.4375576221694);
+    path << QPointF(799.115879670088, 867.5939447547289);
+    path << QPointF(804.5608128209333, 868.2650594004886);
+    path << QPointF(807.5317661719646, 868.2782441618697);
+    path << QPointF(809.8795601157717, 867.8994015359809);
+    path << QPointF(811.5497808719051, 867.1100192966705);
+    path << QPointF(812.4880146599148, 865.8915852177861);
+    path << QPointF(812.6398476993509, 864.2255870731761);
+    path << QPointF(811.9508662097637, 862.0935126366886);
+    path << QPointF(810.3666564107034, 859.4768496821717);
+    path << QPointF(806.3216663321919, 854.66911491981);
+    path << QPointF(802.0871811023624, 850.6707401574804);
+    path << QPointF(799.4598981526765, 850.6707401574804);
+    path << QPointF(802.0871811023624, 1653.9337322834645);
+    path << QPointF(61.86670866141733, 1653.9337322834645);
+
+    QVector<QPointF> res;
+    res << QPointF(61.86670866141733, 446.92270866141735);
+    res << QPointF(650.6504606788366, 473.2192016666484);
+    res << QPointF(649.4426552757304, 480.5376973511262);
+    res << QPointF(646.5769170924987, 501.9977838630714);
+    res << QPointF(644.6382908004568, 523.6358081043691);
+    res << QPointF(643.4592698551749, 551.9888717674471);
+    res << QPointF(642.9134698671897, 584.1776423714557);
+    res << QPointF(643.1914832622404, 613.2382010061506);
+    res << QPointF(644.2199668178571, 639.3780275889782);
+    res << QPointF(645.9255773115714, 662.8046020373845);
+    res << QPointF(648.2349715209137, 683.7254042688159);
+    res << QPointF(651.0748062234152, 702.3479142007185);
+    res << QPointF(654.3717381966065, 718.8796117505387);
+    res << QPointF(658.0524242180187, 733.5279768357226);
+    res << QPointF(662.0435210651824, 746.5004893737165);
+    res << QPointF(666.2716855156286, 758.0046292819667);
+    res << QPointF(670.6635743468883, 768.2478764779191);
+    res << QPointF(677.400406718071, 781.7952098705392);
+    res << QPointF(691.6740007010135, 806.2608114022295);
+    res << QPointF(694.5877745571677, 810.2150054671212);
+    res << QPointF(699.9560352035193, 816.1706553153153);
+    res << QPointF(708.9007628091615, 824.0594196166176);
+    res << QPointF(719.3794725391945, 831.7499791040799);
+    res << QPointF(730.9568541500198, 839.0942359684872);
+    res << QPointF(743.1975973980386, 845.9440924006244);
+    res << QPointF(755.6663920396528, 852.1514505912763);
+    res << QPointF(767.9279278312633, 857.568212731228);
+    res << QPointF(779.5468945292718, 862.046281011264);
+    res << QPointF(790.0879818900794, 865.4375576221694);
+    res << QPointF(799.115879670088, 867.5939447547289);
+    res << QPointF(799.5154110117976, 867.6431889469776);
+    res << QPointF(802.0871811023624, 1653.9337322834645);
+    res << QPointF(61.86670866141733, 1653.9337322834645);
+
+    // See file "collection/bugs/Issue_#609_case1.val"
+    // Clear a main path. Bound intersection. External loop. Outside a loop. Start point Ф1.
+    QTest::newRow("Issue 609. Case1a") << path << res;
+
+    path.clear();
+    path << QPointF(-365.68188649000314, -2143.126579528016);
+    path << QPointF(-195.75487873249062, -2116.7935769656237);
+    path << QPointF(-195.75487873249062, -1836.0319480765759);
+    path << QPointF(-233.39027086052477, -1838.4849618976993);
+    path << QPointF(-231.15080237392075, -1855.5915146519483);
+    path << QPointF(-225.84473077299972, -1889.4811404382626);
+    path << QPointF(-219.39861487985402, -1922.986407729537);
+    path << QPointF(-211.6695159016421, -1955.9990283342697);
+    path << QPointF(-204.87723909172885, -1980.439660924953);
+    path << QPointF(-199.87970909142098, -1996.6270828437923);
+    path << QPointF(-194.48099536000245, -2012.6451713592935);
+    path << QPointF(-188.65032933731845, -2028.5246588116781);
+    path << QPointF(-182.36812965707693, -2044.2602109802488);
+    path << QPointF(-175.61499879935675, -2059.8462252736344);
+    path << QPointF(-168.3717693169516, -2075.2768492268588);
+    path << QPointF(-160.6424572210866, -2090.5008865466684);
+    path << QPointF(-150.22847685877994, -2109.7385074212525);
+    path << QPointF(194.23861004296444, -2056.3576305273214);
+    path << QPointF(302.4787663409577, -1301.003761061316);
+    path << QPointF(279.86810151275455, -1288.330749878147);
+    path << QPointF(-641.7062267185897, -2051.118466118487);
+    path << QPointF(-365.68188649000314, -2143.126579528016);
+
+    res.clear();
+    res << QPointF(-365.68188649000314, -2143.126579528016);
+    res << QPointF(-195.75487873249062, -2116.7935769656237);
+    res << QPointF(-195.75487873249062, -2008.8655346469059);
+    res << QPointF(-194.48099536000245, -2012.6451713592935);
+    res << QPointF(-188.65032933731845, -2028.5246588116781);
+    res << QPointF(-182.36812965707693, -2044.2602109802488);
+    res << QPointF(-175.61499879935675, -2059.8462252736344);
+    res << QPointF(-168.3717693169516, -2075.2768492268588);
+    res << QPointF(-160.6424572210866, -2090.5008865466684);
+    res << QPointF(-150.22847685877994, -2109.7385074212525);
+    res << QPointF(194.23861004296444, -2056.3576305273214);
+    res << QPointF(302.4787663409577, -1301.003761061316);
+    res << QPointF(279.86810151275455, -1288.330749878147);
+    res << QPointF(-641.7062267185897, -2051.118466118487);
+    res << QPointF(-365.68188649000314, -2143.126579528016);
+
+    // See file "collection/bugs/Issue_#609_case2.val"
+    // Clear an equdistant. Bound intersection. Internal loop. Outside a loop. Start point А2.
+    QTest::newRow("Issue 609. Case2b") << path << res;
+
+    path.clear();
+    path << QPointF(0, 10);
+    path << QPointF(5, 10);
+    path << QPointF(2.5, 15);
+    path << QPointF(7.5, 15);
+    path << QPointF(5, 10);
+    path << QPointF(10, 10);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+
+    QTest::newRow("Internal loop. Valid case.") << path << path;
+
+    path.clear();
+    path << QPointF(0, 10);
+    path << QPointF(5, 10);
+    path << QPointF(7.5, 15);
+    path << QPointF(2.5, 15);
+    path << QPointF(5, 10);
+    path << QPointF(10, 10);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+
+    res.clear();
+    res << QPointF(0, 10);
+    res << QPointF(10, 10);
+    res << QPointF(10, 20);
+    res << QPointF(0, 20);
+    res << QPointF(0, 10);
+
+    QTest::newRow("Internal loop. Invalid case.") << path << res;
+
+    path.clear();
+    path << QPointF(0, 10);
+    path << QPointF(5, 10);
+    path << QPointF(0, 0);
+    path << QPointF(10, 0);
+    path << QPointF(5, 10);
+    path << QPointF(10, 10);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+
+    QTest::newRow("External loop. Valid case.") << path << path;
+
+    path.clear();
+    path << QPointF(0, 10);
+    path << QPointF(5, 10);
+    path << QPointF(10, 0);
+    path << QPointF(0, 0);
+    path << QPointF(5, 10);
+    path << QPointF(10, 10);
+    path << QPointF(10, 20);
+    path << QPointF(0, 20);
+    path << QPointF(0, 10);
+
+    res.clear();
+    res << QPointF(0, 10);
+    res << QPointF(10, 10);
+    res << QPointF(10, 20);
+    res << QPointF(0, 20);
+    res << QPointF(0, 10);
+
+    QTest::newRow("External loop. Invalid case.") << path << res;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PathLoopsCase() const
+{
+    QFETCH(QVector<QPointF>, path);
+    QFETCH(QVector<QPointF>, expect);
+
+    const QVector<QPointF> res = VAbstractPiece::CheckLoops(path);
+    Comparison(res, expect);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::BrokenDetailEquidistant_data() const
+{
+    QTest::addColumn<QVector<VSAPoint>>("points");
+    QTest::addColumn<qreal>("width");
+    QTest::addColumn<QVector<QPointF>>("ekvOrig");
+
+    // For more details see the file "collection/bugs/GAVAUDAN Laure - corsage - figure 4.val".
+    // We will test only one detail. The second require too accurate data that we cannot get from debuger.
+    // The test check an open equdistant of correct detail.
+    QVector<VSAPoint> points;// Input points.
+    points.append(VSAPoint(787.5835464566929, 1701.3138897637796));
+    points.append(VSAPoint(938.7646488188976, 1701.3138897637796));
+    points.append(VSAPoint(928.6149958683911, 1732.4440719866434));
+    points.append(VSAPoint(910.0209091217698, 1792.3369853889722));
+    points.append(VSAPoint(893.3643262819251, 1849.7845131987456));
+    points.append(VSAPoint(878.5244039283091, 1905.2261617043234));
+    points.append(VSAPoint(865.3802986403739, 1959.101437194065));
+    points.append(VSAPoint(863.9366982685195, 1965.6834024491068));
+    points.append(VSAPoint(852.8936778444679, 1919.6965437838999));
+    points.append(VSAPoint(837.0628180560684, 1860.2846653184251));
+    points.append(VSAPoint(819.0677656132684, 1798.6758641921479));
+    points.append(VSAPoint(798.7585839758027, 1734.54810216256));
+    points.append(VSAPoint(787.5835464566929, 1701.3138897637796));
+
+    qreal width = 37.795275590551185; // seam allowance width
+
+    QVector<QPointF> ekvOrig;
+    ekvOrig.append(QPointF(774.8748468280837, 1663.5186141732283));
+    ekvOrig.append(QPointF(990.8407795072413, 1663.5186141732283));
+    ekvOrig.append(QPointF(964.6314912875667, 1743.9055911653147));
+    ekvOrig.append(QPointF(946.2221157804494, 1803.203536155223));
+    ekvOrig.append(QPointF(929.7733291125676, 1859.9343877726233));
+    ekvOrig.append(QPointF(915.1430746962241, 1914.5927211230298));
+    ekvOrig.append(QPointF(902.2033544443959, 1967.630259856634));
+    ekvOrig.append(QPointF(894.4064781634931, 2003.1794116713015));
+    ekvOrig.append(QPointF(834.213891302752, 2003.7742535883901));
+    ekvOrig.append(QPointF(816.2523103379473, 1928.9761772004185));
+    ekvOrig.append(QPointF(800.6574884611877, 1870.4501290629887));
+    ekvOrig.append(QPointF(782.9077417718742, 1809.6811695225983));
+    ekvOrig.append(QPointF(786.7126382487066, 1698.723835966227));
+
+    QTest::newRow("GAVAUDAN Laure.") << points << width << ekvOrig;
+
+    points.clear();
+    points.append(VSAPoint(97.33089106412862, -223.03306117556497));
+    points.append(VSAPoint(990.7494050554426, 2.819093995045));
+    points.append(VSAPoint(908.3966357321774, 379.5839357215547));
+    points.append(VSAPoint(-135.41154226686143, 697.6417881399819));
+
+    width = 11.338582677165354;
+
+    ekvOrig.clear();
+    ekvOrig.append(VSAPoint(100.10981413873267, -234.02583351343978));
+    ekvOrig.append(VSAPoint(1004.1704360325447, -5.483401649771952));
+    ekvOrig.append(VSAPoint(918.0553412376563, 388.4941212347381));
+    ekvOrig.append(VSAPoint(-138.65807550610091, 710.4843173601864));
+
+    // See the file "collection/bugs/Issue_#604.val" (since 0.5.0)
+    QTest::newRow("Issue #604.") << points << width << ekvOrig;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::BrokenDetailEquidistant() const
+{
+    QFETCH(QVector<VSAPoint>, points);
+    QFETCH(qreal, width);
+    QFETCH(QVector<QPointF>, ekvOrig);
+
+    const QVector<QPointF> ekv = VAbstractPiece::Equidistant(points, width);// Take result
+
+    // Begin comparison
+    Comparison(ekv, ekvOrig);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::CorrectEquidistantPoints_data() const
+{
+    // See file zigzag.val
+    QTest::addColumn<QVector<QPointF>>("points");
+    QTest::addColumn<QVector<QPointF>>("expect");
+    QTest::addColumn<bool>("removeFirstAndLast");
+
+    QVector<QPointF> points;
+    points.append(QPointF(-741.7894588053705, 1065.7336503858917));
+    points.append(QPointF(-759.696551643576, -115.81420543069257));
+    points.append(QPointF(-278.17249953019325, -217.1037453126913));
+    points.append(QPointF(-244.64654130659474, 1077.9548221866635));
+    points.append(QPointF(-741.7894588053705, 1065.7336503858917));
+
+    QVector<QPointF> expect;
+    expect.append(QPointF(-741.7894588053705, 1065.7336503858917));
+    expect.append(QPointF(-759.696551643576, -115.81420543069257));
+    expect.append(QPointF(-278.17249953019325, -217.1037453126913));
+    expect.append(QPointF(-244.64654130659474, 1077.9548221866635));
+    expect.append(QPointF(-741.7894588053705, 1065.7336503858917));
+
+    QTest::newRow("Closed seam allowance. Last point equal first.") << points << expect << false;
+
+    points.clear();
+    points.append(QPointF(-704.5489521643801, 1028.8424328418016));
+    points.append(QPointF(-721.4335720065426, -85.24049234531904));
+    points.append(QPointF(-707.7852899705758, 755.7064514429209));
+    points.append(QPointF(-721.4335720065426, -85.24049234531904));
+    points.append(QPointF(-314.78124296268265, -170.7806167067443));
+    points.append(QPointF(-283.4579031023758, 1039.1940357173805));
+
+    expect.clear();
+    expect.append(QPointF(-704.5489521643801, 1028.8424328418016));
+    expect.append(QPointF(-721.4335720065426, -85.24049234531904));
+    expect.append(QPointF(-314.78124296268265, -170.7806167067443));
+    expect.append(QPointF(-283.4579031023758, 1039.1940357173805));
+
+    QTest::newRow("Clearing bad main path.") << points << expect << true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::CorrectEquidistantPoints() const
+{
+    QFETCH(QVector<QPointF>, points);
+    QFETCH(QVector<QPointF>, expect);
+    QFETCH(bool, removeFirstAndLast);
+
+    const QVector<QPointF> res = VAbstractPiece::CorrectEquidistantPoints(points, removeFirstAndLast);
+
+    // Begin comparison
+    Comparison(res, expect);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::TestCorrectEquidistantPoints_data()
+{
+    QTest::addColumn<QVector<QPointF>>("before");
+    QTest::addColumn<QVector<QPointF>>("expect");
+
+    QVector<QPointF> before;
+    before << QPointF(30.0, 39.999874015748034);
+    before << QPointF(785.9055118110236, 39.999874015748034);
+    before << QPointF(785.9055118110236, 3819.527433070866);
+    before << QPointF(483.54330708661416, 3819.527433070866);
+    before << QPointF(483.54330708661416, 1929.763653543307);
+    before << QPointF(407.9527559055629, 984.8817637795973);
+    before << QPointF(407.9527559055118, 1929.763653543307);
+    before << QPointF(407.9527559055118, 3819.527433070866);
+    before << QPointF(30.0, 3819.527433070866);
+
+    QVector<QPointF> expect;
+    expect << QPointF(30.0, 39.999874015748034);
+    expect << QPointF(785.9055118110236, 39.999874015748034);
+    expect << QPointF(785.9055118110236, 3819.527433070866);
+    expect << QPointF(483.54330708661416, 3819.527433070866);
+    expect << QPointF(483.54330708661416, 1929.763653543307);
+    expect << QPointF(407.9527559055629, 984.8817637795973);
+    expect << QPointF(407.9527559055118, 3819.527433070866);
+    expect << QPointF(30.0, 3819.527433070866);
+
+    QTest::newRow("Test case issue #548") << before << expect;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::TestCorrectEquidistantPoints() const
+{
+    QFETCH(QVector<QPointF>, before);
+    QFETCH(QVector<QPointF>, expect);
+
+    QVector<QPointF> after = VAbstractPiece::CorrectEquidistantPoints(before);
+    Comparison(after, expect);
+}
+
+#ifndef Q_OS_WIN
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PossibleInfiniteClearLoops_data() const
+{
+    QTest::addColumn<QVector<QPointF>>("path");
+    QTest::addColumn<QVector<QPointF>>("expect");
+
+    QVector<QPointF> path;
+    path << QPointF(-670.6449010946802, 4046.36220472441);
+    path << QPointF(-1025.9051277126944, 4046.36220472441);
+    path << QPointF(-1026.4460203880594, 4010.5247429150854);
+    path << QPointF(-1027.2972172274538, 3924.202328582098);
+    path << QPointF(-1028.1383921346433, 3768.5948526129496);
+    path << QPointF(-1028.5065585022217, 3521.575730066707);
+    path << QPointF(-1028.2712136539103, 3252.2436039362233);
+    path << QPointF(-1027.2910122410117, 2850.1024469719814);
+    path << QPointF(-1025.9446023682538, 2439.350819630564);
+    path << QPointF(-1025.8983315247287, 2338.629525677473);
+    path << QPointF(-1025.3536572186458, 2309.970015878699);
+    path << QPointF(-1024.2100836932389, 2281.714612342931);
+    path << QPointF(-1022.5102766116828, 2253.846781520112);
+    path << QPointF(-1020.2969016371525, 2226.349989860186);
+    path << QPointF(-1017.6126244328227, 2199.207703813094);
+    path << QPointF(-1014.5001106618688, 2172.403389828782);
+    path << QPointF(-1011.0020259874652, 2145.9205143571917);
+    path << QPointF(-1005.1601480132764, 2106.7277181407126);
+    path << QPointF(-996.3625412018714, 2055.4921956731814);
+    path << QPointF(-986.7906327138169, 2005.2448233555149);
+    path << QPointF(-976.785747854512, 1955.8533327872588);
+    path << QPointF(-961.6606968634906, 1883.0158867454916);
+    path << QPointF(-947.5864881030896, 1811.4914675744105);
+    path << QPointF(-939.2629508127773, 1764.2008199992524);
+    path << QPointF(-933.8852659113251, 1728.8707137815559);
+    path << QPointF(-930.742733377741, 1705.3464944792456);
+    path << QPointF(-928.0252775410311, 1681.829576238578);
+    path << QPointF(-925.7755640643697, 1658.3034255094963);
+    path << QPointF(-924.036258610932, 1634.7515087419433);
+    path << QPointF(-922.850026843893, 1611.1572923858625);
+    path << QPointF(-922.2595344264276, 1587.504242891197);
+    path << QPointF(-922.3074470217107, 1563.7758267078902);
+    path << QPointF(-922.613405031688, 1551.8740157480315);
+    path << QPointF(-960.4086806222392, 841.3228346456693);
+    path << QPointF(-954.9336313684444, 841.5464781141166);
+    path << QPointF(-944.0363771538431, 841.3102753632543);
+    path << QPointF(-933.2160856340209, 840.291423017261);
+    path << QPointF(-922.4878118569704, 838.5316299985567);
+    path << QPointF(-911.8666108706839, 836.0726052295611);
+    path << QPointF(-901.3675377231535, 832.9560576326933);
+    path << QPointF(-891.005647462372, 829.2236961303737);
+    path << QPointF(-880.7959951363317, 824.9172296450213);
+    path << QPointF(-870.7536357930251, 820.0783670990559);
+    path << QPointF(-860.893624480444, 814.7488174148973);
+    path << QPointF(-851.2310162465817, 808.9702895149649);
+    path << QPointF(-841.7808661394299, 802.7844923216785);
+    path << QPointF(-832.5582292069812, 796.2331347574575);
+    path << QPointF(-823.578160497228, 789.3579257447218);
+    path << QPointF(-810.5607800373014, 778.5565764202543);
+    path << QPointF(-794.2367125298769, 763.3635567727296);
+    path << QPointF(-779.1539087770976, 747.6258919346988);
+    path << QPointF(-765.4328091629026, 731.6772532855191);
+    path << QPointF(-753.193854071231, 715.8513122045474);
+    path << QPointF(-742.557483886022, 700.4817400711408);
+    path << QPointF(-733.644138991215, 685.9022082646563);
+    path << QPointF(-726.5742597707488, 672.446388164451);
+    path << QPointF(-721.4682866085625, 660.447951149882);
+    path << QPointF(-718.6229063234249, 651.1532303788147);
+    path << QPointF(-716.6036430255488, 642.9038041285014);
+    path << QPointF(-714.137568179324, 630.1235656609365);
+    path << QPointF(-711.8605525364693, 612.2344502588126);
+    path << QPointF(-710.4560555432737, 593.4222205889721);
+    path << QPointF(-709.4234847119759, 563.5940176156308);
+    path << QPointF(-708.952111561728, 520.4666582691573);
+    path << QPointF(-708.4401766852314, 497.3858267716535);
+    path << QPointF(-400.92922424489655, 469.03937007874015);
+    path << QPointF(-708.4401766852314, 440.6929133858268);
+    path << QPointF(-708.7078446526739, 341.66122584661264);
+    path << QPointF(-709.3427685457568, 299.60322373665383);
+    path << QPointF(-710.6909230403871, 257.048095841136);
+    path << QPointF(-713.0251717477311, 214.57984397612822);
+    path << QPointF(-715.632864794307, 183.1716335401434);
+    path << QPointF(-717.7953694429818, 162.55016633308693);
+    path << QPointF(-720.3578834261159, 142.27891915519677);
+    path << QPointF(-723.3545146951046, 122.43089223348173);
+    path << QPointF(-725.0465030138121, 112.71059563115871);
+    path << QPointF(-219.59055118110237, -35.52755905511811);
+    path << QPointF(-218.99352387527398, -33.21125072212394);
+    path << QPointF(-217.35724543521775, -28.699086141666157);
+    path << QPointF(-215.20035586903225, -24.33136255454731);
+    path << QPointF(-212.53403014110648, -20.10796717265881);
+    path << QPointF(-209.36944321582945, -16.02878720789205);
+    path << QPointF(-205.71777005759026, -12.093709872138447);
+    path << QPointF(-201.59018563077785, -8.302622377289406);
+    path << QPointF(-196.99786489978123, -4.65541193523633);
+    path << QPointF(-189.3170483291933, 0.5638303631539586);
+    path << QPointF(-177.47808861476295, 6.996342387787443);
+    path << QPointF(-163.981333042598, 12.855376387191757);
+    path << QPointF(-148.91618132781048, 18.141834666235646);
+    path << QPointF(-132.37203318551252, 22.856619529787864);
+    path << QPointF(-114.43828833081622, 27.00063328271716);
+    path << QPointF(-95.20434647883366, 30.574778229892296);
+    path << QPointF(-74.75960734467688, 33.57995667618201);
+    path << QPointF(-53.193470643458, 36.01707092645505);
+    path << QPointF(-30.595336090289106, 37.887023285580185);
+    path << QPointF(-7.0546034002822875, 39.19071605842615);
+    path << QPointF(17.339327711450373, 39.929051549861704);
+    path << QPointF(29.858267716535437, 40.06299212598426);
+    path << QPointF(-45.73228346456693, 1589.6692913385828);
+    path << QPointF(-45.73228346456693, 4046.36220472441);
+    path << QPointF(-297.70078740157487, 4046.36220472441);
+    path << QPointF(-297.70078740157487, 2118.8031496062995);
+    path << QPointF(-222.1102362204725, 1589.6692913385828);
+    path << QPointF(-297.70078740157487, 1060.535433070866);
+    path << QPointF(-373.2913385826772, 1589.6692913385828);
+    path << QPointF(-297.70078740157487, 2118.8031496062995);
+    path << QPointF(-297.70078740157487, 4046.36220472441);
+    path << QPointF(-670.6449010946802, 4046.36220472441);
+    path << QPointF(-670.6449010946802, 2024.3149606299214);
+    path << QPointF(-622.7555214134819, 1570.7716535433071);
+    path << QPointF(-670.6449010946802, 1117.2283464566929);
+    path << QPointF(-718.5342807758785, 1570.7716535433071);
+    path << QPointF(-670.6449010946802, 2024.3149606299214);
+
+    QVector<QPointF> expect;
+    expect << QPointF(-670.6449010946802, 4046.36220472441);
+    expect << QPointF(-670.6449010946802, 4046.36220472441);
+    expect << QPointF(-670.6449010946802, 2024.3149606299214);
+    expect << QPointF(-670.6449010946802, 2024.3149606299214);
+    expect << QPointF(-670.6449010946802, 2024.3149606299214);
+
+    // See the file "collection/bugs/possible_inf_loop.val"
+    QTest::newRow("Possible infinite loop") << path << expect;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::PossibleInfiniteClearLoops() const
+{
+    QFETCH(QVector<QPointF>, path);
+    QFETCH(QVector<QPointF>, expect);
+
+    QVector<QPointF> res = VAbstractPiece::CheckLoops(path);
+    Comparison(res, expect);
+}
+#endif //#ifndef Q_OS_WIN
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::Case3() const
+{
+    const QVector<QPointF> points = InputPointsCase3a(); // Input points.
+
+    const qreal result = VAbstractPiece::SumTrapezoids(points);
+    QVERIFY(result < 0);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::Case4() const
+{
+    const QVector<QPointF> points = InputPointsCase4a(); // Input points.
+
+    const qreal result = VAbstractPiece::SumTrapezoids(points);
+    QVERIFY(result > 0);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractPiece::Case5() const
+{
+    const QVector<QPointF> points = InputPointsCase5a(); // Input points.
+
+    const qreal result = VAbstractPiece::SumTrapezoids(points);
+    QVERIFY(qFuzzyIsNull(result));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsIssue298Case1() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(35, 39.9999);
+    points += QPointF(412.953, 39.9999);
+    points += QPointF(417.135, 417.929);
+    points += QPointF(417.135, 417.929);
+    points += QPointF(408.797, 405.589);
+    points += QPointF(390.909, 377.669);
+    points += QPointF(362.315, 330.86);
+    points += QPointF(323.075, 264.247);
+    points += QPointF(286.15, 201.448);
+    points += QPointF(262.477, 162.745);
+    points += QPointF(249.22, 142.455);
+    points += QPointF(241.092, 131.261);
+    points += QPointF(236.545, 125.75);
+    points += QPointF(232.808, 122.058);
+    points += QPointF(230.6, 120.629);
+    points += QPointF(229.393, 120.277);
+    points += QPointF(228.421, 120.456);
+    points += QPointF(227.69, 121.185);
+    points += QPointF(227.033, 123.272);
+    points += QPointF(227.112, 128.232);
+    points += QPointF(228.29, 135.699);
+    points += QPointF(230.625, 145.81);
+    points += QPointF(234.173, 158.703);
+    points += QPointF(241.73, 183.168);
+    points += QPointF(248.796, 204.144);
+    points += QPointF(248.796, 204.144);
+    points += QPointF(251.528, 212.406);
+    points += QPointF(255.482, 227.075);
+    points += QPointF(257.717, 239.591);
+    points += QPointF(258.279, 247.554);
+    points += QPointF(258.203, 252.278);
+    points += QPointF(257.756, 256.51);
+    points += QPointF(256.949, 260.264);
+    points += QPointF(255.795, 263.547);
+    points += QPointF(254.308, 266.372);
+    points += QPointF(252.501, 268.749);
+    points += QPointF(250.385, 270.688);
+    points += QPointF(247.974, 272.201);
+    points += QPointF(245.281, 273.296);
+    points += QPointF(242.319, 273.986);
+    points += QPointF(239.1, 274.28);
+    points += QPointF(233.846, 274.05);
+    points += QPointF(226.022, 272.393);
+    points += QPointF(217.402, 269.345);
+    points += QPointF(208.09, 264.991);
+    points += QPointF(198.186, 259.414);
+    points += QPointF(187.795, 252.7);
+    points += QPointF(177.019, 244.933);
+    points += QPointF(165.96, 236.197);
+    points += QPointF(154.721, 226.576);
+    points += QPointF(143.405, 216.157);
+    points += QPointF(132.113, 205.022);
+    points += QPointF(120.95, 193.257);
+    points += QPointF(110.017, 180.946);
+    points += QPointF(99.4167, 168.174);
+    points += QPointF(89.2522, 155.024);
+    points += QPointF(79.626, 141.582);
+    points += QPointF(70.6405, 127.933);
+    points += QPointF(62.3985, 114.16);
+    points += QPointF(55.0025, 100.348);
+    points += QPointF(48.5551, 86.5823);
+    points += QPointF(43.159, 72.9466);
+    points += QPointF(38.9167, 59.5258);
+    points += QPointF(35.9309, 46.4042);
+    points += QPointF(35, 39.9999);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue298Case1() const
+{
+    QVector<QPointF> points;
+    points += QPointF(-52.3724798442221, -35.5907);
+    points += QPointF(487.7117748779425, -35.5907);
+    points += QPointF(493.3432017362585, 473.32371517914754);
+    points += QPointF(385.98559977345093, 506.8445742667132);
+    points += QPointF(345.64704646524604, 447.1446764706891);
+    points += QPointF(326.82411403464874, 417.76541252489994);
+    points += QPointF(297.4844355409708, 369.73572061014266);
+    points += QPointF(280.35686644039447, 340.63425704493835);
+    points += QPointF(268.2336759982877, 345.56366422433183);
+    points += QPointF(254.38869069377708, 348.78886336684104);
+    points += QPointF(240.8928242225697, 350.0214774527481);
+    points += QPointF(224.29748398011193, 349.2949970081793);
+    points += QPointF(205.50330859478322, 345.31468660256957);
+    points += QPointF(188.72568121178054, 339.38217984347546);
+    points += QPointF(173.487571907339, 332.2573164509149);
+    points += QPointF(159.09346043909582, 324.15190856941325);
+    points += QPointF(145.1562378134811, 315.1465661857729);
+    points += QPointF(131.46917217609203, 305.28136213922494);
+    points += QPointF(117.9345600633141, 294.589765121662);
+    points += QPointF(104.5254725457231, 283.11108988305153);
+    points += QPointF(91.25156649455745, 270.88938370179534);
+    points += QPointF(78.14294517511125, 257.9630200468154);
+    points += QPointF(65.25722328495372, 244.3823949426573);
+    points += QPointF(52.65759889494496, 230.19470850111355);
+    points += QPointF(40.412239584772514, 215.4406233233806);
+    points += QPointF(28.600027181043494, 200.15894757848054);
+    points += QPointF(17.304913602921047, 184.38648111018338);
+    points += QPointF(6.6105681133211736, 168.14173996194046);
+    points += QPointF(-3.3897319816688407, 151.43048866270516);
+    points += QPointF(-12.592267484961765, 134.24479093805914);
+    points += QPointF(-20.880547263016442, 116.54866956498358);
+    points += QPointF(-28.111192294561146, 98.27715746242171);
+    points += QPointF(-34.098213657706594, 79.33681465062016);
+    points += QPointF(-38.441724866417594, 60.24852451858777);
+    points += QPointF(-52.3724798442221, -35.5907);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsIssue298Case2() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(35, 39.9999);
+    points += QPointF(35, 39.9999);
+    points += QPointF(35.9309, 46.4042);
+    points += QPointF(38.9167, 59.5258);
+    points += QPointF(43.159, 72.9466);
+    points += QPointF(48.5551, 86.5823);
+    points += QPointF(55.0025, 100.348);
+    points += QPointF(62.3985, 114.16);
+    points += QPointF(70.6405, 127.933);
+    points += QPointF(79.626, 141.582);
+    points += QPointF(89.2522, 155.024);
+    points += QPointF(99.4167, 168.174);
+    points += QPointF(110.017, 180.946);
+    points += QPointF(120.95, 193.257);
+    points += QPointF(132.113, 205.022);
+    points += QPointF(143.405, 216.157);
+    points += QPointF(154.721, 226.576);
+    points += QPointF(165.96, 236.197);
+    points += QPointF(177.019, 244.933);
+    points += QPointF(187.795, 252.7);
+    points += QPointF(198.186, 259.414);
+    points += QPointF(208.09, 264.991);
+    points += QPointF(217.402, 269.345);
+    points += QPointF(226.022, 272.393);
+    points += QPointF(233.846, 274.05);
+    points += QPointF(239.1, 274.28);
+    points += QPointF(242.319, 273.986);
+    points += QPointF(245.281, 273.296);
+    points += QPointF(247.974, 272.201);
+    points += QPointF(250.385, 270.688);
+    points += QPointF(252.501, 268.749);
+    points += QPointF(254.308, 266.372);
+    points += QPointF(255.795, 263.547);
+    points += QPointF(256.949, 260.264);
+    points += QPointF(257.756, 256.51);
+    points += QPointF(258.203, 252.278);
+    points += QPointF(258.279, 247.554);
+    points += QPointF(257.717, 239.591);
+    points += QPointF(255.482, 227.075);
+    points += QPointF(251.528, 212.406);
+    points += QPointF(248.796, 204.144);
+    points += QPointF(248.796, 204.144);
+    points += QPointF(241.73, 183.168);
+    points += QPointF(234.173, 158.703);
+    points += QPointF(230.625, 145.81);
+    points += QPointF(228.29, 135.699);
+    points += QPointF(227.112, 128.232);
+    points += QPointF(227.033, 123.272);
+    points += QPointF(227.69, 121.185);
+    points += QPointF(228.421, 120.456);
+    points += QPointF(229.393, 120.277);
+    points += QPointF(230.6, 120.629);
+    points += QPointF(232.808, 122.058);
+    points += QPointF(236.545, 125.75);
+    points += QPointF(241.092, 131.261);
+    points += QPointF(249.22, 142.455);
+    points += QPointF(262.477, 162.745);
+    points += QPointF(286.15, 201.448);
+    points += QPointF(323.075, 264.247);
+    points += QPointF(362.315, 330.86);
+    points += QPointF(390.909, 377.669);
+    points += QPointF(408.797, 405.589);
+    points += QPointF(417.135, 417.929);
+    points += QPointF(417.135, 417.929);
+    points += QPointF(35, 417.953);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue298Case2() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(-2.7952999999999975, 4.8384699505981095);
+    points += QPointF(67.34448942068963, -0.23248582689164274);
+    points += QPointF(73.11721243320879, 39.48203774070609);
+    points += QPointF(75.42415682885321, 49.62029267468959);
+    points += QPointF(78.79409614728041, 60.281321268788744);
+    points += QPointF(83.27292363150828, 71.59911521750833);
+    points += QPointF(88.79988374248082, 83.39960453097031);
+    points += QPointF(95.2926159908344, 95.5247556686474);
+    points += QPointF(102.65546594334339, 107.82863001903641);
+    points += QPointF(110.78654319853989, 120.17975944490887);
+    points += QPointF(119.5782864094781, 132.4565262107595);
+    points += QPointF(128.91893020761376, 144.54068833830968);
+    points += QPointF(138.69670055252752, 156.3216457494432);
+    points += QPointF(148.79638835752286, 167.69430252867102);
+    points += QPointF(159.09802741244354, 178.55148997659143);
+    points += QPointF(169.48171675272164, 188.79080814910267);
+    points += QPointF(179.81876372713828, 198.30845505847407);
+    points += QPointF(189.9727199683426, 207.00061743916868);
+    points += QPointF(199.7939139119543, 214.75881893038778);
+    points += QPointF(209.1143810932559, 221.476716907111);
+    points += QPointF(216.03386663545683, 225.9476461661168);
+    points += QPointF(215.3306509043856, 223.3387762725701);
+    points += QPointF(205.75073516810195, 194.75155680967347);
+    points += QPointF(197.88802785264718, 169.29686123304236);
+    points += QPointF(193.97579117825833, 155.08026950731082);
+    points += QPointF(191.1640933645057, 142.90507610480435);
+    points += QPointF(189.3638602852325, 131.49392126360493);
+    points += QPointF(189.14507682295456, 117.75764312564759);
+    points += QPointF(194.42693552963567, 100.97950138920423);
+    points += QPointF(210.03879336533757, 85.41035725481989);
+    points += QPointF(231.36634627769158, 81.48275234606332);
+    points += QPointF(246.4916615881645, 85.89378050620131);
+    points += QPointF(256.60614755001956, 92.43979519799973);
+    points += QPointF(264.4750900046005, 100.21398185636762);
+    points += QPointF(270.9888544453203, 108.1087159300009);
+    points += QPointF(280.35077918473866, 121.00209505562212);
+    points += QPointF(294.42535276480356, 142.5434013797918);
+    points += QPointF(318.5597512322288, 182.00074197391842);
+    points += QPointF(394.73028222951507, 311.42213969492946);
+    points += QPointF(422.9514429826756, 357.62079373755);
+    points += QPointF(440.37197676737753, 384.8111617646563);
+    points += QPointF(488.2841719585649, 455.71983154868764);
+    points += QPointF(-2.795300000000013, 455.7506738094777);
+    points += QPointF(-2.7952999999999975, 4.8384699505981095);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case1() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(236.97989607468364, 65.89325192030674);
+    points += QPointF(198.93409106041895, 172.04876297154925);
+    points += QPointF(260.32251114299453, 75.38027418944861);
+    points += QPointF(324.54110236213444, 101.48031496062993);
+    points += QPointF(29.858267716535437, 300.85039370078744);
+    points += QPointF(99.86433649395013, 10.166060970128015);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case1() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(251.32210577118798, 59.48301432799721);
+    points += QPointF(243.9841262159756, 79.95746530820585);
+    points += QPointF(255.82424817748586, 61.31279754390509);
+    points += QPointF(348.48337789725855, 98.9717841021069);
+    points += QPointF(29.780382054543473, 314.59289909613994);
+    points += QPointF(17.01672179602679, 305.7450049304056);
+    points += QPointF(91.92616539550944, -5.299480329501037);
+    points += QPointF(251.32210577118798, 59.48301432799721);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case2() const
+{
+    QVector<QPointF> points;
+    points << QPointF(99.86433649395013, 10.166060970128015);
+    points << QPointF(236.97989607468364, 65.89325192030674);
+    points << QPointF(198.93409106041895, 172.04876297154925);
+    points << QPointF(260.32251114299453, 75.38027418944861);
+    points << QPointF(324.54110236213444, 101.48031496062993);
+    points << QPointF(29.858267716535437, 300.85039370078744);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case2() const
+{
+    QVector<QPointF> points;
+    points << QPointF(73.40376616581447, -41.38574336196901);
+    points << QPointF(245.32830125796568, 28.488685370970344);
+    points << QPointF(245.32830125796573, 28.488685370970277);
+    points << QPointF(404.3486874792147, 93.11854543221973);
+    points << QPointF(29.598648843228922, 346.6587450186291);
+    points << QPointF(-12.946885351826726, 317.1657644661815);
+    points << QPointF(73.40376616581447, -41.38574336196901);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case3() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(99.86433649395013, 10.166060970128015);
+    points += QPointF(236.97989607468364, 65.89325192030674);
+    points += QPointF(198.93409106041895, 172.04876297154925);
+    points += QPointF(260.32251114299453, 75.38027418944861);
+    points += QPointF(324.54110236213444, 101.48031496062993);
+    points += QPointF(29.858267716535437, 300.85039370078744);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case3() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(46.94319583767885, -92.9375476940661);
+#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
+    points += QPointF(234.2633962639462, -16.805935717278903);
+#else
+    points += QPointF(238.798634936, -14.9627013515);
+#endif
+    points += QPointF(484.15627259629446, 84.75677590380938);
+    points += QPointF(29.339029969922702, 392.46709633647066);
+    points += QPointF(-55.75203842018885, 333.48113523157537);
+    points += QPointF(46.94319583767885, -92.9375476940661);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsCase3a() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(35, 35);
+    points += QPointF(50, 50);
+    points += QPointF(15, 50);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsCase4a() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(15, 15);
+    points += QPointF(15, 50);
+    points += QPointF(50, 50);
+
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> TST_VAbstractPiece::InputPointsCase5a() const
+{
+    QVector<QPointF> points;
+
+    points += QPointF(35, 35);
+
+    return points;
+}
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.h b/src/test/ValentinaTest/tst_vabstractpiece.h
index cd2b37eed..af965d1a4 100644
--- a/src/test/ValentinaTest/tst_vabstractpiece.h
+++ b/src/test/ValentinaTest/tst_vabstractpiece.h
@@ -42,6 +42,22 @@ public:
 private slots:
     void EquidistantRemoveLoop_data();
     void EquidistantRemoveLoop() const;
+    void SumTrapezoids() const;
+    void PathRemoveLoop_data() const;
+    void PathRemoveLoop() const;
+    void PathLoopsCase_data() const;
+    void PathLoopsCase() const;
+    void BrokenDetailEquidistant_data() const;
+    void BrokenDetailEquidistant() const;
+    void CorrectEquidistantPoints_data() const;
+    void CorrectEquidistantPoints() const;
+    void TestCorrectEquidistantPoints_data();
+    void TestCorrectEquidistantPoints() const;
+#ifndef Q_OS_WIN
+    void PossibleInfiniteClearLoops_data() const;
+    void PossibleInfiniteClearLoops() const;
+#endif
+
 private:
     QVector<VSAPoint> InputPointsCase1() const;
     QVector<QPointF>  OutputPointsCase1() const;
@@ -51,6 +67,29 @@ private:
 
     QVector<VSAPoint> InputPointsCase3() const;
     QVector<QPointF>  OutputPointsCase3() const;
+
+    void Case3() const;
+    void Case4() const;
+    void Case5() const;
+
+    QVector<QPointF> InputPointsIssue298Case1() const;
+    QVector<QPointF> OutputPointsIssue298Case1() const;
+
+    QVector<QPointF> InputPointsIssue298Case2() const;
+    QVector<QPointF> OutputPointsIssue298Case2() const;
+
+    QVector<QPointF> InputPointsIssue548Case1() const;
+    QVector<QPointF> OutputPointsIssue548Case1() const;
+
+    QVector<QPointF> InputPointsIssue548Case2() const;
+    QVector<QPointF> OutputPointsIssue548Case2() const;
+
+    QVector<QPointF> InputPointsIssue548Case3() const;
+    QVector<QPointF> OutputPointsIssue548Case3() const;
+
+    QVector<QPointF> InputPointsCase3a() const;
+    QVector<QPointF> InputPointsCase4a() const;
+    QVector<QPointF> InputPointsCase5a() const;
 };
 
 #endif // TST_VABSTRACTPIECE_H
diff --git a/src/test/ValentinaTest/tst_varc.cpp b/src/test/ValentinaTest/tst_varc.cpp
index 207050c34..20d35574b 100644
--- a/src/test/ValentinaTest/tst_varc.cpp
+++ b/src/test/ValentinaTest/tst_varc.cpp
@@ -28,7 +28,7 @@
 
 #include "tst_varc.h"
 #include "../vgeometry/varc.h"
-#include "../vlayout/vabstractdetail.h"
+#include "../vlayout/vabstractpiece.h"
 #include "../vmisc/logging.h"
 
 #include <QtTest>
@@ -203,7 +203,7 @@ void TST_VArc::TestGetPoints()
         }
 
         // calculated square
-        const qreal cSquare = qAbs(VAbstractDetail::SumTrapezoids(points)/2.0);
+        const qreal cSquare = qAbs(VAbstractPiece::SumTrapezoids(points)/2.0);
         const qreal value = qAbs(gSquere - cSquare);
         const QString errorMsg =
                 QString("Broken the second rule. Interpolation has too big computing error. Error ='%1'.").arg(value);
diff --git a/src/test/ValentinaTest/tst_vellipticalarc.cpp b/src/test/ValentinaTest/tst_vellipticalarc.cpp
index 5abd8b583..794af45ef 100644
--- a/src/test/ValentinaTest/tst_vellipticalarc.cpp
+++ b/src/test/ValentinaTest/tst_vellipticalarc.cpp
@@ -28,7 +28,7 @@
 
 #include "tst_vellipticalarc.h"
 #include "../vgeometry/vellipticalarc.h"
-#include "../vlayout/vabstractdetail.h"
+#include "../vlayout/vabstractpiece.h"
 #include "../vmisc/logging.h"
 
 #include <QtGlobal>
@@ -372,7 +372,7 @@ void TST_VEllipticalArc::TestGetPoints3()
     {// calculated full ellipse square
         const qreal ellipseSquare = M_PI * radius1 * radius2;
         const qreal epsSquare = ellipseSquare * 0.5 / 100; // computing error 0.5 % from origin squere
-        const qreal arcSquare = qAbs(VAbstractDetail::SumTrapezoids(points)/2.0);
+        const qreal arcSquare = qAbs(VAbstractPiece::SumTrapezoids(points)/2.0);
         const qreal diffSquare = qAbs(ellipseSquare - arcSquare);
         const QString errorMsg1 = QString("Broken the second rule. Interpolation has too big computing error. "
                                           "Difference ='%1' bigger than eps = '%2'.").arg(diffSquare).arg(epsSquare);

From a1a25a39e7bcad43e08ea9fae3476447a1ff10e2 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 13:20:04 +0200
Subject: [PATCH 189/208] Fixed typo.

--HG--
branch : feature
---
 src/libs/vlayout/vlayoutpiece.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp
index 29c1235e2..5f47a35a5 100644
--- a/src/libs/vlayout/vlayoutpiece.cpp
+++ b/src/libs/vlayout/vlayoutpiece.cpp
@@ -811,7 +811,7 @@ QVector<QPointF> VLayoutPiece::DetailPath() const
 QVector<VSAPoint> VLayoutPiece::PrepareAllowance(const QVector<QPointF> &points)
 {
     QVector<VSAPoint> allowancePoints;
-    for(int i = 0; i < points.size(); +i)
+    for(int i = 0; i < points.size(); ++i)
     {
         allowancePoints.append(VSAPoint(points.at(i)));
     }

From b99bdc474238d029e8d36ff8d7ba2c83c21513f5 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 13:21:07 +0200
Subject: [PATCH 190/208] A seam allowance is alwayse closed.

--HG--
branch : feature
---
 src/libs/vlayout/vlayoutpiece.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp
index 5f47a35a5..e41d2b2b5 100644
--- a/src/libs/vlayout/vlayoutpiece.cpp
+++ b/src/libs/vlayout/vlayoutpiece.cpp
@@ -128,7 +128,7 @@ QVector<QPointF> VLayoutPiece::GetContourPoints() const
 //---------------------------------------------------------------------------------------------------------------------
 void VLayoutPiece::SetCountourPoints(const QVector<QPointF> &points)
 {
-    d->contour = RemoveDublicates(RoundPoints(points));
+    d->contour = RemoveDublicates(RoundPoints(points), false);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -147,7 +147,7 @@ void VLayoutPiece::SetSeamAllowencePoints(const QVector<QPointF> &points, bool s
         d->seamAllowence = points;
         if (not d->seamAllowence.isEmpty())
         {
-            d->seamAllowence = RemoveDublicates(RoundPoints(d->seamAllowence));
+            d->seamAllowence = RemoveDublicates(RoundPoints(d->seamAllowence), false);
         }
         else
         {

From 8c1bd374919d864e02cc313f6c300037e8490593 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 14:32:25 +0200
Subject: [PATCH 191/208] Show piece's internal paths on a layout.

--HG--
branch : feature
---
 src/libs/vlayout/vgraphicsfillitem.cpp |  4 +-
 src/libs/vlayout/vgraphicsfillitem.h   |  2 +-
 src/libs/vlayout/vlayoutpaper.cpp      | 10 ----
 src/libs/vlayout/vlayoutpiece.cpp      | 76 ++++++++++++++++++++------
 src/libs/vlayout/vlayoutpiece.h        | 17 ++++--
 src/libs/vlayout/vlayoutpiece_p.h      | 76 +++++++++++++++++---------
 src/libs/vpatterndb/vpiece.cpp         | 15 +++++
 src/libs/vpatterndb/vpiece.h           |  2 +
 8 files changed, 142 insertions(+), 60 deletions(-)

diff --git a/src/libs/vlayout/vgraphicsfillitem.cpp b/src/libs/vlayout/vgraphicsfillitem.cpp
index d619b1278..e29fbb5b0 100644
--- a/src/libs/vlayout/vgraphicsfillitem.cpp
+++ b/src/libs/vlayout/vgraphicsfillitem.cpp
@@ -29,8 +29,8 @@
 #include "vgraphicsfillitem.h"
 
 //---------------------------------------------------------------------------------------------------------------------
-VGraphicsFillItem::VGraphicsFillItem()
-    :QGraphicsPathItem()
+VGraphicsFillItem::VGraphicsFillItem(QGraphicsItem *parent)
+    :QGraphicsPathItem(parent)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vlayout/vgraphicsfillitem.h b/src/libs/vlayout/vgraphicsfillitem.h
index 467d62e12..3862d5d3f 100644
--- a/src/libs/vlayout/vgraphicsfillitem.h
+++ b/src/libs/vlayout/vgraphicsfillitem.h
@@ -38,7 +38,7 @@ public:
     /**
      * @brief VGraphicsFillItem Constructor
      */
-    VGraphicsFillItem();
+    VGraphicsFillItem(QGraphicsItem *parent = nullptr);
     /**
      * @brief ~VGraphicsFillItem Destructor
      */
diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp
index 890c6dea4..d3c21749c 100644
--- a/src/libs/vlayout/vlayoutpaper.cpp
+++ b/src/libs/vlayout/vlayoutpaper.cpp
@@ -354,16 +354,6 @@ QList<QGraphicsItem *> VLayoutPaper::GetItemDetails() const
     for (int i=0; i < d->details.count(); ++i)
     {
         list.append(d->details.at(i).GetItem());
-        for (int iT = 0; iT < d->details.at(i).GetTextItemsCount(); ++iT)
-        {
-            list.append(d->details.at(i).GetTextItem(iT));
-        }
-
-        QGraphicsItem* pItem = d->details.at(i).GetGrainlineItem();
-        if (pItem != 0)
-        {
-            list.append(pItem);
-        }
     }
     return list;
 }
diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp
index e41d2b2b5..1be1f19ff 100644
--- a/src/libs/vlayout/vlayoutpiece.cpp
+++ b/src/libs/vlayout/vlayoutpiece.cpp
@@ -86,9 +86,10 @@ VLayoutPiece::~VLayoutPiece()
 //---------------------------------------------------------------------------------------------------------------------
 VLayoutPiece VLayoutPiece::Create(const VPiece &piece, const VContainer *pattern)
 {
-    VLayoutPiece det = VLayoutPiece();
+    VLayoutPiece det;
     det.SetCountourPoints(piece.MainPathPoints(pattern));
     det.SetSeamAllowencePoints(piece.SeamAllowancePoints(pattern), piece.IsSeamAllowance());
+    det.SetInternlaPathsPoints(piece.GetInternalPathsPoints(pattern));
     det.SetName(piece.GetName());
     const VPatternPieceData& data = piece.GetPatternPieceData();
     if (data.IsVisible() == true)
@@ -498,6 +499,18 @@ void VLayoutPiece::SetLayoutAllowencePoints()
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QVector<QPointF>> VLayoutPiece::GetInternlaPathsPoints() const
+{
+    return d->m_internalPaths;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VLayoutPiece::SetInternlaPathsPoints(const QVector<QVector<QPointF>> &internalPathsPoints)
+{
+    d->m_internalPaths = internalPathsPoints;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VLayoutPiece::Map(const QVector<QPointF> &points) const
 {
@@ -695,21 +708,17 @@ void VLayoutPiece::CreateTextItems()
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-int VLayoutPiece::GetTextItemsCount() const
-{
-    return d->m_liPP.count();
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 /**
- * @brief VLayoutDetail::GetTextItem Creates and returns the i-th text item
+ * @brief CreateTextItem Creates the i-th text item
  * @param i index of the requested item
- * @return pointer to the newly created item. The caller is responsible to delete it.
+ * @param parent parent of this text item. Can't be null.
  */
-QGraphicsItem* VLayoutPiece::GetTextItem(int i) const
+void VLayoutPiece::CreateTextItem(int i, QGraphicsItem *parent) const
 {
-    QGraphicsPathItem* item = new QGraphicsPathItem();
+    SCASSERT(parent != nullptr)
+
+    QGraphicsPathItem* item = new QGraphicsPathItem(parent);
     QTransform transform = d->matrix;
 
     QPainterPath path = transform.map(d->m_liPP[i]);
@@ -747,7 +756,6 @@ QGraphicsItem* VLayoutPiece::GetTextItem(int i) const
 
     item->setPath(path);
     item->setBrush(QBrush(Qt::black));
-    return item;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -771,18 +779,30 @@ QPainterPath VLayoutPiece::LayoutAllowencePath() const
 QGraphicsItem *VLayoutPiece::GetItem() const
 {
     QGraphicsPathItem *item = new QGraphicsPathItem();
-    item->setPath(ContourPath());
+    QPainterPath contour = ContourPath();
+    contour.addPath(InternalPathsPath());
+    item->setPath(contour);
+
+    for (int i = 0; i < d->m_liPP.count(); ++i)
+    {
+        CreateTextItem(i, item);
+    }
+
+    CreateGrainlineItem(item);
+
     return item;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QGraphicsItem* VLayoutPiece::GetGrainlineItem() const
+void VLayoutPiece::CreateGrainlineItem(QGraphicsItem *parent) const
 {
+    SCASSERT(parent != nullptr)
+
     if (d->grainlinePoints.count() < 2)
     {
-        return 0;
+        return;
     }
-    VGraphicsFillItem* item = new VGraphicsFillItem();
+    VGraphicsFillItem* item = new VGraphicsFillItem(parent);
     QPainterPath path;
     QVector<QPointF> v = Map(d->grainlinePoints);
     path.moveTo(v.at(0));
@@ -791,7 +811,29 @@ QGraphicsItem* VLayoutPiece::GetGrainlineItem() const
         path.lineTo(v.at(i));
     }
     item->setPath(path);
-    return item;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPainterPath VLayoutPiece::InternalPathsPath() const
+{
+    QPainterPath allPaths;
+    allPaths.setFillRule(Qt::WindingFill);
+
+    for (qint32 i = 0; i < d->m_internalPaths.count(); ++i)
+    {
+        const QVector<QPointF> points = Map(d->m_internalPaths.at(i));
+        QPainterPath path;
+        path.setFillRule(Qt::WindingFill);
+        path.moveTo(points.at(0));
+        for (qint32 j = 1; j < points.count(); ++j)
+        {
+            path.lineTo(points.at(j));
+        }
+        path.lineTo(points.at(0));
+        allPaths.addPath(path);
+    }
+
+    return allPaths;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/libs/vlayout/vlayoutpiece.h b/src/libs/vlayout/vlayoutpiece.h
index 63a46a9db..bf7ae6c84 100644
--- a/src/libs/vlayout/vlayoutpiece.h
+++ b/src/libs/vlayout/vlayoutpiece.h
@@ -79,6 +79,9 @@ public:
     QVector<QPointF> GetLayoutAllowencePoints() const;
     void SetLayoutAllowencePoints();
 
+    QVector<QVector<QPointF>> GetInternlaPathsPoints() const;
+    void SetInternlaPathsPoints(const QVector<QVector<QPointF>> &internalPathsPoints);
+
     void SetDetail(const QString &qsName, const VPatternPieceData& data, const QFont& font);
 
     void SetPatternInfo(const VAbstractPattern* pDoc, const VPatternInfoGeometry& geom, const QFont& font,
@@ -115,19 +118,23 @@ public:
     bool isNull() const;
     qint64 Square() const;
     QPainterPath ContourPath() const;
-    void ClearTextItems();
-    void CreateTextItems();
-    int GetTextItemsCount() const Q_REQUIRED_RESULT;
-    QGraphicsItem* GetTextItem(int i) const Q_REQUIRED_RESULT;
+
     QPainterPath LayoutAllowencePath() const;
     QGraphicsItem *GetItem() const Q_REQUIRED_RESULT;
-    QGraphicsItem* GetGrainlineItem() const Q_REQUIRED_RESULT;
 
 private:
     QSharedDataPointer<VLayoutPieceData>   d;
 
     QVector<QPointF> DetailPath() const;
 
+    void ClearTextItems();
+    void CreateTextItems();
+
+    void CreateTextItem(int i, QGraphicsItem *parent) const;
+    void CreateGrainlineItem(QGraphicsItem *parent) const;
+
+    QPainterPath InternalPathsPath() const;
+
     static QVector<VSAPoint> PrepareAllowance(const QVector<QPointF> &points);
     QVector<QPointF> Map(const QVector<QPointF> &points) const;
     static QVector<QPointF> RoundPoints(const QVector<QPointF> &points);
diff --git a/src/libs/vlayout/vlayoutpiece_p.h b/src/libs/vlayout/vlayoutpiece_p.h
index 76a5b1cff..dc2e3d821 100644
--- a/src/libs/vlayout/vlayoutpiece_p.h
+++ b/src/libs/vlayout/vlayoutpiece_p.h
@@ -47,58 +47,84 @@ class VLayoutPieceData : public QSharedData
 {
 public:
     VLayoutPieceData()
-        :contour(QVector<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()),
-          matrix(QMatrix()), layoutWidth(0), mirror(false), detailLabel(QVector<QPointF>()),
-          patternInfo(QVector<QPointF>()), grainlinePoints(QVector<QPointF>()), detailData(), patternGeom(),
-          grainlineGeom(), m_tmDetail(), m_tmPattern(), m_liPP(QList<QPainterPath>())
+        : contour(),
+          seamAllowence(),
+          layoutAllowence(),
+          m_internalPaths(),
+          matrix(),
+          layoutWidth(0),
+          mirror(false),
+          detailLabel(),
+          patternInfo(),
+          grainlinePoints(),
+          detailData(),
+          patternGeom(),
+          grainlineGeom(),
+          m_tmDetail(),
+          m_tmPattern(),
+          m_liPP()
     {}
 
     VLayoutPieceData(const VLayoutPieceData &detail)
-        :QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence),
-          layoutAllowence(detail.layoutAllowence), matrix(detail.matrix),
-          layoutWidth(detail.layoutWidth), mirror(detail.mirror), detailLabel(detail.detailLabel),
-          patternInfo(detail.patternInfo), grainlinePoints(detail.grainlinePoints), detailData(detail.detailData),
-          patternGeom(detail.patternGeom), grainlineGeom(detail.grainlineGeom), m_tmDetail(detail.m_tmDetail),
-          m_tmPattern(detail.m_tmPattern), m_liPP(detail.m_liPP)
+        : QSharedData(detail),
+          contour(detail.contour),
+          seamAllowence(detail.seamAllowence),
+          layoutAllowence(detail.layoutAllowence),
+          m_internalPaths(detail.m_internalPaths),
+          matrix(detail.matrix),
+          layoutWidth(detail.layoutWidth),
+          mirror(detail.mirror),
+          detailLabel(detail.detailLabel),
+          patternInfo(detail.patternInfo),
+          grainlinePoints(detail.grainlinePoints),
+          detailData(detail.detailData),
+          patternGeom(detail.patternGeom),
+          grainlineGeom(detail.grainlineGeom),
+          m_tmDetail(detail.m_tmDetail),
+          m_tmPattern(detail.m_tmPattern),
+          m_liPP(detail.m_liPP)
     {}
 
     ~VLayoutPieceData() {}
 
     /** @brief contour list of contour points. */
-    QVector<QPointF>                        contour;
+    QVector<QPointF>          contour;
 
     /** @brief seamAllowence list of seam allowence points. */
-    QVector<QPointF>                        seamAllowence;
+    QVector<QPointF>          seamAllowence;
 
     /** @brief layoutAllowence list of layout allowence points. */
-    QVector<QPointF>                        layoutAllowence;
+    QVector<QPointF>          layoutAllowence;
+
+    /** @brief m_layoutAllowence list of internal paths points. */
+    QVector<QVector<QPointF>> m_internalPaths;
 
     /** @brief matrix transformation matrix*/
-    QTransform                              matrix;
+    QTransform                matrix;
 
     /** @brief layoutWidth value layout allowence width in pixels. */
-    qreal                                   layoutWidth;
+    qreal                     layoutWidth;
 
-    bool                                    mirror;
+    bool                      mirror;
 
     /** @brief detailLabel detail label rectangle */
-    QVector<QPointF>                        detailLabel;
+    QVector<QPointF>          detailLabel;
     /** @brief patternInfo pattern info rectangle */
-    QVector<QPointF>                        patternInfo;
+    QVector<QPointF>          patternInfo;
     /** @brief grainlineInfo line */
-    QVector<QPointF>                        grainlinePoints;
+    QVector<QPointF>          grainlinePoints;
     /** @brief detailData detail data */
-    VPatternPieceData                       detailData;
+    VPatternPieceData         detailData;
     /** @brief patternGeom pattern geometry */
-    VPatternInfoGeometry                    patternGeom;
+    VPatternInfoGeometry      patternGeom;
     /** @brief grainlineGeom grainline geometry */
-    VGrainlineGeometry                      grainlineGeom;
+    VGrainlineGeometry        grainlineGeom;
     /** @brief m_tmDetail text manager for laying out detail info */
-    VTextManager                            m_tmDetail;
+    VTextManager              m_tmDetail;
     /** @brief m_tmPattern text manager for laying out pattern info */
-    VTextManager                            m_tmPattern;
+    VTextManager              m_tmPattern;
     /** @bried m_liPP list of generated text painter paths */
-    QList<QPainterPath>                     m_liPP;
+    QList<QPainterPath>       m_liPP;
 
 private:
     VLayoutPieceData &operator=(const VLayoutPieceData &) Q_DECL_EQ_DELETE;
diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp
index 85200418d..704921167 100644
--- a/src/libs/vpatterndb/vpiece.cpp
+++ b/src/libs/vpatterndb/vpiece.cpp
@@ -177,6 +177,21 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
     return Equidistant(pointsEkv, width);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QVector<QPointF>> VPiece::GetInternalPathsPoints(const VContainer *data) const
+{
+    QVector<QVector<QPointF>> pathsPoints;
+    for (int i = 0; i < d->m_internalPaths.size(); ++i)
+    {
+        const VPiecePath path = data->GetPiecePath(d->m_internalPaths.at(i));
+        if (path.GetType() == PiecePathType::InternalPath)
+        {
+            pathsPoints.append(path.PathPoints(data));
+        }
+    }
+    return pathsPoints;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 QPainterPath VPiece::MainPathPath(const VContainer *data) const
 {
diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h
index 0ea0180e4..111d368c7 100644
--- a/src/libs/vpatterndb/vpiece.h
+++ b/src/libs/vpatterndb/vpiece.h
@@ -64,6 +64,8 @@ public:
     QVector<VPointF> MainPathNodePoints(const VContainer *data) const;
     QVector<QPointF> SeamAllowancePoints(const VContainer *data) const;
 
+    QVector<QVector<QPointF>> GetInternalPathsPoints(const VContainer *data) const;
+
     QPainterPath MainPathPath(const VContainer *data) const;
     QPainterPath SeamAllowancePath(const VContainer *data) const;
 

From 426e24dccf15c608b5e734b96a3c362b8e6b922b Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 15:08:59 +0200
Subject: [PATCH 192/208] Use predefined symbol degree variable.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index a9d1b5a44..e2f9c1d74 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -891,8 +891,7 @@ void DialogSeamAllowance::UpdateValues()
         {
             plbVal = ui->labelRot;
             plbText = ui->labelEditRot;
-            QChar ch(0x00b0);
-            qsUnit = ch;
+            qsUnit = degreeSymbol;
         }
         else
         {

From 75efd4021b7fbd4d1b6c8577399ffbfa9521db0e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 15:21:08 +0200
Subject: [PATCH 193/208] All united details should have appropriate flag
 setted up.

--HG--
branch : feature
---
 src/libs/vtools/tools/vtooluniondetails.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index f3b116ad6..b2ebddbfc 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -1186,6 +1186,7 @@ void CreateUnitedDetail(quint32 id, const VToolUnionDetailsInitData &initData, q
     newDetail.SetFormulaSAWidth(formulaSAWidth, d1.GetSAWidth());
     newDetail.SetMx(d1.GetMx());
     newDetail.SetMy(d1.GetMy());
+    newDetail.SetUnited(true);
     VToolSeamAllowance::Create(0, newDetail, formulaSAWidth, initData.scene, initData.doc, initData.data,
                                initData.parse, Source::FromTool, drawName);
 

From 5b7e359fcd904eea70ce657e53518623d7f9a2a1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sun, 22 Jan 2017 15:29:23 +0200
Subject: [PATCH 194/208] Rename class TST_VDetail.

--HG--
branch : feature
---
 src/test/ValentinaTest/ValentinaTest.pro                   | 4 ++--
 src/test/ValentinaTest/qttestmainlambda.cpp                | 4 ++--
 src/test/ValentinaTest/{tst_vdetail.cpp => tst_vpiece.cpp} | 6 +++---
 src/test/ValentinaTest/{tst_vdetail.h => tst_vpiece.h}     | 6 +++---
 4 files changed, 10 insertions(+), 10 deletions(-)
 rename src/test/ValentinaTest/{tst_vdetail.cpp => tst_vpiece.cpp} (98%)
 rename src/test/ValentinaTest/{tst_vdetail.h => tst_vpiece.h} (91%)

diff --git a/src/test/ValentinaTest/ValentinaTest.pro b/src/test/ValentinaTest/ValentinaTest.pro
index a421d5acf..0427cb402 100644
--- a/src/test/ValentinaTest/ValentinaTest.pro
+++ b/src/test/ValentinaTest/ValentinaTest.pro
@@ -45,7 +45,7 @@ SOURCES += \
     tst_vlockguard.cpp \
     tst_misc.cpp \
     tst_vcommandline.cpp \
-    tst_vdetail.cpp \
+    tst_vpiece.cpp \
     tst_vabstractcurve.cpp \
     tst_findpoint.cpp \
     tst_vellipticalarc.cpp \
@@ -71,7 +71,7 @@ HEADERS += \
     tst_vlockguard.h \
     tst_misc.h \
     tst_vcommandline.h \
-    tst_vdetail.h \
+    tst_vpiece.h \
     tst_vabstractcurve.h \
     tst_findpoint.h \
     tst_vellipticalarc.h \
diff --git a/src/test/ValentinaTest/qttestmainlambda.cpp b/src/test/ValentinaTest/qttestmainlambda.cpp
index 6bbf8113c..8a3537b56 100644
--- a/src/test/ValentinaTest/qttestmainlambda.cpp
+++ b/src/test/ValentinaTest/qttestmainlambda.cpp
@@ -40,7 +40,7 @@
 #include "tst_vlockguard.h"
 #include "tst_misc.h"
 #include "tst_vcommandline.h"
-#include "tst_vdetail.h"
+#include "tst_vpiece.h"
 #include "tst_findpoint.h"
 #include "tst_vabstractcurve.h"
 #include "tst_vcubicbezierpath.h"
@@ -67,7 +67,7 @@ int main(int argc, char** argv)
     };
 
     ASSERT_TEST(new TST_FindPoint());
-    ASSERT_TEST(new TST_VDetail());
+    ASSERT_TEST(new TST_VPiece());
     ASSERT_TEST(new TST_VPoster());
     ASSERT_TEST(new TST_VAbstractPiece());
     ASSERT_TEST(new TST_VSpline());
diff --git a/src/test/ValentinaTest/tst_vdetail.cpp b/src/test/ValentinaTest/tst_vpiece.cpp
similarity index 98%
rename from src/test/ValentinaTest/tst_vdetail.cpp
rename to src/test/ValentinaTest/tst_vpiece.cpp
index d835b449c..bdc4d83ef 100644
--- a/src/test/ValentinaTest/tst_vdetail.cpp
+++ b/src/test/ValentinaTest/tst_vpiece.cpp
@@ -26,7 +26,7 @@
  **
  *************************************************************************/
 
-#include "tst_vdetail.h"
+#include "tst_vpiece.h"
 #include "../vpatterndb/vcontainer.h"
 #include "../vpatterndb/vpiece.h"
 #include "../vpatterndb/vpiecenode.h"
@@ -36,13 +36,13 @@
 #include <QtTest>
 
 //---------------------------------------------------------------------------------------------------------------------
-TST_VDetail::TST_VDetail(QObject *parent)
+TST_VPiece::TST_VPiece(QObject *parent)
     :AbstractTest(parent)
 {
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void TST_VDetail::ClearLoop()
+void TST_VPiece::ClearLoop()
 {
     // Input data taken from real case
     // See file <root>/src/app/share/collection/jacketМ6_30-110.val
diff --git a/src/test/ValentinaTest/tst_vdetail.h b/src/test/ValentinaTest/tst_vpiece.h
similarity index 91%
rename from src/test/ValentinaTest/tst_vdetail.h
rename to src/test/ValentinaTest/tst_vpiece.h
index ef7034caa..d2b8898b0 100644
--- a/src/test/ValentinaTest/tst_vdetail.h
+++ b/src/test/ValentinaTest/tst_vpiece.h
@@ -31,17 +31,17 @@
 
 #include "../vmisc/abstracttest.h"
 
-class TST_VDetail : public AbstractTest
+class TST_VPiece : public AbstractTest
 {
     Q_OBJECT
 public:
-    explicit TST_VDetail(QObject *parent = nullptr);
+    explicit TST_VPiece(QObject *parent = nullptr);
 
 private slots:
     void ClearLoop();
 
 private:
-    Q_DISABLE_COPY(TST_VDetail)
+    Q_DISABLE_COPY(TST_VPiece)
 };
 
 #endif // TST_VDETAIL_H

From 41c7031aead4186e1104b222624b55c4423447d2 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 23 Jan 2017 14:02:05 +0200
Subject: [PATCH 195/208] Remove unused anymore enum class EquidistantType.

--HG--
branch : feature
---
 src/libs/vlayout/vlayoutdef.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/libs/vlayout/vlayoutdef.h b/src/libs/vlayout/vlayoutdef.h
index 19fbcc297..d302fd957 100644
--- a/src/libs/vlayout/vlayoutdef.h
+++ b/src/libs/vlayout/vlayoutdef.h
@@ -33,8 +33,6 @@
     #include <ciso646>
 #endif /* Q_CC_MSVC */
 
-enum class EquidistantType : char { OpenEquidistant, CloseEquidistant };
-
 enum class LayoutErrors : char
 {
     NoError,

From 3d835be3b737acb1297887f26db3ce692b35a941 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 23 Jan 2017 14:02:34 +0200
Subject: [PATCH 196/208] Fix test warning message.

--HG--
branch : feature
---
 src/libs/vmisc/abstracttest.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libs/vmisc/abstracttest.cpp b/src/libs/vmisc/abstracttest.cpp
index d22c3e696..73ddd2be4 100644
--- a/src/libs/vmisc/abstracttest.cpp
+++ b/src/libs/vmisc/abstracttest.cpp
@@ -67,7 +67,8 @@ void AbstractTest::Comparison(const QVector<QPointF> &ekv, const QVector<QPointF
     {
         const QPoint p1 = ekv.at(i).toPoint();
         const QPoint p2 = ekvOrig.at(i).toPoint();
-        const QString msg = QString("Got '%1;%2', Exprected '%3;%4'.").arg(p1.x(), p1.y()).arg(p2.x(), p2.y());
+        const QString msg = QString("Index: %1. Got '%2;%3', Exprected '%4;%5'.")
+                .arg(i).arg(p1.x()).arg(p1.y()).arg(p2.x()).arg(p2.y());
         // Check each point. Don't use comparison float values
         QVERIFY2(p1 == p2, qUtf8Printable(msg));
     }

From 7817936d3e4d0ef321441b6bfc48bd47e5af22e4 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Mon, 23 Jan 2017 14:03:07 +0200
Subject: [PATCH 197/208] Fix conversion bug.

--HG--
branch : feature
---
 src/libs/ifc/xml/vpatternconverter.cpp | 5 +++--
 src/libs/vpatterndb/vpiecepath.cpp     | 8 ++++----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index f9d936502..eda09eb61 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -132,6 +132,7 @@ const QString strInLayout                  = QStringLiteral("inLayout");
 const QString strSeamAllowance             = QStringLiteral("seamAllowance");
 const QString strNodeType                  = QStringLiteral("nodeType");
 const QString strDet                       = QStringLiteral("det");
+const QString strTypeObject                = QStringLiteral("typeObject");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)
@@ -1716,9 +1717,9 @@ void VPatternConverter::TagRemoveAttributeTypeObjectInV0_4_0()
                 QDomElement domElement = domNode.toElement();
                 if (not domElement.isNull())
                 {
-                    if (domElement.hasAttribute(strNodeType))
+                    if (domElement.hasAttribute(strTypeObject))
                     {
-                        domElement.removeAttribute(strNodeType);
+                        domElement.removeAttribute(strTypeObject);
                     }
                 }
                 domNode = domNode.nextSibling();
diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 2a35473e4..91e6a8723 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -580,8 +580,8 @@ QPointF VPiecePath::NodePreviousPoint(const VContainer *data, int i) const
             {
                 const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
 
-                const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
-                const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
+                const VSAPoint begin = StartSegment(data, d->m_nodes, index, node.GetReverse());
+                const VSAPoint end = EndSegment(data, d->m_nodes, index, node.GetReverse());
 
                 const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
                 if (points.size() > 1)
@@ -631,8 +631,8 @@ QPointF VPiecePath::NodeNextPoint(const VContainer *data, int i) const
             {
                 const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
 
-                const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
-                const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
+                const VSAPoint begin = StartSegment(data, d->m_nodes, index, node.GetReverse());
+                const VSAPoint end = EndSegment(data, d->m_nodes, index, node.GetReverse());
 
                 const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
                 if (points.size() > 1)

From 49167c0c3c4109bda172eb0dee065d7045effca3 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 11:32:52 +0200
Subject: [PATCH 198/208] Fix conversion to new seam allowance.

--HG--
branch : feature
---
 src/app/valentina/xml/vpattern.cpp  |   7 +-
 src/app/valentina/xml/vpattern.h    |   2 +-
 src/libs/vpatterndb/vnodedetail.cpp | 172 +++++++++++-----------------
 src/libs/vpatterndb/vnodedetail.h   |   3 -
 src/libs/vpatterndb/vpiecenode_p.h  |   4 +-
 5 files changed, 75 insertions(+), 113 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index 117437147..1fa4b300a 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -733,7 +733,8 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
                             Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
                                               "Time to refactor the code.");
                             const bool closed = GetParametrUInt(domElement, AttrClosed, "1");
-                            ParseDetailNodes(element, detail, closed);
+                            const qreal width = GetParametrDouble(domElement, AttrWidth, "0.0");
+                            ParseDetailNodes(element, detail, width, closed);
                         }
                         else
                         {
@@ -777,7 +778,7 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const
+void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, qreal width, bool closed) const
 {
     QVector<VNodeDetail> oldNodes;
     const QDomNodeList nodeList = domElement.childNodes();
@@ -791,7 +792,7 @@ void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, b
         }
     }
 
-    detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, detail.GetSAWidth(), closed));
+    detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, width, closed));
 }
 
 //---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h
index 20f0e8a3a..1c0fb2f3f 100644
--- a/src/app/valentina/xml/vpattern.h
+++ b/src/app/valentina/xml/vpattern.h
@@ -120,7 +120,7 @@ private:
     void           ParseDrawElement(const QDomNode& node, const Document &parse);
     void           ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
     void           ParseDetailElement(QDomElement &domElement, const Document &parse);
-    void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
+    void           ParseDetailNodes(const QDomElement &domElement, VPiece &detail, qreal width, bool closed) const;
     void           ParsePieceDataTag(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePiecePatternInfo(const QDomElement &domElement, VPiece &detail) const;
     void           ParsePieceGrainline(const QDomElement &domElement, VPiece &detail) const;
diff --git a/src/libs/vpatterndb/vnodedetail.cpp b/src/libs/vpatterndb/vnodedetail.cpp
index b7fcf60ba..489c2a257 100644
--- a/src/libs/vpatterndb/vnodedetail.cpp
+++ b/src/libs/vpatterndb/vnodedetail.cpp
@@ -36,6 +36,66 @@
 #include <QLineF>
 #include <QVector>
 
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+bool IsOX(const QLineF &line)
+{
+    return VFuzzyComparePossibleNulls(line.angle(), 0)
+            || VFuzzyComparePossibleNulls(line.angle(), 360)
+            || VFuzzyComparePossibleNulls(line.angle(), 180);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool IsOY(const QLineF &line)
+{
+    return VFuzzyComparePossibleNulls(line.angle(), 90) || VFuzzyComparePossibleNulls(line.angle(), 270);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString LocalWidth(const QLineF &line, const QLineF &movedLine)
+{
+    if (VFuzzyComparePossibleNulls(line.angle(), movedLine.angle()))
+    {
+        return QString().setNum(movedLine.length());
+    }
+    else
+    {// different direction means value is negative
+        return QString("0");
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void ConvertBefore(VPieceNode &node, const QLineF &line, qreal mX, qreal mY)
+{
+    if (not qFuzzyIsNull(mX) && IsOX(line))
+    {
+        const QLineF movedLine(line.p1().x(), line.p1().y(), line.p2().x() + mX, line.p2().y());
+        node.SetFormulaSABefore(LocalWidth(line, movedLine));
+    }
+    else if (not qFuzzyIsNull(mY) && IsOY(line))
+    {
+        const QLineF movedLine(line.p1().x(), line.p1().y(), line.p2().x(), line.p2().y() + mY);
+        node.SetFormulaSABefore(LocalWidth(line, movedLine));
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void ConvertAfter(VPieceNode &node, const QLineF &line, qreal mX, qreal mY)
+{
+    if (not qFuzzyIsNull(mX) && IsOX(line))
+    {
+        const QLineF movedLine(line.p1().x(), line.p1().y(), line.p2().x() + mX, line.p2().y());
+        node.SetFormulaSAAfter(LocalWidth(line, movedLine));
+    }
+    else if (not qFuzzyIsNull(mY) && IsOY(line))
+    {
+        const QLineF movedLine(line.p1().x(), line.p1().y(), line.p2().x(), line.p2().y() + mY);
+        node.SetFormulaSAAfter(LocalWidth(line, movedLine));
+    }
+}
+}//static functions
+
 //---------------------------------------------------------------------------------------------------------------------
 VNodeDetail::VNodeDetail()
     :d(new VNodeDetailData)
@@ -170,16 +230,6 @@ QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<V
         path.Append(VPieceNode(node.getId(), node.getTypeTool(), node.getReverse()));
     }
 
-    auto LocalWidth = [width](qreal move) noexcept
-    {
-        qreal value = width + move;
-        if (value < 0)
-        {
-            value = 0;
-        }
-        return value;
-    };
-
     if (path.PathPoints(data).size() > 2)
     {
         for (int i = 0; i < nodes.size(); ++i)
@@ -194,35 +244,17 @@ QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<V
 
                     const QPointF point = data->GeometricObject<VPointF>(node.getId())->toQPointF();
 
-                    const QPointF xPoint(point.x()+node.getMx(), point.y());
-                    const QPointF yPoint(point.x(), point.y()+node.getMy());
+                    QLineF lineBefore(point, previosPoint);
+                    lineBefore.setAngle(lineBefore.angle()-90);
+                    lineBefore.setLength(width);
 
-                    if (IsSABefore(QLineF(point, previosPoint), QLineF(point, xPoint)))
-                    {
-                        path[i].SetFormulaSABefore(QString().setNum(LocalWidth(node.getMx())));
+                    ConvertBefore(path[i], lineBefore, node.getMx(), node.getMy());
 
-                        if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
-                        {
-                            path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMy())));
-                        }
-                    }
-                    else if (IsSABefore(QLineF(point, previosPoint), QLineF(point, yPoint)))
-                    {
-                        path[i].SetFormulaSABefore(QString().setNum(LocalWidth(node.getMy())));
+                    QLineF lineAfter(point, nextPoint);
+                    lineAfter.setAngle(lineAfter.angle()+90);
+                    lineAfter.setLength(width);
 
-                        if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
-                        {
-                            path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMx())));
-                        }
-                    }
-                    else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
-                    {
-                        path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMx())));
-                    }
-                    else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
-                    {
-                        path[i].SetFormulaSAAfter(QString().setNum(LocalWidth(node.getMy())));
-                    }
+                    ConvertAfter(path[i], lineAfter, node.getMx(), node.getMy());
                 }
             }
         }
@@ -236,71 +268,3 @@ QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<V
 
     return path.GetNodes();
 }
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VNodeDetail::IsSABefore(const QLineF &saBaseLine, const QLineF &mLine)
-{
-    if (qFuzzyIsNull(mLine.length()))
-    {
-        return false;
-    }
-
-    QLineF saLine = saBaseLine;
-    saLine.setAngle(saLine.angle() - 90);
-
-    int saAngle = qRound(saLine.angle());
-    if (saAngle >= 360)
-    {
-        saAngle = 0;
-    }
-
-    int mTest1 = qRound(mLine.angle());
-    if (mTest1 >= 360)
-    {
-        mTest1 = 0;
-    }
-
-    QLineF mrLine = mLine;
-    mrLine.setAngle(mrLine.angle()+180);
-    int mTest2 = qRound(mrLine.angle());
-    if (mTest2 >=360)
-    {
-        mTest2 = 0;
-    }
-
-    return (saAngle == mTest1 || saAngle == mTest2);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool VNodeDetail::IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine)
-{
-    if (qFuzzyIsNull(mLine.length()))
-    {
-        return false;
-    }
-
-    QLineF saLine = saBaseLine;
-    saLine.setAngle(saLine.angle() + 90);
-
-    int saAngle = qRound(saLine.angle());
-    if (saAngle >= 360)
-    {
-        saAngle = 0;
-    }
-
-    int mTest1 = qRound(mLine.angle());
-    if (mTest1 >= 360)
-    {
-        mTest1 = 0;
-    }
-
-    QLineF mrLine = mLine;
-    mrLine.setAngle(mrLine.angle()+180);
-    int mTest2 = qRound(mrLine.angle());
-    if (mTest2 >=360)
-    {
-        mTest2 = 0;
-    }
-
-    return (saAngle == mTest1 || saAngle == mTest2);
-}
diff --git a/src/libs/vpatterndb/vnodedetail.h b/src/libs/vpatterndb/vnodedetail.h
index ca6df9f04..a26056923 100644
--- a/src/libs/vpatterndb/vnodedetail.h
+++ b/src/libs/vpatterndb/vnodedetail.h
@@ -129,9 +129,6 @@ public:
                                        bool closed);
 private:
     QSharedDataPointer<VNodeDetailData> d;
-
-    static bool IsSABefore(const QLineF &saBaseLine, const QLineF &mLine);
-    static bool IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine);
 };
 
 Q_DECLARE_METATYPE(VNodeDetail)
diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index 98c6c6797..df6b2e844 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -45,8 +45,8 @@ public:
           m_reverse(false),
           m_saBefore(-1),
           m_saAfter(-1),
-          m_formulaWidthBefore("-1"),
-          m_formulaWidthAfter("-1"),
+          m_formulaWidthBefore(""),
+          m_formulaWidthAfter(""),
           m_angleType(PieceNodeAngle::ByLength)
     {}
 

From e206ef3d5d245623696f7fa892a0b346fd863cf1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 11:40:10 +0200
Subject: [PATCH 199/208] Instead of "-1" use local variable
 "CurrentSeamAllowance" if value is default.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecenode_p.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecenode_p.h b/src/libs/vpatterndb/vpiecenode_p.h
index df6b2e844..6defef952 100644
--- a/src/libs/vpatterndb/vpiecenode_p.h
+++ b/src/libs/vpatterndb/vpiecenode_p.h
@@ -45,8 +45,8 @@ public:
           m_reverse(false),
           m_saBefore(-1),
           m_saAfter(-1),
-          m_formulaWidthBefore(""),
-          m_formulaWidthAfter(""),
+          m_formulaWidthBefore(currentSeamAllowance),
+          m_formulaWidthAfter(currentSeamAllowance),
           m_angleType(PieceNodeAngle::ByLength)
     {}
 
@@ -56,8 +56,8 @@ public:
           m_reverse(reverse),
           m_saBefore(-1),
           m_saAfter(-1),
-          m_formulaWidthBefore("-1"),
-          m_formulaWidthAfter("-1"),
+          m_formulaWidthBefore(currentSeamAllowance),
+          m_formulaWidthAfter(currentSeamAllowance),
           m_angleType(PieceNodeAngle::ByLength)
     {
         if (m_typeTool == Tool::NodePoint)

From 8322c8d0ab01613e6a85515d678fdbcc525394cd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 13:21:23 +0200
Subject: [PATCH 200/208] Fix bug with point on curve.

--HG--
branch : feature
---
 .../share/collection/bugs/pointOnCurve.val    | 282 ++++++++++++++++++
 src/libs/vgeometry/vabstractcurve.cpp         |  12 +-
 src/libs/vgeometry/vabstractcurve.h           |   1 +
 src/test/ValentinaTest/tst_vabstractcurve.cpp |  73 +++++
 src/test/ValentinaTest/tst_vabstractcurve.h   |   3 +-
 5 files changed, 366 insertions(+), 5 deletions(-)
 create mode 100644 src/app/share/collection/bugs/pointOnCurve.val

diff --git a/src/app/share/collection/bugs/pointOnCurve.val b/src/app/share/collection/bugs/pointOnCurve.val
new file mode 100644
index 000000000..58baf1e84
--- /dev/null
+++ b/src/app/share/collection/bugs/pointOnCurve.val
@@ -0,0 +1,282 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<pattern>
+    <!--Valentina pattern format.-->
+    <version>0.4.0</version>
+    <unit>mm</unit>
+    <author/>
+    <description/>
+    <notes/>
+    <gradation defSize="300" defHeight="1100" custom="true">
+        <heights all="true"/>
+        <sizes all="true"/>
+    </gradation>
+    <measurements>../../../../../../../Valentina_0.5.x/build-Valentina-Qt_5_2_1_GCC_32bit-Debug/src/app/valentina/bin/tables/standard/GOST_man_ru.vst</measurements>
+    <increments>
+        <increment name="#Пс_впрз" description="Высота основания" formula="16.1"/>
+        <increment name="#Пк_впрз1" description="проймы сзади АГ" formula="14"/>
+        <increment name="#Пдтс1" description="Длина спинки" formula="13"/>
+        <increment name="#Пдтс2" description="до линии талии АТ" formula="20"/>
+        <increment name="#Пус_ди" description="Длина куртки АН" formula="-67"/>
+        <increment name="#Пс_шс" description="Ширина спинки ГГ2" formula="21"/>
+        <increment name="#Пк_шс1" description="Опис" formula="2"/>
+        <increment name="#Пк_шс2" description="Опис" formula="2"/>
+        <increment name="#Пшпр1" description="Ширина проймы Г2Г3" formula="46"/>
+        <increment name="#Пшпр2" description="Опис" formula="-24"/>
+        <increment name="#Пс_шг" description="Ширина полочки на" formula="42"/>
+        <increment name="#Пк_шг1" description="уровне линии груди" formula="4"/>
+        <increment name="#Пк_шг2" description="Г3Г4" formula="0"/>
+        <increment name="#Пс_шпт" description=" Ширина полочки на уровне линии талии Т3Т4" formula="19"/>
+        <increment name="#Пс_впрс" description="Высота проймы спинки" formula="42"/>
+        <increment name="#Пс_впр" description="Высота проймы полочки Г3П3" formula="28"/>
+        <increment name="#Пк_впр1" description="Опис" formula="8.5"/>
+        <increment name="#Пс_впрп" description="Высота горловины" formula="38"/>
+        <increment name="#Пк_впрп1" description="полочки Г5А4" formula="9"/>
+        <increment name="#Пшгс" description="Ширина горловины спинки А1А2" formula="30"/>
+        <increment name="#Пк_шп1" description="Длина плечевой линии" formula="3"/>
+        <increment name="#Пк_шп2" description="спинки А3П2" formula="-1"/>
+        <increment name="#Ппос_шп" description="Опис" formula="-2"/>
+        <increment name="#Пс_сб" description="Ширина куртки на линии бедер" formula="20"/>
+        <increment name="#Пдр1" description="Длина рукава АН" formula="82"/>
+        <increment name="#Пдр2" description="Опис" formula="20"/>
+        <increment name="#Пдр_лок1" description="Длина рукава до" formula="38"/>
+        <increment name="#Пдр_лок2" description="локтя АЛ" formula="-10"/>
+        <increment name="#Пшр" description="Ширина рукава с курточным окатом АА1 и ББ2" formula="42"/>
+        <increment name="#Ппос_ор" description="Прибавка на посадку по окату рукава" formula="34"/>
+        <increment name="#Пшр1" description="Description" formula="50"/>
+        <increment name="#Пшр2" description="Description" formula="62"/>
+        <increment name="#Швс" description="Description" formula="70"/>
+        <increment name="#Пвк" description="Висота капишона" formula="20"/>
+        <increment name="#Пшк" description="ширина капишона" formula="20"/>
+    </increments>
+    <draw name="Куртка">
+        <calculation>
+            <point type="single" x="16.3689" y="57.7733" id="33" name="А" mx="1.32292" my="2.64583"/>
+            <point type="endLine" typeLine="none" id="34" name="Г" basePoint="33" lineColor="black" mx="1.32292" angle="270" my="2.64583" length="0.2 * bust_arc_f + 0.07 * height + #Пс_впрз+10"/>
+            <point type="alongLine" typeLine="none" id="35" name="У" firstPoint="33" secondPoint="34" lineColor="black" mx="1.32292" my="2.64583" length="0.5*Line_А_Г"/>
+            <point type="endLine" typeLine="none" id="36" name="Т" basePoint="33" lineColor="black" mx="1.32292" angle="270" my="2.64583" length="0.25 * height + #Пдтс2"/>
+            <point type="endLine" typeLine="hair" id="37" name="Н" basePoint="33" lineColor="black" mx="1.32292" angle="270" my="2.64583" length="0.33 * height + 0.33 * indent_neck_back"/>
+            <point type="endLine" typeLine="hair" id="38" name="Г2" basePoint="34" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.35 * bust_arc_f + 0.017 * height + #Пс_шс + #Пк_шс2"/>
+            <point type="endLine" typeLine="hair" id="39" name="Г3" basePoint="38" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.3 * bust_arc_f + #Пшпр2"/>
+            <point type="endLine" typeLine="hair" id="40" name="Г4" basePoint="39" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.35 * bust_arc_f + 0.01 * height + #Пс_шг + #Пк_шг2"/>
+            <point type="endLine" typeLine="hair" id="41" name="А2" basePoint="33" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.35*neck_mid_circ + #Пшгс"/>
+            <point type="endLine" typeLine="none" id="42" name="Г5" basePoint="40" lineColor="black" mx="1.32292" angle="180" my="2.64583" length="Line_А_А2"/>
+            <point type="endLine" typeLine="hair" id="43" name="А3" basePoint="41" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="0.35*Line_А_А2"/>
+            <point type="endLine" typeLine="hair" id="44" name="А20" basePoint="41" lineColor="black" mx="-2.08003" angle="135" my="6.61594" length="0.75*Line_А2_А3"/>
+            <point type="endLine" typeLine="hair" id="45" name="П" basePoint="38" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="0.2 * bust_arc_f + 0.05 * height + #Пс_впрс+10"/>
+            <point type="endLine" typeLine="hair" id="46" name="П1" basePoint="35" lineColor="black" mx="28.6501" angle="0" my="-31.8727" length="Line_Г_Г2"/>
+            <point type="alongLine" typeLine="hair" id="47" name="П2" firstPoint="43" secondPoint="45" lineColor="black" mx="1.32292" my="2.64583" length="0.2 * bust_arc_f + 0.03 * height + #Пк_шп2 + #Ппос_шп"/>
+            <point type="alongLine" typeLine="none" id="48" name="П20" firstPoint="43" secondPoint="45" lineColor="black" mx="1.32292" my="2.64583" length="50"/>
+            <point type="endLine" typeLine="hair" id="49" name="П3" basePoint="39" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="Line_Г2_П"/>
+            <point type="endLine" typeLine="hair" id="50" name="А4" basePoint="42" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="Line_А_Г+Line_А2_А3"/>
+            <point type="alongLine" typeLine="hair" id="51" name="П4" firstPoint="50" secondPoint="49" lineColor="black" mx="-1.00541" my="-11.3242" length="Line_А3_П2"/>
+            <point type="endLine" typeLine="none" id="52" name="П5" basePoint="39" lineColor="black" mx="8.59896" angle="90" my="-2.01084" length="Line_Г3_П3*0.4444"/>
+            <line typeLine="hair" id="53" firstPoint="51" secondPoint="52" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="54" name="П7" firstPoint="52" secondPoint="51" lineColor="black" mx="-9.23943" my="2.64583" length="0.5*Line_П4_П5"/>
+            <point type="normal" typeLine="hair" id="55" name="П8" firstPoint="54" secondPoint="52" lineColor="black" mx="2.61006" angle="0" my="-10.595" length="1"/>
+            <point type="endLine" typeLine="none" id="56" name="Г6" basePoint="34" lineColor="black" mx="5.48569" angle="0" my="4.79765" length="0.5*(Line_Г_Г2+Line_Г2_Г3+Line_Г3_Г4)"/>
+            <point type="endLine" typeLine="hair" id="57" name="З" basePoint="38" lineColor="black" mx="-3.0442" angle="45" my="8.2607" length="0.24*Line_Г2_Г3"/>
+            <point type="endLine" typeLine="hair" id="58" name="З3" basePoint="39" lineColor="black" mx="0.0751693" angle="135" my="8.88457" length="0.24*Line_Г2_Г3"/>
+            <point type="endLine" typeLine="hair" id="59" name="А5" basePoint="50" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_А_А2"/>
+            <line typeLine="hair" id="60" firstPoint="59" secondPoint="40" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="61" name="А6" firstPoint="59" secondPoint="40" lineColor="black" mx="22.4896" my="-8.99584" length="0.82*Line_А4_А5"/>
+            <point type="alongLine" typeLine="none" id="62" name="А7" firstPoint="50" secondPoint="42" lineColor="black" mx="1.32292" my="2.64583" length="0.8*Line_А4_А5"/>
+            <line typeLine="hair" id="63" firstPoint="62" secondPoint="61" lineColor="black"/>
+            <point type="bisector" typeLine="hair" id="64" name="А51" thirdPoint="61" firstPoint="50" secondPoint="62" lineColor="black" mx="1.32292" my="2.64583" length="150"/>
+            <point type="lineIntersect" id="65" name="А50" p2Line1="59" p2Line2="64" p1Line1="50" p1Line2="62" mx="1.32292" my="2.64583"/>
+            <point type="pointOfContact" id="66" name="Ак" radius="Line_А4_А50" firstPoint="62" center="65" secondPoint="61" mx="1.32292" my="2.64583"/>
+            <point type="endLine" typeLine="hair" id="67" name="Т3" basePoint="36" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Г_Г2+Line_Г2_Г3"/>
+            <line typeLine="hair" id="68" firstPoint="39" secondPoint="67" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="69" name="Т4" basePoint="67" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Г3_Г4"/>
+            <line typeLine="hair" id="70" firstPoint="40" secondPoint="69" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="71" name="Н3" basePoint="37" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Т3_Т4+Line_Т_Т3"/>
+            <line typeLine="hair" id="72" firstPoint="69" secondPoint="71" lineColor="black"/>
+            <point type="endLine" typeLine="none" id="73" name="Н5" basePoint="37" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Г_Г6"/>
+            <line typeLine="hair" id="74" firstPoint="56" secondPoint="73" lineColor="black"/>
+            <line typeLine="hair" id="75" firstPoint="65" secondPoint="66" lineColor="black"/>
+            <arc type="simple" angle1="180" angle2="AngleLine_А50_Ак" id="76" radius="Line_А4_А50" center="65" color="black"/>
+            <spline type="pathInteractive" id="77" color="black">
+                <pathPoint angle1="184.205" pSpline="33" angle2="4.20522" length1="0" length2="27.556"/>
+                <pathPoint angle1="215.751" pSpline="44" angle2="35.7515" length1="12.4503" length2="8.15772"/>
+                <pathPoint angle1="234.166" pSpline="43" angle2="54.166" length1="5.84299" length2="0"/>
+            </spline>
+            <spline type="pathInteractive" id="78" color="black">
+                <pathPoint angle1="80.258" pSpline="47" angle2="260.258" length1="0" length2="20.8645"/>
+                <pathPoint angle1="87.674" pSpline="46" angle2="267.674" length1="30.751" length2="50.1703"/>
+                <pathPoint angle1="120.24" pSpline="57" angle2="300.24" length1="11.5169" length2="12.8071"/>
+                <pathPoint angle1="184.589" pSpline="56" angle2="4.58891" length1="12.5947" length2="0"/>
+            </spline>
+            <point type="endLine" typeLine="hair" id="79" name="П5н" basePoint="52" lineColor="black" mx="-13.6151" angle="180" my="5.24991" length="1"/>
+            <spline type="pathInteractive" id="80" color="black">
+                <pathPoint angle1="101.835" pSpline="51" angle2="281.835" length1="0" length2="27.3441"/>
+                <pathPoint angle1="100.326" pSpline="55" angle2="280.326" length1="3.61809" length2="21.5186"/>
+                <pathPoint angle1="93.053" pSpline="79" angle2="273.053" length1="12.096" length2="38.3854"/>
+                <pathPoint angle1="56.906" pSpline="58" angle2="236.906" length1="13.1026" length2="8.79047"/>
+                <pathPoint angle1="355.114" pSpline="56" angle2="175.114" length1="9.58048" length2="0"/>
+            </spline>
+            <line typeLine="hair" id="81" firstPoint="43" secondPoint="50" lineColor="black"/>
+            <line typeLine="hair" id="82" firstPoint="47" secondPoint="51" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="83" name="П11" firstPoint="47" secondPoint="51" lineColor="black" mx="1.32292" my="2.64583" length="Line_П2_П4*0.5"/>
+            <point type="endLine" typeLine="none" id="86" name="Г81" basePoint="83" lineColor="black" mx="-23.9299" angle="270" my="11.8341" length="Line_А_Г"/>
+            <point type="lineIntersect" id="87" name="Г8" p2Line1="86" p2Line2="39" p1Line1="83" p1Line2="34" mx="-26.0772" my="7.75128"/>
+            <line typeLine="hair" id="88" firstPoint="87" secondPoint="83" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="89" name="К2" basePoint="67" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.1*bust_arc_f"/>
+            <point type="endLine" typeLine="hair" id="90" name="К3" basePoint="89" lineColor="black" mx="1.32292" angle="80" my="2.64583" length="50"/>
+            <point type="endLine" typeLine="hair" id="91" name="К4" basePoint="89" lineColor="black" mx="1.32292" angle="260" my="2.64583" length="50"/>
+            <point type="endLine" typeLine="hair" id="92" name="К5" basePoint="90" lineColor="black" mx="1.32292" angle="170" my="2.64583" length="15"/>
+            <point type="endLine" typeLine="hair" id="93" name="К6" basePoint="91" lineColor="black" mx="1.32292" angle="170" my="2.64583" length="15"/>
+            <line typeLine="hair" id="94" firstPoint="92" secondPoint="93" lineColor="black"/>
+            <point type="alongLine" typeLine="hair" id="95" name="А41" firstPoint="50" secondPoint="49" lineColor="black" mx="1.32292" my="2.64583" length="20"/>
+            <line typeLine="hair" id="96" firstPoint="73" secondPoint="71" lineColor="black"/>
+            <point type="alongLine" typeLine="hair" id="97" name="Н31" firstPoint="73" secondPoint="71" lineColor="black" mx="1.32292" my="2.64583" length="Line_Н5_Н3-50"/>
+            <spline type="simpleInteractive" point4="97" angle1="286.103" angle2="92.0822" id="98" color="black" length1="160.559" length2="101.493" point1="95"/>
+            <point type="cutSplinePath" id="203" name="С1" splinePath="78" mx="23.5479" my="13.2292" length="SplPath_П2_Г6*0.5"/>
+            <point type="cutSplinePath" id="209" name="С3" splinePath="80" mx="18.0755" my="25.1094" length="SplPath_П4_Г6*0.5"/>
+            <point type="alongLine" typeLine="none" id="286" name="Ф1" firstPoint="33" secondPoint="36" lineColor="black" mx="1.32292" my="2.64583" length="Line_А_Т*0.205"/>
+            <point type="cutSplinePath" id="287" name="Ф2" splinePath="78" mx="1.32292" my="2.64583" length="SplPath_П2_С1*0.67"/>
+            <line typeLine="hair" id="290" firstPoint="286" secondPoint="287" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="291" name="Ф3" firstPoint="69" secondPoint="59" lineColor="black" mx="1.32292" my="2.64583" length="Line_Ф1_Т"/>
+            <point type="cutSplinePath" id="292" name="Ф4" splinePath="80" mx="1.32292" my="2.64583" length="SplPath_П4_С3*0.67"/>
+            <line typeLine="hair" id="295" firstPoint="292" secondPoint="291" lineColor="black"/>
+        </calculation>
+        <modeling>
+            <point type="modeling" inUse="true" id="296" idObject="33" mx="1.32292" my="2.64583"/>
+            <spline type="modelingPath" inUse="true" id="297" idObject="77"/>
+            <point type="modeling" inUse="true" id="298" idObject="43" mx="1.32292" my="2.64583"/>
+            <point type="modeling" inUse="true" id="299" idObject="47" mx="1.32292" my="2.64583"/>
+            <spline type="modelingPath" inUse="true" id="300" idObject="78"/>
+            <point type="modeling" inUse="true" id="301" idObject="287" mx="1.32292" my="2.64583"/>
+            <point type="modeling" inUse="true" id="302" idObject="286" mx="1.32292" my="2.64583"/>
+        </modeling>
+        <details>
+            <detail closed="0" id="303" name="Деталь" forbidFlipping="true" united="false" seamAllowance="true" width="7" mx="10.0402" inLayout="true" my="-26.0133" version="2">
+                <data rotation="0" letter="" fontSize="0" visible="true" mx="0" width="0" my="0" height="0"/>
+                <patternInfo rotation="0" fontSize="0" visible="true" mx="0" width="0" my="0" height="0"/>
+                <grainline arrows="0" rotation="90" visible="false" mx="0" my="0" length="0"/>
+                <nodes>
+                    <node type="NodePoint" idObject="299"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="300"/>
+                    <node type="NodePoint" idObject="301"/>
+                    <node type="NodePoint" after="0" idObject="302"/>
+                    <node before="0" type="NodePoint" idObject="296"/>
+                    <node type="NodeSplinePath" reverse="0" idObject="297"/>
+                    <node type="NodePoint" idObject="298"/>
+                </nodes>
+            </detail>
+        </details>
+        <groups/>
+    </draw>
+    <draw name="Рукав">
+        <calculation>
+            <point type="single" x="662.911" y="-31.3691" id="125" name="А" mx="1.32292" my="2.64583"/>
+            <point type="endLine" typeLine="hair" id="126" name="Н" basePoint="125" lineColor="black" mx="1.32292" angle="270" my="2.64583" length="0.33*height+0.15*bust_arc_f-50"/>
+            <point type="alongLine" typeLine="none" id="127" name="Б" firstPoint="125" secondPoint="126" lineColor="black" mx="1.32292" my="2.64583" length="0.3792*Line_Г8_П11"/>
+            <point type="endLine" typeLine="none" id="128" name="Б1" basePoint="127" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Г2_Г3+#Пшр1"/>
+            <point type="endLine" typeLine="none" id="129" name="Б4" basePoint="127" lineColor="black" mx="1.32292" angle="180" my="2.64583" length="Line_Г2_Г3+#Пшр1"/>
+            <point type="endLine" typeLine="hair" id="130" name="Н1" basePoint="126" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.6*Line_Б_Б1+38"/>
+            <line typeLine="hair" id="131" firstPoint="128" secondPoint="130" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="132" name="Н2" basePoint="126" lineColor="black" mx="1.32292" angle="180" my="2.64583" length="0.6*Line_Б_Б1+38"/>
+            <line typeLine="hair" id="133" firstPoint="129" secondPoint="132" lineColor="black"/>
+            <point type="alongLine" typeLine="hair" id="138" name="Б2" firstPoint="127" secondPoint="128" lineColor="black" mx="1.32292" my="2.64583" length="((0.5 * (SplPath_П2_Г6+SplPath_П4_Г6) +3)^2 - Line_А_Б^2)^0.5"/>
+            <point type="alongLine" typeLine="hair" id="139" name="Б3" firstPoint="127" secondPoint="129" lineColor="black" mx="1.32292" my="2.64583" length="((0.5 * (SplPath_П2_Г6+SplPath_П4_Г6) -8)^2 - Line_А_Б^2)^0.5"/>
+            <line typeLine="hair" id="140" firstPoint="125" secondPoint="138" lineColor="black"/>
+            <line typeLine="hair" id="141" firstPoint="125" secondPoint="139" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="142" name="А1" firstPoint="125" secondPoint="138" lineColor="black" mx="19.0616" my="-50.5702" length="Line_А_Б2*0.5"/>
+            <point type="alongLine" typeLine="none" id="143" name="А2" firstPoint="125" secondPoint="142" lineColor="black" mx="0.130208" my="6.82032" length="Line_А_А1*0.5"/>
+            <point type="alongLine" typeLine="none" id="144" name="А3" firstPoint="142" secondPoint="138" lineColor="black" mx="5.9633" my="-10.2441" length="Line_А1_Б2*0.5"/>
+            <point type="alongLine" typeLine="none" id="145" name="А1з" firstPoint="125" secondPoint="139" lineColor="black" mx="-4.43017" my="-60.6381" length="Line_А_Б3*0.5"/>
+            <point type="alongLine" typeLine="none" id="146" name="А2з" firstPoint="125" secondPoint="145" lineColor="black" mx="4.33266" my="4.97457" length="Line_А_А1з*0.5"/>
+            <point type="alongLine" typeLine="none" id="147" name="А3з" firstPoint="145" secondPoint="139" lineColor="black" mx="-2.80186" my="-13.3377" length="Line_А1з_Б3*0.5"/>
+            <point type="normal" typeLine="hair" id="148" name="А4" firstPoint="143" secondPoint="138" lineColor="black" mx="1.89007" angle="0" my="-12.1003" length="0.10*Line_А_Б"/>
+            <point type="normal" typeLine="hair" id="149" name="А4з" firstPoint="146" secondPoint="125" lineColor="black" mx="-15.3305" angle="0" my="-20.8475" length="0.10*Line_А_Б"/>
+            <point type="normal" typeLine="hair" id="150" name="А5" firstPoint="144" secondPoint="125" lineColor="black" mx="-5.89299" angle="0" my="6.80045" length="Line_А2_А4"/>
+            <point type="normal" typeLine="hair" id="151" name="А5з" firstPoint="147" secondPoint="139" lineColor="black" mx="2.85356" angle="0" my="5.92579" length="Line_А2з_А4з"/>
+            <line typeLine="hair" id="152" firstPoint="148" secondPoint="150" lineColor="black"/>
+            <line typeLine="hair" id="153" firstPoint="149" secondPoint="151" lineColor="black"/>
+            <point type="alongLine" typeLine="hair" id="154" name="О" firstPoint="148" secondPoint="143" lineColor="black" mx="-9.59601" my="-2.49453" length="Line_А2_А4*0.25"/>
+            <point type="alongLine" typeLine="hair" id="155" name="Оз" firstPoint="149" secondPoint="146" lineColor="black" mx="5.23899" my="-5.3851" length="Line_А2з_А4з*0.25"/>
+            <point type="alongLine" typeLine="hair" id="156" name="О1" firstPoint="150" secondPoint="144" lineColor="black" mx="8.1015" my="5.05114" length="Line_А4_О"/>
+            <point type="alongLine" typeLine="hair" id="157" name="О1з" firstPoint="151" secondPoint="147" lineColor="black" mx="-14.4209" my="2.20851" length="Line_А4з_Оз"/>
+            <point type="alongLine" typeLine="hair" id="158" name="О2" firstPoint="142" secondPoint="148" lineColor="black" mx="6.04115" my="-33.125" length="Line_А4_А5*0.25"/>
+            <point type="alongLine" typeLine="hair" id="159" name="О2з" firstPoint="145" secondPoint="149" lineColor="black" mx="8.66898" my="14.5691" length="Line_А4з_А5з*0.25"/>
+            <point type="alongLine" typeLine="hair" id="160" name="А6" firstPoint="144" secondPoint="150" lineColor="black" mx="9.12091" my="2.93381" length="Line_А3_А5*0.5"/>
+            <point type="alongLine" typeLine="hair" id="161" name="А6з" firstPoint="147" secondPoint="151" lineColor="black" mx="-12.8902" my="-0.415461" length="Line_А3з_А5з*0.5"/>
+            <point type="lineIntersect" id="162" name="О3" p2Line1="158" p2Line2="138" p1Line1="160" p1Line2="125" mx="5.68854" my="-6.37646"/>
+            <point type="lineIntersect" id="163" name="О3з" p2Line1="159" p2Line2="139" p1Line1="161" p1Line2="125" mx="-22.6642" my="-26.58"/>
+            <point type="alongLine" typeLine="hair" id="164" name="О4" firstPoint="160" secondPoint="144" lineColor="black" mx="13.8377" my="-4.63021" length="Line_А3_А6*0.25"/>
+            <point type="alongLine" typeLine="hair" id="165" name="О4з" firstPoint="161" secondPoint="147" lineColor="black" mx="7.08554" my="-5.9981" length="Line_А3з_А6з*0.25"/>
+            <spline type="pathInteractive" id="166" color="black">
+                <pathPoint angle1="179.998" pSpline="125" angle2="359.998" length1="0" length2="12.3634"/>
+                <pathPoint angle1="153.959" pSpline="154" angle2="333.959" length1="14.6138" length2="5.85177"/>
+                <pathPoint angle1="153.373" pSpline="158" angle2="333.373" length1="5.10362" length2="9.46745"/>
+                <pathPoint angle1="152.532" pSpline="142" angle2="332.532" length1="5.90789" length2="19.9914"/>
+                <pathPoint angle1="158.016" pSpline="156" angle2="338.016" length1="13.1046" length2="12.3332"/>
+                <pathPoint angle1="173.032" pSpline="138" angle2="353.032" length1="17.7872" length2="0"/>
+            </spline>
+            <spline type="pathInteractive" id="167" color="black">
+                <pathPoint angle1="1.148" pSpline="125" angle2="181.148" length1="0" length2="9.88634"/>
+                <pathPoint angle1="24.198" pSpline="155" angle2="204.198" length1="17.7795" length2="4.99338"/>
+                <pathPoint angle1="27.376" pSpline="159" angle2="207.376" length1="8.73578" length2="7.35637"/>
+                <pathPoint angle1="26.864" pSpline="163" angle2="206.864" length1="13.129" length2="8.98105"/>
+                <pathPoint angle1="25.87" pSpline="165" angle2="205.87" length1="13.1037" length2="6.12142"/>
+                <pathPoint angle1="9.899" pSpline="139" angle2="189.899" length1="17.6503" length2="0"/>
+            </spline>
+            <spline type="simpleInteractive" point4="138" angle1="84.068" angle2="255.161" id="168" color="black" length1="135.76" length2="82.0371" point1="130"/>
+            <spline type="simpleInteractive" point4="139" angle1="98.0171" angle2="286.671" id="169" color="black" length1="175.212" length2="76.4262" point1="132"/>
+        </calculation>
+        <modeling/>
+        <details/>
+    </draw>
+    <draw name="Комір">
+        <calculation>
+            <point type="single" x="711.333" y="736.791" id="190" name="В" mx="1.32292" my="2.64583"/>
+            <point type="endLine" typeLine="hair" id="192" name="В1" basePoint="190" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="SplPath_А_А3*2+(Arc_А50_76+Line_А6_Ак)*2"/>
+            <point type="endLine" typeLine="hair" id="193" name="В2" basePoint="190" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="#Швс"/>
+            <point type="endLine" typeLine="hair" id="194" name="В3" basePoint="193" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="SplPath_А_А3*2+(Arc_А50_76+Line_А6_Ак)*2"/>
+            <line typeLine="hair" id="195" firstPoint="194" secondPoint="192" lineColor="black"/>
+        </calculation>
+        <modeling/>
+        <details/>
+    </draw>
+    <draw name="капишон">
+        <calculation>
+            <point type="single" x="-264.749" y="32.1467" id="224" name="А" mx="-8.83849" my="-20.0204"/>
+            <point type="endLine" typeLine="hair" id="225" name="Б" basePoint="224" lineColor="black" mx="1.32292" angle="270" my="2.64583" length="1.33*(height-height_neck_back)+#Пвк"/>
+            <point type="alongLine" typeLine="none" id="226" name="В" firstPoint="224" secondPoint="225" lineColor="black" mx="1.32292" my="2.64583" length="0.33*Line_А_Б"/>
+            <point type="alongLine" typeLine="none" id="227" name="Д" firstPoint="225" secondPoint="226" lineColor="black" mx="1.32292" my="2.64583" length="0.25*(height-height_neck_back)"/>
+            <point type="endLine" typeLine="hair" id="228" name="Г" basePoint="225" lineColor="black" mx="0.709236" angle="270" my="2.03215" length="0.33*Line_А5_А6"/>
+            <point type="endLine" typeLine="hair" id="229" name="А1" basePoint="224" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="0.4*head_circ+#Пшк"/>
+            <point type="alongLine" typeLine="none" id="230" name="А2" firstPoint="229" secondPoint="224" lineColor="black" mx="1.32292" my="2.64583" length="Line_А_В"/>
+            <point type="endLine" typeLine="hair" id="231" name="В1" basePoint="226" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_А_А1"/>
+            <point type="alongLine" typeLine="none" id="232" name="В2" firstPoint="231" secondPoint="226" lineColor="black" mx="1.32292" my="2.64583" length="Line_А_В"/>
+            <line typeLine="hair" id="233" firstPoint="230" secondPoint="232" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="235" name="Г1" basePoint="228" lineColor="black" mx="8.68713" angle="180" my="2.03215" length="0.6*Line_А4_А5"/>
+            <point type="alongLine" typeLine="hair" id="236" name="Г2" firstPoint="235" secondPoint="228" lineColor="black" mx="1.32292" my="2.64583" length="SplPath_А_А3+Arc_А50_76+Line_А6_Ак"/>
+            <point type="endLine" typeLine="hair" id="237" name="Б1" basePoint="236" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="Line_Б_Г"/>
+            <line typeLine="hair" id="238" firstPoint="225" secondPoint="237" lineColor="black"/>
+            <point type="endLine" typeLine="hair" id="239" name="Д1" basePoint="227" lineColor="black" mx="1.32292" angle="0" my="2.64583" length="Line_Б_Б1+2"/>
+            <line typeLine="hair" id="240" firstPoint="239" secondPoint="237" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="243" name="А4" firstPoint="224" secondPoint="226" lineColor="black" mx="1.32292" my="2.64583" length="8"/>
+            <point type="alongLine" typeLine="none" id="244" name="А3" firstPoint="224" secondPoint="230" lineColor="black" mx="1.32292" my="2.64583" length="0.65*Line_А2_А"/>
+            <line typeLine="hair" id="249" firstPoint="244" secondPoint="243" lineColor="black"/>
+            <point type="alongLine" typeLine="none" id="250" name="А5" firstPoint="244" secondPoint="243" lineColor="black" mx="1.32292" my="2.64583" length="Line_А3_А4+10"/>
+            <point type="endLine" typeLine="hair" id="254" name="Л" basePoint="235" lineColor="black" mx="1.32292" angle="90" my="2.64583" length="50"/>
+            <point type="alongLine" typeLine="none" id="255" name="Л1" firstPoint="228" secondPoint="227" lineColor="black" mx="6.63051" my="0.750261" length="Line_Г1_Л"/>
+            <line typeLine="hair" id="256" firstPoint="254" secondPoint="255" lineColor="black"/>
+            <spline type="simpleInteractive" point4="237" angle1="358.736" angle2="178.86" id="258" color="black" length1="122.19" length2="106.948" point1="235"/>
+            <spline type="pathInteractive" id="261" color="black">
+                <pathPoint angle1="175.568" pSpline="230" angle2="355.568" length1="0" length2="79.6733"/>
+                <pathPoint angle1="81.86" pSpline="231" angle2="261.86" length1="54.8681" length2="104.96"/>
+                <pathPoint angle1="73.099" pSpline="237" angle2="253.099" length1="60.9341" length2="0"/>
+            </spline>
+            <spline type="pathInteractive" id="263" color="black">
+                <pathPoint angle1="96.992" pSpline="250" angle2="276.992" length1="0" length2="39.4593"/>
+                <pathPoint angle1="94.44" pSpline="226" angle2="274.44" length1="31.3315" length2="57.3187"/>
+                <pathPoint angle1="2.828" pSpline="254" angle2="182.828" length1="65.4653" length2="0"/>
+            </spline>
+            <spline type="simpleInteractive" point4="230" angle1="11.0159" angle2="176.295" id="275" color="black" length1="53.2682" length2="26.8703" point1="250"/>
+        </calculation>
+        <modeling/>
+        <details/>
+        <groups/>
+    </draw>
+</pattern>
diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp
index 341bb51ff..5d00aca93 100644
--- a/src/libs/vgeometry/vabstractcurve.cpp
+++ b/src/libs/vgeometry/vabstractcurve.cpp
@@ -237,10 +237,8 @@ bool VAbstractCurve::IsIntersectLine(const QLineF &line) const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
+bool VAbstractCurve::IsPointOnCurve(const QVector<QPointF> &points, const QPointF &p)
 {
-    const QVector<QPointF> points = GetPoints();
-
     if (points.isEmpty())
     {
         return false;
@@ -253,7 +251,7 @@ bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
     {
         for (qint32 i = 0; i < points.count()-1; ++i)
         {
-            if (IsPointOnLineSegment(p.toPoint(), points.at(i).toPoint(), points.at(i+1).toPoint()))
+            if (IsPointOnLineSegment(p, points.at(i), points.at(i+1)))
             {
                 return true;
             }
@@ -263,6 +261,12 @@ bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
     return false;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractCurve::IsPointOnCurve(const QPointF &p) const
+{
+    return IsPointOnCurve(GetPoints(), p);
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 quint32 VAbstractCurve::GetDuplicate() const
 {
diff --git a/src/libs/vgeometry/vabstractcurve.h b/src/libs/vgeometry/vabstractcurve.h
index 629572adf..6cad2bb9c 100644
--- a/src/libs/vgeometry/vabstractcurve.h
+++ b/src/libs/vgeometry/vabstractcurve.h
@@ -70,6 +70,7 @@ public:
     virtual QVector<QPointF> IntersectLine(const QLineF &line) const;
     virtual bool             IsIntersectLine(const QLineF &line) const;
 
+    static bool              IsPointOnCurve(const QVector<QPointF> &points, const QPointF &p);
     bool                     IsPointOnCurve(const QPointF &p) const;
 
     virtual qreal            GetStartAngle () const=0;
diff --git a/src/test/ValentinaTest/tst_vabstractcurve.cpp b/src/test/ValentinaTest/tst_vabstractcurve.cpp
index 3b5c04da5..0ce69d462 100644
--- a/src/test/ValentinaTest/tst_vabstractcurve.cpp
+++ b/src/test/ValentinaTest/tst_vabstractcurve.cpp
@@ -113,3 +113,76 @@ void TST_VAbstractCurve::GetSegmentPoints_issue458()
     // Begin comparison
     Comparison(points, origPoints);
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractCurve::IsPointOnCurve_data() const
+{
+    QTest::addColumn<QVector<QPointF>>("points");
+    QTest::addColumn<QPointF>("point");
+    QTest::addColumn<bool>("expectedResult");
+
+
+    QVector<QPointF> points;
+    points << QPointF(714.5704733515146, 229.44783247230293);
+    points << QPointF(713.2432059361518, 236.799577781511);
+    points << QPointF(709.8892587314249, 252.1363394689535);
+    points << QPointF(703.6056072956214, 276.4001729111941);
+    points << QPointF(687.7559494358588, 329.1513838344773);
+    points << QPointF(670.3756426535148, 387.2408887452223);
+    points << QPointF(662.3317449567428, 417.643760273044);
+    points << QPointF(657.4471488294345, 438.31881594794856);
+    points << QPointF(653.1084257285696, 459.2974181766972);
+    points << QPointF(649.4426552757304, 480.5376973511262);
+    points << QPointF(646.5769170924987, 501.9977838630714);
+    points << QPointF(644.6382908004568, 523.6358081043691);
+    points << QPointF(644.1029291338583, 534.5132598425197);
+    points << QPointF(644.1029291338583, 534.5132598425197);
+    points << QPointF(643.4592698551749, 551.9888717674471);
+    points << QPointF(642.9134698671897, 584.1776423714557);
+    points << QPointF(643.1914832622404, 613.2382010061506);
+    points << QPointF(644.2199668178571, 639.3780275889782);
+    points << QPointF(645.9255773115714, 662.8046020373845);
+    points << QPointF(648.2349715209137, 683.7254042688159);
+    points << QPointF(651.0748062234152, 702.3479142007185);
+    points << QPointF(654.3717381966065, 718.8796117505387);
+    points << QPointF(658.0524242180187, 733.5279768357226);
+    points << QPointF(662.0435210651824, 746.5004893737165);
+    points << QPointF(666.2716855156286, 758.0046292819667);
+    points << QPointF(670.6635743468883, 768.2478764779191);
+    points << QPointF(677.400406718071, 781.7952098705392);
+    points << QPointF(686.2864119958404, 797.2061069980141);
+    points << QPointF(690.4766621750516, 804.2970071162871);
+    points << QPointF(690.4766621750516, 804.2970071162871);
+    points << QPointF(692.7921674626707, 808.1521079045636);
+    points << QPointF(697.7183992280718, 815.2245015705212);
+    points << QPointF(702.9886930214004, 821.5595818277402);
+    points << QPointF(708.5917117312482, 827.1885221028615);
+    points << QPointF(714.5161182462067, 832.1424958225257);
+    points << QPointF(720.750575454867, 836.4526764133732);
+    points << QPointF(727.2837462458206, 840.1502373020446);
+    points << QPointF(734.1042935076591, 843.2663519151808);
+    points << QPointF(741.200880128974, 845.8321936794223);
+    points << QPointF(748.5621689983566, 847.8789360214096);
+    points << QPointF(756.1768230043983, 849.4377523677833);
+    points << QPointF(764.0335050356908, 850.5398161451842);
+    points << QPointF(772.1208779808252, 851.2163007802526);
+    points << QPointF(780.4276047283932, 851.4983796996295);
+    points << QPointF(793.250306920113, 851.2897382511853);
+    points << QPointF(802.0871811023624, 850.6707401574804);
+
+    QPointF point(652.5169278885382, 462.6106569368444);
+
+    // See file collection/bug/pointOnCurve.val
+    QTest::newRow("Point on curve") << points << point << true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void TST_VAbstractCurve::IsPointOnCurve() const
+{
+    QFETCH(QVector<QPointF>, points);
+    QFETCH(QPointF, point);
+    QFETCH(bool, expectedResult);
+
+    bool result = VAbstractCurve::IsPointOnCurve(points, point);
+    QCOMPARE(result, expectedResult);
+}
diff --git a/src/test/ValentinaTest/tst_vabstractcurve.h b/src/test/ValentinaTest/tst_vabstractcurve.h
index 7ffd2d773..565b995f2 100644
--- a/src/test/ValentinaTest/tst_vabstractcurve.h
+++ b/src/test/ValentinaTest/tst_vabstractcurve.h
@@ -39,7 +39,8 @@ public:
 
 private slots:
     void GetSegmentPoints_issue458();
-
+    void IsPointOnCurve_data() const;
+    void IsPointOnCurve() const;
 };
 
 #endif // TST_VABSTRACTCURVE_H

From d7d9deb53679e53c2eccf85bd6bd694e2c37c918 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 13:51:44 +0200
Subject: [PATCH 201/208] Fix test.

--HG--
branch : feature
---
 src/libs/vmisc/abstracttest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/vmisc/abstracttest.cpp b/src/libs/vmisc/abstracttest.cpp
index 73ddd2be4..74e5d79b9 100644
--- a/src/libs/vmisc/abstracttest.cpp
+++ b/src/libs/vmisc/abstracttest.cpp
@@ -67,7 +67,7 @@ void AbstractTest::Comparison(const QVector<QPointF> &ekv, const QVector<QPointF
     {
         const QPoint p1 = ekv.at(i).toPoint();
         const QPoint p2 = ekvOrig.at(i).toPoint();
-        const QString msg = QString("Index: %1. Got '%2;%3', Exprected '%4;%5'.")
+        const QString msg = QString("Index: %1. Got '%2;%3', Expected '%4;%5'.")
                 .arg(i).arg(p1.x()).arg(p1.y()).arg(p2.x()).arg(p2.y());
         // Check each point. Don't use comparison float values
         QVERIFY2(p1 == p2, qUtf8Printable(msg));

From 19400f5b838ed1d08605299b957146e979ad9ccd Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 14:20:25 +0200
Subject: [PATCH 202/208] A seam allowance value can be 0.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp     | 6 +++---
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 9e71a3a27..5f767e6af 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -376,7 +376,7 @@ void DialogPiecePath::EvalWidth()
     labelEditFormula = ui->labelEditWidth;
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidth->toPlainText();
-    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, true, true);
+    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, false, true);
 
     if (m_saWidth >= 0)
     {
@@ -397,7 +397,7 @@ void DialogPiecePath::EvalWidthBefore()
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidthBefore->toPlainText();
     bool flagFormula = false; // fake flag
-    Eval(formula, flagFormula, ui->labelResultBefore, postfix, true, true);
+    Eval(formula, flagFormula, ui->labelResultBefore, postfix, false, true);
 
     UpdateNodeSABefore(GetFormulaSAWidthBefore());
 }
@@ -409,7 +409,7 @@ void DialogPiecePath::EvalWidthAfter()
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidthAfter->toPlainText();
     bool flagFormula = false; // fake flag
-    Eval(formula, flagFormula, ui->labelResultAfter, postfix, true, true);
+    Eval(formula, flagFormula, ui->labelResultAfter, postfix, false, true);
 
     UpdateNodeSABefore(GetFormulaSAWidthAfter());
 }
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index e2f9c1d74..5b6abae29 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -1081,7 +1081,7 @@ void DialogSeamAllowance::EvalWidth()
     labelEditFormula = ui->labelEditWidth;
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidth->toPlainText();
-    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, true, true);
+    m_saWidth = Eval(formula, flagFormula, ui->labelResultWidth, postfix, false, true);
 
     if (m_saWidth >= 0)
     {
@@ -1102,7 +1102,7 @@ void DialogSeamAllowance::EvalWidthBefore()
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidthBefore->toPlainText();
     bool flagFormula = false; // fake flag
-    Eval(formula, flagFormula, ui->labelResultBefore, postfix, true, true);
+    Eval(formula, flagFormula, ui->labelResultBefore, postfix, false, true);
 
     UpdateNodeSABefore(GetFormulaSAWidthBefore());
 }
@@ -1114,7 +1114,7 @@ void DialogSeamAllowance::EvalWidthAfter()
     const QString postfix = VDomDocument::UnitsToStr(qApp->patternUnit(), true);
     const QString formula = ui->plainTextEditFormulaWidthAfter->toPlainText();
     bool flagFormula = false; // fake flag
-    Eval(formula, flagFormula, ui->labelResultAfter, postfix, true, true);
+    Eval(formula, flagFormula, ui->labelResultAfter, postfix, false, true);
 
     UpdateNodeSAAfter(GetFormulaSAWidthAfter());
 }

From ede59d003fb127dabeecd1b975d35320438a51df Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 14:42:51 +0200
Subject: [PATCH 203/208] Update formula value if node was changed.

--HG--
branch : feature
---
 src/libs/vtools/dialogs/tools/dialogpiecepath.cpp     | 4 ----
 src/libs/vtools/dialogs/tools/dialogseamallowance.cpp | 5 -----
 2 files changed, 9 deletions(-)

diff --git a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
index 5f767e6af..c4ca47744 100644
--- a/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogpiecepath.cpp
@@ -286,8 +286,6 @@ void DialogPiecePath::NodeChanged(int index)
 
     ui->comboBoxAngle->setDisabled(true);
 
-    ui->plainTextEditFormulaWidthBefore->blockSignals(true);
-    ui->plainTextEditFormulaWidthAfter->blockSignals(true);
     ui->comboBoxAngle->blockSignals(true);
 
     if (index != -1)
@@ -353,8 +351,6 @@ void DialogPiecePath::NodeChanged(int index)
         ui->comboBoxAngle->setCurrentIndex(-1);
     }
 
-    ui->plainTextEditFormulaWidthBefore->blockSignals(false);
-    ui->plainTextEditFormulaWidthAfter->blockSignals(false);
     ui->comboBoxAngle->blockSignals(false);
 }
 
diff --git a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
index 5b6abae29..7ebc6f922 100644
--- a/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
+++ b/src/libs/vtools/dialogs/tools/dialogseamallowance.cpp
@@ -603,8 +603,6 @@ void DialogSeamAllowance::NodeChanged(int index)
 
     ui->comboBoxAngle->setDisabled(true);
 
-    ui->plainTextEditFormulaWidthBefore->blockSignals(true);
-    ui->plainTextEditFormulaWidthAfter->blockSignals(true);
     ui->comboBoxAngle->blockSignals(true);
 
     if (index != -1)
@@ -669,9 +667,6 @@ void DialogSeamAllowance::NodeChanged(int index)
         ui->plainTextEditFormulaWidthAfter->setPlainText("");
         ui->comboBoxAngle->setCurrentIndex(-1);
     }
-
-    ui->plainTextEditFormulaWidthBefore->blockSignals(false);
-    ui->plainTextEditFormulaWidthAfter->blockSignals(false);
     ui->comboBoxAngle->blockSignals(false);
 }
 

From af5bbf02f6c5f38c226c7833db4c852764472a82 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 15:45:17 +0200
Subject: [PATCH 204/208] Fix tests.

--HG--
branch : feature
---
 src/app/share/collection/bugs/Issue_#604.val  |   2 +-
 src/app/share/collection/test/merki27.vit     |  24 +
 src/test/ValentinaTest/tst_vabstractpiece.cpp | 743 +++++++++++-------
 src/test/ValentinaTest/tst_vabstractpiece.h   |  10 +-
 src/test/ValentinaTest/tst_vpiece.cpp         |   3 +-
 5 files changed, 496 insertions(+), 286 deletions(-)
 create mode 100644 src/app/share/collection/test/merki27.vit

diff --git a/src/app/share/collection/bugs/Issue_#604.val b/src/app/share/collection/bugs/Issue_#604.val
index 084ddd57b..f43d59593 100644
--- a/src/app/share/collection/bugs/Issue_#604.val
+++ b/src/app/share/collection/bugs/Issue_#604.val
@@ -6,7 +6,7 @@
     <author/>
     <description/>
     <notes/>
-    <measurements>3XL.vit</measurements>
+    <measurements>Issue_#604.vit</measurements>
     <increments/>
     <draw name="Élément de patron 1">
         <calculation>
diff --git a/src/app/share/collection/test/merki27.vit b/src/app/share/collection/test/merki27.vit
new file mode 100644
index 000000000..4b7527a98
--- /dev/null
+++ b/src/app/share/collection/test/merki27.vit
@@ -0,0 +1,24 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<vit>
+    <!--Measurements created with Valentina (http://www.valentina-project.org/).-->
+    <version>0.3.3</version>
+    <read-only>false</read-only>
+    <notes/>
+    <unit>cm</unit>
+    <pm_system>998</pm_system>
+    <personal>
+        <family-name/>
+        <given-name/>
+        <birth-date>1800-01-01</birth-date>
+        <gender>unknown</gender>
+        <email/>
+    </personal>
+    <body-measurements>
+        <m name="lowbust_circ" value="107"/>
+        <m name="hip_circ_with_abdomen" value="88"/>
+        <m name="waist_circ" value="60"/>
+        <m name="neck_back_to_waist_b" value="39"/>
+        <m name="waist_to_highhip_b" value="19"/>
+        <m name="arm_shoulder_tip_to_wrist" value="57"/>
+    </body-measurements>
+</vit>
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp
index 553771c60..6705e500e 100644
--- a/src/test/ValentinaTest/tst_vabstractpiece.cpp
+++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp
@@ -543,34 +543,79 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsCase1() const
 {
     QVector<QPointF> points;
 
-    points += QPointF(30.0, 970.3935748031496);
-    points += QPointF(30.0, 2.1993068570824366);
-    points += QPointF(114.18582053395916, -1.0122621856204752);
-    points += QPointF(193.32267013775137, -14.358819619401812);
-    points += QPointF(242.10707671244683, -32.17908690671806);
-    points += QPointF(271.8971162152593, -50.207724037690014);
-    points += QPointF(295.9981384039675, -73.05193874264779);
-    points += QPointF(291.7916402578659, -67.42426694301096);
+    points += QPointF(30.00000000000004, 970.3929479721926);
+    points += QPointF(30.0, 2.204434307474013);
+    points += QPointF(47.110950439162494, 2.154008996440882);
+    points += QPointF(75.17428353484098, 1.4485680510386028);
+    points += QPointF(94.48820285018608, 0.4902498458165696);
+    points += QPointF(114.29080866669788, -1.0082936883322242);
+    points += QPointF(134.30369213200785, -3.146524533710341);
+    points += QPointF(154.30324182399514, -6.0212092507409025);
+    points += QPointF(174.06202812984606, -9.721413151776975);
+    points += QPointF(193.35089649585723, -14.32603434620921);
+    points += QPointF(212.04908234619523, -19.93308318294329);
+    points += QPointF(225.4146962614004, -24.83196935145066);
+    points += QPointF(233.88383173589082, -28.35105572413872);
+    points += QPointF(242.16354279128632, -32.17883523742874);
+    points += QPointF(250.12919225691988, -36.27548734456109);
+    points += QPointF(257.76141086050376, -40.64361165848513);
+    points += QPointF(265.0438386703493, -45.28609897626606);
+    points += QPointF(271.9635110924753, -50.20688688697322);
+    points += QPointF(278.5110730948284, -55.4119084151831);
+    points += QPointF(284.68071875165725, -60.91018735939974);
+    points += QPointF(290.46975730117975, -66.71498198586181);
+    points += QPointF(295.87773947883056, -72.84482460043537);
+    points += QPointF(301.0311752209645, -79.48669791277798);
+    points += QPointF(292.5914051639158, -67.31392104851938);
     points += QPointF(556.8930273120665, -30.847456102511416);
     points += QPointF(539.6101141051189, 79.89131577778163);
     points += QPointF(585.9167315845334, -20.702420721823447);
-    points += QPointF(1117.424153174025, 212.64949937811681);
-    points += QPointF(1075.303535889726, 303.4417262358707);
-    points += QPointF(1034.367455532369, 409.91489458521534);
-    points += QPointF(1016.7086496269483, 470.1391211588565);
-    points += QPointF(1002.6502749276095, 549.8913110678527);
-    points += QPointF(1002.7092529129402, 594.4292010581551);
-    points += QPointF(1004.1768887194628, 604.1457258376107);
-    points += QPointF(1009.2070121912753, 620.6931338009274);
-    points += QPointF(1019.1613725437678, 641.9748709736807);
-    points += QPointF(1033.0209611044565, 662.9678611314132);
-    points += QPointF(1049.114087400246, 680.4406818558615);
-    points += QPointF(1065.8570577426399, 692.968441452634);
-    points += QPointF(1083.1677152645557, 700.9292457138567);
-    points += QPointF(1105.2479226099044, 705.3103889738845);
-    points += QPointF(1290.6502488400083, 712.9440934612204);
-    points += QPointF(1302.4161318705774, 881.6558256043734);
-    points += QPointF(30.0, 970.3935748031496);
+    points += QPointF(1117.4712505569892, 212.6701769158142);
+    points += QPointF(1107.8013393916237, 232.47256047676322);
+    points += QPointF(1096.0328222042483, 257.2724337531229);
+    points += QPointF(1085.2347243947604, 280.86364678273935);
+    points += QPointF(1075.284743777034, 303.4467181585846);
+    points += QPointF(1066.1500107021461, 325.033221582634);
+    points += QPointF(1057.8916931702825, 345.40221101096097);
+    points += QPointF(1046.6844069650929, 374.5619971088514);
+    points += QPointF(1034.1843603449327, 410.2384638595294);
+    points += QPointF(1024.281900134066, 441.9665592645446);
+    points += QPointF(1016.6128103198599, 470.0987514791772);
+    points += QPointF(1010.8915481272591, 494.7652903217387);
+    points += QPointF(1006.8300406648394, 516.1171535751373);
+    points += QPointF(1004.140951447517, 534.3338730421456);
+    points += QPointF(1002.5429209641061, 549.6340874837038);
+    points += QPointF(1001.7684597861733, 562.2905401031172);
+    points += QPointF(1001.5753826870504, 572.6532694631434);
+    points += QPointF(1001.7511114738644, 580.6472328726268);
+    points += QPointF(1002.5244573746393, 592.6631414076071);
+    points += QPointF(1011.1831553003773, 625.860901250618);
+    points += QPointF(1013.5469326629959, 631.1835932583286);
+    points += QPointF(1016.1978697144372, 636.6181674061058);
+    points += QPointF(1019.1173567112357, 642.0917891993197);
+    points += QPointF(1022.283791807397, 647.5382096308747);
+    points += QPointF(1025.6730034935645, 652.8974380139866);
+    points += QPointF(1029.258679857382, 658.1156604426072);
+    points += QPointF(1033.0128662502555, 663.1453581470851);
+    points += QPointF(1036.906587776057, 667.9455799725583);
+    points += QPointF(1040.910648783598, 672.4823173517011);
+    points += QPointF(1044.9966554234593, 676.7289189086724);
+    points += QPointF(1049.138296281844, 680.666466074281);
+    points += QPointF(1053.3128972071952, 684.2840128781046);
+    points += QPointF(1057.5032369521043, 687.5785757108713);
+    points += QPointF(1061.6995688685456, 690.5547476668297);
+    points += QPointF(1065.9017414956827, 693.2238137995831);
+    points += QPointF(1070.1212524492987, 695.6022659553563);
+    points += QPointF(1074.3830151134682, 697.7096649640421);
+    points += QPointF(1078.7265805419665, 699.565875909043);
+    points += QPointF(1083.206554246492, 701.1878034134409);
+    points += QPointF(1087.8919933013688, 702.5858632116882);
+    points += QPointF(1092.8646688655851, 703.7605199081748);
+    points += QPointF(1098.2162239125396, 704.699271425244);
+    points += QPointF(1104.0444208482252, 705.3744462055462);
+    points += QPointF(1304.758494368609, 711.4626979457951);
+    points += QPointF(1293.9429531218987, 1089.1048479381132);
+    points += QPointF(30.00000000000004, 970.3929479721926);
 
     return points;
 }
@@ -951,24 +996,58 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsCase2() const
 
     points += QPointF(6.735602739585184, 2.204598425196849);
     points += QPointF(445.748031496063, 2.204598425196849);
-    points += QPointF(445.748031496063, 252.741597064484);
-    points += QPointF(407.8726873421697, 270.9512393848742);
-    points += QPointF(383.35720786819263, 278.3073990947694);
-    points += QPointF(358.56601090183574, 281.29234689511463);
-    points += QPointF(311.52157429670274, 276.0460457687877);
-    points += QPointF(269.8658512160491, 259.9136567147091);
-    points += QPointF(234.63885608185402, 236.87965105367914);
-    points += QPointF(206.54666866938726, 209.66914671340476);
-    points += QPointF(196.38622691315896, 194.30278046741873);
-    points += QPointF(185.94813049770778, 196.9895807275079);
-    points += QPointF(139.55536916394507, 195.8595124134453);
-    points += QPointF(94.68200851242605, 182.9587775062589);
-    points += QPointF(53.04420235483193, 161.22643763678528);
-    points += QPointF(17.41948377984963, 131.4802352488134);
-    points += QPointF(3.037173945815, 113.17182142233789);
-    points += QPointF(-7.8903334763093635, 91.91076010344419);
-    points += QPointF(-13.507576311258223, 67.42815708759109);
-    points += QPointF(-11.452400232028667, 42.67167813028373);
+    points += QPointF(445.748031496063, 251.48446223243934);
+    points += QPointF(420.1672505436216, 265.34467354701);
+    points += QPointF(408.16868834563587, 270.74969811280204);
+    points += QPointF(395.75743565485675, 275.06821746196044);
+    points += QPointF(383.28015968092507, 278.216263983686);
+    points += QPointF(370.8288026520235, 280.2409452967658);
+    points += QPointF(358.4874104434599, 281.2043381226534);
+    points += QPointF(346.3281093878975, 281.1794055890767);
+    points += QPointF(334.4094715702431, 280.2452307190486);
+    points += QPointF(322.77695514341303, 278.48262025768446);
+    points += QPointF(311.46472096401544, 275.97070996938834);
+    points += QPointF(300.4980766475991, 272.78475431818316);
+    points += QPointF(289.8959627998986, 268.994968265893);
+    points += QPointF(279.67312801429796, 264.6661417252929);
+    points += QPointF(269.84184205634284, 259.8577269753623);
+    points += QPointF(260.4131332789275, 254.62414553625888);
+    points += QPointF(251.39760921382512, 249.0151257350064);
+    points += QPointF(242.80594716150756, 243.07593816151942);
+    points += QPointF(234.64914462550888, 236.84743207794344);
+    points += QPointF(226.93861367892654, 230.36578881474733);
+    points += QPointF(219.6862008839008, 223.6618981488572);
+    points += QPointF(212.90422632696564, 216.76022967199233);
+    points += QPointF(206.60567695694368, 209.67701009653408);
+    points += QPointF(200.8047886617048, 202.41742546763192);
+    points += QPointF(195.51846445950318, 194.97144814919497);
+    points += QPointF(195.49646472111115, 194.93594659378365);
+    points += QPointF(185.71068181674897, 196.88038239808796);
+    points += QPointF(174.06579870156523, 198.0108674081686);
+    points += QPointF(162.4698365016369, 198.12450807507133);
+    points += QPointF(150.93599464376967, 197.35134057907845);
+    points += QPointF(139.4731688630524, 195.78946993073865);
+    points += QPointF(128.09385198069478, 193.51339391764853);
+    points += QPointF(116.81695231109029, 190.58079085562875);
+    points += QPointF(105.66811291289228, 187.03735678012447);
+    points += QPointF(94.6789709925457, 182.91996300992662);
+    points += QPointF(83.88608373098256, 178.2585220934185);
+    points += QPointF(73.32986575781915, 173.07687844159756);
+    points += QPointF(63.05370660182625, 167.39293026852914);
+    points += QPointF(53.10337911388009, 161.21809122399117);
+    points += QPointF(43.52687054865665, 154.55612780781823);
+    points += QPointF(34.37485617471233, 147.40137397927876);
+    points += QPointF(25.702201154685437, 139.73635741878132);
+    points += QPointF(17.571137619050678, 131.52904674063026);
+    points += QPointF(10.057109595108484, 122.7304016692299);
+    points += QPointF(3.2585649313074336, 113.27395345986065);
+    points += QPointF(-2.688329688884947, 103.08109119247632);
+    points += QPointF(-7.591302782642628, 92.07847647311537);
+    points += QPointF(-11.187498579572614, 80.23547322967522);
+    points += QPointF(-13.151329717912063, 67.62324223181253);
+    points += QPointF(-13.149175120030888, 54.474729701833986);
+    points += QPointF(-10.94337542157982, 41.194055939258014);
+    points += QPointF(-6.654890183208465, 28.745230608885407);
     points += QPointF(6.735602739585184, 2.204598425196849);
 
     return points;
@@ -1653,40 +1732,91 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsCase3() const
     QVector<QPointF> points;
 
     points += QPointF(11.491153250328935, 2.204598425196849);
-    points += QPointF(446.1486580403833, 2.204598425196849);
-    points += QPointF(443.58722975094355, 245.07202661708763);
-    points += QPointF(425.1137484290017, 268.68251714626723);
-    points += QPointF(410.710702976016, 281.17394700785115);
-    points += QPointF(394.6305380089911, 289.87868829070504);
-    points += QPointF(377.68935972259976, 294.42039446773254);
-    points += QPointF(345.2891679003724, 291.71681887702744);
-    points += QPointF(318.8954558500656, 277.387541146342);
-    points += QPointF(299.836181304411, 255.59117266176213);
-    points += QPointF(288.9960506469964, 228.68278781028684);
-    points += QPointF(288.09978928853826, 198.89092343273913);
-    points += QPointF(295.52398476771754, 175.7944621402967);
-    points += QPointF(298.35692700564954, 155.95491384399136);
-    points += QPointF(296.64544203481944, 147.53499165718873);
-    points += QPointF(295.62311476307525, 146.6781151558174);
-    points += QPointF(289.83631178459234, 145.65886137089512);
-    points += QPointF(263.86302969143765, 151.02798077389028);
-    points += QPointF(248.0011124529875, 159.32004134517877);
-    points += QPointF(209.38086747344968, 181.82248571472272);
-    points += QPointF(187.81719911027162, 188.34500166877712);
-    points += QPointF(165.71167711395094, 187.9030433207368);
-    points += QPointF(146.5634417196521, 177.22168648881313);
-    points += QPointF(136.34913944009722, 161.0107028740396);
-    points += QPointF(132.35548185589735, 132.14155778793625);
-    points += QPointF(124.85769773414223, 138.3166750745855);
-    points += QPointF(106.38084062481717, 148.13624736643095);
-    points += QPointF(86.3477370523643, 153.01816260877774);
-    points += QPointF(66.26289964510504, 152.16787828189516);
-    points += QPointF(48.254978841826016, 146.22324827751663);
-    points += QPointF(21.027781980991552, 125.39244823236324);
-    points += QPointF(6.486477180841129, 105.14630485769516);
-    points += QPointF(-4.426684646901568, 80.5250619079355);
-    points += QPointF(-10.01311360817298, 55.62988319219602);
-    points += QPointF(-8.687212589418436, 33.403943526036805);
+    points += QPointF(445.748031496063, 2.204598425196849);
+    points += QPointF(445.748031496063, 239.25772323190495);
+    points += QPointF(437.3011718875349, 252.9620940028659);
+    points += QPointF(431.5210396453687, 261.04286502132345);
+    points += QPointF(425.0742362286929, 268.54423500057675);
+    points += QPointF(418.11166285006243, 275.22268157509825);
+    points += QPointF(410.66293904201643, 281.0200956238725);
+    points += QPointF(402.78657384181963, 285.87157614021027);
+    points += QPointF(394.5732042205309, 289.71737969963584);
+    points += QPointF(386.1419584708077, 292.51680859777775);
+    points += QPointF(377.62937764888807, 294.2596521460023);
+    points += QPointF(369.17363576502424, 294.9709765895621);
+    points += QPointF(360.89908762820056, 294.7076951308071);
+    points += QPointF(352.90578450956633, 293.54885121734077);
+    points += QPointF(345.2659401705694, 291.58363457828597);
+    points += QPointF(338.02638381419206, 288.9008829382743);
+    points += QPointF(331.214452254774, 285.58206377611566);
+    points += QPointF(324.8447893417784, 281.69791760615396);
+    points += QPointF(318.92540323684557, 277.307901893045);
+    points += QPointF(313.4622927999198, 272.4613294067597);
+    points += QPointF(308.4626029358523, 267.199302528306);
+    points += QPointF(303.93656720661477, 261.5568795640949);
+    points += QPointF(299.8985555961715, 255.5651950634023);
+    points += QPointF(296.3674859139379, 249.25344082283073);
+    points += QPointF(293.36675891047514, 242.65070430384247);
+    points += QPointF(290.9237823363554, 235.7876787648548);
+    points += QPointF(289.0690799250026, 228.6982245333719);
+    points += QPointF(287.8349531366277, 221.42069049439027);
+    points += QPointF(287.2536910795491, 213.9988201772971);
+    points += QPointF(287.3554164994589, 206.48200110960104);
+    points += QPointF(288.165803158891, 198.9246157503596);
+    points += QPointF(289.7040578703973, 191.38436170566055);
+    points += QPointF(291.98164916416846, 183.91963819443603);
+    points += QPointF(293.700387439861, 179.7469098237058);
+    points += QPointF(296.5884693392089, 171.49219190163677);
+    points += QPointF(297.59693481965496, 166.31235205234043);
+    points += QPointF(298.2857333094973, 160.53208953533525);
+    points += QPointF(298.43819035278193, 155.84335424804448);
+    points += QPointF(298.1940021729857, 152.25436961670644);
+    points += QPointF(297.7243212024687, 149.73346552056378);
+    points += QPointF(289.51401190033005, 145.54903057599236);
+    points += QPointF(285.1770288005626, 145.6959639947203);
+    points += QPointF(278.3617236899766, 146.6950293230864);
+    points += QPointF(271.14652259400714, 148.48714038237037);
+    points += QPointF(263.9194864200908, 150.92917578435245);
+    points += QPointF(257.2170705229372, 153.76755541765795);
+    points += QPointF(251.60582957396716, 156.6541701343772);
+    points += QPointF(247.78435692308207, 159.04593361720316);
+    points += QPointF(241.3885876220272, 164.12014968959915);
+    points += QPointF(236.47226924439926, 167.68896212834986);
+    points += QPointF(220.7012128062336, 176.43583903855628);
+    points += QPointF(209.5894888372958, 181.6299305429989);
+    points += QPointF(198.8701621522812, 185.51474135189684);
+    points += QPointF(188.2122212804039, 188.0080506184889);
+    points += QPointF(177.3148127107667, 188.81408257358973);
+    points += QPointF(166.19194469464537, 187.37324105698534);
+    points += QPointF(155.57420181410697, 183.17620217869953);
+    points += QPointF(146.72912660379956, 176.5077748886884);
+    points += QPointF(140.4165418057526, 168.5601760939351);
+    points += QPointF(136.398647544906, 160.4725908270882);
+    points += QPointF(134.00844184248987, 152.736031987575);
+    points += QPointF(132.67609691771358, 145.39573210082384);
+    points += QPointF(132.02477039749073, 138.2597894386109);
+    points += QPointF(131.93387537548404, 132.84913141002448);
+    points += QPointF(124.89904457045232, 138.11668139199287);
+    points += QPointF(115.8895831399309, 143.54689645077573);
+    points += QPointF(106.4111230253516, 147.88716086368487);
+    points += QPointF(96.50699490577813, 150.99747783054613);
+    points += QPointF(86.32454442321412, 152.7366302609282);
+    points += QPointF(76.11298204383012, 153.0205687205323);
+    points += QPointF(66.1751535607697, 151.8740677833447);
+    points += QPointF(56.79043276012441, 149.44132674047353);
+    points += QPointF(48.150859730789605, 145.94779600016403);
+    points += QPointF(40.340747704632996, 141.64039002708367);
+    points += QPointF(33.35598458760446, 136.7400113658245);
+    points += QPointF(27.139387101639755, 131.42053399597268);
+    points += QPointF(21.454249077112927, 125.64844566928473);
+    points += QPointF(14.297732218982075, 116.98023078208763);
+    points += QPointF(6.592092174102573, 105.03828991585031);
+    points += QPointF(0.43109819620648937, 92.75351406859683);
+    points += QPointF(-4.287700865002457, 80.50147704363812);
+    points += QPointF(-7.673598677574605, 68.33582707450634);
+    points += QPointF(-9.704701735666333, 56.0002075290815);
+    points += QPointF(-9.95133102840429, 42.85489720779573);
+    points += QPointF(-7.622895431362345, 31.027194419301413);
     points += QPointF(-3.18150493921823, 21.10903158131186);
     points += QPointF(11.491153250328935, 2.204598425196849);
 
@@ -2273,52 +2403,114 @@ void TST_VAbstractPiece::BrokenDetailEquidistant_data() const
     // We will test only one detail. The second require too accurate data that we cannot get from debuger.
     // The test check an open equdistant of correct detail.
     QVector<VSAPoint> points;// Input points.
-    points.append(VSAPoint(787.5835464566929, 1701.3138897637796));
-    points.append(VSAPoint(938.7646488188976, 1701.3138897637796));
-    points.append(VSAPoint(928.6149958683911, 1732.4440719866434));
-    points.append(VSAPoint(910.0209091217698, 1792.3369853889722));
-    points.append(VSAPoint(893.3643262819251, 1849.7845131987456));
-    points.append(VSAPoint(878.5244039283091, 1905.2261617043234));
-    points.append(VSAPoint(865.3802986403739, 1959.101437194065));
-    points.append(VSAPoint(863.9366982685195, 1965.6834024491068));
-    points.append(VSAPoint(852.8936778444679, 1919.6965437838999));
-    points.append(VSAPoint(837.0628180560684, 1860.2846653184251));
-    points.append(VSAPoint(819.0677656132684, 1798.6758641921479));
-    points.append(VSAPoint(798.7585839758027, 1734.54810216256));
-    points.append(VSAPoint(787.5835464566929, 1701.3138897637796));
 
     qreal width = 37.795275590551185; // seam allowance width
 
+    VSAPoint point = VSAPoint(787.5835464566929, 1701.3138897637796);
+    point.SetSAAfter(width);
+    point.SetSABefore(0);
+    points.append(point);
+
+    point = VSAPoint(863.1740976377953, 1701.3138897637796);
+    point.SetSAAfter(width);
+    point.SetSAAfter(width);
+    points.append(point);
+
+    points.append(VSAPoint(938.7646488188976, 1701.3138897637796));
+    points.append(VSAPoint(928.6149944255945, 1732.4440762118775));
+    points.append(VSAPoint(910.0209054382323, 1792.3369946802652));
+    points.append(VSAPoint(893.3643210561819, 1849.7845240486258));
+    points.append(VSAPoint(878.5243977752426, 1905.2261712206746));
+    points.append(VSAPoint(865.3802920912136, 1959.1014431001254));
+    points.append(VSAPoint(853.8111604998944, 2011.8498465906928));
+    points.append(VSAPoint(843.6961594970844, 2063.910888596092));
+    points.append(VSAPoint(834.9144455785826, 2115.7240760200366));
+    points.append(VSAPoint(827.3451752401882, 2167.7289157662426));
+    points.append(VSAPoint(820.8675049777007, 2220.364914738423));
+    points.append(VSAPoint(815.3605912869193, 2274.0715798402925));
+    points.append(VSAPoint(810.703590663643, 2329.2884179755656));
+    points.append(VSAPoint(806.7756596036716, 2386.454936047957));
+    points.append(VSAPoint(803.455954602804, 2446.0106409611817));
+    points.append(VSAPoint(800.6236321568394, 2508.395039618954));
+    points.append(VSAPoint(798.1578487615775, 2574.047638924988));
+    points.append(VSAPoint(797.0323653543306, 2608.4005039370077));
+    points.append(VSAPoint(929.3158299212598, 2608.4005039370077));
+    points.append(VSAPoint(927.9285659612306, 2548.9599884455793));
+    points.append(VSAPoint(925.157717598664, 2463.8329634071292));
+    points.append(VSAPoint(922.7222742526749, 2408.6782012856274));
+    points.append(VSAPoint(919.6220036804666, 2354.5469017384876));
+    points.append(VSAPoint(915.706969354324, 2301.1170261784787));
+    points.append(VSAPoint(910.8272347465313, 2248.066536018368));
+    points.append(VSAPoint(904.8328633293736, 2195.073392670922));
+    points.append(VSAPoint(897.5739185751353, 2141.8155575489095));
+    points.append(VSAPoint(888.9004639561011, 2087.9709920650976));
+    points.append(VSAPoint(878.6625629445558, 2033.2176576322527));
+    points.append(VSAPoint(866.7102790127839, 1977.233515663143));
+    points.append(VSAPoint(852.8936756330698, 1919.696527570536));
+    points.append(VSAPoint(837.0628162776984, 1860.284654767199));
+    points.append(VSAPoint(819.0677644189545, 1798.675858665899));
+    points.append(VSAPoint(798.7585835291225, 1734.548100679404));
+    points.append(VSAPoint(787.5835464566929, 1701.3138897637796));
+
+    point = VSAPoint(797.0323653543306, 2608.4005039370077);
+    point.SetSAAfter(0);
+    point.SetSABefore(width);
+    points.append(point);
+
     QVector<QPointF> ekvOrig;
-    ekvOrig.append(QPointF(774.8748468280837, 1663.5186141732283));
-    ekvOrig.append(QPointF(990.8407795072413, 1663.5186141732283));
-    ekvOrig.append(QPointF(964.6314912875667, 1743.9055911653147));
-    ekvOrig.append(QPointF(946.2221157804494, 1803.203536155223));
-    ekvOrig.append(QPointF(929.7733291125676, 1859.9343877726233));
-    ekvOrig.append(QPointF(915.1430746962241, 1914.5927211230298));
-    ekvOrig.append(QPointF(902.2033544443959, 1967.630259856634));
-    ekvOrig.append(QPointF(894.4064781634931, 2003.1794116713015));
-    ekvOrig.append(QPointF(834.213891302752, 2003.7742535883901));
-    ekvOrig.append(QPointF(816.2523103379473, 1928.9761772004185));
-    ekvOrig.append(QPointF(800.6574884611877, 1870.4501290629887));
-    ekvOrig.append(QPointF(782.9077417718742, 1809.6811695225983));
-    ekvOrig.append(QPointF(786.7126382487066, 1698.723835966227));
+    ekvOrig.append(QPointF(735.0001191244485, 1663.5186141732283));
+    ekvOrig.append(QPointF(990.8407796109454, 1663.5186141732283));
+    ekvOrig.append(QPointF(964.6314897747087, 1743.9055956070622));
+    ekvOrig.append(QPointF(946.222111945205, 1803.203545947388));
+    ekvOrig.append(QPointF(929.7733236875301, 1859.9343993344141));
+    ekvOrig.append(QPointF(915.1430683369846, 1914.5927314447797));
+    ekvOrig.append(QPointF(902.2033477151627, 1967.6302665424967));
+    ekvOrig.append(QPointF(890.8261161082305, 2019.5037195040304));
+    ekvOrig.append(QPointF(880.8841829577946, 2070.673996127427));
+    ekvOrig.append(QPointF(872.2520522462703, 2121.604624314014));
+    ekvOrig.append(QPointF(864.8064761358401, 2172.759620123457));
+    ekvOrig.append(QPointF(864.2562272534083, 2177.2308109121955));
+    ekvOrig.append(QPointF(860.1867773842832, 2147.3738416825267));
+    ekvOrig.append(QPointF(851.6617474319463, 2094.450692409028));
+    ekvOrig.append(QPointF(841.5996933370075, 2040.6378051462616));
+    ekvOrig.append(QPointF(829.8479530577714, 1985.5930036729653));
+    ekvOrig.append(QPointF(816.2523082919595, 1928.9761616385213));
+    ekvOrig.append(QPointF(800.6574868367429, 1870.4501190599349));
+    ekvOrig.append(QPointF(782.9077406929495, 1809.6811643713463));
+    ekvOrig.append(QPointF(762.8278965797896, 1746.2775544138444));
+    ekvOrig.append(QPointF(735.0001191244485, 1663.5186141732283));
 
     QTest::newRow("GAVAUDAN Laure.") << points << width << ekvOrig;
 
-    points.clear();
-    points.append(VSAPoint(97.33089106412862, -223.03306117556497));
-    points.append(VSAPoint(990.7494050554426, 2.819093995045));
-    points.append(VSAPoint(908.3966357321774, 379.5839357215547));
-    points.append(VSAPoint(-135.41154226686143, 697.6417881399819));
-
     width = 11.338582677165354;
 
+    points.clear();
+    point = VSAPoint(97.33089106412862, -223.03306117556497);
+    point.SetSAAfter(width);
+    point.SetSABefore(0);
+    points.append(point);
+
+    point = VSAPoint(990.7494050554426, 2.819093995045);
+    point.SetSAAfter(width);
+    point.SetSABefore(width);
+    points.append(point);
+
+    point = VSAPoint(908.3966357321774, 379.5839357215547);
+    point.SetSAAfter(width);
+    point.SetSABefore(width);
+    points.append(point);
+
+    point = VSAPoint(-135.41154226686143, 697.6417881399819);
+    point.SetSAAfter(0);
+    point.SetSABefore(width);
+    points.append(point);
+
     ekvOrig.clear();
-    ekvOrig.append(VSAPoint(100.10981413873267, -234.02583351343978));
-    ekvOrig.append(VSAPoint(1004.1704360325447, -5.483401649771952));
-    ekvOrig.append(VSAPoint(918.0553412376563, 388.4941212347381));
-    ekvOrig.append(VSAPoint(-138.65807550610091, 710.4843173601864));
+    ekvOrig.append(QPointF(100.10981413873267, -234.02583351343978));
+    ekvOrig.append(QPointF(1004.1704360325447, -5.483401649771952));
+    ekvOrig.append(QPointF(918.0553412376563, 388.4941212347381));
+    ekvOrig.append(QPointF(-138.65807550610091, 710.4843173601864));
+    ekvOrig.append(QPointF(100.10981413873267, -234.02583351343978));
 
     // See the file "collection/bugs/Issue_#604.val" (since 0.5.0)
     QTest::newRow("Issue #604.") << points << width << ekvOrig;
@@ -2603,75 +2795,75 @@ void TST_VAbstractPiece::Case5() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractPiece::InputPointsIssue298Case1() const
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsIssue298Case1() const
 {
-    QVector<QPointF> points;
+    QVector<VSAPoint> points;
 
-    points += QPointF(35, 39.9999);
-    points += QPointF(412.953, 39.9999);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(408.797, 405.589);
-    points += QPointF(390.909, 377.669);
-    points += QPointF(362.315, 330.86);
-    points += QPointF(323.075, 264.247);
-    points += QPointF(286.15, 201.448);
-    points += QPointF(262.477, 162.745);
-    points += QPointF(249.22, 142.455);
-    points += QPointF(241.092, 131.261);
-    points += QPointF(236.545, 125.75);
-    points += QPointF(232.808, 122.058);
-    points += QPointF(230.6, 120.629);
-    points += QPointF(229.393, 120.277);
-    points += QPointF(228.421, 120.456);
-    points += QPointF(227.69, 121.185);
-    points += QPointF(227.033, 123.272);
-    points += QPointF(227.112, 128.232);
-    points += QPointF(228.29, 135.699);
-    points += QPointF(230.625, 145.81);
-    points += QPointF(234.173, 158.703);
-    points += QPointF(241.73, 183.168);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(251.528, 212.406);
-    points += QPointF(255.482, 227.075);
-    points += QPointF(257.717, 239.591);
-    points += QPointF(258.279, 247.554);
-    points += QPointF(258.203, 252.278);
-    points += QPointF(257.756, 256.51);
-    points += QPointF(256.949, 260.264);
-    points += QPointF(255.795, 263.547);
-    points += QPointF(254.308, 266.372);
-    points += QPointF(252.501, 268.749);
-    points += QPointF(250.385, 270.688);
-    points += QPointF(247.974, 272.201);
-    points += QPointF(245.281, 273.296);
-    points += QPointF(242.319, 273.986);
-    points += QPointF(239.1, 274.28);
-    points += QPointF(233.846, 274.05);
-    points += QPointF(226.022, 272.393);
-    points += QPointF(217.402, 269.345);
-    points += QPointF(208.09, 264.991);
-    points += QPointF(198.186, 259.414);
-    points += QPointF(187.795, 252.7);
-    points += QPointF(177.019, 244.933);
-    points += QPointF(165.96, 236.197);
-    points += QPointF(154.721, 226.576);
-    points += QPointF(143.405, 216.157);
-    points += QPointF(132.113, 205.022);
-    points += QPointF(120.95, 193.257);
-    points += QPointF(110.017, 180.946);
-    points += QPointF(99.4167, 168.174);
-    points += QPointF(89.2522, 155.024);
-    points += QPointF(79.626, 141.582);
-    points += QPointF(70.6405, 127.933);
-    points += QPointF(62.3985, 114.16);
-    points += QPointF(55.0025, 100.348);
-    points += QPointF(48.5551, 86.5823);
-    points += QPointF(43.159, 72.9466);
-    points += QPointF(38.9167, 59.5258);
-    points += QPointF(35.9309, 46.4042);
-    points += QPointF(35, 39.9999);
+    points += VSAPoint(35, 39.9999);
+    points += VSAPoint(412.953, 39.9999);
+    points += VSAPoint(417.135, 417.929);
+    points += VSAPoint(417.135, 417.929);
+    points += VSAPoint(408.797, 405.589);
+    points += VSAPoint(390.909, 377.669);
+    points += VSAPoint(362.315, 330.86);
+    points += VSAPoint(323.075, 264.247);
+    points += VSAPoint(286.15, 201.448);
+    points += VSAPoint(262.477, 162.745);
+    points += VSAPoint(249.22, 142.455);
+    points += VSAPoint(241.092, 131.261);
+    points += VSAPoint(236.545, 125.75);
+    points += VSAPoint(232.808, 122.058);
+    points += VSAPoint(230.6, 120.629);
+    points += VSAPoint(229.393, 120.277);
+    points += VSAPoint(228.421, 120.456);
+    points += VSAPoint(227.69, 121.185);
+    points += VSAPoint(227.033, 123.272);
+    points += VSAPoint(227.112, 128.232);
+    points += VSAPoint(228.29, 135.699);
+    points += VSAPoint(230.625, 145.81);
+    points += VSAPoint(234.173, 158.703);
+    points += VSAPoint(241.73, 183.168);
+    points += VSAPoint(248.796, 204.144);
+    points += VSAPoint(248.796, 204.144);
+    points += VSAPoint(251.528, 212.406);
+    points += VSAPoint(255.482, 227.075);
+    points += VSAPoint(257.717, 239.591);
+    points += VSAPoint(258.279, 247.554);
+    points += VSAPoint(258.203, 252.278);
+    points += VSAPoint(257.756, 256.51);
+    points += VSAPoint(256.949, 260.264);
+    points += VSAPoint(255.795, 263.547);
+    points += VSAPoint(254.308, 266.372);
+    points += VSAPoint(252.501, 268.749);
+    points += VSAPoint(250.385, 270.688);
+    points += VSAPoint(247.974, 272.201);
+    points += VSAPoint(245.281, 273.296);
+    points += VSAPoint(242.319, 273.986);
+    points += VSAPoint(239.1, 274.28);
+    points += VSAPoint(233.846, 274.05);
+    points += VSAPoint(226.022, 272.393);
+    points += VSAPoint(217.402, 269.345);
+    points += VSAPoint(208.09, 264.991);
+    points += VSAPoint(198.186, 259.414);
+    points += VSAPoint(187.795, 252.7);
+    points += VSAPoint(177.019, 244.933);
+    points += VSAPoint(165.96, 236.197);
+    points += VSAPoint(154.721, 226.576);
+    points += VSAPoint(143.405, 216.157);
+    points += VSAPoint(132.113, 205.022);
+    points += VSAPoint(120.95, 193.257);
+    points += VSAPoint(110.017, 180.946);
+    points += VSAPoint(99.4167, 168.174);
+    points += VSAPoint(89.2522, 155.024);
+    points += VSAPoint(79.626, 141.582);
+    points += VSAPoint(70.6405, 127.933);
+    points += VSAPoint(62.3985, 114.16);
+    points += VSAPoint(55.0025, 100.348);
+    points += VSAPoint(48.5551, 86.5823);
+    points += VSAPoint(43.159, 72.9466);
+    points += VSAPoint(38.9167, 59.5258);
+    points += VSAPoint(35.9309, 46.4042);
+    points += VSAPoint(35, 39.9999);
 
     return points;
 }
@@ -2720,75 +2912,75 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue298Case1() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractPiece::InputPointsIssue298Case2() const
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsIssue298Case2() const
 {
-    QVector<QPointF> points;
+    QVector<VSAPoint> points;
 
-    points += QPointF(35, 39.9999);
-    points += QPointF(35, 39.9999);
-    points += QPointF(35.9309, 46.4042);
-    points += QPointF(38.9167, 59.5258);
-    points += QPointF(43.159, 72.9466);
-    points += QPointF(48.5551, 86.5823);
-    points += QPointF(55.0025, 100.348);
-    points += QPointF(62.3985, 114.16);
-    points += QPointF(70.6405, 127.933);
-    points += QPointF(79.626, 141.582);
-    points += QPointF(89.2522, 155.024);
-    points += QPointF(99.4167, 168.174);
-    points += QPointF(110.017, 180.946);
-    points += QPointF(120.95, 193.257);
-    points += QPointF(132.113, 205.022);
-    points += QPointF(143.405, 216.157);
-    points += QPointF(154.721, 226.576);
-    points += QPointF(165.96, 236.197);
-    points += QPointF(177.019, 244.933);
-    points += QPointF(187.795, 252.7);
-    points += QPointF(198.186, 259.414);
-    points += QPointF(208.09, 264.991);
-    points += QPointF(217.402, 269.345);
-    points += QPointF(226.022, 272.393);
-    points += QPointF(233.846, 274.05);
-    points += QPointF(239.1, 274.28);
-    points += QPointF(242.319, 273.986);
-    points += QPointF(245.281, 273.296);
-    points += QPointF(247.974, 272.201);
-    points += QPointF(250.385, 270.688);
-    points += QPointF(252.501, 268.749);
-    points += QPointF(254.308, 266.372);
-    points += QPointF(255.795, 263.547);
-    points += QPointF(256.949, 260.264);
-    points += QPointF(257.756, 256.51);
-    points += QPointF(258.203, 252.278);
-    points += QPointF(258.279, 247.554);
-    points += QPointF(257.717, 239.591);
-    points += QPointF(255.482, 227.075);
-    points += QPointF(251.528, 212.406);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(248.796, 204.144);
-    points += QPointF(241.73, 183.168);
-    points += QPointF(234.173, 158.703);
-    points += QPointF(230.625, 145.81);
-    points += QPointF(228.29, 135.699);
-    points += QPointF(227.112, 128.232);
-    points += QPointF(227.033, 123.272);
-    points += QPointF(227.69, 121.185);
-    points += QPointF(228.421, 120.456);
-    points += QPointF(229.393, 120.277);
-    points += QPointF(230.6, 120.629);
-    points += QPointF(232.808, 122.058);
-    points += QPointF(236.545, 125.75);
-    points += QPointF(241.092, 131.261);
-    points += QPointF(249.22, 142.455);
-    points += QPointF(262.477, 162.745);
-    points += QPointF(286.15, 201.448);
-    points += QPointF(323.075, 264.247);
-    points += QPointF(362.315, 330.86);
-    points += QPointF(390.909, 377.669);
-    points += QPointF(408.797, 405.589);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(417.135, 417.929);
-    points += QPointF(35, 417.953);
+    points += VSAPoint(35, 39.9999);
+    points += VSAPoint(35, 39.9999);
+    points += VSAPoint(35.9309, 46.4042);
+    points += VSAPoint(38.9167, 59.5258);
+    points += VSAPoint(43.159, 72.9466);
+    points += VSAPoint(48.5551, 86.5823);
+    points += VSAPoint(55.0025, 100.348);
+    points += VSAPoint(62.3985, 114.16);
+    points += VSAPoint(70.6405, 127.933);
+    points += VSAPoint(79.626, 141.582);
+    points += VSAPoint(89.2522, 155.024);
+    points += VSAPoint(99.4167, 168.174);
+    points += VSAPoint(110.017, 180.946);
+    points += VSAPoint(120.95, 193.257);
+    points += VSAPoint(132.113, 205.022);
+    points += VSAPoint(143.405, 216.157);
+    points += VSAPoint(154.721, 226.576);
+    points += VSAPoint(165.96, 236.197);
+    points += VSAPoint(177.019, 244.933);
+    points += VSAPoint(187.795, 252.7);
+    points += VSAPoint(198.186, 259.414);
+    points += VSAPoint(208.09, 264.991);
+    points += VSAPoint(217.402, 269.345);
+    points += VSAPoint(226.022, 272.393);
+    points += VSAPoint(233.846, 274.05);
+    points += VSAPoint(239.1, 274.28);
+    points += VSAPoint(242.319, 273.986);
+    points += VSAPoint(245.281, 273.296);
+    points += VSAPoint(247.974, 272.201);
+    points += VSAPoint(250.385, 270.688);
+    points += VSAPoint(252.501, 268.749);
+    points += VSAPoint(254.308, 266.372);
+    points += VSAPoint(255.795, 263.547);
+    points += VSAPoint(256.949, 260.264);
+    points += VSAPoint(257.756, 256.51);
+    points += VSAPoint(258.203, 252.278);
+    points += VSAPoint(258.279, 247.554);
+    points += VSAPoint(257.717, 239.591);
+    points += VSAPoint(255.482, 227.075);
+    points += VSAPoint(251.528, 212.406);
+    points += VSAPoint(248.796, 204.144);
+    points += VSAPoint(248.796, 204.144);
+    points += VSAPoint(241.73, 183.168);
+    points += VSAPoint(234.173, 158.703);
+    points += VSAPoint(230.625, 145.81);
+    points += VSAPoint(228.29, 135.699);
+    points += VSAPoint(227.112, 128.232);
+    points += VSAPoint(227.033, 123.272);
+    points += VSAPoint(227.69, 121.185);
+    points += VSAPoint(228.421, 120.456);
+    points += VSAPoint(229.393, 120.277);
+    points += VSAPoint(230.6, 120.629);
+    points += VSAPoint(232.808, 122.058);
+    points += VSAPoint(236.545, 125.75);
+    points += VSAPoint(241.092, 131.261);
+    points += VSAPoint(249.22, 142.455);
+    points += VSAPoint(262.477, 162.745);
+    points += VSAPoint(286.15, 201.448);
+    points += VSAPoint(323.075, 264.247);
+    points += VSAPoint(362.315, 330.86);
+    points += VSAPoint(390.909, 377.669);
+    points += VSAPoint(408.797, 405.589);
+    points += VSAPoint(417.135, 417.929);
+    points += VSAPoint(417.135, 417.929);
+    points += VSAPoint(35, 417.953);
 
     return points;
 }
@@ -2847,16 +3039,16 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue298Case2() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case1() const
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsIssue548Case1() const
 {
-    QVector<QPointF> points;
+    QVector<VSAPoint> points;
 
-    points += QPointF(236.97989607468364, 65.89325192030674);
-    points += QPointF(198.93409106041895, 172.04876297154925);
-    points += QPointF(260.32251114299453, 75.38027418944861);
-    points += QPointF(324.54110236213444, 101.48031496062993);
-    points += QPointF(29.858267716535437, 300.85039370078744);
-    points += QPointF(99.86433649395013, 10.166060970128015);
+    points += VSAPoint(236.97989607468364, 65.89325192030674);
+    points += VSAPoint(198.93409106041895, 172.04876297154925);
+    points += VSAPoint(260.32251114299453, 75.38027418944861);
+    points += VSAPoint(324.54110236213444, 101.48031496062993);
+    points += VSAPoint(29.858267716535437, 300.85039370078744);
+    points += VSAPoint(99.86433649395013, 10.166060970128015);
 
     return points;
 }
@@ -2879,15 +3071,15 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case1() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case2() const
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsIssue548Case2() const
 {
-    QVector<QPointF> points;
-    points << QPointF(99.86433649395013, 10.166060970128015);
-    points << QPointF(236.97989607468364, 65.89325192030674);
-    points << QPointF(198.93409106041895, 172.04876297154925);
-    points << QPointF(260.32251114299453, 75.38027418944861);
-    points << QPointF(324.54110236213444, 101.48031496062993);
-    points << QPointF(29.858267716535437, 300.85039370078744);
+    QVector<VSAPoint> points;
+    points << VSAPoint(99.86433649395013, 10.166060970128015);
+    points << VSAPoint(236.97989607468364, 65.89325192030674);
+    points << VSAPoint(198.93409106041895, 172.04876297154925);
+    points << VSAPoint(260.32251114299453, 75.38027418944861);
+    points << VSAPoint(324.54110236213444, 101.48031496062993);
+    points << VSAPoint(29.858267716535437, 300.85039370078744);
 
     return points;
 }
@@ -2897,10 +3089,8 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case2() const
 {
     QVector<QPointF> points;
     points << QPointF(73.40376616581447, -41.38574336196901);
-    points << QPointF(245.32830125796568, 28.488685370970344);
-    points << QPointF(245.32830125796573, 28.488685370970277);
     points << QPointF(404.3486874792147, 93.11854543221973);
-    points << QPointF(29.598648843228922, 346.6587450186291);
+    points << QPointF(29.59864884322894, 346.6587450186291);
     points << QPointF(-12.946885351826726, 317.1657644661815);
     points << QPointF(73.40376616581447, -41.38574336196901);
 
@@ -2908,16 +3098,16 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case2() const
 }
 
 //---------------------------------------------------------------------------------------------------------------------
-QVector<QPointF> TST_VAbstractPiece::InputPointsIssue548Case3() const
+QVector<VSAPoint> TST_VAbstractPiece::InputPointsIssue548Case3() const
 {
-    QVector<QPointF> points;
+    QVector<VSAPoint> points;
 
-    points += QPointF(99.86433649395013, 10.166060970128015);
-    points += QPointF(236.97989607468364, 65.89325192030674);
-    points += QPointF(198.93409106041895, 172.04876297154925);
-    points += QPointF(260.32251114299453, 75.38027418944861);
-    points += QPointF(324.54110236213444, 101.48031496062993);
-    points += QPointF(29.858267716535437, 300.85039370078744);
+    points += VSAPoint(99.86433649395013, 10.166060970128015);
+    points += VSAPoint(236.97989607468364, 65.89325192030674);
+    points += VSAPoint(198.93409106041895, 172.04876297154925);
+    points += VSAPoint(260.32251114299453, 75.38027418944861);
+    points += VSAPoint(324.54110236213444, 101.48031496062993);
+    points += VSAPoint(29.858267716535437, 300.85039370078744);
 
     return points;
 }
@@ -2928,11 +3118,6 @@ QVector<QPointF> TST_VAbstractPiece::OutputPointsIssue548Case3() const
     QVector<QPointF> points;
 
     points += QPointF(46.94319583767885, -92.9375476940661);
-#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
-    points += QPointF(234.2633962639462, -16.805935717278903);
-#else
-    points += QPointF(238.798634936, -14.9627013515);
-#endif
     points += QPointF(484.15627259629446, 84.75677590380938);
     points += QPointF(29.339029969922702, 392.46709633647066);
     points += QPointF(-55.75203842018885, 333.48113523157537);
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.h b/src/test/ValentinaTest/tst_vabstractpiece.h
index af965d1a4..d46f53f6b 100644
--- a/src/test/ValentinaTest/tst_vabstractpiece.h
+++ b/src/test/ValentinaTest/tst_vabstractpiece.h
@@ -72,19 +72,19 @@ private:
     void Case4() const;
     void Case5() const;
 
-    QVector<QPointF> InputPointsIssue298Case1() const;
+    QVector<VSAPoint> InputPointsIssue298Case1() const;
     QVector<QPointF> OutputPointsIssue298Case1() const;
 
-    QVector<QPointF> InputPointsIssue298Case2() const;
+    QVector<VSAPoint> InputPointsIssue298Case2() const;
     QVector<QPointF> OutputPointsIssue298Case2() const;
 
-    QVector<QPointF> InputPointsIssue548Case1() const;
+    QVector<VSAPoint> InputPointsIssue548Case1() const;
     QVector<QPointF> OutputPointsIssue548Case1() const;
 
-    QVector<QPointF> InputPointsIssue548Case2() const;
+    QVector<VSAPoint> InputPointsIssue548Case2() const;
     QVector<QPointF> OutputPointsIssue548Case2() const;
 
-    QVector<QPointF> InputPointsIssue548Case3() const;
+    QVector<VSAPoint> InputPointsIssue548Case3() const;
     QVector<QPointF> OutputPointsIssue548Case3() const;
 
     QVector<QPointF> InputPointsCase3a() const;
diff --git a/src/test/ValentinaTest/tst_vpiece.cpp b/src/test/ValentinaTest/tst_vpiece.cpp
index bdc4d83ef..3e0927e40 100644
--- a/src/test/ValentinaTest/tst_vpiece.cpp
+++ b/src/test/ValentinaTest/tst_vpiece.cpp
@@ -134,8 +134,9 @@ void TST_VPiece::ClearLoop()
     origPoints.append(QPointF(773.6735265709667, 824.7970381873482));
     origPoints.append(QPointF(780.6615727577812, 825.0343457026618));
     origPoints.append(QPointF(792.1099959092389, 824.8480813766124));
-    origPoints.append(QPointF(825.8245486890017, 822.4865245986581));
+    origPoints.append(QPointF(826.0032661558732, 877.1274330708662));
     origPoints.append(QPointF(828.6858753986579, 1697.305833468011));
+    origPoints.append(QPointF(42.46405659601934, 415.2845470563871));
 
     // Begin comparison
     Comparison(pointsEkv, origPoints);

From 7f1de2e0447cceabe60db1d301c0bb5d60b3144e Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 15:47:55 +0200
Subject: [PATCH 205/208] Refactoring. Made strings static.

--HG--
branch : feature
---
 src/libs/ifc/xml/vpatternconverter.cpp | 134 ++++++++++++-------------
 1 file changed, 67 insertions(+), 67 deletions(-)

diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index eda09eb61..ab86535da 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -66,73 +66,73 @@ const QString VPatternConverter::CurrentSchema    = QStringLiteral("://schema/pa
 
 // The list of all string we use for conversion
 // Better to use global variables because repeating QStringLiteral blows up code size
-const QString strUnit                      = QStringLiteral("unit");
-const QString strVersion                   = QStringLiteral("version");
-const QString strName                      = QStringLiteral("name");
-const QString strBase                      = QStringLiteral("base");
-const QString strFormula                   = QStringLiteral("formula");
-const QString strId                        = QStringLiteral("id");
-const QString strKGrowth                   = QStringLiteral("kgrowth");
-const QString strKSize                     = QStringLiteral("ksize");
-const QString strPoint                     = QStringLiteral("point");
-const QString strLength                    = QStringLiteral("length");
-const QString strAngle                     = QStringLiteral("angle");
-const QString strC1Radius                  = QStringLiteral("c1Radius");
-const QString strC2Radius                  = QStringLiteral("c2Radius");
-const QString strCRadius                   = QStringLiteral("cRadius");
-const QString strArc                       = QStringLiteral("arc");
-const QString strAngle1                    = QStringLiteral("angle1");
-const QString strAngle2                    = QStringLiteral("angle2");
-const QString strRadius                    = QStringLiteral("radius");
-const QString strPathPoint                 = QStringLiteral("pathPoint");
-const QString strKAsm1                     = QStringLiteral("kAsm1");
-const QString strKAsm2                     = QStringLiteral("kAsm2");
-const QString strPath                      = QStringLiteral("path");
-const QString strType                      = QStringLiteral("type");
-const QString strCutArc                    = QStringLiteral("cutArc");
-const QString strSpline                    = QStringLiteral("spline");
-const QString strSplinePath                = QStringLiteral("splinePath");
-const QString strCutSpline                 = QStringLiteral("cutSpline");
-const QString strCutSplinePath             = QStringLiteral("cutSplinePath");
-const QString strColor                     = QStringLiteral("color");
-const QString strMeasurements              = QStringLiteral("measurements");
-const QString strIncrement                 = QStringLiteral("increment");
-const QString strIncrements                = QStringLiteral("increments");
-const QString strModeling                  = QStringLiteral("modeling");
-const QString strTools                     = QStringLiteral("tools");
-const QString strIdTool                    = QStringLiteral("idTool");
-const QString strIdObject                  = QStringLiteral("idObject");
-const QString strChildren                  = QStringLiteral("children");
-const QString strChild                     = QStringLiteral("child");
-const QString strPointOfIntersectionCurves = QStringLiteral("pointOfIntersectionCurves");
-const QString strCurveIntersectAxis        = QStringLiteral("curveIntersectAxis");
-const QString strCurve                     = QStringLiteral("curve");
-const QString strCurve1                    = QStringLiteral("curve1");
-const QString strCurve2                    = QStringLiteral("curve2");
-const QString strModelingPath              = QStringLiteral("modelingPath");
-const QString strModelingSpline            = QStringLiteral("modelingSpline");
-const QString strPointFromArcAndTangent    = QStringLiteral("pointFromArcAndTangent");
-const QString strPointOfIntersectionArcs   = QStringLiteral("pointOfIntersectionArcs");
-const QString strFirstArc                  = QStringLiteral("firstArc");
-const QString strSecondArc                 = QStringLiteral("secondArc");
-const QString strDetail                    = QStringLiteral("detail");
-const QString strSupplement                = QStringLiteral("supplement");
-const QString strClosed                    = QStringLiteral("closed");
-const QString strWidth                     = QStringLiteral("width");
-const QString strNode                      = QStringLiteral("node");
-const QString strNodes                     = QStringLiteral("nodes");
-const QString strData                      = QStringLiteral("data");
-const QString strPatternInfo               = QStringLiteral("patternInfo");
-const QString strGrainline                 = QStringLiteral("grainline");
-const QString strReverse                   = QStringLiteral("reverse");
-const QString strMx                        = QStringLiteral("mx");
-const QString strMy                        = QStringLiteral("my");
-const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
-const QString strInLayout                  = QStringLiteral("inLayout");
-const QString strSeamAllowance             = QStringLiteral("seamAllowance");
-const QString strNodeType                  = QStringLiteral("nodeType");
-const QString strDet                       = QStringLiteral("det");
-const QString strTypeObject                = QStringLiteral("typeObject");
+static const QString strUnit                      = QStringLiteral("unit");
+static const QString strVersion                   = QStringLiteral("version");
+static const QString strName                      = QStringLiteral("name");
+static const QString strBase                      = QStringLiteral("base");
+static const QString strFormula                   = QStringLiteral("formula");
+static const QString strId                        = QStringLiteral("id");
+static const QString strKGrowth                   = QStringLiteral("kgrowth");
+static const QString strKSize                     = QStringLiteral("ksize");
+static const QString strPoint                     = QStringLiteral("point");
+static const QString strLength                    = QStringLiteral("length");
+static const QString strAngle                     = QStringLiteral("angle");
+static const QString strC1Radius                  = QStringLiteral("c1Radius");
+static const QString strC2Radius                  = QStringLiteral("c2Radius");
+static const QString strCRadius                   = QStringLiteral("cRadius");
+static const QString strArc                       = QStringLiteral("arc");
+static const QString strAngle1                    = QStringLiteral("angle1");
+static const QString strAngle2                    = QStringLiteral("angle2");
+static const QString strRadius                    = QStringLiteral("radius");
+static const QString strPathPoint                 = QStringLiteral("pathPoint");
+static const QString strKAsm1                     = QStringLiteral("kAsm1");
+static const QString strKAsm2                     = QStringLiteral("kAsm2");
+static const QString strPath                      = QStringLiteral("path");
+static const QString strType                      = QStringLiteral("type");
+static const QString strCutArc                    = QStringLiteral("cutArc");
+static const QString strSpline                    = QStringLiteral("spline");
+static const QString strSplinePath                = QStringLiteral("splinePath");
+static const QString strCutSpline                 = QStringLiteral("cutSpline");
+static const QString strCutSplinePath             = QStringLiteral("cutSplinePath");
+static const QString strColor                     = QStringLiteral("color");
+static const QString strMeasurements              = QStringLiteral("measurements");
+static const QString strIncrement                 = QStringLiteral("increment");
+static const QString strIncrements                = QStringLiteral("increments");
+static const QString strModeling                  = QStringLiteral("modeling");
+static const QString strTools                     = QStringLiteral("tools");
+static const QString strIdTool                    = QStringLiteral("idTool");
+static const QString strIdObject                  = QStringLiteral("idObject");
+static const QString strChildren                  = QStringLiteral("children");
+static const QString strChild                     = QStringLiteral("child");
+static const QString strPointOfIntersectionCurves = QStringLiteral("pointOfIntersectionCurves");
+static const QString strCurveIntersectAxis        = QStringLiteral("curveIntersectAxis");
+static const QString strCurve                     = QStringLiteral("curve");
+static const QString strCurve1                    = QStringLiteral("curve1");
+static const QString strCurve2                    = QStringLiteral("curve2");
+static const QString strModelingPath              = QStringLiteral("modelingPath");
+static const QString strModelingSpline            = QStringLiteral("modelingSpline");
+static const QString strPointFromArcAndTangent    = QStringLiteral("pointFromArcAndTangent");
+static const QString strPointOfIntersectionArcs   = QStringLiteral("pointOfIntersectionArcs");
+static const QString strFirstArc                  = QStringLiteral("firstArc");
+static const QString strSecondArc                 = QStringLiteral("secondArc");
+static const QString strDetail                    = QStringLiteral("detail");
+static const QString strSupplement                = QStringLiteral("supplement");
+static const QString strClosed                    = QStringLiteral("closed");
+static const QString strWidth                     = QStringLiteral("width");
+static const QString strNode                      = QStringLiteral("node");
+static const QString strNodes                     = QStringLiteral("nodes");
+static const QString strData                      = QStringLiteral("data");
+static const QString strPatternInfo               = QStringLiteral("patternInfo");
+static const QString strGrainline                 = QStringLiteral("grainline");
+static const QString strReverse                   = QStringLiteral("reverse");
+static const QString strMx                        = QStringLiteral("mx");
+static const QString strMy                        = QStringLiteral("my");
+static const QString strForbidFlipping            = QStringLiteral("forbidFlipping");
+static const QString strInLayout                  = QStringLiteral("inLayout");
+static const QString strSeamAllowance             = QStringLiteral("seamAllowance");
+static const QString strNodeType                  = QStringLiteral("nodeType");
+static const QString strDet                       = QStringLiteral("det");
+static const QString strTypeObject                = QStringLiteral("typeObject");
 
 //---------------------------------------------------------------------------------------------------------------------
 VPatternConverter::VPatternConverter(const QString &fileName)

From 9a51b165ac6bab3575b1e2f9edecdeea226a8086 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 16:12:36 +0200
Subject: [PATCH 206/208] Refactoring. Eliminate unneeded reverse points and
 two methods hidden in anonymous namespace.

--HG--
branch : feature
---
 src/libs/vpatterndb/vpiecepath.cpp | 110 +++++++++++++++--------------
 src/libs/vpatterndb/vpiecepath.h   |   4 --
 2 files changed, 58 insertions(+), 56 deletions(-)

diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp
index 91e6a8723..80c30906f 100644
--- a/src/libs/vpatterndb/vpiecepath.cpp
+++ b/src/libs/vpatterndb/vpiecepath.cpp
@@ -34,6 +34,47 @@
 
 #include <QPainterPath>
 
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+VSAPoint CurvePoint(VSAPoint candidate, const VContainer *data, const VPieceNode &node,
+                    const QVector<QPointF> &curvePoints)
+{
+    if (node.GetTypeTool() == Tool::NodePoint)
+    {
+        const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
+        if (VAbstractCurve::IsPointOnCurve(curvePoints, p))
+        {
+            candidate = VSAPoint(p);
+            candidate.SetSAAfter(node.GetSAAfter(data, *data->GetPatternUnit()));
+            candidate.SetSABefore(node.GetSABefore(data, *data->GetPatternUnit()));
+            candidate.SetAngleType(node.GetAngleType());
+        }
+    }
+    return candidate;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+ * @brief indexOfNode return index in list node using id object.
+ * @param list list nodes detail.
+ * @param id object (arc, point, spline, splinePath) id.
+ * @return index in list or -1 id can't find.
+ */
+int IndexOfNode(const QVector<VPieceNode> &list, quint32 id)
+{
+    for (int i = 0; i < list.size(); ++i)
+    {
+        if (list.at(i).GetId() == id)
+        {
+            return i;
+        }
+    }
+    qDebug()<<"Can't find node.";
+    return -1;
+}
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPiecePath::VPiecePath()
     : d(new VPiecePathData)
@@ -269,19 +310,21 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNo
 
     const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
 
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
+    const QVector<QPointF> points = curve->GetPoints();
+    if (points.isEmpty())
     {
-        points = VGObject::GetReversePoints(points);
+        return VSAPoint();
     }
 
-    VSAPoint begin = VSAPoint(points.first());
+    VSAPoint begin;
+    reverse ? begin = VSAPoint(points.last()) : begin = VSAPoint(points.first());
+
     if (nodes.size() > 1)
     {
         int index = 0;
         i == 0 ? index = nodes.size()-1 : index = i-1;
 
-        begin = CurvePoint(begin, data, nodes.at(index), curve);
+        begin = CurvePoint(begin, data, nodes.at(index), points);
     }
     return begin;
 }
@@ -296,19 +339,21 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode
 
     const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
 
-    QVector<QPointF> points = curve->GetPoints();
-    if (reverse)
+    const QVector<QPointF> points = curve->GetPoints();
+    if (points.isEmpty())
     {
-        points = VGObject::GetReversePoints(points);
+        return VSAPoint();
     }
 
-    VSAPoint end = VSAPoint(points.last());
+    VSAPoint end;
+    reverse ? end = VSAPoint(points.first()) : end = VSAPoint(points.last());
+
     if (nodes.size() > 2)
     {
         int index = 0;
         i == nodes.size() - 1 ? index = 0 : index = i+1;
 
-        end = CurvePoint(end, data, nodes.at(index), curve);
+        end = CurvePoint(end, data, nodes.at(index), points);
     }
     return end;
 }
@@ -416,7 +461,7 @@ bool VPiecePath::OnEdge(quint32 p1, quint32 p2) const
         qDebug()<<"Not enough points.";
         return false;
     }
-    int i = indexOfNode(list, p1);
+    int i = IndexOfNode(list, p1);
     int j1 = 0, j2 = 0;
 
     if (i == list.size() - 1)
@@ -462,8 +507,8 @@ int VPiecePath::Edge(quint32 p1, quint32 p2) const
     }
 
     const QVector<VPieceNode> list = ListNodePoint();
-    int i = indexOfNode(list, p1);
-    int j = indexOfNode(list, p2);
+    int i = IndexOfNode(list, p1);
+    int j = IndexOfNode(list, p2);
 
     int min = qMin(i, j);
 
@@ -750,42 +795,3 @@ QVector<VSAPoint> VPiecePath::CurveSeamAllowanceSegment(const VContainer *data,
 
     return pointsEkv;
 }
-
-//---------------------------------------------------------------------------------------------------------------------
-VSAPoint VPiecePath::CurvePoint(const VSAPoint &candidate, const VContainer *data, const VPieceNode &node,
-                                const QSharedPointer<VAbstractCurve> &curve)
-{
-    VSAPoint point = candidate;
-    if (node.GetTypeTool() == Tool::NodePoint)
-    {
-        const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
-        if (curve->IsPointOnCurve(p))
-        {
-            point = VSAPoint(p);
-            point.SetSAAfter(node.GetSAAfter(data, *data->GetPatternUnit()));
-            point.SetSABefore(node.GetSABefore(data, *data->GetPatternUnit()));
-            point.SetAngleType(node.GetAngleType());
-        }
-    }
-    return point;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief indexOfNode return index in list node using id object.
- * @param list list nodes detail.
- * @param id object (arc, point, spline, splinePath) id.
- * @return index in list or -1 id can't find.
- */
-int VPiecePath::indexOfNode(const QVector<VPieceNode> &list, quint32 id)
-{
-    for (int i = 0; i < list.size(); ++i)
-    {
-        if (list.at(i).GetId() == id)
-        {
-            return i;
-        }
-    }
-    qDebug()<<"Can't find node.";
-    return -1;
-}
diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h
index 9f80b1293..40852dd53 100644
--- a/src/libs/vpatterndb/vpiecepath.h
+++ b/src/libs/vpatterndb/vpiecepath.h
@@ -106,10 +106,6 @@ public:
 
 private:
     QSharedDataPointer<VPiecePathData> d;
-
-    static VSAPoint CurvePoint(const VSAPoint &candidate, const VContainer *data, const VPieceNode &node,
-                               const QSharedPointer<VAbstractCurve> &curve);
-    static int      indexOfNode(const QVector<VPieceNode> &list, quint32 id);
 };
 
 Q_DECLARE_TYPEINFO(VPiecePath, Q_MOVABLE_TYPE);

From a7987422ae3344d5653589f137da089f5634121d Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 17:04:53 +0200
Subject: [PATCH 207/208] Cppcheck warnings.

--HG--
branch : feature
---
 src/libs/vlayout/vgraphicsfillitem.h |  2 +-
 src/libs/vpatterndb/vpiecenode.cpp   | 63 +++++++++++++++-------------
 src/libs/vpatterndb/vpiecenode.h     |  2 -
 3 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/src/libs/vlayout/vgraphicsfillitem.h b/src/libs/vlayout/vgraphicsfillitem.h
index 3862d5d3f..564e36986 100644
--- a/src/libs/vlayout/vgraphicsfillitem.h
+++ b/src/libs/vlayout/vgraphicsfillitem.h
@@ -38,7 +38,7 @@ public:
     /**
      * @brief VGraphicsFillItem Constructor
      */
-    VGraphicsFillItem(QGraphicsItem *parent = nullptr);
+    explicit VGraphicsFillItem(QGraphicsItem *parent = nullptr);
     /**
      * @brief ~VGraphicsFillItem Destructor
      */
diff --git a/src/libs/vpatterndb/vpiecenode.cpp b/src/libs/vpatterndb/vpiecenode.cpp
index a03d7e476..2d74cd4a5 100644
--- a/src/libs/vpatterndb/vpiecenode.cpp
+++ b/src/libs/vpatterndb/vpiecenode.cpp
@@ -34,6 +34,39 @@
 #include <QDataStream>
 #include <QtNumeric>
 
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+qreal EvalFormula(const VContainer *data, QString formula)
+{
+    if (formula.isEmpty())
+    {
+        return -1;
+    }
+    else
+    {
+        try
+        {
+            // Replace line return character with spaces for calc if exist
+            formula.replace("\n", " ");
+            QScopedPointer<Calculator> cal(new Calculator());
+            const qreal result = cal->EvalFormula(data->PlainVariables(), formula);
+
+            if (qIsInf(result) || qIsNaN(result))
+            {
+                return -1;
+            }
+            return result;
+        }
+        catch (qmu::QmuParserError &e)
+        {
+            Q_UNUSED(e)
+            return -1;
+        }
+    }
+}
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 VPieceNode::VPieceNode()
     : d(new VPieceNodeData)
@@ -182,36 +215,6 @@ void VPieceNode::SetAngleType(PieceNodeAngle type)
     }
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-qreal VPieceNode::EvalFormula(const VContainer *data, QString formula) const
-{
-    if (formula.isEmpty())
-    {
-        return -1;
-    }
-    else
-    {
-        try
-        {
-            // Replace line return character with spaces for calc if exist
-            formula.replace("\n", " ");
-            QScopedPointer<Calculator> cal(new Calculator());
-            const qreal result = cal->EvalFormula(data->PlainVariables(), formula);
-
-            if (qIsInf(result) || qIsNaN(result))
-            {
-                return -1;
-            }
-            return result;
-        }
-        catch (qmu::QmuParserError &e)
-        {
-            Q_UNUSED(e)
-            return -1;
-        }
-    }
-}
-
 // Friend functions
 //---------------------------------------------------------------------------------------------------------------------
 QDataStream& operator<<(QDataStream& out, const VPieceNode& p)
diff --git a/src/libs/vpatterndb/vpiecenode.h b/src/libs/vpatterndb/vpiecenode.h
index 9114b6c33..c2e7c9b1c 100644
--- a/src/libs/vpatterndb/vpiecenode.h
+++ b/src/libs/vpatterndb/vpiecenode.h
@@ -76,8 +76,6 @@ public:
     void           SetAngleType(PieceNodeAngle type);
 private:
     QSharedDataPointer<VPieceNodeData> d;
-
-    qreal EvalFormula(const VContainer *data, QString formula) const;
 };
 
 Q_DECLARE_METATYPE(VPieceNode)

From 6cf3cce21517263c9fbda0d4e660c5c62dbe4109 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Wed, 25 Jan 2017 17:20:44 +0200
Subject: [PATCH 208/208] Updated changelog.

--HG--
branch : feature
---
 ChangeLog.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ChangeLog.txt b/ChangeLog.txt
index 0539717c8..6363689a1 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -50,6 +50,10 @@
 - [#589] Valentina lock up if not enough space for label.
 - [#606] Mac OS X. Can’t type in measurements due to digit count limitation.
 - [#612] Valentina crashes when network is disabled on Linux.
+- [#406] New feature: Seam allowance tool -> Preview.
+- [#88] New feature: Variable width seam allowances.
+- [#280] New tool: 'Hem' in Detail mode.
+- [#509] Improve feature: Support internal Paths in Detail tool.
 
 # Version 0.4.6
 - [#594] Broken export on Mac.