Salome HOME
Fix for the issue #2753 : error when dump/load script
[modules/shaper.git] / src / Model / Model_Objects.cpp
index 4c44977c41b3d8f083148b17bb27b4a59bd204a7..352c2e60c82b78bf34f98d7c07713a0341cc7006 100644 (file)
@@ -41,7 +41,6 @@
 #include <TDF_ChildIDIterator.hxx>
 #include <TDataStd_ReferenceArray.hxx>
 #include <TDataStd_HLabelArray1.hxx>
-#include <TDataStd_Name.hxx>
 #include <TDF_Reference.hxx>
 #include <TDF_ChildIDIterator.hxx>
 #include <TDF_LabelMapHasher.hxx>
@@ -310,7 +309,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->isSub(theFeature)) {
+      if (aComposite.get() && aComposite->data()->isValid() && aComposite->isSub(theFeature)) {
         aComposite->removeFeature(theFeature);
       }
     }
@@ -364,7 +363,7 @@ void Model_Objects::eraseAllFeatures()
   }
   kCreator->sendDeleted(myDoc, ModelAPI_Feature::group());
   myFeatures.Clear(); // just remove features without modification of DS
-  updateHistory(ModelAPI_Feature::group());
+  myHistory.clear();
 }
 
 void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis)
@@ -378,6 +377,9 @@ void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis)
   if (theAfterThis.get())
     anAfterLab = std::dynamic_pointer_cast<Model_Data>(theAfterThis->data())->label().Father();
 
+  // check whether some folder refers to the moved feature by start or end: if yes, remove from it
+  removeFromFolder(std::list<FeaturePtr>(1, theMoved));
+
   Handle(TDataStd_HLabelArray1) aNewArray =
     new TDataStd_HLabelArray1(aRefs->Lower(), aRefs->Upper());
   int aPassedMovedFrom = 0; // the prev feature location is found and passed
@@ -589,7 +591,8 @@ ObjectPtr Model_Objects::object(TDF_Label theLabel)
         const std::list<ResultPtr>& aResults = aFeature->results();
         std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
         for(; aRIter != aResults.cend(); aRIter++) {
-          std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
+          std::shared_ptr<Model_Data> aResData =
+            std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
           if (aResData->label().Father().IsEqual(aSubLab.ChangeValue())) {
             aCurrentResult = *aRIter;
             break;
@@ -624,15 +627,17 @@ std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
   createHistory(theGroupID);
   if (theGroupID == ModelAPI_Feature::group()) { // searching among features (in history or not)
     std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
-    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
-    for(; anObjIter != allObjs.end(); anObjIter++) {
+    // from the end to find the latest result with such name
+    std::list<std::shared_ptr<ModelAPI_Feature> >::reverse_iterator anObjIter = allObjs.rbegin();
+    for(; anObjIter != allObjs.rend(); anObjIter++) {
       if ((*anObjIter)->data()->name() == theName)
         return *anObjIter;
     }
   } else { // searching among results (concealed or not)
     std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
-    std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
-    for(; anObjIter != allObjs.end(); anObjIter++) {
+    // from the end to find the latest result with such name
+    std::list<std::shared_ptr<ModelAPI_Feature> >::reverse_iterator anObjIter = allObjs.rbegin();
+    for(; anObjIter != allObjs.rend(); anObjIter++) {
       std::list<ResultPtr> allRes;
       ModelAPI_Tools::allResults(*anObjIter, allRes);
       for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
@@ -1181,24 +1186,28 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData,
                                   std::string& theParentName) const
 {
   ResultBodyPtr aBodyRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theFeatureData->owner());
-  if (aBodyRes && std::dynamic_pointer_cast<Model_Data>(theFeatureData)->label().Depth() < 7) {
+  if (aBodyRes) {
     // only for top-results (works for the cases when results are not yet added to the feature)
     FeaturePtr anOwner = ModelAPI_Feature::feature(theResult);
 
     // names of sub-solids in CompSolid should be default (for example,
     // result of boolean operation 'Boolean_1' is a CompSolid which is renamed to 'MyBOOL',
     // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1', 'Boolean_1_2' etc.)
-    std::ostringstream aDefaultName;
-    aDefaultName << anOwner->name();
-    // compute default name of CompSolid (name of feature + index of CompSolid's result)
-    int aBodyResultIndex = 0;
-    const std::list<ResultPtr>& aResults = anOwner->results();
-    std::list<ResultPtr>::const_iterator anIt = aResults.begin();
-    for(; anIt != aResults.end(); ++anIt, ++aBodyResultIndex)
-      if(aBodyRes == *anIt)
-        break;
-    aDefaultName << "_" << (aBodyResultIndex + 1);
-    theParentName = aDefaultName.str();
+    if (std::dynamic_pointer_cast<Model_Data>(aBodyRes->data())->label().Depth() == 6) {
+      std::ostringstream aDefaultName;
+      // compute default name of CompSolid (name of feature + index of CompSolid's result)
+      int aBodyResultIndex = 0;
+      const std::list<ResultPtr>& aResults = anOwner->results();
+      std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+      for (; anIt != aResults.end(); ++anIt, ++aBodyResultIndex)
+        if (aBodyRes == *anIt)
+          break;
+      aDefaultName << anOwner->name();
+      aDefaultName << "_" << (aBodyResultIndex + 1);
+      theParentName = aDefaultName.str();
+    } else { // just name of the parent result if it is deeper than just a sub-result
+      theParentName = aBodyRes->data()->name();
+    }
     return false;
   }
 
@@ -1788,7 +1797,7 @@ std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
     const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
-  if (aData.get()) {
+  if (aData.get() && aData->isValid()) {
     TDF_Label aFeatureLab = aData->label().Father().Father().Father();
     FeaturePtr aFeature = feature(aFeatureLab);
     while(!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result
@@ -1832,8 +1841,6 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
     }
   }
 
-  // for not persistent is will be done by parametric updater automatically
-  //if (!theFeature->isPersistentResult()) return;
   // check the existing results and remove them if there is nothing on the label
   std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
   while(aResIter != theFeature->results().cend()) {
@@ -1867,13 +1874,20 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
         if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
           aNewBody = createBody(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
-          std::shared_ptr<ModelAPI_ResultPart> aNewP = createPart(theFeature->data(), aResIndex);
-          theFeature->setResult(aNewP, aResIndex);
-          if (!aNewP->partDoc().get())
-            // create the part result: it is better to restore the previous result if it is possible
-            theFeature->execute();
+          if (aResIndex <= theFeature->results().size()) { // to avoid crash if previous execute
+            // for index = 0 erases result
+            std::shared_ptr<ModelAPI_ResultPart> aNewP = createPart(theFeature->data(), aResIndex);
+            theFeature->setResult(aNewP, aResIndex);
+            if (!aNewP->partDoc().get())
+              // create the part result: it is better to restore the previous result if possible
+              theFeature->execute();
+          }
         } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
-          theFeature->execute(); // construction shapes are needed for sketch solver
+          ResultConstructionPtr aConstr = createConstruction(theFeature->data(), aResIndex);
+          if (!aConstr->updateShape())
+            theFeature->execute(); // not stored shape in the data structure, execute to have it
+          else
+            theFeature->setResult(aConstr, aResIndex); // result is ready without execution
         } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
           aNewBody = createGroup(theFeature->data(), aResIndex);
         } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) {
@@ -1890,6 +1904,22 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set<FeaturePtr>& t
       }
     }
   }
+  if (aResSize > 0) { // check there exist a body that must be updated
+    std::list<ResultPtr>::const_iterator aRes = theFeature->results().cbegin();
+    for (; aResSize && aRes != theFeature->results().cend(); aRes++, aResSize++) {
+      if ((*aRes)->data()->isValid()) {
+        if ((*aRes)->groupName() == ModelAPI_ResultBody::group()) {
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRes);
+          aBody->updateSubs(aBody->shape(), false);
+        } else if ((*aRes)->groupName() == ModelAPI_ResultConstruction::group()) {
+          // update the cashed myShape presented in construction
+          ResultConstructionPtr aConstr =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+          aConstr->updateShape();
+        }
+      }
+    }
+  }
 }
 
 ResultPtr Model_Objects::findByName(const std::string theName)
@@ -1968,11 +1998,12 @@ FeaturePtr Model_Objects::lastFeature()
 {
   Handle(TDataStd_ReferenceArray) aRefs;
   if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
-    FeaturePtr aLast = feature(aRefs->Value(aRefs->Upper()));
+    // comment this because of #2674 - features are removed from array on deactivation of Part
+    /*FeaturePtr aLast = feature(aRefs->Value(aRefs->Upper()));
     if (!aLast.get() && aRefs->Length() != 0) { // erase the invalid feature from the array
       RemoveFromRefArray(featuresLabel(), aRefs->Value(aRefs->Upper()));
       return lastFeature(); // try once again, after the last was removed
-    }
+    }*/
     return feature(aRefs->Value(aRefs->Upper()));
   }
   return FeaturePtr(); // no features at all