From 7edae2e3ede0ca739810de747c975f4983398f76 Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 25 Jul 2014 10:58:24 +0400 Subject: [PATCH] Updater mechanism update --- src/Model/Model_Document.cpp | 60 ++++++++++++------ src/Model/Model_Document.h | 7 ++- src/Model/Model_Update.cpp | 78 +++++++++++++++++------- src/Model/Model_Update.h | 6 +- src/ModelAPI/ModelAPI_Document.h | 6 +- src/ModelAPI/ModelAPI_Feature.cpp | 20 ++++++ src/ModelAPI/ModelAPI_Feature.h | 3 + src/SketchPlugin/SketchPlugin_Circle.cpp | 14 ++++- 8 files changed, 147 insertions(+), 47 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 41c7e79bf..c50b4a05b 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -493,16 +493,29 @@ boost::shared_ptr 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 >& aResults = aFeature->results(); std::list >::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 >& aResults = aFeature->results(); std::list >::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 aThis = Model_Application::getApplication()->getDocument(myID); // update all objects by checking are they of labels or not - std::set aCheckedFeatures; + std::set 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::iterator aNewIter = aNewFeatures.begin(); + for(; aNewIter != aNewFeatures.end(); aNewIter++) { + (*aNewIter)->execute(); + }*/ // check all features are checked: if not => it was removed NCollection_DataMap::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(); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 340ecd4cc..8bb19057c 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -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 createConstruction( diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 15b8139ec..a50f19c6a 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -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 >::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 aFeature = boost::dynamic_pointer_cast - ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex)); + FeaturePtr aFeature = boost::dynamic_pointer_cast + ((*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 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(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 > aRefs = - theObject->data()->attributes(ModelAPI_AttributeReference::type()); + theFeature->data()->attributes(ModelAPI_AttributeReference::type()); list >::iterator aRefsIter = aRefs.begin(); for(; aRefsIter != aRefs.end(); aRefsIter++) { boost::shared_ptr aSub = boost::dynamic_pointer_cast(*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 aListRef = boost::dynamic_pointer_cast(*aRefsIter)->list(); list::iterator aListIter = aListRef.begin(); for(; aListIter != aListRef.end(); aListIter++) { boost::shared_ptr 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 >& aResults = aRealFeature->results(); + const std::list >& aResults = theFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); for(; aRIter != aResults.cend(); aRIter++) { boost::shared_ptr 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 >& aResults = theFeature->results(); + std::list >::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 theObject) +{ + if (!theObject) + return false; + FeaturePtr aFeature = boost::dynamic_pointer_cast(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(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 } diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h index f59d891f7..f96bbf8ad 100644 --- a/src/Model/Model_Update.h +++ b/src/Model/Model_Update.h @@ -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 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 theObject); }; diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index 2aebf34d9..ab055f324 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -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 - 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() {} diff --git a/src/ModelAPI/ModelAPI_Feature.cpp b/src/ModelAPI/ModelAPI_Feature.cpp index fa4651408..5617cedd9 100644 --- a/src/ModelAPI/ModelAPI_Feature.cpp +++ b/src/ModelAPI/ModelAPI_Feature.cpp @@ -37,6 +37,26 @@ void ModelAPI_Feature::setResult(const boost::shared_ptr& theRe Events_Loop::loop()->flush(anEvent); } +void ModelAPI_Feature::setResult( + const boost::shared_ptr& theResult, const int theIndex) +{ + std::list >::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_Feature::documentToAdd() { return ModelAPI_PluginManager::get()->currentDocument(); diff --git a/src/ModelAPI/ModelAPI_Feature.h b/src/ModelAPI/ModelAPI_Feature.h index 2305044ed..b42266074 100644 --- a/src/ModelAPI/ModelAPI_Feature.h +++ b/src/ModelAPI/ModelAPI_Feature.h @@ -48,6 +48,9 @@ public: MODELAPI_EXPORT boost::shared_ptr firstResult(); /// sets the alone result MODELAPI_EXPORT void setResult(const boost::shared_ptr& theResult); + /// sets the result by index (zero based), results before this must be set before + MODELAPI_EXPORT void setResult( + const boost::shared_ptr& 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"). diff --git a/src/SketchPlugin/SketchPlugin_Circle.cpp b/src/SketchPlugin/SketchPlugin_Circle.cpp index 35371ff9d..d8be73285 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@ -43,7 +43,12 @@ void SketchPlugin_Circle::execute() boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); // make a visible point boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); - aShapes.push_back(aCenterPointShape); + //aShapes.push_back(aCenterPointShape); + boost::shared_ptr aConstr1 = + document()->createConstruction(data()); + aConstr1->setShape(aCenterPointShape); + aConstr1->setIsInHistory(false); + setResult(aConstr1, 0); // make a visible circle boost::shared_ptr aNDir = @@ -58,8 +63,14 @@ void SketchPlugin_Circle::execute() boost::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); aShapes.push_back(aCircleShape); + boost::shared_ptr aConstr2 = + document()->createConstruction(data()); + aConstr2->setShape(aCircleShape); + aConstr2->setIsInHistory(false); + setResult(aConstr2, 1); } } + /* boost::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); // store the result boost::shared_ptr aConstr = @@ -67,6 +78,7 @@ void SketchPlugin_Circle::execute() aConstr->setShape(aCompound); aConstr->setIsInHistory(false); setResult(aConstr); + */ } } -- 2.39.2