From 36063c8969dc4067cda6196c2d3abba7e9ed3af9 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 4 Sep 2018 17:15:24 +0300 Subject: [PATCH] Issue #2612 : Re-calculate model after modification of parameters Advanced version of Update mechanism change for blocking of recalculation --- src/Model/Model_Session.cpp | 1 + src/Model/Model_Update.cpp | 86 ++++++++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index d150d44f9..07f3e98f0 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -582,6 +582,7 @@ int Model_Session::transactionID() void Model_Session::blockAutoUpdate(const bool theBlock) { if (myIsAutoUpdateBlocked != theBlock) { + myIsAutoUpdateBlocked = theBlock; static Events_Loop* aLoop = Events_Loop::loop(); if (theBlock) { static const Events_ID kAutoOff = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE); diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 7ff05ab13..2bf951ae7 100755 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include #include @@ -74,6 +76,10 @@ Model_Update::Model_Update() aLoop->registerListener(this, kReorderEvent); static const Events_ID kUpdatedSel = aLoop->eventByName(EVENT_UPDATE_SELECTION); aLoop->registerListener(this, kUpdatedSel); + static const Events_ID kAutomaticOff = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE); + aLoop->registerListener(this, kAutomaticOff); + static const Events_ID kAutomaticOn = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE); + aLoop->registerListener(this, kAutomaticOn); // Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; myIsParamUpdated = false; @@ -106,7 +112,7 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { } // update arguments for "apply button" state change - if ((!theFeature->isPreviewNeeded() && !myIsFinish) || myIsPreviewBlocked || myUpdateBlocked) { + if ((!theFeature->isPreviewNeeded() && !myIsFinish) || myIsPreviewBlocked) { if (theReason.get()) myProcessOnFinish[theFeature].insert(theReason); else if (myProcessOnFinish.find(theFeature) == myProcessOnFinish.end()) @@ -136,7 +142,7 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { aLoop->flush(kRedisplayEvent); } - if (!myIsPreviewBlocked && !myUpdateBlocked) + if (!myIsPreviewBlocked) return true; } if (myModified.find(theFeature) != myModified.end()) { @@ -222,6 +228,7 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { void Model_Update::processEvent(const std::shared_ptr& theMessage) { static Events_Loop* aLoop = Events_Loop::loop(); + static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators(); static const Events_ID kCreatedEvent = aLoop->eventByName(EVENT_OBJECT_CREATED); static const Events_ID kUpdatedEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED); static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation"); @@ -266,6 +273,20 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag myUpdateBlocked = false; // then process all modified features, even if preview is blocked bool aPreviewBlockedState = myIsPreviewBlocked; // to update the selected arguments myIsPreviewBlocked = false; + // iterate everything and add efatures in state "MustBeUpdated" into modified + std::list > allDocs = + ModelAPI_Session::get()->allOpenedDocuments(); + std::list >::iterator aDoc = allDocs.begin(); + for(; aDoc != allDocs.end(); aDoc++) { + std::list > allFeats = (*aDoc)->allFeatures(); + std::list >::iterator aFeat = allFeats.begin(); + for(; aFeat != allFeats.end(); aFeat++) { + if ((*aFeat)->data()->isValid() && + (*aFeat)->data()->execState() == ModelAPI_StateMustBeUpdated) { + addModified(*aFeat, FeaturePtr()); + } + } + } processFeatures(); myIsPreviewBlocked = myIsPreviewBlocked; return; @@ -315,6 +336,18 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag if (anUpdated.get()) { if (addModified(anUpdated, FeaturePtr())) aSomeModified = true; + if (myUpdateBlocked) { // execute this feature anyway to show the current result + /*if (!anUpdated->isStable() && anUpdated->results().size() && ( + anUpdated->firstResult()->groupName() == ModelAPI_ResultBody::group() || + anUpdated->firstResult()->groupName() == ModelAPI_ResultPart::group())) { + if (aFactory->validate(anUpdated)) { + executeFeature(anUpdated); + redisplayWithResults(anUpdated, ModelAPI_StateNothing, false); + static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + aLoop->flush(EVENT_DISP); + } + }*/ + } } else { // process the updated result as update of features that refers to this result const std::set >& @@ -343,7 +376,7 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag theMessage->eventID() == kOpStartEvent) { myIsPreviewBlocked = false; - if (theMessage->eventID() == kOpFinishEvent && !myUpdateBlocked) {// if update is blocked, skip + if (theMessage->eventID() == kOpFinishEvent) {// if update is blocked, skip myIsFinish = true; // add features that wait for finish as modified std::map, std::set > >:: @@ -363,25 +396,22 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag myIsFinish = false; } // processed features must be only on finish, so clear anyway (to avoid reimport on load) - if (!myUpdateBlocked) { - myProcessOnFinish.clear(); + myProcessOnFinish.clear(); - // #2156: current must be sketch, left after the macro execution - DocumentPtr anActiveDoc = ModelAPI_Session::get()->activeDocument(); - FeaturePtr aCurrent; - if (anActiveDoc.get()) - aCurrent = anActiveDoc->currentFeature(false); + // #2156: current must be sketch, left after the macro execution + DocumentPtr anActiveDoc = ModelAPI_Session::get()->activeDocument(); + FeaturePtr aCurrent; + if (anActiveDoc.get()) + aCurrent = anActiveDoc->currentFeature(false); - if (!(theMessage->eventID() == kOpStartEvent)) { - processFeatures(false); - } - - if (anActiveDoc.get() && aCurrent.get() && aCurrent->data()->isValid()) { - if (anActiveDoc->currentFeature(false) != aCurrent) - anActiveDoc->setCurrentFeature(aCurrent, false); // #2156 make the current feature back - } + if (!(theMessage->eventID() == kOpStartEvent)) { + processFeatures(false); } + if (anActiveDoc.get() && aCurrent.get() && aCurrent->data()->isValid()) { + if (anActiveDoc->currentFeature(false) != aCurrent) + anActiveDoc->setCurrentFeature(aCurrent, false); // #2156 make the current feature back + } // remove all macros before clearing all created std::set::iterator anUpdatedIter = myWaitForFinish.begin(); @@ -423,7 +453,7 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag void Model_Update::processFeatures(const bool theFlushRedisplay) { // perform update of everything if it is not performed right now or any preview is blocked - if (!myIsProcessed && !myIsPreviewBlocked && !myUpdateBlocked) { + if (!myIsProcessed && !myIsPreviewBlocked) { myIsProcessed = true; #ifdef DEB_UPDATE std::cout<<"****** Start processing"<data()->execState(); if (aFactory->validate(theFeature)) { if (!isPostponedMain) { - executeFeature(theFeature); + bool aDoExecute = true; + if (myUpdateBlocked) { + if (!theFeature->isStable()) { + aDoExecute = true; + } else if (theFeature->results().size()) { // execute only not-results features + aDoExecute = !(theFeature->firstResult()->groupName() == ModelAPI_ResultBody::group() || + theFeature->firstResult()->groupName() == ModelAPI_ResultPart::group()); + } else { + aDoExecute = aState != ModelAPI_StateInvalidArgument; + } + } + if (aDoExecute) { + executeFeature(theFeature); + } else { + // store information that this feature must be executed later + theFeature->data()->execState(ModelAPI_StateMustBeUpdated); + } } } else { #ifdef DEB_UPDATE -- 2.30.2