Salome HOME
Fix for the issue #587 and general optimization and debug of parametric update.
authormpv <mpv@opencascade.com>
Wed, 1 Jul 2015 17:06:23 +0000 (20:06 +0300)
committermpv <mpv@opencascade.com>
Wed, 1 Jul 2015 17:06:23 +0000 (20:06 +0300)
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_Document.h
src/PartSetPlugin/PartSetPlugin_Part.cpp

index 62e27bdd0cbdd343cd149ad0ed74b00bcd6bdbb0..cc37e8bef00f14c1cbeb63352724ec64aacae789 100644 (file)
@@ -902,3 +902,13 @@ bool Model_Document::isOpened()
 {
   return myObjs && !myDoc.IsNull();
 }
+
+int Model_Document::numInternalFeatures()
+{
+  return myObjs->numInternalFeatures();
+}
+
+std::shared_ptr<ModelAPI_Feature> Model_Document::internalFeature(const int theIndex)
+{
+  return myObjs->internalFeature(theIndex);
+}
index 586d50a28b8981ee6443a898a4a3c8d84c48a9d4..ba7ecb7afdc1561b35aa31d500e04f52ec4ea1e0 100644 (file)
@@ -136,6 +136,11 @@ class Model_Document : public ModelAPI_Document
   //! Makes the current feature one feature upper
   MODEL_EXPORT virtual void setCurrentFeatureUp();
 
+  //! Returns the number of all features: in the history or not
+  MODEL_EXPORT virtual int numInternalFeatures();
+  //! Returns the feature by zero-based index: features in the history or not
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> internalFeature(const int theIndex);
+
   /// Creates a construction cresults
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
index 1361a931a49baca81ba39b0b83ee3ac10d237a62..224d9d9dbf9039cf65e175116b66c1ce1eb5cafd 100644 (file)
@@ -913,6 +913,24 @@ std::list<std::shared_ptr<ModelAPI_Feature> > Model_Objects::allFeatures()
   return aResult;
 }
 
+int Model_Objects::numInternalFeatures()
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    return aRefs->Upper() - aRefs->Lower() + 1;
+  }
+  return 0; // invalid
+}
+
+std::shared_ptr<ModelAPI_Feature> Model_Objects::internalFeature(const int theIndex)
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    return feature(aRefs->Value(aRefs->Lower() + theIndex));
+  }
+  return FeaturePtr(); // invalid
+}
+
 Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
 {
   return TDF_LabelMapHasher::HashCode(theLab, theUpper);
index cd7f440e75a95f065045ebc982e410372ab86bcf..9bab83b67c38f4c87e7fc155b008e8aadf11c4e4 100644 (file)
@@ -86,6 +86,11 @@ class Model_Objects
   ///! Returns all (and disabled) results of the given type. Not fast method (iterates all features).
   void allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults);
 
+  //! Returns the number of all features: in the history or not
+  int numInternalFeatures();
+  //! Returns the feature by zero-based index: features in the history or not
+  std::shared_ptr<ModelAPI_Feature> internalFeature(const int theIndex);
+
   /// Creates a construction cresults
   std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
index d87e87ed8c0f615e71172eac4e890f2c6f93c425..1e5bb3fed0a9da0e32f878ab40d0cbbddff24fbc 100644 (file)
@@ -59,6 +59,7 @@ Model_Update::Model_Update()
   myIsAutomatic =
     Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
   myIsParamUpdated = false;
+  myIsFinish = false;
 }
 
 void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
@@ -72,7 +73,6 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
   static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
   static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
   static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
-  bool isOperationChanged = false;
   if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
     bool aPropVal =
       Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
@@ -104,34 +104,28 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     // this event is for solver update, not here, do not react immideately
     if (!isOnlyResults && !(theMessage->eventID() == kMovedEvent))
       processOperation(false);
-  } else if (theMessage->eventID() == kOpStartEvent) {
-    // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
-    isOperationChanged = true;
-  } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
-    processOperation(true, theMessage->eventID() == kOpFinishEvent);
-    isOperationChanged = true;
-  }
-  if (isOperationChanged) {
-    // remove all macros before clearing all created and execute all not-previewed
-    std::set<ObjectPtr>::iterator anUpdatedIter = myJustUpdated.begin();
-    while(anUpdatedIter != myJustUpdated.end()) {
+  } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent ||
+      theMessage->eventID() == kOpStartEvent) {
+    myIsParamUpdated = false;
+
+    if (!(theMessage->eventID() == kOpStartEvent)) {
+      myIsFinish = true;
+      processOperation(true, theMessage->eventID() == kOpFinishEvent);
+      myIsFinish = false;
+    }
+    // remove all macros before clearing all created
+    std::set<ObjectPtr>::iterator anUpdatedIter = myWaitForFinish.begin();
+    while(anUpdatedIter != myWaitForFinish.end()) {
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anUpdatedIter);
       if (aFeature.get()) {
-        // execute not-previewed feature on "apply"
-        if (!aFeature->isPreviewNeeded()) {
-          static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
-          if (aFactory->validate(aFeature)) {
-            executeFeature(aFeature);
-          }
-        }
-        // remove macro on apply
+        // remove macro on finish
         if (aFeature->isMacro()) {
           aFeature->document()->removeFeature(aFeature);
-          myJustUpdated.erase(aFeature);
+          myWaitForFinish.erase(aFeature);
         }
         // to avoid the map update problems on "remove"
-        if (myJustUpdated.find(aFeature) == myJustUpdated.end()) {
-          anUpdatedIter = myJustUpdated.begin();
+        if (myWaitForFinish.find(aFeature) == myWaitForFinish.end()) {
+          anUpdatedIter = myWaitForFinish.begin();
         } else {
           anUpdatedIter++;
         }
@@ -139,7 +133,10 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
         anUpdatedIter++;
       }
     }
-    myIsParamUpdated = false;
+    // in the end of transaction everything is updated, so clear the old objects (the only one
+    // place where results are cleared)
+    myJustUpdated.clear();
+    myWaitForFinish.clear();
   }
 }
 
@@ -163,7 +160,6 @@ void Model_Update::processOperation(const bool theTotalUpdate, const bool theFin
         }
       }
     }
-    myWaitForFinish.clear();
   }
   // perform update of everything if needed
   if (!myIsExecuted) {
@@ -243,8 +239,8 @@ void Model_Update::updateFeature(FeaturePtr theFeature, std::set<FeaturePtr>& th
     aJustUpdated = true;
 
   // execute feature if it must be updated
-  if (theFeature->isPreviewNeeded()) {
-    if ((myIsAutomatic || aJustUpdated) &&
+  if (theFeature->isPreviewNeeded() || myIsFinish) {
+    if (aJustUpdated &&
       std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures()) {
         ModelAPI_ExecState aState = theFeature->data()->execState();
         if (aFactory->validate(theFeature)) {
@@ -257,6 +253,8 @@ void Model_Update::updateFeature(FeaturePtr theFeature, std::set<FeaturePtr>& th
   } else { // preview is not needed => make state Done
     if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) {
       theFeature->data()->execState(ModelAPI_StateDone);
+      if (aJustUpdated) // store that it must be updated on finish
+        myJustUpdated.insert(theFeature);
     }
   }
 }
@@ -431,6 +429,21 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       aState = stateByReference(*aRefObj, aState);
     }
   }
+  // composites sub-elements
+  CompositeFeaturePtr aCompos = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
+  // composite feature must be executed after sub-features execution
+  if (aCompos) {
+    // number of subs can be changed in execution: like fillet
+    for(int a = 0; a < aCompos->numberOfSubs(); a++) {
+      FeaturePtr aSub = aCompos->subFeature(a);
+      if (myJustUpdated.find(aSub) != myJustUpdated.end() || 
+             (aSub.get() && aSub->data()->updateID() > theFeature->data()->updateID())) {
+          if (aState == ModelAPI_StateDone)
+            aState = ModelAPI_StateMustBeUpdated;
+      }
+    }
+  }
+
 
   if (aState != ModelAPI_StateDone)
     theFeature->data()->execState(aState);
index 1ae12eb09a913cb9d83ec1d21beb72fb9093a2a0..d8d590497deb710c2867dc21f7a8b35bca0c1707 100644 (file)
@@ -33,6 +33,8 @@ class Model_Update : public Events_Listener
   bool myIsAutomatic;
   /// to know that some parameter was changed during this operation
   bool myIsParamUpdated;
+  /// to execute features of finish if perview is not needed
+  bool myIsFinish;
 
  public:
   /// Is called only once, on startup of the application
index 2a97982b0a79f8b8711a316ac37144bc2b6edd90..6d778360fbde1d611fc4ffb12711237d8d3431d2 100644 (file)
@@ -102,6 +102,12 @@ public:
   //! Makes the current feature one feature upper
   virtual void setCurrentFeatureUp() = 0;
 
+  //! Returns the number of all features: in the history or not
+  virtual int numInternalFeatures() = 0;
+  //! Returns the feature by zero-based index: features in the history or not
+  virtual std::shared_ptr<ModelAPI_Feature> internalFeature(const int theIndex) = 0;
+
+
   //! To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_Document();
 
index 04b6ddd6ef97461c7c2de13f7178078f20c79901..3ef0eb1928bb04f2984ef6f86a7eadf6f7bebe60 100644 (file)
@@ -67,7 +67,7 @@ int PartSetPlugin_Part::numberOfSubs() const
   if (aResult.get()) {
     DocumentPtr aDoc = aResult->partDoc();
     if (aDoc.get())
-      return aDoc->size(ModelAPI_Feature::group());
+      return aDoc->numInternalFeatures();
   }
   return 0;
 }
@@ -78,8 +78,7 @@ std::shared_ptr<ModelAPI_Feature> PartSetPlugin_Part::subFeature(const int theIn
   if (aResult.get()) {
     DocumentPtr aDoc = aResult->partDoc();
     if (aDoc.get()) {
-      return std::dynamic_pointer_cast<ModelAPI_Feature>(
-        aDoc->object(ModelAPI_Feature::group(), theIndex));
+      return aDoc->internalFeature(theIndex);
     }
   }
   return FeaturePtr();