From 204a8ad6efa9e33e01da086109418fdb9253b0d7 Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 9 Oct 2015 17:36:38 +0300 Subject: [PATCH] Finalization of concealment management with stable and not stable feature --- src/Model/Model_Data.cpp | 27 ++++--- src/Model/Model_Data.h | 6 +- src/Model/Model_Objects.cpp | 129 ++++++++++++++----------------- src/Model/Model_Objects.h | 7 +- src/Model/Model_Update.cpp | 7 ++ src/ModelAPI/ModelAPI_Result.cpp | 11 ++- 6 files changed, 104 insertions(+), 83 deletions(-) diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index e43e34e25..75b38aeb0 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -368,13 +368,20 @@ void Model_Data::eraseBackReferences() void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID) { AttributePtr anAttribute = theFeature->data()->attribute(theAttrID); - if (myRefsToMe.find(anAttribute) == myRefsToMe.end()) + removeBackReference(anAttribute); +} + +void Model_Data::removeBackReference(AttributePtr theAttr) +{ + if (myRefsToMe.find(theAttr) == myRefsToMe.end()) return; - myRefsToMe.erase(anAttribute); + myRefsToMe.erase(theAttr); // remove concealment immideately: on deselection it must be posible to reselect in GUI the same - if (ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) { + FeaturePtr aFeatureOwner = std::dynamic_pointer_cast(theAttr->owner()); + if (aFeatureOwner.get() && + ModelAPI_Session::get()->validators()->isConcealed(aFeatureOwner->getKind(), theAttr->id())) { updateConcealmentFlag(); } } @@ -406,10 +413,15 @@ void Model_Data::updateConcealmentFlag() for(; aRefsIter != myRefsToMe.end(); aRefsIter++) { if (aRefsIter->get()) { FeaturePtr aFeature = std::dynamic_pointer_cast((*aRefsIter)->owner()); - if (aFeature.get() && !aFeature->isDisabled()) { + if (aFeature.get() && !aFeature->isDisabled() && aFeature->isStable()) { if (ModelAPI_Session::get()->validators()->isConcealed( aFeature->getKind(), (*aRefsIter)->id())) { - return; // it is still concealed, nothing to do + std::shared_ptr aRes = + std::dynamic_pointer_cast(myObject); + if (aRes.get()) { + aRes->setIsConcealed(true); // set concealed + } + return; } } } @@ -417,11 +429,8 @@ void Model_Data::updateConcealmentFlag() // thus, no concealment references anymore => make not-concealed std::shared_ptr aRes = std::dynamic_pointer_cast(myObject); - if (aRes.get() && aRes->isConcealed()) { + if (aRes.get()) { aRes->setIsConcealed(false); - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aRes, anEvent); - Events_Loop::loop()->flush(anEvent); } } diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 1e6c0d650..da40e7d4a 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -223,11 +223,13 @@ protected: private: /// Removes all information about back references void eraseBackReferences(); - /// Adds a back reference (with identifier which attribute references to this object - /// It does not change the consealment flag of the data object result + /// Removes a back reference (with identifier which attribute references to this object) /// \param theFeature feature referenced to this /// \param theAttrID identifier of the attribute that is references from theFeature to this void removeBackReference(FeaturePtr theFeature, std::string theAttrID); + /// Removes a back reference (by the attribute) + /// \param theAttr the referenced attribute + void removeBackReference(AttributePtr theAttr); /// Adds a back reference (with identifier which attribute references to this object /// \param theFeature feature referenced to this /// \param theAttrID identifier of the attribute that is references from theFeature to this diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 9e209eb72..53c9d554f 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -696,91 +696,82 @@ void Model_Objects::synchronizeFeatures( anOwner->executeFeatures() = true; } -void Model_Objects::synchronizeBackRefs() +/// synchronises back references for the given object basing on the collected data +void Model_Objects::synchronizeBackRefsForObject(const std::set& theNewRefs, + ObjectPtr theObject) { - // keeps the concealed flags of result to catch the change and create created/deleted events - std::list > aConcealed; - // first cycle: erase all data about back-references - NCollection_DataMap::Iterator aFeatures(myFeatures); - for(; aFeatures.More(); aFeatures.Next()) { - FeaturePtr aFeature = aFeatures.Value(); - std::shared_ptr aFData = - std::dynamic_pointer_cast(aFeature->data()); - if (aFData.get()) { - aFData->eraseBackReferences(); + if (!theObject.get() || !theObject->data()->isValid()) + return; // invalid + std::shared_ptr aData = std::dynamic_pointer_cast(theObject->data()); + // iterate new list to compare with curent + std::set::iterator aNewIter = theNewRefs.begin(); + for(; aNewIter != theNewRefs.end(); aNewIter++) { + if (aData->refsToMe().find(*aNewIter) == aData->refsToMe().end()) { + FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aNewIter)->owner()); + aData->addBackReference(aRefFeat, (*aNewIter)->id()); } - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { - std::shared_ptr aResData = - std::dynamic_pointer_cast((*aRIter)->data()); - if (aResData.get()) { - aConcealed.push_back(std::pair(*aRIter, (*aRIter)->isConcealed())); - aResData->eraseBackReferences(); - } - // iterate sub-bodies of compsolid - ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aRIter); - if (aComp.get()) { - int aNumSub = aComp->numberOfSubs(); - for(int a = 0; a < aNumSub; a++) { - ResultPtr aSub = aComp->subResult(a); - std::shared_ptr aResData = - std::dynamic_pointer_cast(aSub->data()); - if (aResData.get()) { - aConcealed.push_back(std::pair(aSub, aSub->isConcealed())); - aResData->eraseBackReferences(); - } - } - } + } + if (theNewRefs.size() != aData->refsToMe().size()) { // some back ref must be removed + std::set::iterator aCurrentIter = aData->refsToMe().begin(); + while(aCurrentIter != aData->refsToMe().end()) { + if (theNewRefs.find(*aCurrentIter) == theNewRefs.end()) { + aData->removeBackReference(*aCurrentIter); + aCurrentIter = aData->refsToMe().begin(); // reinitialize iteration after delete + } else aCurrentIter++; } } + aData->updateConcealmentFlag(); +} - // second cycle: set new back-references: only features may have reference, iterate only them - ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); - for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) { +void Model_Objects::synchronizeBackRefs() +{ + // collect all back references in the separated container: to update everything at once, + // without additional Concealment switchin on and off: only the final modification + + // referenced (slave) objects to referencing attirbutes + std::map > allRefs; + NCollection_DataMap::Iterator aFeatures(myFeatures); + for(; aFeatures.More(); aFeatures.Next()) { FeaturePtr aFeature = aFeatures.Value(); - std::shared_ptr aFData = - std::dynamic_pointer_cast(aFeature->data()); + std::shared_ptr aFData = std::dynamic_pointer_cast(aFeature->data()); if (aFData.get()) { std::list > > aRefs; aFData->referencesToObjects(aRefs); - std::list > >::iterator - aRefsIter = aRefs.begin(); - for(; aRefsIter != aRefs.end(); aRefsIter++) { - std::list::iterator aRefTo = aRefsIter->second.begin(); - for(; aRefTo != aRefsIter->second.end(); aRefTo++) { + std::list > >::iterator aRefsIt = aRefs.begin(); + for(; aRefsIt != aRefs.end(); aRefsIt++) { + std::list::iterator aRefTo = aRefsIt->second.begin(); + for(; aRefTo != aRefsIt->second.end(); aRefTo++) { if (*aRefTo) { - std::shared_ptr aRefData = - std::dynamic_pointer_cast((*aRefTo)->data()); - aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated - // update enable/disable status: the nested status must be equal to the composite - /* MPV: not sub-elements of sketch may be enabled during editition of sketch - CompositeFeaturePtr aComp = - std::dynamic_pointer_cast(aFeature); - if (aComp.get()) { - FeaturePtr aReferenced = std::dynamic_pointer_cast(*aRefTo); - if (aReferenced.get()) { - aReferenced->setDisabled(aComp->isDisabled()); - } + std::map >::iterator aFound = allRefs.find(*aRefTo); + if (aFound == allRefs.end()) { + allRefs[*aRefTo] = std::set(); + aFound = allRefs.find(*aRefTo); } - */ + aFound->second.insert(aFeature->data()->attribute(aRefsIt->first)); } } } } } - std::list >::iterator aCIter = aConcealed.begin(); - for(; aCIter != aConcealed.end(); aCIter++) { - if (aCIter->first->isConcealed() != aCIter->second) { // something is changed => produce event - if (aCIter->second) { // was concealed become not => creation event - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent); - } else { // was not concealed become concealed => delete event - ModelAPI_EventCreator::get()->sendDeleted(myDoc, aCIter->first->groupName()); - // redisplay for the viewer (it must be disappeared also) - static Events_ID EVENT_DISP = - Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP); + // second iteration: just compare back-references with existing in features and results + for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) { + FeaturePtr aFeature = aFeatures.Value(); + static std::set anEmpty; + std::map >::iterator aFound = allRefs.find(aFeature); + if (aFound == allRefs.end()) { // not found => erase all back references + synchronizeBackRefsForObject(anEmpty, aFeature); + } else { + synchronizeBackRefsForObject(aFound->second, aFeature); + } + // also for results + const std::list >& aResults = aFeature->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + for(; aRes != aResults.cend(); aRes++) { + aFound = allRefs.find(*aRes); + if (aFound == allRefs.end()) { // not found => erase all back references + synchronizeBackRefsForObject(anEmpty, *aRes); + } else { + synchronizeBackRefsForObject(aFound->second, *aRes); } } } diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h index dc1fe7855..9f947c776 100644 --- a/src/Model/Model_Objects.h +++ b/src/Model/Model_Objects.h @@ -190,10 +190,13 @@ class Model_Objects /// be created before) std::string featureResultGroup(FeaturePtr theFeature); - ///! Returns all features of the document including the hidden features which are not in - ///! history. Not very fast method, for calling once, not in big cycles. + //! Returns all features of the document including the hidden features which are not in + //! history. Not very fast method, for calling once, not in big cycles. std::list > allFeatures(); + //! synchronises back references for the given object basing on the collected data + void synchronizeBackRefsForObject( + const std::set>& theNewRefs, ObjectPtr theObject); private: TDF_Label myMain; ///< main label of the data storage diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 0f8c3abdc..595feacf1 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -677,6 +677,7 @@ void Model_Update::executeFeature(FeaturePtr theFeature) void Model_Update::updateStability(void* theSender) { if (theSender) { + bool added = false; // object may be was crated ModelAPI_Object* aSender = static_cast(theSender); if (aSender && aSender->document()) { FeaturePtr aFeatureSender = @@ -701,6 +702,7 @@ void Model_Update::updateStability(void* theSender) aData->addBackReference(aFeatureSender, aRefIt->first); } else { aData->removeBackReference(aFeatureSender, aRefIt->first); + added = true; // remove of concealment may be caused creation of some result } } } @@ -708,6 +710,11 @@ void Model_Update::updateStability(void* theSender) } } } + if (added) { + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID kEventCreated = aLoop->eventByName(EVENT_OBJECT_CREATED); + aLoop->flush(kEventCreated); + } } } diff --git a/src/ModelAPI/ModelAPI_Result.cpp b/src/ModelAPI/ModelAPI_Result.cpp index 624566416..cefbd7af8 100644 --- a/src/ModelAPI/ModelAPI_Result.cpp +++ b/src/ModelAPI/ModelAPI_Result.cpp @@ -54,8 +54,17 @@ void ModelAPI_Result::setIsConcealed(const bool theValue) { if (myIsConcealed != theValue) { myIsConcealed = theValue; - if (document().get()) // can be on creation of result + if (document().get()) { // can be on creation of result document()->updateHistory(groupName()); // to update the history cash data in the document + if (myIsConcealed) { + ModelAPI_EventCreator::get()->sendDeleted(document(), groupName()); + static Events_ID kDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), kDispEvent); + } else { + static Events_ID kEventCreated = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), kEventCreated); + } + } } } -- 2.39.2