]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Add checking that object is used before the delete operation
authormpv <mikhail.ponikarov@opencascade.com>
Mon, 22 Sep 2014 07:50:29 +0000 (11:50 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Mon, 22 Sep 2014 07:50:29 +0000 (11:50 +0400)
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Document.h
src/SketchPlugin/SketchPlugin_Sketch.cpp

index 26f537d689aa677e3e9bc36bbcd0bd1b2a79d4ee..495bd04bc539c6ffdf1102dc2449e3e5102d1017 100644 (file)
@@ -12,6 +12,8 @@
 #include <Model_AttributeBoolean.h>
 #include <Model_AttributeString.h>
 #include <Model_Events.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
 
 #include <GeomData_Point.h>
 #include <GeomData_Point2D.h>
@@ -285,6 +287,7 @@ void Model_Data::erase()
     myLab.ForgetAllAttributes();
 }
 
+/// identifeir of the "must be updated" flag in the data tree
 Standard_GUID kMustBeUpdatedGUID("baede74c-31a6-4416-9c4d-e48ce65f2005");
 
 void Model_Data::mustBeUpdated(const bool theFlag)
@@ -299,3 +302,40 @@ bool Model_Data::mustBeUpdated()
 {
   return myLab.IsAttribute(kMustBeUpdatedGUID) == Standard_True;
 }
+
+bool Model_Data::referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature)
+{
+  // collect results of this feature first to check references quickly in the cycle
+  std::set<ObjectPtr> aFeatureObjs;
+  aFeatureObjs.insert(theFeature);
+  std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter =
+    theFeature->results().cbegin();
+  for(; aRIter != theFeature->results().cend(); aRIter++) {
+    if (*aRIter)
+      aFeatureObjs.insert(*aRIter);
+  }
+
+  std::map<std::string, boost::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter = 
+    myAttrs.begin();
+  for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
+    if (anAttrsIter->second->attributeType() == ModelAPI_AttributeRefAttr::type()) {
+      boost::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr = 
+        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttrsIter->second);
+      if (aRefAttr && aRefAttr->isObject()) { // check referenced object
+        if (aFeatureObjs.find(aRefAttr->object()) != aFeatureObjs.end())
+          return true;
+      } else { // check object of referenced attribute
+        boost::shared_ptr<ModelAPI_Attribute> anAttr = aRefAttr->attr();
+        if (anAttr && aFeatureObjs.find(anAttr->owner()) != aFeatureObjs.end())
+          return true;
+      }
+    } else if (anAttrsIter->second->attributeType() == ModelAPI_AttributeReference::type()) {
+      boost::shared_ptr<ModelAPI_AttributeReference> aRef = 
+        boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttrsIter->second);
+      if (aFeatureObjs.find(aRef->value()) != aFeatureObjs.end()) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
index 136e4504ffa310ce30d8179a2c45237c00358f52..559fc12adb3444e4a31cc8e30fca673dd00db810 100644 (file)
@@ -136,6 +136,9 @@ class Model_Data : public ModelAPI_Data
 
   /// Returns true if feature must be updated (re-executed) on rebuild
   MODEL_EXPORT virtual bool mustBeUpdated();
+
+  /// Returns true if this data attributes are referenced to the given feature or its results
+  MODEL_EXPORT virtual bool referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature);
 };
 
 #endif
index 57241b6b52926fa23f5ac029c2628988f5a2ee36..08eb944fa8e84d39e687cce872e802912fc61f2a 100644 (file)
@@ -459,16 +459,27 @@ static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, co
   return aResult;
 }
 
-void Model_Document::removeFeature(FeaturePtr theFeature)
-{
-  // check the feature: it must have no depended objects on it
-  std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
-  for(; aResIter != theFeature->results().cend(); aResIter++) {
-    if (myConcealedResults.find(*aResIter) != myConcealedResults.end()) {
-      Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
-      return;
+void Model_Document::removeFeature(FeaturePtr theFeature, const bool theCheck)
+{
+  if (theCheck) {
+    // check the feature: it must have no depended objects on it
+    std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+    for(; aResIter != theFeature->results().cend(); aResIter++) {
+      if (myConcealedResults.find(*aResIter) != myConcealedResults.end()) {
+        Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+        return;
+      }
+    }
+    NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myObjs);
+    for(; anObjIter.More(); anObjIter.Next()) {
+      DataPtr aData = anObjIter.Value()->data();
+      if (aData->referencesTo(theFeature)) {
+        Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+        return;
+      }
     }
   }
+
   boost::shared_ptr<Model_Data> aData = boost::static_pointer_cast<Model_Data>(theFeature->data());
   TDF_Label aFeatureLabel = aData->label().Father();
   if (myObjs.IsBound(aFeatureLabel))
@@ -745,9 +756,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated)
     if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
         && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
       FeaturePtr aFeature = aFIter.Value();
-      TDF_Label aLab = aFIter.Key();
-      aFIter.Next();
-      myObjs.UnBind(aLab);
       // event: model is updated
       //if (aFeature->isInHistory()) {
         ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
@@ -767,6 +775,10 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated)
       // redisplay also removed feature (used for sketch and AISObject)
       ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
       aFeature->erase();
+      // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
+      TDF_Label aLab = aFIter.Key();
+      aFIter.Next();
+      myObjs.UnBind(aLab);
     } else
       aFIter.Next();
   }
index 38625983c593ff4787c6120136c249d4ae7eeb71..6f813bd231da45a6b72917c1b7cb508605c3259f 100644 (file)
@@ -77,7 +77,8 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID);
 
   //! Removes the feature from the document (with result)
-  MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
+  //! \param theCheck if it is false, do not check the references
+  MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature, const bool theCheck = true);
 
   //! Returns the existing feature by the label
   //! \param theLabel base label of the feature
index e82a4c44ab1a5f438e4814ee51595f27e789078f..1265a51bd2a08738bfa1c14a1559d9d18c585873 100644 (file)
@@ -20,6 +20,7 @@ class ModelAPI_AttributeBoolean;
 class ModelAPI_AttributeString;
 class ModelAPI_Document;
 class ModelAPI_Attribute;
+class ModelAPI_Feature;
 class GeomAPI_Shape;
 
 /**\class ModelAPI_Data
@@ -98,6 +99,9 @@ class MODELAPI_EXPORT ModelAPI_Data
   /// Returns true if feature must be updated (re-executed) on rebuild
   virtual bool mustBeUpdated() = 0;
 
+  /// Returns true if this data attributes are referenced to the given feature or its results
+  virtual bool referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature) = 0;
+
  protected:
   /// Objects are created for features automatically
   ModelAPI_Data()
index 6e432ae020b935d6c8227fbd8064db4b75c23500..1a5aee9bf535aabecb2c7eff61386a4923343555 100644 (file)
@@ -41,11 +41,11 @@ public:
   virtual boost::shared_ptr<ModelAPI_Feature> addFeature(std::string theID) = 0;
 
   //! Removes the feature from the document
-  virtual void removeFeature(boost::shared_ptr<ModelAPI_Feature> theFeature) = 0;
+  virtual void removeFeature(
+    boost::shared_ptr<ModelAPI_Feature> theFeature, const bool theCheck = true) = 0;
 
   ///! Adds a new sub-document by the identifier, or returns existing one if it is already exist
-  virtual boost::shared_ptr<ModelAPI_Document>
-    subDocument(std::string theDocID) = 0;
+  virtual boost::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID) = 0;
 
   ///! Returns the id of the document
   virtual const std::string& id() const = 0;
index 256ba9d5e5057573512dfde8770fe3bb6569fac1..1bc1b469cce3187af65006bbb02a5aa1cbbf868e 100644 (file)
@@ -176,8 +176,10 @@ void SketchPlugin_Sketch::erase()
   std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
   for (; anIt != aFeatures.end(); anIt++) {
     FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
-    if (aFeature)
-      document()->removeFeature(aFeature);
+    if (aFeature) {
+       // subs are referenced from sketch, but must be removed for sure, so not checkings
+      document()->removeFeature(aFeature, false);
+    }
   }
   SketchPlugin_Feature::erase();
 }