Salome HOME
Issue #459: Check pre-selection for group operation
[modules/shaper.git] / src / Model / Model_Update.cpp
index dd2b02b4cb066dcd7fad1921a4f71e65f7a38c6e..142f5c1e12557284b0c4420054f1eb4c42b94dfe 100644 (file)
@@ -50,8 +50,9 @@ Model_Update::Model_Update()
   aLoop->registerListener(this, kOpStartEvent);
 
   Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild immediately",
-                                   Config_Prop::Bool, "false");
-  isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
+                                   Config_Prop::Boolean, "false");
+  myIsAutomatic =
+    Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
 }
 
 void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
@@ -67,21 +68,30 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
   static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
   bool isAutomaticChanged = false;
   if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
-    isAutomatic = 
+    bool aPropVal =
       Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
+    if (aPropVal == myIsAutomatic)
+      return; // nothing is changed, so nithing to do
+    myIsAutomatic = aPropVal;
+    if (!myIsAutomatic)
+      return; // less automatization => nothing to do
   } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
-    if (isAutomatic == false) {
+    if (myIsAutomatic == false) {
       isAutomaticChanged = true;
-      isAutomatic = true;
+      myIsAutomatic = true;
     }
   } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent ||
-    theMessage->eventID() == kMovedEvent) {
+             theMessage->eventID() == kMovedEvent) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     const std::set<ObjectPtr>& anObjs = aMsg->objects();
     std::set<ObjectPtr>::const_iterator anObjIter = anObjs.cbegin();
     for(; anObjIter != anObjs.cend(); anObjIter++) {
       myJustCreatedOrUpdated.insert(*anObjIter);
+      // created objects are always must be up to date (python box feature)
+      // and updated not in internal uptation chain
+      if (!myIsExecuted || theMessage->eventID() == kCreatedEvent)
+        myInitial.insert(*anObjIter);
       // TODO(mpv): check the next line. Came into dev 0.6.1 from BR_PYTHON_PLUGIN
       // (*anObjIter)->data()->mustBeUpdated(true); // object must be updated because it was changed
     }
@@ -89,11 +99,12 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
       return; // this event is for solver update, not here
   } else if (theMessage->eventID() == kOpStartEvent) {
     myJustCreatedOrUpdated.clear();
+    myInitial.clear();
     return; // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
   } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
-    if (isAutomatic == false) { // Apply button now works as "Rebuild"
+    if (myIsAutomatic == false) { // Apply button now works as "Rebuild"
       isAutomaticChanged = true;
-      isAutomatic = true;
+      myIsAutomatic = true;
     }
     // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
     if (theMessage->eventID() == kOpFinishEvent) {
@@ -101,12 +112,15 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
       for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++)
       {
         FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
-        if (aF && aF->getKind() == "Extrusion") {
-          if (aF->selection("extrusion_face")) {
-            ResultPtr aSketchRes = aF->selection("extrusion_face")->context();
-            if (aSketchRes) {
-              static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
-              ModelAPI_EventCreator::get()->sendUpdated(aSketchRes, HIDE_DISP);
+        if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
+          AttributeSelectionListPtr aBase = aF->selectionList("base");
+          if (aBase.get()) {
+            for(int a = aBase->size() - 1; a >= 0; a--) {
+              ResultPtr aSketchRes = aBase->value(a)->context();
+              if (aSketchRes) {
+                static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
+                ModelAPI_EventCreator::get()->sendUpdated(aSketchRes, HIDE_DISP);
+              }
             }
           }
         }
@@ -114,17 +128,11 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     }
   }
 
-  if (isExecuted)
+  if (myIsExecuted)
     return;  // nothing to do: it is executed now
 
   //Events_LongOp::start(this);
-  isExecuted = true;
-  std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
-      std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-  if (aMsg) myInitial = aMsg->objects();
-  else {
-    myInitial.clear();
-  }
+  myIsExecuted = true;
   // iterate all documents: features in Root first, then - subs
   updateInDoc(ModelAPI_Session::get()->moduleDocument());
 
@@ -133,13 +141,14 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
   static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   aLoop->flush(EVENT_DISP);
   //Events_LongOp::end(this);
-  if (isAutomaticChanged) isAutomatic = false;
+  if (isAutomaticChanged) myIsAutomatic = false;
 
   if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
     myJustCreatedOrUpdated.clear();
+    myInitial.clear();
   }
 
-  isExecuted = false;
+  myIsExecuted = false;
 }
 
 void Model_Update::updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc)
@@ -212,8 +221,8 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
     CompositeFeaturePtr aComposite = 
       std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
     if (aComposite) {
-      int aSubsNum = aComposite->numberOfSubs();
-      for(int a = 0; a < aSubsNum; a++) {
+      // number of subs can be changed in execution: like fillet
+      for(int a = 0; a < aComposite->numberOfSubs(); a++) {
         if (updateFeature(aComposite->subFeature(a)))
           aMustbeUpdated = true;
       }
@@ -242,7 +251,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
       if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
           !theFeature->isPersistentResult()) {
         if (aFactory->validate(theFeature)) {
-          if (isAutomatic || 
+          if (myIsAutomatic || 
               (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) ||
               !theFeature->isPersistentResult() /* execute quick, not persistent results */) 
           {
@@ -256,7 +265,8 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
                 std::shared_ptr<ModelAPI_AttributeSelection> aSel =
                   std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
                 if (!aSel->update()) { // this must be done on execution since it may be long operation
-                  if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)))
+                  if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)) &&
+                      aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
                     aState = ModelAPI_StateInvalidArgument;
                 }
               }
@@ -270,7 +280,8 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
                   if (aSelAttr) {
                     if (!aSelAttr->update()) {
                       if (!aFactory->isNotObligatory(
-                          theFeature->getKind(), theFeature->data()->id(aSel)))
+                            theFeature->getKind(), theFeature->data()->id(aSel)) &&
+                          aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
                         aState = ModelAPI_StateInvalidArgument;
                     }
                   }
@@ -279,8 +290,8 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
               // for sketch after update of plane (by update of selection attribute)
               // but before execute, all sub-elements also must be updated (due to the plane changes)
               if (aComposite) {
-                int aSubsNum = aComposite->numberOfSubs();
-                for(int a = 0; a < aSubsNum; a++) {
+                // number of subs can be changed in execution: like fillet
+                for(int a = 0; a < aComposite->numberOfSubs(); a++) {
                   FeaturePtr aSub = aComposite->subFeature(a);
                   bool aWasModified = myUpdated[aSub];
                   myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed)
@@ -290,7 +301,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
                 }
                 // re-execute after update: solver may update the previous values, so, shapes must be
                 // updated
-                for(int a = 0; a < aSubsNum; a++) {
+                for(int a = 0; a < aComposite->numberOfSubs(); a++) {
                   if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a)))
                     aComposite->subFeature(a)->execute();
                 }