X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Update.cpp;h=3a70e463a2b8a73b74c16cc938fa877ce197f907;hb=50c050906e6b5926727fcbadcbf4247326ef60be;hp=910527bb2702fdc4d93185b0fb557870d5c76b17;hpb=98728587134b06fd3dfe2a158bd39015fa0df2ab;p=modules%2Fshaper.git diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 910527bb2..3a70e463a 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -52,7 +52,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"); @@ -74,8 +74,8 @@ 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++) { @@ -93,10 +93,10 @@ void Model_Update::processEvent(const boost::shared_ptr& theMess } // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply if (theMessage->eventID() == kOpFinishEvent) { - std::set >::iterator aFIter; + std::set >::iterator aFIter; for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++) { - FeaturePtr aF = boost::dynamic_pointer_cast(*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(); @@ -115,37 +115,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); @@ -160,20 +138,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(); + 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) @@ -185,11 +201,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++) { @@ -197,10 +214,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++) { @@ -209,84 +228,108 @@ 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))) + 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))) + 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(); + 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; @@ -299,7 +342,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 @@ -308,7 +351,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); } @@ -316,7 +359,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) {