From 372df4661a3f9a3ea7e28446230e53ce6e88d5b1 Mon Sep 17 00:00:00 2001
From: Roman Telezhynskyi <kroluku@gmail.com>
Date: Sat, 16 Feb 2019 11:57:47 +0200
Subject: [PATCH] Fix reference counting for modeling objects.

--HG--
branch : develop
---
 src/app/valentina/xml/vpattern.cpp            | 44 +++++++++++++++++++
 .../toolsinglepoint/vtoolbasepoint.cpp        | 12 -----
 .../toolsinglepoint/vtoolbasepoint.h          |  1 -
 src/libs/vtools/tools/drawTools/vdrawtool.h   |  2 +-
 .../tools/nodeDetails/vtoolpiecepath.cpp      |  1 -
 src/libs/vtools/tools/vabstracttool.cpp       |  2 +-
 src/libs/vtools/tools/vdatatool.cpp           |  2 +-
 src/libs/vtools/tools/vtoolseamallowance.cpp  |  2 +-
 src/libs/vtools/tools/vtooluniondetails.cpp   |  1 -
 9 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp
index a35d5dfc1..99f43d8b8 100644
--- a/src/app/valentina/xml/vpattern.cpp
+++ b/src/app/valentina/xml/vpattern.cpp
@@ -1820,6 +1820,18 @@ void VPattern::ParsePinPoint(const QDomElement &domElement, const Document &pars
 
         ToolsCommonAttributes(domElement, initData.id);
         initData.pointId = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
+
+        try
+        {
+            initData.data->GeometricObject<VPointF>(initData.pointId);
+        }
+        catch (const VExceptionBadId &)
+        { // Possible case. Parent was deleted, but the node object is still here.
+            qDebug() << "Broken relation. Parent was deleted, but the place label object is still here. Place label "
+                        "id =" << initData.id << ".";
+            return;// Just ignore
+        }
+
         initData.idTool = GetParametrUInt(domElement, VAbstractNode::AttrIdTool, NULL_ID_STR);
         VToolPin::Create(initData);
     }
@@ -1846,6 +1858,18 @@ void VPattern::ParsePlaceLabel(QDomElement &domElement, const Document &parse)
 
         ToolsCommonAttributes(domElement, initData.id);
         initData.centerPoint = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
+
+        try
+        {
+            initData.data->GeometricObject<VPointF>(initData.centerPoint);
+        }
+        catch (const VExceptionBadId &)
+        { // Possible case. Parent was deleted, but the node object is still here.
+            qDebug() << "Broken relation. Parent was deleted, but the place label object is still here. Place label "
+                        "id =" << initData.id << ".";
+            return;// Just ignore
+        }
+
         initData.idTool = GetParametrUInt(domElement, VAbstractNode::AttrIdTool, NULL_ID_STR);
 
         initData.width = GetParametrString(domElement, AttrWidth, QStringLiteral("1.0"));
@@ -3787,6 +3811,26 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
         if (not element.isNull())
         {
             initData.path = ParsePathNodes(element);
+
+            try
+            {
+                for (int i = 0; i < initData.path.CountNodes(); ++i)
+                {
+                    initData.data->GetGObject(initData.path.at(i).GetId());
+                }
+            }
+            catch (const VExceptionBadId &)
+            { // Possible case. Parent was deleted, but the node object is still here.
+                qDebug() << "Broken relation. Parent was deleted, but the piece path object is still here. Piece "
+                            "path id =" << initData.id << ".";
+                return;// Just ignore
+            }
+        }
+        else
+        {
+            VExceptionObjectError excep(tr("Error creating or updating a piece path"), domElement);
+            excep.AddMoreInformation(tr("Piece path doesn't contain nodes"));
+            throw excep;
         }
 
         const QString defType = QString().setNum(static_cast<int>(PiecePathType::CustomSeamAllowance));
diff --git a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp
index 02cae6eb5..44a2b6e9f 100644
--- a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp
+++ b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.cpp
@@ -226,18 +226,6 @@ QVariant VToolBasePoint::itemChange(QGraphicsItem::GraphicsItemChange change, co
     return VToolSinglePoint::itemChange(change, value);
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-/**
- * @brief decrementReferens decrement referens parents objects.
- */
-void VToolBasePoint::decrementReferens()
-{
-    if (_referens > 1)
-    {
-        --_referens;
-    }
-}
-
 //---------------------------------------------------------------------------------------------------------------------
 QPointF VToolBasePoint::GetBasePointPos() const
 {
diff --git a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.h b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.h
index 016f44b93..870406cb3 100644
--- a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.h
+++ b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/vtoolbasepoint.h
@@ -74,7 +74,6 @@ public:
     virtual int  type() const override {return Type;}
     enum { Type = UserType + static_cast<int>(Tool::BasePoint)};
     virtual void ShowVisualization(bool show) override;
-    virtual void decrementReferens() override;
 
     QPointF GetBasePointPos() const;
     void    SetBasePointPos(const QPointF &pos);
diff --git a/src/libs/vtools/tools/drawTools/vdrawtool.h b/src/libs/vtools/tools/drawTools/vdrawtool.h
index 7be7bca28..0e9711b8b 100644
--- a/src/libs/vtools/tools/drawTools/vdrawtool.h
+++ b/src/libs/vtools/tools/drawTools/vdrawtool.h
@@ -227,7 +227,7 @@ void VDrawTool::ContextMenu(QGraphicsSceneContextMenuEvent *event, quint32 itemI
     {
         if (ref == Referens::Follow)
         {
-            if (_referens > 1)
+            if (_referens > 0)
             {
                 qCDebug(vTool, "Remove disabled. Tool has childern.");
                 actionRemove->setEnabled(false);
diff --git a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
index cc2b77cd3..e117e3c4c 100644
--- a/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
+++ b/src/libs/vtools/tools/nodeDetails/vtoolpiecepath.cpp
@@ -294,7 +294,6 @@ VToolPiecePath::VToolPiecePath(const VToolPiecePathInitData &initData, QObject *
       QGraphicsPathItem(parent),
       m_pieceId(initData.idObject)
 {
-    IncrementNodes(VAbstractTool::data.GetPiecePath(initData.id));
     RefreshGeometry();
     ToolCreation(initData.typeCreation);
 }
diff --git a/src/libs/vtools/tools/vabstracttool.cpp b/src/libs/vtools/tools/vabstracttool.cpp
index 98a19d9c2..0fa15a6be 100644
--- a/src/libs/vtools/tools/vabstracttool.cpp
+++ b/src/libs/vtools/tools/vabstracttool.cpp
@@ -211,7 +211,7 @@ qreal VAbstractTool::CheckFormula(const quint32 &toolId, QString &formula, VCont
 void VAbstractTool::DeleteToolWithConfirm(bool ask)
 {
     qCDebug(vTool, "Deleting abstract tool.");
-    if (_referens <= 1)
+    if (_referens == 0)
     {
         qCDebug(vTool, "No children.");
         emit qApp->getSceneView()->itemClicked(nullptr);
diff --git a/src/libs/vtools/tools/vdatatool.cpp b/src/libs/vtools/tools/vdatatool.cpp
index d71dff04a..860eda4cd 100644
--- a/src/libs/vtools/tools/vdatatool.cpp
+++ b/src/libs/vtools/tools/vdatatool.cpp
@@ -39,7 +39,7 @@ Q_LOGGING_CATEGORY(vTool, "v.tool")
  * @param parent parent object
  */
 VDataTool::VDataTool(VContainer *data, QObject *parent)
-    : QObject(parent), data(*data), _referens(1)
+    : QObject(parent), data(*data), _referens(0)
 {
     SCASSERT(data != nullptr)
 }
diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp
index f70d14659..4e09c6466 100644
--- a/src/libs/vtools/tools/vtoolseamallowance.cpp
+++ b/src/libs/vtools/tools/vtoolseamallowance.cpp
@@ -1124,7 +1124,7 @@ void VToolSeamAllowance::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
     forceFlippingOption->setChecked(detail.IsForceFlipping());
 
     QAction *actionRemove = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Delete"));
-    _referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
+    actionRemove->setDisabled(_referens > 0);
 
     QAction *selectedAction = menu.exec(event->screenPos());
     if (selectedAction == actionOption)
diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp
index 261a2cfc4..62474f573 100644
--- a/src/libs/vtools/tools/vtooluniondetails.cpp
+++ b/src/libs/vtools/tools/vtooluniondetails.cpp
@@ -1667,7 +1667,6 @@ VToolUnionDetails::VToolUnionDetails(const VToolUnionDetailsInitData &initData,
       indexD2(initData.indexD2),
       version(initData.version)
 {
-    _referens = 0;
     ToolCreation(initData.typeCreation);
 }