Salome HOME
Fix for the issue #1156
[modules/shaper.git] / src / Model / Model_Update.cpp
index e9cec6c469ba0aef85e533073863aa2e27c411c2..9d655c03c64a57db054c18350b13bd99554b50fc 100644 (file)
@@ -172,7 +172,8 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     // place where results are cleared)
     myIsParamUpdated = false;
     myUpdated.clear();
-    myModification = 0;
+    // do not erase it since there may be modification increment on start of operation
+    //myModification = 0;
     myWaitForFinish.clear();
   }
 }
@@ -240,6 +241,8 @@ void Model_Update::processOperation(const bool theTotalUpdate, const bool theFin
       isAutomaticChanged = true;
       myIsAutomatic = true;
     }
+    // modifications inside of the iteration will be different from modification that comes outside
+    myModification++;
     // init iteration from the root document
     iterateUpdate(CompositeFeaturePtr());
 
@@ -398,9 +401,11 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex
 {
   // make updated and redisplay all results
   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
-  std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-  for (; aRIter != aResults.cend(); aRIter++) {
+
+  std::list<ResultPtr> allResults;
+  ModelAPI_Tools::allResults(theFeature, allResults);
+  std::list<ResultPtr>::iterator aRIter = allResults.begin();
+  for (; aRIter != allResults.cend(); aRIter++) {
     std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
     if (!aRes->isDisabled()) {// update state only for enabled results (Placement Result Part may make the original Part Result as invalid)
       aRes->data()->execState(theState);
@@ -411,27 +416,11 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex
       aRes->data()->setUpdateID(theFeature->data()->updateID());
     }
     ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
-    // iterate sub-bodies of compsolid
-    ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
-    if (aComp.get()) {
-      int aNumSub = aComp->numberOfSubs();
-      for(int a = 0; a < aNumSub; a++) {
-        ResultPtr aSub = aComp->subResult(a);
-        if (!aSub->isDisabled()) {// update state only for enabled results (Placement Result Part may make the original Part Result as invalid)
-          aSub->data()->execState(theState);
-          if (theState == ModelAPI_StateDone) // feature become "done", so execution changed results
-            myUpdated[aSub] = myModification;
-        }
-        if (theFeature->data()->updateID() > aSub->data()->updateID()) {
-          aSub->data()->setUpdateID(theFeature->data()->updateID());
-        }
-        ModelAPI_EventCreator::get()->sendUpdated(aSub, EVENT_DISP);
-      }
-    }
   }
   // to redisplay "presentable" feature (for ex. distance constraint)
   ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
   theFeature->data()->execState(theState);
+  myUpdated[theFeature] = myModification; // feature is also updated to avoid re-updation of it
 }
 
 /// Updates the state by the referenced object: if something bad with it, set state for this one
@@ -459,6 +448,27 @@ bool Model_Update::isOlder(std::shared_ptr<ModelAPI_Feature> theFeature,
   std::map<std::shared_ptr<ModelAPI_Object>, int >::iterator anAIter = myUpdated.find(theArgument);
   if (anAIter == myUpdated.end())
     return false;
+  // for the modification IDs compare results: modification ID of feature means only that attributes
+  // of this feature were updated, but if results are obsolete relatively to the referenced results,
+  // the feature must be updated
+  std::list<ResultPtr> aResults;
+  ModelAPI_Tools::allResults(theFeature, aResults);
+  std::list<ResultPtr>::iterator aRIter = aResults.begin();
+  for (; aRIter != aResults.cend(); aRIter++) {
+    std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+    if (!aRes->isDisabled()) {
+      std::map<std::shared_ptr<ModelAPI_Object>, int >::iterator anRIter = myUpdated.find(aRes);
+      int aResultID = aRes->data()->updateID();
+      if (aResultID < anArgID)
+        return true;
+      if (anRIter == myUpdated.end()) // not updated at all
+        return true;
+      if (anRIter->second < anAIter->second)
+        return true;
+    }
+  }
+  // also check a feature: some have no parameters,
+  // but must be updated anyway (like Coincidence of sketch) to be redisplayed
   std::map<std::shared_ptr<ModelAPI_Object>, int >::iterator aFIter = myUpdated.find(theFeature);
   if (aFIter == myUpdated.end())
     return true; // argument is updated, but feature is not updated at all
@@ -654,13 +664,14 @@ void Model_Update::executeFeature(FeaturePtr theFeature)
       aState = ModelAPI_StateExecFailed;
     } else {
       aState = ModelAPI_StateDone;
-      myWaitForFinish.insert(theFeature);
     }
   } catch(...) {
     aState = ModelAPI_StateExecFailed;
     Events_Error::send(
       "Feature " + theFeature->getKind() + " has failed during the execution");
   }
+  // The macro feature has to be deleted in any case even its execution is failed 
+  myWaitForFinish.insert(theFeature);
   if (aState != ModelAPI_StateDone) {
     theFeature->eraseResults();
   }