X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Update.cpp;h=561882b7c28d3157111c3cff3df98d6bbb186620;hb=0c0c2fd5b941ad2e65a0e82251dca2f796750b97;hp=e3e9f548b74d5c56d651992a5f8b20497f70d861;hpb=ebf59abe16d4ccc81cd1eb506f1f897c06a41ccb;p=modules%2Fshaper.git diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index e3e9f548b..561882b7c 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -33,6 +33,7 @@ using namespace std; Model_Update MY_UPDATER_INSTANCE; /// the only one instance initialized on load of the library +//#define DEB_UPDATE Model_Update::Model_Update() { @@ -59,6 +60,7 @@ Model_Update::Model_Update() myIsAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; myIsParamUpdated = false; + myIsFinish = false; } void Model_Update::processEvent(const std::shared_ptr& theMessage) @@ -72,7 +74,6 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation"); static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation"); static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation"); - bool isOperationChanged = false; if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed bool aPropVal = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; @@ -100,38 +101,37 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag // created objects are always must be up to date (python box feature) // and updated not in internal uptation chain myJustUpdated.insert(*anObjIter); + #ifdef DEB_UPDATE + if ((*anObjIter)->data() && (*anObjIter)->data()->isValid()) { + std::cout<<"Add updated "<<(*anObjIter)->groupName()<<" " + <<(*anObjIter)->data()->name()<eventID() == kMovedEvent)) processOperation(false); - } else if (theMessage->eventID() == kOpStartEvent) { - // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent) - isOperationChanged = true; - } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) { - processOperation(true, theMessage->eventID() == kOpFinishEvent); - isOperationChanged = true; - } - if (isOperationChanged) { - // remove all macros before clearing all created and execute all not-previewed - std::set::iterator anUpdatedIter = myJustUpdated.begin(); - while(anUpdatedIter != myJustUpdated.end()) { + } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent || + theMessage->eventID() == kOpStartEvent) { + + if (!(theMessage->eventID() == kOpStartEvent)) { + myIsFinish = true; + processOperation(true, theMessage->eventID() == kOpFinishEvent); + myIsFinish = false; + } + // remove all macros before clearing all created + std::set::iterator anUpdatedIter = myWaitForFinish.begin(); + while(anUpdatedIter != myWaitForFinish.end()) { FeaturePtr aFeature = std::dynamic_pointer_cast(*anUpdatedIter); if (aFeature.get()) { - // execute not-previewed feature on "apply" - if (!aFeature->isPreviewNeeded()) { - static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); - if (aFactory->validate(aFeature)) { - executeFeature(aFeature); - } - } - // remove macro on apply + // remove macro on finish if (aFeature->isMacro()) { aFeature->document()->removeFeature(aFeature); - myJustUpdated.erase(aFeature); + myWaitForFinish.erase(aFeature); } // to avoid the map update problems on "remove" - if (myJustUpdated.find(aFeature) == myJustUpdated.end()) { - anUpdatedIter = myJustUpdated.begin(); + if (myWaitForFinish.find(aFeature) == myWaitForFinish.end()) { + anUpdatedIter = myWaitForFinish.begin(); } else { anUpdatedIter++; } @@ -139,7 +139,11 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag anUpdatedIter++; } } + // in the end of transaction everything is updated, so clear the old objects (the only one + // place where results are cleared) myIsParamUpdated = false; + myJustUpdated.clear(); + myWaitForFinish.clear(); } } @@ -148,7 +152,7 @@ void Model_Update::processOperation(const bool theTotalUpdate, const bool theFin if (theFinish) { // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply std::set >::iterator aFIter; - for(aFIter = myJustUpdated.begin(); aFIter != myJustUpdated.end(); aFIter++) + for(aFIter = myWaitForFinish.begin(); aFIter != myWaitForFinish.end(); aFIter++) { FeaturePtr aF = std::dynamic_pointer_cast(*aFIter); if (aF && aF->data()->isValid() && aF->getKind() == "Extrusion") { @@ -166,6 +170,9 @@ void Model_Update::processOperation(const bool theTotalUpdate, const bool theFin } // perform update of everything if needed if (!myIsExecuted) { + #ifdef DEB_UPDATE + std::cout<<"****** Start processing"<moduleDocument(); Model_Objects* anObjs = std::dynamic_pointer_cast(aRootDoc)->objects(); if (!anObjs) return; + // two cycles: parameters are first to process FeaturePtr aFeatureIter = anObjs->firstFeature(); std::set aProcessedFeatures; // to avoid processing twice for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) { - updateFeature(aFeatureIter, aProcessedFeatures); + if (aFeatureIter->getKind() == "Parameter") + updateFeature(aFeatureIter, aProcessedFeatures); + } + aFeatureIter = anObjs->firstFeature(); + for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) { + if (aFeatureIter->getKind() != "Parameter") + updateFeature(aFeatureIter, aProcessedFeatures); } if (isAutomaticChanged) myIsAutomatic = false; @@ -192,6 +206,9 @@ void Model_Update::processOperation(const bool theTotalUpdate, const bool theFin static Events_Loop* aLoop = Events_Loop::loop(); static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); aLoop->flush(EVENT_DISP); + #ifdef DEB_UPDATE + std::cout<<"****** End processing"<& th if (theFeature->isDisabled()) return; + #ifdef DEB_UPDATE + std::cout<<"Update Feature "<name()<(theFeature); // If automatice update is not needed and feature attributes were not updated right now, // do not execute it and do not update arguments. @@ -222,10 +242,17 @@ void Model_Update::updateFeature(FeaturePtr theFeature, std::set& th // composite feature must be executed after sub-features execution if (aCompos) { + // two cycles: parameters must be processed first + for(int a = 0; a < aCompos->numberOfSubs(); a++) { + FeaturePtr aSub = aCompos->subFeature(a); + if (aSub->getKind() == "Parameter") + updateFeature(aSub, theProcessed); + } // number of subs can be changed in execution: like fillet for(int a = 0; a < aCompos->numberOfSubs(); a++) { FeaturePtr aSub = aCompos->subFeature(a); - updateFeature(aSub, theProcessed); + if (aSub->getKind() != "Parameter") + updateFeature(aSub, theProcessed); } } // this checking must be after the composite feature sub-elements processing: @@ -241,21 +268,46 @@ void Model_Update::updateFeature(FeaturePtr theFeature, std::set& th if (myIsAutomatic && theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) aJustUpdated = true; + // On abort, undo or redo execute is not needed: results in document are updated automatically + // But redisplay is needed: results are updated, must be also updated in the viewer. + if (aJustUpdated && + !std::dynamic_pointer_cast(theFeature->document())->executeFeatures()) { + if (!theFeature->isPersistentResult()) { // not persistent must be re-executed on abort, etc. + ModelAPI_ExecState aState = theFeature->data()->execState(); + if (aFactory->validate(theFeature)) { + executeFeature(theFeature); + } else { + theFeature->eraseResults(); + redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated + } + } else { + redisplayWithResults(theFeature, ModelAPI_StateNothing); + if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { // it is done (in the tree) + theFeature->data()->execState(ModelAPI_StateDone); + } + } + return; + } + // execute feature if it must be updated - if (theFeature->isPreviewNeeded()) { - if ((myIsAutomatic || aJustUpdated) && - std::dynamic_pointer_cast(theFeature->document())->executeFeatures()) { - ModelAPI_ExecState aState = theFeature->data()->execState(); - if (aFactory->validate(theFeature)) { - executeFeature(theFeature); - } else { - theFeature->eraseResults(); - redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated - } + if (theFeature->isPreviewNeeded() || myIsFinish) { + if (aJustUpdated) { + ModelAPI_ExecState aState = theFeature->data()->execState(); + if (aFactory->validate(theFeature)) { + #ifdef DEB_UPDATE + std::cout<<"Execute Feature "<name()<eraseResults(); + redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated + } } } else { // preview is not needed => make state Done if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { theFeature->data()->execState(ModelAPI_StateDone); + if (aJustUpdated) // store that it must be updated on finish + myJustUpdated.insert(theFeature); } } } @@ -268,7 +320,8 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { std::shared_ptr aRes = *aRIter; - aRes->data()->execState(theState); + if (!aRes->isDisabled()) // update state only for enabled results (Placement Result Part may make the original Part Result as invalid) + aRes->data()->execState(theState); if (theFeature->data()->updateID() > aRes->data()->updateID()) { aRes->data()->setUpdateID(theFeature->data()->updateID()); } @@ -296,11 +349,14 @@ ModelAPI_ExecState stateByReference(ObjectPtr theTarget, const ModelAPI_ExecStat void Model_Update::updateArguments(FeaturePtr theFeature) { // perform this method also for disabled features: to make "not done" state for - // featuers referenced to the active and modified features + // features referenced to the active and modified features static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); ModelAPI_ExecState aState = theFeature->data()->execState(); + if (aState == ModelAPI_StateExecFailed) { // try again failed feature: issue 577 + aState = ModelAPI_StateMustBeUpdated; + } if (aState == ModelAPI_StateInvalidArgument) // a chance to be corrected aState = ModelAPI_StateMustBeUpdated; // check the parameters state @@ -370,7 +426,8 @@ void Model_Update::updateArguments(FeaturePtr theFeature) { ObjectPtr aContext = aSel->context(); // update argument onlt if the referenced object is changed if (aContext.get() && !aContext->isDisabled() && - aContext->data()->updateID() > theFeature->data()->updateID()) { + (myJustUpdated.find(aContext) != myJustUpdated.end() || + aContext->data()->updateID() > theFeature->data()->updateID())) { if (aState == ModelAPI_StateDone) aState = ModelAPI_StateMustBeUpdated; if (!aSel->update()) { // this must be done on execution since it may be long operation @@ -391,7 +448,8 @@ void Model_Update::updateArguments(FeaturePtr theFeature) { ObjectPtr aContext = aSelAttr->context(); // update argument onlt if the referenced object is changed if (aContext.get() && !aContext->isDisabled() && - aContext->data()->updateID() > theFeature->data()->updateID()) { + (myJustUpdated.find(aContext) != myJustUpdated.end() || + aContext->data()->updateID() > theFeature->data()->updateID())) { if (aState == ModelAPI_StateDone) aState = ModelAPI_StateMustBeUpdated; if (!aSelAttr->update()) { @@ -427,6 +485,32 @@ void Model_Update::updateArguments(FeaturePtr theFeature) { aState = stateByReference(*aRefObj, aState); } } + // composites sub-elements + CompositeFeaturePtr aCompos = std::dynamic_pointer_cast(theFeature); + // composite feature must be executed after sub-features execution + if (aCompos) { + // number of subs can be changed in execution: like fillet + for(int a = 0; a < aCompos->numberOfSubs(); a++) { + FeaturePtr aSub = aCompos->subFeature(a); + if (aSub.get() && aState == ModelAPI_StateDone) { + if (myJustUpdated.find(aSub) != myJustUpdated.end() || + (aSub->data()->updateID() > theFeature->data()->updateID())) { + aState = ModelAPI_StateMustBeUpdated; + } + // also check that all results of subs were updated: composite also depends on the results + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aResIter = aResults.begin(); + for(; aResIter != aResults.end(); aResIter++) { + if (aResIter->get() && (*aResIter)->data()->isValid() && !(*aResIter)->isDisabled() && + (myJustUpdated.find(*aResIter) != myJustUpdated.end() || + ((*aResIter)->data()->updateID() > theFeature->data()->updateID()))) { + aState = ModelAPI_StateMustBeUpdated; + } + } + } + } + } + if (aState != ModelAPI_StateDone) theFeature->data()->execState(aState); @@ -444,6 +528,7 @@ void Model_Update::executeFeature(FeaturePtr theFeature) aState = ModelAPI_StateExecFailed; } else { aState = ModelAPI_StateDone; + myWaitForFinish.insert(theFeature); } } catch(...) { aState = ModelAPI_StateExecFailed;