-// Copyright (C) 2014-2020 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <Model_Document.h>
#include <Model_Data.h>
#include <Model_Objects.h>
-#include <Model_AttributeSelection.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
Model_Update MY_UPDATER_INSTANCE; /// the only one instance initialized on load of the library
//#define DEB_UPDATE
+#ifdef DEB_UPDATE
+#include <Locale_Convert.h>
+#endif
+
Model_Update::Model_Update()
{
Events_Loop* aLoop = Events_Loop::loop();
else if (myProcessOnFinish.find(theFeature) == myProcessOnFinish.end())
myProcessOnFinish[theFeature] = std::set<std::shared_ptr<ModelAPI_Feature> >();
#ifdef DEB_UPDATE
- std::cout<<"*** Add process on finish "<<theFeature->name()<<std::endl;
+ std::wcout<<L"*** Add process on finish "<<theFeature->name()<<std::endl;
#endif
// keeps the currently updated features to avoid infinitive cycling here: where feature on
// "updateArguments" sends "updated" (in selection attribute) and goes here again
#endif
}
// clear processed and fill modified recursively
+ std::set<FeaturePtr> aRefSet;
const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = theFeature->data()->refsToMe();
std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
for(; aRefIter != aRefs.cend(); aRefIter++) {
if ((*aRefIter)->isArgument()) {
FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
if (aReferenced.get()) {
- addModified(aReferenced, theFeature);
+ aRefSet.insert(aReferenced);
}
}
}
ModelAPI_Tools::allResults(theFeature, allResults);
std::list<ResultPtr>::iterator aRes = allResults.begin();
for(; aRes != allResults.end(); aRes++) {
- const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = (*aRes)->data()->refsToMe();
- std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
- for(; aRefIter != aRefs.cend(); aRefIter++) {
- if ((*aRefIter)->isArgument()) {
- FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
+ const std::set<std::shared_ptr<ModelAPI_Attribute> >& aResRefs = (*aRes)->data()->refsToMe();
+ std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRIter = aResRefs.cbegin();
+ for(; aRIter != aResRefs.cend(); aRIter++) {
+ if ((*aRIter)->isArgument()) {
+ FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRIter)->owner());
if (aReferenced.get()) {
- addModified(aReferenced, theFeature);
+ aRefSet.insert(aReferenced);
}
}
}
}
-
// also add part feature that contains this feature to the modified
if (theFeature->document()->kind() != "PartSet") {
FeaturePtr aPart = ModelAPI_Tools::findPartFeature(
ModelAPI_Session::get()->moduleDocument(), theFeature->document());
if (aPart.get())
- addModified(aPart, theFeature);
+ aRefSet.insert(aPart);
}
+ for(std::set<FeaturePtr>::iterator aRef = aRefSet.begin(); aRef != aRefSet.end(); aRef++)
+ addModified(*aRef, theFeature);
+
return true;
}
void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
{
static Events_Loop* aLoop = Events_Loop::loop();
- static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+ //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");
}
}
processFeatures();
- myIsPreviewBlocked = myIsPreviewBlocked;
+ myIsPreviewBlocked = aPreviewBlockedState;
}
}
aFeatures.push_back(*anObjIter);
} else {
aResults.push_back(*anObjIter);
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*anObjIter);
+ if (aPart.get() && aPart->data().get() && aPart->data()->isValid()) {
+ aPart->shape(); // to update the shape on creation of the result
+ }
}
}
}
if (!(*anObjIter)->data()->isValid())
continue;
#ifdef DEB_UPDATE
- std::cout<<">>> in event updated "<<(*anObjIter)->groupName()<<
- " "<<(*anObjIter)->data()->name()<<std::endl;
+ std::wcout<<L">>> in event updated "<<Locale::Convert::toWString((*anObjIter)->groupName())
+ <<L" "<<(*anObjIter)->data()->name()<<std::endl;
#endif
if ((*anObjIter)->groupName() == ModelAPI_ResultParameter::group()) {
myIsParamUpdated = true;
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<std::shared_ptr<ModelAPI_Attribute> >&
for(; aRefIter != aRefs.cend(); aRefIter++) {
if (!(*aRefIter)->owner()->data()->isValid())
continue;
- FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
+ anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
if (anUpdated.get()) {
if (addModified(anUpdated, aReason))
aSomeModified = true;
}
#ifdef DEB_UPDATE
- std::cout<<"* Process feature "<<theFeature->name()<<std::endl;
+ std::wcout<<L"* Process feature "<<theFeature->name()<<std::endl;
#endif
// update the sketch plane before the sketch sub-elements are recomputed
// (otherwise sketch will update plane, modify subs, after executed, but with old subs edges)
if (aIsModified && theFeature->getKind() == "Sketch") {
#ifdef DEB_UPDATE
- std::cout << "****** Update sketch args " << theFeature->name() << std::endl;
+ std::wcout << L"****** Update sketch args " << theFeature->name() << std::endl;
#endif
AttributeSelectionPtr anExtSel = theFeature->selection("External");
if (anExtSel.get()) {
}
#ifdef DEB_UPDATE
- std::cout<<"Update args "<<theFeature->name()<<std::endl;
+ std::wcout<<L"Update args "<<theFeature->name()<<std::endl;
#endif
// TestImport.py : after arguments are updated, theFeature may be removed
if (!theFeature->data()->isValid())
// don't disable Part because it will make disabled all the features
// (performance and problems with the current feature)
#ifdef DEB_UPDATE
- std::cout<<"Invalid args "<<theFeature->name()<<std::endl;
+ std::wcout<<L"Invalid args "<<theFeature->name()<<std::endl;
#endif
theFeature->eraseResults(false);
redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
if (!isPostponedMain) {
bool aDoExecute = true;
if (myUpdateBlocked) {
- if (!theFeature->isStable()) {
+ if (!theFeature->isStable() || (theFeature->getKind().size() > 6 &&
+ theFeature->getKind().substr(0, 6) == "Sketch")) { // automatic update sketch elements
aDoExecute = true;
} else if (theFeature->results().size()) { // execute only not persistent results features
aDoExecute = !theFeature->isPersistentResult();
}
} else {
#ifdef DEB_UPDATE
- std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
+ std::wcout<<L"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
#endif
theFeature->eraseResults(false);
redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
bool isObligatory = !aFactory->isNotObligatory(
theFeature->getKind(), theFeature->data()->id(aSel)) &&
aFactory->isCase(theFeature, theFeature->data()->id(aSel));
- if (isObligatory)
+ if (isObligatory ||
+ // #24260 : sketch plane was selected, but selection becomes wrong, make it invalid
+ (theFeature->getKind() == "Sketch" && aSel->id() == "External"))
aState = ModelAPI_StateInvalidArgument;
}
}
bool isObligatory = aFactory->isCase(theFeature, theFeature->data()->id(aSel));
if (isObligatory)
aState = ModelAPI_StateInvalidArgument;
+ } else if (aSel->isInitialized()) {
+ // #19703 : if sketch plane was selected, but after context disappears, it must become invalid
+ aSel->update();
+ if (aSel->isInvalid()) {
+ aState = ModelAPI_StateInvalidArgument;
+ }
}
}
// update the selection list attributes if any
for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
+ // #19071 : avoid sending of update event in cycle
+ bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true);
+ // list to keep the shared pointers while update is blocked (in messages raw poiters are used)
+ std::list<AttributeSelectionPtr> anAttrList;
for(int a = aSel->size() - 1; a >= 0; a--) {
std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
// update argument only if the referenced object is ready to use
if (aContext.get() && !aContext->isDisabled()) {
if (isReason(theFeature, aContext)) {
+ anAttrList.push_back(aSelAttr);
if (!aSelAttr->update()) {
bool isObligatory = !aFactory->isNotObligatory(
theFeature->getKind(), theFeature->data()->id(aSel)) &&
}
}
}
+ if (!aWasBlocked)
+ theFeature->data()->blockSendAttributeUpdated(false);
}
if (aState != ModelAPI_StateDone)
void Model_Update::executeFeature(FeaturePtr theFeature)
{
#ifdef DEB_UPDATE
- std::cout<<"Execute Feature "<<theFeature->name()<<std::endl;
+ std::wcout<<L"Execute Feature "<<theFeature->name()<<std::endl;
#endif
// execute in try-catch to avoid internal problems of the feature
ModelAPI_ExecState aState = ModelAPI_StateDone;
(*anObj)->data()->attributes(ModelAPI_AttributeSelection::typeId());
std::list<AttributePtr>::iterator aRefsIter = aRefs.begin();
for (; aRefsIter != aRefs.end(); aRefsIter++) {
- std::shared_ptr<Model_AttributeSelection> aSel =
- std::dynamic_pointer_cast<Model_AttributeSelection>(*aRefsIter);
+ AttributeSelectionPtr aSel =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
bool aRemove = false;
aSel->updateInHistory(aRemove);
}
std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
for(int a = aSel->size() - 1; a >= 0; a--) {
- std::shared_ptr<Model_AttributeSelection> aSelAttr =
- std::dynamic_pointer_cast<Model_AttributeSelection>(aSel->value(a));
+ AttributeSelectionPtr aSelAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
if (aSelAttr.get()) {
- bool theRemove = false;
- aSelAttr->updateInHistory(theRemove);
- if (theRemove) {
+ bool aRemove = false;
+ aSelAttr->updateInHistory(aRemove);
+ if (aRemove) {
aRemoveSet.insert(a);
}
}