]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Fixes for crashes and bad behavior on delete of features and Parts. For now delete...
authormpv <mpv@opencascade.com>
Mon, 11 Apr 2016 13:08:54 +0000 (16:08 +0300)
committermpv <mpv@opencascade.com>
Mon, 11 Apr 2016 13:08:54 +0000 (16:08 +0300)
17 files changed:
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h
src/GeomAPI/GeomAPI_PlanarEdges.cpp
src/GeomAPI/GeomAPI_PlanarEdges.h
src/GeomValidators/GeomValidators_ZeroOffset.cpp
src/Model/Model_AttributeReference.cpp
src/Model/Model_Data.cpp
src/Model/Model_Document.cpp
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_Session.cpp
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_CompositeFeature.cpp
src/ModelAPI/ModelAPI_CompositeFeature.h
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchPlugin/SketchPlugin_Sketch.h

index b8bd1ee23397beff8c0285659dac7140c3cbf29e..5e7c13d43b14d6b22555231d2e65e0b87f055c40 100644 (file)
@@ -104,19 +104,6 @@ void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feat
   reference(SKETCH_ID())->setValue(ObjectPtr());
 }
 
-//=================================================================================================
-void FeaturesPlugin_CompositeSketch::erase()
-{
-  if(data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
-    FeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_Feature>(reference(SKETCH_ID())->value());
-    if(aSketch.get() && aSketch->data()->isValid()) {
-      document()->removeFeature(aSketch);
-    }
-  }
-
-  ModelAPI_CompositeFeature::erase();
-}
-
 //=================================================================================================
 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
                                                    const bool theIsMakeShells)
index f83fe924be9bee115137f3cb47fefa5f5dbb82ec..21479418cfb61404446ae00de44042751f71a26e 100644 (file)
@@ -52,9 +52,6 @@ public:
   /// structures of the owner (the remove from the document will be done outside just after).
   FEATURESPLUGIN_EXPORT virtual void removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
 
-  /// Removes also all sub-sketch.
-  FEATURESPLUGIN_EXPORT virtual void erase();
-
 protected:
   enum InitFlags {
     InitSketchLauncher   = 1 << 0,
index e87ce4d893facc4393d2d4e0badcebcab7d02d9b..e49d39e6d58b8add07b4318d6024e33d367b61ec 100644 (file)
@@ -40,7 +40,6 @@ void GeomAPI_PlanarEdges::addEdge(std::shared_ptr<GeomAPI_Shape> theEdge)
 std::list<std::shared_ptr<GeomAPI_Shape> > GeomAPI_PlanarEdges::getEdges()
 {
   TopoDS_Shape& aShape = const_cast<TopoDS_Shape&>(impl<TopoDS_Shape>());
-  //BRepTools_WireExplorer aWireExp(TopoDS::Wire(aShape));
   TopExp_Explorer aWireExp(aShape, TopAbs_EDGE);
   std::list<std::shared_ptr<GeomAPI_Shape> > aResult;
   for (; aWireExp.More(); aWireExp.Next()) {
@@ -101,4 +100,24 @@ void GeomAPI_PlanarEdges::setPlane(const std::shared_ptr<GeomAPI_Pnt>& theOrigin
                                    const std::shared_ptr<GeomAPI_Dir>& theNorm)
 {
   myPlane = std::shared_ptr<GeomAPI_Ax3>(new GeomAPI_Ax3(theOrigin, theDirX, theNorm));
-}
\ No newline at end of file
+}
+
+bool GeomAPI_PlanarEdges::isEqual(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+  if (!theShape.get())
+    return false;
+  TopoDS_Shape& aMyShape = const_cast<TopoDS_Shape&>(impl<TopoDS_Shape>());
+  TopoDS_Shape aTheShape = theShape->impl<TopoDS_Shape>();
+  TopExp_Explorer aMyExp(aMyShape, TopAbs_EDGE);
+  TopExp_Explorer aTheExp(aTheShape, TopAbs_EDGE);
+  for (; aMyExp.More() && aTheExp.More(); aMyExp.Next(), aTheExp.Next()) {
+    // check that edge by edge all geometrically matches
+    std::shared_ptr<GeomAPI_Edge> aMyEdge(new GeomAPI_Edge);
+    aMyEdge->setImpl<TopoDS_Shape>(new TopoDS_Shape(aMyExp.Current()));
+    std::shared_ptr<GeomAPI_Edge> aTheEdge(new GeomAPI_Edge);
+    aTheEdge->setImpl<TopoDS_Shape>(new TopoDS_Shape(aTheExp.Current()));
+    if (!aMyEdge->isEqual(aTheEdge))
+      return false;
+  }
+  return !(aMyExp.More() || aTheExp.More());
+}
index 5628f40e89844516c1cc3d8fc19c338c5a8cd418..15fb093f01b4dd26682fc26e91919ebc23208796 100644 (file)
@@ -65,6 +65,10 @@ class GeomAPI_PlanarEdges : public GeomAPI_Shape
                                const std::shared_ptr<GeomAPI_Dir>& theDirX,
                                const std::shared_ptr<GeomAPI_Dir>& theNorm);
 
+  /// Returns whether the shapes are equal
+  GEOMAPI_EXPORT 
+  virtual bool isEqual(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
 private:
 
   std::shared_ptr<GeomAPI_Ax3> myPlane;
index 1ba9664d992f2a58501d8cf8bb0d41056daa0e62..f898a2297b219ba1f5b5066b754a95cfdabec6c6 100644 (file)
@@ -140,9 +140,17 @@ bool GeomValidators_ZeroOffset::isValid(const std::shared_ptr<ModelAPI_Feature>&
     isPlanesCoincident = true;
   } else if(aFromShape.get() && aToShape.get()) {
     std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aFromShape));
+    if (aFromFace->isNull()) {
+      theError = "From face selection is invalid.";
+      return false;
+    }
     std::shared_ptr<GeomAPI_Pln>  aFromPln = aFromFace->getPlane();
 
     std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aToShape));
+    if (aToFace->isNull()) {
+      theError = "To face selection is invalid.";
+      return false;
+    }
     std::shared_ptr<GeomAPI_Pln>  aToPln = aToFace->getPlane();
 
     if(aFromPln.get()) {
@@ -152,8 +160,16 @@ bool GeomValidators_ZeroOffset::isValid(const std::shared_ptr<ModelAPI_Feature>&
     std::shared_ptr<GeomAPI_Face> aFace;
     if(aFromShape.get()) {
       aFace.reset(new GeomAPI_Face(aFromShape));
+      if (aFace->isNull()) {
+        theError = "From face selection is invalid.";
+        return false;
+      }
     } else {
       aFace.reset(new GeomAPI_Face(aToShape));
+      if (aFace->isNull()) {
+        theError = "To face selection is invalid.";
+        return false;
+      }
     }
     std::shared_ptr<GeomAPI_Pln> aPln = aFace->getPlane();
     if(aPln.get()) {
index 40ad13ad987acd868549bf29403c4a22167f5fc1..d63b4e3737cc2812d7b53c04aa72480471a2fa66 100644 (file)
@@ -126,8 +126,4 @@ void Model_AttributeReference::setObject(const std::shared_ptr<ModelAPI_Object>&
 }
 
 Model_AttributeReference::~Model_AttributeReference()
-{
-  std::shared_ptr<Model_Document> aDoc =
-    std::dynamic_pointer_cast<Model_Document>(owner()->document());
-  TDF_Label aLab = myRef->Get();
-}
+{}
index e9d808ade039cee5c7f934664bdfa7817b73b81e..c907ea63fc9b628d55cee9e920ccf9e8240be6fd 100644 (file)
@@ -302,8 +302,24 @@ void Model_Data::blockSendAttributeUpdated(const bool theBlock)
 
 void Model_Data::erase()
 {
-  if (!myLab.IsNull())
+  if (!myLab.IsNull()) {
+    // remove in order to clear back references in other objects
+    std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+    referencesToObjects(aRefs);
+    std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator anAttrIter = aRefs.begin();
+    for(; anAttrIter != aRefs.end(); anAttrIter++) {
+      std::list<ObjectPtr>::iterator aReferenced = anAttrIter->second.begin();
+      for(; aReferenced != anAttrIter->second.end(); aReferenced++) {
+        if (aReferenced->get() && (*aReferenced)->data()->isValid()) {
+          std::shared_ptr<Model_Data> aData = 
+            std::dynamic_pointer_cast<Model_Data>((*aReferenced)->data());
+          aData->removeBackReference(myAttrs[anAttrIter->first]);
+        }
+      }
+    }
+    myAttrs.clear();
     myLab.ForgetAllAttributes();
+  }
 }
 
 // indexes in the state array
index 09469b85b193fad9c22f712243d6d6d4719b6e5d..2c4bb4bd8068ba34c7749dae169269171483ef20 100755 (executable)
@@ -621,7 +621,7 @@ void Model_Document::abortOperation()
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->abortOperation();
   // references may be changed because they are set in attributes on the fly
-  myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+  myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
 }
 
 bool Model_Document::isOperation() const
@@ -687,7 +687,7 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
   }
   // after undo of all sub-documents to avoid updates on not-modified data (issue 370)
   if (theSynchronize) {
-    myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+    myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
     // update the current features status
     setCurrentFeature(currentFeature(false), false);
   }
@@ -734,7 +734,7 @@ void Model_Document::redo()
     subDoc(*aSubIter)->redo();
 
   // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
-  myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+  myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
   // update the current features status
   setCurrentFeature(currentFeature(false), false);
 }
index 6a4752d09e805252de006f190ec421e514e9ef28..11365789dc8b98dd6cad5a020905b69b4bd552d6 100644 (file)
@@ -54,7 +54,7 @@ void Model_Objects::setOwner(DocumentPtr theDoc)
   myDoc = theDoc;
   // update all fields and recreate features and result objects if needed
   TDF_LabelList aNoUpdated;
-  synchronizeFeatures(aNoUpdated, true, true);
+  synchronizeFeatures(aNoUpdated, true, true, true);
   myHistory.clear();
 }
 
@@ -240,7 +240,7 @@ void Model_Objects::removeFeature(FeaturePtr theFeature)
     for(; aRefIter != aRefs.end(); aRefIter++) {
       std::shared_ptr<ModelAPI_CompositeFeature> aComposite = 
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
-      if (aComposite.get() && aComposite->data()->isValid()) {
+      if (aComposite.get()) {
         aComposite->removeFeature(theFeature);
       }
     }
@@ -606,7 +606,8 @@ std::shared_ptr<ModelAPI_Feature> Model_Objects::featureById(const int theId)
 }
 
 void Model_Objects::synchronizeFeatures(
-  const TDF_LabelList& theUpdated, const bool theUpdateReferences, const bool theFlush)
+  const TDF_LabelList& theUpdated, const bool theUpdateReferences, 
+  const bool theOpen, const bool theFlush)
 {
   Model_Document* anOwner = std::dynamic_pointer_cast<Model_Document>(myDoc).get();
   if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize
@@ -728,7 +729,8 @@ void Model_Objects::synchronizeFeatures(
     myHistory.clear();
   }
 
-  anOwner->executeFeatures() = false;
+  if (theOpen)
+    anOwner->executeFeatures() = false;
   aLoop->activateFlushes(isActive);
 
   if (theFlush) {
@@ -740,7 +742,8 @@ void Model_Objects::synchronizeFeatures(
     aLoop->flush(aRedispEvent);
     aLoop->flush(aToHideEvent);
   }
-  anOwner->executeFeatures() = true;
+  if (theOpen)
+    anOwner->executeFeatures() = true;
 }
 
 /// synchronises back references for the given object basing on the collected data
index 740a3d54250c758b248f352e96a6021ea12dda80..517311b1edd765c0ae73ccfda572204cab7bbf41 100644 (file)
@@ -144,9 +144,10 @@ class Model_Objects
   //! Synchronizes myFeatures list with the updated document
   //! \param theUpdated list of labels that are marked as modified, so featrues must be also
   //! \param theUpdateReferences causes the update of back-references
+  //! \param theOpen - on open nothing must be reexecuted, except not persistent results
   //! \param theFlush makes flush all events in the end of all modifications of this method
   void synchronizeFeatures(const TDF_LabelList& theUpdated, const bool theUpdateReferences,
-    const bool theFlush);
+    const bool theOpen, const bool theFlush);
   //! Synchronizes the BackReferences list in Data of Features and Results
   void synchronizeBackRefs();
 
index e336d1652d3f7d2166cc095b231232cd09ece395..4525cbf4a85c9f64a64616f04c5e4e14f339d471 100644 (file)
@@ -263,7 +263,7 @@ void Model_Session::setActiveDocument(
         bool aWasChecked = myCheckTransactions;
         setCheckTransactions(false);
         TDF_LabelList anEmptyUpdated;
-        aDoc->objects()->synchronizeFeatures(anEmptyUpdated, true, true);
+        aDoc->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true);
         if (aWasChecked)
             setCheckTransactions(true);
       }
@@ -326,7 +326,7 @@ std::shared_ptr<ModelAPI_Document> Model_Session::copy(
   TDF_CopyTool::Copy(aDS, aRT);
 
   TDF_LabelList anEmptyUpdated;
-  aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true);
+  aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true);
   return aNew;
 }
 
index d88c1fec3d55430ffec2f27d3ec52cfa2c54c29d..bb7b681638d2dce66427b00a3e3ae8071e12a009 100644 (file)
@@ -59,9 +59,16 @@ Model_Update::Model_Update()
   myIsProcessed = false;
 }
 
-void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
+bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
+
   if (!theFeature->data()->isValid())
-    return; // delete an extrusion created on the sketch
+    return false; // delete an extrusion created on the sketch
+
+  if (theFeature->isPersistentResult()) {
+    if (!std::dynamic_pointer_cast<Model_Document>((theFeature)->document())->executeFeatures())
+      return false;
+  }
+
   if (!theFeature->isPreviewNeeded() && !myIsFinish) {
     myProcessOnFinish.insert(theFeature);
 #ifdef DEB_UPDATE
@@ -73,7 +80,7 @@ void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
       static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
       aFactory->validate(theFeature); // need to be validated to update the "Apply" state if not previewed
     }
-    return;
+    return true;
   }
   if (myModified.find(theFeature) != myModified.end()) {
     if (theReason.get()) {
@@ -82,7 +89,7 @@ void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
 #endif
       myModified[theFeature].insert(theReason);
     }
-    return; // already is marked as modified, so, nothing to do, it will be processed
+    return true;
   }
   // do not add the disabled, but possibly the sub-elements are not disabled
   bool aIsDisabled = theFeature->isDisabled();
@@ -103,7 +110,7 @@ void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
     if (theFeature->data()->execState() == ModelAPI_StateDone)
       theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
     else 
-      return; // do not need iteration deeply if it is already marked as modified or so
+      return true; // do not need iteration deeply if it is already marked as modified or so
 #ifdef DEB_UPDATE
     std::cout<<"*** Set modified state "<<theFeature->name()<<std::endl;
 #endif
@@ -139,7 +146,7 @@ void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
     if (aPart.get())
       addModified(aPart, theFeature);
   }
-  return;
+  return true;
 }
 
 void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
@@ -186,14 +193,10 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
         myIsParamUpdated = true;
       }
       // on undo/redo, abort do not update persisten features
-      bool anUpdateOnlyNotPersistent = 
-        !std::dynamic_pointer_cast<Model_Document>((*anObjIter)->document())->executeFeatures();
       FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
       if (anUpdated.get()) {
-        if (!anUpdateOnlyNotPersistent || !anUpdated->isPersistentResult()) {
-          addModified(anUpdated, FeaturePtr());
+        if (addModified(anUpdated, FeaturePtr()))
           aSomeModified = true;
-        }
       } else { // process the updated result as update of features that refers to this result
         const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = (*anObjIter)->data()->refsToMe();
         std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
@@ -201,9 +204,9 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
           if (!(*aRefIter)->owner()->data()->isValid())
             continue;
           FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
-          if (anUpdated.get() && (!anUpdateOnlyNotPersistent || !anUpdated->isPersistentResult())) {
-            addModified(anUpdated, FeaturePtr());
-            aSomeModified = true;
+          if (anUpdated.get()) {
+            if (addModified(anUpdated, FeaturePtr()))
+              aSomeModified = true;
           }
         }
       }
@@ -294,6 +297,11 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
     return false;
   }
 
+  if (theFeature->isPersistentResult()) {
+    if (!std::dynamic_pointer_cast<Model_Document>((theFeature)->document())->executeFeatures())
+      return false;
+  }
+
   // check this feature is not yet checked or processed
   bool aIsModified = myModified.find(theFeature) != myModified.end();
   if (!aIsModified && myIsFinish) { // get info about the modification for features without preview
@@ -399,42 +407,26 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
   // this checking must be after the composite feature sub-elements processing:
   // composite feature status may depend on it's subelements
   if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument) {
+  #ifdef DEB_UPDATE
+    std::cout<<"Invalid args "<<theFeature->name()<<std::endl;
+  #endif
     theFeature->eraseResults();
     redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
     return true; // so, feature is modified (results are erased)
   }
 
-  // On abort, undo or redo execute is not needed: results in document are updated automatically
-  // But redisplay is needed: results are updated, must be also updated in the viewer.
-  if (!std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures()) {
-    if (!theFeature->isPersistentResult()) { // not persistent must be re-executed on abort, etc.
-      ModelAPI_ExecState aState = theFeature->data()->execState();
-      if (aFactory->validate(theFeature)) {
-        executeFeature(theFeature);
-      } else {
-        theFeature->eraseResults();
-        redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
-      }
-    } else {
-      redisplayWithResults(theFeature, ModelAPI_StateNothing);
-      if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { // it is done (in the tree)
-        theFeature->data()->execState(ModelAPI_StateDone);
-      }
+  // execute feature if it must be updated
+  ModelAPI_ExecState aState = theFeature->data()->execState();
+  if (aFactory->validate(theFeature)) {
+    if (!isPostponedMain) {
+      executeFeature(theFeature);
     }
   } else {
-    // execute feature if it must be updated
-    ModelAPI_ExecState aState = theFeature->data()->execState();
-    if (aFactory->validate(theFeature)) {
-      if (!isPostponedMain) {
-        executeFeature(theFeature);
-      }
-    } else {
-      #ifdef DEB_UPDATE
-        std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
-      #endif
-      theFeature->eraseResults();
-      redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
-    }
+    #ifdef DEB_UPDATE
+      std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
+    #endif
+    theFeature->eraseResults();
+    redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
   }
   return true;
 }
@@ -660,6 +652,7 @@ void Model_Update::executeFeature(FeaturePtr theFeature)
 
 void Model_Update::updateStability(void* theSender)
 {
+  static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
   if (theSender) {
     bool added = false; // object may be was crated
     ModelAPI_Object* aSender = static_cast<ModelAPI_Object*>(theSender);
@@ -676,6 +669,8 @@ void Model_Update::updateStability(void* theSender)
           aSender->data()->referencesToObjects(aRefs);
           std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefIt = aRefs.begin();
           for(; aRefIt != aRefs.end(); aRefIt++) {
+            if (!aFactory->isConcealed(aFeatureSender->getKind(), aRefIt->first))
+              continue; // take into account only concealed references (do not remove the sketch constraint and the edge on constraint edit)
             std::list<ObjectPtr>& aRefFeaturesList = aRefIt->second;
             std::list<ObjectPtr>::iterator aReferenced = aRefFeaturesList.begin();
             for(; aReferenced != aRefFeaturesList.end(); aReferenced++) {
index 060b5c9d965cb36a18b4cf9f06db23053e44989e..106b48cbcd366180f0075325dda3a213246f610d 100644 (file)
@@ -52,7 +52,8 @@ protected:
   /// Appends the new modified feature to the myModified, clears myProcessed if needed
   /// Returns true if some feature really was marked as modified
   /// theReason is the object that causes modification of this feature
-  void addModified(
+  /// returns true if something reallsy was added to the modified and must be processed
+  bool addModified(
     std::shared_ptr<ModelAPI_Feature> theFeature, std::shared_ptr<ModelAPI_Feature> theReason);
 
   /// Recoursively checks and updates features if needed (calls the execute method)
index 7913a8bde50d9e534dc7fd0ff19c982d782288be..34066ecd23c61a970d8ac23d4491ed89c5548427 100644 (file)
@@ -16,3 +16,16 @@ void ModelAPI_CompositeFeature::exchangeIDs(
 {
   // by default nothing is in the implementation
 }
+
+void ModelAPI_CompositeFeature::erase()
+{
+  // erase all sub-features
+  for(int a = numberOfSubs(); a > 0; a--) {
+    FeaturePtr aFeature = subFeature(a - 1);
+    if (aFeature.get()) {
+      // subs are referenced from sketch, but must be removed for sure, so not checkings
+      aFeature->document()->removeFeature(aFeature);
+    }
+  }
+  ModelAPI_Feature::erase();
+}
index bc31a21eb80cc57f014b44c3e9478cf2843aaf4d..ab58f092f4610f8f23f5f38c03ceae308f79a896 100644 (file)
@@ -43,6 +43,9 @@ public:
   /// Exchanges IDs of two given features: needed for more correct naming in some cases (issue 769)
   MODELAPI_EXPORT virtual void exchangeIDs(std::shared_ptr<ModelAPI_Feature> theFeature1,
     std::shared_ptr<ModelAPI_Feature> theFeature2);
+
+  /// in addition removes all subs
+  MODELAPI_EXPORT virtual void erase();
 };
 
 //! Pointer on the composite feature object
index 0e2b9acd367eb776c13ed5cf18654e5bfb671b5b..354666bc956fd698908f3a5c1b2fa8c65c782580 100644 (file)
@@ -206,22 +206,6 @@ bool SketchPlugin_Sketch::isSub(ObjectPtr theObject) const
 }
 
 
-void SketchPlugin_Sketch::erase()
-{
-  std::shared_ptr<ModelAPI_AttributeRefList> aRefList = std::dynamic_pointer_cast<
-      ModelAPI_AttributeRefList>(data()->attribute(SketchPlugin_Sketch::FEATURES_ID()));
-  std::list<ObjectPtr> aFeatures = aRefList->list();
-  std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
-  for (; anIt != aFeatures.end(); anIt++) {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
-    if (aFeature) {
-      // subs are referenced from sketch, but must be removed for sure, so not checkings
-      document()->removeFeature(aFeature);
-    }
-  }
-  ModelAPI_CompositeFeature::erase();
-}
-
 void SketchPlugin_Sketch::attributeChanged(const std::string& theID) {
   if (theID == SketchPlugin_SketchEntity::EXTERNAL_ID()) {
     std::shared_ptr<GeomAPI_Shape> aSelection = 
index d97ea573dc1dcc30c1821c1d85802b2f390f87fc..d541415f3e9021fdf1eb408a711c35ac8a2d453e 100644 (file)
@@ -169,9 +169,6 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_ICu
   }
 
 
-  /// removes also all sub-sketch elements
-  SKETCHPLUGIN_EXPORT virtual void erase();
-
   /// appends a feature to the sketch sub-elements container
   SKETCHPLUGIN_EXPORT virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID);