#include <TDF_AttributeIterator.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_RelocationTable.hxx>
+#include <TColStd_HArray1OfByte.hxx>
#include <string>
static const int kFlagInHistory = 0;
// 1 - is displayed or not
static const int kFlagDisplayed = 1;
+// 2 - is deleted (for results) or not
+static const int kFlagDeleted = 2;
// invalid data
const static std::shared_ptr<ModelAPI_Data> kInvalid(new Model_Data());
// set or get the default flags
if (!myLab.FindAttribute(TDataStd_BooleanArray::GetID(), myFlags)) {
// set default values if not found
- myFlags = TDataStd_BooleanArray::Set(myLab, 0, 1);
+ myFlags = TDataStd_BooleanArray::Set(myLab, 0, 2);
myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
+ myFlags->SetValue(kFlagDeleted, Standard_False); // is deleted by default is false
+ } else if (myFlags->Length() != 3) { // for old formats support
+ Handle(TColStd_HArray1OfByte) aNewArray = new TColStd_HArray1OfByte(0, 2);
+ aNewArray->SetValue(0, myFlags->Upper() > 0 ? myFlags->Value(0) : Standard_True);
+ aNewArray->SetValue(1, myFlags->Upper() > 1 ? myFlags->Value(1) : Standard_True);
+ aNewArray->SetValue(1, myFlags->Upper() > 2 ? myFlags->Value(2) : Standard_False);
+ myFlags->SetInternalArray(aNewArray);
}
}
TDataStd_AsciiString::Set(myLab, theError.c_str());
}
+void Model_Data::eraseErrorString()
+{
+ myLab.ForgetAttribute(TDataStd_AsciiString::GetID());
+}
+
std::string Model_Data::error() const
{
Handle(TDataStd_AsciiString) anErrorAttr;
// thus, no concealment references anymore => make not-concealed
std::shared_ptr<ModelAPI_Result> aRes =
std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
- if (aRes.get()) {
+ if (aRes.get() && aRes->isConcealed()) {
aRes->setIsConcealed(false);
static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
ModelAPI_EventCreator::get()->sendUpdated(aRes, anEvent);
return myFlags->SetValue(kFlagInHistory, theFlag);
}
+bool Model_Data::isDeleted()
+{
+ return myFlags->Value(kFlagDeleted) == Standard_True;
+}
+
+void Model_Data::setIsDeleted(const bool theFlag)
+{
+ return myFlags->SetValue(kFlagDeleted, theFlag);
+}
+
bool Model_Data::isDisplayed()
{
if (!myObject.get() || !myObject->document().get() || // object is in valid
/// Registers error during the execution, causes the ExecutionFailed state
MODEL_EXPORT virtual void setError(const std::string& theError, bool theSend = true);
+ /// Erases the error string if it is not empty
+ void eraseErrorString();
+
/// Registers error during the execution, causes the ExecutionFailed state
MODEL_EXPORT virtual std::string error() const;
/// Defines the custom "is in history" behavior
MODEL_EXPORT virtual void setIsInHistory(const bool theFlag);
+ /// Returns true if the object is deleted, but some data is still keept in memory
+ MODEL_EXPORT virtual bool isDeleted();
+
+ /// Sets true if the object is deleted, but some data is still keept in memory
+ MODEL_EXPORT virtual void setIsDeleted(const bool theFlag);
+
private:
/// Removes all information about back references
void eraseBackReferences();
subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize);
}
}
- // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
+ // after undo of all sub-documents to avoid updates on not-modified data (issue 370)
if (theSynchronize) {
myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
// update the current features status
for (; aRIter != aResults.cend(); aRIter++) {
ResultPtr aRes = *aRIter;
if (aRes->groupName() != theGroupID) break; // feature have only same group results
- if (aRes->isInHistory() && !aRes->isConcealed()) {
+ // iterate also concealed: ALL RESULTS (for translation parts undo/redo management)
+ //if (aRes->isInHistory() && !aRes->isConcealed()) {
theResults.push_back(*aRIter);
- }
+ //}
}
}
}
while(aResIter != theFeature->results().cend()) {
ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
if (aBody.get()) {
- if (!aBody->data()->isValid()) {
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(aBody->data());
+ if (!aData.get() || !aData->isValid() || aData->isDeleted()) {
// found a disappeared result => remove it
theFeature->eraseResultFromList(aBody);
// start iterate from beginning because iterator is corrupted by removing
TCollection_AsciiString(aGroup->Get()).ToCString());
}
}
- if (aNewBody) {
+ if (aNewBody && !aNewBody->data()->isDeleted()) {
theFeature->setResult(aNewBody, aResIndex);
}
}
if ((*anObjIter)->groupName() == ModelAPI_ResultParameter::group()) {
myIsParamUpdated = true;
}
- // created objects are always must be up to date (python box feature)
- // and updated not in internal uptation chain
- myUpdated[*anObjIter] = myModification;
-
- // something is updated during the execution: re-execute it (sketch update by parameters or
- // Box macro that updates the upper features during the execution)
- if (myIsExecuted) {
- FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
- if (anUpdated.get() && anUpdated->data()->isValid())
- iterateUpdateBreak(anUpdated);
- }
- #ifdef DEB_UPDATE
- if (myIsExecuted) std::cout<<"During execution ";
- if ((*anObjIter)->data() && (*anObjIter)->data()->isValid()) {
- std::cout<<"add updated "<<(*anObjIter)->groupName()<<" "
- <<(*anObjIter)->data()->name()<<std::endl;
+ // on undo/redo, abort do not update persisten features
+ FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
+ if (std::dynamic_pointer_cast<Model_Document>((*anObjIter)->document())->executeFeatures() ||
+ (anUpdated.get() && !anUpdated->isPersistentResult())) {
+ // created objects are always must be up to date (python box feature)
+ // and updated not in internal uptation chain
+ myUpdated[*anObjIter] = myModification;
+
+ // something is updated during the execution: re-execute it (sketch update by parameters or
+ // Box macro that updates the upper features during the execution)
+ if (myIsExecuted) {
+ FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
+ if (anUpdated.get() && anUpdated->data()->isValid())
+ iterateUpdateBreak(anUpdated);
+ }
+#ifdef DEB_UPDATE
+ if (myIsExecuted) std::cout<<"During execution ";
+ if ((*anObjIter)->data() && (*anObjIter)->data()->isValid()) {
+ std::cout<<"add updated "<<(*anObjIter)->groupName()<<" "
+ <<(*anObjIter)->data()->name()<<std::endl;
+ }
+#endif
}
- #endif
+
}
// this event is for solver update, not here, do not react immediately
if (!isOnlyResults && !(theMessage->eventID() == kMovedEvent))
CompositeFeaturePtr aCompos = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
// If automatice update is not needed and feature attributes were not updated right now,
// do not execute it and do not update arguments.
- if (!myIsAutomatic && myUpdated.find(theFeature) == myUpdated.end() && !aCompos.get()) {
+ if (!myIsAutomatic &&
+ (myUpdated.find(theFeature) == myUpdated.end() || myUpdated[theFeature] != myModification)
+ && !aCompos.get()) {
// execute will be performed later, but some features may have not-result
// presentations, so call update for them (like coincidence in the sketcher)
static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
return;
}
- bool aJustUpdated = myUpdated.find(theFeature) != myUpdated.end();
+ // only the currently updated features are executed
+ bool aJustUpdated = myUpdated.find(theFeature) != myUpdated.end() && myUpdated[theFeature] == myModification;
if (myIsAutomatic && theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)
aJustUpdated = true;
if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { // it is done (in the tree)
theFeature->data()->execState(ModelAPI_StateDone);
}
+ // it will be not updated with new modifications: only the currently updated features are updated
+ //if (myUpdated.find(theFeature) != myUpdated.end()) {
+ // myUpdated.erase(theFeature); // do not update this persistent feature even in the future
+ //}
}
return;
}
#include <ModelAPI_Attribute.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_AttributeValidator.h>
-#include <ModelAPI_Data.h>
#include <ModelAPI_Feature.h>
+#include <Model_Data.h>
#include <Events_Error.h>
bool Model_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature) const
{
- ModelAPI_ExecState anExecState = theFeature->data()->execState();
- theFeature->setError("", false);
- theFeature->data()->execState(anExecState);
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theFeature->data());
+ if (aData.get() && aData->isValid()) {
+ if (aData->execState() == ModelAPI_StateDone)
+ aData->eraseErrorString(); // no error => erase the information string
+ } else {
+ return false; // feature is broken, already not presented in the data structure
+ }
// check feature validators first
Validators aValidators;
//}
// check all attributes for validity
- std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
// Validity of data is checked by "Model_FeatureValidator" (kDefaultId)
// if (!aData || !aData->isValid())
// return false;
/// Returns the owner of htis data
virtual std::shared_ptr<ModelAPI_Object> owner() = 0;
+ /// Returns true if the object is deleted, but some data is still keept in memory
+ virtual bool isDeleted() = 0;
+
+ /// Sets true if the object is deleted, but some data is still keept in memory
+ virtual void setIsDeleted(const bool theFlag) = 0;
+
protected:
/// Objects are created for features automatically
ModelAPI_Data();
return false;
}
-bool ModelAPI_Feature::isDisabled() const
+bool ModelAPI_Feature::isDisabled()
{
return myIsDisabled;
}
MODELAPI_EXPORT virtual bool setDisabled(const bool theFlag);
/// Returns the feature is disabled or not.
- MODELAPI_EXPORT virtual bool isDisabled() const;
+ MODELAPI_EXPORT virtual bool isDisabled();
/// To virtually destroy the fields of successors
MODELAPI_EXPORT virtual ~ModelAPI_Feature();
virtual void initAttributes() = 0;
/// Returns the feature is disabled or not.
- virtual bool isDisabled() const = 0;
+ virtual bool isDisabled() = 0;
/// Called on change of any argument-attribute of this object
/// \param theID identifier of changed attribute
{
if (myIsDisabled != theFlag) {
myIsDisabled = theFlag;
+ data()->setIsDeleted(theFlag); // store it in data model (t oget back on undo/redo, etc)
// this must be before "updated" message send to have history updated for OB update
document()->updateHistory(groupName()); // to update the history cash data in the document
// generate related events
return false;
}
-bool ModelAPI_Result::isDisabled() const
+bool ModelAPI_Result::isDisabled()
{
+ if (myIsDisabled != data()->isDeleted())
+ setDisabled(std::dynamic_pointer_cast<ModelAPI_Result>(
+ data()->owner()), data()->isDeleted()); // restore from the data model the correct value
return myIsDisabled;
}
const bool theFlag);
/// Returns the result is disabled or not.
- MODELAPI_EXPORT virtual bool isDisabled() const;
+ MODELAPI_EXPORT virtual bool isDisabled();
// Returns the parameters of color definition in the resources config manager
virtual void colorConfigInfo(std::string& theSection, std::string& theName,
TO_STRING(ModelAPI_StateExecFailed)
TO_STRING(ModelAPI_StateInvalidArgument)
TO_STRING(ModelAPI_StateNothing)
- default: "Unknown ExecState.";
+ default: return "Unknown ExecState.";
}
#undef TO_STRING
}