]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Updater mechanism update
authormpv <mikhail.ponikarov@opencascade.com>
Fri, 25 Jul 2014 06:58:24 +0000 (10:58 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Fri, 25 Jul 2014 06:58:24 +0000 (10:58 +0400)
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Feature.cpp
src/ModelAPI/ModelAPI_Feature.h
src/SketchPlugin/SketchPlugin_Circle.cpp

index 41c7e79bfa14bf9f26f80494717548ba50e32089..c50b4a05b44f6a52465d4c441b8617d93596e355 100644 (file)
@@ -493,16 +493,29 @@ boost::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string the
   return Model_Application::getApplication()->getDocument(theDocID);
 }
 
-ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
+ObjectPtr Model_Document::object(const std::string& theGroupID, 
+  const int theIndex, const bool theHidden)
 {
   if (theGroupID == ModelAPI_Feature::group()) {
-    Handle(TDataStd_ReferenceArray) aRefs;
-    if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
-      return ObjectPtr();
-    if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex)
-      return ObjectPtr();
-    TDF_Label aFeatureLabel = aRefs->Value(theIndex);
-    return feature(aFeatureLabel);
+    if (theHidden) {
+      int anIndex = 0;
+      TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
+      for(; aLabIter.More(); aLabIter.Next()) {
+        if (theIndex == anIndex) {
+          TDF_Label aFLabel = aLabIter.Value()->Label();
+          return feature(aFLabel);
+        }
+        anIndex++;
+      }
+    } else {
+      Handle(TDataStd_ReferenceArray) aRefs;
+      if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+        return ObjectPtr();
+      if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex)
+        return ObjectPtr();
+      TDF_Label aFeatureLabel = aRefs->Value(theIndex);
+      return feature(aFeatureLabel);
+    }
   } else {
     // comment must be in any feature: it is kind
     int anIndex = 0;
@@ -513,7 +526,7 @@ ObjectPtr Model_Document::object(const std::string& theGroupID, const int theInd
       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
       for(; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) {
+        if ((theHidden || (*aRIter)->isInHistory()) && (*aRIter)->groupName() == theGroupID) {
           if (anIndex == theIndex)
             return *aRIter;
           anIndex++;
@@ -525,13 +538,17 @@ ObjectPtr Model_Document::object(const std::string& theGroupID, const int theInd
   return ObjectPtr();
 }
 
-int Model_Document::size(const std::string& theGroupID) 
+int Model_Document::size(const std::string& theGroupID, const bool theHidden
 {
   int aResult = 0;
   if (theGroupID == ModelAPI_Feature::group()) {
-    Handle(TDataStd_ReferenceArray) aRefs;
-    if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
-      return aRefs->Length();
+    if (theHidden) {
+      return myObjs.Size();
+    } else {
+      Handle(TDataStd_ReferenceArray) aRefs;
+      if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+        return aRefs->Length();
+    }
   } else {
     // comment must be in any feature: it is kind
     TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
@@ -541,7 +558,7 @@ int Model_Document::size(const std::string& theGroupID)
       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
       for(; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->isInHistory() && (*aRIter)->groupName() == theGroupID) {
+        if ((theHidden || (*aRIter)->isInHistory()) && (*aRIter)->groupName() == theGroupID) {
           aResult++;
         }
       }
@@ -614,7 +631,7 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated)
   boost::shared_ptr<ModelAPI_Document> aThis = 
     Model_Application::getApplication()->getDocument(myID);
   // update all objects by checking are they of labels or not
-  std::set<FeaturePtr> aCheckedFeatures;
+  std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
   TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
   for(; aLabIter.More(); aLabIter.Next()) {
     TDF_Label aFeatureLabel = aLabIter.Value()->Label();
@@ -625,26 +642,31 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated)
         .ToCString());
       // this must be before "setData" to redo the sketch line correctly
       myObjs.Bind(aFeatureLabel, aNewObj);
-      aCheckedFeatures.insert(aNewObj);
+      aNewFeatures.insert(aNewObj);
       initData(aNewObj, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
-      aNewObj->execute(); // to restore results list
 
       // event: model is updated
       static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
       ModelAPI_EventCreator::get()->sendUpdated(aNewObj, anEvent);
       // feature for this label is added, so go to the next label
     } else { // nothing is changed, both iterators are incremented
-      aCheckedFeatures.insert(myObjs.Find(aFeatureLabel));
+      aKeptFeatures.insert(myObjs.Find(aFeatureLabel));
       if (theMarkUpdated) {
         static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
         ModelAPI_EventCreator::get()->sendUpdated(myObjs.Find(aFeatureLabel), anEvent);
       }
     }
   }
+  // execute new features to restore results: after features creation to make all references valid
+  /*std::set<FeaturePtr>::iterator aNewIter = aNewFeatures.begin();
+  for(; aNewIter != aNewFeatures.end(); aNewIter++) {
+      (*aNewIter)->execute();
+  }*/
   // check all features are checked: if not => it was removed
   NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
   while(aFIter.More()) {
-    if (aCheckedFeatures.find(aFIter.Value()) == aCheckedFeatures.end()) {
+    if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end() &&
+        aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
       FeaturePtr aFeature = aFIter.Value();
       TDF_Label aLab = aFIter.Key();
       aFIter.Next();
index 340ecd4ccf9d662be95224b9c883686c01a1ac99..8bb19057c8ef1aea4c60479fa68aecbcc12017e6 100644 (file)
@@ -92,10 +92,13 @@ public:
   //! \param theGroupID group that contains a feature
   //! \param theIndex zero-based index of feature in the group
   //! \param isOperation if it is true, returns feature (not Object)
-  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex);
+  //! \param theHidden if it is true, it counts also the features that are not in tree
+  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex,
+    const bool theHidden = false);
 
   //! Returns the number of features in the group
-  MODEL_EXPORT virtual int size(const std::string& theGroupID);
+  //! If theHidden is true, it counts also the features that are not in tree
+  MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theHidden = false);
 
   /// Creates a construction cresults
   MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
index 15b8139ec1138a7c1c6528e3bf9707e25821387c..a50f19c6a2ba91767aee44ca7ad51e17b4b03349 100644 (file)
@@ -18,6 +18,7 @@ Model_Update MY_INSTANCE; /// the only one instance initialized on load of the l
 
 Model_Update::Model_Update()
 {
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
 }
 
@@ -32,15 +33,15 @@ void Model_Update::processEvent(const Events_Message* theMessage)
   for(; aFIter != myInitial.end(); aFIter++) {
     aDocs.insert((*aFIter)->document());
   }
-  // iterate all features of features-documents to update them
+  // iterate all features of features-documents to update them (including hidden)
   set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
   for(; aDIter != aDocs.end(); aDIter++) {
-    int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group());
+    int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
     for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
-      boost::shared_ptr<ModelAPI_Object> aFeature = boost::dynamic_pointer_cast<ModelAPI_Object>
-        ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex));
+      FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>
+        ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
       if (aFeature)
-        updateObject(aFeature);
+        updateFeature(aFeature);
     }
   }
   myUpdated.clear();
@@ -49,52 +50,85 @@ void Model_Update::processEvent(const Events_Message* theMessage)
   Events_Loop::loop()->flush(EVENT_DISP);
 }
 
-bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
+bool Model_Update::updateFeature(FeaturePtr theFeature)
 {
   // check it is already processed
-  if (myUpdated.find(theObject) != myUpdated.end())
-    return myUpdated[theObject];
+  if (myUpdated.find(theFeature) != myUpdated.end())
+    return myUpdated[theFeature];
   // check all features this feature depended on (recursive call of updateFeature)
-  bool anExecute = myInitial.find(theObject) != myInitial.end();
-  bool aMustbeUpdated = myInitial.find(theObject) != myInitial.end();
-  FeaturePtr aRealFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-  if (aRealFeature) { // only real feature contains references to other objects
+  bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
+  if (theFeature) { // only real feature contains references to other objects
     // references
     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = 
-      theObject->data()->attributes(ModelAPI_AttributeReference::type());
+      theFeature->data()->attributes(ModelAPI_AttributeReference::type());
     list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
     for(; aRefsIter != aRefs.end(); aRefsIter++) {
       boost::shared_ptr<ModelAPI_Object> aSub =
         boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRefsIter)->value();
-      if (aSub && aSub != theObject && updateObject(aSub))
+      if (updateObject(aSub)) {
         aMustbeUpdated = true;
+      }
     }
     // lists of references
-    aRefs = theObject->data()->attributes(ModelAPI_AttributeRefList::type());
+    aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
     for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
       list<ObjectPtr> aListRef = 
         boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
       list<ObjectPtr>::iterator aListIter = aListRef.begin();
       for(; aListIter != aListRef.end(); aListIter++) {
         boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
-        if (aSub && updateObject(aSub))
+        if (updateObject(aSub)) {
           aMustbeUpdated = true;
+        }
       }
     }
     // execute feature if it must be updated
-    anExecute = aMustbeUpdated || anExecute;
-    if (anExecute) {
-      aRealFeature->execute();
+    if (aMustbeUpdated) {
+      theFeature->execute();
       // redisplay all results
       static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-      const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aRealFeature->results();
+      const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
       for(; aRIter != aResults.cend(); aRIter++) {
         boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+        myUpdated[aRes] = true;
         ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
       }
+    } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
+      const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+      std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for(; aRIter != aResults.cend(); aRIter++) {
+        if (myInitial.find(*aRIter) != myInitial.end()) {
+          aMustbeUpdated = true;
+          break;
+        }
+      }
+    }
+  }
+  myUpdated[theFeature] = aMustbeUpdated;
+  return aMustbeUpdated;
+}
+
+bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
+{
+  if (!theObject) 
+    return false;
+  FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+  if (aFeature) { // for feature just call update Feature
+    return updateFeature(aFeature);
+  }
+  // check general object, possible just a result
+  if (myUpdated.find(theObject) != myUpdated.end())
+    return myUpdated[theObject]; // already processed
+  // check the feature of this object must be executed
+  ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  if (aResult) {
+    FeaturePtr aResFeature = aResult->document()->feature(aResult);
+    if (aResFeature) {
+      return updateFeature(aResFeature);
     }
   }
-  myUpdated[theObject] = anExecute;
-  return anExecute;
+  if (myInitial.find(theObject) != myInitial.end())
+    return true;
+  return false; // nothing is known
 }
index f59d891f78609c6cc067908da3eeb02893893e0a..f96bbf8adaed2c069f054122de127c2d699907ff 100644 (file)
@@ -32,7 +32,11 @@ public:
   MODEL_EXPORT virtual void processEvent(const Events_Message* theMessage);
 
 protected:
-  /// Recoursively checks and updates the object if needed
+  /// Recoursively checks and updates the feature if needed (calls the execute method)
+  /// Returns true if feature was updated.
+  bool updateFeature(boost::shared_ptr<ModelAPI_Feature> theFeature);
+
+  /// Recoursively checks and updates the object (result or feature) if needed (calls updateFeature)
   /// Returns true if object was updated.
   bool updateObject(boost::shared_ptr<ModelAPI_Object> theObject);
 };
index 2aebf34d9d4ad326283d83eeddff0179b49b598d..ab055f32484a4db83d9d447192709832bd74c31f 100644 (file)
@@ -78,11 +78,13 @@ public:
   //! Returns the object in the group by the index (started from zero)
   //! \param theGroupID group that contains an object
   //! \param theIndex zero-based index of feature in the group
+  //! \param theHidden if it is true, it counts also the features that are not in tree
   virtual boost::shared_ptr<ModelAPI_Object> 
-    object(const std::string& theGroupID, const int theIndex) = 0;
+    object(const std::string& theGroupID, const int theIndex, const bool theHidden = false) = 0;
 
   //! Returns the number of objects in the group of objects
-  virtual int size(const std::string& theGroupID) = 0;
+  //! If theHidden is true, it counts also the features that are not in tree
+  virtual int size(const std::string& theGroupID, const bool theHidden = false) = 0;
 
   /// To virtually destroy the fields of successors
   virtual ~ModelAPI_Document() {}
index fa4651408dd513c906e83528f53b41141ee8c085..5617cedd9a9fffdb5747edd7b6269a688dd0309d 100644 (file)
@@ -37,6 +37,26 @@ void ModelAPI_Feature::setResult(const boost::shared_ptr<ModelAPI_Result>& theRe
   Events_Loop::loop()->flush(anEvent);
 }
 
+void ModelAPI_Feature::setResult(
+  const boost::shared_ptr<ModelAPI_Result>& theResult, const int theIndex) 
+{
+  std::list<boost::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+  for(int anIndex = 0; anIndex < theIndex; anIndex++) {
+    aResIter++;
+  }
+  if (aResIter == myResults.end()) { // append
+    myResults.push_back(theResult);
+    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
+    // Create event for first Feature, send it to make "created" earlier than "updated"
+    Events_Loop::loop()->flush(anEvent);
+  } else { // update
+    *aResIter = theResult;
+    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
+  }
+}
+
 boost::shared_ptr<ModelAPI_Document> ModelAPI_Feature::documentToAdd()
 {
   return ModelAPI_PluginManager::get()->currentDocument();
index 2305044edd546e0905e5e07d2d6b8daff88dba3f..b42266074ba9bb3a2e54e2a015194de812a8539f 100644 (file)
@@ -48,6 +48,9 @@ public:
   MODELAPI_EXPORT boost::shared_ptr<ModelAPI_Result> firstResult();
   /// sets the alone result
   MODELAPI_EXPORT void setResult(const boost::shared_ptr<ModelAPI_Result>& theResult);
+  /// sets the result by index (zero based), results before this must be set before
+  MODELAPI_EXPORT void setResult(
+    const boost::shared_ptr<ModelAPI_Result>& theResult, const int theIndex);
 
   /// Returns true if this feature must not be created: this is just an action
   /// that is not stored in the features history and data model (like "delete part").
index 35371ff9dea7dd90994a7f78f0d83393224532e1..d8be73285033ba3efff5efe4db974950b42c5e15 100644 (file)
@@ -43,7 +43,12 @@ void SketchPlugin_Circle::execute()
       boost::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
       // make a visible point
       boost::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
-      aShapes.push_back(aCenterPointShape);
+      //aShapes.push_back(aCenterPointShape);
+      boost::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = 
+        document()->createConstruction(data());
+      aConstr1->setShape(aCenterPointShape);
+      aConstr1->setIsInHistory(false);
+      setResult(aConstr1, 0);
 
       // make a visible circle
       boost::shared_ptr<GeomDataAPI_Dir> aNDir = 
@@ -58,8 +63,14 @@ void SketchPlugin_Circle::execute()
         boost::shared_ptr<GeomAPI_Shape> aCircleShape = 
                                 GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
         aShapes.push_back(aCircleShape);
+        boost::shared_ptr<ModelAPI_ResultConstruction> aConstr2 = 
+          document()->createConstruction(data());
+        aConstr2->setShape(aCircleShape);
+        aConstr2->setIsInHistory(false);
+        setResult(aConstr2, 1);
       }
     }
+    /*
     boost::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
       // store the result
       boost::shared_ptr<ModelAPI_ResultConstruction> aConstr = 
@@ -67,6 +78,7 @@ void SketchPlugin_Circle::execute()
       aConstr->setShape(aCompound);
       aConstr->setIsInHistory(false);
       setResult(aConstr);
+      */
   }
 }