Salome HOME
Fix the revolution algorithm revolving an edge between faces.
[modules/shaper.git] / src / Model / Model_Update.cpp
index 9e8de8d22f270a7c2c7fb2c3bf6102a4592df638..9127a9915cab6da6e7d1306a10cfc62007505ade 100644 (file)
@@ -21,7 +21,6 @@
 #include <Model_Document.h>
 #include <Model_Data.h>
 #include <Model_Objects.h>
-#include <Model_AttributeSelection.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
 Model_Update MY_UPDATER_INSTANCE;  /// the only one instance initialized on load of the library
 //#define DEB_UPDATE
 
+#ifdef DEB_UPDATE
+#include <Locale_Convert.h>
+#endif
+
 Model_Update::Model_Update()
 {
   Events_Loop* aLoop = Events_Loop::loop();
@@ -117,7 +120,7 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
     else if (myProcessOnFinish.find(theFeature) == myProcessOnFinish.end())
       myProcessOnFinish[theFeature] = std::set<std::shared_ptr<ModelAPI_Feature> >();
 #ifdef DEB_UPDATE
-      std::cout<<"*** Add process on finish "<<theFeature->name()<<std::endl;
+      std::wcout<<L"*** Add process on finish "<<theFeature->name()<<std::endl;
 #endif
     // keeps the currently updated features to avoid infinitive cycling here: where feature on
     // "updateArguments" sends "updated" (in selection attribute) and goes here again
@@ -187,13 +190,14 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
 #endif
   }
   // clear processed and fill modified recursively
+  std::set<FeaturePtr> aRefSet;
   const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = theFeature->data()->refsToMe();
   std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
   for(; aRefIter != aRefs.cend(); aRefIter++) {
     if ((*aRefIter)->isArgument()) {
       FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
       if (aReferenced.get()) {
-        addModified(aReferenced, theFeature);
+        aRefSet.insert(aReferenced);
       }
     }
   }
@@ -202,25 +206,27 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
   ModelAPI_Tools::allResults(theFeature, allResults);
   std::list<ResultPtr>::iterator aRes = allResults.begin();
   for(; aRes != allResults.end(); aRes++) {
-    const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = (*aRes)->data()->refsToMe();
-    std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
-    for(; aRefIter != aRefs.cend(); aRefIter++) {
-      if ((*aRefIter)->isArgument()) {
-        FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
+    const std::set<std::shared_ptr<ModelAPI_Attribute> >& aResRefs = (*aRes)->data()->refsToMe();
+    std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRIter = aResRefs.cbegin();
+    for(; aRIter != aResRefs.cend(); aRIter++) {
+      if ((*aRIter)->isArgument()) {
+        FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRIter)->owner());
         if (aReferenced.get()) {
-          addModified(aReferenced, theFeature);
+          aRefSet.insert(aReferenced);
         }
       }
     }
   }
-
   // also add part feature that contains this feature to the modified
   if (theFeature->document()->kind() != "PartSet") {
     FeaturePtr aPart = ModelAPI_Tools::findPartFeature(
       ModelAPI_Session::get()->moduleDocument(), theFeature->document());
     if (aPart.get())
-      addModified(aPart, theFeature);
+      aRefSet.insert(aPart);
   }
+  for(std::set<FeaturePtr>::iterator aRef = aRefSet.begin(); aRef != aRefSet.end(); aRef++)
+    addModified(*aRef, theFeature);
+
   return true;
 }
 
@@ -308,6 +314,10 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
           aFeatures.push_back(*anObjIter);
         } else {
           aResults.push_back(*anObjIter);
+          ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*anObjIter);
+          if (aPart.get() && aPart->data().get() && aPart->data()->isValid()) {
+            aPart->shape(); // to update the shape on creation of the result
+          }
         }
       }
     }
@@ -325,8 +335,8 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
       if (!(*anObjIter)->data()->isValid())
         continue;
 #ifdef DEB_UPDATE
-      std::cout<<">>> in event updated "<<(*anObjIter)->groupName()<<
-        " "<<(*anObjIter)->data()->name()<<std::endl;
+      std::wcout<<L">>> in event updated "<<Locale::Convert::toWString((*anObjIter)->groupName())
+                <<L" "<<(*anObjIter)->data()->name()<<std::endl;
 #endif
       if ((*anObjIter)->groupName() == ModelAPI_ResultParameter::group()) {
         myIsParamUpdated = true;
@@ -360,7 +370,7 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
         for(; aRefIter != aRefs.cend(); aRefIter++) {
           if (!(*aRefIter)->owner()->data()->isValid())
             continue;
-          FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
+          anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
           if (anUpdated.get()) {
             if (addModified(anUpdated, aReason))
               aSomeModified = true;
@@ -563,14 +573,14 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
   }
 
 #ifdef DEB_UPDATE
-    std::cout<<"* Process feature "<<theFeature->name()<<std::endl;
+    std::wcout<<L"* Process feature "<<theFeature->name()<<std::endl;
 #endif
 
   // update the sketch plane before the sketch sub-elements are recomputed
   // (otherwise sketch will update plane, modify subs, after executed, but with old subs edges)
     if (aIsModified && theFeature->getKind() == "Sketch") {
 #ifdef DEB_UPDATE
-      std::cout << "****** Update sketch args " << theFeature->name() << std::endl;
+      std::wcout << L"****** Update sketch args " << theFeature->name() << std::endl;
 #endif
       AttributeSelectionPtr anExtSel = theFeature->selection("External");
       if (anExtSel.get()) {
@@ -689,7 +699,7 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
   }
 
 #ifdef DEB_UPDATE
-  std::cout<<"Update args "<<theFeature->name()<<std::endl;
+  std::wcout<<L"Update args "<<theFeature->name()<<std::endl;
 #endif
   // TestImport.py : after arguments are updated, theFeature may be removed
   if (!theFeature->data()->isValid())
@@ -712,7 +722,7 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
       // don't disable Part because it will make disabled all the features
       // (performance and problems with the current feature)
   #ifdef DEB_UPDATE
-    std::cout<<"Invalid args "<<theFeature->name()<<std::endl;
+    std::wcout<<L"Invalid args "<<theFeature->name()<<std::endl;
   #endif
     theFeature->eraseResults(false);
     redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
@@ -742,7 +752,7 @@ bool Model_Update::processFeature(FeaturePtr theFeature)
     }
   } else {
     #ifdef DEB_UPDATE
-      std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
+      std::wcout<<L"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
     #endif
     theFeature->eraseResults(false);
     redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
@@ -904,6 +914,13 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       bool isObligatory = aFactory->isCase(theFeature, theFeature->data()->id(aSel));
       if (isObligatory)
         aState = ModelAPI_StateInvalidArgument;
+    } else if (theFeature->getKind() == "Sketch" && aSel->id() == "External" &&
+               aSel->isInitialized()) {
+      // #19703 : if sketch plane was selected, but after context disappears, it must become invalid
+      aSel->update();
+      if (aSel->isInvalid()) {
+          aState = ModelAPI_StateInvalidArgument;
+      }
     }
   }
   // update the selection list attributes if any
@@ -913,6 +930,8 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
     // #19071 : avoid sending of update event in cycle
     bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true);
+    // list to keep the shared pointers while update is blocked (in messages raw poiters are used)
+    std::list<AttributeSelectionPtr> anAttrList;
     for(int a = aSel->size() - 1; a >= 0; a--) {
       std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
@@ -921,6 +940,7 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
         // update argument only if the referenced object is ready to use
         if (aContext.get() && !aContext->isDisabled()) {
           if (isReason(theFeature, aContext)) {
+            anAttrList.push_back(aSelAttr);
             if (!aSelAttr->update()) {
               bool isObligatory = !aFactory->isNotObligatory(
                 theFeature->getKind(), theFeature->data()->id(aSel)) &&
@@ -983,7 +1003,7 @@ bool Model_Update::isReason(std::shared_ptr<ModelAPI_Feature>& theFeature,
 void Model_Update::executeFeature(FeaturePtr theFeature)
 {
 #ifdef DEB_UPDATE
-  std::cout<<"Execute Feature "<<theFeature->name()<<std::endl;
+  std::wcout<<L"Execute Feature "<<theFeature->name()<<std::endl;
 #endif
   // execute in try-catch to avoid internal problems of the feature
   ModelAPI_ExecState aState = ModelAPI_StateDone;
@@ -1073,8 +1093,8 @@ void Model_Update::updateSelection(const std::set<std::shared_ptr<ModelAPI_Objec
       (*anObj)->data()->attributes(ModelAPI_AttributeSelection::typeId());
     std::list<AttributePtr>::iterator aRefsIter = aRefs.begin();
     for (; aRefsIter != aRefs.end(); aRefsIter++) {
-      std::shared_ptr<Model_AttributeSelection> aSel =
-        std::dynamic_pointer_cast<Model_AttributeSelection>(*aRefsIter);
+      AttributeSelectionPtr aSel =
+        std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
       bool aRemove = false;
       aSel->updateInHistory(aRemove);
     }
@@ -1085,12 +1105,12 @@ void Model_Update::updateSelection(const std::set<std::shared_ptr<ModelAPI_Objec
       std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
         std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
       for(int a = aSel->size() - 1; a >= 0; a--) {
-        std::shared_ptr<Model_AttributeSelection> aSelAttr =
-          std::dynamic_pointer_cast<Model_AttributeSelection>(aSel->value(a));
+        AttributeSelectionPtr aSelAttr =
+          std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
         if (aSelAttr.get()) {
-          bool theRemove = false;
-          aSelAttr->updateInHistory(theRemove);
-          if (theRemove) {
+          bool aRemove = false;
+          aSelAttr->updateInHistory(aRemove);
+          if (aRemove) {
             aRemoveSet.insert(a);
           }
         }