X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Update.cpp;h=51eba966c182977e5787340582512cc134b426e3;hb=f7a976b98d8cadadcb54a61e42ddb66e00759689;hp=cb511c8e3773c1c75ca25310bc84f2ac6e60fdf4;hpb=ad00c1e3ae3541f4a208b98e9aa45e6c46c7f4a9;p=modules%2Fshaper.git diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index cb511c8e3..51eba966c 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + // File: Model_Update.cxx // Created: 25 Jun 2014 // Author: Mikhail PONIKAROV @@ -52,7 +54,7 @@ Model_Update::Model_Update() isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; } -void Model_Update::processEvent(const boost::shared_ptr& theMessage) +void Model_Update::processEvent(const std::shared_ptr& theMessage) { static Events_Loop* aLoop = Events_Loop::loop(); static const Events_ID kChangedEvent = aLoop->eventByName("PreferenceChanged"); @@ -65,8 +67,11 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation"); bool isAutomaticChanged = false; if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed - isAutomatic = - Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; + bool aPropVal = + Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; + if (aPropVal == isAutomatic) + return;// nothing to + isAutomatic = aPropVal; } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command if (isAutomatic == false) { isAutomaticChanged = true; @@ -74,12 +79,14 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess } } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent || theMessage->eventID() == kMovedEvent) { - boost::shared_ptr aMsg = - boost::dynamic_pointer_cast(theMessage); + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); const std::set& anObjs = aMsg->objects(); std::set::const_iterator anObjIter = anObjs.cbegin(); for(; anObjIter != anObjs.cend(); anObjIter++) { myJustCreatedOrUpdated.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 } if (theMessage->eventID() == kMovedEvent) return; // this event is for solver update, not here @@ -91,6 +98,23 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess isAutomaticChanged = true; isAutomatic = true; } + // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply + if (theMessage->eventID() == kOpFinishEvent) { + std::set >::iterator aFIter; + for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++) + { + FeaturePtr aF = std::dynamic_pointer_cast(*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 (isExecuted) @@ -98,37 +122,15 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess //Events_LongOp::start(this); isExecuted = true; - std::list > aDocs; - boost::shared_ptr aMsg = - boost::dynamic_pointer_cast(theMessage); + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); if (aMsg) myInitial = aMsg->objects(); else { myInitial.clear(); - // on change flag all documents must be updated - if (isAutomatic) { - aDocs = ModelAPI_Session::get()->allOpenedDocuments(); - } - } - // collect all documents involved into the update process - set >::iterator aFIter = myInitial.begin(); - for (; aFIter != myInitial.end(); aFIter++) { - aDocs.push_back((*aFIter)->document()); - } - // iterate all features of features-documents to update them (including hidden) - std::set > alreadyUsed; - list >::iterator aDIter = aDocs.begin(); - for (; aDIter != aDocs.end(); aDIter++) { - if (alreadyUsed.find(*aDIter) != alreadyUsed.end()) - continue; - alreadyUsed.insert(*aDIter); - int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true); - for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { - FeaturePtr aFeature = boost::dynamic_pointer_cast( - (*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true)); - if (aFeature) - updateFeature(aFeature); - } } + // iterate all documents: features in Root first, then - subs + updateInDoc(ModelAPI_Session::get()->moduleDocument()); + myUpdated.clear(); // flush to update display static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); @@ -143,20 +145,58 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess isExecuted = false; } -void Model_Update::redisplayWithResults(FeaturePtr theFeature) { - // maske updated and redisplay all results +void Model_Update::updateInDoc(std::shared_ptr theDoc) +{ + // all features one by one + int aNbFeatures = theDoc->size(ModelAPI_Feature::group(), true); + for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { + FeaturePtr aFeature = std::dynamic_pointer_cast( + theDoc->object(ModelAPI_Feature::group(), aFIndex, true)); + if (aFeature) + updateFeature(aFeature); + } + // all sub-documents one by one + std::shared_ptr aDoc = std::dynamic_pointer_cast(theDoc); + if (aDoc) { + const std::set aSubs = aDoc->subDocuments(true); + for(std::set::iterator aSub = aSubs.begin(); aSub != aSubs.end(); aSub++) { + DocumentPtr aSubDoc = theDoc->subDocument(*aSub); + if (aSubDoc) { + updateInDoc(aSubDoc); + } + } + } +} + +void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_ExecState theState) +{ + // make updated and redisplay all results static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - const std::list >& aResults = theFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); + const std::list >& aResults = theFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { - boost::shared_ptr aRes = *aRIter; - aRes->data()->mustBeUpdated(false); + std::shared_ptr aRes = *aRIter; + aRes->data()->execState(theState); myUpdated[aRes] = true; ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP); } // to redisplay "presentable" feature (for ex. distance constraint) ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP); - theFeature->data()->mustBeUpdated(false); + theFeature->data()->execState(theState); +} + +/// Updates the state by the referenced object: if something bad with it, set state for this one +ModelAPI_ExecState stateByReference(ObjectPtr theTarget, const ModelAPI_ExecState theCurrent) +{ + if (theTarget) { + ModelAPI_ExecState aRefState = theTarget->data()->execState(); + if (aRefState == ModelAPI_StateMustBeUpdated) { + return ModelAPI_StateMustBeUpdated; + } else if (aRefState != ModelAPI_StateDone) { + return ModelAPI_StateInvalidArgument; + } + } + return theCurrent; } bool Model_Update::updateFeature(FeaturePtr theFeature) @@ -168,11 +208,12 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end(); if (theFeature) { // only real feature contains references to other objects - if (theFeature->data()->mustBeUpdated()) aMustbeUpdated = true; + if (theFeature->data()->execState() != ModelAPI_StateDone) + aMustbeUpdated = true; // composite feature must be executed after sub-features execution CompositeFeaturePtr aComposite = - boost::dynamic_pointer_cast(theFeature); + std::dynamic_pointer_cast(theFeature); if (aComposite) { int aSubsNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubsNum; a++) { @@ -180,10 +221,12 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) aMustbeUpdated = true; } } + ModelAPI_ExecState aState = ModelAPI_StateDone; // check all references: if referenced objects are updated, this object also must be updated + // also check state of referenced objects: if they are not ready, inherit corresponding state std::list > > aRefs; - boost::shared_ptr aData = - boost::dynamic_pointer_cast(theFeature->data()); + std::shared_ptr aData = + std::dynamic_pointer_cast(theFeature->data()); aData->referencesToObjects(aRefs); std::list > >::iterator aRef = aRefs.begin(); for(; aRef != aRefs.end(); aRef++) { @@ -192,84 +235,112 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) if (updateObject(*aRefObj)) { aMustbeUpdated = true; } + aState = stateByReference(*aRefObj, aState); } } //std::cout<<"Update feature "<getKind()<<" must be updated = "<(theFeature->document())->executeFeatures() || + if (std::dynamic_pointer_cast(theFeature->document())->executeFeatures() || !theFeature->isPersistentResult()) { if (aFactory->validate(theFeature)) { - if (isAutomatic || (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) || - !theFeature->isPersistentResult() /* execute quick, not persistent results */) + if (isAutomatic || + (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) || + !theFeature->isPersistentResult() /* execute quick, not persistent results */) { - //std::cout<<"Execute feature "<getKind()< aRefs = - theFeature->data()->attributes(ModelAPI_AttributeSelection::type()); - list::iterator aRefsIter = aRefs.begin(); - for (; aRefsIter != aRefs.end(); aRefsIter++) { - boost::shared_ptr aSel = - boost::dynamic_pointer_cast(*aRefsIter); - aSel->update(); // this must be done on execution since it may be long operation - } - aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::type()); - for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { - boost::shared_ptr aSel = - boost::dynamic_pointer_cast(*aRefsIter); - for(int a = aSel->size() - 1; a >= 0; a--) { - aSel->value(a)->update(); + if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used + //std::cout<<"Execute feature "<getKind()< aRefs = + theFeature->data()->attributes(ModelAPI_AttributeSelection::type()); + list::iterator aRefsIter = aRefs.begin(); + for (; aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*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)) && + aFactory->isCase(theFeature, theFeature->data()->id(aSel))) + aState = ModelAPI_StateInvalidArgument; + } } - } - // 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++) { - FeaturePtr aSub = aComposite->subFeature(a); - bool aWasModified = myUpdated[aSub]; - myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed) - myInitial.insert(aSub); - updateFeature(aSub); - myUpdated[aSub] = aWasModified; // restore value + aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::type()); + for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*aRefsIter); + for(int a = aSel->size() - 1; a >= 0; a--) { + std::shared_ptr aSelAttr = + std::dynamic_pointer_cast(aSel->value(a)); + if (aSelAttr) { + if (!aSelAttr->update()) { + if (!aFactory->isNotObligatory( + theFeature->getKind(), theFeature->data()->id(aSel)) && + aFactory->isCase(theFeature, theFeature->data()->id(aSel))) + aState = ModelAPI_StateInvalidArgument; + } + } + } } - // re-execute after update: solver may update the previous values, so, shapes must be - // updated - for(int a = 0; a < aSubsNum; a++) { - if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a))) - aComposite->subFeature(a)->execute(); + // 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++) { + FeaturePtr aSub = aComposite->subFeature(a); + bool aWasModified = myUpdated[aSub]; + myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed) + myInitial.insert(aSub); + updateFeature(aSub); + myUpdated[aSub] = aWasModified; // restore value + } + // re-execute after update: solver may update the previous values, so, shapes must be + // updated + for(int a = 0; a < aSubsNum; a++) { + if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a))) + aComposite->subFeature(a)->execute(); + } } } // execute in try-catch to avoid internal problems of the feature - try { - theFeature->execute(); - } catch(...) { - Events_Error::send( - "Feature " + theFeature->getKind() + " has failed during the execution"); + if (aState == ModelAPI_StateDone) { + theFeature->data()->execState(ModelAPI_StateDone); + try { + theFeature->execute(); + if (theFeature->data()->execState() != ModelAPI_StateDone) { + aState = ModelAPI_StateExecFailed; + } + } catch(...) { + aState = ModelAPI_StateExecFailed; + Events_Error::send( + "Feature " + theFeature->getKind() + " has failed during the execution"); + } + } + if (aState != ModelAPI_StateDone) { theFeature->eraseResults(); } - redisplayWithResults(theFeature); + redisplayWithResults(theFeature, aState); } else { // must be updatet, but not updated yet - theFeature->data()->mustBeUpdated(true); - const std::list >& aResults = theFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); + theFeature->data()->execState(ModelAPI_StateMustBeUpdated); + const std::list >& aResults = theFeature->results(); + std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { - boost::shared_ptr aRes = *aRIter; - aRes->data()->mustBeUpdated(true); + std::shared_ptr aRes = *aRIter; + aRes->data()->execState(ModelAPI_StateMustBeUpdated); } } } else { theFeature->eraseResults(); - redisplayWithResults(theFeature); // result also must be updated + redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated } } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway - redisplayWithResults(theFeature); + redisplayWithResults(theFeature, ModelAPI_StateNothing); } - } 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(); + } 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; @@ -282,7 +353,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature) return aMustbeUpdated; } -bool Model_Update::updateObject(boost::shared_ptr theObject, const bool theCyclic) +bool Model_Update::updateObject(std::shared_ptr theObject, const bool theCyclic) { if (myUpdated.find(theObject) != myUpdated.end()) return myUpdated[theObject]; // already processed @@ -291,7 +362,7 @@ bool Model_Update::updateObject(boost::shared_ptr theObject, co if (theCyclic) { // algorithm for update of all features by dependencies tree if (!theObject) return false; - FeaturePtr aFeature = boost::dynamic_pointer_cast(theObject); + FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); if (aFeature) { // for feature just call update Feature return updateFeature(aFeature); } @@ -299,7 +370,7 @@ bool Model_Update::updateObject(boost::shared_ptr theObject, co 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); + ResultPtr aResult = std::dynamic_pointer_cast(theObject); if (aResult) { FeaturePtr aResFeature = aResult->document()->feature(aResult); if (aResFeature) {